diff options
-rw-r--r-- | drivers/mfd/wm831x-core.c | 65 |
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 | */ |
323 | int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input) | 323 | int 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); |