]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/i2c/chips/eeprom.c
i2c/eeprom: Fall back to SMBus read word transactions
[linux-2.6-omap-h63xx.git] / drivers / i2c / chips / eeprom.c
index 213a9f98decc8048c6cb684d207c9f853cb01755..9a81252a72181e8389d7c848d41c4a1d74c6c210 100644 (file)
@@ -78,7 +78,7 @@ static struct i2c_driver eeprom_driver = {
 static void eeprom_update_client(struct i2c_client *client, u8 slice)
 {
        struct eeprom_data *data = i2c_get_clientdata(client);
-       int i, j;
+       int i;
 
        mutex_lock(&data->update_lock);
 
@@ -93,15 +93,12 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice)
                                                        != 32)
                                        goto exit;
                } else {
-                       if (i2c_smbus_write_byte(client, slice << 5)) {
-                               dev_dbg(&client->dev, "eeprom read start has failed!\n");
-                               goto exit;
-                       }
-                       for (i = slice << 5; i < (slice + 1) << 5; i++) {
-                               j = i2c_smbus_read_byte(client);
-                               if (j < 0)
+                       for (i = slice << 5; i < (slice + 1) << 5; i += 2) {
+                               int word = i2c_smbus_read_word_data(client, i);
+                               if (word < 0)
                                        goto exit;
-                               data->data[i] = (u8) j;
+                               data->data[i] = word & 0xff;
+                               data->data[i + 1] = word >> 8;
                        }
                }
                data->last_updated[slice] = jiffies;
@@ -177,14 +174,15 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
        if (!(adapter->class & I2C_CLASS_SPD) && address >= 0x51)
                goto exit;
 
-       /* There are three ways we can read the EEPROM data:
+       /* There are four ways we can read the EEPROM data:
           (1) I2C block reads (faster, but unsupported by most adapters)
-          (2) Consecutive byte reads (100% overhead)
-          (3) Regular byte data reads (200% overhead)
-          The third method is not implemented by this driver because all
-          known adapters support at least the second. */
-       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA
-                                           | I2C_FUNC_SMBUS_BYTE))
+          (2) Word reads (128% overhead)
+          (3) Consecutive byte reads (88% overhead, unsafe)
+          (4) Regular byte data reads (265% overhead)
+          The third and fourth methods are not implemented by this driver
+          because all known adapters support one of the first two. */
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)
+        && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK))
                goto exit;
 
        if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
@@ -212,13 +210,14 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
 
        /* Detect the Vaio nature of EEPROMs.
           We use the "PCG-" or "VGN-" prefix as the signature. */
-       if (address == 0x57) {
+       if (address == 0x57
+        && i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
                char name[4];
 
                name[0] = i2c_smbus_read_byte_data(new_client, 0x80);
-               name[1] = i2c_smbus_read_byte(new_client);
-               name[2] = i2c_smbus_read_byte(new_client);
-               name[3] = i2c_smbus_read_byte(new_client);
+               name[1] = i2c_smbus_read_byte_data(new_client, 0x81);
+               name[2] = i2c_smbus_read_byte_data(new_client, 0x82);
+               name[3] = i2c_smbus_read_byte_data(new_client, 0x83);
 
                if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) {
                        dev_info(&new_client->dev, "Vaio EEPROM detected, "