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 | ||
