diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-02-23 06:08:05 -0500 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2010-03-07 16:17:33 -0500 |
commit | d19663ac61a6e36eec655d3c84a106686ebddd2c (patch) | |
tree | 186e46cad833116613f9cdd1c11fde53b0aa32e5 /drivers | |
parent | 11a441ce82d6ffecfd39b324024de0cd630b36c1 (diff) |
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: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mfd/wm8350-core.c | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index 9a970bd68775..bd75807d5302 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c | |||
@@ -339,7 +339,6 @@ EXPORT_SYMBOL_GPL(wm8350_reg_unlock); | |||
339 | int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref) | 339 | int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref) |
340 | { | 340 | { |
341 | u16 reg, result = 0; | 341 | u16 reg, result = 0; |
342 | int tries = 5; | ||
343 | 342 | ||
344 | if (channel < WM8350_AUXADC_AUX1 || channel > WM8350_AUXADC_TEMP) | 343 | if (channel < WM8350_AUXADC_AUX1 || channel > WM8350_AUXADC_TEMP) |
345 | return -EINVAL; | 344 | return -EINVAL; |
@@ -363,12 +362,13 @@ int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref) | |||
363 | reg |= 1 << channel | WM8350_AUXADC_POLL; | 362 | reg |= 1 << channel | WM8350_AUXADC_POLL; |
364 | wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg); | 363 | wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg); |
365 | 364 | ||
366 | do { | 365 | /* We ignore the result of the completion and just check for a |
367 | schedule_timeout_interruptible(1); | 366 | * conversion result, allowing us to soldier on if the IRQ |
368 | reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1); | 367 | * infrastructure is not set up for the chip. */ |
369 | } while ((reg & WM8350_AUXADC_POLL) && --tries); | 368 | wait_for_completion_timeout(&wm8350->auxadc_done, msecs_to_jiffies(5)); |
370 | 369 | ||
371 | if (!tries) | 370 | reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1); |
371 | if (reg & WM8350_AUXADC_POLL) | ||
372 | dev_err(wm8350->dev, "adc chn %d read timeout\n", channel); | 372 | dev_err(wm8350->dev, "adc chn %d read timeout\n", channel); |
373 | else | 373 | else |
374 | result = wm8350_reg_read(wm8350, | 374 | result = wm8350_reg_read(wm8350, |
@@ -385,6 +385,15 @@ int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref) | |||
385 | } | 385 | } |
386 | EXPORT_SYMBOL_GPL(wm8350_read_auxadc); | 386 | EXPORT_SYMBOL_GPL(wm8350_read_auxadc); |
387 | 387 | ||
388 | static irqreturn_t wm8350_auxadc_irq(int irq, void *irq_data) | ||
389 | { | ||
390 | struct wm8350 *wm8350 = irq_data; | ||
391 | |||
392 | complete(&wm8350->auxadc_done); | ||
393 | |||
394 | return IRQ_HANDLED; | ||
395 | } | ||
396 | |||
388 | /* | 397 | /* |
389 | * Cache is always host endian. | 398 | * Cache is always host endian. |
390 | */ | 399 | */ |
@@ -682,11 +691,22 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, | |||
682 | } | 691 | } |
683 | 692 | ||
684 | mutex_init(&wm8350->auxadc_mutex); | 693 | mutex_init(&wm8350->auxadc_mutex); |
694 | init_completion(&wm8350->auxadc_done); | ||
685 | 695 | ||
686 | ret = wm8350_irq_init(wm8350, irq, pdata); | 696 | ret = wm8350_irq_init(wm8350, irq, pdata); |
687 | if (ret < 0) | 697 | if (ret < 0) |
688 | goto err; | 698 | goto err; |
689 | 699 | ||
700 | if (wm8350->irq_base) { | ||
701 | ret = request_threaded_irq(wm8350->irq_base + | ||
702 | WM8350_IRQ_AUXADC_DATARDY, | ||
703 | NULL, wm8350_auxadc_irq, 0, | ||
704 | "auxadc", wm8350); | ||
705 | if (ret < 0) | ||
706 | dev_warn(wm8350->dev, | ||
707 | "Failed to request AUXADC IRQ: %d\n", ret); | ||
708 | } | ||
709 | |||
690 | if (pdata && pdata->init) { | 710 | if (pdata && pdata->init) { |
691 | ret = pdata->init(wm8350); | 711 | ret = pdata->init(wm8350); |
692 | if (ret != 0) { | 712 | if (ret != 0) { |
@@ -736,6 +756,9 @@ void wm8350_device_exit(struct wm8350 *wm8350) | |||
736 | platform_device_unregister(wm8350->gpio.pdev); | 756 | platform_device_unregister(wm8350->gpio.pdev); |
737 | platform_device_unregister(wm8350->codec.pdev); | 757 | platform_device_unregister(wm8350->codec.pdev); |
738 | 758 | ||
759 | if (wm8350->irq_base) | ||
760 | free_irq(wm8350->irq_base + WM8350_IRQ_AUXADC_DATARDY, wm8350); | ||
761 | |||
739 | wm8350_irq_exit(wm8350); | 762 | wm8350_irq_exit(wm8350); |
740 | 763 | ||
741 | kfree(wm8350->reg_cache); | 764 | kfree(wm8350->reg_cache); |