diff options
Diffstat (limited to 'drivers/i2c/chips/eeprom.c')
-rw-r--r-- | drivers/i2c/chips/eeprom.c | 39 |
1 files changed, 19 insertions, 20 deletions
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c index 213a9f98decc..9a81252a7218 100644 --- a/drivers/i2c/chips/eeprom.c +++ b/drivers/i2c/chips/eeprom.c | |||
@@ -78,7 +78,7 @@ static struct i2c_driver eeprom_driver = { | |||
78 | static void eeprom_update_client(struct i2c_client *client, u8 slice) | 78 | static void eeprom_update_client(struct i2c_client *client, u8 slice) |
79 | { | 79 | { |
80 | struct eeprom_data *data = i2c_get_clientdata(client); | 80 | struct eeprom_data *data = i2c_get_clientdata(client); |
81 | int i, j; | 81 | int i; |
82 | 82 | ||
83 | mutex_lock(&data->update_lock); | 83 | mutex_lock(&data->update_lock); |
84 | 84 | ||
@@ -93,15 +93,12 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice) | |||
93 | != 32) | 93 | != 32) |
94 | goto exit; | 94 | goto exit; |
95 | } else { | 95 | } else { |
96 | if (i2c_smbus_write_byte(client, slice << 5)) { | 96 | for (i = slice << 5; i < (slice + 1) << 5; i += 2) { |
97 | dev_dbg(&client->dev, "eeprom read start has failed!\n"); | 97 | int word = i2c_smbus_read_word_data(client, i); |
98 | goto exit; | 98 | if (word < 0) |
99 | } | ||
100 | for (i = slice << 5; i < (slice + 1) << 5; i++) { | ||
101 | j = i2c_smbus_read_byte(client); | ||
102 | if (j < 0) | ||
103 | goto exit; | 99 | goto exit; |
104 | data->data[i] = (u8) j; | 100 | data->data[i] = word & 0xff; |
101 | data->data[i + 1] = word >> 8; | ||
105 | } | 102 | } |
106 | } | 103 | } |
107 | data->last_updated[slice] = jiffies; | 104 | data->last_updated[slice] = jiffies; |
@@ -177,14 +174,15 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) | |||
177 | if (!(adapter->class & I2C_CLASS_SPD) && address >= 0x51) | 174 | if (!(adapter->class & I2C_CLASS_SPD) && address >= 0x51) |
178 | goto exit; | 175 | goto exit; |
179 | 176 | ||
180 | /* There are three ways we can read the EEPROM data: | 177 | /* There are four ways we can read the EEPROM data: |
181 | (1) I2C block reads (faster, but unsupported by most adapters) | 178 | (1) I2C block reads (faster, but unsupported by most adapters) |
182 | (2) Consecutive byte reads (100% overhead) | 179 | (2) Word reads (128% overhead) |
183 | (3) Regular byte data reads (200% overhead) | 180 | (3) Consecutive byte reads (88% overhead, unsafe) |
184 | The third method is not implemented by this driver because all | 181 | (4) Regular byte data reads (265% overhead) |
185 | known adapters support at least the second. */ | 182 | The third and fourth methods are not implemented by this driver |
186 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA | 183 | because all known adapters support one of the first two. */ |
187 | | I2C_FUNC_SMBUS_BYTE)) | 184 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA) |
185 | && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) | ||
188 | goto exit; | 186 | goto exit; |
189 | 187 | ||
190 | if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { | 188 | 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) | |||
212 | 210 | ||
213 | /* Detect the Vaio nature of EEPROMs. | 211 | /* Detect the Vaio nature of EEPROMs. |
214 | We use the "PCG-" or "VGN-" prefix as the signature. */ | 212 | We use the "PCG-" or "VGN-" prefix as the signature. */ |
215 | if (address == 0x57) { | 213 | if (address == 0x57 |
214 | && i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) { | ||
216 | char name[4]; | 215 | char name[4]; |
217 | 216 | ||
218 | name[0] = i2c_smbus_read_byte_data(new_client, 0x80); | 217 | name[0] = i2c_smbus_read_byte_data(new_client, 0x80); |
219 | name[1] = i2c_smbus_read_byte(new_client); | 218 | name[1] = i2c_smbus_read_byte_data(new_client, 0x81); |
220 | name[2] = i2c_smbus_read_byte(new_client); | 219 | name[2] = i2c_smbus_read_byte_data(new_client, 0x82); |
221 | name[3] = i2c_smbus_read_byte(new_client); | 220 | name[3] = i2c_smbus_read_byte_data(new_client, 0x83); |
222 | 221 | ||
223 | if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) { | 222 | if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) { |
224 | dev_info(&new_client->dev, "Vaio EEPROM detected, " | 223 | dev_info(&new_client->dev, "Vaio EEPROM detected, " |