aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/eeprom/at24.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/eeprom/at24.c')
-rw-r--r--drivers/misc/eeprom/at24.c103
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
254static ssize_t at24_read(struct at24_data *at24, 252static 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
373static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off, 369static 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*/
413static 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
426static 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
444static 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
453static void at24_get_ofdata(struct i2c_client *client, 402static 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