diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-06-13 23:12:38 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-06-13 23:12:38 +0300 |
commit | 91fa58840ae22cbf6d7c505ce6564c4c48f29af3 (patch) | |
tree | 02aa51d6ffac7e4b0871f0e67895a143b3a8447a /drivers/i2c/i2c-slave-eeprom.c | |
parent | ac911b316336ad3d22b09e82698f0463347a5507 (diff) | |
parent | d790eeb3db6aefac39ffa06e598eb31b7352ca4f (diff) | |
download | linux-91fa58840ae22cbf6d7c505ce6564c4c48f29af3.tar.xz |
Merge branch 'i2c/for-5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang:
"I2C has quite some patches for you this time. I hope it is the move to
per-driver-maintainers which is now showing results. We will see.
The big news is two new drivers (Nuvoton NPCM and Qualcomm CCI),
larger refactoring of the Designware, Tegra, and PXA drivers, the
Cadence driver supports being a slave now, and there is support to
instanciate SPD eeproms for well-known cases (which will be
user-visible because the i801 driver supports it), and some
devm_platform_ioremap_resource() conversions which blow up the
diffstat.
Note that I applied the Nuvoton driver quite late, so some minor fixup
patches arrived during the merge window. I chose to apply them right
away because they were trivial"
* 'i2c/for-5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (109 commits)
i2c: Drop stray comma in MODULE_AUTHOR statements
i2c: npcm7xx: npcm_i2caddr[] can be static
MAINTAINERS: npcm7xx: Add maintainer for Nuvoton NPCM BMC
i2c: npcm7xx: Fix a couple of error codes in probe
i2c: icy: Fix build with CONFIG_AMIGA_PCMCIA=n
i2c: npcm7xx: Remove unnecessary parentheses
i2c: npcm7xx: Add support for slave mode for Nuvoton
i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver
dt-bindings: i2c: npcm7xx: add NPCM I2C controller
i2c: pxa: don't error out if there's no pinctrl
i2c: add 'single-master' property to generic bindings
i2c: designware: Add Baikal-T1 System I2C support
i2c: designware: Move reg-space remapping into a dedicated function
i2c: designware: Retrieve quirk flags as early as possible
i2c: designware: Convert driver to using regmap API
i2c: designware: Discard Cherry Trail model flag
i2c: designware: Add Baytrail sem config DW I2C platform dependency
i2c: designware: slave: Set DW I2C core module dependency
i2c: designware: Use `-y` to build multi-object modules
dt-bindings: i2c: dw: Add Baikal-T1 SoC I2C controller
...
Diffstat (limited to 'drivers/i2c/i2c-slave-eeprom.c')
-rw-r--r-- | drivers/i2c/i2c-slave-eeprom.c | 39 |
1 files changed, 32 insertions, 7 deletions
diff --git a/drivers/i2c/i2c-slave-eeprom.c b/drivers/i2c/i2c-slave-eeprom.c index cb415b10642f..593f2fd39d17 100644 --- a/drivers/i2c/i2c-slave-eeprom.c +++ b/drivers/i2c/i2c-slave-eeprom.c @@ -5,10 +5,9 @@ * Copyright (C) 2014 by Wolfram Sang, Sang Engineering <wsa@sang-engineering.com> * Copyright (C) 2014 by Renesas Electronics Corporation * - * Because most IP blocks can only detect one I2C slave address anyhow, this - * driver does not support simulating EEPROM types which take more than one - * address. It is prepared to simulate bigger EEPROMs with an internal 16 bit - * pointer, yet implementation is deferred until the need actually arises. + * Because most slave IP cores can only detect one I2C slave address anyhow, + * this driver does not support simulating EEPROM types which take more than + * one address. */ /* @@ -18,6 +17,7 @@ */ #include <linux/bitfield.h> +#include <linux/firmware.h> #include <linux/i2c.h> #include <linux/init.h> #include <linux/module.h> @@ -40,7 +40,7 @@ struct eeprom_data { #define I2C_SLAVE_BYTELEN GENMASK(15, 0) #define I2C_SLAVE_FLAG_ADDR16 BIT(16) #define I2C_SLAVE_FLAG_RO BIT(17) -#define I2C_SLAVE_DEVICE_MAGIC(_len, _flags) ((_flags) | (_len)) +#define I2C_SLAVE_DEVICE_MAGIC(_len, _flags) ((_flags) | ((_len) - 1)) static int i2c_slave_eeprom_slave_cb(struct i2c_client *client, enum i2c_slave_event event, u8 *val) @@ -120,24 +120,47 @@ static ssize_t i2c_slave_eeprom_bin_write(struct file *filp, struct kobject *kob return count; } +static int i2c_slave_init_eeprom_data(struct eeprom_data *eeprom, struct i2c_client *client, + unsigned int size) +{ + const struct firmware *fw; + const char *eeprom_data; + int ret = device_property_read_string(&client->dev, "firmware-name", &eeprom_data); + + if (!ret) { + ret = request_firmware_into_buf(&fw, eeprom_data, &client->dev, + eeprom->buffer, size); + if (ret) + return ret; + release_firmware(fw); + } else { + /* An empty eeprom typically has all bits set to 1 */ + memset(eeprom->buffer, 0xff, size); + } + return 0; +} + static int i2c_slave_eeprom_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct eeprom_data *eeprom; int ret; - unsigned int size = FIELD_GET(I2C_SLAVE_BYTELEN, id->driver_data); + unsigned int size = FIELD_GET(I2C_SLAVE_BYTELEN, id->driver_data) + 1; unsigned int flag_addr16 = FIELD_GET(I2C_SLAVE_FLAG_ADDR16, id->driver_data); eeprom = devm_kzalloc(&client->dev, sizeof(struct eeprom_data) + size, GFP_KERNEL); if (!eeprom) return -ENOMEM; - eeprom->idx_write_cnt = 0; eeprom->num_address_bytes = flag_addr16 ? 2 : 1; eeprom->address_mask = size - 1; eeprom->read_only = FIELD_GET(I2C_SLAVE_FLAG_RO, id->driver_data); spin_lock_init(&eeprom->buffer_lock); i2c_set_clientdata(client, eeprom); + ret = i2c_slave_init_eeprom_data(eeprom, client, size); + if (ret) + return ret; + sysfs_bin_attr_init(&eeprom->bin); eeprom->bin.attr.name = "slave-eeprom"; eeprom->bin.attr.mode = S_IRUSR | S_IWUSR; @@ -175,6 +198,8 @@ static const struct i2c_device_id i2c_slave_eeprom_id[] = { { "slave-24c32ro", I2C_SLAVE_DEVICE_MAGIC(32768 / 8, I2C_SLAVE_FLAG_ADDR16 | I2C_SLAVE_FLAG_RO) }, { "slave-24c64", I2C_SLAVE_DEVICE_MAGIC(65536 / 8, I2C_SLAVE_FLAG_ADDR16) }, { "slave-24c64ro", I2C_SLAVE_DEVICE_MAGIC(65536 / 8, I2C_SLAVE_FLAG_ADDR16 | I2C_SLAVE_FLAG_RO) }, + { "slave-24c512", I2C_SLAVE_DEVICE_MAGIC(524288 / 8, I2C_SLAVE_FLAG_ADDR16) }, + { "slave-24c512ro", I2C_SLAVE_DEVICE_MAGIC(524288 / 8, I2C_SLAVE_FLAG_ADDR16 | I2C_SLAVE_FLAG_RO) }, { } }; MODULE_DEVICE_TABLE(i2c, i2c_slave_eeprom_id); |