diff options
Diffstat (limited to 'drivers/power/ab8500_charger.c')
-rw-r--r-- | drivers/power/ab8500_charger.c | 105 |
1 files changed, 103 insertions, 2 deletions
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c index dcd3c6feca97..3eb23cf9ff47 100644 --- a/drivers/power/ab8500_charger.c +++ b/drivers/power/ab8500_charger.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #define VBUS_DET_DBNC100 0x02 | 52 | #define VBUS_DET_DBNC100 0x02 |
53 | #define VBUS_DET_DBNC1 0x01 | 53 | #define VBUS_DET_DBNC1 0x01 |
54 | #define OTP_ENABLE_WD 0x01 | 54 | #define OTP_ENABLE_WD 0x01 |
55 | #define DROP_COUNT_RESET 0x01 | ||
55 | 56 | ||
56 | #define MAIN_CH_INPUT_CURR_SHIFT 4 | 57 | #define MAIN_CH_INPUT_CURR_SHIFT 4 |
57 | #define VBUS_IN_CURR_LIM_SHIFT 4 | 58 | #define VBUS_IN_CURR_LIM_SHIFT 4 |
@@ -1678,6 +1679,105 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger, | |||
1678 | } | 1679 | } |
1679 | 1680 | ||
1680 | /** | 1681 | /** |
1682 | * ab8500_charger_usb_check_enable() - enable usb charging | ||
1683 | * @charger: pointer to the ux500_charger structure | ||
1684 | * @vset: charging voltage | ||
1685 | * @iset: charger output current | ||
1686 | * | ||
1687 | * Check if the VBUS charger has been disconnected and reconnected without | ||
1688 | * AB8500 rising an interrupt. Returns 0 on success. | ||
1689 | */ | ||
1690 | static int ab8500_charger_usb_check_enable(struct ux500_charger *charger, | ||
1691 | int vset, int iset) | ||
1692 | { | ||
1693 | u8 usbch_ctrl1 = 0; | ||
1694 | int ret = 0; | ||
1695 | |||
1696 | struct ab8500_charger *di = to_ab8500_charger_usb_device_info(charger); | ||
1697 | |||
1698 | if (!di->usb.charger_connected) | ||
1699 | return ret; | ||
1700 | |||
1701 | ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, | ||
1702 | AB8500_USBCH_CTRL1_REG, &usbch_ctrl1); | ||
1703 | if (ret < 0) { | ||
1704 | dev_err(di->dev, "ab8500 read failed %d\n", __LINE__); | ||
1705 | return ret; | ||
1706 | } | ||
1707 | dev_dbg(di->dev, "USB charger ctrl: 0x%02x\n", usbch_ctrl1); | ||
1708 | |||
1709 | if (!(usbch_ctrl1 & USB_CH_ENA)) { | ||
1710 | dev_info(di->dev, "Charging has been disabled abnormally and will be re-enabled\n"); | ||
1711 | |||
1712 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
1713 | AB8500_CHARGER, AB8500_CHARGER_CTRL, | ||
1714 | DROP_COUNT_RESET, DROP_COUNT_RESET); | ||
1715 | if (ret < 0) { | ||
1716 | dev_err(di->dev, "ab8500 write failed %d\n", __LINE__); | ||
1717 | return ret; | ||
1718 | } | ||
1719 | |||
1720 | ret = ab8500_charger_usb_en(&di->usb_chg, true, vset, iset); | ||
1721 | if (ret < 0) { | ||
1722 | dev_err(di->dev, "Failed to enable VBUS charger %d\n", | ||
1723 | __LINE__); | ||
1724 | return ret; | ||
1725 | } | ||
1726 | } | ||
1727 | return ret; | ||
1728 | } | ||
1729 | |||
1730 | /** | ||
1731 | * ab8500_charger_ac_check_enable() - enable usb charging | ||
1732 | * @charger: pointer to the ux500_charger structure | ||
1733 | * @vset: charging voltage | ||
1734 | * @iset: charger output current | ||
1735 | * | ||
1736 | * Check if the AC charger has been disconnected and reconnected without | ||
1737 | * AB8500 rising an interrupt. Returns 0 on success. | ||
1738 | */ | ||
1739 | static int ab8500_charger_ac_check_enable(struct ux500_charger *charger, | ||
1740 | int vset, int iset) | ||
1741 | { | ||
1742 | u8 mainch_ctrl1 = 0; | ||
1743 | int ret = 0; | ||
1744 | |||
1745 | struct ab8500_charger *di = to_ab8500_charger_ac_device_info(charger); | ||
1746 | |||
1747 | if (!di->ac.charger_connected) | ||
1748 | return ret; | ||
1749 | |||
1750 | ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, | ||
1751 | AB8500_MCH_CTRL1, &mainch_ctrl1); | ||
1752 | if (ret < 0) { | ||
1753 | dev_err(di->dev, "ab8500 read failed %d\n", __LINE__); | ||
1754 | return ret; | ||
1755 | } | ||
1756 | dev_dbg(di->dev, "AC charger ctrl: 0x%02x\n", mainch_ctrl1); | ||
1757 | |||
1758 | if (!(mainch_ctrl1 & MAIN_CH_ENA)) { | ||
1759 | dev_info(di->dev, "Charging has been disabled abnormally and will be re-enabled\n"); | ||
1760 | |||
1761 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
1762 | AB8500_CHARGER, AB8500_CHARGER_CTRL, | ||
1763 | DROP_COUNT_RESET, DROP_COUNT_RESET); | ||
1764 | |||
1765 | if (ret < 0) { | ||
1766 | dev_err(di->dev, "ab8500 write failed %d\n", __LINE__); | ||
1767 | return ret; | ||
1768 | } | ||
1769 | |||
1770 | ret = ab8500_charger_ac_en(&di->usb_chg, true, vset, iset); | ||
1771 | if (ret < 0) { | ||
1772 | dev_err(di->dev, "failed to enable AC charger %d\n", | ||
1773 | __LINE__); | ||
1774 | return ret; | ||
1775 | } | ||
1776 | } | ||
1777 | return ret; | ||
1778 | } | ||
1779 | |||
1780 | /** | ||
1681 | * ab8500_charger_watchdog_kick() - kick charger watchdog | 1781 | * ab8500_charger_watchdog_kick() - kick charger watchdog |
1682 | * @di: pointer to the ab8500_charger structure | 1782 | * @di: pointer to the ab8500_charger structure |
1683 | * | 1783 | * |
@@ -1734,8 +1834,7 @@ static int ab8500_charger_update_charger_current(struct ux500_charger *charger, | |||
1734 | 1834 | ||
1735 | /* Reset the main and usb drop input current measurement counter */ | 1835 | /* Reset the main and usb drop input current measurement counter */ |
1736 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | 1836 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, |
1737 | AB8500_CHARGER_CTRL, | 1837 | AB8500_CHARGER_CTRL, DROP_COUNT_RESET); |
1738 | 0x1); | ||
1739 | if (ret) { | 1838 | if (ret) { |
1740 | dev_err(di->dev, "%s write failed\n", __func__); | 1839 | dev_err(di->dev, "%s write failed\n", __func__); |
1741 | return ret; | 1840 | return ret; |
@@ -3221,6 +3320,7 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
3221 | di->ac_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface), | 3320 | di->ac_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface), |
3222 | /* ux500_charger sub-class */ | 3321 | /* ux500_charger sub-class */ |
3223 | di->ac_chg.ops.enable = &ab8500_charger_ac_en; | 3322 | di->ac_chg.ops.enable = &ab8500_charger_ac_en; |
3323 | di->ac_chg.ops.check_enable = &ab8500_charger_ac_check_enable; | ||
3224 | di->ac_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; | 3324 | di->ac_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; |
3225 | di->ac_chg.ops.update_curr = &ab8500_charger_update_charger_current; | 3325 | di->ac_chg.ops.update_curr = &ab8500_charger_update_charger_current; |
3226 | di->ac_chg.max_out_volt = ab8500_charger_voltage_map[ | 3326 | di->ac_chg.max_out_volt = ab8500_charger_voltage_map[ |
@@ -3242,6 +3342,7 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
3242 | di->usb_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface), | 3342 | di->usb_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface), |
3243 | /* ux500_charger sub-class */ | 3343 | /* ux500_charger sub-class */ |
3244 | di->usb_chg.ops.enable = &ab8500_charger_usb_en; | 3344 | di->usb_chg.ops.enable = &ab8500_charger_usb_en; |
3345 | di->usb_chg.ops.check_enable = &ab8500_charger_usb_check_enable; | ||
3245 | di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; | 3346 | di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; |
3246 | di->usb_chg.ops.update_curr = &ab8500_charger_update_charger_current; | 3347 | di->usb_chg.ops.update_curr = &ab8500_charger_update_charger_current; |
3247 | di->usb_chg.max_out_volt = ab8500_charger_voltage_map[ | 3348 | di->usb_chg.max_out_volt = ab8500_charger_voltage_map[ |