• Home
  • Raw
  • Download

Lines Matching +full:no +full:- +full:read +full:- +full:rollover

1 // SPDX-License-Identifier: GPL-2.0+
3 * at24.c - handle most I2C EEPROMs
5 * Copyright (C) 2005-2007 David Brownell
23 #include <linux/nvmem-provider.h>
32 * MicroChip 24LC, etc) won't much matter for typical read/write access.
36 * However, misconfiguration can lose data. "Set 16-bit memory address"
37 * to a part with 8-bit addressing will overwrite data. Writing with too
42 * Accordingly, explicit board-specific configuration data should be used
47 * told what devices exist. That may be in arch/X/mach-Y/board-Z.c or
48 * similar kernel-resident tables; or, configuration data coming from
53 * It also handles larger devices (32 kbit and up) with two-byte addresses,
91 * clock, one 256 byte read takes about 1/43 second which is excessive;
123 /* needs 8 addresses as A0-A2 are ignored */
142 /* 24rf08 quirk is handled at i2c-core */
229 * Assumes that sanity checks for offset happened at sysfs-layer.
232 * set the byte address; on a multi-master board, another master
240 if (at24->flags & AT24_FLAG_ADDR16) { in at24_translate_offset()
248 return &at24->client[i]; in at24_translate_offset()
253 return &at24->client[0].client->dev; in at24_base_client_dev()
263 * In case of multi-address chips that don't rollover reads to in at24_adjust_read_count()
265 * so that the read never straddles slaves. in at24_adjust_read_count()
267 if (at24->flags & AT24_FLAG_NO_RDROL) { in at24_adjust_read_count()
268 bits = (at24->flags & AT24_FLAG_ADDR16) ? 16 : 8; in at24_adjust_read_count()
269 remainder = BIT(bits) - offset; in at24_adjust_read_count()
290 regmap = at24_client->regmap; in at24_regmap_read()
291 client = at24_client->client; in at24_regmap_read()
294 /* adjust offset for mac and serial read ops */ in at24_regmap_read()
295 offset += at24->offset_adj; in at24_regmap_read()
306 dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n", in at24_regmap_read()
314 return -ETIMEDOUT; in at24_regmap_read()
318 * Note that if the hardware write-protect pin is pulled high, the whole
332 if (count > at24->write_max) in at24_adjust_write_count()
333 count = at24->write_max; in at24_adjust_write_count()
336 next_page = roundup(offset + 1, at24->page_size); in at24_adjust_write_count()
338 count = next_page - offset; in at24_adjust_write_count()
353 regmap = at24_client->regmap; in at24_regmap_write()
354 client = at24_client->client; in at24_regmap_write()
366 dev_dbg(&client->dev, "write %zu@%d --> %d (%ld)\n", in at24_regmap_write()
374 return -ETIMEDOUT; in at24_regmap_write()
390 if (off + count > at24->byte_len) in at24_read()
391 return -EINVAL; in at24_read()
400 * Read data from chip, protecting against concurrent updates in at24_read()
403 mutex_lock(&at24->lock); in at24_read()
408 mutex_unlock(&at24->lock); in at24_read()
414 count -= ret; in at24_read()
417 mutex_unlock(&at24->lock); in at24_read()
435 return -EINVAL; in at24_write()
437 if (off + count > at24->byte_len) in at24_write()
438 return -EINVAL; in at24_write()
450 mutex_lock(&at24->lock); in at24_write()
451 gpiod_set_value_cansleep(at24->wp_gpio, 0); in at24_write()
456 gpiod_set_value_cansleep(at24->wp_gpio, 1); in at24_write()
457 mutex_unlock(&at24->lock); in at24_write()
463 count -= ret; in at24_write()
466 gpiod_set_value_cansleep(at24->wp_gpio, 1); in at24_write()
467 mutex_unlock(&at24->lock); in at24_write()
480 if (device_property_present(dev, "read-only")) in at24_properties_to_pdata()
481 chip->flags |= AT24_FLAG_READONLY; in at24_properties_to_pdata()
482 if (device_property_present(dev, "no-read-rollover")) in at24_properties_to_pdata()
483 chip->flags |= AT24_FLAG_NO_RDROL; in at24_properties_to_pdata()
485 err = device_property_read_u32(dev, "address-width", &val); in at24_properties_to_pdata()
489 if (chip->flags & AT24_FLAG_ADDR16) in at24_properties_to_pdata()
491 chip->flags &= ~AT24_FLAG_ADDR16; in at24_properties_to_pdata()
494 chip->flags |= AT24_FLAG_ADDR16; in at24_properties_to_pdata()
497 dev_warn(dev, "Bad \"address-width\" property: %u\n", in at24_properties_to_pdata()
504 chip->byte_len = val; in at24_properties_to_pdata()
508 chip->page_size = val; in at24_properties_to_pdata()
512 * play safe. Specifying custom eeprom-types via platform_data in at24_properties_to_pdata()
515 chip->page_size = 1; in at24_properties_to_pdata()
521 struct device_node *of_node = dev->of_node; in at24_get_pdata()
542 cdata = (void *)id->driver_data; in at24_get_pdata()
547 return -ENODEV; in at24_get_pdata()
549 pdata->byte_len = cdata->byte_len; in at24_get_pdata()
550 pdata->flags = cdata->flags; in at24_get_pdata()
560 for (i = 1; i < at24->num_addresses; i++) in at24_remove_dummy_clients()
561 i2c_unregister_device(at24->client[i].client); in at24_remove_dummy_clients()
572 base_client = at24->client[0].client; in at24_make_dummy_client()
573 dev = &base_client->dev; in at24_make_dummy_client()
574 addr = base_client->addr + index; in at24_make_dummy_client()
576 dummy_client = i2c_new_dummy(base_client->adapter, in at24_make_dummy_client()
577 base_client->addr + index); in at24_make_dummy_client()
580 return -EADDRINUSE; in at24_make_dummy_client()
589 at24->client[index].client = dummy_client; in at24_make_dummy_client()
590 at24->client[index].regmap = regmap; in at24_make_dummy_client()
598 /* EUI-48 starts from 0x9a, EUI-64 from 0x98 */ in at24_get_offset_adj()
599 return 0xa0 - byte_len; in at24_get_offset_adj()
623 struct device *dev = &client->dev; in at24_probe()
633 i2c_fn_i2c = i2c_check_functionality(client->adapter, I2C_FUNC_I2C); in at24_probe()
634 i2c_fn_block = i2c_check_functionality(client->adapter, in at24_probe()
646 return -EINVAL; in at24_probe()
650 dev_warn(dev, "page_size looks suspicious (no power of 2)!\n"); in at24_probe()
660 "invalid device data - cannot have both AT24_FLAG_SERIAL & AT24_FLAG_MAC."); in at24_probe()
661 return -EINVAL; in at24_probe()
675 return -ENOMEM; in at24_probe()
677 mutex_init(&at24->lock); in at24_probe()
678 at24->byte_len = pdata.byte_len; in at24_probe()
679 at24->page_size = pdata.page_size; in at24_probe()
680 at24->flags = pdata.flags; in at24_probe()
681 at24->num_addresses = num_addresses; in at24_probe()
682 at24->offset_adj = at24_get_offset_adj(pdata.flags, pdata.byte_len); in at24_probe()
683 at24->client[0].client = client; in at24_probe()
684 at24->client[0].regmap = regmap; in at24_probe()
686 at24->wp_gpio = devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_HIGH); in at24_probe()
687 if (IS_ERR(at24->wp_gpio)) in at24_probe()
688 return PTR_ERR(at24->wp_gpio); in at24_probe()
692 at24->write_max = min_t(unsigned int, in at24_probe()
694 if (!i2c_fn_i2c && at24->write_max > I2C_SMBUS_BLOCK_MAX) in at24_probe()
695 at24->write_max = I2C_SMBUS_BLOCK_MAX; in at24_probe()
698 /* use dummy devices for multiple-address chips */ in at24_probe()
714 * Perform a one-byte test read to verify that the in at24_probe()
720 err = -ENODEV; in at24_probe()
738 at24->nvmem = devm_nvmem_register(dev, &nvmem_config); in at24_probe()
739 if (IS_ERR(at24->nvmem)) { in at24_probe()
740 err = PTR_ERR(at24->nvmem); in at24_probe()
745 pdata.byte_len, client->name, in at24_probe()
746 writable ? "writable" : "read-only", at24->write_max); in at24_probe()
750 pdata.setup(at24->nvmem, pdata.context); in at24_probe()
768 pm_runtime_disable(&client->dev); in at24_remove()
769 pm_runtime_set_suspended(&client->dev); in at24_remove()
789 return -EINVAL; in at24_init()