Commit 668ba5e6 authored by Wolfram Sang's avatar Wolfram Sang

Merge tag 'at24-updates-for-v5.10' of...

Merge tag 'at24-updates-for-v5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux into i2c/for-5.10

at24 updates for v5.10

- add support for masking sensitive data in VAIO EEPROMs
- set the nvmem TYPE to NVMEM_TYPE_EEPROM
- add support for the new 'label' property
- set the nvmem ID to NVMEM_DEVID_AUTO by default (for backward
  compatibility) or to NVMEM_DEVID_NONE if label is defined
parents 9b65b020 61f764c3
...@@ -114,6 +114,9 @@ properties: ...@@ -114,6 +114,9 @@ properties:
- const: renesas,r1ex24128 - const: renesas,r1ex24128
- const: atmel,24c128 - const: atmel,24c128
label:
description: Descriptive name of the EEPROM.
reg: reg:
maxItems: 1 maxItems: 1
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/capability.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -89,6 +90,7 @@ struct at24_data { ...@@ -89,6 +90,7 @@ struct at24_data {
struct nvmem_device *nvmem; struct nvmem_device *nvmem;
struct regulator *vcc_reg; 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 * 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)"); ...@@ -121,6 +123,7 @@ MODULE_PARM_DESC(at24_write_timeout, "Time (in ms) to try writes (default 25)");
struct at24_chip_data { struct at24_chip_data {
u32 byte_len; u32 byte_len;
u8 flags; u8 flags;
void (*read_post)(unsigned int off, char *buf, size_t count);
}; };
#define AT24_CHIP_DATA(_name, _len, _flags) \ #define AT24_CHIP_DATA(_name, _len, _flags) \
...@@ -128,6 +131,32 @@ struct at24_chip_data { ...@@ -128,6 +131,32 @@ struct at24_chip_data {
.byte_len = _len, .flags = _flags, \ .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 */ /* needs 8 addresses as A0-A2 are ignored */
AT24_CHIP_DATA(at24_data_24c00, 128 / 8, AT24_FLAG_TAKE8ADDR); AT24_CHIP_DATA(at24_data_24c00, 128 / 8, AT24_FLAG_TAKE8ADDR);
/* old variants can't be handled with this generic entry! */ /* old variants can't be handled with this generic entry! */
...@@ -144,6 +173,10 @@ AT24_CHIP_DATA(at24_data_24mac602, 64 / 8, ...@@ -144,6 +173,10 @@ AT24_CHIP_DATA(at24_data_24mac602, 64 / 8,
/* spd is a 24c02 in memory DIMMs */ /* spd is a 24c02 in memory DIMMs */
AT24_CHIP_DATA(at24_data_spd, 2048 / 8, AT24_CHIP_DATA(at24_data_spd, 2048 / 8,
AT24_FLAG_READONLY | AT24_FLAG_IRUGO); 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_24c04, 4096 / 8, 0);
AT24_CHIP_DATA(at24_data_24cs04, 16, AT24_CHIP_DATA(at24_data_24cs04, 16,
AT24_FLAG_SERIAL | AT24_FLAG_READONLY); AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
...@@ -177,6 +210,7 @@ static const struct i2c_device_id at24_ids[] = { ...@@ -177,6 +210,7 @@ static const struct i2c_device_id at24_ids[] = {
{ "24mac402", (kernel_ulong_t)&at24_data_24mac402 }, { "24mac402", (kernel_ulong_t)&at24_data_24mac402 },
{ "24mac602", (kernel_ulong_t)&at24_data_24mac602 }, { "24mac602", (kernel_ulong_t)&at24_data_24mac602 },
{ "spd", (kernel_ulong_t)&at24_data_spd }, { "spd", (kernel_ulong_t)&at24_data_spd },
{ "24c02-vaio", (kernel_ulong_t)&at24_data_24c02_vaio },
{ "24c04", (kernel_ulong_t)&at24_data_24c04 }, { "24c04", (kernel_ulong_t)&at24_data_24c04 },
{ "24cs04", (kernel_ulong_t)&at24_data_24cs04 }, { "24cs04", (kernel_ulong_t)&at24_data_24cs04 },
{ "24c08", (kernel_ulong_t)&at24_data_24c08 }, { "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) ...@@ -388,7 +422,7 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count)
struct at24_data *at24; struct at24_data *at24;
struct device *dev; struct device *dev;
char *buf = val; char *buf = val;
int ret; int i, ret;
at24 = priv; at24 = priv;
dev = at24_base_client_dev(at24); dev = at24_base_client_dev(at24);
...@@ -411,22 +445,22 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count) ...@@ -411,22 +445,22 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count)
*/ */
mutex_lock(&at24->lock); mutex_lock(&at24->lock);
while (count) { for (i = 0; count; i += ret, count -= ret) {
ret = at24_regmap_read(at24, buf, off, count); ret = at24_regmap_read(at24, buf + i, off + i, count);
if (ret < 0) { if (ret < 0) {
mutex_unlock(&at24->lock); mutex_unlock(&at24->lock);
pm_runtime_put(dev); pm_runtime_put(dev);
return ret; return ret;
} }
buf += ret;
off += ret;
count -= ret;
} }
mutex_unlock(&at24->lock); mutex_unlock(&at24->lock);
pm_runtime_put(dev); pm_runtime_put(dev);
if (unlikely(at24->read_post))
at24->read_post(off, buf, i);
return 0; return 0;
} }
...@@ -654,6 +688,7 @@ static int at24_probe(struct i2c_client *client) ...@@ -654,6 +688,7 @@ static int at24_probe(struct i2c_client *client)
at24->byte_len = byte_len; at24->byte_len = byte_len;
at24->page_size = page_size; at24->page_size = page_size;
at24->flags = flags; at24->flags = flags;
at24->read_post = cdata->read_post;
at24->num_addresses = num_addresses; at24->num_addresses = num_addresses;
at24->offset_adj = at24_get_offset_adj(flags, byte_len); at24->offset_adj = at24_get_offset_adj(flags, byte_len);
at24->client[0].client = client; at24->client[0].client = client;
...@@ -678,8 +713,30 @@ static int at24_probe(struct i2c_client *client) ...@@ -678,8 +713,30 @@ static int at24_probe(struct i2c_client *client)
return err; 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.dev = dev;
nvmem_config.id = NVMEM_DEVID_AUTO;
nvmem_config.read_only = !writable; nvmem_config.read_only = !writable;
nvmem_config.root_only = !(flags & AT24_FLAG_IRUGO); nvmem_config.root_only = !(flags & AT24_FLAG_IRUGO);
nvmem_config.owner = THIS_MODULE; nvmem_config.owner = THIS_MODULE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment