|
@@ -322,7 +322,11 @@ EXPORT_SYMBOL_GPL(wm831x_set_bits);
|
|
|
*/
|
|
|
int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
|
|
|
{
|
|
|
- int ret, src;
|
|
|
+ int ret, src, irq_masked, timeout;
|
|
|
+
|
|
|
+ /* Are we using the interrupt? */
|
|
|
+ irq_masked = wm831x_reg_read(wm831x, WM831X_INTERRUPT_STATUS_1_MASK);
|
|
|
+ irq_masked &= WM831X_AUXADC_DATA_EINT;
|
|
|
|
|
|
mutex_lock(&wm831x->auxadc_lock);
|
|
|
|
|
@@ -342,6 +346,9 @@ int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
+ /* Clear any notification from a very late arriving interrupt */
|
|
|
+ try_wait_for_completion(&wm831x->auxadc_done);
|
|
|
+
|
|
|
ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
|
|
|
WM831X_AUX_CVT_ENA, WM831X_AUX_CVT_ENA);
|
|
|
if (ret < 0) {
|
|
@@ -349,22 +356,46 @@ int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
|
|
|
goto disable;
|
|
|
}
|
|
|
|
|
|
- /* If an interrupt arrived late clean up after it */
|
|
|
- try_wait_for_completion(&wm831x->auxadc_done);
|
|
|
-
|
|
|
- /* 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) {
|
|
|
- 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");
|
|
|
- ret = -EBUSY;
|
|
|
- goto disable;
|
|
|
+ if (irq_masked) {
|
|
|
+ /* If we're not using interrupts then poll the
|
|
|
+ * interrupt status register */
|
|
|
+ timeout = 5;
|
|
|
+ while (timeout) {
|
|
|
+ msleep(1);
|
|
|
+
|
|
|
+ ret = wm831x_reg_read(wm831x,
|
|
|
+ WM831X_INTERRUPT_STATUS_1);
|
|
|
+ if (ret < 0) {
|
|
|
+ dev_err(wm831x->dev,
|
|
|
+ "ISR 1 read failed: %d\n", ret);
|
|
|
+ goto disable;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Did it complete? */
|
|
|
+ if (ret & WM831X_AUXADC_DATA_EINT) {
|
|
|
+ wm831x_reg_write(wm831x,
|
|
|
+ WM831X_INTERRUPT_STATUS_1,
|
|
|
+ WM831X_AUXADC_DATA_EINT);
|
|
|
+ break;
|
|
|
+ } else {
|
|
|
+ dev_err(wm831x->dev,
|
|
|
+ "AUXADC conversion timeout\n");
|
|
|
+ ret = -EBUSY;
|
|
|
+ goto disable;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ /* If we are using interrupts then wait for the
|
|
|
+ * interrupt to complete. Use an extremely long
|
|
|
+ * timeout to handle situations with heavy load where
|
|
|
+ * the notification of the interrupt may be delayed by
|
|
|
+ * threaded IRQ handling. */
|
|
|
+ if (!wait_for_completion_timeout(&wm831x->auxadc_done,
|
|
|
+ msecs_to_jiffies(500))) {
|
|
|
+ dev_err(wm831x->dev, "Timed out waiting for AUXADC\n");
|
|
|
+ ret = -EBUSY;
|
|
|
+ goto disable;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA);
|