xref: /OK3568_Linux_fs/kernel/drivers/power/supply/pm2301_charger.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright 2012 ST Ericsson.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Power supply driver for ST Ericsson pm2xxx_charger charger
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/init.h>
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/device.h>
11*4882a593Smuzhiyun #include <linux/interrupt.h>
12*4882a593Smuzhiyun #include <linux/delay.h>
13*4882a593Smuzhiyun #include <linux/slab.h>
14*4882a593Smuzhiyun #include <linux/platform_device.h>
15*4882a593Smuzhiyun #include <linux/power_supply.h>
16*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
17*4882a593Smuzhiyun #include <linux/err.h>
18*4882a593Smuzhiyun #include <linux/i2c.h>
19*4882a593Smuzhiyun #include <linux/workqueue.h>
20*4882a593Smuzhiyun #include <linux/mfd/abx500/ab8500.h>
21*4882a593Smuzhiyun #include <linux/mfd/abx500/ab8500-bm.h>
22*4882a593Smuzhiyun #include <linux/mfd/abx500/ux500_chargalg.h>
23*4882a593Smuzhiyun #include <linux/pm2301_charger.h>
24*4882a593Smuzhiyun #include <linux/gpio.h>
25*4882a593Smuzhiyun #include <linux/pm_runtime.h>
26*4882a593Smuzhiyun #include <linux/pm.h>
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #include "pm2301_charger.h"
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #define to_pm2xxx_charger_ac_device_info(x) container_of((x), \
31*4882a593Smuzhiyun 		struct pm2xxx_charger, ac_chg)
32*4882a593Smuzhiyun #define SLEEP_MIN		50
33*4882a593Smuzhiyun #define SLEEP_MAX		100
34*4882a593Smuzhiyun #define PM2XXX_AUTOSUSPEND_DELAY 500
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun static int pm2xxx_interrupt_registers[] = {
37*4882a593Smuzhiyun 	PM2XXX_REG_INT1,
38*4882a593Smuzhiyun 	PM2XXX_REG_INT2,
39*4882a593Smuzhiyun 	PM2XXX_REG_INT3,
40*4882a593Smuzhiyun 	PM2XXX_REG_INT4,
41*4882a593Smuzhiyun 	PM2XXX_REG_INT5,
42*4882a593Smuzhiyun 	PM2XXX_REG_INT6,
43*4882a593Smuzhiyun };
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun static enum power_supply_property pm2xxx_charger_ac_props[] = {
46*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_HEALTH,
47*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_PRESENT,
48*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_ONLINE,
49*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_VOLTAGE_AVG,
50*4882a593Smuzhiyun };
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun static int pm2xxx_charger_voltage_map[] = {
53*4882a593Smuzhiyun 	3500,
54*4882a593Smuzhiyun 	3525,
55*4882a593Smuzhiyun 	3550,
56*4882a593Smuzhiyun 	3575,
57*4882a593Smuzhiyun 	3600,
58*4882a593Smuzhiyun 	3625,
59*4882a593Smuzhiyun 	3650,
60*4882a593Smuzhiyun 	3675,
61*4882a593Smuzhiyun 	3700,
62*4882a593Smuzhiyun 	3725,
63*4882a593Smuzhiyun 	3750,
64*4882a593Smuzhiyun 	3775,
65*4882a593Smuzhiyun 	3800,
66*4882a593Smuzhiyun 	3825,
67*4882a593Smuzhiyun 	3850,
68*4882a593Smuzhiyun 	3875,
69*4882a593Smuzhiyun 	3900,
70*4882a593Smuzhiyun 	3925,
71*4882a593Smuzhiyun 	3950,
72*4882a593Smuzhiyun 	3975,
73*4882a593Smuzhiyun 	4000,
74*4882a593Smuzhiyun 	4025,
75*4882a593Smuzhiyun 	4050,
76*4882a593Smuzhiyun 	4075,
77*4882a593Smuzhiyun 	4100,
78*4882a593Smuzhiyun 	4125,
79*4882a593Smuzhiyun 	4150,
80*4882a593Smuzhiyun 	4175,
81*4882a593Smuzhiyun 	4200,
82*4882a593Smuzhiyun 	4225,
83*4882a593Smuzhiyun 	4250,
84*4882a593Smuzhiyun 	4275,
85*4882a593Smuzhiyun 	4300,
86*4882a593Smuzhiyun };
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun static int pm2xxx_charger_current_map[] = {
89*4882a593Smuzhiyun 	200,
90*4882a593Smuzhiyun 	200,
91*4882a593Smuzhiyun 	400,
92*4882a593Smuzhiyun 	600,
93*4882a593Smuzhiyun 	800,
94*4882a593Smuzhiyun 	1000,
95*4882a593Smuzhiyun 	1200,
96*4882a593Smuzhiyun 	1400,
97*4882a593Smuzhiyun 	1600,
98*4882a593Smuzhiyun 	1800,
99*4882a593Smuzhiyun 	2000,
100*4882a593Smuzhiyun 	2200,
101*4882a593Smuzhiyun 	2400,
102*4882a593Smuzhiyun 	2600,
103*4882a593Smuzhiyun 	2800,
104*4882a593Smuzhiyun 	3000,
105*4882a593Smuzhiyun };
106*4882a593Smuzhiyun 
set_lpn_pin(struct pm2xxx_charger * pm2)107*4882a593Smuzhiyun static void set_lpn_pin(struct pm2xxx_charger *pm2)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun 	if (!pm2->ac.charger_connected && gpio_is_valid(pm2->lpn_pin)) {
110*4882a593Smuzhiyun 		gpio_set_value(pm2->lpn_pin, 1);
111*4882a593Smuzhiyun 		usleep_range(SLEEP_MIN, SLEEP_MAX);
112*4882a593Smuzhiyun 	}
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun 
clear_lpn_pin(struct pm2xxx_charger * pm2)115*4882a593Smuzhiyun static void clear_lpn_pin(struct pm2xxx_charger *pm2)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun 	if (!pm2->ac.charger_connected && gpio_is_valid(pm2->lpn_pin))
118*4882a593Smuzhiyun 		gpio_set_value(pm2->lpn_pin, 0);
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun 
pm2xxx_reg_read(struct pm2xxx_charger * pm2,int reg,u8 * val)121*4882a593Smuzhiyun static int pm2xxx_reg_read(struct pm2xxx_charger *pm2, int reg, u8 *val)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun 	int ret;
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	/* wake up the device */
126*4882a593Smuzhiyun 	pm_runtime_get_sync(pm2->dev);
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	ret = i2c_smbus_read_i2c_block_data(pm2->config.pm2xxx_i2c, reg,
129*4882a593Smuzhiyun 				1, val);
130*4882a593Smuzhiyun 	if (ret < 0)
131*4882a593Smuzhiyun 		dev_err(pm2->dev, "Error reading register at 0x%x\n", reg);
132*4882a593Smuzhiyun 	else
133*4882a593Smuzhiyun 		ret = 0;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	pm_runtime_put_sync(pm2->dev);
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	return ret;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun 
pm2xxx_reg_write(struct pm2xxx_charger * pm2,int reg,u8 val)140*4882a593Smuzhiyun static int pm2xxx_reg_write(struct pm2xxx_charger *pm2, int reg, u8 val)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun 	int ret;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	/* wake up the device */
145*4882a593Smuzhiyun 	pm_runtime_get_sync(pm2->dev);
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	ret = i2c_smbus_write_i2c_block_data(pm2->config.pm2xxx_i2c, reg,
148*4882a593Smuzhiyun 				1, &val);
149*4882a593Smuzhiyun 	if (ret < 0)
150*4882a593Smuzhiyun 		dev_err(pm2->dev, "Error writing register at 0x%x\n", reg);
151*4882a593Smuzhiyun 	else
152*4882a593Smuzhiyun 		ret = 0;
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	pm_runtime_put_sync(pm2->dev);
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 	return ret;
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun 
pm2xxx_charging_enable_mngt(struct pm2xxx_charger * pm2)159*4882a593Smuzhiyun static int pm2xxx_charging_enable_mngt(struct pm2xxx_charger *pm2)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun 	int ret;
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	/* Enable charging */
164*4882a593Smuzhiyun 	ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG2,
165*4882a593Smuzhiyun 			(PM2XXX_CH_AUTO_RESUME_EN | PM2XXX_CHARGER_ENA));
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	return ret;
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun 
pm2xxx_charging_disable_mngt(struct pm2xxx_charger * pm2)170*4882a593Smuzhiyun static int pm2xxx_charging_disable_mngt(struct pm2xxx_charger *pm2)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun 	int ret;
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	/* Disable SW EOC ctrl */
175*4882a593Smuzhiyun 	ret = pm2xxx_reg_write(pm2, PM2XXX_SW_CTRL_REG, PM2XXX_SWCTRL_HW);
176*4882a593Smuzhiyun 	if (ret < 0) {
177*4882a593Smuzhiyun 		dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__);
178*4882a593Smuzhiyun 		return ret;
179*4882a593Smuzhiyun 	}
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	/* Disable charging */
182*4882a593Smuzhiyun 	ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG2,
183*4882a593Smuzhiyun 			(PM2XXX_CH_AUTO_RESUME_DIS | PM2XXX_CHARGER_DIS));
184*4882a593Smuzhiyun 	if (ret < 0) {
185*4882a593Smuzhiyun 		dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__);
186*4882a593Smuzhiyun 		return ret;
187*4882a593Smuzhiyun 	}
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	return 0;
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun 
pm2xxx_charger_batt_therm_mngt(struct pm2xxx_charger * pm2,int val)192*4882a593Smuzhiyun static int pm2xxx_charger_batt_therm_mngt(struct pm2xxx_charger *pm2, int val)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun 	queue_work(pm2->charger_wq, &pm2->check_main_thermal_prot_work);
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	return 0;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 
pm2xxx_charger_die_therm_mngt(struct pm2xxx_charger * pm2,int val)200*4882a593Smuzhiyun static int pm2xxx_charger_die_therm_mngt(struct pm2xxx_charger *pm2, int val)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun 	queue_work(pm2->charger_wq, &pm2->check_main_thermal_prot_work);
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun 	return 0;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun 
pm2xxx_charger_ovv_mngt(struct pm2xxx_charger * pm2,int val)207*4882a593Smuzhiyun static int pm2xxx_charger_ovv_mngt(struct pm2xxx_charger *pm2, int val)
208*4882a593Smuzhiyun {
209*4882a593Smuzhiyun 	dev_err(pm2->dev, "Overvoltage detected\n");
210*4882a593Smuzhiyun 	pm2->flags.ovv = true;
211*4882a593Smuzhiyun 	power_supply_changed(pm2->ac_chg.psy);
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	/* Schedule a new HW failure check */
214*4882a593Smuzhiyun 	queue_delayed_work(pm2->charger_wq, &pm2->check_hw_failure_work, 0);
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	return 0;
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun 
pm2xxx_charger_wd_exp_mngt(struct pm2xxx_charger * pm2,int val)219*4882a593Smuzhiyun static int pm2xxx_charger_wd_exp_mngt(struct pm2xxx_charger *pm2, int val)
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun 	dev_dbg(pm2->dev , "20 minutes watchdog expired\n");
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	pm2->ac.wd_expired = true;
224*4882a593Smuzhiyun 	power_supply_changed(pm2->ac_chg.psy);
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	return 0;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun 
pm2xxx_charger_vbat_lsig_mngt(struct pm2xxx_charger * pm2,int val)229*4882a593Smuzhiyun static int pm2xxx_charger_vbat_lsig_mngt(struct pm2xxx_charger *pm2, int val)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun 	int ret;
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	switch (val) {
234*4882a593Smuzhiyun 	case PM2XXX_INT1_ITVBATLOWR:
235*4882a593Smuzhiyun 		dev_dbg(pm2->dev, "VBAT grows above VBAT_LOW level\n");
236*4882a593Smuzhiyun 		/* Enable SW EOC ctrl */
237*4882a593Smuzhiyun 		ret = pm2xxx_reg_write(pm2, PM2XXX_SW_CTRL_REG,
238*4882a593Smuzhiyun 							PM2XXX_SWCTRL_SW);
239*4882a593Smuzhiyun 		if (ret < 0) {
240*4882a593Smuzhiyun 			dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__);
241*4882a593Smuzhiyun 			return ret;
242*4882a593Smuzhiyun 		}
243*4882a593Smuzhiyun 		break;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	case PM2XXX_INT1_ITVBATLOWF:
246*4882a593Smuzhiyun 		dev_dbg(pm2->dev, "VBAT drops below VBAT_LOW level\n");
247*4882a593Smuzhiyun 		/* Disable SW EOC ctrl */
248*4882a593Smuzhiyun 		ret = pm2xxx_reg_write(pm2, PM2XXX_SW_CTRL_REG,
249*4882a593Smuzhiyun 							PM2XXX_SWCTRL_HW);
250*4882a593Smuzhiyun 		if (ret < 0) {
251*4882a593Smuzhiyun 			dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__);
252*4882a593Smuzhiyun 			return ret;
253*4882a593Smuzhiyun 		}
254*4882a593Smuzhiyun 		break;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	default:
257*4882a593Smuzhiyun 		dev_err(pm2->dev, "Unknown VBAT level\n");
258*4882a593Smuzhiyun 	}
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	return 0;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun 
pm2xxx_charger_bat_disc_mngt(struct pm2xxx_charger * pm2,int val)263*4882a593Smuzhiyun static int pm2xxx_charger_bat_disc_mngt(struct pm2xxx_charger *pm2, int val)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun 	dev_dbg(pm2->dev, "battery disconnected\n");
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	return 0;
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun 
pm2xxx_charger_detection(struct pm2xxx_charger * pm2,u8 * val)270*4882a593Smuzhiyun static int pm2xxx_charger_detection(struct pm2xxx_charger *pm2, u8 *val)
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun 	int ret;
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 	ret = pm2xxx_reg_read(pm2, PM2XXX_SRCE_REG_INT2, val);
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	if (ret < 0) {
277*4882a593Smuzhiyun 		dev_err(pm2->dev, "Charger detection failed\n");
278*4882a593Smuzhiyun 		goto out;
279*4882a593Smuzhiyun 	}
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	*val &= (PM2XXX_INT2_S_ITVPWR1PLUG | PM2XXX_INT2_S_ITVPWR2PLUG);
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun out:
284*4882a593Smuzhiyun 	return ret;
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun 
pm2xxx_charger_itv_pwr_plug_mngt(struct pm2xxx_charger * pm2,int val)287*4882a593Smuzhiyun static int pm2xxx_charger_itv_pwr_plug_mngt(struct pm2xxx_charger *pm2, int val)
288*4882a593Smuzhiyun {
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 	int ret;
291*4882a593Smuzhiyun 	u8 read_val;
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	/*
294*4882a593Smuzhiyun 	 * Since we can't be sure that the events are received
295*4882a593Smuzhiyun 	 * synchronously, we have the check if the main charger is
296*4882a593Smuzhiyun 	 * connected by reading the interrupt source register.
297*4882a593Smuzhiyun 	 */
298*4882a593Smuzhiyun 	ret = pm2xxx_charger_detection(pm2, &read_val);
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	if ((ret == 0) && read_val) {
301*4882a593Smuzhiyun 		pm2->ac.charger_connected = 1;
302*4882a593Smuzhiyun 		pm2->ac_conn = true;
303*4882a593Smuzhiyun 		queue_work(pm2->charger_wq, &pm2->ac_work);
304*4882a593Smuzhiyun 	}
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	return ret;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun 
pm2xxx_charger_itv_pwr_unplug_mngt(struct pm2xxx_charger * pm2,int val)310*4882a593Smuzhiyun static int pm2xxx_charger_itv_pwr_unplug_mngt(struct pm2xxx_charger *pm2,
311*4882a593Smuzhiyun 								int val)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun 	pm2->ac.charger_connected = 0;
314*4882a593Smuzhiyun 	queue_work(pm2->charger_wq, &pm2->ac_work);
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	return 0;
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun 
pm2_int_reg0(void * pm2_data,int val)319*4882a593Smuzhiyun static int pm2_int_reg0(void *pm2_data, int val)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun 	struct pm2xxx_charger *pm2 = pm2_data;
322*4882a593Smuzhiyun 	int ret = 0;
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	if (val & PM2XXX_INT1_ITVBATLOWR) {
325*4882a593Smuzhiyun 		ret = pm2xxx_charger_vbat_lsig_mngt(pm2,
326*4882a593Smuzhiyun 						PM2XXX_INT1_ITVBATLOWR);
327*4882a593Smuzhiyun 		if (ret < 0)
328*4882a593Smuzhiyun 			goto out;
329*4882a593Smuzhiyun 	}
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	if (val & PM2XXX_INT1_ITVBATLOWF) {
332*4882a593Smuzhiyun 		ret = pm2xxx_charger_vbat_lsig_mngt(pm2,
333*4882a593Smuzhiyun 						PM2XXX_INT1_ITVBATLOWF);
334*4882a593Smuzhiyun 		if (ret < 0)
335*4882a593Smuzhiyun 			goto out;
336*4882a593Smuzhiyun 	}
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	if (val & PM2XXX_INT1_ITVBATDISCONNECT) {
339*4882a593Smuzhiyun 		ret = pm2xxx_charger_bat_disc_mngt(pm2,
340*4882a593Smuzhiyun 				PM2XXX_INT1_ITVBATDISCONNECT);
341*4882a593Smuzhiyun 		if (ret < 0)
342*4882a593Smuzhiyun 			goto out;
343*4882a593Smuzhiyun 	}
344*4882a593Smuzhiyun out:
345*4882a593Smuzhiyun 	return ret;
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun 
pm2_int_reg1(void * pm2_data,int val)348*4882a593Smuzhiyun static int pm2_int_reg1(void *pm2_data, int val)
349*4882a593Smuzhiyun {
350*4882a593Smuzhiyun 	struct pm2xxx_charger *pm2 = pm2_data;
351*4882a593Smuzhiyun 	int ret = 0;
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 	if (val & (PM2XXX_INT2_ITVPWR1PLUG | PM2XXX_INT2_ITVPWR2PLUG)) {
354*4882a593Smuzhiyun 		dev_dbg(pm2->dev , "Main charger plugged\n");
355*4882a593Smuzhiyun 		ret = pm2xxx_charger_itv_pwr_plug_mngt(pm2, val &
356*4882a593Smuzhiyun 			(PM2XXX_INT2_ITVPWR1PLUG | PM2XXX_INT2_ITVPWR2PLUG));
357*4882a593Smuzhiyun 	}
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	if (val &
360*4882a593Smuzhiyun 		(PM2XXX_INT2_ITVPWR1UNPLUG | PM2XXX_INT2_ITVPWR2UNPLUG)) {
361*4882a593Smuzhiyun 		dev_dbg(pm2->dev , "Main charger unplugged\n");
362*4882a593Smuzhiyun 		ret = pm2xxx_charger_itv_pwr_unplug_mngt(pm2, val &
363*4882a593Smuzhiyun 						(PM2XXX_INT2_ITVPWR1UNPLUG |
364*4882a593Smuzhiyun 						PM2XXX_INT2_ITVPWR2UNPLUG));
365*4882a593Smuzhiyun 	}
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	return ret;
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun 
pm2_int_reg2(void * pm2_data,int val)370*4882a593Smuzhiyun static int pm2_int_reg2(void *pm2_data, int val)
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun 	struct pm2xxx_charger *pm2 = pm2_data;
373*4882a593Smuzhiyun 	int ret = 0;
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	if (val & PM2XXX_INT3_ITAUTOTIMEOUTWD)
376*4882a593Smuzhiyun 		ret = pm2xxx_charger_wd_exp_mngt(pm2, val);
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	if (val & (PM2XXX_INT3_ITCHPRECHARGEWD |
379*4882a593Smuzhiyun 				PM2XXX_INT3_ITCHCCWD | PM2XXX_INT3_ITCHCVWD)) {
380*4882a593Smuzhiyun 		dev_dbg(pm2->dev,
381*4882a593Smuzhiyun 			"Watchdog occurred for precharge, CC and CV charge\n");
382*4882a593Smuzhiyun 	}
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 	return ret;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun 
pm2_int_reg3(void * pm2_data,int val)387*4882a593Smuzhiyun static int pm2_int_reg3(void *pm2_data, int val)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun 	struct pm2xxx_charger *pm2 = pm2_data;
390*4882a593Smuzhiyun 	int ret = 0;
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	if (val & (PM2XXX_INT4_ITCHARGINGON)) {
393*4882a593Smuzhiyun 		dev_dbg(pm2->dev ,
394*4882a593Smuzhiyun 			"charging operation has started\n");
395*4882a593Smuzhiyun 	}
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	if (val & (PM2XXX_INT4_ITVRESUME)) {
398*4882a593Smuzhiyun 		dev_dbg(pm2->dev,
399*4882a593Smuzhiyun 			"battery discharged down to VResume threshold\n");
400*4882a593Smuzhiyun 	}
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun 	if (val & (PM2XXX_INT4_ITBATTFULL)) {
403*4882a593Smuzhiyun 		dev_dbg(pm2->dev , "battery fully detected\n");
404*4882a593Smuzhiyun 	}
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun 	if (val & (PM2XXX_INT4_ITCVPHASE)) {
407*4882a593Smuzhiyun 		dev_dbg(pm2->dev, "CV phase enter with 0.5C charging\n");
408*4882a593Smuzhiyun 	}
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 	if (val & (PM2XXX_INT4_ITVPWR2OVV | PM2XXX_INT4_ITVPWR1OVV)) {
411*4882a593Smuzhiyun 		pm2->failure_case = VPWR_OVV;
412*4882a593Smuzhiyun 		ret = pm2xxx_charger_ovv_mngt(pm2, val &
413*4882a593Smuzhiyun 			(PM2XXX_INT4_ITVPWR2OVV | PM2XXX_INT4_ITVPWR1OVV));
414*4882a593Smuzhiyun 		dev_dbg(pm2->dev, "VPWR/VSYSTEM overvoltage detected\n");
415*4882a593Smuzhiyun 	}
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 	if (val & (PM2XXX_INT4_S_ITBATTEMPCOLD |
418*4882a593Smuzhiyun 				PM2XXX_INT4_S_ITBATTEMPHOT)) {
419*4882a593Smuzhiyun 		ret = pm2xxx_charger_batt_therm_mngt(pm2, val &
420*4882a593Smuzhiyun 			(PM2XXX_INT4_S_ITBATTEMPCOLD |
421*4882a593Smuzhiyun 			PM2XXX_INT4_S_ITBATTEMPHOT));
422*4882a593Smuzhiyun 		dev_dbg(pm2->dev, "BTEMP is too Low/High\n");
423*4882a593Smuzhiyun 	}
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	return ret;
426*4882a593Smuzhiyun }
427*4882a593Smuzhiyun 
pm2_int_reg4(void * pm2_data,int val)428*4882a593Smuzhiyun static int pm2_int_reg4(void *pm2_data, int val)
429*4882a593Smuzhiyun {
430*4882a593Smuzhiyun 	struct pm2xxx_charger *pm2 = pm2_data;
431*4882a593Smuzhiyun 	int ret = 0;
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	if (val & PM2XXX_INT5_ITVSYSTEMOVV) {
434*4882a593Smuzhiyun 		pm2->failure_case = VSYSTEM_OVV;
435*4882a593Smuzhiyun 		ret = pm2xxx_charger_ovv_mngt(pm2, val &
436*4882a593Smuzhiyun 						PM2XXX_INT5_ITVSYSTEMOVV);
437*4882a593Smuzhiyun 		dev_dbg(pm2->dev, "VSYSTEM overvoltage detected\n");
438*4882a593Smuzhiyun 	}
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun 	if (val & (PM2XXX_INT5_ITTHERMALWARNINGFALL |
441*4882a593Smuzhiyun 				PM2XXX_INT5_ITTHERMALWARNINGRISE |
442*4882a593Smuzhiyun 				PM2XXX_INT5_ITTHERMALSHUTDOWNFALL |
443*4882a593Smuzhiyun 				PM2XXX_INT5_ITTHERMALSHUTDOWNRISE)) {
444*4882a593Smuzhiyun 		dev_dbg(pm2->dev, "BTEMP die temperature is too Low/High\n");
445*4882a593Smuzhiyun 		ret = pm2xxx_charger_die_therm_mngt(pm2, val &
446*4882a593Smuzhiyun 			(PM2XXX_INT5_ITTHERMALWARNINGFALL |
447*4882a593Smuzhiyun 			PM2XXX_INT5_ITTHERMALWARNINGRISE |
448*4882a593Smuzhiyun 			PM2XXX_INT5_ITTHERMALSHUTDOWNFALL |
449*4882a593Smuzhiyun 			PM2XXX_INT5_ITTHERMALSHUTDOWNRISE));
450*4882a593Smuzhiyun 	}
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	return ret;
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun 
pm2_int_reg5(void * pm2_data,int val)455*4882a593Smuzhiyun static int pm2_int_reg5(void *pm2_data, int val)
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun 	struct pm2xxx_charger *pm2 = pm2_data;
458*4882a593Smuzhiyun 	int ret = 0;
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 	if (val & (PM2XXX_INT6_ITVPWR2DROP | PM2XXX_INT6_ITVPWR1DROP)) {
461*4882a593Smuzhiyun 		dev_dbg(pm2->dev, "VMPWR drop to VBAT level\n");
462*4882a593Smuzhiyun 	}
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	if (val & (PM2XXX_INT6_ITVPWR2VALIDRISE |
465*4882a593Smuzhiyun 			PM2XXX_INT6_ITVPWR1VALIDRISE |
466*4882a593Smuzhiyun 			PM2XXX_INT6_ITVPWR2VALIDFALL |
467*4882a593Smuzhiyun 			PM2XXX_INT6_ITVPWR1VALIDFALL)) {
468*4882a593Smuzhiyun 		dev_dbg(pm2->dev, "Falling/Rising edge on WPWR1/2\n");
469*4882a593Smuzhiyun 	}
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun 	return ret;
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun 
pm2xxx_irq_int(int irq,void * data)474*4882a593Smuzhiyun static irqreturn_t  pm2xxx_irq_int(int irq, void *data)
475*4882a593Smuzhiyun {
476*4882a593Smuzhiyun 	struct pm2xxx_charger *pm2 = data;
477*4882a593Smuzhiyun 	struct pm2xxx_interrupts *interrupt = pm2->pm2_int;
478*4882a593Smuzhiyun 	int i;
479*4882a593Smuzhiyun 
480*4882a593Smuzhiyun 	/* wake up the device */
481*4882a593Smuzhiyun 	pm_runtime_get_sync(pm2->dev);
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 	do {
484*4882a593Smuzhiyun 		for (i = 0; i < PM2XXX_NUM_INT_REG; i++) {
485*4882a593Smuzhiyun 			pm2xxx_reg_read(pm2,
486*4882a593Smuzhiyun 				pm2xxx_interrupt_registers[i],
487*4882a593Smuzhiyun 				&(interrupt->reg[i]));
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun 			if (interrupt->reg[i] > 0)
490*4882a593Smuzhiyun 				interrupt->handler[i](pm2, interrupt->reg[i]);
491*4882a593Smuzhiyun 		}
492*4882a593Smuzhiyun 	} while (gpio_get_value(pm2->pdata->gpio_irq_number) == 0);
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	pm_runtime_mark_last_busy(pm2->dev);
495*4882a593Smuzhiyun 	pm_runtime_put_autosuspend(pm2->dev);
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	return IRQ_HANDLED;
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun 
pm2xxx_charger_get_ac_cv(struct pm2xxx_charger * pm2)500*4882a593Smuzhiyun static int pm2xxx_charger_get_ac_cv(struct pm2xxx_charger *pm2)
501*4882a593Smuzhiyun {
502*4882a593Smuzhiyun 	int ret = 0;
503*4882a593Smuzhiyun 	u8 val;
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	if (pm2->ac.charger_connected && pm2->ac.charger_online) {
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 		ret = pm2xxx_reg_read(pm2, PM2XXX_SRCE_REG_INT4, &val);
508*4882a593Smuzhiyun 		if (ret < 0) {
509*4882a593Smuzhiyun 			dev_err(pm2->dev, "%s pm2xxx read failed\n", __func__);
510*4882a593Smuzhiyun 			goto out;
511*4882a593Smuzhiyun 		}
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun 		if (val & PM2XXX_INT4_S_ITCVPHASE)
514*4882a593Smuzhiyun 			ret = PM2XXX_CONST_VOLT;
515*4882a593Smuzhiyun 		else
516*4882a593Smuzhiyun 			ret = PM2XXX_CONST_CURR;
517*4882a593Smuzhiyun 	}
518*4882a593Smuzhiyun out:
519*4882a593Smuzhiyun 	return ret;
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun 
pm2xxx_current_to_regval(int curr)522*4882a593Smuzhiyun static int pm2xxx_current_to_regval(int curr)
523*4882a593Smuzhiyun {
524*4882a593Smuzhiyun 	int i;
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 	if (curr < pm2xxx_charger_current_map[0])
527*4882a593Smuzhiyun 		return 0;
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun 	for (i = 1; i < ARRAY_SIZE(pm2xxx_charger_current_map); i++) {
530*4882a593Smuzhiyun 		if (curr < pm2xxx_charger_current_map[i])
531*4882a593Smuzhiyun 			return (i - 1);
532*4882a593Smuzhiyun 	}
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun 	i = ARRAY_SIZE(pm2xxx_charger_current_map) - 1;
535*4882a593Smuzhiyun 	if (curr == pm2xxx_charger_current_map[i])
536*4882a593Smuzhiyun 		return i;
537*4882a593Smuzhiyun 	else
538*4882a593Smuzhiyun 		return -EINVAL;
539*4882a593Smuzhiyun }
540*4882a593Smuzhiyun 
pm2xxx_voltage_to_regval(int curr)541*4882a593Smuzhiyun static int pm2xxx_voltage_to_regval(int curr)
542*4882a593Smuzhiyun {
543*4882a593Smuzhiyun 	int i;
544*4882a593Smuzhiyun 
545*4882a593Smuzhiyun 	if (curr < pm2xxx_charger_voltage_map[0])
546*4882a593Smuzhiyun 		return 0;
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun 	for (i = 1; i < ARRAY_SIZE(pm2xxx_charger_voltage_map); i++) {
549*4882a593Smuzhiyun 		if (curr < pm2xxx_charger_voltage_map[i])
550*4882a593Smuzhiyun 			return i - 1;
551*4882a593Smuzhiyun 	}
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 	i = ARRAY_SIZE(pm2xxx_charger_voltage_map) - 1;
554*4882a593Smuzhiyun 	if (curr == pm2xxx_charger_voltage_map[i])
555*4882a593Smuzhiyun 		return i;
556*4882a593Smuzhiyun 	else
557*4882a593Smuzhiyun 		return -EINVAL;
558*4882a593Smuzhiyun }
559*4882a593Smuzhiyun 
pm2xxx_charger_update_charger_current(struct ux500_charger * charger,int ich_out)560*4882a593Smuzhiyun static int pm2xxx_charger_update_charger_current(struct ux500_charger *charger,
561*4882a593Smuzhiyun 		int ich_out)
562*4882a593Smuzhiyun {
563*4882a593Smuzhiyun 	int ret;
564*4882a593Smuzhiyun 	int curr_index;
565*4882a593Smuzhiyun 	struct pm2xxx_charger *pm2;
566*4882a593Smuzhiyun 	u8 val;
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun 	if (charger->psy->desc->type == POWER_SUPPLY_TYPE_MAINS)
569*4882a593Smuzhiyun 		pm2 = to_pm2xxx_charger_ac_device_info(charger);
570*4882a593Smuzhiyun 	else
571*4882a593Smuzhiyun 		return -ENXIO;
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun 	curr_index = pm2xxx_current_to_regval(ich_out);
574*4882a593Smuzhiyun 	if (curr_index < 0) {
575*4882a593Smuzhiyun 		dev_err(pm2->dev,
576*4882a593Smuzhiyun 			"Charger current too high, charging not started\n");
577*4882a593Smuzhiyun 		return -ENXIO;
578*4882a593Smuzhiyun 	}
579*4882a593Smuzhiyun 
580*4882a593Smuzhiyun 	ret = pm2xxx_reg_read(pm2, PM2XXX_BATT_CTRL_REG6, &val);
581*4882a593Smuzhiyun 	if (ret >= 0) {
582*4882a593Smuzhiyun 		val &= ~PM2XXX_DIR_CH_CC_CURRENT_MASK;
583*4882a593Smuzhiyun 		val |= curr_index;
584*4882a593Smuzhiyun 		ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG6, val);
585*4882a593Smuzhiyun 		if (ret < 0) {
586*4882a593Smuzhiyun 			dev_err(pm2->dev,
587*4882a593Smuzhiyun 				"%s write failed\n", __func__);
588*4882a593Smuzhiyun 		}
589*4882a593Smuzhiyun 	}
590*4882a593Smuzhiyun 	else
591*4882a593Smuzhiyun 		dev_err(pm2->dev, "%s read failed\n", __func__);
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun 	return ret;
594*4882a593Smuzhiyun }
595*4882a593Smuzhiyun 
pm2xxx_charger_ac_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)596*4882a593Smuzhiyun static int pm2xxx_charger_ac_get_property(struct power_supply *psy,
597*4882a593Smuzhiyun 	enum power_supply_property psp,
598*4882a593Smuzhiyun 	union power_supply_propval *val)
599*4882a593Smuzhiyun {
600*4882a593Smuzhiyun 	struct pm2xxx_charger *pm2;
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun 	pm2 = to_pm2xxx_charger_ac_device_info(psy_to_ux500_charger(psy));
603*4882a593Smuzhiyun 
604*4882a593Smuzhiyun 	switch (psp) {
605*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_HEALTH:
606*4882a593Smuzhiyun 		if (pm2->flags.mainextchnotok)
607*4882a593Smuzhiyun 			val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
608*4882a593Smuzhiyun 		else if (pm2->ac.wd_expired)
609*4882a593Smuzhiyun 			val->intval = POWER_SUPPLY_HEALTH_DEAD;
610*4882a593Smuzhiyun 		else if (pm2->flags.main_thermal_prot)
611*4882a593Smuzhiyun 			val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
612*4882a593Smuzhiyun 		else if (pm2->flags.ovv)
613*4882a593Smuzhiyun 			val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
614*4882a593Smuzhiyun 		else
615*4882a593Smuzhiyun 			val->intval = POWER_SUPPLY_HEALTH_GOOD;
616*4882a593Smuzhiyun 		break;
617*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_ONLINE:
618*4882a593Smuzhiyun 		val->intval = pm2->ac.charger_online;
619*4882a593Smuzhiyun 		break;
620*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_PRESENT:
621*4882a593Smuzhiyun 		val->intval = pm2->ac.charger_connected;
622*4882a593Smuzhiyun 		break;
623*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_VOLTAGE_AVG:
624*4882a593Smuzhiyun 		pm2->ac.cv_active = pm2xxx_charger_get_ac_cv(pm2);
625*4882a593Smuzhiyun 		val->intval = pm2->ac.cv_active;
626*4882a593Smuzhiyun 		break;
627*4882a593Smuzhiyun 	default:
628*4882a593Smuzhiyun 		return -EINVAL;
629*4882a593Smuzhiyun 	}
630*4882a593Smuzhiyun 	return 0;
631*4882a593Smuzhiyun }
632*4882a593Smuzhiyun 
pm2xxx_charging_init(struct pm2xxx_charger * pm2)633*4882a593Smuzhiyun static int pm2xxx_charging_init(struct pm2xxx_charger *pm2)
634*4882a593Smuzhiyun {
635*4882a593Smuzhiyun 	int ret = 0;
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun 	/* enable CC and CV watchdog */
638*4882a593Smuzhiyun 	ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG3,
639*4882a593Smuzhiyun 		(PM2XXX_CH_WD_CV_PHASE_60MIN | PM2XXX_CH_WD_CC_PHASE_60MIN));
640*4882a593Smuzhiyun 	if( ret < 0)
641*4882a593Smuzhiyun 		return ret;
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun 	/* enable precharge watchdog */
644*4882a593Smuzhiyun 	ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG4,
645*4882a593Smuzhiyun 					PM2XXX_CH_WD_PRECH_PHASE_60MIN);
646*4882a593Smuzhiyun 
647*4882a593Smuzhiyun 	/* Disable auto timeout */
648*4882a593Smuzhiyun 	ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG5,
649*4882a593Smuzhiyun 					PM2XXX_CH_WD_AUTO_TIMEOUT_20MIN);
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun 	/*
652*4882a593Smuzhiyun      * EOC current level = 100mA
653*4882a593Smuzhiyun 	 * Precharge current level = 100mA
654*4882a593Smuzhiyun 	 * CC current level = 1000mA
655*4882a593Smuzhiyun 	 */
656*4882a593Smuzhiyun 	ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG6,
657*4882a593Smuzhiyun 		(PM2XXX_DIR_CH_CC_CURRENT_1000MA |
658*4882a593Smuzhiyun 		PM2XXX_CH_PRECH_CURRENT_100MA |
659*4882a593Smuzhiyun 		PM2XXX_CH_EOC_CURRENT_100MA));
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun 	/*
662*4882a593Smuzhiyun      * recharge threshold = 3.8V
663*4882a593Smuzhiyun 	 * Precharge to CC threshold = 2.9V
664*4882a593Smuzhiyun 	 */
665*4882a593Smuzhiyun 	ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG7,
666*4882a593Smuzhiyun 		(PM2XXX_CH_PRECH_VOL_2_9 | PM2XXX_CH_VRESUME_VOL_3_8));
667*4882a593Smuzhiyun 
668*4882a593Smuzhiyun 	/* float voltage charger level = 4.2V */
669*4882a593Smuzhiyun 	ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG8,
670*4882a593Smuzhiyun 		PM2XXX_CH_VOLT_4_2);
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun 	/* Voltage drop between VBAT and VSYS in HW charging = 300mV */
673*4882a593Smuzhiyun 	ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG9,
674*4882a593Smuzhiyun 		(PM2XXX_CH_150MV_DROP_300MV | PM2XXX_CHARCHING_INFO_DIS |
675*4882a593Smuzhiyun 		PM2XXX_CH_CC_REDUCED_CURRENT_IDENT |
676*4882a593Smuzhiyun 		PM2XXX_CH_CC_MODEDROP_DIS));
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun 	/* Input charger level of over voltage = 10V */
679*4882a593Smuzhiyun 	ret = pm2xxx_reg_write(pm2, PM2XXX_INP_VOLT_VPWR2,
680*4882a593Smuzhiyun 					PM2XXX_VPWR2_OVV_10);
681*4882a593Smuzhiyun 	ret = pm2xxx_reg_write(pm2, PM2XXX_INP_VOLT_VPWR1,
682*4882a593Smuzhiyun 					PM2XXX_VPWR1_OVV_10);
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun 	/* Input charger drop */
685*4882a593Smuzhiyun 	ret = pm2xxx_reg_write(pm2, PM2XXX_INP_DROP_VPWR2,
686*4882a593Smuzhiyun 		(PM2XXX_VPWR2_HW_OPT_DIS | PM2XXX_VPWR2_VALID_DIS |
687*4882a593Smuzhiyun 		PM2XXX_VPWR2_DROP_DIS));
688*4882a593Smuzhiyun 	ret = pm2xxx_reg_write(pm2, PM2XXX_INP_DROP_VPWR1,
689*4882a593Smuzhiyun 		(PM2XXX_VPWR1_HW_OPT_DIS | PM2XXX_VPWR1_VALID_DIS |
690*4882a593Smuzhiyun 		PM2XXX_VPWR1_DROP_DIS));
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun 	/* Disable battery low monitoring */
693*4882a593Smuzhiyun 	ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_LOW_LEV_COMP_REG,
694*4882a593Smuzhiyun 		PM2XXX_VBAT_LOW_MONITORING_ENA);
695*4882a593Smuzhiyun 
696*4882a593Smuzhiyun 	return ret;
697*4882a593Smuzhiyun }
698*4882a593Smuzhiyun 
pm2xxx_charger_ac_en(struct ux500_charger * charger,int enable,int vset,int iset)699*4882a593Smuzhiyun static int pm2xxx_charger_ac_en(struct ux500_charger *charger,
700*4882a593Smuzhiyun 	int enable, int vset, int iset)
701*4882a593Smuzhiyun {
702*4882a593Smuzhiyun 	int ret;
703*4882a593Smuzhiyun 	int volt_index;
704*4882a593Smuzhiyun 	int curr_index;
705*4882a593Smuzhiyun 	u8 val;
706*4882a593Smuzhiyun 
707*4882a593Smuzhiyun 	struct pm2xxx_charger *pm2 = to_pm2xxx_charger_ac_device_info(charger);
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun 	if (enable) {
710*4882a593Smuzhiyun 		if (!pm2->ac.charger_connected) {
711*4882a593Smuzhiyun 			dev_dbg(pm2->dev, "AC charger not connected\n");
712*4882a593Smuzhiyun 			return -ENXIO;
713*4882a593Smuzhiyun 		}
714*4882a593Smuzhiyun 
715*4882a593Smuzhiyun 		dev_dbg(pm2->dev, "Enable AC: %dmV %dmA\n", vset, iset);
716*4882a593Smuzhiyun 		if (!pm2->vddadc_en_ac) {
717*4882a593Smuzhiyun 			ret = regulator_enable(pm2->regu);
718*4882a593Smuzhiyun 			if (ret)
719*4882a593Smuzhiyun 				dev_warn(pm2->dev,
720*4882a593Smuzhiyun 					"Failed to enable vddadc regulator\n");
721*4882a593Smuzhiyun 			else
722*4882a593Smuzhiyun 				pm2->vddadc_en_ac = true;
723*4882a593Smuzhiyun 		}
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun 		ret = pm2xxx_charging_init(pm2);
726*4882a593Smuzhiyun 		if (ret < 0) {
727*4882a593Smuzhiyun 			dev_err(pm2->dev, "%s charging init failed\n",
728*4882a593Smuzhiyun 					__func__);
729*4882a593Smuzhiyun 			goto error_occured;
730*4882a593Smuzhiyun 		}
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun 		volt_index = pm2xxx_voltage_to_regval(vset);
733*4882a593Smuzhiyun 		curr_index = pm2xxx_current_to_regval(iset);
734*4882a593Smuzhiyun 
735*4882a593Smuzhiyun 		if (volt_index < 0 || curr_index < 0) {
736*4882a593Smuzhiyun 			dev_err(pm2->dev,
737*4882a593Smuzhiyun 				"Charger voltage or current too high, "
738*4882a593Smuzhiyun 				"charging not started\n");
739*4882a593Smuzhiyun 			return -ENXIO;
740*4882a593Smuzhiyun 		}
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 		ret = pm2xxx_reg_read(pm2, PM2XXX_BATT_CTRL_REG8, &val);
743*4882a593Smuzhiyun 		if (ret < 0) {
744*4882a593Smuzhiyun 			dev_err(pm2->dev, "%s pm2xxx read failed\n", __func__);
745*4882a593Smuzhiyun 			goto error_occured;
746*4882a593Smuzhiyun 		}
747*4882a593Smuzhiyun 		val &= ~PM2XXX_CH_VOLT_MASK;
748*4882a593Smuzhiyun 		val |= volt_index;
749*4882a593Smuzhiyun 		ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG8, val);
750*4882a593Smuzhiyun 		if (ret < 0) {
751*4882a593Smuzhiyun 			dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__);
752*4882a593Smuzhiyun 			goto error_occured;
753*4882a593Smuzhiyun 		}
754*4882a593Smuzhiyun 
755*4882a593Smuzhiyun 		ret = pm2xxx_reg_read(pm2, PM2XXX_BATT_CTRL_REG6, &val);
756*4882a593Smuzhiyun 		if (ret < 0) {
757*4882a593Smuzhiyun 			dev_err(pm2->dev, "%s pm2xxx read failed\n", __func__);
758*4882a593Smuzhiyun 			goto error_occured;
759*4882a593Smuzhiyun 		}
760*4882a593Smuzhiyun 		val &= ~PM2XXX_DIR_CH_CC_CURRENT_MASK;
761*4882a593Smuzhiyun 		val |= curr_index;
762*4882a593Smuzhiyun 		ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG6, val);
763*4882a593Smuzhiyun 		if (ret < 0) {
764*4882a593Smuzhiyun 			dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__);
765*4882a593Smuzhiyun 			goto error_occured;
766*4882a593Smuzhiyun 		}
767*4882a593Smuzhiyun 
768*4882a593Smuzhiyun 		if (!pm2->bat->enable_overshoot) {
769*4882a593Smuzhiyun 			ret = pm2xxx_reg_read(pm2, PM2XXX_LED_CTRL_REG, &val);
770*4882a593Smuzhiyun 			if (ret < 0) {
771*4882a593Smuzhiyun 				dev_err(pm2->dev, "%s pm2xxx read failed\n",
772*4882a593Smuzhiyun 								__func__);
773*4882a593Smuzhiyun 				goto error_occured;
774*4882a593Smuzhiyun 			}
775*4882a593Smuzhiyun 			val |= PM2XXX_ANTI_OVERSHOOT_EN;
776*4882a593Smuzhiyun 			ret = pm2xxx_reg_write(pm2, PM2XXX_LED_CTRL_REG, val);
777*4882a593Smuzhiyun 			if (ret < 0) {
778*4882a593Smuzhiyun 				dev_err(pm2->dev, "%s pm2xxx write failed\n",
779*4882a593Smuzhiyun 								__func__);
780*4882a593Smuzhiyun 				goto error_occured;
781*4882a593Smuzhiyun 			}
782*4882a593Smuzhiyun 		}
783*4882a593Smuzhiyun 
784*4882a593Smuzhiyun 		ret = pm2xxx_charging_enable_mngt(pm2);
785*4882a593Smuzhiyun 		if (ret < 0) {
786*4882a593Smuzhiyun 			dev_err(pm2->dev, "Failed to enable"
787*4882a593Smuzhiyun 						"pm2xxx ac charger\n");
788*4882a593Smuzhiyun 			goto error_occured;
789*4882a593Smuzhiyun 		}
790*4882a593Smuzhiyun 
791*4882a593Smuzhiyun 		pm2->ac.charger_online = 1;
792*4882a593Smuzhiyun 	} else {
793*4882a593Smuzhiyun 		pm2->ac.charger_online = 0;
794*4882a593Smuzhiyun 		pm2->ac.wd_expired = false;
795*4882a593Smuzhiyun 
796*4882a593Smuzhiyun 		/* Disable regulator if enabled */
797*4882a593Smuzhiyun 		if (pm2->vddadc_en_ac) {
798*4882a593Smuzhiyun 			regulator_disable(pm2->regu);
799*4882a593Smuzhiyun 			pm2->vddadc_en_ac = false;
800*4882a593Smuzhiyun 		}
801*4882a593Smuzhiyun 
802*4882a593Smuzhiyun 		ret = pm2xxx_charging_disable_mngt(pm2);
803*4882a593Smuzhiyun 		if (ret < 0) {
804*4882a593Smuzhiyun 			dev_err(pm2->dev, "failed to disable"
805*4882a593Smuzhiyun 						"pm2xxx ac charger\n");
806*4882a593Smuzhiyun 			goto error_occured;
807*4882a593Smuzhiyun 		}
808*4882a593Smuzhiyun 
809*4882a593Smuzhiyun 		dev_dbg(pm2->dev, "PM2301: " "Disabled AC charging\n");
810*4882a593Smuzhiyun 	}
811*4882a593Smuzhiyun 	power_supply_changed(pm2->ac_chg.psy);
812*4882a593Smuzhiyun 
813*4882a593Smuzhiyun error_occured:
814*4882a593Smuzhiyun 	return ret;
815*4882a593Smuzhiyun }
816*4882a593Smuzhiyun 
pm2xxx_charger_watchdog_kick(struct ux500_charger * charger)817*4882a593Smuzhiyun static int pm2xxx_charger_watchdog_kick(struct ux500_charger *charger)
818*4882a593Smuzhiyun {
819*4882a593Smuzhiyun 	int ret;
820*4882a593Smuzhiyun 	struct pm2xxx_charger *pm2;
821*4882a593Smuzhiyun 
822*4882a593Smuzhiyun 	if (charger->psy->desc->type == POWER_SUPPLY_TYPE_MAINS)
823*4882a593Smuzhiyun 		pm2 = to_pm2xxx_charger_ac_device_info(charger);
824*4882a593Smuzhiyun 	else
825*4882a593Smuzhiyun 		return -ENXIO;
826*4882a593Smuzhiyun 
827*4882a593Smuzhiyun 	ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_WD_KICK, WD_TIMER);
828*4882a593Smuzhiyun 	if (ret)
829*4882a593Smuzhiyun 		dev_err(pm2->dev, "Failed to kick WD!\n");
830*4882a593Smuzhiyun 
831*4882a593Smuzhiyun 	return ret;
832*4882a593Smuzhiyun }
833*4882a593Smuzhiyun 
pm2xxx_charger_ac_work(struct work_struct * work)834*4882a593Smuzhiyun static void pm2xxx_charger_ac_work(struct work_struct *work)
835*4882a593Smuzhiyun {
836*4882a593Smuzhiyun 	struct pm2xxx_charger *pm2 = container_of(work,
837*4882a593Smuzhiyun 		struct pm2xxx_charger, ac_work);
838*4882a593Smuzhiyun 
839*4882a593Smuzhiyun 
840*4882a593Smuzhiyun 	power_supply_changed(pm2->ac_chg.psy);
841*4882a593Smuzhiyun 	sysfs_notify(&pm2->ac_chg.psy->dev.kobj, NULL, "present");
842*4882a593Smuzhiyun };
843*4882a593Smuzhiyun 
pm2xxx_charger_check_hw_failure_work(struct work_struct * work)844*4882a593Smuzhiyun static void pm2xxx_charger_check_hw_failure_work(struct work_struct *work)
845*4882a593Smuzhiyun {
846*4882a593Smuzhiyun 	u8 reg_value;
847*4882a593Smuzhiyun 
848*4882a593Smuzhiyun 	struct pm2xxx_charger *pm2 = container_of(work,
849*4882a593Smuzhiyun 		struct pm2xxx_charger, check_hw_failure_work.work);
850*4882a593Smuzhiyun 
851*4882a593Smuzhiyun 	if (pm2->flags.ovv) {
852*4882a593Smuzhiyun 		pm2xxx_reg_read(pm2, PM2XXX_SRCE_REG_INT4, &reg_value);
853*4882a593Smuzhiyun 
854*4882a593Smuzhiyun 		if (!(reg_value & (PM2XXX_INT4_S_ITVPWR1OVV |
855*4882a593Smuzhiyun 					PM2XXX_INT4_S_ITVPWR2OVV))) {
856*4882a593Smuzhiyun 			pm2->flags.ovv = false;
857*4882a593Smuzhiyun 			power_supply_changed(pm2->ac_chg.psy);
858*4882a593Smuzhiyun 		}
859*4882a593Smuzhiyun 	}
860*4882a593Smuzhiyun 
861*4882a593Smuzhiyun 	/* If we still have a failure, schedule a new check */
862*4882a593Smuzhiyun 	if (pm2->flags.ovv) {
863*4882a593Smuzhiyun 		queue_delayed_work(pm2->charger_wq,
864*4882a593Smuzhiyun 			&pm2->check_hw_failure_work, round_jiffies(HZ));
865*4882a593Smuzhiyun 	}
866*4882a593Smuzhiyun }
867*4882a593Smuzhiyun 
pm2xxx_charger_check_main_thermal_prot_work(struct work_struct * work)868*4882a593Smuzhiyun static void pm2xxx_charger_check_main_thermal_prot_work(
869*4882a593Smuzhiyun 	struct work_struct *work)
870*4882a593Smuzhiyun {
871*4882a593Smuzhiyun 	int ret;
872*4882a593Smuzhiyun 	u8 val;
873*4882a593Smuzhiyun 
874*4882a593Smuzhiyun 	struct pm2xxx_charger *pm2 = container_of(work, struct pm2xxx_charger,
875*4882a593Smuzhiyun 					check_main_thermal_prot_work);
876*4882a593Smuzhiyun 
877*4882a593Smuzhiyun 	/* Check if die temp warning is still active */
878*4882a593Smuzhiyun 	ret = pm2xxx_reg_read(pm2, PM2XXX_SRCE_REG_INT5, &val);
879*4882a593Smuzhiyun 	if (ret < 0) {
880*4882a593Smuzhiyun 		dev_err(pm2->dev, "%s pm2xxx read failed\n", __func__);
881*4882a593Smuzhiyun 		return;
882*4882a593Smuzhiyun 	}
883*4882a593Smuzhiyun 	if (val & (PM2XXX_INT5_S_ITTHERMALWARNINGRISE
884*4882a593Smuzhiyun 			| PM2XXX_INT5_S_ITTHERMALSHUTDOWNRISE))
885*4882a593Smuzhiyun 		pm2->flags.main_thermal_prot = true;
886*4882a593Smuzhiyun 	else if (val & (PM2XXX_INT5_S_ITTHERMALWARNINGFALL
887*4882a593Smuzhiyun 				| PM2XXX_INT5_S_ITTHERMALSHUTDOWNFALL))
888*4882a593Smuzhiyun 		pm2->flags.main_thermal_prot = false;
889*4882a593Smuzhiyun 
890*4882a593Smuzhiyun 	power_supply_changed(pm2->ac_chg.psy);
891*4882a593Smuzhiyun }
892*4882a593Smuzhiyun 
893*4882a593Smuzhiyun static struct pm2xxx_interrupts pm2xxx_int = {
894*4882a593Smuzhiyun 	.handler[0] = pm2_int_reg0,
895*4882a593Smuzhiyun 	.handler[1] = pm2_int_reg1,
896*4882a593Smuzhiyun 	.handler[2] = pm2_int_reg2,
897*4882a593Smuzhiyun 	.handler[3] = pm2_int_reg3,
898*4882a593Smuzhiyun 	.handler[4] = pm2_int_reg4,
899*4882a593Smuzhiyun 	.handler[5] = pm2_int_reg5,
900*4882a593Smuzhiyun };
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun static struct pm2xxx_irq pm2xxx_charger_irq[] = {
903*4882a593Smuzhiyun 	{"PM2XXX_IRQ_INT", pm2xxx_irq_int},
904*4882a593Smuzhiyun };
905*4882a593Smuzhiyun 
pm2xxx_wall_charger_resume(struct device * dev)906*4882a593Smuzhiyun static int __maybe_unused pm2xxx_wall_charger_resume(struct device *dev)
907*4882a593Smuzhiyun {
908*4882a593Smuzhiyun 	struct i2c_client *i2c_client = to_i2c_client(dev);
909*4882a593Smuzhiyun 	struct pm2xxx_charger *pm2;
910*4882a593Smuzhiyun 
911*4882a593Smuzhiyun 	pm2 =  (struct pm2xxx_charger *)i2c_get_clientdata(i2c_client);
912*4882a593Smuzhiyun 	set_lpn_pin(pm2);
913*4882a593Smuzhiyun 
914*4882a593Smuzhiyun 	/* If we still have a HW failure, schedule a new check */
915*4882a593Smuzhiyun 	if (pm2->flags.ovv)
916*4882a593Smuzhiyun 		queue_delayed_work(pm2->charger_wq,
917*4882a593Smuzhiyun 				&pm2->check_hw_failure_work, 0);
918*4882a593Smuzhiyun 
919*4882a593Smuzhiyun 	return 0;
920*4882a593Smuzhiyun }
921*4882a593Smuzhiyun 
pm2xxx_wall_charger_suspend(struct device * dev)922*4882a593Smuzhiyun static int __maybe_unused pm2xxx_wall_charger_suspend(struct device *dev)
923*4882a593Smuzhiyun {
924*4882a593Smuzhiyun 	struct i2c_client *i2c_client = to_i2c_client(dev);
925*4882a593Smuzhiyun 	struct pm2xxx_charger *pm2;
926*4882a593Smuzhiyun 
927*4882a593Smuzhiyun 	pm2 =  (struct pm2xxx_charger *)i2c_get_clientdata(i2c_client);
928*4882a593Smuzhiyun 	clear_lpn_pin(pm2);
929*4882a593Smuzhiyun 
930*4882a593Smuzhiyun 	/* Cancel any pending HW failure check */
931*4882a593Smuzhiyun 	if (delayed_work_pending(&pm2->check_hw_failure_work))
932*4882a593Smuzhiyun 		cancel_delayed_work(&pm2->check_hw_failure_work);
933*4882a593Smuzhiyun 
934*4882a593Smuzhiyun 	flush_work(&pm2->ac_work);
935*4882a593Smuzhiyun 	flush_work(&pm2->check_main_thermal_prot_work);
936*4882a593Smuzhiyun 
937*4882a593Smuzhiyun 	return 0;
938*4882a593Smuzhiyun }
939*4882a593Smuzhiyun 
pm2xxx_runtime_suspend(struct device * dev)940*4882a593Smuzhiyun static int __maybe_unused pm2xxx_runtime_suspend(struct device *dev)
941*4882a593Smuzhiyun {
942*4882a593Smuzhiyun 	struct i2c_client *pm2xxx_i2c_client = to_i2c_client(dev);
943*4882a593Smuzhiyun 	struct pm2xxx_charger *pm2;
944*4882a593Smuzhiyun 
945*4882a593Smuzhiyun 	pm2 = (struct pm2xxx_charger *)i2c_get_clientdata(pm2xxx_i2c_client);
946*4882a593Smuzhiyun 	clear_lpn_pin(pm2);
947*4882a593Smuzhiyun 
948*4882a593Smuzhiyun 	return 0;
949*4882a593Smuzhiyun }
950*4882a593Smuzhiyun 
pm2xxx_runtime_resume(struct device * dev)951*4882a593Smuzhiyun static int __maybe_unused pm2xxx_runtime_resume(struct device *dev)
952*4882a593Smuzhiyun {
953*4882a593Smuzhiyun 	struct i2c_client *pm2xxx_i2c_client = to_i2c_client(dev);
954*4882a593Smuzhiyun 	struct pm2xxx_charger *pm2;
955*4882a593Smuzhiyun 
956*4882a593Smuzhiyun 	pm2 = (struct pm2xxx_charger *)i2c_get_clientdata(pm2xxx_i2c_client);
957*4882a593Smuzhiyun 
958*4882a593Smuzhiyun 	if (gpio_is_valid(pm2->lpn_pin) && gpio_get_value(pm2->lpn_pin) == 0)
959*4882a593Smuzhiyun 		set_lpn_pin(pm2);
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun 	return 0;
962*4882a593Smuzhiyun }
963*4882a593Smuzhiyun 
964*4882a593Smuzhiyun static const struct dev_pm_ops pm2xxx_pm_ops __maybe_unused = {
965*4882a593Smuzhiyun 	SET_SYSTEM_SLEEP_PM_OPS(pm2xxx_wall_charger_suspend,
966*4882a593Smuzhiyun 		pm2xxx_wall_charger_resume)
967*4882a593Smuzhiyun 	SET_RUNTIME_PM_OPS(pm2xxx_runtime_suspend, pm2xxx_runtime_resume, NULL)
968*4882a593Smuzhiyun };
969*4882a593Smuzhiyun 
pm2xxx_wall_charger_probe(struct i2c_client * i2c_client,const struct i2c_device_id * id)970*4882a593Smuzhiyun static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client,
971*4882a593Smuzhiyun 		const struct i2c_device_id *id)
972*4882a593Smuzhiyun {
973*4882a593Smuzhiyun 	struct pm2xxx_platform_data *pl_data = i2c_client->dev.platform_data;
974*4882a593Smuzhiyun 	struct power_supply_config psy_cfg = {};
975*4882a593Smuzhiyun 	struct pm2xxx_charger *pm2;
976*4882a593Smuzhiyun 	int ret = 0;
977*4882a593Smuzhiyun 	u8 val;
978*4882a593Smuzhiyun 	int i;
979*4882a593Smuzhiyun 
980*4882a593Smuzhiyun 	if (!pl_data) {
981*4882a593Smuzhiyun 		dev_err(&i2c_client->dev, "No platform data supplied\n");
982*4882a593Smuzhiyun 		return -EINVAL;
983*4882a593Smuzhiyun 	}
984*4882a593Smuzhiyun 
985*4882a593Smuzhiyun 	pm2 = kzalloc(sizeof(struct pm2xxx_charger), GFP_KERNEL);
986*4882a593Smuzhiyun 	if (!pm2) {
987*4882a593Smuzhiyun 		dev_err(&i2c_client->dev, "pm2xxx_charger allocation failed\n");
988*4882a593Smuzhiyun 		return -ENOMEM;
989*4882a593Smuzhiyun 	}
990*4882a593Smuzhiyun 
991*4882a593Smuzhiyun 	/* get parent data */
992*4882a593Smuzhiyun 	pm2->dev = &i2c_client->dev;
993*4882a593Smuzhiyun 
994*4882a593Smuzhiyun 	pm2->pm2_int = &pm2xxx_int;
995*4882a593Smuzhiyun 
996*4882a593Smuzhiyun 	/* get charger spcific platform data */
997*4882a593Smuzhiyun 	if (!pl_data->wall_charger) {
998*4882a593Smuzhiyun 		dev_err(pm2->dev, "no charger platform data supplied\n");
999*4882a593Smuzhiyun 		ret = -EINVAL;
1000*4882a593Smuzhiyun 		goto free_device_info;
1001*4882a593Smuzhiyun 	}
1002*4882a593Smuzhiyun 
1003*4882a593Smuzhiyun 	pm2->pdata = pl_data->wall_charger;
1004*4882a593Smuzhiyun 
1005*4882a593Smuzhiyun 	/* get battery specific platform data */
1006*4882a593Smuzhiyun 	if (!pl_data->battery) {
1007*4882a593Smuzhiyun 		dev_err(pm2->dev, "no battery platform data supplied\n");
1008*4882a593Smuzhiyun 		ret = -EINVAL;
1009*4882a593Smuzhiyun 		goto free_device_info;
1010*4882a593Smuzhiyun 	}
1011*4882a593Smuzhiyun 
1012*4882a593Smuzhiyun 	pm2->bat = pl_data->battery;
1013*4882a593Smuzhiyun 
1014*4882a593Smuzhiyun 	if (!i2c_check_functionality(i2c_client->adapter,
1015*4882a593Smuzhiyun 			I2C_FUNC_SMBUS_BYTE_DATA |
1016*4882a593Smuzhiyun 			I2C_FUNC_SMBUS_READ_WORD_DATA)) {
1017*4882a593Smuzhiyun 		ret = -ENODEV;
1018*4882a593Smuzhiyun 		dev_info(pm2->dev, "pm2301 i2c_check_functionality failed\n");
1019*4882a593Smuzhiyun 		goto free_device_info;
1020*4882a593Smuzhiyun 	}
1021*4882a593Smuzhiyun 
1022*4882a593Smuzhiyun 	pm2->config.pm2xxx_i2c = i2c_client;
1023*4882a593Smuzhiyun 	pm2->config.pm2xxx_id = (struct i2c_device_id *) id;
1024*4882a593Smuzhiyun 	i2c_set_clientdata(i2c_client, pm2);
1025*4882a593Smuzhiyun 
1026*4882a593Smuzhiyun 	/* AC supply */
1027*4882a593Smuzhiyun 	/* power_supply base class */
1028*4882a593Smuzhiyun 	pm2->ac_chg_desc.name = pm2->pdata->label;
1029*4882a593Smuzhiyun 	pm2->ac_chg_desc.type = POWER_SUPPLY_TYPE_MAINS;
1030*4882a593Smuzhiyun 	pm2->ac_chg_desc.properties = pm2xxx_charger_ac_props;
1031*4882a593Smuzhiyun 	pm2->ac_chg_desc.num_properties = ARRAY_SIZE(pm2xxx_charger_ac_props);
1032*4882a593Smuzhiyun 	pm2->ac_chg_desc.get_property = pm2xxx_charger_ac_get_property;
1033*4882a593Smuzhiyun 
1034*4882a593Smuzhiyun 	psy_cfg.supplied_to = pm2->pdata->supplied_to;
1035*4882a593Smuzhiyun 	psy_cfg.num_supplicants = pm2->pdata->num_supplicants;
1036*4882a593Smuzhiyun 	/* pm2xxx_charger sub-class */
1037*4882a593Smuzhiyun 	pm2->ac_chg.ops.enable = &pm2xxx_charger_ac_en;
1038*4882a593Smuzhiyun 	pm2->ac_chg.ops.kick_wd = &pm2xxx_charger_watchdog_kick;
1039*4882a593Smuzhiyun 	pm2->ac_chg.ops.update_curr = &pm2xxx_charger_update_charger_current;
1040*4882a593Smuzhiyun 	pm2->ac_chg.max_out_volt = pm2xxx_charger_voltage_map[
1041*4882a593Smuzhiyun 		ARRAY_SIZE(pm2xxx_charger_voltage_map) - 1];
1042*4882a593Smuzhiyun 	pm2->ac_chg.max_out_curr = pm2xxx_charger_current_map[
1043*4882a593Smuzhiyun 		ARRAY_SIZE(pm2xxx_charger_current_map) - 1];
1044*4882a593Smuzhiyun 	pm2->ac_chg.wdt_refresh = WD_KICK_INTERVAL;
1045*4882a593Smuzhiyun 	pm2->ac_chg.enabled = true;
1046*4882a593Smuzhiyun 	pm2->ac_chg.external = true;
1047*4882a593Smuzhiyun 
1048*4882a593Smuzhiyun 	/* Create a work queue for the charger */
1049*4882a593Smuzhiyun 	pm2->charger_wq = alloc_ordered_workqueue("pm2xxx_charger_wq",
1050*4882a593Smuzhiyun 						  WQ_MEM_RECLAIM);
1051*4882a593Smuzhiyun 	if (pm2->charger_wq == NULL) {
1052*4882a593Smuzhiyun 		ret = -ENOMEM;
1053*4882a593Smuzhiyun 		dev_err(pm2->dev, "failed to create work queue\n");
1054*4882a593Smuzhiyun 		goto free_device_info;
1055*4882a593Smuzhiyun 	}
1056*4882a593Smuzhiyun 
1057*4882a593Smuzhiyun 	/* Init work for charger detection */
1058*4882a593Smuzhiyun 	INIT_WORK(&pm2->ac_work, pm2xxx_charger_ac_work);
1059*4882a593Smuzhiyun 
1060*4882a593Smuzhiyun 	/* Init work for checking HW status */
1061*4882a593Smuzhiyun 	INIT_WORK(&pm2->check_main_thermal_prot_work,
1062*4882a593Smuzhiyun 		pm2xxx_charger_check_main_thermal_prot_work);
1063*4882a593Smuzhiyun 
1064*4882a593Smuzhiyun 	/* Init work for HW failure check */
1065*4882a593Smuzhiyun 	INIT_DEFERRABLE_WORK(&pm2->check_hw_failure_work,
1066*4882a593Smuzhiyun 		pm2xxx_charger_check_hw_failure_work);
1067*4882a593Smuzhiyun 
1068*4882a593Smuzhiyun 	/*
1069*4882a593Smuzhiyun 	 * VDD ADC supply needs to be enabled from this driver when there
1070*4882a593Smuzhiyun 	 * is a charger connected to avoid erroneous BTEMP_HIGH/LOW
1071*4882a593Smuzhiyun 	 * interrupts during charging
1072*4882a593Smuzhiyun 	 */
1073*4882a593Smuzhiyun 	pm2->regu = regulator_get(pm2->dev, "vddadc");
1074*4882a593Smuzhiyun 	if (IS_ERR(pm2->regu)) {
1075*4882a593Smuzhiyun 		ret = PTR_ERR(pm2->regu);
1076*4882a593Smuzhiyun 		dev_err(pm2->dev, "failed to get vddadc regulator\n");
1077*4882a593Smuzhiyun 		goto free_charger_wq;
1078*4882a593Smuzhiyun 	}
1079*4882a593Smuzhiyun 
1080*4882a593Smuzhiyun 	/* Register AC charger class */
1081*4882a593Smuzhiyun 	pm2->ac_chg.psy = power_supply_register(pm2->dev, &pm2->ac_chg_desc,
1082*4882a593Smuzhiyun 						&psy_cfg);
1083*4882a593Smuzhiyun 	if (IS_ERR(pm2->ac_chg.psy)) {
1084*4882a593Smuzhiyun 		dev_err(pm2->dev, "failed to register AC charger\n");
1085*4882a593Smuzhiyun 		ret = PTR_ERR(pm2->ac_chg.psy);
1086*4882a593Smuzhiyun 		goto free_regulator;
1087*4882a593Smuzhiyun 	}
1088*4882a593Smuzhiyun 
1089*4882a593Smuzhiyun 	/* Register interrupts */
1090*4882a593Smuzhiyun 	ret = request_threaded_irq(gpio_to_irq(pm2->pdata->gpio_irq_number),
1091*4882a593Smuzhiyun 				NULL,
1092*4882a593Smuzhiyun 				pm2xxx_charger_irq[0].isr,
1093*4882a593Smuzhiyun 				pm2->pdata->irq_type | IRQF_ONESHOT,
1094*4882a593Smuzhiyun 				pm2xxx_charger_irq[0].name, pm2);
1095*4882a593Smuzhiyun 
1096*4882a593Smuzhiyun 	if (ret != 0) {
1097*4882a593Smuzhiyun 		dev_err(pm2->dev, "failed to request %s IRQ %d: %d\n",
1098*4882a593Smuzhiyun 		pm2xxx_charger_irq[0].name,
1099*4882a593Smuzhiyun 			gpio_to_irq(pm2->pdata->gpio_irq_number), ret);
1100*4882a593Smuzhiyun 		goto unregister_pm2xxx_charger;
1101*4882a593Smuzhiyun 	}
1102*4882a593Smuzhiyun 
1103*4882a593Smuzhiyun 	ret = pm_runtime_set_active(pm2->dev);
1104*4882a593Smuzhiyun 	if (ret)
1105*4882a593Smuzhiyun 		dev_err(pm2->dev, "set active Error\n");
1106*4882a593Smuzhiyun 
1107*4882a593Smuzhiyun 	pm_runtime_enable(pm2->dev);
1108*4882a593Smuzhiyun 	pm_runtime_set_autosuspend_delay(pm2->dev, PM2XXX_AUTOSUSPEND_DELAY);
1109*4882a593Smuzhiyun 	pm_runtime_use_autosuspend(pm2->dev);
1110*4882a593Smuzhiyun 	pm_runtime_resume(pm2->dev);
1111*4882a593Smuzhiyun 
1112*4882a593Smuzhiyun 	/* pm interrupt can wake up system */
1113*4882a593Smuzhiyun 	ret = enable_irq_wake(gpio_to_irq(pm2->pdata->gpio_irq_number));
1114*4882a593Smuzhiyun 	if (ret) {
1115*4882a593Smuzhiyun 		dev_err(pm2->dev, "failed to set irq wake\n");
1116*4882a593Smuzhiyun 		goto unregister_pm2xxx_interrupt;
1117*4882a593Smuzhiyun 	}
1118*4882a593Smuzhiyun 
1119*4882a593Smuzhiyun 	mutex_init(&pm2->lock);
1120*4882a593Smuzhiyun 
1121*4882a593Smuzhiyun 	if (gpio_is_valid(pm2->pdata->lpn_gpio)) {
1122*4882a593Smuzhiyun 		/* get lpn GPIO from platform data */
1123*4882a593Smuzhiyun 		pm2->lpn_pin = pm2->pdata->lpn_gpio;
1124*4882a593Smuzhiyun 
1125*4882a593Smuzhiyun 		/*
1126*4882a593Smuzhiyun 		 * Charger detection mechanism requires pulling up the LPN pin
1127*4882a593Smuzhiyun 		 * while i2c communication if Charger is not connected
1128*4882a593Smuzhiyun 		 * LPN pin of PM2301 is GPIO60 of AB9540
1129*4882a593Smuzhiyun 		 */
1130*4882a593Smuzhiyun 		ret = gpio_request(pm2->lpn_pin, "pm2301_lpm_gpio");
1131*4882a593Smuzhiyun 
1132*4882a593Smuzhiyun 		if (ret < 0) {
1133*4882a593Smuzhiyun 			dev_err(pm2->dev, "pm2301_lpm_gpio request failed\n");
1134*4882a593Smuzhiyun 			goto disable_pm2_irq_wake;
1135*4882a593Smuzhiyun 		}
1136*4882a593Smuzhiyun 		ret = gpio_direction_output(pm2->lpn_pin, 0);
1137*4882a593Smuzhiyun 		if (ret < 0) {
1138*4882a593Smuzhiyun 			dev_err(pm2->dev, "pm2301_lpm_gpio direction failed\n");
1139*4882a593Smuzhiyun 			goto free_gpio;
1140*4882a593Smuzhiyun 		}
1141*4882a593Smuzhiyun 		set_lpn_pin(pm2);
1142*4882a593Smuzhiyun 	}
1143*4882a593Smuzhiyun 
1144*4882a593Smuzhiyun 	/* read  interrupt registers */
1145*4882a593Smuzhiyun 	for (i = 0; i < PM2XXX_NUM_INT_REG; i++)
1146*4882a593Smuzhiyun 		pm2xxx_reg_read(pm2,
1147*4882a593Smuzhiyun 			pm2xxx_interrupt_registers[i],
1148*4882a593Smuzhiyun 			&val);
1149*4882a593Smuzhiyun 
1150*4882a593Smuzhiyun 	ret = pm2xxx_charger_detection(pm2, &val);
1151*4882a593Smuzhiyun 
1152*4882a593Smuzhiyun 	if ((ret == 0) && val) {
1153*4882a593Smuzhiyun 		pm2->ac.charger_connected = 1;
1154*4882a593Smuzhiyun 		ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON,
1155*4882a593Smuzhiyun 					     AB8500_MAIN_CH_DET);
1156*4882a593Smuzhiyun 		pm2->ac_conn = true;
1157*4882a593Smuzhiyun 		power_supply_changed(pm2->ac_chg.psy);
1158*4882a593Smuzhiyun 		sysfs_notify(&pm2->ac_chg.psy->dev.kobj, NULL, "present");
1159*4882a593Smuzhiyun 	}
1160*4882a593Smuzhiyun 
1161*4882a593Smuzhiyun 	return 0;
1162*4882a593Smuzhiyun 
1163*4882a593Smuzhiyun free_gpio:
1164*4882a593Smuzhiyun 	if (gpio_is_valid(pm2->lpn_pin))
1165*4882a593Smuzhiyun 		gpio_free(pm2->lpn_pin);
1166*4882a593Smuzhiyun disable_pm2_irq_wake:
1167*4882a593Smuzhiyun 	disable_irq_wake(gpio_to_irq(pm2->pdata->gpio_irq_number));
1168*4882a593Smuzhiyun unregister_pm2xxx_interrupt:
1169*4882a593Smuzhiyun 	/* disable interrupt */
1170*4882a593Smuzhiyun 	free_irq(gpio_to_irq(pm2->pdata->gpio_irq_number), pm2);
1171*4882a593Smuzhiyun unregister_pm2xxx_charger:
1172*4882a593Smuzhiyun 	/* unregister power supply */
1173*4882a593Smuzhiyun 	power_supply_unregister(pm2->ac_chg.psy);
1174*4882a593Smuzhiyun free_regulator:
1175*4882a593Smuzhiyun 	/* disable the regulator */
1176*4882a593Smuzhiyun 	regulator_put(pm2->regu);
1177*4882a593Smuzhiyun free_charger_wq:
1178*4882a593Smuzhiyun 	destroy_workqueue(pm2->charger_wq);
1179*4882a593Smuzhiyun free_device_info:
1180*4882a593Smuzhiyun 	kfree(pm2);
1181*4882a593Smuzhiyun 
1182*4882a593Smuzhiyun 	return ret;
1183*4882a593Smuzhiyun }
1184*4882a593Smuzhiyun 
pm2xxx_wall_charger_remove(struct i2c_client * i2c_client)1185*4882a593Smuzhiyun static int pm2xxx_wall_charger_remove(struct i2c_client *i2c_client)
1186*4882a593Smuzhiyun {
1187*4882a593Smuzhiyun 	struct pm2xxx_charger *pm2 = i2c_get_clientdata(i2c_client);
1188*4882a593Smuzhiyun 
1189*4882a593Smuzhiyun 	/* Disable pm_runtime */
1190*4882a593Smuzhiyun 	pm_runtime_disable(pm2->dev);
1191*4882a593Smuzhiyun 	/* Disable AC charging */
1192*4882a593Smuzhiyun 	pm2xxx_charger_ac_en(&pm2->ac_chg, false, 0, 0);
1193*4882a593Smuzhiyun 
1194*4882a593Smuzhiyun 	/* Disable wake by pm interrupt */
1195*4882a593Smuzhiyun 	disable_irq_wake(gpio_to_irq(pm2->pdata->gpio_irq_number));
1196*4882a593Smuzhiyun 
1197*4882a593Smuzhiyun 	/* Disable interrupts */
1198*4882a593Smuzhiyun 	free_irq(gpio_to_irq(pm2->pdata->gpio_irq_number), pm2);
1199*4882a593Smuzhiyun 
1200*4882a593Smuzhiyun 	/* Delete the work queue */
1201*4882a593Smuzhiyun 	destroy_workqueue(pm2->charger_wq);
1202*4882a593Smuzhiyun 
1203*4882a593Smuzhiyun 	flush_scheduled_work();
1204*4882a593Smuzhiyun 
1205*4882a593Smuzhiyun 	/* disable the regulator */
1206*4882a593Smuzhiyun 	regulator_put(pm2->regu);
1207*4882a593Smuzhiyun 
1208*4882a593Smuzhiyun 	power_supply_unregister(pm2->ac_chg.psy);
1209*4882a593Smuzhiyun 
1210*4882a593Smuzhiyun 	if (gpio_is_valid(pm2->lpn_pin))
1211*4882a593Smuzhiyun 		gpio_free(pm2->lpn_pin);
1212*4882a593Smuzhiyun 
1213*4882a593Smuzhiyun 	kfree(pm2);
1214*4882a593Smuzhiyun 
1215*4882a593Smuzhiyun 	return 0;
1216*4882a593Smuzhiyun }
1217*4882a593Smuzhiyun 
1218*4882a593Smuzhiyun static const struct i2c_device_id pm2xxx_id[] = {
1219*4882a593Smuzhiyun 	{ "pm2301", 0 },
1220*4882a593Smuzhiyun 	{ }
1221*4882a593Smuzhiyun };
1222*4882a593Smuzhiyun 
1223*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, pm2xxx_id);
1224*4882a593Smuzhiyun 
1225*4882a593Smuzhiyun static struct i2c_driver pm2xxx_charger_driver = {
1226*4882a593Smuzhiyun 	.probe = pm2xxx_wall_charger_probe,
1227*4882a593Smuzhiyun 	.remove = pm2xxx_wall_charger_remove,
1228*4882a593Smuzhiyun 	.driver = {
1229*4882a593Smuzhiyun 		.name = "pm2xxx-wall_charger",
1230*4882a593Smuzhiyun 		.pm = IS_ENABLED(CONFIG_PM) ? &pm2xxx_pm_ops : NULL,
1231*4882a593Smuzhiyun 	},
1232*4882a593Smuzhiyun 	.id_table = pm2xxx_id,
1233*4882a593Smuzhiyun };
1234*4882a593Smuzhiyun 
pm2xxx_charger_init(void)1235*4882a593Smuzhiyun static int __init pm2xxx_charger_init(void)
1236*4882a593Smuzhiyun {
1237*4882a593Smuzhiyun 	return i2c_add_driver(&pm2xxx_charger_driver);
1238*4882a593Smuzhiyun }
1239*4882a593Smuzhiyun 
pm2xxx_charger_exit(void)1240*4882a593Smuzhiyun static void __exit pm2xxx_charger_exit(void)
1241*4882a593Smuzhiyun {
1242*4882a593Smuzhiyun 	i2c_del_driver(&pm2xxx_charger_driver);
1243*4882a593Smuzhiyun }
1244*4882a593Smuzhiyun 
1245*4882a593Smuzhiyun device_initcall_sync(pm2xxx_charger_init);
1246*4882a593Smuzhiyun module_exit(pm2xxx_charger_exit);
1247*4882a593Smuzhiyun 
1248*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
1249*4882a593Smuzhiyun MODULE_AUTHOR("Rajkumar kasirajan, Olivier Launay");
1250*4882a593Smuzhiyun MODULE_DESCRIPTION("PM2xxx charger management driver");
1251