aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mfd/wm831x-core.c65
1 files changed, 48 insertions, 17 deletions
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
index f2ab025ad97a..da00ca9e0c71 100644
--- a/drivers/mfd/wm831x-core.c
+++ b/drivers/mfd/wm831x-core.c
@@ -322,7 +322,11 @@ EXPORT_SYMBOL_GPL(wm831x_set_bits);
322 */ 322 */
323int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input) 323int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
324{ 324{
325 int ret, src; 325 int ret, src, irq_masked, timeout;
326
327 /* Are we using the interrupt? */
328 irq_masked = wm831x_reg_read(wm831x, WM831X_INTERRUPT_STATUS_1_MASK);
329 irq_masked &= WM831X_AUXADC_DATA_EINT;
326 330
327 mutex_lock(&wm831x->auxadc_lock); 331 mutex_lock(&wm831x->auxadc_lock);
328 332
@@ -342,6 +346,9 @@ int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
342 goto out; 346 goto out;
343 } 347 }
344 348
349 /* Clear any notification from a very late arriving interrupt */
350 try_wait_for_completion(&wm831x->auxadc_done);
351
345 ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, 352 ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
346 WM831X_AUX_CVT_ENA, WM831X_AUX_CVT_ENA); 353 WM831X_AUX_CVT_ENA, WM831X_AUX_CVT_ENA);
347 if (ret < 0) { 354 if (ret < 0) {
@@ -349,22 +356,46 @@ int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
349 goto disable; 356 goto disable;
350 } 357 }
351 358
352 /* If an interrupt arrived late clean up after it */ 359 if (irq_masked) {
353 try_wait_for_completion(&wm831x->auxadc_done); 360 /* If we're not using interrupts then poll the
354 361 * interrupt status register */
355 /* Ignore the result to allow us to soldier on without IRQ hookup */ 362 timeout = 5;
356 wait_for_completion_timeout(&wm831x->auxadc_done, msecs_to_jiffies(5)); 363 while (timeout) {
357 364 msleep(1);
358 ret = wm831x_reg_read(wm831x, WM831X_AUXADC_CONTROL); 365
359 if (ret < 0) { 366 ret = wm831x_reg_read(wm831x,
360 dev_err(wm831x->dev, "AUXADC status read failed: %d\n", ret); 367 WM831X_INTERRUPT_STATUS_1);
361 goto disable; 368 if (ret < 0) {
362 } 369 dev_err(wm831x->dev,
363 370 "ISR 1 read failed: %d\n", ret);
364 if (ret & WM831X_AUX_CVT_ENA) { 371 goto disable;
365 dev_err(wm831x->dev, "Timed out reading AUXADC\n"); 372 }
366 ret = -EBUSY; 373
367 goto disable; 374 /* Did it complete? */
375 if (ret & WM831X_AUXADC_DATA_EINT) {
376 wm831x_reg_write(wm831x,
377 WM831X_INTERRUPT_STATUS_1,
378 WM831X_AUXADC_DATA_EINT);
379 break;
380 } else {
381 dev_err(wm831x->dev,
382 "AUXADC conversion timeout\n");
383 ret = -EBUSY;
384 goto disable;
385 }
386 }
387 } else {
388 /* If we are using interrupts then wait for the
389 * interrupt to complete. Use an extremely long
390 * timeout to handle situations with heavy load where
391 * the notification of the interrupt may be delayed by
392 * threaded IRQ handling. */
393 if (!wait_for_completion_timeout(&wm831x->auxadc_done,
394 msecs_to_jiffies(500))) {
395 dev_err(wm831x->dev, "Timed out waiting for AUXADC\n");
396 ret = -EBUSY;
397 goto disable;
398 }
368 } 399 }
369 400
370 ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA); 401 ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA);