diff options
author | Kevin Hilman <khilman@deeprootsystems.com> | 2009-04-02 19:56:57 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-02 22:04:50 -0400 |
commit | 7274ec8bd71e99018642f474528ea7de4bb3ae25 (patch) | |
tree | 3c2e719f696292afa0717f7111d174bdfc073f27 /drivers | |
parent | 06c421ee0d5af95c8c6749ca0ba620cd5010707f (diff) |
memory_accessor: implement the new memory_accessor interface for I2C EEPROM
In the case of at24, the platform code registers a 'setup' callback with
the at24_platform_data. When the at24 driver detects an EEPROM, it fills
out the read and write functions of the memory_accessor and calls the
setup callback passing the memory_accessor struct. The platform code can
then use the read/write functions in the memory_accessor struct for
reading and writing the EEPROM.
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/misc/eeprom/at24.c | 67 |
1 files changed, 54 insertions, 13 deletions
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index d4775528abc6..d184dfab9631 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c | |||
@@ -53,6 +53,7 @@ | |||
53 | 53 | ||
54 | struct at24_data { | 54 | struct at24_data { |
55 | struct at24_platform_data chip; | 55 | struct at24_platform_data chip; |
56 | struct memory_accessor macc; | ||
56 | bool use_smbus; | 57 | bool use_smbus; |
57 | 58 | ||
58 | /* | 59 | /* |
@@ -225,14 +226,11 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, | |||
225 | return status; | 226 | return status; |
226 | } | 227 | } |
227 | 228 | ||
228 | static ssize_t at24_bin_read(struct kobject *kobj, struct bin_attribute *attr, | 229 | static ssize_t at24_read(struct at24_data *at24, |
229 | char *buf, loff_t off, size_t count) | 230 | char *buf, loff_t off, size_t count) |
230 | { | 231 | { |
231 | struct at24_data *at24; | ||
232 | ssize_t retval = 0; | 232 | ssize_t retval = 0; |
233 | 233 | ||
234 | at24 = dev_get_drvdata(container_of(kobj, struct device, kobj)); | ||
235 | |||
236 | if (unlikely(!count)) | 234 | if (unlikely(!count)) |
237 | return count; | 235 | return count; |
238 | 236 | ||
@@ -262,12 +260,14 @@ static ssize_t at24_bin_read(struct kobject *kobj, struct bin_attribute *attr, | |||
262 | return retval; | 260 | return retval; |
263 | } | 261 | } |
264 | 262 | ||
263 | static ssize_t at24_bin_read(struct kobject *kobj, struct bin_attribute *attr, | ||
264 | char *buf, loff_t off, size_t count) | ||
265 | { | ||
266 | struct at24_data *at24; | ||
265 | 267 | ||
266 | /* | 268 | at24 = dev_get_drvdata(container_of(kobj, struct device, kobj)); |
267 | * REVISIT: export at24_bin{read,write}() to let other kernel code use | 269 | return at24_read(at24, buf, off, count); |
268 | * eeprom data. For example, it might hold a board's Ethernet address, or | 270 | } |
269 | * board-specific calibration data generated on the manufacturing floor. | ||
270 | */ | ||
271 | 271 | ||
272 | 272 | ||
273 | /* | 273 | /* |
@@ -347,14 +347,11 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, char *buf, | |||
347 | return -ETIMEDOUT; | 347 | return -ETIMEDOUT; |
348 | } | 348 | } |
349 | 349 | ||
350 | static ssize_t at24_bin_write(struct kobject *kobj, struct bin_attribute *attr, | 350 | static ssize_t at24_write(struct at24_data *at24, |
351 | char *buf, loff_t off, size_t count) | 351 | char *buf, loff_t off, size_t count) |
352 | { | 352 | { |
353 | struct at24_data *at24; | ||
354 | ssize_t retval = 0; | 353 | ssize_t retval = 0; |
355 | 354 | ||
356 | at24 = dev_get_drvdata(container_of(kobj, struct device, kobj)); | ||
357 | |||
358 | if (unlikely(!count)) | 355 | if (unlikely(!count)) |
359 | return count; | 356 | return count; |
360 | 357 | ||
@@ -384,6 +381,39 @@ static ssize_t at24_bin_write(struct kobject *kobj, struct bin_attribute *attr, | |||
384 | return retval; | 381 | return retval; |
385 | } | 382 | } |
386 | 383 | ||
384 | static ssize_t at24_bin_write(struct kobject *kobj, struct bin_attribute *attr, | ||
385 | char *buf, loff_t off, size_t count) | ||
386 | { | ||
387 | struct at24_data *at24; | ||
388 | |||
389 | at24 = dev_get_drvdata(container_of(kobj, struct device, kobj)); | ||
390 | return at24_write(at24, buf, off, count); | ||
391 | } | ||
392 | |||
393 | /*-------------------------------------------------------------------------*/ | ||
394 | |||
395 | /* | ||
396 | * This lets other kernel code access the eeprom data. For example, it | ||
397 | * might hold a board's Ethernet address, or board-specific calibration | ||
398 | * data generated on the manufacturing floor. | ||
399 | */ | ||
400 | |||
401 | static ssize_t at24_macc_read(struct memory_accessor *macc, char *buf, | ||
402 | off_t offset, size_t count) | ||
403 | { | ||
404 | struct at24_data *at24 = container_of(macc, struct at24_data, macc); | ||
405 | |||
406 | return at24_read(at24, buf, offset, count); | ||
407 | } | ||
408 | |||
409 | static ssize_t at24_macc_write(struct memory_accessor *macc, char *buf, | ||
410 | off_t offset, size_t count) | ||
411 | { | ||
412 | struct at24_data *at24 = container_of(macc, struct at24_data, macc); | ||
413 | |||
414 | return at24_write(at24, buf, offset, count); | ||
415 | } | ||
416 | |||
387 | /*-------------------------------------------------------------------------*/ | 417 | /*-------------------------------------------------------------------------*/ |
388 | 418 | ||
389 | static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) | 419 | static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) |
@@ -413,6 +443,9 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
413 | * is recommended anyhow. | 443 | * is recommended anyhow. |
414 | */ | 444 | */ |
415 | chip.page_size = 1; | 445 | chip.page_size = 1; |
446 | |||
447 | chip.setup = NULL; | ||
448 | chip.context = NULL; | ||
416 | } | 449 | } |
417 | 450 | ||
418 | if (!is_power_of_2(chip.byte_len)) | 451 | if (!is_power_of_2(chip.byte_len)) |
@@ -463,6 +496,8 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
463 | at24->bin.read = at24_bin_read; | 496 | at24->bin.read = at24_bin_read; |
464 | at24->bin.size = chip.byte_len; | 497 | at24->bin.size = chip.byte_len; |
465 | 498 | ||
499 | at24->macc.read = at24_macc_read; | ||
500 | |||
466 | writable = !(chip.flags & AT24_FLAG_READONLY); | 501 | writable = !(chip.flags & AT24_FLAG_READONLY); |
467 | if (writable) { | 502 | if (writable) { |
468 | if (!use_smbus || i2c_check_functionality(client->adapter, | 503 | if (!use_smbus || i2c_check_functionality(client->adapter, |
@@ -470,6 +505,8 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
470 | 505 | ||
471 | unsigned write_max = chip.page_size; | 506 | unsigned write_max = chip.page_size; |
472 | 507 | ||
508 | at24->macc.write = at24_macc_write; | ||
509 | |||
473 | at24->bin.write = at24_bin_write; | 510 | at24->bin.write = at24_bin_write; |
474 | at24->bin.attr.mode |= S_IWUSR; | 511 | at24->bin.attr.mode |= S_IWUSR; |
475 | 512 | ||
@@ -520,6 +557,10 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
520 | at24->write_max, | 557 | at24->write_max, |
521 | use_smbus ? ", use_smbus" : ""); | 558 | use_smbus ? ", use_smbus" : ""); |
522 | 559 | ||
560 | /* export data to kernel code */ | ||
561 | if (chip.setup) | ||
562 | chip.setup(&at24->macc, chip.context); | ||
563 | |||
523 | return 0; | 564 | return 0; |
524 | 565 | ||
525 | err_clients: | 566 | err_clients: |