eeprom: at24: add basic regmap_i2c support
authorHeiner Kallweit <hkallweit1@gmail.com>
Tue, 28 Nov 2017 20:51:40 +0000 (21:51 +0100)
committerBartosz Golaszewski <brgl@bgdev.pl>
Mon, 1 Jan 2018 18:40:46 +0000 (19:40 +0100)
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>
drivers/misc/eeprom/Kconfig
drivers/misc/eeprom/at24.c

index de58762..68a1ac9 100644 (file)
@@ -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
index 4d63ac8..04c455b 100644 (file)
@@ -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>
 
  * 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 = &regmap_config_16;
+       else
+               config = &regmap_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);