summaryrefslogtreecommitdiffstats
path: root/drivers/misc/eeprom
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/eeprom')
-rw-r--r--drivers/misc/eeprom/at24.c76
-rw-r--r--drivers/misc/eeprom/max6875.c29
2 files changed, 50 insertions, 55 deletions
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index db39f4a..2cb2736 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -158,6 +158,7 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
struct i2c_msg msg[2];
u8 msgbuf[2];
struct i2c_client *client;
+ unsigned long timeout, read_time;
int status, i;
memset(msg, 0, sizeof(msg));
@@ -183,47 +184,60 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
if (count > io_limit)
count = io_limit;
- /* Smaller eeproms can work given some SMBus extension calls */
if (at24->use_smbus) {
+ /* Smaller eeproms can work given some SMBus extension calls */
if (count > I2C_SMBUS_BLOCK_MAX)
count = I2C_SMBUS_BLOCK_MAX;
- status = i2c_smbus_read_i2c_block_data(client, offset,
- count, buf);
- dev_dbg(&client->dev, "smbus read %zu@%d --> %d\n",
- count, offset, status);
- return (status < 0) ? -EIO : status;
+ } else {
+ /*
+ * When we have a better choice than SMBus calls, use a
+ * combined I2C message. Write address; then read up to
+ * io_limit data bytes. Note that read page rollover helps us
+ * here (unlike writes). msgbuf is u8 and will cast to our
+ * needs.
+ */
+ i = 0;
+ if (at24->chip.flags & AT24_FLAG_ADDR16)
+ msgbuf[i++] = offset >> 8;
+ msgbuf[i++] = offset;
+
+ msg[0].addr = client->addr;
+ msg[0].buf = msgbuf;
+ msg[0].len = i;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].buf = buf;
+ msg[1].len = count;
}
/*
- * When we have a better choice than SMBus calls, use a combined
- * I2C message. Write address; then read up to io_limit data bytes.
- * Note that read page rollover helps us here (unlike writes).
- * msgbuf is u8 and will cast to our needs.
+ * Reads fail if the previous write didn't complete yet. We may
+ * loop a few times until this one succeeds, waiting at least
+ * long enough for one entire page write to work.
*/
- i = 0;
- if (at24->chip.flags & AT24_FLAG_ADDR16)
- msgbuf[i++] = offset >> 8;
- msgbuf[i++] = offset;
-
- msg[0].addr = client->addr;
- msg[0].buf = msgbuf;
- msg[0].len = i;
+ timeout = jiffies + msecs_to_jiffies(write_timeout);
+ do {
+ read_time = jiffies;
+ if (at24->use_smbus) {
+ status = i2c_smbus_read_i2c_block_data(client, offset,
+ count, buf);
+ } else {
+ status = i2c_transfer(client->adapter, msg, 2);
+ if (status == 2)
+ status = count;
+ }
+ dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n",
+ count, offset, status, jiffies);
- msg[1].addr = client->addr;
- msg[1].flags = I2C_M_RD;
- msg[1].buf = buf;
- msg[1].len = count;
+ if (status == count)
+ return count;
- status = i2c_transfer(client->adapter, msg, 2);
- dev_dbg(&client->dev, "i2c read %zu@%d --> %d\n",
- count, offset, status);
+ /* REVISIT: at HZ=100, this is sloooow */
+ msleep(1);
+ } while (time_before(read_time, timeout));
- if (status == 2)
- return count;
- else if (status >= 0)
- return -EIO;
- else
- return status;
+ return -ETIMEDOUT;
}
static ssize_t at24_read(struct at24_data *at24,
diff --git a/drivers/misc/eeprom/max6875.c b/drivers/misc/eeprom/max6875.c
index 3c0c58e..5a6b2bc 100644
--- a/drivers/misc/eeprom/max6875.c
+++ b/drivers/misc/eeprom/max6875.c
@@ -33,12 +33,6 @@
#include <linux/i2c.h>
#include <linux/mutex.h>
-/* Do not scan - the MAX6875 access method will write to some EEPROM chips */
-static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
-
-/* Insmod parameters */
-I2C_CLIENT_INSMOD_1(max6875);
-
/* The MAX6875 can only read/write 16 bytes at a time */
#define SLICE_SIZE 16
#define SLICE_BITS 4
@@ -146,31 +140,21 @@ static struct bin_attribute user_eeprom_attr = {
.read = max6875_read,
};
-/* Return 0 if detection is successful, -ENODEV otherwise */
-static int max6875_detect(struct i2c_client *client, int kind,
- struct i2c_board_info *info)
+static int max6875_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = client->adapter;
+ struct max6875_data *data;
+ int err;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA
| I2C_FUNC_SMBUS_READ_BYTE))
return -ENODEV;
- /* Only check even addresses */
+ /* Only bind to even addresses */
if (client->addr & 1)
return -ENODEV;
- strlcpy(info->type, "max6875", I2C_NAME_SIZE);
-
- return 0;
-}
-
-static int max6875_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct max6875_data *data;
- int err;
-
if (!(data = kzalloc(sizeof(struct max6875_data), GFP_KERNEL)))
return -ENOMEM;
@@ -222,9 +206,6 @@ static struct i2c_driver max6875_driver = {
.probe = max6875_probe,
.remove = max6875_remove,
.id_table = max6875_id,
-
- .detect = max6875_detect,
- .address_data = &addr_data,
};
static int __init max6875_init(void)
OpenPOWER on IntegriCloud