eeprom: at24: split at24_eeprom_read() into specialized functions
authorBartosz Golaszewski <bgolaszewski@baylibre.com>
Mon, 6 Jun 2016 08:48:48 +0000 (10:48 +0200)
committerWolfram Sang <wsa@the-dreams.de>
Sun, 17 Jul 2016 17:41:54 +0000 (19:41 +0200)
Split at24_eeprom_read() into two smaller functions - one for the
i2c operations and one for the smbus extensions. Assign them in
at24_probe() depending on the bus capabilities.

Also: in order to avoid duplications move the comments related to
offset calculations above the at24_translate_offset() routine.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
drivers/misc/eeprom/at24.c

index 2efb572..e7db137 100644 (file)
@@ -165,6 +165,19 @@ MODULE_DEVICE_TABLE(acpi, at24_acpi_ids);
  * This routine supports chips which consume multiple I2C addresses. It
  * computes the addressing information to be used for a given r/w request.
  * Assumes that sanity checks for offset happened at sysfs-layer.
+ *
+ * Slave address and byte offset derive from the offset. Always
+ * set the byte address; on a multi-master board, another master
+ * may have changed the chip's "current" address pointer.
+ *
+ * REVISIT some multi-address chips don't rollover page reads to
+ * the next slave address, so we may need to truncate the count.
+ * Those chips might need another quirk flag.
+ *
+ * If the real hardware used four adjacent 24c02 chips and that
+ * were misconfigured as one 24c08, that would be a similar effect:
+ * one "eeprom" file not four, but larger reads would fail when
+ * they crossed certain pages.
  */
 static struct i2c_client *at24_translate_offset(struct at24_data *at24,
                                                unsigned int *offset)
@@ -182,74 +195,77 @@ static struct i2c_client *at24_translate_offset(struct at24_data *at24,
        return at24->client[i];
 }
 
-static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
-                               unsigned int offset, size_t count)
+static ssize_t at24_eeprom_read_smbus(struct at24_data *at24, char *buf,
+                                     unsigned int offset, size_t count)
 {
-       struct i2c_msg msg[2];
-       u8 msgbuf[2];
+       unsigned long timeout, read_time;
        struct i2c_client *client;
+       int status;
+
+       client = at24_translate_offset(at24, &offset);
+
+       if (count > io_limit)
+               count = io_limit;
+
+       /* Smaller eeproms can work given some SMBus extension calls */
+       if (count > I2C_SMBUS_BLOCK_MAX)
+               count = I2C_SMBUS_BLOCK_MAX;
+
+       loop_until_timeout(timeout, read_time) {
+               status = i2c_smbus_read_i2c_block_data_or_emulated(client,
+                                                                  offset,
+                                                                  count, buf);
+
+               dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n",
+                               count, offset, status, jiffies);
+
+               if (status == count)
+                       return count;
+       }
+
+       return -ETIMEDOUT;
+}
+
+static ssize_t at24_eeprom_read_i2c(struct at24_data *at24, char *buf,
+                                   unsigned int offset, size_t count)
+{
        unsigned long timeout, read_time;
+       struct i2c_client *client;
+       struct i2c_msg msg[2];
        int status, i;
+       u8 msgbuf[2];
 
        memset(msg, 0, sizeof(msg));
-
-       /*
-        * REVISIT some multi-address chips don't rollover page reads to
-        * the next slave address, so we may need to truncate the count.
-        * Those chips might need another quirk flag.
-        *
-        * If the real hardware used four adjacent 24c02 chips and that
-        * were misconfigured as one 24c08, that would be a similar effect:
-        * one "eeprom" file not four, but larger reads would fail when
-        * they crossed certain pages.
-        */
-
-       /*
-        * Slave address and byte offset derive from the offset. Always
-        * set the byte address; on a multi-master board, another master
-        * may have changed the chip's "current" address pointer.
-        */
        client = at24_translate_offset(at24, &offset);
 
        if (count > io_limit)
                count = io_limit;
 
-       if (at24->use_smbus) {
-               /* Smaller eeproms can work given some SMBus extension calls */
-               if (count > I2C_SMBUS_BLOCK_MAX)
-                       count = I2C_SMBUS_BLOCK_MAX;
-       } 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;
+       /*
+        * 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[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;
-       }
+       msg[1].addr = client->addr;
+       msg[1].flags = I2C_M_RD;
+       msg[1].buf = buf;
+       msg[1].len = count;
 
        loop_until_timeout(timeout, read_time) {
-               if (at24->use_smbus) {
-                       status = i2c_smbus_read_i2c_block_data_or_emulated(client, offset,
-                                                                          count, buf);
-               } else {
-                       status = i2c_transfer(client->adapter, msg, 2);
-                       if (status == 2)
-                               status = count;
-               }
+               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);
 
@@ -520,7 +536,8 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
        at24->chip = chip;
        at24->num_addresses = num_addresses;
 
-       at24->read_func = at24_eeprom_read;
+       at24->read_func = at24->use_smbus ? at24_eeprom_read_smbus
+                                         : at24_eeprom_read_i2c;
        at24->write_func = at24_eeprom_write;
 
        writable = !(chip.flags & AT24_FLAG_READONLY);