diff options
author | Christian Gmeiner <christian.gmeiner@gmail.com> | 2014-10-09 05:07:58 -0400 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2014-11-17 13:54:22 -0500 |
commit | a839ce663b3183209fdf7b1fc4796bfe2a4679c3 (patch) | |
tree | c8ba8197fe356f0da31e8a5af5082d4fa28998a3 | |
parent | 3eee1799aed90e990e02a73a89bfcff1982c74dd (diff) |
eeprom: at24: extend driver to allow writing via i2c_smbus_write_byte_data
I have a at24 EEPROM connected via i2c bus provided by ISCH i2c
bus driver. This bus driver does not support
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK and so I was looking for a way
to be able to write the eeprom. This patch adds support for
I2C_SMBUS_BYTE_DATA writing via i2c_smbus_write_byte_data.
It is quite slow, but it works.
Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
[wsa: s/use_smbuse_write/use_smbus_write/]
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
-rw-r--r-- | drivers/misc/eeprom/at24.c | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index d87f77f790d6..2d3db81be099 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c | |||
@@ -56,6 +56,7 @@ struct at24_data { | |||
56 | struct at24_platform_data chip; | 56 | struct at24_platform_data chip; |
57 | struct memory_accessor macc; | 57 | struct memory_accessor macc; |
58 | int use_smbus; | 58 | int use_smbus; |
59 | int use_smbus_write; | ||
59 | 60 | ||
60 | /* | 61 | /* |
61 | * Lock protects against activities from other Linux tasks, | 62 | * Lock protects against activities from other Linux tasks, |
@@ -324,7 +325,7 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, | |||
324 | { | 325 | { |
325 | struct i2c_client *client; | 326 | struct i2c_client *client; |
326 | struct i2c_msg msg; | 327 | struct i2c_msg msg; |
327 | ssize_t status; | 328 | ssize_t status = 0; |
328 | unsigned long timeout, write_time; | 329 | unsigned long timeout, write_time; |
329 | unsigned next_page; | 330 | unsigned next_page; |
330 | 331 | ||
@@ -365,9 +366,18 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, | |||
365 | timeout = jiffies + msecs_to_jiffies(write_timeout); | 366 | timeout = jiffies + msecs_to_jiffies(write_timeout); |
366 | do { | 367 | do { |
367 | write_time = jiffies; | 368 | write_time = jiffies; |
368 | if (at24->use_smbus) { | 369 | if (at24->use_smbus_write) { |
369 | status = i2c_smbus_write_i2c_block_data(client, | 370 | switch (at24->use_smbus_write) { |
370 | offset, count, buf); | 371 | case I2C_SMBUS_I2C_BLOCK_DATA: |
372 | status = i2c_smbus_write_i2c_block_data(client, | ||
373 | offset, count, buf); | ||
374 | break; | ||
375 | case I2C_SMBUS_BYTE_DATA: | ||
376 | status = i2c_smbus_write_byte_data(client, | ||
377 | offset, buf[0]); | ||
378 | break; | ||
379 | } | ||
380 | |||
371 | if (status == 0) | 381 | if (status == 0) |
372 | status = count; | 382 | status = count; |
373 | } else { | 383 | } else { |
@@ -487,6 +497,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
487 | struct at24_platform_data chip; | 497 | struct at24_platform_data chip; |
488 | bool writable; | 498 | bool writable; |
489 | int use_smbus = 0; | 499 | int use_smbus = 0; |
500 | int use_smbus_write = 0; | ||
490 | struct at24_data *at24; | 501 | struct at24_data *at24; |
491 | int err; | 502 | int err; |
492 | unsigned i, num_addresses; | 503 | unsigned i, num_addresses; |
@@ -546,6 +557,18 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
546 | } | 557 | } |
547 | } | 558 | } |
548 | 559 | ||
560 | /* Use I2C operations unless we're stuck with SMBus extensions. */ | ||
561 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
562 | if (i2c_check_functionality(client->adapter, | ||
563 | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) { | ||
564 | use_smbus_write = I2C_SMBUS_I2C_BLOCK_DATA; | ||
565 | } else if (i2c_check_functionality(client->adapter, | ||
566 | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { | ||
567 | use_smbus_write = I2C_SMBUS_BYTE_DATA; | ||
568 | chip.page_size = 1; | ||
569 | } | ||
570 | } | ||
571 | |||
549 | if (chip.flags & AT24_FLAG_TAKE8ADDR) | 572 | if (chip.flags & AT24_FLAG_TAKE8ADDR) |
550 | num_addresses = 8; | 573 | num_addresses = 8; |
551 | else | 574 | else |
@@ -559,6 +582,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
559 | 582 | ||
560 | mutex_init(&at24->lock); | 583 | mutex_init(&at24->lock); |
561 | at24->use_smbus = use_smbus; | 584 | at24->use_smbus = use_smbus; |
585 | at24->use_smbus_write = use_smbus_write; | ||
562 | at24->chip = chip; | 586 | at24->chip = chip; |
563 | at24->num_addresses = num_addresses; | 587 | at24->num_addresses = num_addresses; |
564 | 588 | ||
@@ -576,8 +600,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
576 | 600 | ||
577 | writable = !(chip.flags & AT24_FLAG_READONLY); | 601 | writable = !(chip.flags & AT24_FLAG_READONLY); |
578 | if (writable) { | 602 | if (writable) { |
579 | if (!use_smbus || i2c_check_functionality(client->adapter, | 603 | if (!use_smbus || use_smbus_write) { |
580 | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) { | ||
581 | 604 | ||
582 | unsigned write_max = chip.page_size; | 605 | unsigned write_max = chip.page_size; |
583 | 606 | ||