aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLee Jones <lee.jones@linaro.org>2013-01-11 08:12:51 -0500
committerAnton Vorontsov <anton@enomsg.org>2013-01-15 20:35:12 -0500
commitb269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddc (patch)
tree5a36453c476b251e0f6d363ed8e672dc2b6c9036
parent3988a4df3499e604a3f2ae979372d27fc5664f77 (diff)
ab8500_charger: Detect charger removal
Add two new work queues to provide USB and AC charger disconnect detection. Signed-off-by: Lee Jones <lee.jones@linaro.org> Signed-off-by: Anton Vorontsov <anton@enomsg.org>
-rw-r--r--drivers/power/ab8500_charger.c142
1 files changed, 141 insertions, 1 deletions
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index a941e6a66996..24c4ae58dab5 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -31,6 +31,7 @@
31#include <linux/mfd/abx500/ab8500-gpadc.h> 31#include <linux/mfd/abx500/ab8500-gpadc.h>
32#include <linux/mfd/abx500/ux500_chargalg.h> 32#include <linux/mfd/abx500/ux500_chargalg.h>
33#include <linux/usb/otg.h> 33#include <linux/usb/otg.h>
34#include <linux/mutex.h>
34 35
35/* Charger constants */ 36/* Charger constants */
36#define NO_PW_CONN 0 37#define NO_PW_CONN 0
@@ -68,6 +69,11 @@
68#define MAIN_CH_NOK 0x01 69#define MAIN_CH_NOK 0x01
69#define VBUS_DET 0x80 70#define VBUS_DET 0x80
70 71
72#define MAIN_CH_STATUS2_MAINCHGDROP 0x80
73#define MAIN_CH_STATUS2_MAINCHARGERDETDBNC 0x40
74#define USB_CH_VBUSDROP 0x40
75#define USB_CH_VBUSDETDBNC 0x01
76
71/* UsbLineStatus register bit masks */ 77/* UsbLineStatus register bit masks */
72#define AB8500_USB_LINK_STATUS 0x78 78#define AB8500_USB_LINK_STATUS 0x78
73#define AB8500_STD_HOST_SUSP 0x18 79#define AB8500_STD_HOST_SUSP 0x18
@@ -82,6 +88,8 @@
82/* Step up/down delay in us */ 88/* Step up/down delay in us */
83#define STEP_UDELAY 1000 89#define STEP_UDELAY 1000
84 90
91#define CHARGER_STATUS_POLL 10 /* in ms */
92
85/* UsbLineStatus register - usb types */ 93/* UsbLineStatus register - usb types */
86enum ab8500_charger_link_status { 94enum ab8500_charger_link_status {
87 USB_STAT_NOT_CONFIGURED, 95 USB_STAT_NOT_CONFIGURED,
@@ -203,6 +211,10 @@ struct ab8500_charger_usb_state {
203 * @check_usbchgnotok_work: Work for checking USB charger not ok status 211 * @check_usbchgnotok_work: Work for checking USB charger not ok status
204 * @kick_wd_work: Work for kicking the charger watchdog in case 212 * @kick_wd_work: Work for kicking the charger watchdog in case
205 * of ABB rev 1.* due to the watchog logic bug 213 * of ABB rev 1.* due to the watchog logic bug
214 * @ac_charger_attached_work: Work for checking if AC charger is still
215 * connected
216 * @usb_charger_attached_work: Work for checking if USB charger is still
217 * connected
206 * @ac_work: Work for checking AC charger connection 218 * @ac_work: Work for checking AC charger connection
207 * @detect_usb_type_work: Work for detecting the USB type connected 219 * @detect_usb_type_work: Work for detecting the USB type connected
208 * @usb_link_status_work: Work for checking the new USB link status 220 * @usb_link_status_work: Work for checking the new USB link status
@@ -211,6 +223,7 @@ struct ab8500_charger_usb_state {
211 * Work for checking Main thermal status 223 * Work for checking Main thermal status
212 * @check_usb_thermal_prot_work: 224 * @check_usb_thermal_prot_work:
213 * Work for checking USB thermal status 225 * Work for checking USB thermal status
226 * @charger_attached_mutex: For controlling the wakelock
214 */ 227 */
215struct ab8500_charger { 228struct ab8500_charger {
216 struct device *dev; 229 struct device *dev;
@@ -239,6 +252,8 @@ struct ab8500_charger {
239 struct delayed_work check_hw_failure_work; 252 struct delayed_work check_hw_failure_work;
240 struct delayed_work check_usbchgnotok_work; 253 struct delayed_work check_usbchgnotok_work;
241 struct delayed_work kick_wd_work; 254 struct delayed_work kick_wd_work;
255 struct delayed_work ac_charger_attached_work;
256 struct delayed_work usb_charger_attached_work;
242 struct work_struct ac_work; 257 struct work_struct ac_work;
243 struct work_struct detect_usb_type_work; 258 struct work_struct detect_usb_type_work;
244 struct work_struct usb_link_status_work; 259 struct work_struct usb_link_status_work;
@@ -247,6 +262,7 @@ struct ab8500_charger {
247 struct work_struct check_usb_thermal_prot_work; 262 struct work_struct check_usb_thermal_prot_work;
248 struct usb_phy *usb_phy; 263 struct usb_phy *usb_phy;
249 struct notifier_block nb; 264 struct notifier_block nb;
265 struct mutex charger_attached_mutex;
250}; 266};
251 267
252/* AC properties */ 268/* AC properties */
@@ -349,6 +365,19 @@ static void ab8500_charger_set_usb_connected(struct ab8500_charger *di,
349 dev_dbg(di->dev, "USB connected:%i\n", connected); 365 dev_dbg(di->dev, "USB connected:%i\n", connected);
350 di->usb.charger_connected = connected; 366 di->usb.charger_connected = connected;
351 sysfs_notify(&di->usb_chg.psy.dev->kobj, NULL, "present"); 367 sysfs_notify(&di->usb_chg.psy.dev->kobj, NULL, "present");
368
369 if (connected) {
370 mutex_lock(&di->charger_attached_mutex);
371 mutex_unlock(&di->charger_attached_mutex);
372
373 queue_delayed_work(di->charger_wq,
374 &di->usb_charger_attached_work,
375 HZ);
376 } else {
377 cancel_delayed_work_sync(&di->usb_charger_attached_work);
378 mutex_lock(&di->charger_attached_mutex);
379 mutex_unlock(&di->charger_attached_mutex);
380 }
352 } 381 }
353} 382}
354 383
@@ -1706,6 +1735,84 @@ static void ab8500_charger_ac_work(struct work_struct *work)
1706 sysfs_notify(&di->ac_chg.psy.dev->kobj, NULL, "present"); 1735 sysfs_notify(&di->ac_chg.psy.dev->kobj, NULL, "present");
1707} 1736}
1708 1737
1738static void ab8500_charger_usb_attached_work(struct work_struct *work)
1739{
1740 struct ab8500_charger *di = container_of(work,
1741 struct ab8500_charger,
1742 usb_charger_attached_work.work);
1743 int usbch = (USB_CH_VBUSDROP | USB_CH_VBUSDETDBNC);
1744 int ret, i;
1745 u8 statval;
1746
1747 for (i = 0; i < 10; i++) {
1748 ret = abx500_get_register_interruptible(di->dev,
1749 AB8500_CHARGER,
1750 AB8500_CH_USBCH_STAT1_REG,
1751 &statval);
1752 if (ret < 0) {
1753 dev_err(di->dev, "ab8500 read failed %d\n", __LINE__);
1754 goto reschedule;
1755 }
1756 if ((statval & usbch) != usbch)
1757 goto reschedule;
1758
1759 msleep(CHARGER_STATUS_POLL);
1760 }
1761
1762 ab8500_charger_usb_en(&di->usb_chg, 0, 0, 0);
1763
1764 mutex_lock(&di->charger_attached_mutex);
1765 mutex_unlock(&di->charger_attached_mutex);
1766
1767 return;
1768
1769reschedule:
1770 queue_delayed_work(di->charger_wq,
1771 &di->usb_charger_attached_work,
1772 HZ);
1773}
1774
1775static void ab8500_charger_ac_attached_work(struct work_struct *work)
1776{
1777
1778 struct ab8500_charger *di = container_of(work,
1779 struct ab8500_charger,
1780 ac_charger_attached_work.work);
1781 int mainch = (MAIN_CH_STATUS2_MAINCHGDROP |
1782 MAIN_CH_STATUS2_MAINCHARGERDETDBNC);
1783 int ret, i;
1784 u8 statval;
1785
1786 for (i = 0; i < 10; i++) {
1787 ret = abx500_get_register_interruptible(di->dev,
1788 AB8500_CHARGER,
1789 AB8500_CH_STATUS2_REG,
1790 &statval);
1791 if (ret < 0) {
1792 dev_err(di->dev, "ab8500 read failed %d\n", __LINE__);
1793 goto reschedule;
1794 }
1795
1796 if ((statval & mainch) != mainch)
1797 goto reschedule;
1798
1799 msleep(CHARGER_STATUS_POLL);
1800 }
1801
1802 ab8500_charger_ac_en(&di->ac_chg, 0, 0, 0);
1803 queue_work(di->charger_wq, &di->ac_work);
1804
1805 mutex_lock(&di->charger_attached_mutex);
1806 mutex_unlock(&di->charger_attached_mutex);
1807
1808 return;
1809
1810reschedule:
1811 queue_delayed_work(di->charger_wq,
1812 &di->ac_charger_attached_work,
1813 HZ);
1814}
1815
1709/** 1816/**
1710 * ab8500_charger_detect_usb_type_work() - work to detect USB type 1817 * ab8500_charger_detect_usb_type_work() - work to detect USB type
1711 * @work: Pointer to the work_struct structure 1818 * @work: Pointer to the work_struct structure
@@ -1986,6 +2093,10 @@ static irqreturn_t ab8500_charger_mainchunplugdet_handler(int irq, void *_di)
1986 dev_dbg(di->dev, "Main charger unplugged\n"); 2093 dev_dbg(di->dev, "Main charger unplugged\n");
1987 queue_work(di->charger_wq, &di->ac_work); 2094 queue_work(di->charger_wq, &di->ac_work);
1988 2095
2096 cancel_delayed_work_sync(&di->ac_charger_attached_work);
2097 mutex_lock(&di->charger_attached_mutex);
2098 mutex_unlock(&di->charger_attached_mutex);
2099
1989 return IRQ_HANDLED; 2100 return IRQ_HANDLED;
1990} 2101}
1991 2102
@@ -2003,6 +2114,11 @@ static irqreturn_t ab8500_charger_mainchplugdet_handler(int irq, void *_di)
2003 dev_dbg(di->dev, "Main charger plugged\n"); 2114 dev_dbg(di->dev, "Main charger plugged\n");
2004 queue_work(di->charger_wq, &di->ac_work); 2115 queue_work(di->charger_wq, &di->ac_work);
2005 2116
2117 mutex_lock(&di->charger_attached_mutex);
2118 mutex_unlock(&di->charger_attached_mutex);
2119 queue_delayed_work(di->charger_wq,
2120 &di->ac_charger_attached_work,
2121 HZ);
2006 return IRQ_HANDLED; 2122 return IRQ_HANDLED;
2007} 2123}
2008 2124
@@ -2634,7 +2750,7 @@ static int ab8500_charger_probe(struct platform_device *pdev)
2634 struct device_node *np = pdev->dev.of_node; 2750 struct device_node *np = pdev->dev.of_node;
2635 struct abx500_bm_data *plat = pdev->dev.platform_data; 2751 struct abx500_bm_data *plat = pdev->dev.platform_data;
2636 struct ab8500_charger *di; 2752 struct ab8500_charger *di;
2637 int irq, i, charger_status, ret = 0; 2753 int irq, i, charger_status, ret = 0, ch_stat;
2638 2754
2639 di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); 2755 di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
2640 if (!di) { 2756 if (!di) {
@@ -2713,12 +2829,19 @@ static int ab8500_charger_probe(struct platform_device *pdev)
2713 return -ENOMEM; 2829 return -ENOMEM;
2714 } 2830 }
2715 2831
2832 mutex_init(&di->charger_attached_mutex);
2833
2716 /* Init work for HW failure check */ 2834 /* Init work for HW failure check */
2717 INIT_DEFERRABLE_WORK(&di->check_hw_failure_work, 2835 INIT_DEFERRABLE_WORK(&di->check_hw_failure_work,
2718 ab8500_charger_check_hw_failure_work); 2836 ab8500_charger_check_hw_failure_work);
2719 INIT_DEFERRABLE_WORK(&di->check_usbchgnotok_work, 2837 INIT_DEFERRABLE_WORK(&di->check_usbchgnotok_work,
2720 ab8500_charger_check_usbchargernotok_work); 2838 ab8500_charger_check_usbchargernotok_work);
2721 2839
2840 INIT_DELAYED_WORK(&di->ac_charger_attached_work,
2841 ab8500_charger_ac_attached_work);
2842 INIT_DELAYED_WORK(&di->usb_charger_attached_work,
2843 ab8500_charger_usb_attached_work);
2844
2722 /* 2845 /*
2723 * For ABB revision 1.0 and 1.1 there is a bug in the watchdog 2846 * For ABB revision 1.0 and 1.1 there is a bug in the watchdog
2724 * logic. That means we have to continously kick the charger 2847 * logic. That means we have to continously kick the charger
@@ -2832,6 +2955,23 @@ static int ab8500_charger_probe(struct platform_device *pdev)
2832 2955
2833 platform_set_drvdata(pdev, di); 2956 platform_set_drvdata(pdev, di);
2834 2957
2958 mutex_lock(&di->charger_attached_mutex);
2959
2960 ch_stat = ab8500_charger_detect_chargers(di);
2961
2962 if ((ch_stat & AC_PW_CONN) == AC_PW_CONN) {
2963 queue_delayed_work(di->charger_wq,
2964 &di->ac_charger_attached_work,
2965 HZ);
2966 }
2967 if ((ch_stat & USB_PW_CONN) == USB_PW_CONN) {
2968 queue_delayed_work(di->charger_wq,
2969 &di->usb_charger_attached_work,
2970 HZ);
2971 }
2972
2973 mutex_unlock(&di->charger_attached_mutex);
2974
2835 return ret; 2975 return ret;
2836 2976
2837free_irq: 2977free_irq: