aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2010-02-23 11:08:06 +0000
committerSamuel Ortiz <sameo@linux.intel.com>2010-03-07 22:17:34 +0100
commit473fe73650b9f92114edbedfbb616561c1a0026c (patch)
tree24e4a0ee61eb73b990055a6b0f427e430d4d5234 /drivers/mfd
parentd19663ac61a6e36eec655d3c84a106686ebddd2c (diff)
downloadkernel_goldelico_gta04-473fe73650b9f92114edbedfbb616561c1a0026c.zip
kernel_goldelico_gta04-473fe73650b9f92114edbedfbb616561c1a0026c.tar.gz
kernel_goldelico_gta04-473fe73650b9f92114edbedfbb616561c1a0026c.tar.bz2
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 <broonie@opensource.wolfsonmicro.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/wm831x-core.c36
1 files changed, 29 insertions, 7 deletions
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
index c428d9f..07101e9 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);
}