From 1df5981b82d9eabdd6e66d1d9514164c02329345 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 10 Jun 2011 19:28:10 +0100 Subject: mfd: Convert WM831x to use regmap API Factor out the register read/write code to use the register map API. We still need some wm831x specific code and locking in place to check that the user key is handled correctly but only on the write side, reads are not affected by the key. Signed-off-by: Mark Brown Acked-by: Samuel Ortiz --- include/linux/mfd/wm831x/core.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/include/linux/mfd/wm831x/core.h b/include/linux/mfd/wm831x/core.h index 8dda8ded5cda..44acdb25681b 100644 --- a/include/linux/mfd/wm831x/core.h +++ b/include/linux/mfd/wm831x/core.h @@ -18,6 +18,7 @@ #include #include #include +#include /* * Register values. @@ -361,12 +362,8 @@ struct wm831x { struct mutex io_lock; struct device *dev; - int (*read_dev)(struct wm831x *wm831x, unsigned short reg, - int bytes, void *dest); - int (*write_dev)(struct wm831x *wm831x, unsigned short reg, - int bytes, void *src); - void *control_data; + struct regmap *regmap; int irq; /* Our chip IRQ */ struct mutex irq_lock; @@ -416,4 +413,6 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq); void wm831x_irq_exit(struct wm831x *wm831x); void wm831x_auxadc_init(struct wm831x *wm831x); +extern struct regmap_config wm831x_regmap_config; + #endif -- cgit v1.2.3 From d6c645fc00777a6f8a7df1f580065ec30c71be7b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 17 Jun 2011 13:02:27 +0100 Subject: mfd: Convert WM8994 to use new register map API Signed-off-by: Mark Brown Acked-by: Samuel Ortiz --- drivers/mfd/Kconfig | 1 + drivers/mfd/wm8994-core.c | 178 ++++++++-------------------------------- include/linux/mfd/wm8994/core.h | 9 +- 3 files changed, 36 insertions(+), 152 deletions(-) (limited to 'include/linux') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index cfae5c594d24..a67adcbd0fa1 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -490,6 +490,7 @@ config MFD_WM8350_I2C config MFD_WM8994 bool "Support Wolfson Microelectronics WM8994" select MFD_CORE + select REGMAP_I2C depends on I2C=y && GENERIC_HARDIRQS help The WM8994 is a highly integrated hi-fi CODEC designed for diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index 96479c9b1728..bfde4e8ec638 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -16,9 +16,11 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -29,22 +31,7 @@ static int wm8994_read(struct wm8994 *wm8994, unsigned short reg, int bytes, void *dest) { - int ret, i; - u16 *buf = dest; - - BUG_ON(bytes % 2); - BUG_ON(bytes <= 0); - - ret = wm8994->read_dev(wm8994, reg, bytes, dest); - if (ret < 0) - return ret; - - for (i = 0; i < bytes / 2; i++) { - dev_vdbg(wm8994->dev, "Read %04x from R%d(0x%x)\n", - be16_to_cpu(buf[i]), reg + i, reg + i); - } - - return 0; + return regmap_raw_read(wm8994->regmap, reg, dest, bytes); } /** @@ -55,19 +42,15 @@ static int wm8994_read(struct wm8994 *wm8994, unsigned short reg, */ int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg) { - unsigned short val; + unsigned int val; int ret; - mutex_lock(&wm8994->io_lock); - - ret = wm8994_read(wm8994, reg, 2, &val); - - mutex_unlock(&wm8994->io_lock); + ret = regmap_read(wm8994->regmap, reg, &val); if (ret < 0) return ret; else - return be16_to_cpu(val); + return val; } EXPORT_SYMBOL_GPL(wm8994_reg_read); @@ -82,33 +65,13 @@ EXPORT_SYMBOL_GPL(wm8994_reg_read); int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg, int count, u16 *buf) { - int ret; - - mutex_lock(&wm8994->io_lock); - - ret = wm8994_read(wm8994, reg, count * 2, buf); - - mutex_unlock(&wm8994->io_lock); - - return ret; + return regmap_bulk_read(wm8994->regmap, reg, buf, count); } -EXPORT_SYMBOL_GPL(wm8994_bulk_read); static int wm8994_write(struct wm8994 *wm8994, unsigned short reg, int bytes, const void *src) { - const u16 *buf = src; - int i; - - BUG_ON(bytes % 2); - BUG_ON(bytes <= 0); - - for (i = 0; i < bytes / 2; i++) { - dev_vdbg(wm8994->dev, "Write %04x to R%d(0x%x)\n", - be16_to_cpu(buf[i]), reg + i, reg + i); - } - - return wm8994->write_dev(wm8994, reg, bytes, src); + return regmap_raw_write(wm8994->regmap, reg, src, bytes); } /** @@ -121,17 +84,7 @@ static int wm8994_write(struct wm8994 *wm8994, unsigned short reg, int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg, unsigned short val) { - int ret; - - val = cpu_to_be16(val); - - mutex_lock(&wm8994->io_lock); - - ret = wm8994_write(wm8994, reg, 2, &val); - - mutex_unlock(&wm8994->io_lock); - - return ret; + return regmap_write(wm8994->regmap, reg, val); } EXPORT_SYMBOL_GPL(wm8994_reg_write); @@ -146,15 +99,7 @@ EXPORT_SYMBOL_GPL(wm8994_reg_write); int wm8994_bulk_write(struct wm8994 *wm8994, unsigned short reg, int count, const u16 *buf) { - int ret; - - mutex_lock(&wm8994->io_lock); - - ret = wm8994_write(wm8994, reg, count * 2, buf); - - mutex_unlock(&wm8994->io_lock); - - return ret; + return regmap_raw_write(wm8994->regmap, reg, buf, count * sizeof(u16)); } EXPORT_SYMBOL_GPL(wm8994_bulk_write); @@ -169,28 +114,7 @@ EXPORT_SYMBOL_GPL(wm8994_bulk_write); int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg, unsigned short mask, unsigned short val) { - int ret; - u16 r; - - mutex_lock(&wm8994->io_lock); - - ret = wm8994_read(wm8994, reg, 2, &r); - if (ret < 0) - goto out; - - r = be16_to_cpu(r); - - r &= ~mask; - r |= val; - - r = cpu_to_be16(r); - - ret = wm8994_write(wm8994, reg, 2, &r); - -out: - mutex_unlock(&wm8994->io_lock); - - return ret; + return regmap_update_bits(wm8994->regmap, reg, mask, val); } EXPORT_SYMBOL_GPL(wm8994_set_bits); @@ -378,6 +302,11 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo) } #endif +static struct regmap_config wm8994_regmap_config = { + .reg_bits = 16, + .val_bits = 16, +}; + /* * Instantiate the generic non-control parts of the device. */ @@ -387,7 +316,6 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) const char *devname; int ret, i; - mutex_init(&wm8994->io_lock); dev_set_drvdata(wm8994->dev, wm8994); /* Add the on-chip regulators first for bootstrapping */ @@ -397,7 +325,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) NULL, 0); if (ret != 0) { dev_err(wm8994->dev, "Failed to add children: %d\n", ret); - goto err; + goto err_regmap; } switch (wm8994->type) { @@ -409,7 +337,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) break; default: BUG(); - goto err; + goto err_regmap; } wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) * @@ -417,7 +345,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) GFP_KERNEL); if (!wm8994->supplies) { ret = -ENOMEM; - goto err; + goto err_regmap; } switch (wm8994->type) { @@ -431,7 +359,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) break; default: BUG(); - goto err; + goto err_regmap; } ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies, @@ -554,7 +482,8 @@ err_get: regulator_bulk_free(wm8994->num_supplies, wm8994->supplies); err_supplies: kfree(wm8994->supplies); -err: +err_regmap: + regmap_exit(wm8994->regmap); mfd_remove_devices(wm8994->dev); kfree(wm8994); return ret; @@ -569,62 +498,15 @@ static void wm8994_device_exit(struct wm8994 *wm8994) wm8994->supplies); regulator_bulk_free(wm8994->num_supplies, wm8994->supplies); kfree(wm8994->supplies); + regmap_exit(wm8994->regmap); kfree(wm8994); } -static int wm8994_i2c_read_device(struct wm8994 *wm8994, unsigned short reg, - int bytes, void *dest) -{ - struct i2c_client *i2c = wm8994->control_data; - int ret; - u16 r = cpu_to_be16(reg); - - ret = i2c_master_send(i2c, (unsigned char *)&r, 2); - if (ret < 0) - return ret; - if (ret != 2) - return -EIO; - - ret = i2c_master_recv(i2c, dest, bytes); - if (ret < 0) - return ret; - if (ret != bytes) - return -EIO; - return 0; -} - -static int wm8994_i2c_write_device(struct wm8994 *wm8994, unsigned short reg, - int bytes, const void *src) -{ - struct i2c_client *i2c = wm8994->control_data; - struct i2c_msg xfer[2]; - int ret; - - reg = cpu_to_be16(reg); - - xfer[0].addr = i2c->addr; - xfer[0].flags = 0; - xfer[0].len = 2; - xfer[0].buf = (char *)® - - xfer[1].addr = i2c->addr; - xfer[1].flags = I2C_M_NOSTART; - xfer[1].len = bytes; - xfer[1].buf = (char *)src; - - ret = i2c_transfer(i2c->adapter, xfer, 2); - if (ret < 0) - return ret; - if (ret != 2) - return -EIO; - - return 0; -} - static int wm8994_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8994 *wm8994; + int ret; wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL); if (wm8994 == NULL) @@ -632,12 +514,18 @@ static int wm8994_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, wm8994); wm8994->dev = &i2c->dev; - wm8994->control_data = i2c; - wm8994->read_dev = wm8994_i2c_read_device; - wm8994->write_dev = wm8994_i2c_write_device; wm8994->irq = i2c->irq; wm8994->type = id->driver_data; + wm8994->regmap = regmap_init_i2c(i2c, &wm8994_regmap_config); + if (IS_ERR(wm8994->regmap)) { + ret = PTR_ERR(wm8994->regmap); + dev_err(wm8994->dev, "Failed to allocate register map: %d\n", + ret); + kfree(wm8994); + return ret; + } + return wm8994_device_init(wm8994, i2c->irq); } diff --git a/include/linux/mfd/wm8994/core.h b/include/linux/mfd/wm8994/core.h index f0b69cdae41c..45df450d869f 100644 --- a/include/linux/mfd/wm8994/core.h +++ b/include/linux/mfd/wm8994/core.h @@ -24,6 +24,7 @@ enum wm8994_type { struct regulator_dev; struct regulator_bulk_data; +struct regmap; #define WM8994_NUM_GPIO_REGS 11 #define WM8994_NUM_LDO_REGS 2 @@ -50,18 +51,12 @@ struct regulator_bulk_data; #define WM8994_IRQ_GPIO(x) (x + WM8994_IRQ_TEMP_WARN) struct wm8994 { - struct mutex io_lock; struct mutex irq_lock; enum wm8994_type type; struct device *dev; - int (*read_dev)(struct wm8994 *wm8994, unsigned short reg, - int bytes, void *dest); - int (*write_dev)(struct wm8994 *wm8994, unsigned short reg, - int bytes, const void *src); - - void *control_data; + struct regmap *regmap; int gpio_base; int irq_base; -- cgit v1.2.3 From 50eeef5d3cea5afcced17a0410e8b0bf88997845 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 9 Aug 2011 16:34:29 +0900 Subject: mfd: Convert WM8400 to regmap API Signed-off-by: Mark Brown --- drivers/mfd/wm8400-core.c | 106 ++++++++++--------------------------- include/linux/mfd/wm8400-private.h | 7 ++- 2 files changed, 32 insertions(+), 81 deletions(-) (limited to 'include/linux') diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c index 597f82edacaa..e06ba9440cdb 100644 --- a/drivers/mfd/wm8400-core.c +++ b/drivers/mfd/wm8400-core.c @@ -13,11 +13,13 @@ */ #include +#include #include #include #include #include #include +#include #include static struct { @@ -123,14 +125,9 @@ static int wm8400_read(struct wm8400 *wm8400, u8 reg, int num_regs, u16 *dest) /* If there are any volatile reads then read back the entire block */ for (i = reg; i < reg + num_regs; i++) if (reg_data[i].vol) { - ret = wm8400->read_dev(wm8400->io_data, reg, - num_regs, dest); - if (ret != 0) - return ret; - for (i = 0; i < num_regs; i++) - dest[i] = be16_to_cpu(dest[i]); - - return 0; + ret = regmap_bulk_read(wm8400->regmap, reg, dest, + num_regs); + return ret; } /* Otherwise use the cache */ @@ -149,14 +146,11 @@ static int wm8400_write(struct wm8400 *wm8400, u8 reg, int num_regs, for (i = 0; i < num_regs; i++) { BUG_ON(!reg_data[reg + i].writable); wm8400->reg_cache[reg + i] = src[i]; - src[i] = cpu_to_be16(src[i]); + ret = regmap_write(wm8400->regmap, reg, src[i]); + if (ret != 0) + return ret; } - /* Do the actual I/O */ - ret = wm8400->write_dev(wm8400->io_data, reg, num_regs, src); - if (ret != 0) - return -EIO; - return 0; } @@ -270,14 +264,14 @@ static int wm8400_init(struct wm8400 *wm8400, dev_set_drvdata(wm8400->dev, wm8400); /* Check that this is actually a WM8400 */ - ret = wm8400->read_dev(wm8400->io_data, WM8400_RESET_ID, 1, ®); + ret = regmap_read(wm8400->regmap, WM8400_RESET_ID, &i); if (ret != 0) { dev_err(wm8400->dev, "Chip ID register read failed\n"); return -EIO; } - if (be16_to_cpu(reg) != reg_data[WM8400_RESET_ID].default_val) { + if (i != reg_data[WM8400_RESET_ID].default_val) { dev_err(wm8400->dev, "Device is not a WM8400, ID is %x\n", - be16_to_cpu(reg)); + reg); return -ENODEV; } @@ -285,9 +279,8 @@ static int wm8400_init(struct wm8400 *wm8400, * is a PMIC we can't reset it safely so initialise the register * cache from the hardware. */ - ret = wm8400->read_dev(wm8400->io_data, 0, - ARRAY_SIZE(wm8400->reg_cache), - wm8400->reg_cache); + ret = regmap_raw_read(wm8400->regmap, 0, wm8400->reg_cache, + ARRAY_SIZE(wm8400->reg_cache)); if (ret != 0) { dev_err(wm8400->dev, "Register cache read failed\n"); return -EIO; @@ -337,60 +330,13 @@ static void wm8400_release(struct wm8400 *wm8400) mfd_remove_devices(wm8400->dev); } -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static int wm8400_i2c_read(void *io_data, char reg, int count, u16 *dest) -{ - struct i2c_client *i2c = io_data; - struct i2c_msg xfer[2]; - int ret; - - /* Write register */ - xfer[0].addr = i2c->addr; - xfer[0].flags = 0; - xfer[0].len = 1; - xfer[0].buf = ® - - /* Read data */ - xfer[1].addr = i2c->addr; - xfer[1].flags = I2C_M_RD; - xfer[1].len = count * sizeof(u16); - xfer[1].buf = (u8 *)dest; - - ret = i2c_transfer(i2c->adapter, xfer, 2); - if (ret == 2) - ret = 0; - else if (ret >= 0) - ret = -EIO; - - return ret; -} - -static int wm8400_i2c_write(void *io_data, char reg, int count, const u16 *src) -{ - struct i2c_client *i2c = io_data; - u8 *msg; - int ret; - - /* We add 1 byte for device register - ideally I2C would gather. */ - msg = kmalloc((count * sizeof(u16)) + 1, GFP_KERNEL); - if (msg == NULL) - return -ENOMEM; - - msg[0] = reg; - memcpy(&msg[1], src, count * sizeof(u16)); - - ret = i2c_master_send(i2c, msg, (count * sizeof(u16)) + 1); - - if (ret == (count * 2) + 1) - ret = 0; - else if (ret >= 0) - ret = -EIO; - - kfree(msg); - - return ret; -} +static const struct regmap_config wm8400_regmap_config = { + .reg_bits = 8, + .val_bits = 16, + .max_register = WM8400_REGISTER_COUNT - 1, +}; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static int wm8400_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -403,18 +349,23 @@ static int wm8400_i2c_probe(struct i2c_client *i2c, goto err; } - wm8400->io_data = i2c; - wm8400->read_dev = wm8400_i2c_read; - wm8400->write_dev = wm8400_i2c_write; + wm8400->regmap = regmap_init_i2c(i2c, &wm8400_regmap_config); + if (IS_ERR(wm8400->regmap)) { + ret = PTR_ERR(wm8400->regmap); + goto struct_err; + } + wm8400->dev = &i2c->dev; i2c_set_clientdata(i2c, wm8400); ret = wm8400_init(wm8400, i2c->dev.platform_data); if (ret != 0) - goto struct_err; + goto map_err; return 0; +map_err: + regmap_exit(wm8400->regmap); struct_err: kfree(wm8400); err: @@ -426,6 +377,7 @@ static int wm8400_i2c_remove(struct i2c_client *i2c) struct wm8400 *wm8400 = i2c_get_clientdata(i2c); wm8400_release(wm8400); + regmap_exit(wm8400->regmap); kfree(wm8400); return 0; diff --git a/include/linux/mfd/wm8400-private.h b/include/linux/mfd/wm8400-private.h index 2aab4e93a5c9..0147b6968510 100644 --- a/include/linux/mfd/wm8400-private.h +++ b/include/linux/mfd/wm8400-private.h @@ -25,16 +25,15 @@ #include #include +struct regmap; + #define WM8400_REGISTER_COUNT 0x55 struct wm8400 { struct device *dev; - int (*read_dev)(void *data, char reg, int count, u16 *dst); - int (*write_dev)(void *data, char reg, int count, const u16 *src); - struct mutex io_lock; - void *io_data; + struct regmap *regmap; u16 reg_cache[WM8400_REGISTER_COUNT]; -- cgit v1.2.3