From f92e8f8144243a3651b2e350b706ea2d04931f8c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 17 Feb 2010 18:45:25 +0000 Subject: mfd: Add WM831x revision B support Revision B of the WM831x devices changes the sense of the tristate bit for GPIO configuration, inverting it to become an enable instead. Take account of this in the gpiolib driver. A current sink regulation status bit has also been added in revision B, add a flag indicating if it's present but don't use it yet. This revision also adds an interrupt on key up for the ON pin event which the existing code is able to take advantage of. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/wm831x-core.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/mfd/wm831x-core.c') diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 4b2021af1d9..c428d9f918f 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -1449,18 +1449,33 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) case WM8310: parent = WM8310; wm831x->num_gpio = 16; + if (rev > 0) { + wm831x->has_gpio_ena = 1; + wm831x->has_cs_sts = 1; + } + dev_info(wm831x->dev, "WM8310 revision %c\n", 'A' + rev); break; case WM8311: parent = WM8311; wm831x->num_gpio = 16; + if (rev > 0) { + wm831x->has_gpio_ena = 1; + wm831x->has_cs_sts = 1; + } + dev_info(wm831x->dev, "WM8311 revision %c\n", 'A' + rev); break; case WM8312: parent = WM8312; wm831x->num_gpio = 16; + if (rev > 0) { + wm831x->has_gpio_ena = 1; + wm831x->has_cs_sts = 1; + } + dev_info(wm831x->dev, "WM8312 revision %c\n", 'A' + rev); break; -- cgit v1.2.3-70-g09d2 From 473fe73650b9f92114edbedfbb616561c1a0026c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 23 Feb 2010 11:08:06 +0000 Subject: mfd: Use completion interrupt for WM831x AUXADC Use the completion interrupt generated by the device rather than polling for conversions to complete. As a backup we still check the status of the AUXADC if we don't get a completion, mostly for systems that don't have the WM831x interrupt infrastructure hooked up. Also reduce the timeout for completion of conversions to 5ms from the previous 10ms, the lower timeout should be sufficient. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/wm831x-core.c | 36 +++++++++++++++++++++++++++++------- include/linux/mfd/wm831x/core.h | 2 ++ 2 files changed, 31 insertions(+), 7 deletions(-) (limited to 'drivers/mfd/wm831x-core.c') diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index c428d9f918f..07101e9e1cb 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -321,7 +321,6 @@ EXPORT_SYMBOL_GPL(wm831x_set_bits); */ int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input) { - int tries = 10; int ret, src; mutex_lock(&wm831x->auxadc_lock); @@ -349,13 +348,14 @@ int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input) goto disable; } - do { - msleep(1); + /* Ignore the result to allow us to soldier on without IRQ hookup */ + wait_for_completion_timeout(&wm831x->auxadc_done, msecs_to_jiffies(5)); - ret = wm831x_reg_read(wm831x, WM831X_AUXADC_CONTROL); - if (ret < 0) - ret = WM831X_AUX_CVT_ENA; - } while ((ret & WM831X_AUX_CVT_ENA) && --tries); + ret = wm831x_reg_read(wm831x, WM831X_AUXADC_CONTROL); + if (ret < 0) { + dev_err(wm831x->dev, "AUXADC status read failed: %d\n", ret); + goto disable; + } if (ret & WM831X_AUX_CVT_ENA) { dev_err(wm831x->dev, "Timed out reading AUXADC\n"); @@ -390,6 +390,15 @@ out: } EXPORT_SYMBOL_GPL(wm831x_auxadc_read); +static irqreturn_t wm831x_auxadc_irq(int irq, void *irq_data) +{ + struct wm831x *wm831x = irq_data; + + complete(&wm831x->auxadc_done); + + return IRQ_HANDLED; +} + /** * wm831x_auxadc_read_uv: Read a voltage from the WM831x AUXADC * @@ -1411,6 +1420,7 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) mutex_init(&wm831x->io_lock); mutex_init(&wm831x->key_lock); mutex_init(&wm831x->auxadc_lock); + init_completion(&wm831x->auxadc_done); dev_set_drvdata(wm831x->dev, wm831x); ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID); @@ -1523,6 +1533,16 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) if (ret != 0) goto err; + if (wm831x->irq_base) { + ret = request_threaded_irq(wm831x->irq_base + + WM831X_IRQ_AUXADC_DATA, + NULL, wm831x_auxadc_irq, 0, + "auxadc", wm831x); + if (ret < 0) + dev_err(wm831x->dev, "AUXADC IRQ request failed: %d\n", + ret); + } + /* The core device is up, instantiate the subdevices. */ switch (parent) { case WM8310: @@ -1593,6 +1613,8 @@ static void wm831x_device_exit(struct wm831x *wm831x) { wm831x_otp_exit(wm831x); mfd_remove_devices(wm831x->dev); + if (wm831x->irq_base) + free_irq(wm831x->irq_base + WM831X_IRQ_AUXADC_DATA, wm831x); wm831x_irq_exit(wm831x); kfree(wm831x); } diff --git a/include/linux/mfd/wm831x/core.h b/include/linux/mfd/wm831x/core.h index 53580b592bc..5915f6e3d9a 100644 --- a/include/linux/mfd/wm831x/core.h +++ b/include/linux/mfd/wm831x/core.h @@ -15,6 +15,7 @@ #ifndef __MFD_WM831X_CORE_H__ #define __MFD_WM831X_CORE_H__ +#include #include /* @@ -261,6 +262,7 @@ struct wm831x { int num_gpio; struct mutex auxadc_lock; + struct completion auxadc_done; /* The WM831x has a security key blocking access to certain * registers. The mutex is taken by the accessors for locking -- cgit v1.2.3-70-g09d2