diff options
Diffstat (limited to 'drivers/mfd/wm831x-core.c')
-rw-r--r-- | drivers/mfd/wm831x-core.c | 112 |
1 files changed, 95 insertions, 17 deletions
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index f2ab025ad97a..1a968f34d679 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); |
@@ -1463,6 +1494,7 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1463 | case WM8310: | 1494 | case WM8310: |
1464 | parent = WM8310; | 1495 | parent = WM8310; |
1465 | wm831x->num_gpio = 16; | 1496 | wm831x->num_gpio = 16; |
1497 | wm831x->charger_irq_wake = 1; | ||
1466 | if (rev > 0) { | 1498 | if (rev > 0) { |
1467 | wm831x->has_gpio_ena = 1; | 1499 | wm831x->has_gpio_ena = 1; |
1468 | wm831x->has_cs_sts = 1; | 1500 | wm831x->has_cs_sts = 1; |
@@ -1474,6 +1506,7 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1474 | case WM8311: | 1506 | case WM8311: |
1475 | parent = WM8311; | 1507 | parent = WM8311; |
1476 | wm831x->num_gpio = 16; | 1508 | wm831x->num_gpio = 16; |
1509 | wm831x->charger_irq_wake = 1; | ||
1477 | if (rev > 0) { | 1510 | if (rev > 0) { |
1478 | wm831x->has_gpio_ena = 1; | 1511 | wm831x->has_gpio_ena = 1; |
1479 | wm831x->has_cs_sts = 1; | 1512 | wm831x->has_cs_sts = 1; |
@@ -1485,6 +1518,7 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1485 | case WM8312: | 1518 | case WM8312: |
1486 | parent = WM8312; | 1519 | parent = WM8312; |
1487 | wm831x->num_gpio = 16; | 1520 | wm831x->num_gpio = 16; |
1521 | wm831x->charger_irq_wake = 1; | ||
1488 | if (rev > 0) { | 1522 | if (rev > 0) { |
1489 | wm831x->has_gpio_ena = 1; | 1523 | wm831x->has_gpio_ena = 1; |
1490 | wm831x->has_cs_sts = 1; | 1524 | wm831x->has_cs_sts = 1; |
@@ -1623,6 +1657,42 @@ static void wm831x_device_exit(struct wm831x *wm831x) | |||
1623 | kfree(wm831x); | 1657 | kfree(wm831x); |
1624 | } | 1658 | } |
1625 | 1659 | ||
1660 | static int wm831x_device_suspend(struct wm831x *wm831x) | ||
1661 | { | ||
1662 | int reg, mask; | ||
1663 | |||
1664 | /* If the charger IRQs are a wake source then make sure we ack | ||
1665 | * them even if they're not actively being used (eg, no power | ||
1666 | * driver or no IRQ line wired up) then acknowledge the | ||
1667 | * interrupts otherwise suspend won't last very long. | ||
1668 | */ | ||
1669 | if (wm831x->charger_irq_wake) { | ||
1670 | reg = wm831x_reg_read(wm831x, WM831X_INTERRUPT_STATUS_2_MASK); | ||
1671 | |||
1672 | mask = WM831X_CHG_BATT_HOT_EINT | | ||
1673 | WM831X_CHG_BATT_COLD_EINT | | ||
1674 | WM831X_CHG_BATT_FAIL_EINT | | ||
1675 | WM831X_CHG_OV_EINT | WM831X_CHG_END_EINT | | ||
1676 | WM831X_CHG_TO_EINT | WM831X_CHG_MODE_EINT | | ||
1677 | WM831X_CHG_START_EINT; | ||
1678 | |||
1679 | /* If any of the interrupts are masked read the statuses */ | ||
1680 | if (reg & mask) | ||
1681 | reg = wm831x_reg_read(wm831x, | ||
1682 | WM831X_INTERRUPT_STATUS_2); | ||
1683 | |||
1684 | if (reg & mask) { | ||
1685 | dev_info(wm831x->dev, | ||
1686 | "Acknowledging masked charger IRQs: %x\n", | ||
1687 | reg & mask); | ||
1688 | wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_2, | ||
1689 | reg & mask); | ||
1690 | } | ||
1691 | } | ||
1692 | |||
1693 | return 0; | ||
1694 | } | ||
1695 | |||
1626 | static int wm831x_i2c_read_device(struct wm831x *wm831x, unsigned short reg, | 1696 | static int wm831x_i2c_read_device(struct wm831x *wm831x, unsigned short reg, |
1627 | int bytes, void *dest) | 1697 | int bytes, void *dest) |
1628 | { | 1698 | { |
@@ -1697,6 +1767,13 @@ static int wm831x_i2c_remove(struct i2c_client *i2c) | |||
1697 | return 0; | 1767 | return 0; |
1698 | } | 1768 | } |
1699 | 1769 | ||
1770 | static int wm831x_i2c_suspend(struct i2c_client *i2c, pm_message_t mesg) | ||
1771 | { | ||
1772 | struct wm831x *wm831x = i2c_get_clientdata(i2c); | ||
1773 | |||
1774 | return wm831x_device_suspend(wm831x); | ||
1775 | } | ||
1776 | |||
1700 | static const struct i2c_device_id wm831x_i2c_id[] = { | 1777 | static const struct i2c_device_id wm831x_i2c_id[] = { |
1701 | { "wm8310", WM8310 }, | 1778 | { "wm8310", WM8310 }, |
1702 | { "wm8311", WM8311 }, | 1779 | { "wm8311", WM8311 }, |
@@ -1714,6 +1791,7 @@ static struct i2c_driver wm831x_i2c_driver = { | |||
1714 | }, | 1791 | }, |
1715 | .probe = wm831x_i2c_probe, | 1792 | .probe = wm831x_i2c_probe, |
1716 | .remove = wm831x_i2c_remove, | 1793 | .remove = wm831x_i2c_remove, |
1794 | .suspend = wm831x_i2c_suspend, | ||
1717 | .id_table = wm831x_i2c_id, | 1795 | .id_table = wm831x_i2c_id, |
1718 | }; | 1796 | }; |
1719 | 1797 | ||