diff options
author | Heiner Kallweit <hkallweit1@gmail.com> | 2017-11-28 21:51:40 +0100 |
---|---|---|
committer | Bartosz Golaszewski <brgl@bgdev.pl> | 2018-01-01 19:40:46 +0100 |
commit | 5c015258478eaac484c2fc91bd1d06babacb1ec4 (patch) | |
tree | 8812b0d93a6f153b178f593c6eb1eb3d1e372c02 | |
parent | 30a7acd573899fd8b8ac39236eff6468b195ac7d (diff) | |
download | linux-stable-5c015258478eaac484c2fc91bd1d06babacb1ec4.tar.gz linux-stable-5c015258478eaac484c2fc91bd1d06babacb1ec4.tar.bz2 linux-stable-5c015258478eaac484c2fc91bd1d06babacb1ec4.zip |
eeprom: at24: add basic regmap_i2c support
This patch adds basic regmap support to be used by subsequent
patches of this series.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
-rw-r--r-- | drivers/misc/eeprom/Kconfig | 1 | ||||
-rw-r--r-- | drivers/misc/eeprom/at24.c | 57 |
2 files changed, 45 insertions, 13 deletions
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig index de58762097c4..68a1ac929917 100644 --- a/drivers/misc/eeprom/Kconfig +++ b/drivers/misc/eeprom/Kconfig @@ -4,6 +4,7 @@ config EEPROM_AT24 tristate "I2C EEPROMs / RAMs / ROMs from most vendors" depends on I2C && SYSFS select NVMEM + select REGMAP_I2C help Enable this driver to get read/write support to most I2C EEPROMs and compatible devices like FRAMs, SRAMs, ROMs etc. After you diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index 4d63ac8a82e0..04c455ba4b77 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -24,6 +24,7 @@ #include <linux/acpi.h> #include <linux/i2c.h> #include <linux/nvmem-provider.h> +#include <linux/regmap.h> #include <linux/platform_data/at24.h> #include <linux/pm_runtime.h> @@ -55,6 +56,11 @@ * which won't work on pure SMBus systems. */ +struct at24_client { + struct i2c_client *client; + struct regmap *regmap; +}; + struct at24_data { struct at24_platform_data chip; int use_smbus; @@ -81,7 +87,7 @@ struct at24_data { * Some chips tie up multiple I2C addresses; dummy devices reserve * them for us, and we'll use them with SMBus calls. */ - struct i2c_client *client[]; + struct at24_client client[]; }; /* @@ -274,7 +280,7 @@ static struct i2c_client *at24_translate_offset(struct at24_data *at24, *offset &= 0xff; } - return at24->client[i]; + return at24->client[i].client; } static ssize_t at24_eeprom_read_smbus(struct at24_data *at24, char *buf, @@ -562,7 +568,7 @@ static ssize_t at24_eeprom_write_i2c(struct at24_data *at24, const char *buf, static int at24_read(void *priv, unsigned int off, void *val, size_t count) { struct at24_data *at24 = priv; - struct device *dev = &at24->client[0]->dev; + struct device *dev = &at24->client[0].client->dev; char *buf = val; int ret; @@ -608,7 +614,7 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count) static int at24_write(void *priv, unsigned int off, void *val, size_t count) { struct at24_data *at24 = priv; - struct device *dev = &at24->client[0]->dev; + struct device *dev = &at24->client[0].client->dev; char *buf = val; int ret; @@ -676,6 +682,16 @@ static void at24_get_pdata(struct device *dev, struct at24_platform_data *chip) } } +static const struct regmap_config regmap_config_8 = { + .reg_bits = 8, + .val_bits = 8, +}; + +static const struct regmap_config regmap_config_16 = { + .reg_bits = 16, + .val_bits = 8, +}; + static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct at24_platform_data chip; @@ -686,6 +702,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) struct at24_data *at24; int err; unsigned i, num_addresses; + const struct regmap_config *config; u8 test_byte; if (client->dev.platform_data) { @@ -777,8 +794,13 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) num_addresses = DIV_ROUND_UP(chip.byte_len, (chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256); + if (chip.flags & AT24_FLAG_ADDR16) + config = ®map_config_16; + else + config = ®map_config_8; + at24 = devm_kzalloc(&client->dev, sizeof(struct at24_data) + - num_addresses * sizeof(struct i2c_client *), GFP_KERNEL); + num_addresses * sizeof(struct at24_client), GFP_KERNEL); if (!at24) return -ENOMEM; @@ -788,6 +810,11 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) at24->chip = chip; at24->num_addresses = num_addresses; + at24->client[0].client = client; + at24->client[0].regmap = devm_regmap_init_i2c(client, config); + if (IS_ERR(at24->client[0].regmap)) + return PTR_ERR(at24->client[0].regmap); + if ((chip.flags & AT24_FLAG_SERIAL) && (chip.flags & AT24_FLAG_MAC)) { dev_err(&client->dev, "invalid device data - cannot have both AT24_FLAG_SERIAL & AT24_FLAG_MAC."); @@ -835,18 +862,22 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) } } - at24->client[0] = client; - /* use dummy devices for multiple-address chips */ for (i = 1; i < num_addresses; i++) { - at24->client[i] = i2c_new_dummy(client->adapter, - client->addr + i); - if (!at24->client[i]) { + at24->client[i].client = i2c_new_dummy(client->adapter, + client->addr + i); + if (!at24->client[i].client) { dev_err(&client->dev, "address 0x%02x unavailable\n", client->addr + i); err = -EADDRINUSE; goto err_clients; } + at24->client[i].regmap = devm_regmap_init_i2c( + at24->client[i].client, config); + if (IS_ERR(at24->client[i].regmap)) { + err = PTR_ERR(at24->client[i].regmap); + goto err_clients; + } } i2c_set_clientdata(client, at24); @@ -905,8 +936,8 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) err_clients: for (i = 1; i < num_addresses; i++) - if (at24->client[i]) - i2c_unregister_device(at24->client[i]); + if (at24->client[i].client) + i2c_unregister_device(at24->client[i].client); pm_runtime_disable(&client->dev); @@ -923,7 +954,7 @@ static int at24_remove(struct i2c_client *client) nvmem_unregister(at24->nvmem); for (i = 1; i < at24->num_addresses; i++) - i2c_unregister_device(at24->client[i]); + i2c_unregister_device(at24->client[i].client); pm_runtime_disable(&client->dev); pm_runtime_set_suspended(&client->dev); |