1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * axp288_charger.c - X-power AXP288 PMIC Charger driver
4  *
5  * Copyright (C) 2016-2017 Hans de Goede <hdegoede@redhat.com>
6  * Copyright (C) 2014 Intel Corporation
7  * Author: Ramakrishna Pallala <ramakrishna.pallala@intel.com>
8  */
9 
10 #include <linux/acpi.h>
11 #include <linux/bitops.h>
12 #include <linux/module.h>
13 #include <linux/device.h>
14 #include <linux/regmap.h>
15 #include <linux/workqueue.h>
16 #include <linux/delay.h>
17 #include <linux/platform_device.h>
18 #include <linux/usb/otg.h>
19 #include <linux/notifier.h>
20 #include <linux/power_supply.h>
21 #include <linux/property.h>
22 #include <linux/mfd/axp20x.h>
23 #include <linux/extcon.h>
24 
25 #define PS_STAT_VBUS_TRIGGER		BIT(0)
26 #define PS_STAT_BAT_CHRG_DIR		BIT(2)
27 #define PS_STAT_VBAT_ABOVE_VHOLD	BIT(3)
28 #define PS_STAT_VBUS_VALID		BIT(4)
29 #define PS_STAT_VBUS_PRESENT		BIT(5)
30 
31 #define CHRG_STAT_BAT_SAFE_MODE		BIT(3)
32 #define CHRG_STAT_BAT_VALID		BIT(4)
33 #define CHRG_STAT_BAT_PRESENT		BIT(5)
34 #define CHRG_STAT_CHARGING		BIT(6)
35 #define CHRG_STAT_PMIC_OTP		BIT(7)
36 
37 #define VBUS_ISPOUT_CUR_LIM_MASK	0x03
38 #define VBUS_ISPOUT_CUR_LIM_BIT_POS	0
39 #define VBUS_ISPOUT_CUR_LIM_900MA	0x0	/* 900mA */
40 #define VBUS_ISPOUT_CUR_LIM_1500MA	0x1	/* 1500mA */
41 #define VBUS_ISPOUT_CUR_LIM_2000MA	0x2	/* 2000mA */
42 #define VBUS_ISPOUT_CUR_NO_LIM		0x3	/* 2500mA */
43 #define VBUS_ISPOUT_VHOLD_SET_MASK	0x31
44 #define VBUS_ISPOUT_VHOLD_SET_BIT_POS	0x3
45 #define VBUS_ISPOUT_VHOLD_SET_OFFSET	4000	/* 4000mV */
46 #define VBUS_ISPOUT_VHOLD_SET_LSB_RES	100	/* 100mV */
47 #define VBUS_ISPOUT_VHOLD_SET_4300MV	0x3	/* 4300mV */
48 #define VBUS_ISPOUT_VBUS_PATH_DIS	BIT(7)
49 
50 #define CHRG_CCCV_CC_MASK		0xf		/* 4 bits */
51 #define CHRG_CCCV_CC_BIT_POS		0
52 #define CHRG_CCCV_CC_OFFSET		200		/* 200mA */
53 #define CHRG_CCCV_CC_LSB_RES		200		/* 200mA */
54 #define CHRG_CCCV_ITERM_20P		BIT(4)		/* 20% of CC */
55 #define CHRG_CCCV_CV_MASK		0x60		/* 2 bits */
56 #define CHRG_CCCV_CV_BIT_POS		5
57 #define CHRG_CCCV_CV_4100MV		0x0		/* 4.10V */
58 #define CHRG_CCCV_CV_4150MV		0x1		/* 4.15V */
59 #define CHRG_CCCV_CV_4200MV		0x2		/* 4.20V */
60 #define CHRG_CCCV_CV_4350MV		0x3		/* 4.35V */
61 #define CHRG_CCCV_CHG_EN		BIT(7)
62 
63 #define CNTL2_CC_TIMEOUT_MASK		0x3	/* 2 bits */
64 #define CNTL2_CC_TIMEOUT_OFFSET		6	/* 6 Hrs */
65 #define CNTL2_CC_TIMEOUT_LSB_RES	2	/* 2 Hrs */
66 #define CNTL2_CC_TIMEOUT_12HRS		0x3	/* 12 Hrs */
67 #define CNTL2_CHGLED_TYPEB		BIT(4)
68 #define CNTL2_CHG_OUT_TURNON		BIT(5)
69 #define CNTL2_PC_TIMEOUT_MASK		0xC0
70 #define CNTL2_PC_TIMEOUT_OFFSET		40	/* 40 mins */
71 #define CNTL2_PC_TIMEOUT_LSB_RES	10	/* 10 mins */
72 #define CNTL2_PC_TIMEOUT_70MINS		0x3
73 
74 #define CHRG_ILIM_TEMP_LOOP_EN		BIT(3)
75 #define CHRG_VBUS_ILIM_MASK		0xf0
76 #define CHRG_VBUS_ILIM_BIT_POS		4
77 #define CHRG_VBUS_ILIM_100MA		0x0	/* 100mA */
78 #define CHRG_VBUS_ILIM_500MA		0x1	/* 500mA */
79 #define CHRG_VBUS_ILIM_900MA		0x2	/* 900mA */
80 #define CHRG_VBUS_ILIM_1500MA		0x3	/* 1500mA */
81 #define CHRG_VBUS_ILIM_2000MA		0x4	/* 2000mA */
82 #define CHRG_VBUS_ILIM_2500MA		0x5	/* 2500mA */
83 #define CHRG_VBUS_ILIM_3000MA		0x6	/* 3000mA */
84 #define CHRG_VBUS_ILIM_3500MA		0x7	/* 3500mA */
85 #define CHRG_VBUS_ILIM_4000MA		0x8	/* 4000mA */
86 
87 #define CHRG_VLTFC_0C			0xA5	/* 0 DegC */
88 #define CHRG_VHTFC_45C			0x1F	/* 45 DegC */
89 
90 #define FG_CNTL_OCV_ADJ_EN		BIT(3)
91 
92 #define CV_4100MV			4100	/* 4100mV */
93 #define CV_4150MV			4150	/* 4150mV */
94 #define CV_4200MV			4200	/* 4200mV */
95 #define CV_4350MV			4350	/* 4350mV */
96 
97 #define AXP288_EXTCON_DEV_NAME		"axp288_extcon"
98 #define USB_HOST_EXTCON_HID		"INT3496"
99 #define USB_HOST_EXTCON_NAME		"INT3496:00"
100 
101 enum {
102 	VBUS_OV_IRQ = 0,
103 	CHARGE_DONE_IRQ,
104 	CHARGE_CHARGING_IRQ,
105 	BAT_SAFE_QUIT_IRQ,
106 	BAT_SAFE_ENTER_IRQ,
107 	QCBTU_IRQ,
108 	CBTU_IRQ,
109 	QCBTO_IRQ,
110 	CBTO_IRQ,
111 	CHRG_INTR_END,
112 };
113 
114 struct axp288_chrg_info {
115 	struct platform_device *pdev;
116 	struct regmap *regmap;
117 	struct regmap_irq_chip_data *regmap_irqc;
118 	int irq[CHRG_INTR_END];
119 	struct power_supply *psy_usb;
120 
121 	/* OTG/Host mode */
122 	struct {
123 		struct work_struct work;
124 		struct extcon_dev *cable;
125 		struct notifier_block id_nb;
126 		bool id_short;
127 	} otg;
128 
129 	/* SDP/CDP/DCP USB charging cable notifications */
130 	struct {
131 		struct extcon_dev *edev;
132 		struct notifier_block nb;
133 		struct work_struct work;
134 	} cable;
135 
136 	int cc;
137 	int cv;
138 	int max_cc;
139 	int max_cv;
140 };
141 
142 static inline int axp288_charger_set_cc(struct axp288_chrg_info *info, int cc)
143 {
144 	u8 reg_val;
145 	int ret;
146 
147 	if (cc < CHRG_CCCV_CC_OFFSET)
148 		cc = CHRG_CCCV_CC_OFFSET;
149 	else if (cc > info->max_cc)
150 		cc = info->max_cc;
151 
152 	reg_val = (cc - CHRG_CCCV_CC_OFFSET) / CHRG_CCCV_CC_LSB_RES;
153 	cc = (reg_val * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET;
154 	reg_val = reg_val << CHRG_CCCV_CC_BIT_POS;
155 
156 	ret = regmap_update_bits(info->regmap,
157 				AXP20X_CHRG_CTRL1,
158 				CHRG_CCCV_CC_MASK, reg_val);
159 	if (ret >= 0)
160 		info->cc = cc;
161 
162 	return ret;
163 }
164 
165 static inline int axp288_charger_set_cv(struct axp288_chrg_info *info, int cv)
166 {
167 	u8 reg_val;
168 	int ret;
169 
170 	if (cv <= CV_4100MV) {
171 		reg_val = CHRG_CCCV_CV_4100MV;
172 		cv = CV_4100MV;
173 	} else if (cv <= CV_4150MV) {
174 		reg_val = CHRG_CCCV_CV_4150MV;
175 		cv = CV_4150MV;
176 	} else if (cv <= CV_4200MV) {
177 		reg_val = CHRG_CCCV_CV_4200MV;
178 		cv = CV_4200MV;
179 	} else {
180 		reg_val = CHRG_CCCV_CV_4350MV;
181 		cv = CV_4350MV;
182 	}
183 
184 	reg_val = reg_val << CHRG_CCCV_CV_BIT_POS;
185 
186 	ret = regmap_update_bits(info->regmap,
187 				AXP20X_CHRG_CTRL1,
188 				CHRG_CCCV_CV_MASK, reg_val);
189 
190 	if (ret >= 0)
191 		info->cv = cv;
192 
193 	return ret;
194 }
195 
196 static int axp288_charger_get_vbus_inlmt(struct axp288_chrg_info *info)
197 {
198 	unsigned int val;
199 	int ret;
200 
201 	ret = regmap_read(info->regmap, AXP20X_CHRG_BAK_CTRL, &val);
202 	if (ret < 0)
203 		return ret;
204 
205 	val >>= CHRG_VBUS_ILIM_BIT_POS;
206 	switch (val) {
207 	case CHRG_VBUS_ILIM_100MA:
208 		return 100000;
209 	case CHRG_VBUS_ILIM_500MA:
210 		return 500000;
211 	case CHRG_VBUS_ILIM_900MA:
212 		return 900000;
213 	case CHRG_VBUS_ILIM_1500MA:
214 		return 1500000;
215 	case CHRG_VBUS_ILIM_2000MA:
216 		return 2000000;
217 	case CHRG_VBUS_ILIM_2500MA:
218 		return 2500000;
219 	case CHRG_VBUS_ILIM_3000MA:
220 		return 3000000;
221 	case CHRG_VBUS_ILIM_3500MA:
222 		return 3500000;
223 	default:
224 		/* All b1xxx values map to 4000 mA */
225 		return 4000000;
226 	}
227 }
228 
229 static inline int axp288_charger_set_vbus_inlmt(struct axp288_chrg_info *info,
230 					   int inlmt)
231 {
232 	int ret;
233 	u8 reg_val;
234 
235 	if (inlmt >= 4000000)
236 		reg_val = CHRG_VBUS_ILIM_4000MA << CHRG_VBUS_ILIM_BIT_POS;
237 	else if (inlmt >= 3500000)
238 		reg_val = CHRG_VBUS_ILIM_3500MA << CHRG_VBUS_ILIM_BIT_POS;
239 	else if (inlmt >= 3000000)
240 		reg_val = CHRG_VBUS_ILIM_3000MA << CHRG_VBUS_ILIM_BIT_POS;
241 	else if (inlmt >= 2500000)
242 		reg_val = CHRG_VBUS_ILIM_2500MA << CHRG_VBUS_ILIM_BIT_POS;
243 	else if (inlmt >= 2000000)
244 		reg_val = CHRG_VBUS_ILIM_2000MA << CHRG_VBUS_ILIM_BIT_POS;
245 	else if (inlmt >= 1500000)
246 		reg_val = CHRG_VBUS_ILIM_1500MA << CHRG_VBUS_ILIM_BIT_POS;
247 	else if (inlmt >= 900000)
248 		reg_val = CHRG_VBUS_ILIM_900MA << CHRG_VBUS_ILIM_BIT_POS;
249 	else if (inlmt >= 500000)
250 		reg_val = CHRG_VBUS_ILIM_500MA << CHRG_VBUS_ILIM_BIT_POS;
251 	else
252 		reg_val = CHRG_VBUS_ILIM_100MA << CHRG_VBUS_ILIM_BIT_POS;
253 
254 	ret = regmap_update_bits(info->regmap, AXP20X_CHRG_BAK_CTRL,
255 				 CHRG_VBUS_ILIM_MASK, reg_val);
256 	if (ret < 0)
257 		dev_err(&info->pdev->dev, "charger BAK control %d\n", ret);
258 
259 	return ret;
260 }
261 
262 static int axp288_charger_vbus_path_select(struct axp288_chrg_info *info,
263 								bool enable)
264 {
265 	int ret;
266 
267 	if (enable)
268 		ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT,
269 					VBUS_ISPOUT_VBUS_PATH_DIS, 0);
270 	else
271 		ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT,
272 			VBUS_ISPOUT_VBUS_PATH_DIS, VBUS_ISPOUT_VBUS_PATH_DIS);
273 
274 	if (ret < 0)
275 		dev_err(&info->pdev->dev, "axp288 vbus path select %d\n", ret);
276 
277 	return ret;
278 }
279 
280 static int axp288_charger_enable_charger(struct axp288_chrg_info *info,
281 								bool enable)
282 {
283 	int ret;
284 
285 	if (enable)
286 		ret = regmap_update_bits(info->regmap, AXP20X_CHRG_CTRL1,
287 				CHRG_CCCV_CHG_EN, CHRG_CCCV_CHG_EN);
288 	else
289 		ret = regmap_update_bits(info->regmap, AXP20X_CHRG_CTRL1,
290 				CHRG_CCCV_CHG_EN, 0);
291 	if (ret < 0)
292 		dev_err(&info->pdev->dev, "axp288 enable charger %d\n", ret);
293 
294 	return ret;
295 }
296 
297 static int axp288_charger_is_present(struct axp288_chrg_info *info)
298 {
299 	int ret, present = 0;
300 	unsigned int val;
301 
302 	ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val);
303 	if (ret < 0)
304 		return ret;
305 
306 	if (val & PS_STAT_VBUS_PRESENT)
307 		present = 1;
308 	return present;
309 }
310 
311 static int axp288_charger_is_online(struct axp288_chrg_info *info)
312 {
313 	int ret, online = 0;
314 	unsigned int val;
315 
316 	ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val);
317 	if (ret < 0)
318 		return ret;
319 
320 	if (val & PS_STAT_VBUS_VALID)
321 		online = 1;
322 	return online;
323 }
324 
325 static int axp288_get_charger_health(struct axp288_chrg_info *info)
326 {
327 	int ret, pwr_stat, chrg_stat;
328 	int health = POWER_SUPPLY_HEALTH_UNKNOWN;
329 	unsigned int val;
330 
331 	ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val);
332 	if ((ret < 0) || !(val & PS_STAT_VBUS_PRESENT))
333 		goto health_read_fail;
334 	else
335 		pwr_stat = val;
336 
337 	ret = regmap_read(info->regmap, AXP20X_PWR_OP_MODE, &val);
338 	if (ret < 0)
339 		goto health_read_fail;
340 	else
341 		chrg_stat = val;
342 
343 	if (!(pwr_stat & PS_STAT_VBUS_VALID))
344 		health = POWER_SUPPLY_HEALTH_DEAD;
345 	else if (chrg_stat & CHRG_STAT_PMIC_OTP)
346 		health = POWER_SUPPLY_HEALTH_OVERHEAT;
347 	else if (chrg_stat & CHRG_STAT_BAT_SAFE_MODE)
348 		health = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
349 	else
350 		health = POWER_SUPPLY_HEALTH_GOOD;
351 
352 health_read_fail:
353 	return health;
354 }
355 
356 static int axp288_charger_usb_set_property(struct power_supply *psy,
357 				    enum power_supply_property psp,
358 				    const union power_supply_propval *val)
359 {
360 	struct axp288_chrg_info *info = power_supply_get_drvdata(psy);
361 	int ret = 0;
362 	int scaled_val;
363 
364 	switch (psp) {
365 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
366 		scaled_val = min(val->intval, info->max_cc);
367 		scaled_val = DIV_ROUND_CLOSEST(scaled_val, 1000);
368 		ret = axp288_charger_set_cc(info, scaled_val);
369 		if (ret < 0)
370 			dev_warn(&info->pdev->dev, "set charge current failed\n");
371 		break;
372 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
373 		scaled_val = min(val->intval, info->max_cv);
374 		scaled_val = DIV_ROUND_CLOSEST(scaled_val, 1000);
375 		ret = axp288_charger_set_cv(info, scaled_val);
376 		if (ret < 0)
377 			dev_warn(&info->pdev->dev, "set charge voltage failed\n");
378 		break;
379 	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
380 		ret = axp288_charger_set_vbus_inlmt(info, val->intval);
381 		if (ret < 0)
382 			dev_warn(&info->pdev->dev, "set input current limit failed\n");
383 		break;
384 	default:
385 		ret = -EINVAL;
386 	}
387 
388 	return ret;
389 }
390 
391 static int axp288_charger_usb_get_property(struct power_supply *psy,
392 				    enum power_supply_property psp,
393 				    union power_supply_propval *val)
394 {
395 	struct axp288_chrg_info *info = power_supply_get_drvdata(psy);
396 	int ret;
397 
398 	switch (psp) {
399 	case POWER_SUPPLY_PROP_PRESENT:
400 		/* Check for OTG case first */
401 		if (info->otg.id_short) {
402 			val->intval = 0;
403 			break;
404 		}
405 		ret = axp288_charger_is_present(info);
406 		if (ret < 0)
407 			return ret;
408 		val->intval = ret;
409 		break;
410 	case POWER_SUPPLY_PROP_ONLINE:
411 		/* Check for OTG case first */
412 		if (info->otg.id_short) {
413 			val->intval = 0;
414 			break;
415 		}
416 		ret = axp288_charger_is_online(info);
417 		if (ret < 0)
418 			return ret;
419 		val->intval = ret;
420 		break;
421 	case POWER_SUPPLY_PROP_HEALTH:
422 		val->intval = axp288_get_charger_health(info);
423 		break;
424 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
425 		val->intval = info->cc * 1000;
426 		break;
427 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
428 		val->intval = info->max_cc * 1000;
429 		break;
430 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
431 		val->intval = info->cv * 1000;
432 		break;
433 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
434 		val->intval = info->max_cv * 1000;
435 		break;
436 	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
437 		ret = axp288_charger_get_vbus_inlmt(info);
438 		if (ret < 0)
439 			return ret;
440 		val->intval = ret;
441 		break;
442 	default:
443 		return -EINVAL;
444 	}
445 
446 	return 0;
447 }
448 
449 static int axp288_charger_property_is_writeable(struct power_supply *psy,
450 		enum power_supply_property psp)
451 {
452 	int ret;
453 
454 	switch (psp) {
455 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
456 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
457 	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
458 		ret = 1;
459 		break;
460 	default:
461 		ret = 0;
462 	}
463 
464 	return ret;
465 }
466 
467 static enum power_supply_property axp288_usb_props[] = {
468 	POWER_SUPPLY_PROP_PRESENT,
469 	POWER_SUPPLY_PROP_ONLINE,
470 	POWER_SUPPLY_PROP_TYPE,
471 	POWER_SUPPLY_PROP_HEALTH,
472 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
473 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
474 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
475 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
476 	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
477 };
478 
479 static const struct power_supply_desc axp288_charger_desc = {
480 	.name			= "axp288_charger",
481 	.type			= POWER_SUPPLY_TYPE_USB,
482 	.properties		= axp288_usb_props,
483 	.num_properties		= ARRAY_SIZE(axp288_usb_props),
484 	.get_property		= axp288_charger_usb_get_property,
485 	.set_property		= axp288_charger_usb_set_property,
486 	.property_is_writeable	= axp288_charger_property_is_writeable,
487 };
488 
489 static irqreturn_t axp288_charger_irq_thread_handler(int irq, void *dev)
490 {
491 	struct axp288_chrg_info *info = dev;
492 	int i;
493 
494 	for (i = 0; i < CHRG_INTR_END; i++) {
495 		if (info->irq[i] == irq)
496 			break;
497 	}
498 
499 	if (i >= CHRG_INTR_END) {
500 		dev_warn(&info->pdev->dev, "spurious interrupt!!\n");
501 		return IRQ_NONE;
502 	}
503 
504 	switch (i) {
505 	case VBUS_OV_IRQ:
506 		dev_dbg(&info->pdev->dev, "VBUS Over Voltage INTR\n");
507 		break;
508 	case CHARGE_DONE_IRQ:
509 		dev_dbg(&info->pdev->dev, "Charging Done INTR\n");
510 		break;
511 	case CHARGE_CHARGING_IRQ:
512 		dev_dbg(&info->pdev->dev, "Start Charging IRQ\n");
513 		break;
514 	case BAT_SAFE_QUIT_IRQ:
515 		dev_dbg(&info->pdev->dev,
516 			"Quit Safe Mode(restart timer) Charging IRQ\n");
517 		break;
518 	case BAT_SAFE_ENTER_IRQ:
519 		dev_dbg(&info->pdev->dev,
520 			"Enter Safe Mode(timer expire) Charging IRQ\n");
521 		break;
522 	case QCBTU_IRQ:
523 		dev_dbg(&info->pdev->dev,
524 			"Quit Battery Under Temperature(CHRG) INTR\n");
525 		break;
526 	case CBTU_IRQ:
527 		dev_dbg(&info->pdev->dev,
528 			"Hit Battery Under Temperature(CHRG) INTR\n");
529 		break;
530 	case QCBTO_IRQ:
531 		dev_dbg(&info->pdev->dev,
532 			"Quit Battery Over Temperature(CHRG) INTR\n");
533 		break;
534 	case CBTO_IRQ:
535 		dev_dbg(&info->pdev->dev,
536 			"Hit Battery Over Temperature(CHRG) INTR\n");
537 		break;
538 	default:
539 		dev_warn(&info->pdev->dev, "Spurious Interrupt!!!\n");
540 		goto out;
541 	}
542 
543 	power_supply_changed(info->psy_usb);
544 out:
545 	return IRQ_HANDLED;
546 }
547 
548 static void axp288_charger_extcon_evt_worker(struct work_struct *work)
549 {
550 	struct axp288_chrg_info *info =
551 	    container_of(work, struct axp288_chrg_info, cable.work);
552 	int ret, current_limit;
553 	struct extcon_dev *edev = info->cable.edev;
554 	unsigned int val;
555 
556 	ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val);
557 	if (ret < 0) {
558 		dev_err(&info->pdev->dev, "Error reading status (%d)\n", ret);
559 		return;
560 	}
561 
562 	/* Offline? Disable charging and bail */
563 	if (!(val & PS_STAT_VBUS_VALID)) {
564 		dev_dbg(&info->pdev->dev, "USB charger disconnected\n");
565 		axp288_charger_enable_charger(info, false);
566 		power_supply_changed(info->psy_usb);
567 		return;
568 	}
569 
570 	/* Determine cable/charger type */
571 	if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {
572 		dev_dbg(&info->pdev->dev, "USB SDP charger is connected\n");
573 		current_limit = 500000;
574 	} else if (extcon_get_state(edev, EXTCON_CHG_USB_CDP) > 0) {
575 		dev_dbg(&info->pdev->dev, "USB CDP charger is connected\n");
576 		current_limit = 1500000;
577 	} else if (extcon_get_state(edev, EXTCON_CHG_USB_DCP) > 0) {
578 		dev_dbg(&info->pdev->dev, "USB DCP charger is connected\n");
579 		current_limit = 2000000;
580 	} else {
581 		/* Charger type detection still in progress, bail. */
582 		return;
583 	}
584 
585 	/* Set vbus current limit first, then enable charger */
586 	ret = axp288_charger_set_vbus_inlmt(info, current_limit);
587 	if (ret == 0)
588 		axp288_charger_enable_charger(info, true);
589 	else
590 		dev_err(&info->pdev->dev,
591 			"error setting current limit (%d)\n", ret);
592 
593 	power_supply_changed(info->psy_usb);
594 }
595 
596 static int axp288_charger_handle_cable_evt(struct notifier_block *nb,
597 					   unsigned long event, void *param)
598 {
599 	struct axp288_chrg_info *info =
600 		container_of(nb, struct axp288_chrg_info, cable.nb);
601 	schedule_work(&info->cable.work);
602 	return NOTIFY_OK;
603 }
604 
605 static void axp288_charger_otg_evt_worker(struct work_struct *work)
606 {
607 	struct axp288_chrg_info *info =
608 	    container_of(work, struct axp288_chrg_info, otg.work);
609 	struct extcon_dev *edev = info->otg.cable;
610 	int ret, usb_host = extcon_get_state(edev, EXTCON_USB_HOST);
611 
612 	dev_dbg(&info->pdev->dev, "external connector USB-Host is %s\n",
613 				usb_host ? "attached" : "detached");
614 
615 	/*
616 	 * Set usb_id_short flag to avoid running charger detection logic
617 	 * in case usb host.
618 	 */
619 	info->otg.id_short = usb_host;
620 
621 	/* Disable VBUS path before enabling the 5V boost */
622 	ret = axp288_charger_vbus_path_select(info, !info->otg.id_short);
623 	if (ret < 0)
624 		dev_warn(&info->pdev->dev, "vbus path disable failed\n");
625 }
626 
627 static int axp288_charger_handle_otg_evt(struct notifier_block *nb,
628 				   unsigned long event, void *param)
629 {
630 	struct axp288_chrg_info *info =
631 	    container_of(nb, struct axp288_chrg_info, otg.id_nb);
632 
633 	schedule_work(&info->otg.work);
634 
635 	return NOTIFY_OK;
636 }
637 
638 static int charger_init_hw_regs(struct axp288_chrg_info *info)
639 {
640 	int ret, cc, cv;
641 	unsigned int val;
642 
643 	/* Program temperature thresholds */
644 	ret = regmap_write(info->regmap, AXP20X_V_LTF_CHRG, CHRG_VLTFC_0C);
645 	if (ret < 0) {
646 		dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
647 							AXP20X_V_LTF_CHRG, ret);
648 		return ret;
649 	}
650 
651 	ret = regmap_write(info->regmap, AXP20X_V_HTF_CHRG, CHRG_VHTFC_45C);
652 	if (ret < 0) {
653 		dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
654 							AXP20X_V_HTF_CHRG, ret);
655 		return ret;
656 	}
657 
658 	/* Do not turn-off charger o/p after charge cycle ends */
659 	ret = regmap_update_bits(info->regmap,
660 				AXP20X_CHRG_CTRL2,
661 				CNTL2_CHG_OUT_TURNON, CNTL2_CHG_OUT_TURNON);
662 	if (ret < 0) {
663 		dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
664 						AXP20X_CHRG_CTRL2, ret);
665 		return ret;
666 	}
667 
668 	/* Setup ending condition for charging to be 10% of I(chrg) */
669 	ret = regmap_update_bits(info->regmap,
670 				AXP20X_CHRG_CTRL1,
671 				CHRG_CCCV_ITERM_20P, 0);
672 	if (ret < 0) {
673 		dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
674 						AXP20X_CHRG_CTRL1, ret);
675 		return ret;
676 	}
677 
678 	/* Disable OCV-SOC curve calibration */
679 	ret = regmap_update_bits(info->regmap,
680 				AXP20X_CC_CTRL,
681 				FG_CNTL_OCV_ADJ_EN, 0);
682 	if (ret < 0) {
683 		dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
684 						AXP20X_CC_CTRL, ret);
685 		return ret;
686 	}
687 
688 	/* Read current charge voltage and current limit */
689 	ret = regmap_read(info->regmap, AXP20X_CHRG_CTRL1, &val);
690 	if (ret < 0) {
691 		dev_err(&info->pdev->dev, "register(%x) read error(%d)\n",
692 			AXP20X_CHRG_CTRL1, ret);
693 		return ret;
694 	}
695 
696 	/* Determine charge voltage */
697 	cv = (val & CHRG_CCCV_CV_MASK) >> CHRG_CCCV_CV_BIT_POS;
698 	switch (cv) {
699 	case CHRG_CCCV_CV_4100MV:
700 		info->cv = CV_4100MV;
701 		break;
702 	case CHRG_CCCV_CV_4150MV:
703 		info->cv = CV_4150MV;
704 		break;
705 	case CHRG_CCCV_CV_4200MV:
706 		info->cv = CV_4200MV;
707 		break;
708 	case CHRG_CCCV_CV_4350MV:
709 		info->cv = CV_4350MV;
710 		break;
711 	}
712 
713 	/* Determine charge current limit */
714 	cc = (val & CHRG_CCCV_CC_MASK) >> CHRG_CCCV_CC_BIT_POS;
715 	cc = (cc * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET;
716 	info->cc = cc;
717 
718 	/*
719 	 * Do not allow the user to configure higher settings then those
720 	 * set by the firmware
721 	 */
722 	info->max_cv = info->cv;
723 	info->max_cc = info->cc;
724 
725 	return 0;
726 }
727 
728 static void axp288_charger_cancel_work(void *data)
729 {
730 	struct axp288_chrg_info *info = data;
731 
732 	cancel_work_sync(&info->otg.work);
733 	cancel_work_sync(&info->cable.work);
734 }
735 
736 static int axp288_charger_probe(struct platform_device *pdev)
737 {
738 	int ret, i, pirq;
739 	struct axp288_chrg_info *info;
740 	struct device *dev = &pdev->dev;
741 	struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
742 	struct power_supply_config charger_cfg = {};
743 	unsigned int val;
744 
745 	/*
746 	 * On some devices the fuelgauge and charger parts of the axp288 are
747 	 * not used, check that the fuelgauge is enabled (CC_CTRL != 0).
748 	 */
749 	ret = regmap_read(axp20x->regmap, AXP20X_CC_CTRL, &val);
750 	if (ret < 0)
751 		return ret;
752 	if (val == 0)
753 		return -ENODEV;
754 
755 	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
756 	if (!info)
757 		return -ENOMEM;
758 
759 	info->pdev = pdev;
760 	info->regmap = axp20x->regmap;
761 	info->regmap_irqc = axp20x->regmap_irqc;
762 
763 	info->cable.edev = extcon_get_extcon_dev(AXP288_EXTCON_DEV_NAME);
764 	if (info->cable.edev == NULL) {
765 		dev_dbg(&pdev->dev, "%s is not ready, probe deferred\n",
766 			AXP288_EXTCON_DEV_NAME);
767 		return -EPROBE_DEFER;
768 	}
769 
770 	if (acpi_dev_present(USB_HOST_EXTCON_HID, NULL, -1)) {
771 		info->otg.cable = extcon_get_extcon_dev(USB_HOST_EXTCON_NAME);
772 		if (info->otg.cable == NULL) {
773 			dev_dbg(dev, "EXTCON_USB_HOST is not ready, probe deferred\n");
774 			return -EPROBE_DEFER;
775 		}
776 		dev_info(&pdev->dev,
777 			 "Using " USB_HOST_EXTCON_HID " extcon for usb-id\n");
778 	}
779 
780 	platform_set_drvdata(pdev, info);
781 
782 	ret = charger_init_hw_regs(info);
783 	if (ret)
784 		return ret;
785 
786 	/* Register with power supply class */
787 	charger_cfg.drv_data = info;
788 	info->psy_usb = devm_power_supply_register(dev, &axp288_charger_desc,
789 						   &charger_cfg);
790 	if (IS_ERR(info->psy_usb)) {
791 		ret = PTR_ERR(info->psy_usb);
792 		dev_err(dev, "failed to register power supply: %d\n", ret);
793 		return ret;
794 	}
795 
796 	/* Cancel our work on cleanup, register this before the notifiers */
797 	ret = devm_add_action(dev, axp288_charger_cancel_work, info);
798 	if (ret)
799 		return ret;
800 
801 	/* Register for extcon notification */
802 	INIT_WORK(&info->cable.work, axp288_charger_extcon_evt_worker);
803 	info->cable.nb.notifier_call = axp288_charger_handle_cable_evt;
804 	ret = devm_extcon_register_notifier_all(dev, info->cable.edev,
805 						&info->cable.nb);
806 	if (ret) {
807 		dev_err(dev, "failed to register cable extcon notifier\n");
808 		return ret;
809 	}
810 	schedule_work(&info->cable.work);
811 
812 	/* Register for OTG notification */
813 	INIT_WORK(&info->otg.work, axp288_charger_otg_evt_worker);
814 	info->otg.id_nb.notifier_call = axp288_charger_handle_otg_evt;
815 	if (info->otg.cable) {
816 		ret = devm_extcon_register_notifier(&pdev->dev, info->otg.cable,
817 					EXTCON_USB_HOST, &info->otg.id_nb);
818 		if (ret) {
819 			dev_err(dev, "failed to register EXTCON_USB_HOST notifier\n");
820 			return ret;
821 		}
822 		schedule_work(&info->otg.work);
823 	}
824 
825 	/* Register charger interrupts */
826 	for (i = 0; i < CHRG_INTR_END; i++) {
827 		pirq = platform_get_irq(info->pdev, i);
828 		if (pirq < 0) {
829 			dev_err(&pdev->dev, "Failed to get IRQ: %d\n", pirq);
830 			return pirq;
831 		}
832 		info->irq[i] = regmap_irq_get_virq(info->regmap_irqc, pirq);
833 		if (info->irq[i] < 0) {
834 			dev_warn(&info->pdev->dev,
835 				"failed to get virtual interrupt=%d\n", pirq);
836 			return info->irq[i];
837 		}
838 		ret = devm_request_threaded_irq(&info->pdev->dev, info->irq[i],
839 					NULL, axp288_charger_irq_thread_handler,
840 					IRQF_ONESHOT, info->pdev->name, info);
841 		if (ret) {
842 			dev_err(&pdev->dev, "failed to request interrupt=%d\n",
843 								info->irq[i]);
844 			return ret;
845 		}
846 	}
847 
848 	return 0;
849 }
850 
851 static const struct platform_device_id axp288_charger_id_table[] = {
852 	{ .name = "axp288_charger" },
853 	{},
854 };
855 MODULE_DEVICE_TABLE(platform, axp288_charger_id_table);
856 
857 static struct platform_driver axp288_charger_driver = {
858 	.probe = axp288_charger_probe,
859 	.id_table = axp288_charger_id_table,
860 	.driver = {
861 		.name = "axp288_charger",
862 	},
863 };
864 
865 module_platform_driver(axp288_charger_driver);
866 
867 MODULE_AUTHOR("Ramakrishna Pallala <ramakrishna.pallala@intel.com>");
868 MODULE_DESCRIPTION("X-power AXP288 Charger Driver");
869 MODULE_LICENSE("GPL v2");
870