aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power
diff options
context:
space:
mode:
authorMichel JAOUEN <michel.jaouen@stericsson.com>2012-04-26 04:00:04 -0400
committerLee Jones <lee.jones@linaro.org>2013-01-23 06:33:02 -0500
commit01ec8c5423901c4fe8d97f786ed9a0c31215b53a (patch)
tree51e12bce93f8d030f7896a7df8dc5a66ec052d3f /drivers/power
parent8fd526fd18233887ba652079a369f4eee0de9d9d (diff)
pm2301: Provide u9540 support for the pm2301 charger
AC charger driver for the DB9540 based platforms. Signed-off-by: Rajkumar Kasirajan <rajkumar.kasirajan@stericsson.com> Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com> Signed-off-by: Lee Jones <lee.jones@linaro.org> Reviewed-by: Michel JAOUEN <michel.jaouen@stericsson.com> Tested-by: Michel JAOUEN <michel.jaouen@stericsson.com>
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/Kconfig7
-rw-r--r--drivers/power/Makefile1
-rw-r--r--drivers/power/ab8500_charger.c36
-rw-r--r--drivers/power/pm2301_charger.c1455
4 files changed, 1486 insertions, 13 deletions
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 9f45e2f77d53..4811b59ba730 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -346,6 +346,13 @@ config AB8500_BM
346 help 346 help
347 Say Y to include support for AB8500 battery management. 347 Say Y to include support for AB8500 battery management.
348 348
349config CHARGER_PM2301
350 bool "PM2301 Battery Charger Driver"
351 depends on AB8500_BM
352 help
353 Say Y to include support for PM2301 charger driver.
354 Depends on AB8500 battery management core.
355
349source "drivers/power/reset/Kconfig" 356source "drivers/power/reset/Kconfig"
350 357
351endif # POWER_SUPPLY 358endif # POWER_SUPPLY
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index b11e0c7ea0f1..aa966e806834 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_CHARGER_LP8727) += lp8727_charger.o
46obj-$(CONFIG_CHARGER_LP8788) += lp8788-charger.o 46obj-$(CONFIG_CHARGER_LP8788) += lp8788-charger.o
47obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o 47obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o
48obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o 48obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o
49obj-$(CONFIG_CHARGER_PM2301) += pm2301_charger.o
49obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o 50obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
50obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o 51obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
51obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o 52obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index d5a8bdadb49a..43ec82ba4275 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -2830,8 +2830,11 @@ static int ab8500_charger_remove(struct platform_device *pdev)
2830 destroy_workqueue(di->charger_wq); 2830 destroy_workqueue(di->charger_wq);
2831 2831
2832 flush_scheduled_work(); 2832 flush_scheduled_work();
2833 power_supply_unregister(&di->usb_chg.psy); 2833 if(di->usb_chg.enabled)
2834 power_supply_unregister(&di->ac_chg.psy); 2834 power_supply_unregister(&di->usb_chg.psy);
2835 if(di->ac_chg.enabled)
2836 power_supply_unregister(&di->ac_chg.psy);
2837
2835 platform_set_drvdata(pdev, NULL); 2838 platform_set_drvdata(pdev, NULL);
2836 2839
2837 return 0; 2840 return 0;
@@ -2899,6 +2902,7 @@ static int ab8500_charger_probe(struct platform_device *pdev)
2899 ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; 2902 ARRAY_SIZE(ab8500_charger_voltage_map) - 1];
2900 di->ac_chg.max_out_curr = ab8500_charger_current_map[ 2903 di->ac_chg.max_out_curr = ab8500_charger_current_map[
2901 ARRAY_SIZE(ab8500_charger_current_map) - 1]; 2904 ARRAY_SIZE(ab8500_charger_current_map) - 1];
2905 di->ac_chg.enabled = di->pdata->ac_enabled;
2902 2906
2903 /* USB supply */ 2907 /* USB supply */
2904 /* power_supply base class */ 2908 /* power_supply base class */
@@ -2917,7 +2921,7 @@ static int ab8500_charger_probe(struct platform_device *pdev)
2917 ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; 2921 ARRAY_SIZE(ab8500_charger_voltage_map) - 1];
2918 di->usb_chg.max_out_curr = ab8500_charger_current_map[ 2922 di->usb_chg.max_out_curr = ab8500_charger_current_map[
2919 ARRAY_SIZE(ab8500_charger_current_map) - 1]; 2923 ARRAY_SIZE(ab8500_charger_current_map) - 1];
2920 2924 di->usb_chg.enabled = di->pdata->usb_enabled;
2921 2925
2922 /* Create a work queue for the charger */ 2926 /* Create a work queue for the charger */
2923 di->charger_wq = 2927 di->charger_wq =
@@ -2995,17 +2999,21 @@ static int ab8500_charger_probe(struct platform_device *pdev)
2995 } 2999 }
2996 3000
2997 /* Register AC charger class */ 3001 /* Register AC charger class */
2998 ret = power_supply_register(di->dev, &di->ac_chg.psy); 3002 if(di->ac_chg.enabled) {
2999 if (ret) { 3003 ret = power_supply_register(di->dev, &di->ac_chg.psy);
3000 dev_err(di->dev, "failed to register AC charger\n"); 3004 if (ret) {
3001 goto free_charger_wq; 3005 dev_err(di->dev, "failed to register AC charger\n");
3006 goto free_charger_wq;
3007 }
3002 } 3008 }
3003 3009
3004 /* Register USB charger class */ 3010 /* Register USB charger class */
3005 ret = power_supply_register(di->dev, &di->usb_chg.psy); 3011 if(di->usb_chg.enabled) {
3006 if (ret) { 3012 ret = power_supply_register(di->dev, &di->usb_chg.psy);
3007 dev_err(di->dev, "failed to register USB charger\n"); 3013 if (ret) {
3008 goto free_ac; 3014 dev_err(di->dev, "failed to register USB charger\n");
3015 goto free_ac;
3016 }
3009 } 3017 }
3010 3018
3011 di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); 3019 di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
@@ -3085,9 +3093,11 @@ free_irq:
3085put_usb_phy: 3093put_usb_phy:
3086 usb_put_phy(di->usb_phy); 3094 usb_put_phy(di->usb_phy);
3087free_usb: 3095free_usb:
3088 power_supply_unregister(&di->usb_chg.psy); 3096 if(di->usb_chg.enabled)
3097 power_supply_unregister(&di->usb_chg.psy);
3089free_ac: 3098free_ac:
3090 power_supply_unregister(&di->ac_chg.psy); 3099 if(di->ac_chg.enabled)
3100 power_supply_unregister(&di->ac_chg.psy);
3091free_charger_wq: 3101free_charger_wq:
3092 destroy_workqueue(di->charger_wq); 3102 destroy_workqueue(di->charger_wq);
3093 return ret; 3103 return ret;
diff --git a/drivers/power/pm2301_charger.c b/drivers/power/pm2301_charger.c
new file mode 100644
index 000000000000..60a30323151e
--- /dev/null
+++ b/drivers/power/pm2301_charger.c
@@ -0,0 +1,1455 @@
1/*
2 * Power supply driver for ST Ericsson pm2xxx_charger charger
3 *
4 * Copyright 2012 ST Ericsson.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/init.h>
12#include <linux/module.h>
13#include <linux/device.h>
14#include <linux/interrupt.h>
15#include <linux/delay.h>
16#include <linux/slab.h>
17#include <linux/platform_device.h>
18#include <linux/power_supply.h>
19#include <linux/completion.h>
20#include <linux/regulator/consumer.h>
21#include <linux/err.h>
22#include <linux/i2c.h>
23#include <linux/workqueue.h>
24#include <linux/kobject.h>
25#include <linux/mfd/abx500.h>
26#include <linux/mfd/abx500/ab8500.h>
27#include <linux/mfd/abx500/ab8500-bm.h>
28#include <linux/mfd/abx500/ab8500-gpadc.h>
29#include <linux/mfd/abx500/ux500_chargalg.h>
30#include <linux/pm2301_charger.h>
31
32#define MAIN_WDOG_ENA 0x01
33#define MAIN_WDOG_KICK 0x02
34#define MAIN_WDOG_DIS 0x00
35#define CHARG_WD_KICK 0x01
36#define MAIN_CH_ENA 0x01
37#define MAIN_CH_NO_OVERSHOOT_ENA_N 0x02
38#define MAIN_CH_DET 0x01
39#define MAIN_CH_CV_ON 0x04
40#define OTP_ENABLE_WD 0x01
41
42#define MAIN_CH_INPUT_CURR_SHIFT 4
43
44#define LED_INDICATOR_PWM_ENA 0x01
45#define LED_INDICATOR_PWM_DIS 0x00
46#define LED_IND_CUR_5MA 0x04
47#define LED_INDICATOR_PWM_DUTY_252_256 0xBF
48
49/* HW failure constants */
50#define MAIN_CH_TH_PROT 0x02
51#define MAIN_CH_NOK 0x01
52
53/* Watchdog timeout constant */
54#define WD_TIMER 0x30 /* 4min */
55#define WD_KICK_INTERVAL (60 * HZ)
56
57/* Constant voltage/current */
58#define PM2XXX_CONST_CURR 0x0
59#define PM2XXX_CONST_VOLT 0x1
60
61/* Lowest charger voltage is 3.39V -> 0x4E */
62#define LOW_VOLT_REG 0x4E
63
64#define PM2XXX_BATT_CTRL_REG1 0x00
65#define PM2XXX_BATT_CTRL_REG2 0x01
66#define PM2XXX_BATT_CTRL_REG3 0x02
67#define PM2XXX_BATT_CTRL_REG4 0x03
68#define PM2XXX_BATT_CTRL_REG5 0x04
69#define PM2XXX_BATT_CTRL_REG6 0x05
70#define PM2XXX_BATT_CTRL_REG7 0x06
71#define PM2XXX_BATT_CTRL_REG8 0x07
72#define PM2XXX_NTC_CTRL_REG1 0x08
73#define PM2XXX_NTC_CTRL_REG2 0x09
74#define PM2XXX_BATT_CTRL_REG9 0x0A
75#define PM2XXX_BATT_STAT_REG1 0x0B
76#define PM2XXX_INP_VOLT_VPWR2 0x11
77#define PM2XXX_INP_DROP_VPWR2 0x13
78#define PM2XXX_INP_VOLT_VPWR1 0x15
79#define PM2XXX_INP_DROP_VPWR1 0x17
80#define PM2XXX_INP_MODE_VPWR 0x18
81#define PM2XXX_BATT_WD_KICK 0x70
82#define PM2XXX_DEV_VER_STAT 0x0C
83#define PM2XXX_THERM_WARN_CTRL_REG 0x20
84#define PM2XXX_BATT_DISC_REG 0x21
85#define PM2XXX_BATT_LOW_LEV_COMP_REG 0x22
86#define PM2XXX_BATT_LOW_LEV_VAL_REG 0x23
87#define PM2XXX_I2C_PAD_CTRL_REG 0x24
88#define PM2XXX_SW_CTRL_REG 0x26
89#define PM2XXX_LED_CTRL_REG 0x28
90
91#define PM2XXX_REG_INT1 0x40
92#define PM2XXX_MASK_REG_INT1 0x50
93#define PM2XXX_SRCE_REG_INT1 0x60
94#define PM2XXX_REG_INT2 0x41
95#define PM2XXX_MASK_REG_INT2 0x51
96#define PM2XXX_SRCE_REG_INT2 0x61
97#define PM2XXX_REG_INT3 0x42
98#define PM2XXX_MASK_REG_INT3 0x52
99#define PM2XXX_SRCE_REG_INT3 0x62
100#define PM2XXX_REG_INT4 0x43
101#define PM2XXX_MASK_REG_INT4 0x53
102#define PM2XXX_SRCE_REG_INT4 0x63
103#define PM2XXX_REG_INT5 0x44
104#define PM2XXX_MASK_REG_INT5 0x54
105#define PM2XXX_SRCE_REG_INT5 0x64
106#define PM2XXX_REG_INT6 0x45
107#define PM2XXX_MASK_REG_INT6 0x55
108#define PM2XXX_SRCE_REG_INT6 0x65
109
110#define VPWR_OVV 0x0
111#define VSYSTEM_OVV 0x1
112
113/* control Reg 1 */
114#define PM2XXX_CH_RESUME_EN 0x1
115#define PM2XXX_CH_RESUME_DIS 0x0
116
117/* control Reg 2 */
118#define PM2XXX_CH_AUTO_RESUME_EN 0X2
119#define PM2XXX_CH_AUTO_RESUME_DIS 0X0
120#define PM2XXX_CHARGER_ENA 0x4
121#define PM2XXX_CHARGER_DIS 0x0
122
123/* control Reg 3 */
124#define PM2XXX_CH_WD_CC_PHASE_OFF 0x0
125#define PM2XXX_CH_WD_CC_PHASE_5MIN 0x1
126#define PM2XXX_CH_WD_CC_PHASE_10MIN 0x2
127#define PM2XXX_CH_WD_CC_PHASE_30MIN 0x3
128#define PM2XXX_CH_WD_CC_PHASE_60MIN 0x4
129#define PM2XXX_CH_WD_CC_PHASE_120MIN 0x5
130#define PM2XXX_CH_WD_CC_PHASE_240MIN 0x6
131#define PM2XXX_CH_WD_CC_PHASE_360MIN 0x7
132
133#define PM2XXX_CH_WD_CV_PHASE_OFF (0x0<<3)
134#define PM2XXX_CH_WD_CV_PHASE_5MIN (0x1<<3)
135#define PM2XXX_CH_WD_CV_PHASE_10MIN (0x2<<3)
136#define PM2XXX_CH_WD_CV_PHASE_30MIN (0x3<<3)
137#define PM2XXX_CH_WD_CV_PHASE_60MIN (0x4<<3)
138#define PM2XXX_CH_WD_CV_PHASE_120MIN (0x5<<3)
139#define PM2XXX_CH_WD_CV_PHASE_240MIN (0x6<<3)
140#define PM2XXX_CH_WD_CV_PHASE_360MIN (0x7<<3)
141
142/* control Reg 4 */
143#define PM2XXX_CH_WD_PRECH_PHASE_OFF 0x0
144#define PM2XXX_CH_WD_PRECH_PHASE_1MIN 0x1
145#define PM2XXX_CH_WD_PRECH_PHASE_5MIN 0x2
146#define PM2XXX_CH_WD_PRECH_PHASE_10MIN 0x3
147#define PM2XXX_CH_WD_PRECH_PHASE_30MIN 0x4
148#define PM2XXX_CH_WD_PRECH_PHASE_60MIN 0x5
149#define PM2XXX_CH_WD_PRECH_PHASE_120MIN 0x6
150#define PM2XXX_CH_WD_PRECH_PHASE_240MIN 0x7
151
152/* control Reg 5 */
153#define PM2XXX_CH_WD_AUTO_TIMEOUT_NONE 0x0
154#define PM2XXX_CH_WD_AUTO_TIMEOUT_20MIN 0x1
155
156/* control Reg 6 */
157#define PM2XXX_DIR_CH_CC_CURRENT_MASK 0x0F
158#define PM2XXX_DIR_CH_CC_CURRENT_200MA 0x0
159#define PM2XXX_DIR_CH_CC_CURRENT_400MA 0x2
160#define PM2XXX_DIR_CH_CC_CURRENT_600MA 0x3
161#define PM2XXX_DIR_CH_CC_CURRENT_800MA 0x4
162#define PM2XXX_DIR_CH_CC_CURRENT_1000MA 0x5
163#define PM2XXX_DIR_CH_CC_CURRENT_1200MA 0x6
164#define PM2XXX_DIR_CH_CC_CURRENT_1400MA 0x7
165#define PM2XXX_DIR_CH_CC_CURRENT_1600MA 0x8
166#define PM2XXX_DIR_CH_CC_CURRENT_1800MA 0x9
167#define PM2XXX_DIR_CH_CC_CURRENT_2000MA 0xA
168#define PM2XXX_DIR_CH_CC_CURRENT_2200MA 0xB
169#define PM2XXX_DIR_CH_CC_CURRENT_2400MA 0xC
170#define PM2XXX_DIR_CH_CC_CURRENT_2600MA 0xD
171#define PM2XXX_DIR_CH_CC_CURRENT_2800MA 0xE
172#define PM2XXX_DIR_CH_CC_CURRENT_3000MA 0xF
173
174#define PM2XXX_CH_PRECH_CURRENT_MASK 0x30
175#define PM2XXX_CH_PRECH_CURRENT_25MA (0x0<<4)
176#define PM2XXX_CH_PRECH_CURRENT_50MA (0x1<<4)
177#define PM2XXX_CH_PRECH_CURRENT_75MA (0x2<<4)
178#define PM2XXX_CH_PRECH_CURRENT_100MA (0x3<<4)
179
180#define PM2XXX_CH_EOC_CURRENT_MASK 0xC0
181#define PM2XXX_CH_EOC_CURRENT_100MA (0x0<<6)
182#define PM2XXX_CH_EOC_CURRENT_150MA (0x1<<6)
183#define PM2XXX_CH_EOC_CURRENT_300MA (0x2<<6)
184#define PM2XXX_CH_EOC_CURRENT_400MA (0x3<<6)
185
186/* control Reg 7 */
187#define PM2XXX_CH_PRECH_VOL_2_5 0x0
188#define PM2XXX_CH_PRECH_VOL_2_7 0x1
189#define PM2XXX_CH_PRECH_VOL_2_9 0x2
190#define PM2XXX_CH_PRECH_VOL_3_1 0x3
191
192#define PM2XXX_CH_VRESUME_VOL_3_2 (0x0<<2)
193#define PM2XXX_CH_VRESUME_VOL_3_4 (0x1<<2)
194#define PM2XXX_CH_VRESUME_VOL_3_6 (0x2<<2)
195#define PM2XXX_CH_VRESUME_VOL_3_8 (0x3<<2)
196
197/* control Reg 8 */
198#define PM2XXX_CH_VOLT_MASK 0x3F
199#define PM2XXX_CH_VOLT_3_5 0x0
200#define PM2XXX_CH_VOLT_3_5225 0x1
201#define PM2XXX_CH_VOLT_3_6 0x4
202#define PM2XXX_CH_VOLT_3_7 0x8
203#define PM2XXX_CH_VOLT_4_0 0x14
204#define PM2XXX_CH_VOLT_4_175 0x1B
205#define PM2XXX_CH_VOLT_4_2 0x1C
206#define PM2XXX_CH_VOLT_4_275 0x1F
207#define PM2XXX_CH_VOLT_4_3 0x20
208
209/*NTC control register 1*/
210#define PM2XXX_BTEMP_HIGH_TH_45 0x0
211#define PM2XXX_BTEMP_HIGH_TH_50 0x1
212#define PM2XXX_BTEMP_HIGH_TH_55 0x2
213#define PM2XXX_BTEMP_HIGH_TH_60 0x3
214#define PM2XXX_BTEMP_HIGH_TH_65 0x4
215
216#define PM2XXX_BTEMP_LOW_TH_N5 (0x0<<3)
217#define PM2XXX_BTEMP_LOW_TH_0 (0x1<<3)
218#define PM2XXX_BTEMP_LOW_TH_5 (0x2<<3)
219#define PM2XXX_BTEMP_LOW_TH_10 (0x3<<3)
220
221/*NTC control register 2*/
222#define PM2XXX_NTC_BETA_COEFF_3477 0x0
223#define PM2XXX_NTC_BETA_COEFF_3964 0x1
224
225#define PM2XXX_NTC_RES_10K (0x0<<2)
226#define PM2XXX_NTC_RES_47K (0x1<<2)
227#define PM2XXX_NTC_RES_100K (0x2<<2)
228#define PM2XXX_NTC_RES_NO_NTC (0x3<<2)
229
230/* control Reg 9 */
231#define PM2XXX_CH_CC_MODEDROP_EN 1
232#define PM2XXX_CH_CC_MODEDROP_DIS 0
233
234#define PM2XXX_CH_CC_REDUCED_CURRENT_100MA (0x0<<1)
235#define PM2XXX_CH_CC_REDUCED_CURRENT_200MA (0x1<<1)
236#define PM2XXX_CH_CC_REDUCED_CURRENT_400MA (0x2<<1)
237#define PM2XXX_CH_CC_REDUCED_CURRENT_IDENT (0x3<<1)
238
239#define PM2XXX_CHARCHING_INFO_DIS (0<<3)
240#define PM2XXX_CHARCHING_INFO_EN (1<<3)
241
242#define PM2XXX_CH_150MV_DROP_300MV (0<<4)
243#define PM2XXX_CH_150MV_DROP_150MV (1<<4)
244
245
246/* charger status register */
247#define PM2XXX_CHG_STATUS_OFF 0x0
248#define PM2XXX_CHG_STATUS_ON 0x1
249#define PM2XXX_CHG_STATUS_FULL 0x2
250#define PM2XXX_CHG_STATUS_ERR 0x3
251#define PM2XXX_CHG_STATUS_WAIT 0x4
252#define PM2XXX_CHG_STATUS_NOBAT 0x5
253
254/* Input charger voltage VPWR2 */
255#define PM2XXX_VPWR2_OVV_6_0 0x0
256#define PM2XXX_VPWR2_OVV_6_3 0x1
257#define PM2XXX_VPWR2_OVV_10 0x2
258#define PM2XXX_VPWR2_OVV_NONE 0x3
259
260/* Input charger voltage VPWR1 */
261#define PM2XXX_VPWR1_OVV_6_0 0x0
262#define PM2XXX_VPWR1_OVV_6_3 0x1
263#define PM2XXX_VPWR1_OVV_10 0x2
264#define PM2XXX_VPWR1_OVV_NONE 0x3
265
266/* Battery low level comparator control register */
267#define PM2XXX_VBAT_LOW_MONITORING_DIS 0x0
268#define PM2XXX_VBAT_LOW_MONITORING_ENA 0x1
269
270/* Battery low level value control register */
271#define PM2XXX_VBAT_LOW_LEVEL_2_3 0x0
272#define PM2XXX_VBAT_LOW_LEVEL_2_4 0x1
273#define PM2XXX_VBAT_LOW_LEVEL_2_5 0x2
274#define PM2XXX_VBAT_LOW_LEVEL_2_6 0x3
275#define PM2XXX_VBAT_LOW_LEVEL_2_7 0x4
276#define PM2XXX_VBAT_LOW_LEVEL_2_8 0x5
277#define PM2XXX_VBAT_LOW_LEVEL_2_9 0x6
278#define PM2XXX_VBAT_LOW_LEVEL_3_0 0x7
279#define PM2XXX_VBAT_LOW_LEVEL_3_1 0x8
280#define PM2XXX_VBAT_LOW_LEVEL_3_2 0x9
281#define PM2XXX_VBAT_LOW_LEVEL_3_3 0xA
282#define PM2XXX_VBAT_LOW_LEVEL_3_4 0xB
283#define PM2XXX_VBAT_LOW_LEVEL_3_5 0xC
284#define PM2XXX_VBAT_LOW_LEVEL_3_6 0xD
285#define PM2XXX_VBAT_LOW_LEVEL_3_7 0xE
286#define PM2XXX_VBAT_LOW_LEVEL_3_8 0xF
287#define PM2XXX_VBAT_LOW_LEVEL_3_9 0x10
288#define PM2XXX_VBAT_LOW_LEVEL_4_0 0x11
289#define PM2XXX_VBAT_LOW_LEVEL_4_1 0x12
290#define PM2XXX_VBAT_LOW_LEVEL_4_2 0x13
291
292/* SW CTRL */
293#define PM2XXX_SWCTRL_HW 0x0
294#define PM2XXX_SWCTRL_SW 0x1
295
296
297/* LED Driver Control */
298#define PM2XXX_LED_CURRENT_MASK 0x0C
299#define PM2XXX_LED_CURRENT_2_5MA (0X0<<2)
300#define PM2XXX_LED_CURRENT_1MA (0X1<<2)
301#define PM2XXX_LED_CURRENT_5MA (0X2<<2)
302#define PM2XXX_LED_CURRENT_10MA (0X3<<2)
303
304#define PM2XXX_LED_SELECT_MASK 0x02
305#define PM2XXX_LED_SELECT_EN (0X0<<1)
306#define PM2XXX_LED_SELECT_DIS (0X1<<1)
307
308#define PM2XXX_ANTI_OVERSHOOT_MASK 0x01
309#define PM2XXX_ANTI_OVERSHOOT_DIS 0X0
310#define PM2XXX_ANTI_OVERSHOOT_EN 0X1
311
312#define to_pm2xxx_charger_ac_device_info(x) container_of((x), \
313 struct pm2xxx_charger, ac_chg)
314
315static int pm2xxx_interrupt_registers[] = {
316 PM2XXX_REG_INT1,
317 PM2XXX_REG_INT2,
318 PM2XXX_REG_INT3,
319 PM2XXX_REG_INT4,
320 PM2XXX_REG_INT5,
321 PM2XXX_REG_INT6,
322};
323
324enum pm2xxx_reg_int1 {
325 PM2XXX_INT1_ITVBATDISCONNECT = 0x02,
326 PM2XXX_INT1_ITVBATLOWR = 0x04,
327 PM2XXX_INT1_ITVBATLOWF = 0x08,
328};
329
330enum pm2xxx_mask_reg_int1 {
331 PM2XXX_INT1_M_ITVBATDISCONNECT = 0x02,
332 PM2XXX_INT1_M_ITVBATLOWR = 0x04,
333 PM2XXX_INT1_M_ITVBATLOWF = 0x08,
334};
335
336enum pm2xxx_source_reg_int1 {
337 PM2XXX_INT1_S_ITVBATDISCONNECT = 0x02,
338 PM2XXX_INT1_S_ITVBATLOWR = 0x04,
339 PM2XXX_INT1_S_ITVBATLOWF = 0x08,
340};
341
342enum pm2xxx_reg_int2 {
343 PM2XXX_INT2_ITVPWR2PLUG = 0x01,
344 PM2XXX_INT2_ITVPWR2UNPLUG = 0x02,
345 PM2XXX_INT2_ITVPWR1PLUG = 0x04,
346 PM2XXX_INT2_ITVPWR1UNPLUG = 0x08,
347};
348
349enum pm2xxx_mask_reg_int2 {
350 PM2XXX_INT2_M_ITVPWR2PLUG = 0x01,
351 PM2XXX_INT2_M_ITVPWR2UNPLUG = 0x02,
352 PM2XXX_INT2_M_ITVPWR1PLUG = 0x04,
353 PM2XXX_INT2_M_ITVPWR1UNPLUG = 0x08,
354};
355
356enum pm2xxx_source_reg_int2 {
357 PM2XXX_INT2_S_ITVPWR2PLUG = 0x03,
358 PM2XXX_INT2_S_ITVPWR1PLUG = 0x0c,
359};
360
361enum pm2xxx_reg_int3 {
362 PM2XXX_INT3_ITCHPRECHARGEWD = 0x01,
363 PM2XXX_INT3_ITCHCCWD = 0x02,
364 PM2XXX_INT3_ITCHCVWD = 0x04,
365 PM2XXX_INT3_ITAUTOTIMEOUTWD = 0x08,
366};
367
368enum pm2xxx_mask_reg_int3 {
369 PM2XXX_INT3_M_ITCHPRECHARGEWD = 0x01,
370 PM2XXX_INT3_M_ITCHCCWD = 0x02,
371 PM2XXX_INT3_M_ITCHCVWD = 0x04,
372 PM2XXX_INT3_M_ITAUTOTIMEOUTWD = 0x08,
373};
374
375enum pm2xxx_source_reg_int3 {
376 PM2XXX_INT3_S_ITCHPRECHARGEWD = 0x01,
377 PM2XXX_INT3_S_ITCHCCWD = 0x02,
378 PM2XXX_INT3_S_ITCHCVWD = 0x04,
379 PM2XXX_INT3_S_ITAUTOTIMEOUTWD = 0x08,
380};
381
382enum pm2xxx_reg_int4 {
383 PM2XXX_INT4_ITBATTEMPCOLD = 0x01,
384 PM2XXX_INT4_ITBATTEMPHOT = 0x02,
385 PM2XXX_INT4_ITVPWR2OVV = 0x04,
386 PM2XXX_INT4_ITVPWR1OVV = 0x08,
387 PM2XXX_INT4_ITCHARGINGON = 0x10,
388 PM2XXX_INT4_ITVRESUME = 0x20,
389 PM2XXX_INT4_ITBATTFULL = 0x40,
390 PM2XXX_INT4_ITCVPHASE = 0x80,
391};
392
393enum pm2xxx_mask_reg_int4 {
394 PM2XXX_INT4_M_ITBATTEMPCOLD = 0x01,
395 PM2XXX_INT4_M_ITBATTEMPHOT = 0x02,
396 PM2XXX_INT4_M_ITVPWR2OVV = 0x04,
397 PM2XXX_INT4_M_ITVPWR1OVV = 0x08,
398 PM2XXX_INT4_M_ITCHARGINGON = 0x10,
399 PM2XXX_INT4_M_ITVRESUME = 0x20,
400 PM2XXX_INT4_M_ITBATTFULL = 0x40,
401 PM2XXX_INT4_M_ITCVPHASE = 0x80,
402};
403
404enum pm2xxx_source_reg_int4 {
405 PM2XXX_INT4_S_ITBATTEMPCOLD = 0x01,
406 PM2XXX_INT4_S_ITBATTEMPHOT = 0x02,
407 PM2XXX_INT4_S_ITVPWR2OVV = 0x04,
408 PM2XXX_INT4_S_ITVPWR1OVV = 0x08,
409 PM2XXX_INT4_S_ITCHARGINGON = 0x10,
410 PM2XXX_INT4_S_ITVRESUME = 0x20,
411 PM2XXX_INT4_S_ITBATTFULL = 0x40,
412 PM2XXX_INT4_S_ITCVPHASE = 0x80,
413};
414
415enum pm2xxx_reg_int5 {
416 PM2XXX_INT5_ITTHERMALSHUTDOWNRISE = 0x01,
417 PM2XXX_INT5_ITTHERMALSHUTDOWNFALL = 0x02,
418 PM2XXX_INT5_ITTHERMALWARNINGRISE = 0x04,
419 PM2XXX_INT5_ITTHERMALWARNINGFALL = 0x08,
420 PM2XXX_INT5_ITVSYSTEMOVV = 0x10,
421};
422
423enum pm2xxx_mask_reg_int5 {
424 PM2XXX_INT5_M_ITTHERMALSHUTDOWNRISE = 0x01,
425 PM2XXX_INT5_M_ITTHERMALSHUTDOWNFALL = 0x02,
426 PM2XXX_INT5_M_ITTHERMALWARNINGRISE = 0x04,
427 PM2XXX_INT5_M_ITTHERMALWARNINGFALL = 0x08,
428 PM2XXX_INT5_M_ITVSYSTEMOVV = 0x10,
429};
430
431enum pm2xxx_source_reg_int5 {
432 PM2XXX_INT5_S_ITTHERMALSHUTDOWNRISE = 0x01,
433 PM2XXX_INT5_S_ITTHERMALSHUTDOWNFALL = 0x02,
434 PM2XXX_INT5_S_ITTHERMALWARNINGRISE = 0x04,
435 PM2XXX_INT5_S_ITTHERMALWARNINGFALL = 0x08,
436 PM2XXX_INT5_S_ITVSYSTEMOVV = 0x10,
437};
438
439enum pm2xxx_reg_int6 {
440 PM2XXX_INT6_ITVPWR2DROP = 0x01,
441 PM2XXX_INT6_ITVPWR1DROP = 0x02,
442 PM2XXX_INT6_ITVPWR2VALIDRISE = 0x04,
443 PM2XXX_INT6_ITVPWR2VALIDFALL = 0x08,
444 PM2XXX_INT6_ITVPWR1VALIDRISE = 0x10,
445 PM2XXX_INT6_ITVPWR1VALIDFALL = 0x20,
446};
447
448enum pm2xxx_mask_reg_int6 {
449 PM2XXX_INT6_M_ITVPWR2DROP = 0x01,
450 PM2XXX_INT6_M_ITVPWR1DROP = 0x02,
451 PM2XXX_INT6_M_ITVPWR2VALIDRISE = 0x04,
452 PM2XXX_INT6_M_ITVPWR2VALIDFALL = 0x08,
453 PM2XXX_INT6_M_ITVPWR1VALIDRISE = 0x10,
454 PM2XXX_INT6_M_ITVPWR1VALIDFALL = 0x20,
455};
456
457enum pm2xxx_source_reg_int6 {
458 PM2XXX_INT6_S_ITVPWR2DROP = 0x01,
459 PM2XXX_INT6_S_ITVPWR1DROP = 0x02,
460 PM2XXX_INT6_S_ITVPWR2VALIDRISE = 0x04,
461 PM2XXX_INT6_S_ITVPWR2VALIDFALL = 0x08,
462 PM2XXX_INT6_S_ITVPWR1VALIDRISE = 0x10,
463 PM2XXX_INT6_S_ITVPWR1VALIDFALL = 0x20,
464};
465
466static enum power_supply_property pm2xxx_charger_ac_props[] = {
467 POWER_SUPPLY_PROP_HEALTH,
468 POWER_SUPPLY_PROP_PRESENT,
469 POWER_SUPPLY_PROP_ONLINE,
470 POWER_SUPPLY_PROP_VOLTAGE_NOW,
471 POWER_SUPPLY_PROP_VOLTAGE_AVG,
472 POWER_SUPPLY_PROP_CURRENT_NOW,
473};
474
475static int pm2xxx_charger_voltage_map[] = {
476 3500,
477 3525,
478 3550,
479 3575,
480 3600,
481 3625,
482 3650,
483 3675,
484 3700,
485 3725,
486 3750,
487 3775,
488 3800,
489 3825,
490 3850,
491 3875,
492 3900,
493 3925,
494 3950,
495 3975,
496 4000,
497 4025,
498 4050,
499 4075,
500 4100,
501 4125,
502 4150,
503 4175,
504 4200,
505 4225,
506 4250,
507 4275,
508 4300,
509};
510
511static int pm2xxx_charger_current_map[] = {
512 200,
513 200,
514 400,
515 600,
516 800,
517 1000,
518 1200,
519 1400,
520 1600,
521 1800,
522 2000,
523 2200,
524 2400,
525 2600,
526 2800,
527 3000,
528};
529
530struct pm2xxx_irq {
531 char *name;
532 irqreturn_t (*isr)(int irq, void *data);
533};
534
535struct pm2xxx_charger_info {
536 int charger_connected;
537 int charger_online;
538 int charger_voltage;
539 int cv_active;
540 bool wd_expired;
541};
542
543struct pm2xxx_charger_event_flags {
544 bool mainextchnotok;
545 bool main_thermal_prot;
546 bool ovv;
547 bool chgwdexp;
548};
549
550struct pm2xxx_config {
551 struct i2c_client *pm2xxx_i2c;
552 struct i2c_device_id *pm2xxx_id;
553};
554
555struct pm2xxx_charger {
556 struct device *dev;
557 u8 chip_id;
558 bool vddadc_en_ac;
559 struct pm2xxx_config config;
560 bool ac_conn;
561 unsigned int gpio_irq;
562 int vbat;
563 int old_vbat;
564 int failure_case;
565 int failure_input_ovv;
566 u8 pm2_int[6];
567 struct ab8500_gpadc *gpadc;
568 struct regulator *regu;
569 struct pm2xxx_bm_data *bat;
570 struct mutex lock;
571 struct ab8500 *parent;
572 struct pm2xxx_charger_info ac;
573 struct pm2xxx_charger_platform_data *pdata;
574 struct workqueue_struct *charger_wq;
575 struct delayed_work check_vbat_work;
576 struct work_struct ac_work;
577 struct work_struct check_main_thermal_prot_work;
578 struct ux500_charger ac_chg;
579 struct pm2xxx_charger_event_flags flags;
580};
581
582static const struct i2c_device_id pm2xxx_ident[] = {
583 { "pm2301", 0 },
584 { }
585};
586
587static int pm2xxx_reg_read(struct pm2xxx_charger *pm2, int reg, u8 *val)
588{
589 int ret;
590
591 ret = i2c_smbus_read_i2c_block_data(pm2->config.pm2xxx_i2c, reg,
592 1, val);
593 if (ret < 0)
594 dev_err(pm2->dev, "Error reading register at 0x%x\n", reg);
595
596 return ret;
597}
598
599static int pm2xxx_reg_write(struct pm2xxx_charger *pm2, int reg, u8 val)
600{
601 int ret;
602
603 ret = i2c_smbus_write_i2c_block_data(pm2->config.pm2xxx_i2c, reg,
604 1, &val);
605 if (ret < 0)
606 dev_err(pm2->dev, "Error writing register at 0x%x\n", reg);
607
608 return ret;
609}
610
611static int pm2xxx_charging_enable_mngt(struct pm2xxx_charger *pm2)
612{
613 int ret;
614
615 /* Enable charging */
616 ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG2,
617 (PM2XXX_CH_AUTO_RESUME_EN | PM2XXX_CHARGER_ENA));
618
619 return ret;
620}
621
622static int pm2xxx_charging_disable_mngt(struct pm2xxx_charger *pm2)
623{
624 int ret;
625
626 /* Disable charging */
627 ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG2,
628 (PM2XXX_CH_AUTO_RESUME_DIS | PM2XXX_CHARGER_DIS));
629
630 return ret;
631}
632
633static int pm2xxx_charger_batt_therm_mngt(struct pm2xxx_charger *pm2, int val)
634{
635 queue_work(pm2->charger_wq, &pm2->check_main_thermal_prot_work);
636
637 return 0;
638}
639
640
641int pm2xxx_charger_die_therm_mngt(struct pm2xxx_charger *pm2, int val)
642{
643 queue_work(pm2->charger_wq, &pm2->check_main_thermal_prot_work);
644
645 return 0;
646}
647
648static int pm2xxx_charger_ovv_mngt(struct pm2xxx_charger *pm2, int val)
649{
650 int ret = 0;
651
652 pm2->failure_input_ovv++;
653 if (pm2->failure_input_ovv < 4) {
654 ret = pm2xxx_charging_enable_mngt(pm2);
655 goto out;
656 } else {
657 pm2->failure_input_ovv = 0;
658 dev_err(pm2->dev, "Overvoltage detected\n");
659 pm2->flags.ovv = true;
660 power_supply_changed(&pm2->ac_chg.psy);
661 }
662
663out:
664 return ret;
665}
666
667static int pm2xxx_charger_wd_exp_mngt(struct pm2xxx_charger *pm2, int val)
668{
669 dev_dbg(pm2->dev , "20 minutes watchdog occured\n");
670
671 pm2->ac.wd_expired = true;
672 power_supply_changed(&pm2->ac_chg.psy);
673
674 return 0;
675}
676
677static int pm2xxx_charger_vbat_lsig_mngt(struct pm2xxx_charger *pm2, int val)
678{
679 switch (val) {
680 case PM2XXX_INT1_ITVBATLOWR:
681 dev_dbg(pm2->dev, "VBAT grows above VBAT_LOW level\n");
682 break;
683
684 case PM2XXX_INT1_ITVBATLOWF:
685 dev_dbg(pm2->dev, "VBAT drops below VBAT_LOW level\n");
686 break;
687
688 default:
689 dev_err(pm2->dev, "Unknown VBAT level\n");
690 }
691
692 return 0;
693}
694
695static int pm2xxx_charger_bat_disc_mngt(struct pm2xxx_charger *pm2, int val)
696{
697 dev_dbg(pm2->dev, "battery disconnected\n");
698
699 return (pm2xxx_charging_disable_mngt(pm2));
700}
701
702static int pm2xxx_charger_detection(struct pm2xxx_charger *pm2, u8 *val)
703{
704 int ret = 0;
705
706 ret = pm2xxx_reg_read(pm2, PM2XXX_SRCE_REG_INT2, val);
707
708 if (ret < 0) {
709 dev_err(pm2->dev, "Charger detection failed\n");
710 goto out;
711 }
712
713 *val &= (PM2XXX_INT2_S_ITVPWR1PLUG | PM2XXX_INT2_S_ITVPWR2PLUG);
714out:
715 return ret;
716}
717
718static int pm2xxx_charger_itv_pwr_plug_mngt(struct pm2xxx_charger *pm2, int val)
719{
720
721 int ret;
722 u8 read_val;
723
724 /*
725 * Since we can't be sure that the events are received
726 * synchronously, we have the check if the main charger is
727 * connected by reading the interrupt source register.
728 */
729 ret = pm2xxx_charger_detection(pm2, &read_val);
730
731 if ((ret == 0) && read_val) {
732 pm2->ac.charger_connected = 1;
733 pm2->ac_conn = true;
734 queue_work(pm2->charger_wq, &pm2->ac_work);
735 }
736
737
738 return ret;
739}
740
741static int pm2xxx_charger_itv_pwr_unplug_mngt(struct pm2xxx_charger *pm2,
742 int val)
743{
744 pm2->ac.charger_connected = 0;
745 queue_work(pm2->charger_wq, &pm2->ac_work);
746
747 return 0;
748}
749
750static int pm2_int_reg0(struct pm2xxx_charger *pm2)
751{
752 int ret = 0;
753
754 if (pm2->pm2_int[0] &
755 (PM2XXX_INT1_ITVBATLOWR | PM2XXX_INT1_ITVBATLOWF)) {
756 ret = pm2xxx_charger_vbat_lsig_mngt(pm2, pm2->pm2_int[0] &
757 (PM2XXX_INT1_ITVBATLOWR | PM2XXX_INT1_ITVBATLOWF));
758 }
759
760 if (pm2->pm2_int[0] & PM2XXX_INT1_ITVBATDISCONNECT) {
761 ret = pm2xxx_charger_bat_disc_mngt(pm2,
762 PM2XXX_INT1_ITVBATDISCONNECT);
763 }
764
765 return ret;
766}
767
768static int pm2_int_reg1(struct pm2xxx_charger *pm2)
769{
770 int ret = 0;
771
772 if (pm2->pm2_int[1] &
773 (PM2XXX_INT2_ITVPWR1PLUG | PM2XXX_INT2_ITVPWR2PLUG)) {
774 dev_dbg(pm2->dev , "Main charger plugged\n");
775 ret = pm2xxx_charger_itv_pwr_plug_mngt(pm2, pm2->pm2_int[1] &
776 (PM2XXX_INT2_ITVPWR1PLUG | PM2XXX_INT2_ITVPWR2PLUG));
777 }
778
779 if (pm2->pm2_int[1] &
780 (PM2XXX_INT2_ITVPWR1UNPLUG | PM2XXX_INT2_ITVPWR2UNPLUG)) {
781 dev_dbg(pm2->dev , "Main charger unplugged\n");
782 ret = pm2xxx_charger_itv_pwr_unplug_mngt(pm2, pm2->pm2_int[1] &
783 (PM2XXX_INT2_ITVPWR1UNPLUG |
784 PM2XXX_INT2_ITVPWR2UNPLUG));
785 }
786
787 return ret;
788}
789
790static int pm2_int_reg2(struct pm2xxx_charger *pm2)
791{
792 int ret = 0;
793
794 if (pm2->pm2_int[2] & PM2XXX_INT3_ITAUTOTIMEOUTWD)
795 ret = pm2xxx_charger_wd_exp_mngt(pm2, pm2->pm2_int[2]);
796
797 if (pm2->pm2_int[2] & (PM2XXX_INT3_ITCHPRECHARGEWD |
798 PM2XXX_INT3_ITCHCCWD | PM2XXX_INT3_ITCHCVWD)) {
799 dev_dbg(pm2->dev,
800 "Watchdog occured for precharge, CC and CV charge\n");
801 }
802
803 return ret;
804}
805
806static int pm2_int_reg3(struct pm2xxx_charger *pm2)
807{
808 int ret = 0;
809
810 if (pm2->pm2_int[3] & (PM2XXX_INT4_ITCHARGINGON)) {
811 dev_dbg(pm2->dev ,
812 "chargind operation has started\n");
813 }
814
815 if (pm2->pm2_int[3] & (PM2XXX_INT4_ITVRESUME)) {
816 dev_dbg(pm2->dev,
817 "battery discharged down to VResume threshold\n");
818 }
819
820 if (pm2->pm2_int[3] & (PM2XXX_INT4_ITBATTFULL)) {
821 dev_dbg(pm2->dev , "battery fully detected\n");
822 }
823
824 if (pm2->pm2_int[3] & (PM2XXX_INT4_ITCVPHASE)) {
825 dev_dbg(pm2->dev, "CV phase enter with 0.5C charging\n");
826 }
827
828 if (pm2->pm2_int[3] &
829 (PM2XXX_INT4_ITVPWR2OVV | PM2XXX_INT4_ITVPWR1OVV)) {
830 pm2->failure_case = VPWR_OVV;
831 ret = pm2xxx_charger_ovv_mngt(pm2, pm2->pm2_int[3] &
832 (PM2XXX_INT4_ITVPWR2OVV | PM2XXX_INT4_ITVPWR1OVV));
833 dev_dbg(pm2->dev, "VPWR/VSYSTEM overvoltage detected\n");
834 }
835
836 if (pm2->pm2_int[3] & (PM2XXX_INT4_S_ITBATTEMPCOLD |
837 PM2XXX_INT4_S_ITBATTEMPHOT)) {
838 ret = pm2xxx_charger_batt_therm_mngt(pm2,
839 pm2->pm2_int[3] & (PM2XXX_INT4_S_ITBATTEMPCOLD |
840 PM2XXX_INT4_S_ITBATTEMPHOT));
841 dev_dbg(pm2->dev, "BTEMP is too Low/High\n");
842 }
843
844 return ret;
845}
846
847static int pm2_int_reg4(struct pm2xxx_charger *pm2)
848{
849 int ret = 0;
850
851 if (pm2->pm2_int[4] & PM2XXX_INT5_ITVSYSTEMOVV) {
852 pm2->failure_case = VSYSTEM_OVV;
853 ret = pm2xxx_charger_ovv_mngt(pm2, pm2->pm2_int[4] &
854 PM2XXX_INT5_ITVSYSTEMOVV);
855 dev_dbg(pm2->dev, "VSYSTEM overvoltage detected\n");
856 }
857
858 if (pm2->pm2_int[4] & (PM2XXX_INT5_ITTHERMALWARNINGFALL |
859 PM2XXX_INT5_ITTHERMALWARNINGRISE |
860 PM2XXX_INT5_ITTHERMALSHUTDOWNFALL |
861 PM2XXX_INT5_ITTHERMALSHUTDOWNRISE)) {
862 dev_dbg(pm2->dev, "BTEMP die temperature is too Low/High\n");
863 ret = pm2xxx_charger_die_therm_mngt(pm2, pm2->pm2_int[4] &
864 (PM2XXX_INT5_ITTHERMALWARNINGFALL |
865 PM2XXX_INT5_ITTHERMALWARNINGRISE |
866 PM2XXX_INT5_ITTHERMALSHUTDOWNFALL |
867 PM2XXX_INT5_ITTHERMALSHUTDOWNRISE));
868 }
869
870 return ret;
871}
872
873static int pm2_int_reg5(struct pm2xxx_charger *pm2)
874{
875
876 if (pm2->pm2_int[5]
877 & (PM2XXX_INT6_ITVPWR2DROP | PM2XXX_INT6_ITVPWR1DROP)) {
878 dev_dbg(pm2->dev, "VMPWR drop to VBAT level\n");
879 }
880
881 if (pm2->pm2_int[5] & (PM2XXX_INT6_ITVPWR2VALIDRISE |
882 PM2XXX_INT6_ITVPWR1VALIDRISE |
883 PM2XXX_INT6_ITVPWR2VALIDFALL |
884 PM2XXX_INT6_ITVPWR1VALIDFALL)) {
885 dev_dbg(pm2->dev, "Falling/Rising edge on WPWR1/2\n");
886 }
887
888 return 0;
889}
890
891static irqreturn_t pm2xxx_irq_int(int irq, void *data)
892{
893 struct pm2xxx_charger *pm2 = data;
894 int ret, i;
895
896 for (i = 0; i < ARRAY_SIZE(pm2->pm2_int); i++) {
897 ret = pm2xxx_reg_read(pm2, pm2xxx_interrupt_registers[i],
898 &(pm2->pm2_int[i]));
899 }
900
901 pm2_int_reg0(pm2);
902 pm2_int_reg1(pm2);
903 pm2_int_reg2(pm2);
904 pm2_int_reg3(pm2);
905 pm2_int_reg4(pm2);
906 pm2_int_reg5(pm2);
907
908 return IRQ_HANDLED;
909}
910
911static int pm2xxx_charger_get_ac_voltage(struct pm2xxx_charger *pm2)
912{
913 int vch = 0;
914
915 if (pm2->ac.charger_connected) {
916 vch = ab8500_gpadc_convert(pm2->gpadc, MAIN_CHARGER_V);
917 if (vch < 0)
918 dev_err(pm2->dev, "%s gpadc conv failed,\n", __func__);
919 }
920
921 return vch;
922}
923
924static int pm2xxx_charger_get_ac_cv(struct pm2xxx_charger *pm2)
925{
926 int ret = 0;
927 u8 val;
928
929 if (pm2->ac.charger_connected && pm2->ac.charger_online) {
930
931 ret = pm2xxx_reg_read(pm2, PM2XXX_SRCE_REG_INT4, &val);
932 if (ret < 0) {
933 dev_err(pm2->dev, "%s pm2xxx read failed\n", __func__);
934 goto out;
935 }
936
937 if (val & PM2XXX_INT4_S_ITCVPHASE)
938 ret = PM2XXX_CONST_VOLT;
939 else
940 ret = PM2XXX_CONST_CURR;
941 }
942out:
943 return ret;
944}
945
946static int pm2xxx_charger_get_ac_current(struct pm2xxx_charger *pm2)
947{
948 int ich = 0;
949
950 if (pm2->ac.charger_online) {
951 ich = ab8500_gpadc_convert(pm2->gpadc, MAIN_CHARGER_C);
952 if (ich < 0)
953 dev_err(pm2->dev, "%s gpadc conv failed\n", __func__);
954 }
955
956 return ich;
957}
958
959static int pm2xxx_current_to_regval(int curr)
960{
961 int i;
962
963 if (curr < pm2xxx_charger_current_map[0])
964 return 0;
965
966 for (i = 1; i < ARRAY_SIZE(pm2xxx_charger_current_map); i++) {
967 if (curr < pm2xxx_charger_current_map[i])
968 return (i - 1);
969 }
970
971 i = ARRAY_SIZE(pm2xxx_charger_current_map) - 1;
972 if (curr == pm2xxx_charger_current_map[i])
973 return i;
974 else
975 return -EINVAL;
976}
977
978static int pm2xxx_voltage_to_regval(int curr)
979{
980 int i;
981
982 if (curr < pm2xxx_charger_voltage_map[0])
983 return 0;
984
985 for (i = 1; i < ARRAY_SIZE(pm2xxx_charger_voltage_map); i++) {
986 if (curr < pm2xxx_charger_voltage_map[i])
987 return i - 1;
988 }
989
990 i = ARRAY_SIZE(pm2xxx_charger_voltage_map) - 1;
991 if (curr == pm2xxx_charger_voltage_map[i])
992 return i;
993 else
994 return -EINVAL;
995}
996
997static int pm2xxx_charger_update_charger_current(struct ux500_charger *charger,
998 int ich_out)
999{
1000 int ret;
1001 int curr_index;
1002 struct pm2xxx_charger *pm2;
1003 u8 val;
1004
1005 if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS)
1006 pm2 = to_pm2xxx_charger_ac_device_info(charger);
1007 else
1008 return -ENXIO;
1009
1010 curr_index = pm2xxx_current_to_regval(ich_out);
1011 if (curr_index < 0) {
1012 dev_err(pm2->dev,
1013 "Charger current too high: charging not started\n");
1014 return -ENXIO;
1015 }
1016
1017 ret = pm2xxx_reg_read(pm2, PM2XXX_BATT_CTRL_REG6, &val);
1018 if (ret >= 0) {
1019 val &= ~PM2XXX_DIR_CH_CC_CURRENT_MASK;
1020 val |= curr_index;
1021 ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG6, val);
1022 if (ret < 0) {
1023 dev_err(pm2->dev,
1024 "%s write failed\n", __func__);
1025 }
1026 }
1027 else
1028 dev_err(pm2->dev, "%s read failed\n", __func__);
1029
1030 return ret;
1031}
1032
1033static int pm2xxx_charger_ac_get_property(struct power_supply *psy,
1034 enum power_supply_property psp,
1035 union power_supply_propval *val)
1036{
1037 struct pm2xxx_charger *pm2;
1038
1039 pm2 = to_pm2xxx_charger_ac_device_info(psy_to_ux500_charger(psy));
1040
1041 switch (psp) {
1042 case POWER_SUPPLY_PROP_HEALTH:
1043 if (pm2->flags.mainextchnotok)
1044 val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
1045 else if (pm2->ac.wd_expired)
1046 val->intval = POWER_SUPPLY_HEALTH_DEAD;
1047 else if (pm2->flags.main_thermal_prot)
1048 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
1049 else
1050 val->intval = POWER_SUPPLY_HEALTH_GOOD;
1051 break;
1052 case POWER_SUPPLY_PROP_ONLINE:
1053 val->intval = pm2->ac.charger_online;
1054 break;
1055 case POWER_SUPPLY_PROP_PRESENT:
1056 val->intval = pm2->ac.charger_connected;
1057 break;
1058 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
1059 pm2->ac.charger_voltage = pm2xxx_charger_get_ac_voltage(pm2);
1060 val->intval = pm2->ac.charger_voltage * 1000;
1061 break;
1062 case POWER_SUPPLY_PROP_VOLTAGE_AVG:
1063 pm2->ac.cv_active = pm2xxx_charger_get_ac_cv(pm2);
1064 val->intval = pm2->ac.cv_active;
1065 break;
1066 case POWER_SUPPLY_PROP_CURRENT_NOW:
1067 val->intval = pm2xxx_charger_get_ac_current(pm2) * 1000;
1068 break;
1069 default:
1070 return -EINVAL;
1071 }
1072 return 0;
1073}
1074
1075static int pm2xxx_charging_init(struct pm2xxx_charger *pm2)
1076{
1077 int ret = 0;
1078
1079 /* enable CC and CV watchdog */
1080 ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG3,
1081 (PM2XXX_CH_WD_CV_PHASE_60MIN | PM2XXX_CH_WD_CC_PHASE_60MIN));
1082 if( ret < 0)
1083 return ret;
1084
1085 /* enable precharge watchdog */
1086 ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG4,
1087 PM2XXX_CH_WD_PRECH_PHASE_60MIN);
1088
1089 return ret;
1090}
1091
1092static int pm2xxx_charger_ac_en(struct ux500_charger *charger,
1093 int enable, int vset, int iset)
1094{
1095 int ret;
1096 int volt_index;
1097 int curr_index;
1098 u8 val;
1099
1100 struct pm2xxx_charger *pm2 = to_pm2xxx_charger_ac_device_info(charger);
1101
1102 if (enable) {
1103 if (!pm2->ac.charger_connected) {
1104 dev_dbg(pm2->dev, "AC charger not connected\n");
1105 return -ENXIO;
1106 }
1107
1108 dev_dbg(pm2->dev, "Enable AC: %dmV %dmA\n", vset, iset);
1109 if (!pm2->vddadc_en_ac) {
1110 regulator_enable(pm2->regu);
1111 pm2->vddadc_en_ac = true;
1112 }
1113
1114 ret = pm2xxx_charging_init(pm2);
1115 if (ret < 0) {
1116 dev_err(pm2->dev, "%s charging init failed\n",
1117 __func__);
1118 goto error_occured;
1119 }
1120
1121 volt_index = pm2xxx_voltage_to_regval(vset);
1122 curr_index = pm2xxx_current_to_regval(iset);
1123
1124 if (volt_index < 0 || curr_index < 0) {
1125 dev_err(pm2->dev,
1126 "Charger voltage or current too high, "
1127 "charging not started\n");
1128 return -ENXIO;
1129 }
1130
1131 ret = pm2xxx_reg_read(pm2, PM2XXX_BATT_CTRL_REG8, &val);
1132 if (ret >= 0) {
1133 val &= ~PM2XXX_CH_VOLT_MASK;
1134 val |= volt_index;
1135 ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG8, val);
1136
1137 if (ret < 0) {
1138 dev_err(pm2->dev,
1139 "%s write failed\n", __func__);
1140 goto error_occured;
1141 }
1142 else
1143 dev_err(pm2->dev, "%s read failed\n", __func__);
1144 }
1145
1146 ret = pm2xxx_reg_read(pm2, PM2XXX_BATT_CTRL_REG6, &val);
1147 if (ret >= 0) {
1148 val &= ~PM2XXX_DIR_CH_CC_CURRENT_MASK;
1149 val |= curr_index;
1150 ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG6, val);
1151 if (ret < 0) {
1152 dev_err(pm2->dev,
1153 "%s write failed\n", __func__);
1154 goto error_occured;
1155 }
1156 else
1157 dev_err(pm2->dev, "%s read failed\n", __func__);
1158 }
1159
1160 if (!pm2->bat->enable_overshoot) {
1161 ret = pm2xxx_reg_read(pm2, PM2XXX_LED_CTRL_REG, &val);
1162 if (ret >= 0) {
1163 val |= PM2XXX_ANTI_OVERSHOOT_EN;
1164 ret = pm2xxx_reg_write(pm2, PM2XXX_LED_CTRL_REG,
1165 val);
1166 if (ret < 0){
1167 dev_err(pm2->dev, "%s write failed\n",
1168 __func__);
1169 goto error_occured;
1170 }
1171 }
1172 else
1173 dev_err(pm2->dev, "%s read failed\n", __func__);
1174 }
1175
1176 ret = pm2xxx_charging_enable_mngt(pm2);
1177 if (ret) {
1178 dev_err(pm2->dev, "%s write failed\n", __func__);
1179 goto error_occured;
1180 }
1181
1182 pm2->ac.charger_online = 1;
1183 } else {
1184 pm2->ac.charger_online = 0;
1185 pm2->ac.wd_expired = false;
1186
1187 /* Disable regulator if enabled */
1188 if (pm2->vddadc_en_ac) {
1189 regulator_disable(pm2->regu);
1190 pm2->vddadc_en_ac = false;
1191 }
1192
1193 ret = pm2xxx_charging_disable_mngt(pm2);
1194 if (ret) {
1195 dev_err(pm2->dev, "%s write failed\n", __func__);
1196 return ret;
1197 }
1198
1199 dev_dbg(pm2->dev, "PM2301: " "Disabled AC charging\n");
1200 }
1201 power_supply_changed(&pm2->ac_chg.psy);
1202
1203error_occured:
1204 return ret;
1205}
1206
1207static int pm2xxx_charger_watchdog_kick(struct ux500_charger *charger)
1208{
1209 int ret;
1210 struct pm2xxx_charger *pm2;
1211
1212 if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS)
1213 pm2 = to_pm2xxx_charger_ac_device_info(charger);
1214 else
1215 return -ENXIO;
1216
1217 ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_WD_KICK, WD_TIMER);
1218 if (ret)
1219 dev_err(pm2->dev, "Failed to kick WD!\n");
1220
1221 return ret;
1222}
1223
1224static void pm2xxx_charger_ac_work(struct work_struct *work)
1225{
1226 struct pm2xxx_charger *pm2 = container_of(work,
1227 struct pm2xxx_charger, ac_work);
1228
1229
1230 power_supply_changed(&pm2->ac_chg.psy);
1231 sysfs_notify(&pm2->ac_chg.psy.dev->kobj, NULL, "present");
1232};
1233
1234static void pm2xxx_charger_check_main_thermal_prot_work(
1235 struct work_struct *work)
1236{
1237};
1238
1239static struct pm2xxx_irq pm2xxx_charger_irq[] = {
1240 {"PM2XXX_IRQ_INT", pm2xxx_irq_int},
1241};
1242
1243static int pm2xxx_wall_charger_resume(struct i2c_client *i2c_client)
1244{
1245 return 0;
1246}
1247
1248static int pm2xxx_wall_charger_suspend(struct i2c_client *i2c_client,
1249 pm_message_t state)
1250{
1251 return 0;
1252}
1253
1254static int __devinit pm2xxx_wall_charger_probe(struct i2c_client *i2c_client,
1255 const struct i2c_device_id *id)
1256{
1257 struct pm2xxx_platform_data *pl_data = i2c_client->dev.platform_data;
1258 struct pm2xxx_charger *pm2;
1259 int ret = 0;
1260 u8 val;
1261
1262 pm2 = kzalloc(sizeof(struct pm2xxx_charger), GFP_KERNEL);
1263 if (!pm2) {
1264 dev_err(pm2->dev, "pm2xxx_charger allocation failed\n");
1265 return -ENOMEM;
1266 }
1267
1268 /* get parent data */
1269 pm2->dev = &i2c_client->dev;
1270 pm2->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
1271
1272 /* get charger spcific platform data */
1273 if (!pl_data->wall_charger) {
1274 dev_err(pm2->dev, "no charger platform data supplied\n");
1275 ret = -EINVAL;
1276 goto free_device_info;
1277 }
1278
1279 pm2->pdata = pl_data->wall_charger;
1280
1281 /* get battery specific platform data */
1282 if (!pl_data->battery) {
1283 dev_err(pm2->dev, "no battery platform data supplied\n");
1284 ret = -EINVAL;
1285 goto free_device_info;
1286 }
1287
1288 pm2->bat = pl_data->battery;
1289
1290 if (!i2c_check_functionality(i2c_client->adapter,
1291 I2C_FUNC_SMBUS_BYTE_DATA |
1292 I2C_FUNC_SMBUS_READ_WORD_DATA)) {
1293 ret = -ENODEV;
1294 dev_info(pm2->dev, "pm2301 i2c_check_functionality failed\n");
1295 goto free_device_info;
1296 }
1297
1298 pm2->config.pm2xxx_i2c = i2c_client;
1299 pm2->config.pm2xxx_id = (struct i2c_device_id *) id;
1300 i2c_set_clientdata(i2c_client, pm2);
1301
1302 /* AC supply */
1303 /* power_supply base class */
1304 pm2->ac_chg.psy.name = pm2->pdata->label;
1305 pm2->ac_chg.psy.type = POWER_SUPPLY_TYPE_MAINS;
1306 pm2->ac_chg.psy.properties = pm2xxx_charger_ac_props;
1307 pm2->ac_chg.psy.num_properties = ARRAY_SIZE(pm2xxx_charger_ac_props);
1308 pm2->ac_chg.psy.get_property = pm2xxx_charger_ac_get_property;
1309 pm2->ac_chg.psy.supplied_to = pm2->pdata->supplied_to;
1310 pm2->ac_chg.psy.num_supplicants = pm2->pdata->num_supplicants;
1311 /* pm2xxx_charger sub-class */
1312 pm2->ac_chg.ops.enable = &pm2xxx_charger_ac_en;
1313 pm2->ac_chg.ops.kick_wd = &pm2xxx_charger_watchdog_kick;
1314 pm2->ac_chg.ops.update_curr = &pm2xxx_charger_update_charger_current;
1315 pm2->ac_chg.max_out_volt = pm2xxx_charger_voltage_map[
1316 ARRAY_SIZE(pm2xxx_charger_voltage_map) - 1];
1317 pm2->ac_chg.max_out_curr = pm2xxx_charger_current_map[
1318 ARRAY_SIZE(pm2xxx_charger_current_map) - 1];
1319
1320 /* Create a work queue for the charger */
1321 pm2->charger_wq =
1322 create_singlethread_workqueue("pm2xxx_charger_wq");
1323 if (pm2->charger_wq == NULL) {
1324 dev_err(pm2->dev, "failed to create work queue\n");
1325 goto free_device_info;
1326 }
1327
1328 /* Init work for charger detection */
1329 INIT_WORK(&pm2->ac_work, pm2xxx_charger_ac_work);
1330
1331 /* Init work for checking HW status */
1332 INIT_WORK(&pm2->check_main_thermal_prot_work,
1333 pm2xxx_charger_check_main_thermal_prot_work);
1334
1335 /*
1336 * VDD ADC supply needs to be enabled from this driver when there
1337 * is a charger connected to avoid erroneous BTEMP_HIGH/LOW
1338 * interrupts during charging
1339 */
1340 pm2->regu = regulator_get(pm2->dev, "vddadc");
1341 if (IS_ERR(pm2->regu)) {
1342 ret = PTR_ERR(pm2->regu);
1343 dev_err(pm2->dev, "failed to get vddadc regulator\n");
1344 goto free_charger_wq;
1345 }
1346
1347 /* Register AC charger class */
1348 ret = power_supply_register(pm2->dev, &pm2->ac_chg.psy);
1349 if (ret) {
1350 dev_err(pm2->dev, "failed to register AC charger\n");
1351 goto free_regulator;
1352 }
1353
1354 /* Register interrupts */
1355 ret = request_threaded_irq(pm2->pdata->irq_number, NULL,
1356 pm2xxx_charger_irq[0].isr,
1357 pm2->pdata->irq_type,
1358 pm2xxx_charger_irq[0].name, pm2);
1359
1360 if (ret != 0) {
1361 dev_err(pm2->dev, "failed to request %s IRQ %d: %d\n",
1362 pm2xxx_charger_irq[0].name, pm2->pdata->irq_number, ret);
1363 goto unregister_pm2xxx_charger;
1364 }
1365
1366 /*
1367 * I2C Read/Write will fail, if AC adaptor is not connected.
1368 * fix the charger detection mechanism.
1369 */
1370 ret = pm2xxx_charger_detection(pm2, &val);
1371
1372 if ((ret == 0) && val) {
1373 pm2->ac.charger_connected = 1;
1374 pm2->ac_conn = true;
1375 power_supply_changed(&pm2->ac_chg.psy);
1376 sysfs_notify(&pm2->ac_chg.psy.dev->kobj, NULL, "present");
1377 }
1378
1379 return 0;
1380
1381unregister_pm2xxx_charger:
1382 /* unregister power supply */
1383 power_supply_unregister(&pm2->ac_chg.psy);
1384free_regulator:
1385 /* disable the regulator */
1386 regulator_put(pm2->regu);
1387free_charger_wq:
1388 destroy_workqueue(pm2->charger_wq);
1389free_device_info:
1390 kfree(pm2);
1391 return ret;
1392}
1393
1394static int __devexit pm2xxx_wall_charger_remove(struct i2c_client *i2c_client)
1395{
1396 struct pm2xxx_charger *pm2 = i2c_get_clientdata(i2c_client);
1397
1398 /* Disable AC charging */
1399 pm2xxx_charger_ac_en(&pm2->ac_chg, false, 0, 0);
1400
1401 /* Disable interrupts */
1402 free_irq(pm2->pdata->irq_number, pm2);
1403
1404 /* Delete the work queue */
1405 destroy_workqueue(pm2->charger_wq);
1406
1407 flush_scheduled_work();
1408
1409 /* disable the regulator */
1410 regulator_put(pm2->regu);
1411
1412 power_supply_unregister(&pm2->ac_chg.psy);
1413
1414 kfree(pm2);
1415
1416 return 0;
1417}
1418
1419static const struct i2c_device_id pm2xxx_id[] = {
1420 { "pm2301", 0 },
1421 { }
1422};
1423
1424MODULE_DEVICE_TABLE(i2c, pm2xxx_id);
1425
1426static struct i2c_driver pm2xxx_charger_driver = {
1427 .probe = pm2xxx_wall_charger_probe,
1428 .remove = __devexit_p(pm2xxx_wall_charger_remove),
1429 .suspend = pm2xxx_wall_charger_suspend,
1430 .resume = pm2xxx_wall_charger_resume,
1431 .driver = {
1432 .name = "pm2xxx-wall_charger",
1433 .owner = THIS_MODULE,
1434 },
1435 .id_table = pm2xxx_id,
1436};
1437
1438static int __init pm2xxx_charger_init(void)
1439{
1440 return i2c_add_driver(&pm2xxx_charger_driver);
1441}
1442
1443static void __exit pm2xxx_charger_exit(void)
1444{
1445 i2c_del_driver(&pm2xxx_charger_driver);
1446}
1447
1448subsys_initcall_sync(pm2xxx_charger_init);
1449module_exit(pm2xxx_charger_exit);
1450
1451MODULE_LICENSE("GPL v2");
1452MODULE_AUTHOR("Rajkumar kasirajan, Olivier Launay");
1453MODULE_ALIAS("platform:pm2xxx-charger");
1454MODULE_DESCRIPTION("PM2xxx charger management driver");
1455