From edd639dd8baf979cccd0badde33e5d4a23cc3814 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 5 Sep 2011 20:46:32 +0200 Subject: [PATCH] --- yaml --- r: 266982 b: refs/heads/master c: 069af897f9a3f70248d4a7ba3d3d439f7cd66d92 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/base/regmap/Makefile | 1 - trunk/drivers/base/regmap/internal.h | 69 ---- trunk/drivers/base/regmap/regmap-debugfs.c | 209 ---------- trunk/drivers/base/regmap/regmap-i2c.c | 3 +- trunk/drivers/base/regmap/regmap-spi.c | 4 +- trunk/drivers/base/regmap/regmap.c | 162 +++----- trunk/drivers/mfd/Kconfig | 3 - trunk/drivers/mfd/wm831x-core.c | 424 +++------------------ trunk/drivers/mfd/wm831x-i2c.c | 68 +++- trunk/drivers/mfd/wm831x-spi.c | 196 ++++++++-- trunk/drivers/mfd/wm8400-core.c | 106 ++++-- trunk/drivers/mfd/wm8994-core.c | 178 +++++++-- trunk/include/linux/mfd/wm831x/core.h | 9 +- trunk/include/linux/mfd/wm8400-private.h | 7 +- trunk/include/linux/mfd/wm8994/core.h | 9 +- trunk/include/linux/regmap.h | 7 + trunk/include/trace/events/regmap.h | 112 ------ 18 files changed, 570 insertions(+), 999 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 29f11df4afa5..10c793030de3 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: bbcf61ca8dcf093bd030a4dafb662b714676652d +refs/heads/master: 069af897f9a3f70248d4a7ba3d3d439f7cd66d92 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 a98493cde5c3..000000000000 --- a/trunk/drivers/base/regmap/internal.h +++ /dev/null @@ -1,69 +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); - - u8 read_flag_mask; - u8 write_flag_mask; -}; - -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 -static inline void regmap_debugfs_initcall(void) { } -static inline void regmap_debugfs_init(struct regmap *map) { } -static inline 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 6f397476e27c..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 + 1; 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 + 1; 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 38621ec87c05..c2231ff06cbc 100644 --- a/trunk/drivers/base/regmap/regmap-i2c.c +++ b/trunk/drivers/base/regmap/regmap-i2c.c @@ -90,9 +90,11 @@ 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, + .owner = THIS_MODULE, }; /** @@ -111,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 14132b829062..4deba0621bc7 100644 --- a/trunk/drivers/base/regmap/regmap-spi.c +++ b/trunk/drivers/base/regmap/regmap-spi.c @@ -47,9 +47,11 @@ 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, + .owner = THIS_MODULE, .read_flag_mask = 0x80, }; @@ -68,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 e7adfe70e425..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,14 +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; - - if (config->read_flag_mask || config->write_flag_mask) { - map->read_flag_mask = config->read_flag_mask; - map->write_flag_mask = config->write_flag_mask; - } else { - map->read_flag_mask = bus->read_flag_mask; - } switch (config->reg_bits) { case 4: @@ -205,13 +177,13 @@ struct regmap *regmap_init(struct device *dev, map->work_buf = kmalloc(map->format.buf_size, GFP_KERNEL); if (map->work_buf == NULL) { ret = -ENOMEM; - goto err_map; + goto err_bus; } - regmap_debugfs_init(map); - return map; +err_bus: + module_put(map->bus->owner); err_map: kfree(map); err: @@ -224,8 +196,8 @@ 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); } EXPORT_SYMBOL_GPL(regmap_exit); @@ -233,38 +205,19 @@ EXPORT_SYMBOL_GPL(regmap_exit); static int _regmap_raw_write(struct regmap *map, unsigned int reg, const void *val, size_t val_len) { - u8 *u8 = map->work_buf; 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); - u8[0] |= map->write_flag_mask; - - 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); @@ -278,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); @@ -376,23 +317,20 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, map->format.format_reg(map->work_buf, reg); /* - * Some buses or devices flag reads by setting the high bits in the + * Some buses flag reads by setting the high bits in the * register addresss; since it's always the high bits for all * current formats we can do this here rather than in * formatting. This may break if we get interesting formats. */ - u8[0] |= map->read_flag_mask; - - trace_regmap_hw_read_start(map->dev, reg, - val_len / map->format.val_bytes); + if (map->bus->read_flag_mask) + u8[0] |= map->bus->read_flag_mask; 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, @@ -404,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; } @@ -526,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 a67adcbd0fa1..21574bdf485f 100644 --- a/trunk/drivers/mfd/Kconfig +++ b/trunk/drivers/mfd/Kconfig @@ -404,7 +404,6 @@ 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 @@ -416,7 +415,6 @@ 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 @@ -490,7 +488,6 @@ 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/trunk/drivers/mfd/wm831x-core.c b/trunk/drivers/mfd/wm831x-core.c index 9338f8dcbb83..282e76ab678f 100644 --- a/trunk/drivers/mfd/wm831x-core.c +++ b/trunk/drivers/mfd/wm831x-core.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -161,350 +160,27 @@ int wm831x_reg_unlock(struct wm831x *wm831x) } EXPORT_SYMBOL_GPL(wm831x_reg_unlock); -static bool wm831x_reg_readable(struct device *dev, unsigned int reg) +static int wm831x_read(struct wm831x *wm831x, unsigned short reg, + int bytes, void *dest) { - switch (reg) { - case WM831X_RESET_ID: - case WM831X_REVISION: - case WM831X_PARENT_ID: - case WM831X_SYSVDD_CONTROL: - case WM831X_THERMAL_MONITORING: - case WM831X_POWER_STATE: - case WM831X_WATCHDOG: - case WM831X_ON_PIN_CONTROL: - case WM831X_RESET_CONTROL: - case WM831X_CONTROL_INTERFACE: - case WM831X_SECURITY_KEY: - case WM831X_SOFTWARE_SCRATCH: - case WM831X_OTP_CONTROL: - case WM831X_GPIO_LEVEL: - case WM831X_SYSTEM_STATUS: - case WM831X_ON_SOURCE: - case WM831X_OFF_SOURCE: - case WM831X_SYSTEM_INTERRUPTS: - case WM831X_INTERRUPT_STATUS_1: - case WM831X_INTERRUPT_STATUS_2: - case WM831X_INTERRUPT_STATUS_3: - case WM831X_INTERRUPT_STATUS_4: - case WM831X_INTERRUPT_STATUS_5: - case WM831X_IRQ_CONFIG: - case WM831X_SYSTEM_INTERRUPTS_MASK: - case WM831X_INTERRUPT_STATUS_1_MASK: - case WM831X_INTERRUPT_STATUS_2_MASK: - case WM831X_INTERRUPT_STATUS_3_MASK: - case WM831X_INTERRUPT_STATUS_4_MASK: - case WM831X_INTERRUPT_STATUS_5_MASK: - case WM831X_RTC_WRITE_COUNTER: - case WM831X_RTC_TIME_1: - case WM831X_RTC_TIME_2: - case WM831X_RTC_ALARM_1: - case WM831X_RTC_ALARM_2: - case WM831X_RTC_CONTROL: - case WM831X_RTC_TRIM: - case WM831X_TOUCH_CONTROL_1: - case WM831X_TOUCH_CONTROL_2: - case WM831X_TOUCH_DATA_X: - case WM831X_TOUCH_DATA_Y: - case WM831X_TOUCH_DATA_Z: - case WM831X_AUXADC_DATA: - case WM831X_AUXADC_CONTROL: - case WM831X_AUXADC_SOURCE: - case WM831X_COMPARATOR_CONTROL: - case WM831X_COMPARATOR_1: - case WM831X_COMPARATOR_2: - case WM831X_COMPARATOR_3: - case WM831X_COMPARATOR_4: - case WM831X_GPIO1_CONTROL: - case WM831X_GPIO2_CONTROL: - case WM831X_GPIO3_CONTROL: - case WM831X_GPIO4_CONTROL: - case WM831X_GPIO5_CONTROL: - case WM831X_GPIO6_CONTROL: - case WM831X_GPIO7_CONTROL: - case WM831X_GPIO8_CONTROL: - case WM831X_GPIO9_CONTROL: - case WM831X_GPIO10_CONTROL: - case WM831X_GPIO11_CONTROL: - case WM831X_GPIO12_CONTROL: - case WM831X_GPIO13_CONTROL: - case WM831X_GPIO14_CONTROL: - case WM831X_GPIO15_CONTROL: - case WM831X_GPIO16_CONTROL: - case WM831X_CHARGER_CONTROL_1: - case WM831X_CHARGER_CONTROL_2: - case WM831X_CHARGER_STATUS: - case WM831X_BACKUP_CHARGER_CONTROL: - case WM831X_STATUS_LED_1: - case WM831X_STATUS_LED_2: - case WM831X_CURRENT_SINK_1: - case WM831X_CURRENT_SINK_2: - case WM831X_DCDC_ENABLE: - case WM831X_LDO_ENABLE: - case WM831X_DCDC_STATUS: - case WM831X_LDO_STATUS: - case WM831X_DCDC_UV_STATUS: - case WM831X_LDO_UV_STATUS: - case WM831X_DC1_CONTROL_1: - case WM831X_DC1_CONTROL_2: - case WM831X_DC1_ON_CONFIG: - case WM831X_DC1_SLEEP_CONTROL: - case WM831X_DC1_DVS_CONTROL: - case WM831X_DC2_CONTROL_1: - case WM831X_DC2_CONTROL_2: - case WM831X_DC2_ON_CONFIG: - case WM831X_DC2_SLEEP_CONTROL: - case WM831X_DC2_DVS_CONTROL: - case WM831X_DC3_CONTROL_1: - case WM831X_DC3_CONTROL_2: - case WM831X_DC3_ON_CONFIG: - case WM831X_DC3_SLEEP_CONTROL: - case WM831X_DC4_CONTROL: - case WM831X_DC4_SLEEP_CONTROL: - case WM831X_EPE1_CONTROL: - case WM831X_EPE2_CONTROL: - case WM831X_LDO1_CONTROL: - case WM831X_LDO1_ON_CONTROL: - case WM831X_LDO1_SLEEP_CONTROL: - case WM831X_LDO2_CONTROL: - case WM831X_LDO2_ON_CONTROL: - case WM831X_LDO2_SLEEP_CONTROL: - case WM831X_LDO3_CONTROL: - case WM831X_LDO3_ON_CONTROL: - case WM831X_LDO3_SLEEP_CONTROL: - case WM831X_LDO4_CONTROL: - case WM831X_LDO4_ON_CONTROL: - case WM831X_LDO4_SLEEP_CONTROL: - case WM831X_LDO5_CONTROL: - case WM831X_LDO5_ON_CONTROL: - case WM831X_LDO5_SLEEP_CONTROL: - case WM831X_LDO6_CONTROL: - case WM831X_LDO6_ON_CONTROL: - case WM831X_LDO6_SLEEP_CONTROL: - case WM831X_LDO7_CONTROL: - case WM831X_LDO7_ON_CONTROL: - case WM831X_LDO7_SLEEP_CONTROL: - case WM831X_LDO8_CONTROL: - case WM831X_LDO8_ON_CONTROL: - case WM831X_LDO8_SLEEP_CONTROL: - case WM831X_LDO9_CONTROL: - case WM831X_LDO9_ON_CONTROL: - case WM831X_LDO9_SLEEP_CONTROL: - case WM831X_LDO10_CONTROL: - case WM831X_LDO10_ON_CONTROL: - case WM831X_LDO10_SLEEP_CONTROL: - case WM831X_LDO11_ON_CONTROL: - case WM831X_LDO11_SLEEP_CONTROL: - case WM831X_POWER_GOOD_SOURCE_1: - case WM831X_POWER_GOOD_SOURCE_2: - case WM831X_CLOCK_CONTROL_1: - case WM831X_CLOCK_CONTROL_2: - case WM831X_FLL_CONTROL_1: - case WM831X_FLL_CONTROL_2: - case WM831X_FLL_CONTROL_3: - case WM831X_FLL_CONTROL_4: - case WM831X_FLL_CONTROL_5: - case WM831X_UNIQUE_ID_1: - case WM831X_UNIQUE_ID_2: - case WM831X_UNIQUE_ID_3: - case WM831X_UNIQUE_ID_4: - case WM831X_UNIQUE_ID_5: - case WM831X_UNIQUE_ID_6: - case WM831X_UNIQUE_ID_7: - case WM831X_UNIQUE_ID_8: - case WM831X_FACTORY_OTP_ID: - case WM831X_FACTORY_OTP_1: - case WM831X_FACTORY_OTP_2: - case WM831X_FACTORY_OTP_3: - case WM831X_FACTORY_OTP_4: - case WM831X_FACTORY_OTP_5: - case WM831X_CUSTOMER_OTP_ID: - case WM831X_DC1_OTP_CONTROL: - case WM831X_DC2_OTP_CONTROL: - case WM831X_DC3_OTP_CONTROL: - case WM831X_LDO1_2_OTP_CONTROL: - case WM831X_LDO3_4_OTP_CONTROL: - case WM831X_LDO5_6_OTP_CONTROL: - case WM831X_LDO7_8_OTP_CONTROL: - case WM831X_LDO9_10_OTP_CONTROL: - case WM831X_LDO11_EPE_CONTROL: - case WM831X_GPIO1_OTP_CONTROL: - case WM831X_GPIO2_OTP_CONTROL: - case WM831X_GPIO3_OTP_CONTROL: - case WM831X_GPIO4_OTP_CONTROL: - case WM831X_GPIO5_OTP_CONTROL: - case WM831X_GPIO6_OTP_CONTROL: - case WM831X_DBE_CHECK_DATA: - return true; - default: - return false; - } -} + int ret, i; + u16 *buf = dest; -static bool wm831x_reg_writeable(struct device *dev, unsigned int reg) -{ - struct wm831x *wm831x = dev_get_drvdata(dev); + BUG_ON(bytes % 2); + BUG_ON(bytes <= 0); - if (wm831x_reg_locked(wm831x, reg)) - return false; + ret = wm831x->read_dev(wm831x, reg, bytes, dest); + if (ret < 0) + return ret; - switch (reg) { - case WM831X_SYSVDD_CONTROL: - case WM831X_THERMAL_MONITORING: - case WM831X_POWER_STATE: - case WM831X_WATCHDOG: - case WM831X_ON_PIN_CONTROL: - case WM831X_RESET_CONTROL: - case WM831X_CONTROL_INTERFACE: - case WM831X_SECURITY_KEY: - case WM831X_SOFTWARE_SCRATCH: - case WM831X_OTP_CONTROL: - case WM831X_GPIO_LEVEL: - case WM831X_INTERRUPT_STATUS_1: - case WM831X_INTERRUPT_STATUS_2: - case WM831X_INTERRUPT_STATUS_3: - case WM831X_INTERRUPT_STATUS_4: - case WM831X_INTERRUPT_STATUS_5: - case WM831X_IRQ_CONFIG: - case WM831X_SYSTEM_INTERRUPTS_MASK: - case WM831X_INTERRUPT_STATUS_1_MASK: - case WM831X_INTERRUPT_STATUS_2_MASK: - case WM831X_INTERRUPT_STATUS_3_MASK: - case WM831X_INTERRUPT_STATUS_4_MASK: - case WM831X_INTERRUPT_STATUS_5_MASK: - case WM831X_RTC_TIME_1: - case WM831X_RTC_TIME_2: - case WM831X_RTC_ALARM_1: - case WM831X_RTC_ALARM_2: - case WM831X_RTC_CONTROL: - case WM831X_RTC_TRIM: - case WM831X_TOUCH_CONTROL_1: - case WM831X_TOUCH_CONTROL_2: - case WM831X_AUXADC_CONTROL: - case WM831X_AUXADC_SOURCE: - case WM831X_COMPARATOR_CONTROL: - case WM831X_COMPARATOR_1: - case WM831X_COMPARATOR_2: - case WM831X_COMPARATOR_3: - case WM831X_COMPARATOR_4: - case WM831X_GPIO1_CONTROL: - case WM831X_GPIO2_CONTROL: - case WM831X_GPIO3_CONTROL: - case WM831X_GPIO4_CONTROL: - case WM831X_GPIO5_CONTROL: - case WM831X_GPIO6_CONTROL: - case WM831X_GPIO7_CONTROL: - case WM831X_GPIO8_CONTROL: - case WM831X_GPIO9_CONTROL: - case WM831X_GPIO10_CONTROL: - case WM831X_GPIO11_CONTROL: - case WM831X_GPIO12_CONTROL: - case WM831X_GPIO13_CONTROL: - case WM831X_GPIO14_CONTROL: - case WM831X_GPIO15_CONTROL: - case WM831X_GPIO16_CONTROL: - case WM831X_CHARGER_CONTROL_1: - case WM831X_CHARGER_CONTROL_2: - case WM831X_CHARGER_STATUS: - case WM831X_BACKUP_CHARGER_CONTROL: - case WM831X_STATUS_LED_1: - case WM831X_STATUS_LED_2: - case WM831X_CURRENT_SINK_1: - case WM831X_CURRENT_SINK_2: - case WM831X_DCDC_ENABLE: - case WM831X_LDO_ENABLE: - case WM831X_DC1_CONTROL_1: - case WM831X_DC1_CONTROL_2: - case WM831X_DC1_ON_CONFIG: - case WM831X_DC1_SLEEP_CONTROL: - case WM831X_DC1_DVS_CONTROL: - case WM831X_DC2_CONTROL_1: - case WM831X_DC2_CONTROL_2: - case WM831X_DC2_ON_CONFIG: - case WM831X_DC2_SLEEP_CONTROL: - case WM831X_DC2_DVS_CONTROL: - case WM831X_DC3_CONTROL_1: - case WM831X_DC3_CONTROL_2: - case WM831X_DC3_ON_CONFIG: - case WM831X_DC3_SLEEP_CONTROL: - case WM831X_DC4_CONTROL: - case WM831X_DC4_SLEEP_CONTROL: - case WM831X_EPE1_CONTROL: - case WM831X_EPE2_CONTROL: - case WM831X_LDO1_CONTROL: - case WM831X_LDO1_ON_CONTROL: - case WM831X_LDO1_SLEEP_CONTROL: - case WM831X_LDO2_CONTROL: - case WM831X_LDO2_ON_CONTROL: - case WM831X_LDO2_SLEEP_CONTROL: - case WM831X_LDO3_CONTROL: - case WM831X_LDO3_ON_CONTROL: - case WM831X_LDO3_SLEEP_CONTROL: - case WM831X_LDO4_CONTROL: - case WM831X_LDO4_ON_CONTROL: - case WM831X_LDO4_SLEEP_CONTROL: - case WM831X_LDO5_CONTROL: - case WM831X_LDO5_ON_CONTROL: - case WM831X_LDO5_SLEEP_CONTROL: - case WM831X_LDO6_CONTROL: - case WM831X_LDO6_ON_CONTROL: - case WM831X_LDO6_SLEEP_CONTROL: - case WM831X_LDO7_CONTROL: - case WM831X_LDO7_ON_CONTROL: - case WM831X_LDO7_SLEEP_CONTROL: - case WM831X_LDO8_CONTROL: - case WM831X_LDO8_ON_CONTROL: - case WM831X_LDO8_SLEEP_CONTROL: - case WM831X_LDO9_CONTROL: - case WM831X_LDO9_ON_CONTROL: - case WM831X_LDO9_SLEEP_CONTROL: - case WM831X_LDO10_CONTROL: - case WM831X_LDO10_ON_CONTROL: - case WM831X_LDO10_SLEEP_CONTROL: - case WM831X_LDO11_ON_CONTROL: - case WM831X_LDO11_SLEEP_CONTROL: - case WM831X_POWER_GOOD_SOURCE_1: - case WM831X_POWER_GOOD_SOURCE_2: - case WM831X_CLOCK_CONTROL_1: - case WM831X_CLOCK_CONTROL_2: - case WM831X_FLL_CONTROL_1: - case WM831X_FLL_CONTROL_2: - case WM831X_FLL_CONTROL_3: - case WM831X_FLL_CONTROL_4: - case WM831X_FLL_CONTROL_5: - return true; - default: - return false; - } -} + for (i = 0; i < bytes / 2; i++) { + buf[i] = be16_to_cpu(buf[i]); -static bool wm831x_reg_volatile(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM831X_SYSTEM_STATUS: - case WM831X_ON_SOURCE: - case WM831X_OFF_SOURCE: - case WM831X_GPIO_LEVEL: - case WM831X_SYSTEM_INTERRUPTS: - case WM831X_INTERRUPT_STATUS_1: - case WM831X_INTERRUPT_STATUS_2: - case WM831X_INTERRUPT_STATUS_3: - case WM831X_INTERRUPT_STATUS_4: - case WM831X_INTERRUPT_STATUS_5: - case WM831X_RTC_TIME_1: - case WM831X_RTC_TIME_2: - case WM831X_TOUCH_DATA_X: - case WM831X_TOUCH_DATA_Y: - case WM831X_TOUCH_DATA_Z: - case WM831X_AUXADC_DATA: - case WM831X_CHARGER_STATUS: - case WM831X_DCDC_STATUS: - case WM831X_LDO_STATUS: - case WM831X_DCDC_UV_STATUS: - case WM831X_LDO_UV_STATUS: - return true; - default: - return false; + dev_vdbg(wm831x->dev, "Read %04x from R%d(0x%x)\n", + buf[i], reg + i, reg + i); } + + return 0; } /** @@ -515,10 +191,14 @@ static bool wm831x_reg_volatile(struct device *dev, unsigned int reg) */ int wm831x_reg_read(struct wm831x *wm831x, unsigned short reg) { - unsigned int val; + unsigned short val; int ret; - ret = regmap_read(wm831x->regmap, reg, &val); + mutex_lock(&wm831x->io_lock); + + ret = wm831x_read(wm831x, reg, 2, &val); + + mutex_unlock(&wm831x->io_lock); if (ret < 0) return ret; @@ -538,7 +218,15 @@ EXPORT_SYMBOL_GPL(wm831x_reg_read); int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg, int count, u16 *buf) { - return regmap_bulk_read(wm831x->regmap, reg, buf, count); + int ret; + + mutex_lock(&wm831x->io_lock); + + ret = wm831x_read(wm831x, reg, count * 2, buf); + + mutex_unlock(&wm831x->io_lock); + + return ret; } EXPORT_SYMBOL_GPL(wm831x_bulk_read); @@ -546,7 +234,7 @@ static int wm831x_write(struct wm831x *wm831x, unsigned short reg, int bytes, void *src) { u16 *buf = src; - int i, ret; + int i; BUG_ON(bytes % 2); BUG_ON(bytes <= 0); @@ -557,10 +245,11 @@ 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); - ret = regmap_write(wm831x->regmap, reg + i, buf[i]); + + buf[i] = cpu_to_be16(buf[i]); } - return 0; + return wm831x->write_dev(wm831x, reg, bytes, src); } /** @@ -597,14 +286,20 @@ 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); - if (!wm831x_reg_locked(wm831x, reg)) - ret = regmap_update_bits(wm831x->regmap, reg, mask, val); - else - ret = -EPERM; + ret = wm831x_read(wm831x, reg, 2, &r); + if (ret < 0) + goto out; + + r &= ~mask; + r |= val & mask; + + ret = wm831x_write(wm831x, reg, 2, &r); +out: mutex_unlock(&wm831x->io_lock); return ret; @@ -1597,17 +1292,6 @@ static struct mfd_cell backlight_devs[] = { }, }; -struct regmap_config wm831x_regmap_config = { - .reg_bits = 16, - .val_bits = 16, - - .max_register = WM831X_DBE_CHECK_DATA, - .readable_reg = wm831x_reg_readable, - .writeable_reg = wm831x_reg_writeable, - .volatile_reg = wm831x_reg_volatile, -}; -EXPORT_SYMBOL_GPL(wm831x_regmap_config); - /* * Instantiate the generic non-control parts of the device. */ @@ -1625,7 +1309,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_regmap; + goto err; } switch (ret) { case 0x6204: @@ -1634,20 +1318,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_regmap; + goto err; } ret = wm831x_reg_read(wm831x, WM831X_REVISION); if (ret < 0) { dev_err(wm831x->dev, "Failed to read revision: %d\n", ret); - goto err_regmap; + goto err; } 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_regmap; + goto err; } /* Some engineering samples do not have the ID set, rely on @@ -1722,7 +1406,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_regmap; + goto err; } /* This will need revisiting in future but is OK for all @@ -1736,7 +1420,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_regmap; + goto err; } if (ret != 0) { dev_warn(wm831x->dev, "Security key had non-zero value %x\n", @@ -1749,7 +1433,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_regmap; + goto err; } } @@ -1772,7 +1456,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) ret = wm831x_irq_init(wm831x, irq); if (ret != 0) - goto err_regmap; + goto err; wm831x_auxadc_init(wm831x); @@ -1868,9 +1552,8 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) err_irq: wm831x_irq_exit(wm831x); -err_regmap: +err: mfd_remove_devices(wm831x->dev); - regmap_exit(wm831x->regmap); kfree(wm831x); return ret; } @@ -1882,7 +1565,6 @@ 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 3ec6085d5fc0..a06cbc739716 100644 --- a/trunk/drivers/mfd/wm831x-i2c.c +++ b/trunk/drivers/mfd/wm831x-i2c.c @@ -18,17 +18,67 @@ #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) @@ -36,15 +86,9 @@ static int wm831x_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, wm831x); wm831x->dev = &i2c->dev; - - 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; - } + wm831x->control_data = i2c; + wm831x->read_dev = wm831x_i2c_read_device; + wm831x->write_dev = wm831x_i2c_write_device; 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 5ea60cd860fc..eed8e4f7a5a1 100644 --- a/trunk/drivers/mfd/wm831x-spi.c +++ b/trunk/drivers/mfd/wm831x-spi.c @@ -16,19 +16,78 @@ #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) { - const struct spi_device_id *id = spi_get_device_id(spi); struct wm831x *wm831x; enum wm831x_parent type; - int ret; - type = (enum wm831x_parent)id->driver_data; + /* Currently SPI support for ID tables is unmerged, we're faking it */ + if (strcmp(spi->modalias, "wm8310") == 0) + type = WM8310; + else if (strcmp(spi->modalias, "wm8311") == 0) + type = WM8311; + else if (strcmp(spi->modalias, "wm8312") == 0) + type = WM8312; + else if (strcmp(spi->modalias, "wm8320") == 0) + type = WM8320; + else if (strcmp(spi->modalias, "wm8321") == 0) + type = WM8321; + else if (strcmp(spi->modalias, "wm8325") == 0) + type = WM8325; + else if (strcmp(spi->modalias, "wm8326") == 0) + type = WM8326; + else { + dev_err(&spi->dev, "Unknown device type\n"); + return -EINVAL; + } wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL); if (wm831x == NULL) @@ -39,15 +98,9 @@ static int __devinit wm831x_spi_probe(struct spi_device *spi) dev_set_drvdata(&spi->dev, wm831x); wm831x->dev = &spi->dev; - - wm831x->regmap = regmap_init_spi(spi, &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; - } + wm831x->control_data = spi; + wm831x->read_dev = wm831x_spi_read_device; + wm831x->write_dev = wm831x_spi_write_device; return wm831x_device_init(wm831x, type, spi->irq); } @@ -73,26 +126,79 @@ static const struct dev_pm_ops wm831x_spi_pm = { .suspend = wm831x_spi_suspend, }; -static const struct spi_device_id wm831x_spi_ids[] = { - { "wm8310", WM8310 }, - { "wm8311", WM8311 }, - { "wm8312", WM8312 }, - { "wm8320", WM8320 }, - { "wm8321", WM8321 }, - { "wm8325", WM8325 }, - { "wm8326", WM8326 }, - { }, +static struct spi_driver wm8310_spi_driver = { + .driver = { + .name = "wm8310", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + .pm = &wm831x_spi_pm, + }, + .probe = wm831x_spi_probe, + .remove = __devexit_p(wm831x_spi_remove), +}; + +static struct spi_driver wm8311_spi_driver = { + .driver = { + .name = "wm8311", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + .pm = &wm831x_spi_pm, + }, + .probe = wm831x_spi_probe, + .remove = __devexit_p(wm831x_spi_remove), +}; + +static struct spi_driver wm8312_spi_driver = { + .driver = { + .name = "wm8312", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + .pm = &wm831x_spi_pm, + }, + .probe = wm831x_spi_probe, + .remove = __devexit_p(wm831x_spi_remove), +}; + +static struct spi_driver wm8320_spi_driver = { + .driver = { + .name = "wm8320", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + .pm = &wm831x_spi_pm, + }, + .probe = wm831x_spi_probe, + .remove = __devexit_p(wm831x_spi_remove), +}; + +static struct spi_driver wm8321_spi_driver = { + .driver = { + .name = "wm8321", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + .pm = &wm831x_spi_pm, + }, + .probe = wm831x_spi_probe, + .remove = __devexit_p(wm831x_spi_remove), }; -MODULE_DEVICE_TABLE(spi, wm831x_spi_id); -static struct spi_driver wm831x_spi_driver = { +static struct spi_driver wm8325_spi_driver = { .driver = { - .name = "wm831x", + .name = "wm8325", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + .pm = &wm831x_spi_pm, + }, + .probe = wm831x_spi_probe, + .remove = __devexit_p(wm831x_spi_remove), +}; + +static struct spi_driver wm8326_spi_driver = { + .driver = { + .name = "wm8326", .bus = &spi_bus_type, .owner = THIS_MODULE, .pm = &wm831x_spi_pm, }, - .id_table = wm831x_spi_ids, .probe = wm831x_spi_probe, .remove = __devexit_p(wm831x_spi_remove), }; @@ -101,9 +207,33 @@ static int __init wm831x_spi_init(void) { int ret; - ret = spi_register_driver(&wm831x_spi_driver); + ret = spi_register_driver(&wm8310_spi_driver); + if (ret != 0) + pr_err("Failed to register WM8310 SPI driver: %d\n", ret); + + ret = spi_register_driver(&wm8311_spi_driver); + if (ret != 0) + pr_err("Failed to register WM8311 SPI driver: %d\n", ret); + + ret = spi_register_driver(&wm8312_spi_driver); + if (ret != 0) + pr_err("Failed to register WM8312 SPI driver: %d\n", ret); + + ret = spi_register_driver(&wm8320_spi_driver); + if (ret != 0) + pr_err("Failed to register WM8320 SPI driver: %d\n", ret); + + ret = spi_register_driver(&wm8321_spi_driver); + if (ret != 0) + pr_err("Failed to register WM8321 SPI driver: %d\n", ret); + + ret = spi_register_driver(&wm8325_spi_driver); + if (ret != 0) + pr_err("Failed to register WM8325 SPI driver: %d\n", ret); + + ret = spi_register_driver(&wm8326_spi_driver); if (ret != 0) - pr_err("Failed to register WM831x SPI driver: %d\n", ret); + pr_err("Failed to register WM8326 SPI driver: %d\n", ret); return 0; } @@ -111,7 +241,13 @@ subsys_initcall(wm831x_spi_init); static void __exit wm831x_spi_exit(void) { - spi_unregister_driver(&wm831x_spi_driver); + spi_unregister_driver(&wm8326_spi_driver); + spi_unregister_driver(&wm8325_spi_driver); + spi_unregister_driver(&wm8321_spi_driver); + spi_unregister_driver(&wm8320_spi_driver); + spi_unregister_driver(&wm8312_spi_driver); + spi_unregister_driver(&wm8311_spi_driver); + spi_unregister_driver(&wm8310_spi_driver); } module_exit(wm831x_spi_exit); diff --git a/trunk/drivers/mfd/wm8400-core.c b/trunk/drivers/mfd/wm8400-core.c index e06ba9440cdb..597f82edacaa 100644 --- a/trunk/drivers/mfd/wm8400-core.c +++ b/trunk/drivers/mfd/wm8400-core.c @@ -13,13 +13,11 @@ */ #include -#include #include #include #include #include #include -#include #include static struct { @@ -125,9 +123,14 @@ 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 = regmap_bulk_read(wm8400->regmap, reg, dest, - num_regs); - return ret; + 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; } /* Otherwise use the cache */ @@ -146,11 +149,14 @@ 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]; - ret = regmap_write(wm8400->regmap, reg, src[i]); - if (ret != 0) - return ret; + src[i] = cpu_to_be16(src[i]); } + /* Do the actual I/O */ + ret = wm8400->write_dev(wm8400->io_data, reg, num_regs, src); + if (ret != 0) + return -EIO; + return 0; } @@ -264,14 +270,14 @@ static int wm8400_init(struct wm8400 *wm8400, dev_set_drvdata(wm8400->dev, wm8400); /* Check that this is actually a WM8400 */ - ret = regmap_read(wm8400->regmap, WM8400_RESET_ID, &i); + ret = wm8400->read_dev(wm8400->io_data, WM8400_RESET_ID, 1, ®); if (ret != 0) { dev_err(wm8400->dev, "Chip ID register read failed\n"); return -EIO; } - if (i != reg_data[WM8400_RESET_ID].default_val) { + if (be16_to_cpu(reg) != reg_data[WM8400_RESET_ID].default_val) { dev_err(wm8400->dev, "Device is not a WM8400, ID is %x\n", - reg); + be16_to_cpu(reg)); return -ENODEV; } @@ -279,8 +285,9 @@ 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 = regmap_raw_read(wm8400->regmap, 0, wm8400->reg_cache, - ARRAY_SIZE(wm8400->reg_cache)); + ret = wm8400->read_dev(wm8400->io_data, 0, + ARRAY_SIZE(wm8400->reg_cache), + wm8400->reg_cache); if (ret != 0) { dev_err(wm8400->dev, "Register cache read failed\n"); return -EIO; @@ -330,13 +337,60 @@ static void wm8400_release(struct wm8400 *wm8400) mfd_remove_devices(wm8400->dev); } -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_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 int wm8400_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -349,23 +403,18 @@ static int wm8400_i2c_probe(struct i2c_client *i2c, goto err; } - wm8400->regmap = regmap_init_i2c(i2c, &wm8400_regmap_config); - if (IS_ERR(wm8400->regmap)) { - ret = PTR_ERR(wm8400->regmap); - goto struct_err; - } - + wm8400->io_data = i2c; + wm8400->read_dev = wm8400_i2c_read; + wm8400->write_dev = wm8400_i2c_write; wm8400->dev = &i2c->dev; i2c_set_clientdata(i2c, wm8400); ret = wm8400_init(wm8400, i2c->dev.platform_data); if (ret != 0) - goto map_err; + goto struct_err; return 0; -map_err: - regmap_exit(wm8400->regmap); struct_err: kfree(wm8400); err: @@ -377,7 +426,6 @@ 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/trunk/drivers/mfd/wm8994-core.c b/trunk/drivers/mfd/wm8994-core.c index bfde4e8ec638..96479c9b1728 100644 --- a/trunk/drivers/mfd/wm8994-core.c +++ b/trunk/drivers/mfd/wm8994-core.c @@ -16,11 +16,9 @@ #include #include #include -#include #include #include #include -#include #include #include @@ -31,7 +29,22 @@ static int wm8994_read(struct wm8994 *wm8994, unsigned short reg, int bytes, void *dest) { - return regmap_raw_read(wm8994->regmap, reg, dest, bytes); + 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; } /** @@ -42,15 +55,19 @@ static int wm8994_read(struct wm8994 *wm8994, unsigned short reg, */ int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg) { - unsigned int val; + unsigned short val; int ret; - ret = regmap_read(wm8994->regmap, reg, &val); + mutex_lock(&wm8994->io_lock); + + ret = wm8994_read(wm8994, reg, 2, &val); + + mutex_unlock(&wm8994->io_lock); if (ret < 0) return ret; else - return val; + return be16_to_cpu(val); } EXPORT_SYMBOL_GPL(wm8994_reg_read); @@ -65,13 +82,33 @@ EXPORT_SYMBOL_GPL(wm8994_reg_read); int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg, int count, u16 *buf) { - return regmap_bulk_read(wm8994->regmap, reg, buf, count); + int ret; + + mutex_lock(&wm8994->io_lock); + + ret = wm8994_read(wm8994, reg, count * 2, buf); + + mutex_unlock(&wm8994->io_lock); + + return ret; } +EXPORT_SYMBOL_GPL(wm8994_bulk_read); static int wm8994_write(struct wm8994 *wm8994, unsigned short reg, int bytes, const void *src) { - return regmap_raw_write(wm8994->regmap, reg, src, bytes); + 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); } /** @@ -84,7 +121,17 @@ static int wm8994_write(struct wm8994 *wm8994, unsigned short reg, int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg, unsigned short val) { - return regmap_write(wm8994->regmap, reg, 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; } EXPORT_SYMBOL_GPL(wm8994_reg_write); @@ -99,7 +146,15 @@ EXPORT_SYMBOL_GPL(wm8994_reg_write); int wm8994_bulk_write(struct wm8994 *wm8994, unsigned short reg, int count, const u16 *buf) { - return regmap_raw_write(wm8994->regmap, reg, buf, count * sizeof(u16)); + int ret; + + mutex_lock(&wm8994->io_lock); + + ret = wm8994_write(wm8994, reg, count * 2, buf); + + mutex_unlock(&wm8994->io_lock); + + return ret; } EXPORT_SYMBOL_GPL(wm8994_bulk_write); @@ -114,7 +169,28 @@ EXPORT_SYMBOL_GPL(wm8994_bulk_write); int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg, unsigned short mask, unsigned short val) { - return regmap_update_bits(wm8994->regmap, reg, mask, 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; } EXPORT_SYMBOL_GPL(wm8994_set_bits); @@ -302,11 +378,6 @@ 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. */ @@ -316,6 +387,7 @@ 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 */ @@ -325,7 +397,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_regmap; + goto err; } switch (wm8994->type) { @@ -337,7 +409,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) break; default: BUG(); - goto err_regmap; + goto err; } wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) * @@ -345,7 +417,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) GFP_KERNEL); if (!wm8994->supplies) { ret = -ENOMEM; - goto err_regmap; + goto err; } switch (wm8994->type) { @@ -359,7 +431,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) break; default: BUG(); - goto err_regmap; + goto err; } ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies, @@ -482,8 +554,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) regulator_bulk_free(wm8994->num_supplies, wm8994->supplies); err_supplies: kfree(wm8994->supplies); -err_regmap: - regmap_exit(wm8994->regmap); +err: mfd_remove_devices(wm8994->dev); kfree(wm8994); return ret; @@ -498,15 +569,62 @@ 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) @@ -514,18 +632,12 @@ 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/trunk/include/linux/mfd/wm831x/core.h b/trunk/include/linux/mfd/wm831x/core.h index 44acdb25681b..8dda8ded5cda 100644 --- a/trunk/include/linux/mfd/wm831x/core.h +++ b/trunk/include/linux/mfd/wm831x/core.h @@ -18,7 +18,6 @@ #include #include #include -#include /* * Register values. @@ -362,8 +361,12 @@ 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); - struct regmap *regmap; + void *control_data; int irq; /* Our chip IRQ */ struct mutex irq_lock; @@ -413,6 +416,4 @@ 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/mfd/wm8400-private.h b/trunk/include/linux/mfd/wm8400-private.h index 0147b6968510..2aab4e93a5c9 100644 --- a/trunk/include/linux/mfd/wm8400-private.h +++ b/trunk/include/linux/mfd/wm8400-private.h @@ -25,15 +25,16 @@ #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; - struct regmap *regmap; + void *io_data; u16 reg_cache[WM8400_REGISTER_COUNT]; diff --git a/trunk/include/linux/mfd/wm8994/core.h b/trunk/include/linux/mfd/wm8994/core.h index 45df450d869f..f0b69cdae41c 100644 --- a/trunk/include/linux/mfd/wm8994/core.h +++ b/trunk/include/linux/mfd/wm8994/core.h @@ -24,7 +24,6 @@ enum wm8994_type { struct regulator_dev; struct regulator_bulk_data; -struct regmap; #define WM8994_NUM_GPIO_REGS 11 #define WM8994_NUM_LDO_REGS 2 @@ -51,12 +50,18 @@ struct regmap; #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; - struct regmap *regmap; + 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; int gpio_base; int irq_base; diff --git a/trunk/include/linux/regmap.h b/trunk/include/linux/regmap.h index 18d4afaac166..003c05349ae5 100644 --- a/trunk/include/linux/regmap.h +++ b/trunk/include/linux/regmap.h @@ -89,18 +89,25 @@ 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. * @read: Read operation. Data is returned in the buffer used to transmit * data. + * @owner: Module with the bus implementation, used to pin the implementation + * in memory. * @read_flag_mask: Mask to be set in the top byte of the register when doing * 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; + struct module *owner; u8 read_flag_mask; }; 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