Commit d19663ac authored by Mark Brown's avatar Mark Brown Committed by Samuel Ortiz

mfd: Use completion interrupt for WM835x AUXADC

Use the completion interrupt generated by the device rather than
polling for conversions to complete. As a backup we still check
the state of the AUXADC if we don't get a completion, mostly for
systems that don't have the WM8350 interrupt infrastructure hooked
up.
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 11a441ce
...@@ -339,7 +339,6 @@ EXPORT_SYMBOL_GPL(wm8350_reg_unlock); ...@@ -339,7 +339,6 @@ EXPORT_SYMBOL_GPL(wm8350_reg_unlock);
int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref) int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref)
{ {
u16 reg, result = 0; u16 reg, result = 0;
int tries = 5;
if (channel < WM8350_AUXADC_AUX1 || channel > WM8350_AUXADC_TEMP) if (channel < WM8350_AUXADC_AUX1 || channel > WM8350_AUXADC_TEMP)
return -EINVAL; return -EINVAL;
...@@ -363,12 +362,13 @@ int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref) ...@@ -363,12 +362,13 @@ int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref)
reg |= 1 << channel | WM8350_AUXADC_POLL; reg |= 1 << channel | WM8350_AUXADC_POLL;
wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg); wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg);
do { /* We ignore the result of the completion and just check for a
schedule_timeout_interruptible(1); * conversion result, allowing us to soldier on if the IRQ
reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1); * infrastructure is not set up for the chip. */
} while ((reg & WM8350_AUXADC_POLL) && --tries); wait_for_completion_timeout(&wm8350->auxadc_done, msecs_to_jiffies(5));
if (!tries) reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1);
if (reg & WM8350_AUXADC_POLL)
dev_err(wm8350->dev, "adc chn %d read timeout\n", channel); dev_err(wm8350->dev, "adc chn %d read timeout\n", channel);
else else
result = wm8350_reg_read(wm8350, result = wm8350_reg_read(wm8350,
...@@ -385,6 +385,15 @@ int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref) ...@@ -385,6 +385,15 @@ int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref)
} }
EXPORT_SYMBOL_GPL(wm8350_read_auxadc); EXPORT_SYMBOL_GPL(wm8350_read_auxadc);
static irqreturn_t wm8350_auxadc_irq(int irq, void *irq_data)
{
struct wm8350 *wm8350 = irq_data;
complete(&wm8350->auxadc_done);
return IRQ_HANDLED;
}
/* /*
* Cache is always host endian. * Cache is always host endian.
*/ */
...@@ -682,11 +691,22 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, ...@@ -682,11 +691,22 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
} }
mutex_init(&wm8350->auxadc_mutex); mutex_init(&wm8350->auxadc_mutex);
init_completion(&wm8350->auxadc_done);
ret = wm8350_irq_init(wm8350, irq, pdata); ret = wm8350_irq_init(wm8350, irq, pdata);
if (ret < 0) if (ret < 0)
goto err; goto err;
if (wm8350->irq_base) {
ret = request_threaded_irq(wm8350->irq_base +
WM8350_IRQ_AUXADC_DATARDY,
NULL, wm8350_auxadc_irq, 0,
"auxadc", wm8350);
if (ret < 0)
dev_warn(wm8350->dev,
"Failed to request AUXADC IRQ: %d\n", ret);
}
if (pdata && pdata->init) { if (pdata && pdata->init) {
ret = pdata->init(wm8350); ret = pdata->init(wm8350);
if (ret != 0) { if (ret != 0) {
...@@ -736,6 +756,9 @@ void wm8350_device_exit(struct wm8350 *wm8350) ...@@ -736,6 +756,9 @@ void wm8350_device_exit(struct wm8350 *wm8350)
platform_device_unregister(wm8350->gpio.pdev); platform_device_unregister(wm8350->gpio.pdev);
platform_device_unregister(wm8350->codec.pdev); platform_device_unregister(wm8350->codec.pdev);
if (wm8350->irq_base)
free_irq(wm8350->irq_base + WM8350_IRQ_AUXADC_DATARDY, wm8350);
wm8350_irq_exit(wm8350); wm8350_irq_exit(wm8350);
kfree(wm8350->reg_cache); kfree(wm8350->reg_cache);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/completion.h>
#include <linux/mfd/wm8350/audio.h> #include <linux/mfd/wm8350/audio.h>
#include <linux/mfd/wm8350/gpio.h> #include <linux/mfd/wm8350/gpio.h>
...@@ -621,6 +622,7 @@ struct wm8350 { ...@@ -621,6 +622,7 @@ struct wm8350 {
u16 *reg_cache; u16 *reg_cache;
struct mutex auxadc_mutex; struct mutex auxadc_mutex;
struct completion auxadc_done;
/* Interrupt handling */ /* Interrupt handling */
struct mutex irq_lock; struct mutex irq_lock;
......
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