Messages in this thread Patch in this message | | | Date | Mon, 1 Mar 2010 00:04:23 +0100 | From | Samuel Ortiz <> | Subject | Re: [PATCH 1/2] mfd: Use completion interrupt for WM835x AUXADC |
| |
Hi Mark,
On Tue, Feb 23, 2010 at 11:08:05AM +0000, Mark Brown wrote: > 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. Patch applied, many thanks.
Cheers, Samuel.
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> > --- > drivers/mfd/wm8350-core.c | 35 +++++++++++++++++++++++++++++------ > include/linux/mfd/wm8350/core.h | 2 ++ > 2 files changed, 31 insertions(+), 6 deletions(-) > > diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c > index 9a970bd..bd75807 100644 > --- a/drivers/mfd/wm8350-core.c > +++ b/drivers/mfd/wm8350-core.c > @@ -339,7 +339,6 @@ EXPORT_SYMBOL_GPL(wm8350_reg_unlock); > int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref) > { > u16 reg, result = 0; > - int tries = 5; > > if (channel < WM8350_AUXADC_AUX1 || channel > WM8350_AUXADC_TEMP) > return -EINVAL; > @@ -363,12 +362,13 @@ int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref) > reg |= 1 << channel | WM8350_AUXADC_POLL; > wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg); > > - do { > - schedule_timeout_interruptible(1); > - reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1); > - } while ((reg & WM8350_AUXADC_POLL) && --tries); > + /* We ignore the result of the completion and just check for a > + * conversion result, allowing us to soldier on if the IRQ > + * infrastructure is not set up for the chip. */ > + 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); > else > result = wm8350_reg_read(wm8350, > @@ -385,6 +385,15 @@ int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref) > } > 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. > */ > @@ -682,11 +691,22 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, > } > > mutex_init(&wm8350->auxadc_mutex); > + init_completion(&wm8350->auxadc_done); > > ret = wm8350_irq_init(wm8350, irq, pdata); > if (ret < 0) > 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) { > ret = pdata->init(wm8350); > if (ret != 0) { > @@ -736,6 +756,9 @@ void wm8350_device_exit(struct wm8350 *wm8350) > platform_device_unregister(wm8350->gpio.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); > > kfree(wm8350->reg_cache); > diff --git a/include/linux/mfd/wm8350/core.h b/include/linux/mfd/wm8350/core.h > index fae08aa..98fcc97 100644 > --- a/include/linux/mfd/wm8350/core.h > +++ b/include/linux/mfd/wm8350/core.h > @@ -16,6 +16,7 @@ > #include <linux/kernel.h> > #include <linux/mutex.h> > #include <linux/interrupt.h> > +#include <linux/completion.h> > > #include <linux/mfd/wm8350/audio.h> > #include <linux/mfd/wm8350/gpio.h> > @@ -621,6 +622,7 @@ struct wm8350 { > u16 *reg_cache; > > struct mutex auxadc_mutex; > + struct completion auxadc_done; > > /* Interrupt handling */ > struct mutex irq_lock; > -- > 1.7.0 >
-- Intel Open Source Technology Centre http://oss.intel.com/
| |