aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/misc/eeprom/at24.c59
1 files changed, 48 insertions, 11 deletions
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index db7d0f21b65d..0c11e411d8ec 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -54,7 +54,7 @@
54struct at24_data { 54struct at24_data {
55 struct at24_platform_data chip; 55 struct at24_platform_data chip;
56 struct memory_accessor macc; 56 struct memory_accessor macc;
57 bool use_smbus; 57 int use_smbus;
58 58
59 /* 59 /*
60 * Lock protects against activities from other Linux tasks, 60 * Lock protects against activities from other Linux tasks,
@@ -184,11 +184,19 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
184 if (count > io_limit) 184 if (count > io_limit)
185 count = io_limit; 185 count = io_limit;
186 186
187 if (at24->use_smbus) { 187 switch (at24->use_smbus) {
188 case I2C_SMBUS_I2C_BLOCK_DATA:
188 /* Smaller eeproms can work given some SMBus extension calls */ 189 /* Smaller eeproms can work given some SMBus extension calls */
189 if (count > I2C_SMBUS_BLOCK_MAX) 190 if (count > I2C_SMBUS_BLOCK_MAX)
190 count = I2C_SMBUS_BLOCK_MAX; 191 count = I2C_SMBUS_BLOCK_MAX;
191 } else { 192 break;
193 case I2C_SMBUS_WORD_DATA:
194 count = 2;
195 break;
196 case I2C_SMBUS_BYTE_DATA:
197 count = 1;
198 break;
199 default:
192 /* 200 /*
193 * When we have a better choice than SMBus calls, use a 201 * When we have a better choice than SMBus calls, use a
194 * combined I2C message. Write address; then read up to 202 * combined I2C message. Write address; then read up to
@@ -219,10 +227,27 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
219 timeout = jiffies + msecs_to_jiffies(write_timeout); 227 timeout = jiffies + msecs_to_jiffies(write_timeout);
220 do { 228 do {
221 read_time = jiffies; 229 read_time = jiffies;
222 if (at24->use_smbus) { 230 switch (at24->use_smbus) {
231 case I2C_SMBUS_I2C_BLOCK_DATA:
223 status = i2c_smbus_read_i2c_block_data(client, offset, 232 status = i2c_smbus_read_i2c_block_data(client, offset,
224 count, buf); 233 count, buf);
225 } else { 234 break;
235 case I2C_SMBUS_WORD_DATA:
236 status = i2c_smbus_read_word_data(client, offset);
237 if (status >= 0) {
238 buf[0] = status & 0xff;
239 buf[1] = status >> 8;
240 status = count;
241 }
242 break;
243 case I2C_SMBUS_BYTE_DATA:
244 status = i2c_smbus_read_byte_data(client, offset);
245 if (status >= 0) {
246 buf[0] = status;
247 status = count;
248 }
249 break;
250 default:
226 status = i2c_transfer(client->adapter, msg, 2); 251 status = i2c_transfer(client->adapter, msg, 2);
227 if (status == 2) 252 if (status == 2)
228 status = count; 253 status = count;
@@ -434,7 +459,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
434{ 459{
435 struct at24_platform_data chip; 460 struct at24_platform_data chip;
436 bool writable; 461 bool writable;
437 bool use_smbus = false; 462 int use_smbus = 0;
438 struct at24_data *at24; 463 struct at24_data *at24;
439 int err; 464 int err;
440 unsigned i, num_addresses; 465 unsigned i, num_addresses;
@@ -475,12 +500,19 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
475 err = -EPFNOSUPPORT; 500 err = -EPFNOSUPPORT;
476 goto err_out; 501 goto err_out;
477 } 502 }
478 if (!i2c_check_functionality(client->adapter, 503 if (i2c_check_functionality(client->adapter,
479 I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { 504 I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
505 use_smbus = I2C_SMBUS_I2C_BLOCK_DATA;
506 } else if (i2c_check_functionality(client->adapter,
507 I2C_FUNC_SMBUS_READ_WORD_DATA)) {
508 use_smbus = I2C_SMBUS_WORD_DATA;
509 } else if (i2c_check_functionality(client->adapter,
510 I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
511 use_smbus = I2C_SMBUS_BYTE_DATA;
512 } else {
480 err = -EPFNOSUPPORT; 513 err = -EPFNOSUPPORT;
481 goto err_out; 514 goto err_out;
482 } 515 }
483 use_smbus = true;
484 } 516 }
485 517
486 if (chip.flags & AT24_FLAG_TAKE8ADDR) 518 if (chip.flags & AT24_FLAG_TAKE8ADDR)
@@ -566,11 +598,16 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
566 dev_info(&client->dev, "%zu byte %s EEPROM %s\n", 598 dev_info(&client->dev, "%zu byte %s EEPROM %s\n",
567 at24->bin.size, client->name, 599 at24->bin.size, client->name,
568 writable ? "(writable)" : "(read-only)"); 600 writable ? "(writable)" : "(read-only)");
601 if (use_smbus == I2C_SMBUS_WORD_DATA ||
602 use_smbus == I2C_SMBUS_BYTE_DATA) {
603 dev_notice(&client->dev, "Falling back to %s reads, "
604 "performance will suffer\n", use_smbus ==
605 I2C_SMBUS_WORD_DATA ? "word" : "byte");
606 }
569 dev_dbg(&client->dev, 607 dev_dbg(&client->dev,
570 "page_size %d, num_addresses %d, write_max %d%s\n", 608 "page_size %d, num_addresses %d, write_max %d, use_smbus %d\n",
571 chip.page_size, num_addresses, 609 chip.page_size, num_addresses,
572 at24->write_max, 610 at24->write_max, use_smbus);
573 use_smbus ? ", use_smbus" : "");
574 611
575 /* export data to kernel code */ 612 /* export data to kernel code */
576 if (chip.setup) 613 if (chip.setup)