Commit fec4fe26 authored by Mark Brown's avatar Mark Brown

Merge branch 'regmap-mfd' into regmap-next

parents ae130d22 50eeef5d
...@@ -404,6 +404,7 @@ config MFD_WM831X_I2C ...@@ -404,6 +404,7 @@ config MFD_WM831X_I2C
bool "Support Wolfson Microelectronics WM831x/2x PMICs with I2C" bool "Support Wolfson Microelectronics WM831x/2x PMICs with I2C"
select MFD_CORE select MFD_CORE
select MFD_WM831X select MFD_WM831X
select REGMAP_I2C
depends on I2C=y && GENERIC_HARDIRQS depends on I2C=y && GENERIC_HARDIRQS
help help
Support for the Wolfson Microelecronics WM831x and WM832x PMICs Support for the Wolfson Microelecronics WM831x and WM832x PMICs
...@@ -415,6 +416,7 @@ config MFD_WM831X_SPI ...@@ -415,6 +416,7 @@ config MFD_WM831X_SPI
bool "Support Wolfson Microelectronics WM831x/2x PMICs with SPI" bool "Support Wolfson Microelectronics WM831x/2x PMICs with SPI"
select MFD_CORE select MFD_CORE
select MFD_WM831X select MFD_WM831X
select REGMAP_SPI
depends on SPI_MASTER && GENERIC_HARDIRQS depends on SPI_MASTER && GENERIC_HARDIRQS
help help
Support for the Wolfson Microelecronics WM831x and WM832x PMICs Support for the Wolfson Microelecronics WM831x and WM832x PMICs
...@@ -488,6 +490,7 @@ config MFD_WM8350_I2C ...@@ -488,6 +490,7 @@ config MFD_WM8350_I2C
config MFD_WM8994 config MFD_WM8994
bool "Support Wolfson Microelectronics WM8994" bool "Support Wolfson Microelectronics WM8994"
select MFD_CORE select MFD_CORE
select REGMAP_I2C
depends on I2C=y && GENERIC_HARDIRQS depends on I2C=y && GENERIC_HARDIRQS
help help
The WM8994 is a highly integrated hi-fi CODEC designed for The WM8994 is a highly integrated hi-fi CODEC designed for
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/err.h>
#include <linux/mfd/wm831x/core.h> #include <linux/mfd/wm831x/core.h>
#include <linux/mfd/wm831x/pdata.h> #include <linux/mfd/wm831x/pdata.h>
...@@ -160,27 +161,350 @@ int wm831x_reg_unlock(struct wm831x *wm831x) ...@@ -160,27 +161,350 @@ int wm831x_reg_unlock(struct wm831x *wm831x)
} }
EXPORT_SYMBOL_GPL(wm831x_reg_unlock); EXPORT_SYMBOL_GPL(wm831x_reg_unlock);
static int wm831x_read(struct wm831x *wm831x, unsigned short reg, static bool wm831x_reg_readable(struct device *dev, unsigned int reg)
int bytes, void *dest)
{ {
int ret, i; switch (reg) {
u16 *buf = dest; case WM831X_RESET_ID:
case WM831X_REVISION:
BUG_ON(bytes % 2); case WM831X_PARENT_ID:
BUG_ON(bytes <= 0); 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;
}
}
ret = wm831x->read_dev(wm831x, reg, bytes, dest); static bool wm831x_reg_writeable(struct device *dev, unsigned int reg)
if (ret < 0) {
return ret; struct wm831x *wm831x = dev_get_drvdata(dev);
for (i = 0; i < bytes / 2; i++) { if (wm831x_reg_locked(wm831x, reg))
buf[i] = be16_to_cpu(buf[i]); return false;
dev_vdbg(wm831x->dev, "Read %04x from R%d(0x%x)\n", switch (reg) {
buf[i], reg + i, reg + i); 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;
} }
}
return 0; 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;
}
} }
/** /**
...@@ -191,14 +515,10 @@ static int wm831x_read(struct wm831x *wm831x, unsigned short reg, ...@@ -191,14 +515,10 @@ static int wm831x_read(struct wm831x *wm831x, unsigned short reg,
*/ */
int wm831x_reg_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; int ret;
mutex_lock(&wm831x->io_lock); ret = regmap_read(wm831x->regmap, reg, &val);
ret = wm831x_read(wm831x, reg, 2, &val);
mutex_unlock(&wm831x->io_lock);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -218,15 +538,7 @@ EXPORT_SYMBOL_GPL(wm831x_reg_read); ...@@ -218,15 +538,7 @@ EXPORT_SYMBOL_GPL(wm831x_reg_read);
int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg, int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg,
int count, u16 *buf) int count, u16 *buf)
{ {
int ret; return regmap_bulk_read(wm831x->regmap, reg, buf, count);
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); EXPORT_SYMBOL_GPL(wm831x_bulk_read);
...@@ -234,7 +546,7 @@ static int wm831x_write(struct wm831x *wm831x, unsigned short reg, ...@@ -234,7 +546,7 @@ static int wm831x_write(struct wm831x *wm831x, unsigned short reg,
int bytes, void *src) int bytes, void *src)
{ {
u16 *buf = src; u16 *buf = src;
int i; int i, ret;
BUG_ON(bytes % 2); BUG_ON(bytes % 2);
BUG_ON(bytes <= 0); BUG_ON(bytes <= 0);
...@@ -245,11 +557,10 @@ static int wm831x_write(struct wm831x *wm831x, unsigned short reg, ...@@ -245,11 +557,10 @@ static int wm831x_write(struct wm831x *wm831x, unsigned short reg,
dev_vdbg(wm831x->dev, "Write %04x to R%d(0x%x)\n", dev_vdbg(wm831x->dev, "Write %04x to R%d(0x%x)\n",
buf[i], reg + i, reg + i); buf[i], reg + i, reg + i);
ret = regmap_write(wm831x->regmap, reg + i, buf[i]);
buf[i] = cpu_to_be16(buf[i]);
} }
return wm831x->write_dev(wm831x, reg, bytes, src); return 0;
} }
/** /**
...@@ -286,20 +597,14 @@ int wm831x_set_bits(struct wm831x *wm831x, unsigned short reg, ...@@ -286,20 +597,14 @@ int wm831x_set_bits(struct wm831x *wm831x, unsigned short reg,
unsigned short mask, unsigned short val) unsigned short mask, unsigned short val)
{ {
int ret; int ret;
u16 r;
mutex_lock(&wm831x->io_lock); mutex_lock(&wm831x->io_lock);
ret = wm831x_read(wm831x, reg, 2, &r); if (!wm831x_reg_locked(wm831x, reg))
if (ret < 0) ret = regmap_update_bits(wm831x->regmap, reg, mask, val);
goto out; else
ret = -EPERM;
r &= ~mask;
r |= val & mask;
ret = wm831x_write(wm831x, reg, 2, &r);
out:
mutex_unlock(&wm831x->io_lock); mutex_unlock(&wm831x->io_lock);
return ret; return ret;
...@@ -1292,6 +1597,17 @@ static struct mfd_cell backlight_devs[] = { ...@@ -1292,6 +1597,17 @@ 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. * Instantiate the generic non-control parts of the device.
*/ */
...@@ -1309,7 +1625,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) ...@@ -1309,7 +1625,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID); ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID);
if (ret < 0) { if (ret < 0) {
dev_err(wm831x->dev, "Failed to read parent ID: %d\n", ret); dev_err(wm831x->dev, "Failed to read parent ID: %d\n", ret);
goto err; goto err_regmap;
} }
switch (ret) { switch (ret) {
case 0x6204: case 0x6204:
...@@ -1318,20 +1634,20 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) ...@@ -1318,20 +1634,20 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
default: default:
dev_err(wm831x->dev, "Device is not a WM831x: ID %x\n", ret); dev_err(wm831x->dev, "Device is not a WM831x: ID %x\n", ret);
ret = -EINVAL; ret = -EINVAL;
goto err; goto err_regmap;
} }
ret = wm831x_reg_read(wm831x, WM831X_REVISION); ret = wm831x_reg_read(wm831x, WM831X_REVISION);
if (ret < 0) { if (ret < 0) {
dev_err(wm831x->dev, "Failed to read revision: %d\n", ret); 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; rev = (ret & WM831X_PARENT_REV_MASK) >> WM831X_PARENT_REV_SHIFT;
ret = wm831x_reg_read(wm831x, WM831X_RESET_ID); ret = wm831x_reg_read(wm831x, WM831X_RESET_ID);
if (ret < 0) { if (ret < 0) {
dev_err(wm831x->dev, "Failed to read device ID: %d\n", ret); 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 /* Some engineering samples do not have the ID set, rely on
...@@ -1406,7 +1722,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) ...@@ -1406,7 +1722,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
default: default:
dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret); dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret);
ret = -EINVAL; ret = -EINVAL;
goto err; goto err_regmap;
} }
/* This will need revisiting in future but is OK for all /* This will need revisiting in future but is OK for all
...@@ -1420,7 +1736,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) ...@@ -1420,7 +1736,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
ret = wm831x_reg_read(wm831x, WM831X_SECURITY_KEY); ret = wm831x_reg_read(wm831x, WM831X_SECURITY_KEY);
if (ret < 0) { if (ret < 0) {
dev_err(wm831x->dev, "Failed to read security key: %d\n", ret); dev_err(wm831x->dev, "Failed to read security key: %d\n", ret);
goto err; goto err_regmap;
} }
if (ret != 0) { if (ret != 0) {
dev_warn(wm831x->dev, "Security key had non-zero value %x\n", dev_warn(wm831x->dev, "Security key had non-zero value %x\n",
...@@ -1433,7 +1749,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) ...@@ -1433,7 +1749,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
ret = pdata->pre_init(wm831x); ret = pdata->pre_init(wm831x);
if (ret != 0) { if (ret != 0) {
dev_err(wm831x->dev, "pre_init() failed: %d\n", ret); dev_err(wm831x->dev, "pre_init() failed: %d\n", ret);
goto err; goto err_regmap;
} }
} }
...@@ -1456,7 +1772,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) ...@@ -1456,7 +1772,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
ret = wm831x_irq_init(wm831x, irq); ret = wm831x_irq_init(wm831x, irq);
if (ret != 0) if (ret != 0)
goto err; goto err_regmap;
wm831x_auxadc_init(wm831x); wm831x_auxadc_init(wm831x);
...@@ -1552,8 +1868,9 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) ...@@ -1552,8 +1868,9 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
err_irq: err_irq:
wm831x_irq_exit(wm831x); wm831x_irq_exit(wm831x);
err: err_regmap:
mfd_remove_devices(wm831x->dev); mfd_remove_devices(wm831x->dev);
regmap_exit(wm831x->regmap);
kfree(wm831x); kfree(wm831x);
return ret; return ret;
} }
...@@ -1565,6 +1882,7 @@ void wm831x_device_exit(struct wm831x *wm831x) ...@@ -1565,6 +1882,7 @@ void wm831x_device_exit(struct wm831x *wm831x)
if (wm831x->irq_base) if (wm831x->irq_base)
free_irq(wm831x->irq_base + WM831X_IRQ_AUXADC_DATA, wm831x); free_irq(wm831x->irq_base + WM831X_IRQ_AUXADC_DATA, wm831x);
wm831x_irq_exit(wm831x); wm831x_irq_exit(wm831x);
regmap_exit(wm831x->regmap);
kfree(wm831x); kfree(wm831x);
} }
......
...@@ -18,67 +18,17 @@ ...@@ -18,67 +18,17 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/err.h>
#include <linux/regmap.h>
#include <linux/mfd/wm831x/core.h> #include <linux/mfd/wm831x/core.h>
#include <linux/mfd/wm831x/pdata.h> #include <linux/mfd/wm831x/pdata.h>
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 *)&reg;
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, static int wm831x_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct wm831x *wm831x; struct wm831x *wm831x;
int ret;
wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL); wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
if (wm831x == NULL) if (wm831x == NULL)
...@@ -86,9 +36,15 @@ static int wm831x_i2c_probe(struct i2c_client *i2c, ...@@ -86,9 +36,15 @@ static int wm831x_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, wm831x); i2c_set_clientdata(i2c, wm831x);
wm831x->dev = &i2c->dev; wm831x->dev = &i2c->dev;
wm831x->control_data = i2c;
wm831x->read_dev = wm831x_i2c_read_device; wm831x->regmap = regmap_init_i2c(i2c, &wm831x_regmap_config);
wm831x->write_dev = wm831x_i2c_write_device; 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); return wm831x_device_init(wm831x, id->driver_data, i2c->irq);
} }
......
...@@ -16,78 +16,19 @@ ...@@ -16,78 +16,19 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/regmap.h>
#include <linux/err.h>
#include <linux/mfd/wm831x/core.h> #include <linux/mfd/wm831x/core.h>
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) static int __devinit wm831x_spi_probe(struct spi_device *spi)
{ {
const struct spi_device_id *id = spi_get_device_id(spi);
struct wm831x *wm831x; struct wm831x *wm831x;
enum wm831x_parent type; enum wm831x_parent type;
int ret;
/* Currently SPI support for ID tables is unmerged, we're faking it */ type = (enum wm831x_parent)id->driver_data;
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); wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
if (wm831x == NULL) if (wm831x == NULL)
...@@ -98,9 +39,15 @@ static int __devinit wm831x_spi_probe(struct spi_device *spi) ...@@ -98,9 +39,15 @@ static int __devinit wm831x_spi_probe(struct spi_device *spi)
dev_set_drvdata(&spi->dev, wm831x); dev_set_drvdata(&spi->dev, wm831x);
wm831x->dev = &spi->dev; wm831x->dev = &spi->dev;
wm831x->control_data = spi;
wm831x->read_dev = wm831x_spi_read_device; wm831x->regmap = regmap_init_spi(spi, &wm831x_regmap_config);
wm831x->write_dev = wm831x_spi_write_device; 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); return wm831x_device_init(wm831x, type, spi->irq);
} }
...@@ -126,79 +73,26 @@ static const struct dev_pm_ops wm831x_spi_pm = { ...@@ -126,79 +73,26 @@ static const struct dev_pm_ops wm831x_spi_pm = {
.suspend = wm831x_spi_suspend, .suspend = wm831x_spi_suspend,
}; };
static struct spi_driver wm8310_spi_driver = { static const struct spi_device_id wm831x_spi_ids[] = {
.driver = { { "wm8310", WM8310 },
.name = "wm8310", { "wm8311", WM8311 },
.bus = &spi_bus_type, { "wm8312", WM8312 },
.owner = THIS_MODULE, { "wm8320", WM8320 },
.pm = &wm831x_spi_pm, { "wm8321", WM8321 },
}, { "wm8325", WM8325 },
.probe = wm831x_spi_probe, { "wm8326", WM8326 },
.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 wm8325_spi_driver = { static struct spi_driver wm831x_spi_driver = {
.driver = { .driver = {
.name = "wm8325", .name = "wm831x",
.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, .bus = &spi_bus_type,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &wm831x_spi_pm, .pm = &wm831x_spi_pm,
}, },
.id_table = wm831x_spi_ids,
.probe = wm831x_spi_probe, .probe = wm831x_spi_probe,
.remove = __devexit_p(wm831x_spi_remove), .remove = __devexit_p(wm831x_spi_remove),
}; };
...@@ -207,33 +101,9 @@ static int __init wm831x_spi_init(void) ...@@ -207,33 +101,9 @@ static int __init wm831x_spi_init(void)
{ {
int ret; int ret;
ret = spi_register_driver(&wm8310_spi_driver); ret = spi_register_driver(&wm831x_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) if (ret != 0)
pr_err("Failed to register WM8326 SPI driver: %d\n", ret); pr_err("Failed to register WM831x SPI driver: %d\n", ret);
return 0; return 0;
} }
...@@ -241,13 +111,7 @@ subsys_initcall(wm831x_spi_init); ...@@ -241,13 +111,7 @@ subsys_initcall(wm831x_spi_init);
static void __exit wm831x_spi_exit(void) static void __exit wm831x_spi_exit(void)
{ {
spi_unregister_driver(&wm8326_spi_driver); spi_unregister_driver(&wm831x_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); module_exit(wm831x_spi_exit);
......
...@@ -13,11 +13,13 @@ ...@@ -13,11 +13,13 @@
*/ */
#include <linux/bug.h> #include <linux/bug.h>
#include <linux/err.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
#include <linux/mfd/wm8400-private.h> #include <linux/mfd/wm8400-private.h>
#include <linux/mfd/wm8400-audio.h> #include <linux/mfd/wm8400-audio.h>
#include <linux/regmap.h>
#include <linux/slab.h> #include <linux/slab.h>
static struct { static struct {
...@@ -123,14 +125,9 @@ static int wm8400_read(struct wm8400 *wm8400, u8 reg, int num_regs, u16 *dest) ...@@ -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 */ /* If there are any volatile reads then read back the entire block */
for (i = reg; i < reg + num_regs; i++) for (i = reg; i < reg + num_regs; i++)
if (reg_data[i].vol) { if (reg_data[i].vol) {
ret = wm8400->read_dev(wm8400->io_data, reg, ret = regmap_bulk_read(wm8400->regmap, reg, dest,
num_regs, dest); num_regs);
if (ret != 0) return ret;
return ret;
for (i = 0; i < num_regs; i++)
dest[i] = be16_to_cpu(dest[i]);
return 0;
} }
/* Otherwise use the cache */ /* Otherwise use the cache */
...@@ -149,14 +146,11 @@ static int wm8400_write(struct wm8400 *wm8400, u8 reg, int num_regs, ...@@ -149,14 +146,11 @@ static int wm8400_write(struct wm8400 *wm8400, u8 reg, int num_regs,
for (i = 0; i < num_regs; i++) { for (i = 0; i < num_regs; i++) {
BUG_ON(!reg_data[reg + i].writable); BUG_ON(!reg_data[reg + i].writable);
wm8400->reg_cache[reg + i] = src[i]; 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; return 0;
} }
...@@ -270,14 +264,14 @@ static int wm8400_init(struct wm8400 *wm8400, ...@@ -270,14 +264,14 @@ static int wm8400_init(struct wm8400 *wm8400,
dev_set_drvdata(wm8400->dev, wm8400); dev_set_drvdata(wm8400->dev, wm8400);
/* Check that this is actually a WM8400 */ /* Check that this is actually a WM8400 */
ret = wm8400->read_dev(wm8400->io_data, WM8400_RESET_ID, 1, &reg); ret = regmap_read(wm8400->regmap, WM8400_RESET_ID, &i);
if (ret != 0) { if (ret != 0) {
dev_err(wm8400->dev, "Chip ID register read failed\n"); dev_err(wm8400->dev, "Chip ID register read failed\n");
return -EIO; 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", dev_err(wm8400->dev, "Device is not a WM8400, ID is %x\n",
be16_to_cpu(reg)); reg);
return -ENODEV; return -ENODEV;
} }
...@@ -285,9 +279,8 @@ static int wm8400_init(struct wm8400 *wm8400, ...@@ -285,9 +279,8 @@ static int wm8400_init(struct wm8400 *wm8400,
* is a PMIC we can't reset it safely so initialise the register * is a PMIC we can't reset it safely so initialise the register
* cache from the hardware. * cache from the hardware.
*/ */
ret = wm8400->read_dev(wm8400->io_data, 0, ret = regmap_raw_read(wm8400->regmap, 0, wm8400->reg_cache,
ARRAY_SIZE(wm8400->reg_cache), ARRAY_SIZE(wm8400->reg_cache));
wm8400->reg_cache);
if (ret != 0) { if (ret != 0) {
dev_err(wm8400->dev, "Register cache read failed\n"); dev_err(wm8400->dev, "Register cache read failed\n");
return -EIO; return -EIO;
...@@ -337,60 +330,13 @@ static void wm8400_release(struct wm8400 *wm8400) ...@@ -337,60 +330,13 @@ static void wm8400_release(struct wm8400 *wm8400)
mfd_remove_devices(wm8400->dev); mfd_remove_devices(wm8400->dev);
} }
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static const struct regmap_config wm8400_regmap_config = {
static int wm8400_i2c_read(void *io_data, char reg, int count, u16 *dest) .reg_bits = 8,
{ .val_bits = 16,
struct i2c_client *i2c = io_data; .max_register = WM8400_REGISTER_COUNT - 1,
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 = &reg;
/* 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;
}
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static int wm8400_i2c_probe(struct i2c_client *i2c, static int wm8400_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
...@@ -403,18 +349,23 @@ static int wm8400_i2c_probe(struct i2c_client *i2c, ...@@ -403,18 +349,23 @@ static int wm8400_i2c_probe(struct i2c_client *i2c,
goto err; goto err;
} }
wm8400->io_data = i2c; wm8400->regmap = regmap_init_i2c(i2c, &wm8400_regmap_config);
wm8400->read_dev = wm8400_i2c_read; if (IS_ERR(wm8400->regmap)) {
wm8400->write_dev = wm8400_i2c_write; ret = PTR_ERR(wm8400->regmap);
goto struct_err;
}
wm8400->dev = &i2c->dev; wm8400->dev = &i2c->dev;
i2c_set_clientdata(i2c, wm8400); i2c_set_clientdata(i2c, wm8400);
ret = wm8400_init(wm8400, i2c->dev.platform_data); ret = wm8400_init(wm8400, i2c->dev.platform_data);
if (ret != 0) if (ret != 0)
goto struct_err; goto map_err;
return 0; return 0;
map_err:
regmap_exit(wm8400->regmap);
struct_err: struct_err:
kfree(wm8400); kfree(wm8400);
err: err:
...@@ -426,6 +377,7 @@ static int wm8400_i2c_remove(struct i2c_client *i2c) ...@@ -426,6 +377,7 @@ static int wm8400_i2c_remove(struct i2c_client *i2c)
struct wm8400 *wm8400 = i2c_get_clientdata(i2c); struct wm8400 *wm8400 = i2c_get_clientdata(i2c);
wm8400_release(wm8400); wm8400_release(wm8400);
regmap_exit(wm8400->regmap);
kfree(wm8400); kfree(wm8400);
return 0; return 0;
......
...@@ -16,9 +16,11 @@ ...@@ -16,9 +16,11 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/err.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
...@@ -29,22 +31,7 @@ ...@@ -29,22 +31,7 @@
static int wm8994_read(struct wm8994 *wm8994, unsigned short reg, static int wm8994_read(struct wm8994 *wm8994, unsigned short reg,
int bytes, void *dest) int bytes, void *dest)
{ {
int ret, i; return regmap_raw_read(wm8994->regmap, reg, dest, bytes);
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;
} }
/** /**
...@@ -55,19 +42,15 @@ static int wm8994_read(struct wm8994 *wm8994, unsigned short reg, ...@@ -55,19 +42,15 @@ static int wm8994_read(struct wm8994 *wm8994, unsigned short reg,
*/ */
int wm8994_reg_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; int ret;
mutex_lock(&wm8994->io_lock); ret = regmap_read(wm8994->regmap, reg, &val);
ret = wm8994_read(wm8994, reg, 2, &val);
mutex_unlock(&wm8994->io_lock);
if (ret < 0) if (ret < 0)
return ret; return ret;
else else
return be16_to_cpu(val); return val;
} }
EXPORT_SYMBOL_GPL(wm8994_reg_read); EXPORT_SYMBOL_GPL(wm8994_reg_read);
...@@ -82,33 +65,13 @@ 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 wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
int count, u16 *buf) int count, u16 *buf)
{ {
int ret; return regmap_bulk_read(wm8994->regmap, reg, buf, count);
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, static int wm8994_write(struct wm8994 *wm8994, unsigned short reg,
int bytes, const void *src) int bytes, const void *src)
{ {
const u16 *buf = src; return regmap_raw_write(wm8994->regmap, reg, src, bytes);
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);
} }
/** /**
...@@ -121,17 +84,7 @@ static int wm8994_write(struct wm8994 *wm8994, unsigned short reg, ...@@ -121,17 +84,7 @@ static int wm8994_write(struct wm8994 *wm8994, unsigned short reg,
int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg, int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg,
unsigned short val) unsigned short val)
{ {
int ret; return regmap_write(wm8994->regmap, reg, val);
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); EXPORT_SYMBOL_GPL(wm8994_reg_write);
...@@ -146,15 +99,7 @@ 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 wm8994_bulk_write(struct wm8994 *wm8994, unsigned short reg,
int count, const u16 *buf) int count, const u16 *buf)
{ {
int ret; return regmap_raw_write(wm8994->regmap, reg, buf, count * sizeof(u16));
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); EXPORT_SYMBOL_GPL(wm8994_bulk_write);
...@@ -169,28 +114,7 @@ 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, int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg,
unsigned short mask, unsigned short val) unsigned short mask, unsigned short val)
{ {
int ret; return regmap_update_bits(wm8994->regmap, reg, mask, val);
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); EXPORT_SYMBOL_GPL(wm8994_set_bits);
...@@ -378,6 +302,11 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo) ...@@ -378,6 +302,11 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
} }
#endif #endif
static struct regmap_config wm8994_regmap_config = {
.reg_bits = 16,
.val_bits = 16,
};
/* /*
* Instantiate the generic non-control parts of the device. * Instantiate the generic non-control parts of the device.
*/ */
...@@ -387,7 +316,6 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) ...@@ -387,7 +316,6 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
const char *devname; const char *devname;
int ret, i; int ret, i;
mutex_init(&wm8994->io_lock);
dev_set_drvdata(wm8994->dev, wm8994); dev_set_drvdata(wm8994->dev, wm8994);
/* Add the on-chip regulators first for bootstrapping */ /* Add the on-chip regulators first for bootstrapping */
...@@ -397,7 +325,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) ...@@ -397,7 +325,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
NULL, 0); NULL, 0);
if (ret != 0) { if (ret != 0) {
dev_err(wm8994->dev, "Failed to add children: %d\n", ret); dev_err(wm8994->dev, "Failed to add children: %d\n", ret);
goto err; goto err_regmap;
} }
switch (wm8994->type) { switch (wm8994->type) {
...@@ -409,7 +337,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) ...@@ -409,7 +337,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
break; break;
default: default:
BUG(); BUG();
goto err; goto err_regmap;
} }
wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) * wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
...@@ -417,7 +345,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) ...@@ -417,7 +345,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
GFP_KERNEL); GFP_KERNEL);
if (!wm8994->supplies) { if (!wm8994->supplies) {
ret = -ENOMEM; ret = -ENOMEM;
goto err; goto err_regmap;
} }
switch (wm8994->type) { switch (wm8994->type) {
...@@ -431,7 +359,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) ...@@ -431,7 +359,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
break; break;
default: default:
BUG(); BUG();
goto err; goto err_regmap;
} }
ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies, ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies,
...@@ -554,7 +482,8 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) ...@@ -554,7 +482,8 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
regulator_bulk_free(wm8994->num_supplies, wm8994->supplies); regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
err_supplies: err_supplies:
kfree(wm8994->supplies); kfree(wm8994->supplies);
err: err_regmap:
regmap_exit(wm8994->regmap);
mfd_remove_devices(wm8994->dev); mfd_remove_devices(wm8994->dev);
kfree(wm8994); kfree(wm8994);
return ret; return ret;
...@@ -569,62 +498,15 @@ static void wm8994_device_exit(struct wm8994 *wm8994) ...@@ -569,62 +498,15 @@ static void wm8994_device_exit(struct wm8994 *wm8994)
wm8994->supplies); wm8994->supplies);
regulator_bulk_free(wm8994->num_supplies, wm8994->supplies); regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
kfree(wm8994->supplies); kfree(wm8994->supplies);
regmap_exit(wm8994->regmap);
kfree(wm8994); 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 *)&reg;
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, static int wm8994_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct wm8994 *wm8994; struct wm8994 *wm8994;
int ret;
wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL); wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL);
if (wm8994 == NULL) if (wm8994 == NULL)
...@@ -632,12 +514,18 @@ static int wm8994_i2c_probe(struct i2c_client *i2c, ...@@ -632,12 +514,18 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, wm8994); i2c_set_clientdata(i2c, wm8994);
wm8994->dev = &i2c->dev; 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->irq = i2c->irq;
wm8994->type = id->driver_data; 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); return wm8994_device_init(wm8994, i2c->irq);
} }
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/regmap.h>
/* /*
* Register values. * Register values.
...@@ -361,12 +362,8 @@ struct wm831x { ...@@ -361,12 +362,8 @@ struct wm831x {
struct mutex io_lock; struct mutex io_lock;
struct device *dev; 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 */ int irq; /* Our chip IRQ */
struct mutex irq_lock; struct mutex irq_lock;
...@@ -416,4 +413,6 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq); ...@@ -416,4 +413,6 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq);
void wm831x_irq_exit(struct wm831x *wm831x); void wm831x_irq_exit(struct wm831x *wm831x);
void wm831x_auxadc_init(struct wm831x *wm831x); void wm831x_auxadc_init(struct wm831x *wm831x);
extern struct regmap_config wm831x_regmap_config;
#endif #endif
...@@ -25,16 +25,15 @@ ...@@ -25,16 +25,15 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
struct regmap;
#define WM8400_REGISTER_COUNT 0x55 #define WM8400_REGISTER_COUNT 0x55
struct wm8400 { struct wm8400 {
struct device *dev; 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 mutex io_lock;
void *io_data; struct regmap *regmap;
u16 reg_cache[WM8400_REGISTER_COUNT]; u16 reg_cache[WM8400_REGISTER_COUNT];
......
...@@ -24,6 +24,7 @@ enum wm8994_type { ...@@ -24,6 +24,7 @@ enum wm8994_type {
struct regulator_dev; struct regulator_dev;
struct regulator_bulk_data; struct regulator_bulk_data;
struct regmap;
#define WM8994_NUM_GPIO_REGS 11 #define WM8994_NUM_GPIO_REGS 11
#define WM8994_NUM_LDO_REGS 2 #define WM8994_NUM_LDO_REGS 2
...@@ -50,18 +51,12 @@ struct regulator_bulk_data; ...@@ -50,18 +51,12 @@ struct regulator_bulk_data;
#define WM8994_IRQ_GPIO(x) (x + WM8994_IRQ_TEMP_WARN) #define WM8994_IRQ_GPIO(x) (x + WM8994_IRQ_TEMP_WARN)
struct wm8994 { struct wm8994 {
struct mutex io_lock;
struct mutex irq_lock; struct mutex irq_lock;
enum wm8994_type type; enum wm8994_type type;
struct device *dev; struct device *dev;
int (*read_dev)(struct wm8994 *wm8994, unsigned short reg, struct regmap *regmap;
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 gpio_base;
int irq_base; int irq_base;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment