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>
This commit is contained in:
Mark Brown 2010-02-23 11:08:06 +00:00 committed by Samuel Ortiz
parent d19663ac61
commit 473fe73650
2 changed files with 31 additions and 7 deletions

View File

@ -321,7 +321,6 @@ EXPORT_SYMBOL_GPL(wm831x_set_bits);
*/ */
int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input) int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
{ {
int tries = 10;
int ret, src; int ret, src;
mutex_lock(&wm831x->auxadc_lock); mutex_lock(&wm831x->auxadc_lock);
@ -349,13 +348,14 @@ int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
goto disable; goto disable;
} }
do { /* Ignore the result to allow us to soldier on without IRQ hookup */
msleep(1); wait_for_completion_timeout(&wm831x->auxadc_done, msecs_to_jiffies(5));
ret = wm831x_reg_read(wm831x, WM831X_AUXADC_CONTROL); ret = wm831x_reg_read(wm831x, WM831X_AUXADC_CONTROL);
if (ret < 0) if (ret < 0) {
ret = WM831X_AUX_CVT_ENA; dev_err(wm831x->dev, "AUXADC status read failed: %d\n", ret);
} while ((ret & WM831X_AUX_CVT_ENA) && --tries); goto disable;
}
if (ret & WM831X_AUX_CVT_ENA) { if (ret & WM831X_AUX_CVT_ENA) {
dev_err(wm831x->dev, "Timed out reading AUXADC\n"); dev_err(wm831x->dev, "Timed out reading AUXADC\n");
@ -390,6 +390,15 @@ out:
} }
EXPORT_SYMBOL_GPL(wm831x_auxadc_read); 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 * 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->io_lock);
mutex_init(&wm831x->key_lock); mutex_init(&wm831x->key_lock);
mutex_init(&wm831x->auxadc_lock); mutex_init(&wm831x->auxadc_lock);
init_completion(&wm831x->auxadc_done);
dev_set_drvdata(wm831x->dev, wm831x); dev_set_drvdata(wm831x->dev, wm831x);
ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID); 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) if (ret != 0)
goto err; 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. */ /* The core device is up, instantiate the subdevices. */
switch (parent) { switch (parent) {
case WM8310: case WM8310:
@ -1593,6 +1613,8 @@ static void wm831x_device_exit(struct wm831x *wm831x)
{ {
wm831x_otp_exit(wm831x); wm831x_otp_exit(wm831x);
mfd_remove_devices(wm831x->dev); mfd_remove_devices(wm831x->dev);
if (wm831x->irq_base)
free_irq(wm831x->irq_base + WM831X_IRQ_AUXADC_DATA, wm831x);
wm831x_irq_exit(wm831x); wm831x_irq_exit(wm831x);
kfree(wm831x); kfree(wm831x);
} }

View File

@ -15,6 +15,7 @@
#ifndef __MFD_WM831X_CORE_H__ #ifndef __MFD_WM831X_CORE_H__
#define __MFD_WM831X_CORE_H__ #define __MFD_WM831X_CORE_H__
#include <linux/completion.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
/* /*
@ -261,6 +262,7 @@ struct wm831x {
int num_gpio; int num_gpio;
struct mutex auxadc_lock; struct mutex auxadc_lock;
struct completion auxadc_done;
/* The WM831x has a security key blocking access to certain /* The WM831x has a security key blocking access to certain
* registers. The mutex is taken by the accessors for locking * registers. The mutex is taken by the accessors for locking