diff options
Diffstat (limited to 'drivers/misc/eeprom')
-rw-r--r-- | drivers/misc/eeprom/at24.c | 82 | ||||
-rw-r--r-- | drivers/misc/eeprom/at25.c | 15 | ||||
-rw-r--r-- | drivers/misc/eeprom/ee1004.c | 13 | ||||
-rw-r--r-- | drivers/misc/eeprom/eeprom.c | 2 | ||||
-rw-r--r-- | drivers/misc/eeprom/eeprom_93xx46.c | 1 |
5 files changed, 82 insertions, 31 deletions
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index 2591c21b2b5d..1c0a41803bb6 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -8,6 +8,7 @@ #include <linux/acpi.h> #include <linux/bitops.h> +#include <linux/capability.h> #include <linux/delay.h> #include <linux/i2c.h> #include <linux/init.h> @@ -89,6 +90,7 @@ struct at24_data { struct nvmem_device *nvmem; struct regulator *vcc_reg; + void (*read_post)(unsigned int off, char *buf, size_t count); /* * Some chips tie up multiple I2C addresses; dummy devices reserve @@ -121,6 +123,7 @@ MODULE_PARM_DESC(at24_write_timeout, "Time (in ms) to try writes (default 25)"); struct at24_chip_data { u32 byte_len; u8 flags; + void (*read_post)(unsigned int off, char *buf, size_t count); }; #define AT24_CHIP_DATA(_name, _len, _flags) \ @@ -128,6 +131,32 @@ struct at24_chip_data { .byte_len = _len, .flags = _flags, \ } +#define AT24_CHIP_DATA_CB(_name, _len, _flags, _read_post) \ + static const struct at24_chip_data _name = { \ + .byte_len = _len, .flags = _flags, \ + .read_post = _read_post, \ + } + +static void at24_read_post_vaio(unsigned int off, char *buf, size_t count) +{ + int i; + + if (capable(CAP_SYS_ADMIN)) + return; + + /* + * Hide VAIO private settings to regular users: + * - BIOS passwords: bytes 0x00 to 0x0f + * - UUID: bytes 0x10 to 0x1f + * - Serial number: 0xc0 to 0xdf + */ + for (i = 0; i < count; i++) { + if ((off + i <= 0x1f) || + (off + i >= 0xc0 && off + i <= 0xdf)) + buf[i] = 0; + } +} + /* needs 8 addresses as A0-A2 are ignored */ AT24_CHIP_DATA(at24_data_24c00, 128 / 8, AT24_FLAG_TAKE8ADDR); /* old variants can't be handled with this generic entry! */ @@ -144,6 +173,10 @@ AT24_CHIP_DATA(at24_data_24mac602, 64 / 8, /* spd is a 24c02 in memory DIMMs */ AT24_CHIP_DATA(at24_data_spd, 2048 / 8, AT24_FLAG_READONLY | AT24_FLAG_IRUGO); +/* 24c02_vaio is a 24c02 on some Sony laptops */ +AT24_CHIP_DATA_CB(at24_data_24c02_vaio, 2048 / 8, + AT24_FLAG_READONLY | AT24_FLAG_IRUGO, + at24_read_post_vaio); AT24_CHIP_DATA(at24_data_24c04, 4096 / 8, 0); AT24_CHIP_DATA(at24_data_24cs04, 16, AT24_FLAG_SERIAL | AT24_FLAG_READONLY); @@ -177,6 +210,7 @@ static const struct i2c_device_id at24_ids[] = { { "24mac402", (kernel_ulong_t)&at24_data_24mac402 }, { "24mac602", (kernel_ulong_t)&at24_data_24mac602 }, { "spd", (kernel_ulong_t)&at24_data_spd }, + { "24c02-vaio", (kernel_ulong_t)&at24_data_24c02_vaio }, { "24c04", (kernel_ulong_t)&at24_data_24c04 }, { "24cs04", (kernel_ulong_t)&at24_data_24cs04 }, { "24c08", (kernel_ulong_t)&at24_data_24c08 }, @@ -388,7 +422,7 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count) struct at24_data *at24; struct device *dev; char *buf = val; - int ret; + int i, ret; at24 = priv; dev = at24_base_client_dev(at24); @@ -411,22 +445,22 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count) */ mutex_lock(&at24->lock); - while (count) { - ret = at24_regmap_read(at24, buf, off, count); + for (i = 0; count; i += ret, count -= ret) { + ret = at24_regmap_read(at24, buf + i, off + i, count); if (ret < 0) { mutex_unlock(&at24->lock); pm_runtime_put(dev); return ret; } - buf += ret; - off += ret; - count -= ret; } mutex_unlock(&at24->lock); pm_runtime_put(dev); + if (unlikely(at24->read_post)) + at24->read_post(off, buf, i); + return 0; } @@ -654,6 +688,7 @@ static int at24_probe(struct i2c_client *client) at24->byte_len = byte_len; at24->page_size = page_size; at24->flags = flags; + at24->read_post = cdata->read_post; at24->num_addresses = num_addresses; at24->offset_adj = at24_get_offset_adj(flags, byte_len); at24->client[0].client = client; @@ -678,8 +713,30 @@ static int at24_probe(struct i2c_client *client) return err; } - nvmem_config.name = dev_name(dev); + /* + * If the 'label' property is not present for the AT24 EEPROM, + * then nvmem_config.id is initialised to NVMEM_DEVID_AUTO, + * and this will append the 'devid' to the name of the NVMEM + * device. This is purely legacy and the AT24 driver has always + * defaulted to this. However, if the 'label' property is + * present then this means that the name is specified by the + * firmware and this name should be used verbatim and so it is + * not necessary to append the 'devid'. + */ + if (device_property_present(dev, "label")) { + nvmem_config.id = NVMEM_DEVID_NONE; + err = device_property_read_string(dev, "label", + &nvmem_config.name); + if (err) + return err; + } else { + nvmem_config.id = NVMEM_DEVID_AUTO; + nvmem_config.name = dev_name(dev); + } + + nvmem_config.type = NVMEM_TYPE_EEPROM; nvmem_config.dev = dev; + nvmem_config.id = NVMEM_DEVID_AUTO; nvmem_config.read_only = !writable; nvmem_config.root_only = !(flags & AT24_FLAG_IRUGO); nvmem_config.owner = THIS_MODULE; @@ -692,10 +749,6 @@ static int at24_probe(struct i2c_client *client) nvmem_config.word_size = 1; nvmem_config.size = byte_len; - at24->nvmem = devm_nvmem_register(dev, &nvmem_config); - if (IS_ERR(at24->nvmem)) - return PTR_ERR(at24->nvmem); - i2c_set_clientdata(client, at24); err = regulator_enable(at24->vcc_reg); @@ -708,6 +761,13 @@ static int at24_probe(struct i2c_client *client) pm_runtime_set_active(dev); pm_runtime_enable(dev); + at24->nvmem = devm_nvmem_register(dev, &nvmem_config); + if (IS_ERR(at24->nvmem)) { + pm_runtime_disable(dev); + regulator_disable(at24->vcc_reg); + return PTR_ERR(at24->nvmem); + } + /* * Perform a one-byte test read to verify that the * chip is functional. diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c index cde9a2fc1325..3b7d8b7584f4 100644 --- a/drivers/misc/eeprom/at25.c +++ b/drivers/misc/eeprom/at25.c @@ -90,10 +90,10 @@ static int at25_ee_read(void *priv, unsigned int offset, switch (at25->addrlen) { default: /* case 3 */ *cp++ = offset >> 16; - /* fall through */ + fallthrough; case 2: *cp++ = offset >> 8; - /* fall through */ + fallthrough; case 1: case 0: /* can't happen: for better codegen */ *cp++ = offset >> 0; @@ -178,10 +178,10 @@ static int at25_ee_write(void *priv, unsigned int off, void *val, size_t count) switch (at25->addrlen) { default: /* case 3 */ *cp++ = offset >> 16; - /* fall through */ + fallthrough; case 2: *cp++ = offset >> 8; - /* fall through */ + fallthrough; case 1: case 0: /* can't happen: for better codegen */ *cp++ = offset >> 0; @@ -261,7 +261,7 @@ static int at25_fw_to_chip(struct device *dev, struct spi_eeprom *chip) if (device_property_read_u32(dev, "pagesize", &val) == 0 || device_property_read_u32(dev, "at25,page-size", &val) == 0) { - chip->page_size = (u16)val; + chip->page_size = val; } else { dev_err(dev, "Error: missing \"pagesize\" property\n"); return -ENODEV; @@ -278,7 +278,7 @@ static int at25_fw_to_chip(struct device *dev, struct spi_eeprom *chip) switch (val) { case 9: chip->flags |= EE_INSTR_BIT3_IS_ADDR; - /* fall through */ + fallthrough; case 8: chip->flags |= EE_ADDR1; break; @@ -348,6 +348,7 @@ static int at25_probe(struct spi_device *spi) spi_set_drvdata(spi, at25); at25->addrlen = addrlen; + at25->nvmem_config.type = NVMEM_TYPE_EEPROM; at25->nvmem_config.name = dev_name(&spi->dev); at25->nvmem_config.dev = &spi->dev; at25->nvmem_config.read_only = chip.flags & EE_READONLY; @@ -358,7 +359,7 @@ static int at25_probe(struct spi_device *spi) at25->nvmem_config.reg_read = at25_ee_read; at25->nvmem_config.reg_write = at25_ee_write; at25->nvmem_config.priv = at25; - at25->nvmem_config.stride = 4; + at25->nvmem_config.stride = 1; at25->nvmem_config.word_size = 1; at25->nvmem_config.size = chip.byte_len; diff --git a/drivers/misc/eeprom/ee1004.c b/drivers/misc/eeprom/ee1004.c index b081c67416d7..252e15ba65e1 100644 --- a/drivers/misc/eeprom/ee1004.c +++ b/drivers/misc/eeprom/ee1004.c @@ -280,18 +280,7 @@ static struct i2c_driver ee1004_driver = { .remove = ee1004_remove, .id_table = ee1004_ids, }; - -static int __init ee1004_init(void) -{ - return i2c_add_driver(&ee1004_driver); -} -module_init(ee1004_init); - -static void __exit ee1004_exit(void) -{ - i2c_del_driver(&ee1004_driver); -} -module_exit(ee1004_exit); +module_i2c_driver(ee1004_driver); MODULE_DESCRIPTION("Driver for EE1004-compliant DDR4 SPD EEPROMs"); MODULE_AUTHOR("Jean Delvare"); diff --git a/drivers/misc/eeprom/eeprom.c b/drivers/misc/eeprom/eeprom.c index 226b5efa6a77..34fa385dfd4b 100644 --- a/drivers/misc/eeprom/eeprom.c +++ b/drivers/misc/eeprom/eeprom.c @@ -76,7 +76,7 @@ static ssize_t eeprom_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct i2c_client *client = to_i2c_client(kobj_to_dev(kobj)); + struct i2c_client *client = kobj_to_i2c_client(kobj); struct eeprom_data *data = i2c_get_clientdata(client); u8 slice; diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c index 94cfb675fe4e..7c45f82b4302 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -455,6 +455,7 @@ static int eeprom_93xx46_probe(struct spi_device *spi) edev->pdata = pd; edev->size = 128; + edev->nvmem_config.type = NVMEM_TYPE_EEPROM; edev->nvmem_config.name = dev_name(&spi->dev); edev->nvmem_config.dev = &spi->dev; edev->nvmem_config.read_only = pd->flags & EE_READONLY; |