Lines Matching +full:tie +full:- +full:off
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * at24.c - handle most I2C EEPROMs
5 * Copyright (C) 2005-2007 David Brownell
20 #include <linux/nvmem-provider.h>
31 /* sysfs-entry will be read-only. */
33 /* sysfs-entry will be world-readable. */
37 /* Factory-programmed serial number. */
39 /* Factory-programmed mac address. */
41 /* Does not auto-rollover reads to the next slave address. */
51 * However, misconfiguration can lose data. "Set 16-bit memory address"
52 * to a part with 8-bit addressing will overwrite data. Writing with too
57 * Accordingly, explicit board-specific configuration data should be used
62 * told what devices exist. That may be in arch/X/mach-Y/board-Z.c or
63 * similar kernel-resident tables; or, configuration data coming from
68 * It also handles larger devices (32 kbit and up) with two-byte addresses,
89 void (*read_post)(unsigned int off, char *buf, size_t count);
92 * Some chips tie up multiple I2C addresses; dummy devices reserve
124 void (*read_post)(unsigned int off, char *buf, size_t count);
144 static void at24_read_post_vaio(unsigned int off, char *buf, size_t count) in at24_read_post_vaio() argument
153 * - BIOS passwords: bytes 0x00 to 0x0f in at24_read_post_vaio()
154 * - UUID: bytes 0x10 to 0x1f in at24_read_post_vaio()
155 * - Serial number: 0xc0 to 0xdf in at24_read_post_vaio()
158 if ((off + i <= 0x1f) || in at24_read_post_vaio()
159 (off + i >= 0xc0 && off + i <= 0xdf)) in at24_read_post_vaio()
164 /* needs 8 addresses as A0-A2 are ignored */
191 /* 24rf08 quirk is handled at i2c-core */
199 /* M24C32-D Additional Write lockable page (M24C32-D order codes) */
204 /* M24C64-D Additional Write lockable page (M24C64-D order codes) */
228 { "24c02-vaio", (kernel_ulong_t)&at24_data_24c02_vaio },
236 { "24c32d-wl", (kernel_ulong_t)&at24_data_24c32d_wlp },
239 { "24c64-wl", (kernel_ulong_t)&at24_data_24c64d_wlp },
268 { .compatible = "atmel,24c32d-wl", .data = &at24_data_24c32d_wlp },
271 { .compatible = "atmel,24c64d-wl", .data = &at24_data_24c64d_wlp },
295 * Assumes that sanity checks for offset happened at sysfs-layer.
298 * set the byte address; on a multi-master board, another master
306 if (at24->flags & AT24_FLAG_ADDR16) { in at24_translate_offset()
314 return at24->client_regmaps[i]; in at24_translate_offset()
319 return regmap_get_device(at24->client_regmaps[0]); in at24_base_client_dev()
329 * In case of multi-address chips that don't rollover reads to in at24_adjust_read_count()
333 if (at24->flags & AT24_FLAG_NO_RDROL) { in at24_adjust_read_count()
334 bits = (at24->flags & AT24_FLAG_ADDR16) ? 16 : 8; in at24_adjust_read_count()
335 remainder = BIT(bits) - offset; in at24_adjust_read_count()
357 offset += at24->offset_adj; in at24_regmap_read()
368 dev_dbg(regmap_get_device(regmap), "read %zu@%d --> %d (%ld)\n", in at24_regmap_read()
376 return -ETIMEDOUT; in at24_regmap_read()
380 * Note that if the hardware write-protect pin is pulled high, the whole
394 if (count > at24->write_max) in at24_adjust_write_count()
395 count = at24->write_max; in at24_adjust_write_count()
398 next_page = roundup(offset + 1, at24->page_size); in at24_adjust_write_count()
400 count = next_page - offset; in at24_adjust_write_count()
424 dev_dbg(regmap_get_device(regmap), "write %zu@%d --> %d (%ld)\n", in at24_regmap_write()
432 return -ETIMEDOUT; in at24_regmap_write()
435 static int at24_read(void *priv, unsigned int off, void *val, size_t count) in at24_read() argument
448 if (off + count > at24->byte_len) in at24_read()
449 return -EINVAL; in at24_read()
458 mutex_lock(&at24->lock); in at24_read()
460 for (i = 0; count; i += ret, count -= ret) { in at24_read()
461 ret = at24_regmap_read(at24, buf + i, off + i, count); in at24_read()
463 mutex_unlock(&at24->lock); in at24_read()
469 mutex_unlock(&at24->lock); in at24_read()
473 if (unlikely(at24->read_post)) in at24_read()
474 at24->read_post(off, buf, i); in at24_read()
479 static int at24_write(void *priv, unsigned int off, void *val, size_t count) in at24_write() argument
490 return -EINVAL; in at24_write()
492 if (off + count > at24->byte_len) in at24_write()
493 return -EINVAL; in at24_write()
502 mutex_lock(&at24->lock); in at24_write()
505 ret = at24_regmap_write(at24, buf, off, count); in at24_write()
507 mutex_unlock(&at24->lock); in at24_write()
512 off += ret; in at24_write()
513 count -= ret; in at24_write()
516 mutex_unlock(&at24->lock); in at24_write()
530 dummy_client = devm_i2c_new_dummy_device(&base_client->dev, in at24_make_dummy_client()
531 base_client->adapter, in at24_make_dummy_client()
532 base_client->addr + in at24_make_dummy_client()
533 (index << at24->bank_addr_shift)); in at24_make_dummy_client()
541 at24->client_regmaps[index] = regmap; in at24_make_dummy_client()
549 /* EUI-48 starts from 0x9a, EUI-64 from 0x98 */ in at24_get_offset_adj()
550 return 0xa0 - byte_len; in at24_get_offset_adj()
589 info.addr = 0x18 | (client->addr & 7); in at24_probe_temp_sensor()
591 i2c_new_client_device(client->adapter, &info); in at24_probe_temp_sensor()
600 struct device *dev = &client->dev; in at24_probe()
610 i2c_fn_i2c = i2c_check_functionality(client->adapter, I2C_FUNC_I2C); in at24_probe()
611 i2c_fn_block = i2c_check_functionality(client->adapter, in at24_probe()
616 return -ENODEV; in at24_probe()
622 * play safe. Specifying custom eeprom-types via device tree in at24_probe()
627 flags = cdata->flags; in at24_probe()
628 if (device_property_present(dev, "read-only")) in at24_probe()
630 if (device_property_present(dev, "no-read-rollover")) in at24_probe()
633 err = device_property_read_u32(dev, "address-width", &addrw); in at24_probe()
646 dev_warn(dev, "Bad \"address-width\" property: %u\n", in at24_probe()
653 byte_len = cdata->byte_len; in at24_probe()
660 return -EINVAL; in at24_probe()
666 err = device_property_read_u32(dev, "num-addresses", &num_addresses); in at24_probe()
677 "invalid device data - cannot have both AT24_FLAG_SERIAL & AT24_FLAG_MAC."); in at24_probe()
678 return -EINVAL; in at24_probe()
692 return -ENOMEM; in at24_probe()
694 mutex_init(&at24->lock); in at24_probe()
695 at24->byte_len = byte_len; in at24_probe()
696 at24->page_size = page_size; in at24_probe()
697 at24->flags = flags; in at24_probe()
698 at24->read_post = cdata->read_post; in at24_probe()
699 at24->bank_addr_shift = cdata->bank_addr_shift; in at24_probe()
700 at24->num_addresses = num_addresses; in at24_probe()
701 at24->offset_adj = at24_get_offset_adj(flags, byte_len); in at24_probe()
702 at24->client_regmaps[0] = regmap; in at24_probe()
704 at24->vcc_reg = devm_regulator_get(dev, "vcc"); in at24_probe()
705 if (IS_ERR(at24->vcc_reg)) in at24_probe()
706 return PTR_ERR(at24->vcc_reg); in at24_probe()
710 at24->write_max = min_t(unsigned int, in at24_probe()
712 if (!i2c_fn_i2c && at24->write_max > I2C_SMBUS_BLOCK_MAX) in at24_probe()
713 at24->write_max = I2C_SMBUS_BLOCK_MAX; in at24_probe()
716 /* use dummy devices for multiple-address chips */ in at24_probe()
757 full_power = acpi_dev_state_d0(&client->dev); in at24_probe()
759 err = regulator_enable(at24->vcc_reg); in at24_probe()
770 * Perform a one-byte test read to verify that the chip is functional, in at24_probe()
772 * it's powered off right now). in at24_probe()
779 regulator_disable(at24->vcc_reg); in at24_probe()
780 return -ENODEV; in at24_probe()
784 at24->nvmem = devm_nvmem_register(dev, &nvmem_config); in at24_probe()
785 if (IS_ERR(at24->nvmem)) { in at24_probe()
788 regulator_disable(at24->vcc_reg); in at24_probe()
789 return dev_err_probe(dev, PTR_ERR(at24->nvmem), in at24_probe()
801 byte_len, client->name, at24->write_max); in at24_probe()
803 dev_info(dev, "%u byte %s EEPROM, read-only\n", in at24_probe()
804 byte_len, client->name); in at24_probe()
813 pm_runtime_disable(&client->dev); in at24_remove()
814 if (acpi_dev_state_d0(&client->dev)) { in at24_remove()
815 if (!pm_runtime_status_suspended(&client->dev)) in at24_remove()
816 regulator_disable(at24->vcc_reg); in at24_remove()
817 pm_runtime_set_suspended(&client->dev); in at24_remove()
826 return regulator_disable(at24->vcc_reg); in at24_suspend()
834 return regulator_enable(at24->vcc_reg); in at24_resume()
860 return -EINVAL; in at24_init()