diff options
Diffstat (limited to 'drivers/misc/eeprom/at24.c')
-rw-r--r-- | drivers/misc/eeprom/at24.c | 103 |
1 files changed, 22 insertions, 81 deletions
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index 6cc17b7779a5..9ceb63b62be5 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/acpi.h> | 23 | #include <linux/acpi.h> |
24 | #include <linux/i2c.h> | 24 | #include <linux/i2c.h> |
25 | #include <linux/nvmem-provider.h> | 25 | #include <linux/nvmem-provider.h> |
26 | #include <linux/regmap.h> | ||
27 | #include <linux/platform_data/at24.h> | 26 | #include <linux/platform_data/at24.h> |
28 | 27 | ||
29 | /* | 28 | /* |
@@ -69,7 +68,6 @@ struct at24_data { | |||
69 | unsigned write_max; | 68 | unsigned write_max; |
70 | unsigned num_addresses; | 69 | unsigned num_addresses; |
71 | 70 | ||
72 | struct regmap_config regmap_config; | ||
73 | struct nvmem_config nvmem_config; | 71 | struct nvmem_config nvmem_config; |
74 | struct nvmem_device *nvmem; | 72 | struct nvmem_device *nvmem; |
75 | 73 | ||
@@ -251,10 +249,10 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, | |||
251 | return -ETIMEDOUT; | 249 | return -ETIMEDOUT; |
252 | } | 250 | } |
253 | 251 | ||
254 | static ssize_t at24_read(struct at24_data *at24, | 252 | static int at24_read(void *priv, unsigned int off, void *val, size_t count) |
255 | char *buf, loff_t off, size_t count) | ||
256 | { | 253 | { |
257 | ssize_t retval = 0; | 254 | struct at24_data *at24 = priv; |
255 | char *buf = val; | ||
258 | 256 | ||
259 | if (unlikely(!count)) | 257 | if (unlikely(!count)) |
260 | return count; | 258 | return count; |
@@ -266,23 +264,21 @@ static ssize_t at24_read(struct at24_data *at24, | |||
266 | mutex_lock(&at24->lock); | 264 | mutex_lock(&at24->lock); |
267 | 265 | ||
268 | while (count) { | 266 | while (count) { |
269 | ssize_t status; | 267 | int status; |
270 | 268 | ||
271 | status = at24_eeprom_read(at24, buf, off, count); | 269 | status = at24_eeprom_read(at24, buf, off, count); |
272 | if (status <= 0) { | 270 | if (status < 0) { |
273 | if (retval == 0) | 271 | mutex_unlock(&at24->lock); |
274 | retval = status; | 272 | return status; |
275 | break; | ||
276 | } | 273 | } |
277 | buf += status; | 274 | buf += status; |
278 | off += status; | 275 | off += status; |
279 | count -= status; | 276 | count -= status; |
280 | retval += status; | ||
281 | } | 277 | } |
282 | 278 | ||
283 | mutex_unlock(&at24->lock); | 279 | mutex_unlock(&at24->lock); |
284 | 280 | ||
285 | return retval; | 281 | return 0; |
286 | } | 282 | } |
287 | 283 | ||
288 | /* | 284 | /* |
@@ -370,13 +366,13 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, | |||
370 | return -ETIMEDOUT; | 366 | return -ETIMEDOUT; |
371 | } | 367 | } |
372 | 368 | ||
373 | static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off, | 369 | static int at24_write(void *priv, unsigned int off, void *val, size_t count) |
374 | size_t count) | ||
375 | { | 370 | { |
376 | ssize_t retval = 0; | 371 | struct at24_data *at24 = priv; |
372 | char *buf = val; | ||
377 | 373 | ||
378 | if (unlikely(!count)) | 374 | if (unlikely(!count)) |
379 | return count; | 375 | return -EINVAL; |
380 | 376 | ||
381 | /* | 377 | /* |
382 | * Write data to chip, protecting against concurrent updates | 378 | * Write data to chip, protecting against concurrent updates |
@@ -385,70 +381,23 @@ static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off, | |||
385 | mutex_lock(&at24->lock); | 381 | mutex_lock(&at24->lock); |
386 | 382 | ||
387 | while (count) { | 383 | while (count) { |
388 | ssize_t status; | 384 | int status; |
389 | 385 | ||
390 | status = at24_eeprom_write(at24, buf, off, count); | 386 | status = at24_eeprom_write(at24, buf, off, count); |
391 | if (status <= 0) { | 387 | if (status < 0) { |
392 | if (retval == 0) | 388 | mutex_unlock(&at24->lock); |
393 | retval = status; | 389 | return status; |
394 | break; | ||
395 | } | 390 | } |
396 | buf += status; | 391 | buf += status; |
397 | off += status; | 392 | off += status; |
398 | count -= status; | 393 | count -= status; |
399 | retval += status; | ||
400 | } | 394 | } |
401 | 395 | ||
402 | mutex_unlock(&at24->lock); | 396 | mutex_unlock(&at24->lock); |
403 | 397 | ||
404 | return retval; | ||
405 | } | ||
406 | |||
407 | /*-------------------------------------------------------------------------*/ | ||
408 | |||
409 | /* | ||
410 | * Provide a regmap interface, which is registered with the NVMEM | ||
411 | * framework | ||
412 | */ | ||
413 | static int at24_regmap_read(void *context, const void *reg, size_t reg_size, | ||
414 | void *val, size_t val_size) | ||
415 | { | ||
416 | struct at24_data *at24 = context; | ||
417 | off_t offset = *(u32 *)reg; | ||
418 | int err; | ||
419 | |||
420 | err = at24_read(at24, val, offset, val_size); | ||
421 | if (err) | ||
422 | return err; | ||
423 | return 0; | ||
424 | } | ||
425 | |||
426 | static int at24_regmap_write(void *context, const void *data, size_t count) | ||
427 | { | ||
428 | struct at24_data *at24 = context; | ||
429 | const char *buf; | ||
430 | u32 offset; | ||
431 | size_t len; | ||
432 | int err; | ||
433 | |||
434 | memcpy(&offset, data, sizeof(offset)); | ||
435 | buf = (const char *)data + sizeof(offset); | ||
436 | len = count - sizeof(offset); | ||
437 | |||
438 | err = at24_write(at24, buf, offset, len); | ||
439 | if (err) | ||
440 | return err; | ||
441 | return 0; | 398 | return 0; |
442 | } | 399 | } |
443 | 400 | ||
444 | static const struct regmap_bus at24_regmap_bus = { | ||
445 | .read = at24_regmap_read, | ||
446 | .write = at24_regmap_write, | ||
447 | .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, | ||
448 | }; | ||
449 | |||
450 | /*-------------------------------------------------------------------------*/ | ||
451 | |||
452 | #ifdef CONFIG_OF | 401 | #ifdef CONFIG_OF |
453 | static void at24_get_ofdata(struct i2c_client *client, | 402 | static void at24_get_ofdata(struct i2c_client *client, |
454 | struct at24_platform_data *chip) | 403 | struct at24_platform_data *chip) |
@@ -480,7 +429,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
480 | struct at24_data *at24; | 429 | struct at24_data *at24; |
481 | int err; | 430 | int err; |
482 | unsigned i, num_addresses; | 431 | unsigned i, num_addresses; |
483 | struct regmap *regmap; | ||
484 | 432 | ||
485 | if (client->dev.platform_data) { | 433 | if (client->dev.platform_data) { |
486 | chip = *(struct at24_platform_data *)client->dev.platform_data; | 434 | chip = *(struct at24_platform_data *)client->dev.platform_data; |
@@ -607,19 +555,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
607 | } | 555 | } |
608 | } | 556 | } |
609 | 557 | ||
610 | at24->regmap_config.reg_bits = 32; | ||
611 | at24->regmap_config.val_bits = 8; | ||
612 | at24->regmap_config.reg_stride = 1; | ||
613 | at24->regmap_config.max_register = chip.byte_len - 1; | ||
614 | |||
615 | regmap = devm_regmap_init(&client->dev, &at24_regmap_bus, at24, | ||
616 | &at24->regmap_config); | ||
617 | if (IS_ERR(regmap)) { | ||
618 | dev_err(&client->dev, "regmap init failed\n"); | ||
619 | err = PTR_ERR(regmap); | ||
620 | goto err_clients; | ||
621 | } | ||
622 | |||
623 | at24->nvmem_config.name = dev_name(&client->dev); | 558 | at24->nvmem_config.name = dev_name(&client->dev); |
624 | at24->nvmem_config.dev = &client->dev; | 559 | at24->nvmem_config.dev = &client->dev; |
625 | at24->nvmem_config.read_only = !writable; | 560 | at24->nvmem_config.read_only = !writable; |
@@ -627,6 +562,12 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
627 | at24->nvmem_config.owner = THIS_MODULE; | 562 | at24->nvmem_config.owner = THIS_MODULE; |
628 | at24->nvmem_config.compat = true; | 563 | at24->nvmem_config.compat = true; |
629 | at24->nvmem_config.base_dev = &client->dev; | 564 | at24->nvmem_config.base_dev = &client->dev; |
565 | at24->nvmem_config.reg_read = at24_read; | ||
566 | at24->nvmem_config.reg_write = at24_write; | ||
567 | at24->nvmem_config.priv = at24; | ||
568 | at24->nvmem_config.stride = 4; | ||
569 | at24->nvmem_config.word_size = 1; | ||
570 | at24->nvmem_config.size = chip.byte_len; | ||
630 | 571 | ||
631 | at24->nvmem = nvmem_register(&at24->nvmem_config); | 572 | at24->nvmem = nvmem_register(&at24->nvmem_config); |
632 | 573 | ||