From 01a03ba76fbf221bca638cfe47fc5938e50d043d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 10 Jun 2011 19:28:10 +0100 Subject: [PATCH] --- yaml --- r: 266971 b: refs/heads/master c: 1df5981b82d9eabdd6e66d1d9514164c02329345 h: refs/heads/master i: 266969: 10d018605015550598ba25dae5799ef5fe18c243 266967: c6dfb232da79cc414f963c5385a4af1d4189d5dc v: v3 --- [refs] | 2 +- trunk/drivers/base/regmap/Makefile | 1 - trunk/drivers/base/regmap/internal.h | 66 ------- trunk/drivers/base/regmap/regmap-debugfs.c | 209 --------------------- trunk/drivers/base/regmap/regmap-i2c.c | 2 +- trunk/drivers/base/regmap/regmap-spi.c | 3 +- trunk/drivers/base/regmap/regmap.c | 142 ++++---------- trunk/drivers/mfd/Kconfig | 2 + trunk/drivers/mfd/wm831x-core.c | 89 +++------ trunk/drivers/mfd/wm831x-i2c.c | 68 ++----- trunk/drivers/mfd/wm831x-spi.c | 60 ++---- trunk/include/linux/mfd/wm831x/core.h | 9 +- trunk/include/linux/regmap.h | 4 + trunk/include/trace/events/regmap.h | 112 ----------- 14 files changed, 103 insertions(+), 666 deletions(-) delete mode 100644 trunk/drivers/base/regmap/internal.h delete mode 100644 trunk/drivers/base/regmap/regmap-debugfs.c delete mode 100644 trunk/include/trace/events/regmap.h diff --git a/[refs] b/[refs] index c73b1044b028..31a10e6d91c5 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: ae130d22de8f8977cc3015bfafc09ff93744d92a +refs/heads/master: 1df5981b82d9eabdd6e66d1d9514164c02329345 diff --git a/trunk/drivers/base/regmap/Makefile b/trunk/drivers/base/regmap/Makefile index 057c13f66a67..f476f4571295 100644 --- a/trunk/drivers/base/regmap/Makefile +++ b/trunk/drivers/base/regmap/Makefile @@ -1,4 +1,3 @@ obj-$(CONFIG_REGMAP) += regmap.o -obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o diff --git a/trunk/drivers/base/regmap/internal.h b/trunk/drivers/base/regmap/internal.h deleted file mode 100644 index 5ab3fefa4b05..000000000000 --- a/trunk/drivers/base/regmap/internal.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Register map access API internal header - * - * Copyright 2011 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _REGMAP_INTERNAL_H -#define _REGMAP_INTERNAL_H - -#include -#include - -struct regmap; - -struct regmap_format { - size_t buf_size; - size_t reg_bytes; - size_t val_bytes; - void (*format_write)(struct regmap *map, - unsigned int reg, unsigned int val); - void (*format_reg)(void *buf, unsigned int reg); - void (*format_val)(void *buf, unsigned int val); - unsigned int (*parse_val)(void *buf); -}; - -struct regmap { - struct mutex lock; - - struct device *dev; /* Device we do I/O on */ - void *work_buf; /* Scratch buffer used to format I/O */ - struct regmap_format format; /* Buffer format */ - const struct regmap_bus *bus; - -#ifdef CONFIG_DEBUG_FS - struct dentry *debugfs; -#endif - - unsigned int max_register; - bool (*writeable_reg)(struct device *dev, unsigned int reg); - bool (*readable_reg)(struct device *dev, unsigned int reg); - bool (*volatile_reg)(struct device *dev, unsigned int reg); - bool (*precious_reg)(struct device *dev, unsigned int reg); -}; - -bool regmap_writeable(struct regmap *map, unsigned int reg); -bool regmap_readable(struct regmap *map, unsigned int reg); -bool regmap_volatile(struct regmap *map, unsigned int reg); -bool regmap_precious(struct regmap *map, unsigned int reg); - -#ifdef CONFIG_DEBUG_FS -extern void regmap_debugfs_initcall(void); -extern void regmap_debugfs_init(struct regmap *map); -extern void regmap_debugfs_exit(struct regmap *map); -#else -void regmap_debugfs_initcall(void) { } -void regmap_debugfs_init(struct regmap *map) { } -void regmap_debugfs_exit(struct regmap *map) { } -#endif - -#endif diff --git a/trunk/drivers/base/regmap/regmap-debugfs.c b/trunk/drivers/base/regmap/regmap-debugfs.c deleted file mode 100644 index 7a8d67537d3f..000000000000 --- a/trunk/drivers/base/regmap/regmap-debugfs.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Register map access API - debugfs - * - * Copyright 2011 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include - -#include "internal.h" - -static struct dentry *regmap_debugfs_root; - -/* Calculate the length of a fixed format */ -static size_t regmap_calc_reg_len(int max_val, char *buf, size_t buf_size) -{ - snprintf(buf, buf_size, "%x", max_val); - return strlen(buf); -} - -static int regmap_open_file(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - int reg_len, val_len, tot_len; - size_t buf_pos = 0; - loff_t p = 0; - ssize_t ret; - int i; - struct regmap *map = file->private_data; - char *buf; - unsigned int val; - - if (*ppos < 0 || !count) - return -EINVAL; - - buf = kmalloc(count, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - /* Calculate the length of a fixed format */ - reg_len = regmap_calc_reg_len(map->max_register, buf, count); - val_len = 2 * map->format.val_bytes; - tot_len = reg_len + val_len + 3; /* : \n */ - - for (i = 0; i < map->max_register; i++) { - if (!regmap_readable(map, i)) - continue; - - if (regmap_precious(map, i)) - continue; - - /* If we're in the region the user is trying to read */ - if (p >= *ppos) { - /* ...but not beyond it */ - if (buf_pos >= count - 1 - tot_len) - break; - - /* Format the register */ - snprintf(buf + buf_pos, count - buf_pos, "%.*x: ", - reg_len, i); - buf_pos += reg_len + 2; - - /* Format the value, write all X if we can't read */ - ret = regmap_read(map, i, &val); - if (ret == 0) - snprintf(buf + buf_pos, count - buf_pos, - "%.*x", val_len, val); - else - memset(buf + buf_pos, 'X', val_len); - buf_pos += 2 * map->format.val_bytes; - - buf[buf_pos++] = '\n'; - } - p += tot_len; - } - - ret = buf_pos; - - if (copy_to_user(user_buf, buf, buf_pos)) { - ret = -EFAULT; - goto out; - } - - *ppos += buf_pos; - -out: - kfree(buf); - return ret; -} - -static const struct file_operations regmap_map_fops = { - .open = regmap_open_file, - .read = regmap_map_read_file, - .llseek = default_llseek, -}; - -static ssize_t regmap_access_read_file(struct file *file, - char __user *user_buf, size_t count, - loff_t *ppos) -{ - int reg_len, tot_len; - size_t buf_pos = 0; - loff_t p = 0; - ssize_t ret; - int i; - struct regmap *map = file->private_data; - char *buf; - - if (*ppos < 0 || !count) - return -EINVAL; - - buf = kmalloc(count, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - /* Calculate the length of a fixed format */ - reg_len = regmap_calc_reg_len(map->max_register, buf, count); - tot_len = reg_len + 10; /* ': R W V P\n' */ - - for (i = 0; i < map->max_register; i++) { - /* Ignore registers which are neither readable nor writable */ - if (!regmap_readable(map, i) && !regmap_writeable(map, i)) - continue; - - /* If we're in the region the user is trying to read */ - if (p >= *ppos) { - /* ...but not beyond it */ - if (buf_pos >= count - 1 - tot_len) - break; - - /* Format the register */ - snprintf(buf + buf_pos, count - buf_pos, - "%.*x: %c %c %c %c\n", - reg_len, i, - regmap_readable(map, i) ? 'y' : 'n', - regmap_writeable(map, i) ? 'y' : 'n', - regmap_volatile(map, i) ? 'y' : 'n', - regmap_precious(map, i) ? 'y' : 'n'); - - buf_pos += tot_len; - } - p += tot_len; - } - - ret = buf_pos; - - if (copy_to_user(user_buf, buf, buf_pos)) { - ret = -EFAULT; - goto out; - } - - *ppos += buf_pos; - -out: - kfree(buf); - return ret; -} - -static const struct file_operations regmap_access_fops = { - .open = regmap_open_file, - .read = regmap_access_read_file, - .llseek = default_llseek, -}; - -void regmap_debugfs_init(struct regmap *map) -{ - map->debugfs = debugfs_create_dir(dev_name(map->dev), - regmap_debugfs_root); - if (!map->debugfs) { - dev_warn(map->dev, "Failed to create debugfs directory\n"); - return; - } - - if (map->max_register) { - debugfs_create_file("registers", 0400, map->debugfs, - map, ®map_map_fops); - debugfs_create_file("access", 0400, map->debugfs, - map, ®map_access_fops); - } -} - -void regmap_debugfs_exit(struct regmap *map) -{ - debugfs_remove_recursive(map->debugfs); -} - -void regmap_debugfs_initcall(void) -{ - regmap_debugfs_root = debugfs_create_dir("regmap", NULL); - if (!regmap_debugfs_root) { - pr_warn("regmap: Failed to create debugfs root\n"); - return; - } -} diff --git a/trunk/drivers/base/regmap/regmap-i2c.c b/trunk/drivers/base/regmap/regmap-i2c.c index e7d916d1b3ea..c2231ff06cbc 100644 --- a/trunk/drivers/base/regmap/regmap-i2c.c +++ b/trunk/drivers/base/regmap/regmap-i2c.c @@ -90,6 +90,7 @@ static int regmap_i2c_read(struct device *dev, } static struct regmap_bus regmap_i2c = { + .type = &i2c_bus_type, .write = regmap_i2c_write, .gather_write = regmap_i2c_gather_write, .read = regmap_i2c_read, @@ -112,4 +113,3 @@ struct regmap *regmap_init_i2c(struct i2c_client *i2c, } EXPORT_SYMBOL_GPL(regmap_init_i2c); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/base/regmap/regmap-spi.c b/trunk/drivers/base/regmap/regmap-spi.c index cc0f1164cf99..4deba0621bc7 100644 --- a/trunk/drivers/base/regmap/regmap-spi.c +++ b/trunk/drivers/base/regmap/regmap-spi.c @@ -47,6 +47,7 @@ static int regmap_spi_read(struct device *dev, } static struct regmap_bus regmap_spi = { + .type = &spi_bus_type, .write = regmap_spi_write, .gather_write = regmap_spi_gather_write, .read = regmap_spi_read, @@ -69,5 +70,3 @@ struct regmap *regmap_init_spi(struct spi_device *spi, return regmap_init(&spi->dev, ®map_spi, config); } EXPORT_SYMBOL_GPL(regmap_init_spi); - -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/base/regmap/regmap.c b/trunk/drivers/base/regmap/regmap.c index fa2bd896eb20..2fa55c56897a 100644 --- a/trunk/drivers/base/regmap/regmap.c +++ b/trunk/drivers/base/regmap/regmap.c @@ -15,54 +15,34 @@ #include #include -#define CREATE_TRACE_POINTS -#include - -#include "internal.h" - -bool regmap_writeable(struct regmap *map, unsigned int reg) -{ - if (map->max_register && reg > map->max_register) - return false; - - if (map->writeable_reg) - return map->writeable_reg(map->dev, reg); - - return true; -} - -bool regmap_readable(struct regmap *map, unsigned int reg) -{ - if (map->max_register && reg > map->max_register) - return false; - - if (map->readable_reg) - return map->readable_reg(map->dev, reg); - - return true; -} - -bool regmap_volatile(struct regmap *map, unsigned int reg) -{ - if (map->max_register && reg > map->max_register) - return false; - - if (map->volatile_reg) - return map->volatile_reg(map->dev, reg); - - return true; -} - -bool regmap_precious(struct regmap *map, unsigned int reg) -{ - if (map->max_register && reg > map->max_register) - return false; - - if (map->precious_reg) - return map->precious_reg(map->dev, reg); - - return false; -} +#include + +struct regmap; + +struct regmap_format { + size_t buf_size; + size_t reg_bytes; + size_t val_bytes; + void (*format_write)(struct regmap *map, + unsigned int reg, unsigned int val); + void (*format_reg)(void *buf, unsigned int reg); + void (*format_val)(void *buf, unsigned int val); + unsigned int (*parse_val)(void *buf); +}; + +struct regmap { + struct mutex lock; + + struct device *dev; /* Device we do I/O on */ + void *work_buf; /* Scratch buffer used to format I/O */ + struct regmap_format format; /* Buffer format */ + const struct regmap_bus *bus; + + unsigned int max_register; + bool (*writeable_reg)(struct device *dev, unsigned int reg); + bool (*readable_reg)(struct device *dev, unsigned int reg); + bool (*volatile_reg)(struct device *dev, unsigned int reg); +}; static void regmap_format_4_12_write(struct regmap *map, unsigned int reg, unsigned int val) @@ -145,7 +125,6 @@ struct regmap *regmap_init(struct device *dev, map->writeable_reg = config->writeable_reg; map->readable_reg = config->readable_reg; map->volatile_reg = config->volatile_reg; - map->precious_reg = config->precious_reg; switch (config->reg_bits) { case 4: @@ -201,8 +180,6 @@ struct regmap *regmap_init(struct device *dev, goto err_bus; } - regmap_debugfs_init(map); - return map; err_bus: @@ -219,7 +196,6 @@ EXPORT_SYMBOL_GPL(regmap_init); */ void regmap_exit(struct regmap *map) { - regmap_debugfs_exit(map); kfree(map->work_buf); module_put(map->bus->owner); kfree(map); @@ -232,32 +208,16 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, void *buf; int ret = -ENOTSUPP; size_t len; - int i; - - /* Check for unwritable registers before we start */ - if (map->writeable_reg) - for (i = 0; i < val_len / map->format.val_bytes; i++) - if (!map->writeable_reg(map->dev, reg + i)) - return -EINVAL; map->format.format_reg(map->work_buf, reg); - trace_regmap_hw_write_start(map->dev, reg, - val_len / map->format.val_bytes); - - /* If we're doing a single register write we can probably just - * send the work_buf directly, otherwise try to do a gather - * write. - */ - if (val == map->work_buf + map->format.reg_bytes) - ret = map->bus->write(map->dev, map->work_buf, - map->format.reg_bytes + val_len); - else if (map->bus->gather_write) + /* Try to do a gather write if we can */ + if (map->bus->gather_write) ret = map->bus->gather_write(map->dev, map->work_buf, map->format.reg_bytes, val, val_len); - /* If that didn't work fall back on linearising by hand. */ + /* Otherwise fall back on linearising by hand. */ if (ret == -ENOTSUPP) { len = map->format.reg_bytes + val_len; buf = kmalloc(len, GFP_KERNEL); @@ -271,31 +231,19 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, kfree(buf); } - trace_regmap_hw_write_done(map->dev, reg, - val_len / map->format.val_bytes); - return ret; } static int _regmap_write(struct regmap *map, unsigned int reg, unsigned int val) { - int ret; BUG_ON(!map->format.format_write && !map->format.format_val); - trace_regmap_reg_write(map->dev, reg, val); - if (map->format.format_write) { map->format.format_write(map, reg, val); - trace_regmap_hw_write_start(map->dev, reg, 1); - - ret = map->bus->write(map->dev, map->work_buf, - map->format.buf_size); - - trace_regmap_hw_write_done(map->dev, reg, 1); - - return ret; + return map->bus->write(map->dev, map->work_buf, + map->format.buf_size); } else { map->format.format_val(map->work_buf + map->format.reg_bytes, val); @@ -377,16 +325,12 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, if (map->bus->read_flag_mask) u8[0] |= map->bus->read_flag_mask; - trace_regmap_hw_read_start(map->dev, reg, - val_len / map->format.val_bytes); - ret = map->bus->read(map->dev, map->work_buf, map->format.reg_bytes, - val, val_len); - - trace_regmap_hw_read_done(map->dev, reg, - val_len / map->format.val_bytes); + val, map->format.val_bytes); + if (ret != 0) + return ret; - return ret; + return 0; } static int _regmap_read(struct regmap *map, unsigned int reg, @@ -398,10 +342,8 @@ static int _regmap_read(struct regmap *map, unsigned int reg, return -EINVAL; ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes); - if (ret == 0) { + if (ret == 0) *val = map->format.parse_val(map->work_buf); - trace_regmap_reg_read(map->dev, reg, *val); - } return ret; } @@ -520,11 +462,3 @@ int regmap_update_bits(struct regmap *map, unsigned int reg, return ret; } EXPORT_SYMBOL_GPL(regmap_update_bits); - -static int __init regmap_initcall(void) -{ - regmap_debugfs_initcall(); - - return 0; -} -postcore_initcall(regmap_initcall); diff --git a/trunk/drivers/mfd/Kconfig b/trunk/drivers/mfd/Kconfig index 21574bdf485f..cfae5c594d24 100644 --- a/trunk/drivers/mfd/Kconfig +++ b/trunk/drivers/mfd/Kconfig @@ -404,6 +404,7 @@ config MFD_WM831X_I2C bool "Support Wolfson Microelectronics WM831x/2x PMICs with I2C" select MFD_CORE select MFD_WM831X + select REGMAP_I2C depends on I2C=y && GENERIC_HARDIRQS help Support for the Wolfson Microelecronics WM831x and WM832x PMICs @@ -415,6 +416,7 @@ config MFD_WM831X_SPI bool "Support Wolfson Microelectronics WM831x/2x PMICs with SPI" select MFD_CORE select MFD_WM831X + select REGMAP_SPI depends on SPI_MASTER && GENERIC_HARDIRQS help Support for the Wolfson Microelecronics WM831x and WM832x PMICs diff --git a/trunk/drivers/mfd/wm831x-core.c b/trunk/drivers/mfd/wm831x-core.c index 282e76ab678f..578e0c2ad82b 100644 --- a/trunk/drivers/mfd/wm831x-core.c +++ b/trunk/drivers/mfd/wm831x-core.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -160,29 +161,6 @@ int wm831x_reg_unlock(struct wm831x *wm831x) } EXPORT_SYMBOL_GPL(wm831x_reg_unlock); -static int wm831x_read(struct wm831x *wm831x, unsigned short reg, - int bytes, void *dest) -{ - int ret, i; - u16 *buf = dest; - - BUG_ON(bytes % 2); - BUG_ON(bytes <= 0); - - ret = wm831x->read_dev(wm831x, reg, bytes, dest); - if (ret < 0) - return ret; - - for (i = 0; i < bytes / 2; i++) { - buf[i] = be16_to_cpu(buf[i]); - - dev_vdbg(wm831x->dev, "Read %04x from R%d(0x%x)\n", - buf[i], reg + i, reg + i); - } - - return 0; -} - /** * wm831x_reg_read: Read a single WM831x register. * @@ -191,14 +169,10 @@ static int wm831x_read(struct wm831x *wm831x, unsigned short reg, */ int wm831x_reg_read(struct wm831x *wm831x, unsigned short reg) { - unsigned short val; + unsigned int val; int ret; - mutex_lock(&wm831x->io_lock); - - ret = wm831x_read(wm831x, reg, 2, &val); - - mutex_unlock(&wm831x->io_lock); + ret = regmap_read(wm831x->regmap, reg, &val); if (ret < 0) return ret; @@ -218,15 +192,7 @@ EXPORT_SYMBOL_GPL(wm831x_reg_read); int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg, int count, u16 *buf) { - int ret; - - mutex_lock(&wm831x->io_lock); - - ret = wm831x_read(wm831x, reg, count * 2, buf); - - mutex_unlock(&wm831x->io_lock); - - return ret; + return regmap_bulk_read(wm831x->regmap, reg, buf, count); } EXPORT_SYMBOL_GPL(wm831x_bulk_read); @@ -234,7 +200,7 @@ static int wm831x_write(struct wm831x *wm831x, unsigned short reg, int bytes, void *src) { u16 *buf = src; - int i; + int i, ret; BUG_ON(bytes % 2); BUG_ON(bytes <= 0); @@ -245,11 +211,10 @@ static int wm831x_write(struct wm831x *wm831x, unsigned short reg, dev_vdbg(wm831x->dev, "Write %04x to R%d(0x%x)\n", buf[i], reg + i, reg + i); - - buf[i] = cpu_to_be16(buf[i]); + ret = regmap_write(wm831x->regmap, reg + i, buf[i]); } - return wm831x->write_dev(wm831x, reg, bytes, src); + return 0; } /** @@ -286,20 +251,14 @@ int wm831x_set_bits(struct wm831x *wm831x, unsigned short reg, unsigned short mask, unsigned short val) { int ret; - u16 r; mutex_lock(&wm831x->io_lock); - ret = wm831x_read(wm831x, reg, 2, &r); - if (ret < 0) - goto out; - - r &= ~mask; - r |= val & mask; - - ret = wm831x_write(wm831x, reg, 2, &r); + if (!wm831x_reg_locked(wm831x, reg)) + ret = regmap_update_bits(wm831x->regmap, reg, mask, val); + else + ret = -EPERM; -out: mutex_unlock(&wm831x->io_lock); return ret; @@ -1292,6 +1251,12 @@ static struct mfd_cell backlight_devs[] = { }, }; +struct regmap_config wm831x_regmap_config = { + .reg_bits = 16, + .val_bits = 16, +}; +EXPORT_SYMBOL_GPL(wm831x_regmap_config); + /* * Instantiate the generic non-control parts of the device. */ @@ -1309,7 +1274,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID); if (ret < 0) { dev_err(wm831x->dev, "Failed to read parent ID: %d\n", ret); - goto err; + goto err_regmap; } switch (ret) { case 0x6204: @@ -1318,20 +1283,20 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) default: dev_err(wm831x->dev, "Device is not a WM831x: ID %x\n", ret); ret = -EINVAL; - goto err; + goto err_regmap; } ret = wm831x_reg_read(wm831x, WM831X_REVISION); if (ret < 0) { dev_err(wm831x->dev, "Failed to read revision: %d\n", ret); - goto err; + goto err_regmap; } rev = (ret & WM831X_PARENT_REV_MASK) >> WM831X_PARENT_REV_SHIFT; ret = wm831x_reg_read(wm831x, WM831X_RESET_ID); if (ret < 0) { dev_err(wm831x->dev, "Failed to read device ID: %d\n", ret); - goto err; + goto err_regmap; } /* Some engineering samples do not have the ID set, rely on @@ -1406,7 +1371,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) default: dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret); ret = -EINVAL; - goto err; + goto err_regmap; } /* This will need revisiting in future but is OK for all @@ -1420,7 +1385,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) ret = wm831x_reg_read(wm831x, WM831X_SECURITY_KEY); if (ret < 0) { dev_err(wm831x->dev, "Failed to read security key: %d\n", ret); - goto err; + goto err_regmap; } if (ret != 0) { dev_warn(wm831x->dev, "Security key had non-zero value %x\n", @@ -1433,7 +1398,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) ret = pdata->pre_init(wm831x); if (ret != 0) { dev_err(wm831x->dev, "pre_init() failed: %d\n", ret); - goto err; + goto err_regmap; } } @@ -1456,7 +1421,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) ret = wm831x_irq_init(wm831x, irq); if (ret != 0) - goto err; + goto err_regmap; wm831x_auxadc_init(wm831x); @@ -1552,8 +1517,9 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) err_irq: wm831x_irq_exit(wm831x); -err: +err_regmap: mfd_remove_devices(wm831x->dev); + regmap_exit(wm831x->regmap); kfree(wm831x); return ret; } @@ -1565,6 +1531,7 @@ void wm831x_device_exit(struct wm831x *wm831x) if (wm831x->irq_base) free_irq(wm831x->irq_base + WM831X_IRQ_AUXADC_DATA, wm831x); wm831x_irq_exit(wm831x); + regmap_exit(wm831x->regmap); kfree(wm831x); } diff --git a/trunk/drivers/mfd/wm831x-i2c.c b/trunk/drivers/mfd/wm831x-i2c.c index a06cbc739716..3ec6085d5fc0 100644 --- a/trunk/drivers/mfd/wm831x-i2c.c +++ b/trunk/drivers/mfd/wm831x-i2c.c @@ -18,67 +18,17 @@ #include #include #include +#include +#include #include #include -static int wm831x_i2c_read_device(struct wm831x *wm831x, unsigned short reg, - int bytes, void *dest) -{ - struct i2c_client *i2c = wm831x->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; -} - -/* Currently we allocate the write buffer on the stack; this is OK for - * small writes - if we need to do large writes this will need to be - * revised. - */ -static int wm831x_i2c_write_device(struct wm831x *wm831x, unsigned short reg, - int bytes, void *src) -{ - struct i2c_client *i2c = wm831x->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 wm831x_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm831x *wm831x; + int ret; wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL); if (wm831x == NULL) @@ -86,9 +36,15 @@ static int wm831x_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, wm831x); wm831x->dev = &i2c->dev; - wm831x->control_data = i2c; - wm831x->read_dev = wm831x_i2c_read_device; - wm831x->write_dev = wm831x_i2c_write_device; + + wm831x->regmap = regmap_init_i2c(i2c, &wm831x_regmap_config); + if (IS_ERR(wm831x->regmap)) { + ret = PTR_ERR(wm831x->regmap); + dev_err(wm831x->dev, "Failed to allocate register map: %d\n", + ret); + kfree(wm831x); + return ret; + } return wm831x_device_init(wm831x, id->driver_data, i2c->irq); } diff --git a/trunk/drivers/mfd/wm831x-spi.c b/trunk/drivers/mfd/wm831x-spi.c index eed8e4f7a5a1..dbe11472afce 100644 --- a/trunk/drivers/mfd/wm831x-spi.c +++ b/trunk/drivers/mfd/wm831x-spi.c @@ -16,58 +16,16 @@ #include #include #include +#include +#include #include -static int wm831x_spi_read_device(struct wm831x *wm831x, unsigned short reg, - int bytes, void *dest) -{ - u16 tx_val; - u16 *d = dest; - int r, ret; - - /* Go register at a time */ - for (r = reg; r < reg + (bytes / 2); r++) { - tx_val = r | 0x8000; - - ret = spi_write_then_read(wm831x->control_data, - (u8 *)&tx_val, 2, (u8 *)d, 2); - if (ret != 0) - return ret; - - *d = be16_to_cpu(*d); - - d++; - } - - return 0; -} - -static int wm831x_spi_write_device(struct wm831x *wm831x, unsigned short reg, - int bytes, void *src) -{ - struct spi_device *spi = wm831x->control_data; - u16 *s = src; - u16 data[2]; - int ret, r; - - /* Go register at a time */ - for (r = reg; r < reg + (bytes / 2); r++) { - data[0] = r; - data[1] = *s++; - - ret = spi_write(spi, (char *)&data, sizeof(data)); - if (ret != 0) - return ret; - } - - return 0; -} - static int __devinit wm831x_spi_probe(struct spi_device *spi) { struct wm831x *wm831x; enum wm831x_parent type; + int ret; /* Currently SPI support for ID tables is unmerged, we're faking it */ if (strcmp(spi->modalias, "wm8310") == 0) @@ -98,9 +56,15 @@ static int __devinit wm831x_spi_probe(struct spi_device *spi) dev_set_drvdata(&spi->dev, wm831x); wm831x->dev = &spi->dev; - wm831x->control_data = spi; - wm831x->read_dev = wm831x_spi_read_device; - wm831x->write_dev = wm831x_spi_write_device; + + wm831x->regmap = regmap_init_spi(wm831x->dev, &wm831x_regmap_config); + if (IS_ERR(wm831x->regmap)) { + ret = PTR_ERR(wm831x->regmap); + dev_err(wm831x->dev, "Failed to allocate register map: %d\n", + ret); + kfree(wm831x); + return ret; + } return wm831x_device_init(wm831x, type, spi->irq); } diff --git a/trunk/include/linux/mfd/wm831x/core.h b/trunk/include/linux/mfd/wm831x/core.h index 8dda8ded5cda..44acdb25681b 100644 --- a/trunk/include/linux/mfd/wm831x/core.h +++ b/trunk/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 diff --git a/trunk/include/linux/regmap.h b/trunk/include/linux/regmap.h index 449e2642da95..e2200f21c602 100644 --- a/trunk/include/linux/regmap.h +++ b/trunk/include/linux/regmap.h @@ -80,6 +80,8 @@ typedef int (*regmap_hw_read)(struct device *dev, /** * Description of a hardware bus for the register map infrastructure. * + * @list: Internal use. + * @type: Bus type, used to identify bus to be used for a device. * @write: Write operation. * @gather_write: Write operation with split register/value, return -ENOTSUPP * if not implemented on a given device. @@ -91,6 +93,8 @@ typedef int (*regmap_hw_read)(struct device *dev, * a read. */ struct regmap_bus { + struct list_head list; + struct bus_type *type; regmap_hw_write write; regmap_hw_gather_write gather_write; regmap_hw_read read; diff --git a/trunk/include/trace/events/regmap.h b/trunk/include/trace/events/regmap.h deleted file mode 100644 index e35e37c378c6..000000000000 --- a/trunk/include/trace/events/regmap.h +++ /dev/null @@ -1,112 +0,0 @@ -#undef TRACE_SYSTEM -#define TRACE_SYSTEM regmap - -#if !defined(_TRACE_REGMAP_H) || defined(TRACE_HEADER_MULTI_READ) -#define _TRACE_REGMAP_H - -#include -#include -#include - -struct regmap; - -/* - * Log register events - */ -DECLARE_EVENT_CLASS(regmap_reg, - - TP_PROTO(struct device *dev, unsigned int reg, - unsigned int val), - - TP_ARGS(dev, reg, val), - - TP_STRUCT__entry( - __string( name, dev_name(dev) ) - __field( unsigned int, reg ) - __field( unsigned int, val ) - ), - - TP_fast_assign( - __assign_str(name, dev_name(dev)); - __entry->reg = reg; - __entry->val = val; - ), - - TP_printk("%s reg=%x val=%x", __get_str(name), - (unsigned int)__entry->reg, - (unsigned int)__entry->val) -); - -DEFINE_EVENT(regmap_reg, regmap_reg_write, - - TP_PROTO(struct device *dev, unsigned int reg, - unsigned int val), - - TP_ARGS(dev, reg, val) - -); - -DEFINE_EVENT(regmap_reg, regmap_reg_read, - - TP_PROTO(struct device *dev, unsigned int reg, - unsigned int val), - - TP_ARGS(dev, reg, val) - -); - -DECLARE_EVENT_CLASS(regmap_block, - - TP_PROTO(struct device *dev, unsigned int reg, int count), - - TP_ARGS(dev, reg, count), - - TP_STRUCT__entry( - __string( name, dev_name(dev) ) - __field( unsigned int, reg ) - __field( int, count ) - ), - - TP_fast_assign( - __assign_str(name, dev_name(dev)); - __entry->reg = reg; - __entry->count = count; - ), - - TP_printk("%s reg=%x count=%d", __get_str(name), - (unsigned int)__entry->reg, - (int)__entry->count) -); - -DEFINE_EVENT(regmap_block, regmap_hw_read_start, - - TP_PROTO(struct device *dev, unsigned int reg, int count), - - TP_ARGS(dev, reg, count) -); - -DEFINE_EVENT(regmap_block, regmap_hw_read_done, - - TP_PROTO(struct device *dev, unsigned int reg, int count), - - TP_ARGS(dev, reg, count) -); - -DEFINE_EVENT(regmap_block, regmap_hw_write_start, - - TP_PROTO(struct device *dev, unsigned int reg, int count), - - TP_ARGS(dev, reg, count) -); - -DEFINE_EVENT(regmap_block, regmap_hw_write_done, - - TP_PROTO(struct device *dev, unsigned int reg, int count), - - TP_ARGS(dev, reg, count) -); - -#endif /* _TRACE_REGMAP_H */ - -/* This part must be outside protection */ -#include