dm thin metadata: fix __udivdi3 undefined on 32-bit
[linux/fpc-iii.git] / drivers / power / axp288_charger.c
blobe4d569f57acc90d1dd02840b5f2f9f4d0e4ba152
1 /*
2 * axp288_charger.c - X-power AXP288 PMIC Charger driver
4 * Copyright (C) 2014 Intel Corporation
5 * Author: Ramakrishna Pallala <ramakrishna.pallala@intel.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
17 #include <linux/module.h>
18 #include <linux/device.h>
19 #include <linux/regmap.h>
20 #include <linux/workqueue.h>
21 #include <linux/delay.h>
22 #include <linux/platform_device.h>
23 #include <linux/usb/otg.h>
24 #include <linux/notifier.h>
25 #include <linux/power_supply.h>
26 #include <linux/notifier.h>
27 #include <linux/property.h>
28 #include <linux/mfd/axp20x.h>
29 #include <linux/extcon.h>
31 #define PS_STAT_VBUS_TRIGGER (1 << 0)
32 #define PS_STAT_BAT_CHRG_DIR (1 << 2)
33 #define PS_STAT_VBAT_ABOVE_VHOLD (1 << 3)
34 #define PS_STAT_VBUS_VALID (1 << 4)
35 #define PS_STAT_VBUS_PRESENT (1 << 5)
37 #define CHRG_STAT_BAT_SAFE_MODE (1 << 3)
38 #define CHRG_STAT_BAT_VALID (1 << 4)
39 #define CHRG_STAT_BAT_PRESENT (1 << 5)
40 #define CHRG_STAT_CHARGING (1 << 6)
41 #define CHRG_STAT_PMIC_OTP (1 << 7)
43 #define VBUS_ISPOUT_CUR_LIM_MASK 0x03
44 #define VBUS_ISPOUT_CUR_LIM_BIT_POS 0
45 #define VBUS_ISPOUT_CUR_LIM_900MA 0x0 /* 900mA */
46 #define VBUS_ISPOUT_CUR_LIM_1500MA 0x1 /* 1500mA */
47 #define VBUS_ISPOUT_CUR_LIM_2000MA 0x2 /* 2000mA */
48 #define VBUS_ISPOUT_CUR_NO_LIM 0x3 /* 2500mA */
49 #define VBUS_ISPOUT_VHOLD_SET_MASK 0x31
50 #define VBUS_ISPOUT_VHOLD_SET_BIT_POS 0x3
51 #define VBUS_ISPOUT_VHOLD_SET_OFFSET 4000 /* 4000mV */
52 #define VBUS_ISPOUT_VHOLD_SET_LSB_RES 100 /* 100mV */
53 #define VBUS_ISPOUT_VHOLD_SET_4300MV 0x3 /* 4300mV */
54 #define VBUS_ISPOUT_VBUS_PATH_DIS (1 << 7)
56 #define CHRG_CCCV_CC_MASK 0xf /* 4 bits */
57 #define CHRG_CCCV_CC_BIT_POS 0
58 #define CHRG_CCCV_CC_OFFSET 200 /* 200mA */
59 #define CHRG_CCCV_CC_LSB_RES 200 /* 200mA */
60 #define CHRG_CCCV_ITERM_20P (1 << 4) /* 20% of CC */
61 #define CHRG_CCCV_CV_MASK 0x60 /* 2 bits */
62 #define CHRG_CCCV_CV_BIT_POS 5
63 #define CHRG_CCCV_CV_4100MV 0x0 /* 4.10V */
64 #define CHRG_CCCV_CV_4150MV 0x1 /* 4.15V */
65 #define CHRG_CCCV_CV_4200MV 0x2 /* 4.20V */
66 #define CHRG_CCCV_CV_4350MV 0x3 /* 4.35V */
67 #define CHRG_CCCV_CHG_EN (1 << 7)
69 #define CNTL2_CC_TIMEOUT_MASK 0x3 /* 2 bits */
70 #define CNTL2_CC_TIMEOUT_OFFSET 6 /* 6 Hrs */
71 #define CNTL2_CC_TIMEOUT_LSB_RES 2 /* 2 Hrs */
72 #define CNTL2_CC_TIMEOUT_12HRS 0x3 /* 12 Hrs */
73 #define CNTL2_CHGLED_TYPEB (1 << 4)
74 #define CNTL2_CHG_OUT_TURNON (1 << 5)
75 #define CNTL2_PC_TIMEOUT_MASK 0xC0
76 #define CNTL2_PC_TIMEOUT_OFFSET 40 /* 40 mins */
77 #define CNTL2_PC_TIMEOUT_LSB_RES 10 /* 10 mins */
78 #define CNTL2_PC_TIMEOUT_70MINS 0x3
80 #define CHRG_ILIM_TEMP_LOOP_EN (1 << 3)
81 #define CHRG_VBUS_ILIM_MASK 0xf0
82 #define CHRG_VBUS_ILIM_BIT_POS 4
83 #define CHRG_VBUS_ILIM_100MA 0x0 /* 100mA */
84 #define CHRG_VBUS_ILIM_500MA 0x1 /* 500mA */
85 #define CHRG_VBUS_ILIM_900MA 0x2 /* 900mA */
86 #define CHRG_VBUS_ILIM_1500MA 0x3 /* 1500mA */
87 #define CHRG_VBUS_ILIM_2000MA 0x4 /* 2000mA */
88 #define CHRG_VBUS_ILIM_2500MA 0x5 /* 2500mA */
89 #define CHRG_VBUS_ILIM_3000MA 0x6 /* 3000mA */
91 #define CHRG_VLTFC_0C 0xA5 /* 0 DegC */
92 #define CHRG_VHTFC_45C 0x1F /* 45 DegC */
94 #define BAT_IRQ_CFG_CHRG_DONE (1 << 2)
95 #define BAT_IRQ_CFG_CHRG_START (1 << 3)
96 #define BAT_IRQ_CFG_BAT_SAFE_EXIT (1 << 4)
97 #define BAT_IRQ_CFG_BAT_SAFE_ENTER (1 << 5)
98 #define BAT_IRQ_CFG_BAT_DISCON (1 << 6)
99 #define BAT_IRQ_CFG_BAT_CONN (1 << 7)
100 #define BAT_IRQ_CFG_BAT_MASK 0xFC
102 #define TEMP_IRQ_CFG_QCBTU (1 << 4)
103 #define TEMP_IRQ_CFG_CBTU (1 << 5)
104 #define TEMP_IRQ_CFG_QCBTO (1 << 6)
105 #define TEMP_IRQ_CFG_CBTO (1 << 7)
106 #define TEMP_IRQ_CFG_MASK 0xF0
108 #define FG_CNTL_OCV_ADJ_EN (1 << 3)
110 #define CV_4100MV 4100 /* 4100mV */
111 #define CV_4150MV 4150 /* 4150mV */
112 #define CV_4200MV 4200 /* 4200mV */
113 #define CV_4350MV 4350 /* 4350mV */
115 #define CC_200MA 200 /* 200mA */
116 #define CC_600MA 600 /* 600mA */
117 #define CC_800MA 800 /* 800mA */
118 #define CC_1000MA 1000 /* 1000mA */
119 #define CC_1600MA 1600 /* 1600mA */
120 #define CC_2000MA 2000 /* 2000mA */
122 #define ILIM_100MA 100 /* 100mA */
123 #define ILIM_500MA 500 /* 500mA */
124 #define ILIM_900MA 900 /* 900mA */
125 #define ILIM_1500MA 1500 /* 1500mA */
126 #define ILIM_2000MA 2000 /* 2000mA */
127 #define ILIM_2500MA 2500 /* 2500mA */
128 #define ILIM_3000MA 3000 /* 3000mA */
130 #define AXP288_EXTCON_DEV_NAME "axp288_extcon"
132 #define AXP288_EXTCON_SLOW_CHARGER "SLOW-CHARGER"
133 #define AXP288_EXTCON_DOWNSTREAM_CHARGER "CHARGE-DOWNSTREAM"
134 #define AXP288_EXTCON_FAST_CHARGER "FAST-CHARGER"
136 enum {
137 VBUS_OV_IRQ = 0,
138 CHARGE_DONE_IRQ,
139 CHARGE_CHARGING_IRQ,
140 BAT_SAFE_QUIT_IRQ,
141 BAT_SAFE_ENTER_IRQ,
142 QCBTU_IRQ,
143 CBTU_IRQ,
144 QCBTO_IRQ,
145 CBTO_IRQ,
146 CHRG_INTR_END,
149 struct axp288_chrg_info {
150 struct platform_device *pdev;
151 struct axp20x_chrg_pdata *pdata;
152 struct regmap *regmap;
153 struct regmap_irq_chip_data *regmap_irqc;
154 int irq[CHRG_INTR_END];
155 struct power_supply *psy_usb;
156 struct mutex lock;
158 /* OTG/Host mode */
159 struct {
160 struct work_struct work;
161 struct extcon_specific_cable_nb cable;
162 struct notifier_block id_nb;
163 bool id_short;
164 } otg;
166 /* SDP/CDP/DCP USB charging cable notifications */
167 struct {
168 struct extcon_dev *edev;
169 bool connected;
170 enum power_supply_type chg_type;
171 struct notifier_block nb;
172 struct work_struct work;
173 } cable;
175 int health;
176 int inlmt;
177 int cc;
178 int cv;
179 int max_cc;
180 int max_cv;
181 bool online;
182 bool present;
183 bool enable_charger;
184 bool is_charger_enabled;
187 static inline int axp288_charger_set_cc(struct axp288_chrg_info *info, int cc)
189 u8 reg_val;
190 int ret;
192 if (cc < CHRG_CCCV_CC_OFFSET)
193 cc = CHRG_CCCV_CC_OFFSET;
194 else if (cc > info->max_cc)
195 cc = info->max_cc;
197 reg_val = (cc - CHRG_CCCV_CC_OFFSET) / CHRG_CCCV_CC_LSB_RES;
198 cc = (reg_val * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET;
199 reg_val = reg_val << CHRG_CCCV_CC_BIT_POS;
201 ret = regmap_update_bits(info->regmap,
202 AXP20X_CHRG_CTRL1,
203 CHRG_CCCV_CC_MASK, reg_val);
204 if (ret >= 0)
205 info->cc = cc;
207 return ret;
210 static inline int axp288_charger_set_cv(struct axp288_chrg_info *info, int cv)
212 u8 reg_val;
213 int ret;
215 if (cv <= CV_4100MV) {
216 reg_val = CHRG_CCCV_CV_4100MV;
217 cv = CV_4100MV;
218 } else if (cv <= CV_4150MV) {
219 reg_val = CHRG_CCCV_CV_4150MV;
220 cv = CV_4150MV;
221 } else if (cv <= CV_4200MV) {
222 reg_val = CHRG_CCCV_CV_4200MV;
223 cv = CV_4200MV;
224 } else {
225 reg_val = CHRG_CCCV_CV_4350MV;
226 cv = CV_4350MV;
229 reg_val = reg_val << CHRG_CCCV_CV_BIT_POS;
231 ret = regmap_update_bits(info->regmap,
232 AXP20X_CHRG_CTRL1,
233 CHRG_CCCV_CV_MASK, reg_val);
235 if (ret >= 0)
236 info->cv = cv;
238 return ret;
241 static inline int axp288_charger_set_vbus_inlmt(struct axp288_chrg_info *info,
242 int inlmt)
244 int ret;
245 unsigned int val;
246 u8 reg_val;
248 /* Read in limit register */
249 ret = regmap_read(info->regmap, AXP20X_CHRG_BAK_CTRL, &val);
250 if (ret < 0)
251 goto set_inlmt_fail;
253 if (inlmt <= ILIM_100MA) {
254 reg_val = CHRG_VBUS_ILIM_100MA;
255 inlmt = ILIM_100MA;
256 } else if (inlmt <= ILIM_500MA) {
257 reg_val = CHRG_VBUS_ILIM_500MA;
258 inlmt = ILIM_500MA;
259 } else if (inlmt <= ILIM_900MA) {
260 reg_val = CHRG_VBUS_ILIM_900MA;
261 inlmt = ILIM_900MA;
262 } else if (inlmt <= ILIM_1500MA) {
263 reg_val = CHRG_VBUS_ILIM_1500MA;
264 inlmt = ILIM_1500MA;
265 } else if (inlmt <= ILIM_2000MA) {
266 reg_val = CHRG_VBUS_ILIM_2000MA;
267 inlmt = ILIM_2000MA;
268 } else if (inlmt <= ILIM_2500MA) {
269 reg_val = CHRG_VBUS_ILIM_2500MA;
270 inlmt = ILIM_2500MA;
271 } else {
272 reg_val = CHRG_VBUS_ILIM_3000MA;
273 inlmt = ILIM_3000MA;
276 reg_val = (val & ~CHRG_VBUS_ILIM_MASK)
277 | (reg_val << CHRG_VBUS_ILIM_BIT_POS);
278 ret = regmap_write(info->regmap, AXP20X_CHRG_BAK_CTRL, reg_val);
279 if (ret >= 0)
280 info->inlmt = inlmt;
281 else
282 dev_err(&info->pdev->dev, "charger BAK control %d\n", ret);
285 set_inlmt_fail:
286 return ret;
289 static int axp288_charger_vbus_path_select(struct axp288_chrg_info *info,
290 bool enable)
292 int ret;
294 if (enable)
295 ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT,
296 VBUS_ISPOUT_VBUS_PATH_DIS, 0);
297 else
298 ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT,
299 VBUS_ISPOUT_VBUS_PATH_DIS, VBUS_ISPOUT_VBUS_PATH_DIS);
301 if (ret < 0)
302 dev_err(&info->pdev->dev, "axp288 vbus path select %d\n", ret);
305 return ret;
308 static int axp288_charger_enable_charger(struct axp288_chrg_info *info,
309 bool enable)
311 int ret;
313 if (enable)
314 ret = regmap_update_bits(info->regmap, AXP20X_CHRG_CTRL1,
315 CHRG_CCCV_CHG_EN, CHRG_CCCV_CHG_EN);
316 else
317 ret = regmap_update_bits(info->regmap, AXP20X_CHRG_CTRL1,
318 CHRG_CCCV_CHG_EN, 0);
319 if (ret < 0)
320 dev_err(&info->pdev->dev, "axp288 enable charger %d\n", ret);
321 else
322 info->is_charger_enabled = enable;
324 return ret;
327 static int axp288_charger_is_present(struct axp288_chrg_info *info)
329 int ret, present = 0;
330 unsigned int val;
332 ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val);
333 if (ret < 0)
334 return ret;
336 if (val & PS_STAT_VBUS_PRESENT)
337 present = 1;
338 return present;
341 static int axp288_charger_is_online(struct axp288_chrg_info *info)
343 int ret, online = 0;
344 unsigned int val;
346 ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val);
347 if (ret < 0)
348 return ret;
350 if (val & PS_STAT_VBUS_VALID)
351 online = 1;
352 return online;
355 static int axp288_get_charger_health(struct axp288_chrg_info *info)
357 int ret, pwr_stat, chrg_stat;
358 int health = POWER_SUPPLY_HEALTH_UNKNOWN;
359 unsigned int val;
361 ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val);
362 if ((ret < 0) || !(val & PS_STAT_VBUS_PRESENT))
363 goto health_read_fail;
364 else
365 pwr_stat = val;
367 ret = regmap_read(info->regmap, AXP20X_PWR_OP_MODE, &val);
368 if (ret < 0)
369 goto health_read_fail;
370 else
371 chrg_stat = val;
373 if (!(pwr_stat & PS_STAT_VBUS_VALID))
374 health = POWER_SUPPLY_HEALTH_DEAD;
375 else if (chrg_stat & CHRG_STAT_PMIC_OTP)
376 health = POWER_SUPPLY_HEALTH_OVERHEAT;
377 else if (chrg_stat & CHRG_STAT_BAT_SAFE_MODE)
378 health = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
379 else
380 health = POWER_SUPPLY_HEALTH_GOOD;
382 health_read_fail:
383 return health;
386 static int axp288_charger_usb_set_property(struct power_supply *psy,
387 enum power_supply_property psp,
388 const union power_supply_propval *val)
390 struct axp288_chrg_info *info = power_supply_get_drvdata(psy);
391 int ret = 0;
392 int scaled_val;
394 mutex_lock(&info->lock);
396 switch (psp) {
397 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
398 scaled_val = min(val->intval, info->max_cc);
399 scaled_val = DIV_ROUND_CLOSEST(scaled_val, 1000);
400 ret = axp288_charger_set_cc(info, scaled_val);
401 if (ret < 0)
402 dev_warn(&info->pdev->dev, "set charge current failed\n");
403 break;
404 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
405 scaled_val = min(val->intval, info->max_cv);
406 scaled_val = DIV_ROUND_CLOSEST(scaled_val, 1000);
407 ret = axp288_charger_set_cv(info, scaled_val);
408 if (ret < 0)
409 dev_warn(&info->pdev->dev, "set charge voltage failed\n");
410 break;
411 default:
412 ret = -EINVAL;
415 mutex_unlock(&info->lock);
416 return ret;
419 static int axp288_charger_usb_get_property(struct power_supply *psy,
420 enum power_supply_property psp,
421 union power_supply_propval *val)
423 struct axp288_chrg_info *info = power_supply_get_drvdata(psy);
424 int ret = 0;
426 mutex_lock(&info->lock);
428 switch (psp) {
429 case POWER_SUPPLY_PROP_PRESENT:
430 /* Check for OTG case first */
431 if (info->otg.id_short) {
432 val->intval = 0;
433 break;
435 ret = axp288_charger_is_present(info);
436 if (ret < 0)
437 goto psy_get_prop_fail;
438 info->present = ret;
439 val->intval = info->present;
440 break;
441 case POWER_SUPPLY_PROP_ONLINE:
442 /* Check for OTG case first */
443 if (info->otg.id_short) {
444 val->intval = 0;
445 break;
447 ret = axp288_charger_is_online(info);
448 if (ret < 0)
449 goto psy_get_prop_fail;
450 info->online = ret;
451 val->intval = info->online;
452 break;
453 case POWER_SUPPLY_PROP_HEALTH:
454 val->intval = axp288_get_charger_health(info);
455 break;
456 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
457 val->intval = info->cc * 1000;
458 break;
459 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
460 val->intval = info->max_cc * 1000;
461 break;
462 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
463 val->intval = info->cv * 1000;
464 break;
465 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
466 val->intval = info->max_cv * 1000;
467 break;
468 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
469 val->intval = info->inlmt * 1000;
470 break;
471 default:
472 ret = -EINVAL;
473 goto psy_get_prop_fail;
476 psy_get_prop_fail:
477 mutex_unlock(&info->lock);
478 return ret;
481 static int axp288_charger_property_is_writeable(struct power_supply *psy,
482 enum power_supply_property psp)
484 int ret;
486 switch (psp) {
487 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
488 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
489 ret = 1;
490 break;
491 default:
492 ret = 0;
495 return ret;
498 static enum power_supply_property axp288_usb_props[] = {
499 POWER_SUPPLY_PROP_PRESENT,
500 POWER_SUPPLY_PROP_ONLINE,
501 POWER_SUPPLY_PROP_TYPE,
502 POWER_SUPPLY_PROP_HEALTH,
503 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
504 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
505 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
506 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
507 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
510 static const struct power_supply_desc axp288_charger_desc = {
511 .name = "axp288_charger",
512 .type = POWER_SUPPLY_TYPE_USB,
513 .properties = axp288_usb_props,
514 .num_properties = ARRAY_SIZE(axp288_usb_props),
515 .get_property = axp288_charger_usb_get_property,
516 .set_property = axp288_charger_usb_set_property,
517 .property_is_writeable = axp288_charger_property_is_writeable,
520 static irqreturn_t axp288_charger_irq_thread_handler(int irq, void *dev)
522 struct axp288_chrg_info *info = dev;
523 int i;
525 for (i = 0; i < CHRG_INTR_END; i++) {
526 if (info->irq[i] == irq)
527 break;
530 if (i >= CHRG_INTR_END) {
531 dev_warn(&info->pdev->dev, "spurious interrupt!!\n");
532 return IRQ_NONE;
535 switch (i) {
536 case VBUS_OV_IRQ:
537 dev_dbg(&info->pdev->dev, "VBUS Over Voltage INTR\n");
538 break;
539 case CHARGE_DONE_IRQ:
540 dev_dbg(&info->pdev->dev, "Charging Done INTR\n");
541 break;
542 case CHARGE_CHARGING_IRQ:
543 dev_dbg(&info->pdev->dev, "Start Charging IRQ\n");
544 break;
545 case BAT_SAFE_QUIT_IRQ:
546 dev_dbg(&info->pdev->dev,
547 "Quit Safe Mode(restart timer) Charging IRQ\n");
548 break;
549 case BAT_SAFE_ENTER_IRQ:
550 dev_dbg(&info->pdev->dev,
551 "Enter Safe Mode(timer expire) Charging IRQ\n");
552 break;
553 case QCBTU_IRQ:
554 dev_dbg(&info->pdev->dev,
555 "Quit Battery Under Temperature(CHRG) INTR\n");
556 break;
557 case CBTU_IRQ:
558 dev_dbg(&info->pdev->dev,
559 "Hit Battery Under Temperature(CHRG) INTR\n");
560 break;
561 case QCBTO_IRQ:
562 dev_dbg(&info->pdev->dev,
563 "Quit Battery Over Temperature(CHRG) INTR\n");
564 break;
565 case CBTO_IRQ:
566 dev_dbg(&info->pdev->dev,
567 "Hit Battery Over Temperature(CHRG) INTR\n");
568 break;
569 default:
570 dev_warn(&info->pdev->dev, "Spurious Interrupt!!!\n");
571 goto out;
574 power_supply_changed(info->psy_usb);
575 out:
576 return IRQ_HANDLED;
579 static void axp288_charger_extcon_evt_worker(struct work_struct *work)
581 struct axp288_chrg_info *info =
582 container_of(work, struct axp288_chrg_info, cable.work);
583 int ret, current_limit;
584 bool changed = false;
585 struct extcon_dev *edev = info->cable.edev;
586 bool old_connected = info->cable.connected;
588 /* Determine cable/charger type */
589 if (extcon_get_cable_state(edev, AXP288_EXTCON_SLOW_CHARGER) > 0) {
590 dev_dbg(&info->pdev->dev, "USB SDP charger is connected");
591 info->cable.connected = true;
592 info->cable.chg_type = POWER_SUPPLY_TYPE_USB;
593 } else if (extcon_get_cable_state(edev,
594 AXP288_EXTCON_DOWNSTREAM_CHARGER) > 0) {
595 dev_dbg(&info->pdev->dev, "USB CDP charger is connected");
596 info->cable.connected = true;
597 info->cable.chg_type = POWER_SUPPLY_TYPE_USB_CDP;
598 } else if (extcon_get_cable_state(edev,
599 AXP288_EXTCON_FAST_CHARGER) > 0) {
600 dev_dbg(&info->pdev->dev, "USB DCP charger is connected");
601 info->cable.connected = true;
602 info->cable.chg_type = POWER_SUPPLY_TYPE_USB_DCP;
603 } else {
604 if (old_connected)
605 dev_dbg(&info->pdev->dev, "USB charger disconnected");
606 info->cable.connected = false;
607 info->cable.chg_type = POWER_SUPPLY_TYPE_USB;
610 /* Cable status changed */
611 if (old_connected != info->cable.connected)
612 changed = true;
614 if (!changed)
615 return;
617 mutex_lock(&info->lock);
619 if (info->is_charger_enabled && !info->cable.connected) {
620 info->enable_charger = false;
621 ret = axp288_charger_enable_charger(info, info->enable_charger);
622 if (ret < 0)
623 dev_err(&info->pdev->dev,
624 "cannot disable charger (%d)", ret);
626 } else if (!info->is_charger_enabled && info->cable.connected) {
627 switch (info->cable.chg_type) {
628 case POWER_SUPPLY_TYPE_USB:
629 current_limit = ILIM_500MA;
630 break;
631 case POWER_SUPPLY_TYPE_USB_CDP:
632 current_limit = ILIM_1500MA;
633 break;
634 case POWER_SUPPLY_TYPE_USB_DCP:
635 current_limit = ILIM_2000MA;
636 break;
637 default:
638 /* Unknown */
639 current_limit = 0;
640 break;
643 /* Set vbus current limit first, then enable charger */
644 ret = axp288_charger_set_vbus_inlmt(info, current_limit);
645 if (ret < 0) {
646 dev_err(&info->pdev->dev,
647 "error setting current limit (%d)", ret);
648 } else {
649 info->enable_charger = (current_limit > 0);
650 ret = axp288_charger_enable_charger(info,
651 info->enable_charger);
652 if (ret < 0)
653 dev_err(&info->pdev->dev,
654 "cannot enable charger (%d)", ret);
658 if (changed)
659 info->health = axp288_get_charger_health(info);
661 mutex_unlock(&info->lock);
663 if (changed)
664 power_supply_changed(info->psy_usb);
667 static int axp288_charger_handle_cable_evt(struct notifier_block *nb,
668 unsigned long event, void *param)
670 struct axp288_chrg_info *info =
671 container_of(nb, struct axp288_chrg_info, cable.nb);
673 schedule_work(&info->cable.work);
675 return NOTIFY_OK;
678 static void axp288_charger_otg_evt_worker(struct work_struct *work)
680 struct axp288_chrg_info *info =
681 container_of(work, struct axp288_chrg_info, otg.work);
682 int ret;
684 /* Disable VBUS path before enabling the 5V boost */
685 ret = axp288_charger_vbus_path_select(info, !info->otg.id_short);
686 if (ret < 0)
687 dev_warn(&info->pdev->dev, "vbus path disable failed\n");
690 static int axp288_charger_handle_otg_evt(struct notifier_block *nb,
691 unsigned long event, void *param)
693 struct axp288_chrg_info *info =
694 container_of(nb, struct axp288_chrg_info, otg.id_nb);
695 struct extcon_dev *edev = param;
696 int usb_host = extcon_get_cable_state(edev, "USB-Host");
698 dev_dbg(&info->pdev->dev, "external connector USB-Host is %s\n",
699 usb_host ? "attached" : "detached");
702 * Set usb_id_short flag to avoid running charger detection logic
703 * in case usb host.
705 info->otg.id_short = usb_host;
706 schedule_work(&info->otg.work);
708 return NOTIFY_OK;
711 static void charger_init_hw_regs(struct axp288_chrg_info *info)
713 int ret, cc, cv;
714 unsigned int val;
716 /* Program temperature thresholds */
717 ret = regmap_write(info->regmap, AXP20X_V_LTF_CHRG, CHRG_VLTFC_0C);
718 if (ret < 0)
719 dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n",
720 AXP20X_V_LTF_CHRG, ret);
722 ret = regmap_write(info->regmap, AXP20X_V_HTF_CHRG, CHRG_VHTFC_45C);
723 if (ret < 0)
724 dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n",
725 AXP20X_V_HTF_CHRG, ret);
727 /* Do not turn-off charger o/p after charge cycle ends */
728 ret = regmap_update_bits(info->regmap,
729 AXP20X_CHRG_CTRL2,
730 CNTL2_CHG_OUT_TURNON, 1);
731 if (ret < 0)
732 dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n",
733 AXP20X_CHRG_CTRL2, ret);
735 /* Enable interrupts */
736 ret = regmap_update_bits(info->regmap,
737 AXP20X_IRQ2_EN,
738 BAT_IRQ_CFG_BAT_MASK, 1);
739 if (ret < 0)
740 dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n",
741 AXP20X_IRQ2_EN, ret);
743 ret = regmap_update_bits(info->regmap, AXP20X_IRQ3_EN,
744 TEMP_IRQ_CFG_MASK, 1);
745 if (ret < 0)
746 dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n",
747 AXP20X_IRQ3_EN, ret);
749 /* Setup ending condition for charging to be 10% of I(chrg) */
750 ret = regmap_update_bits(info->regmap,
751 AXP20X_CHRG_CTRL1,
752 CHRG_CCCV_ITERM_20P, 0);
753 if (ret < 0)
754 dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n",
755 AXP20X_CHRG_CTRL1, ret);
757 /* Disable OCV-SOC curve calibration */
758 ret = regmap_update_bits(info->regmap,
759 AXP20X_CC_CTRL,
760 FG_CNTL_OCV_ADJ_EN, 0);
761 if (ret < 0)
762 dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n",
763 AXP20X_CC_CTRL, ret);
765 /* Init charging current and voltage */
766 info->max_cc = info->pdata->max_cc;
767 info->max_cv = info->pdata->max_cv;
769 /* Read current charge voltage and current limit */
770 ret = regmap_read(info->regmap, AXP20X_CHRG_CTRL1, &val);
771 if (ret < 0) {
772 /* Assume default if cannot read */
773 info->cc = info->pdata->def_cc;
774 info->cv = info->pdata->def_cv;
775 } else {
776 /* Determine charge voltage */
777 cv = (val & CHRG_CCCV_CV_MASK) >> CHRG_CCCV_CV_BIT_POS;
778 switch (cv) {
779 case CHRG_CCCV_CV_4100MV:
780 info->cv = CV_4100MV;
781 break;
782 case CHRG_CCCV_CV_4150MV:
783 info->cv = CV_4150MV;
784 break;
785 case CHRG_CCCV_CV_4200MV:
786 info->cv = CV_4200MV;
787 break;
788 case CHRG_CCCV_CV_4350MV:
789 info->cv = CV_4350MV;
790 break;
791 default:
792 info->cv = INT_MAX;
793 break;
796 /* Determine charge current limit */
797 cc = (ret & CHRG_CCCV_CC_MASK) >> CHRG_CCCV_CC_BIT_POS;
798 cc = (cc * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET;
799 info->cc = cc;
801 /* Program default charging voltage and current */
802 cc = min(info->pdata->def_cc, info->max_cc);
803 cv = min(info->pdata->def_cv, info->max_cv);
805 ret = axp288_charger_set_cc(info, cc);
806 if (ret < 0)
807 dev_warn(&info->pdev->dev,
808 "error(%d) in setting CC\n", ret);
810 ret = axp288_charger_set_cv(info, cv);
811 if (ret < 0)
812 dev_warn(&info->pdev->dev,
813 "error(%d) in setting CV\n", ret);
817 static int axp288_charger_probe(struct platform_device *pdev)
819 int ret, i, pirq;
820 struct axp288_chrg_info *info;
821 struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
822 struct power_supply_config charger_cfg = {};
824 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
825 if (!info)
826 return -ENOMEM;
828 info->pdev = pdev;
829 info->regmap = axp20x->regmap;
830 info->regmap_irqc = axp20x->regmap_irqc;
831 info->pdata = pdev->dev.platform_data;
833 if (!info->pdata) {
834 /* Try ACPI provided pdata via device properties */
835 if (!device_property_present(&pdev->dev,
836 "axp288_charger_data\n"))
837 dev_err(&pdev->dev, "failed to get platform data\n");
838 return -ENODEV;
841 info->cable.edev = extcon_get_extcon_dev(AXP288_EXTCON_DEV_NAME);
842 if (info->cable.edev == NULL) {
843 dev_dbg(&pdev->dev, "%s is not ready, probe deferred\n",
844 AXP288_EXTCON_DEV_NAME);
845 return -EPROBE_DEFER;
848 /* Register for extcon notification */
849 INIT_WORK(&info->cable.work, axp288_charger_extcon_evt_worker);
850 info->cable.nb.notifier_call = axp288_charger_handle_cable_evt;
851 ret = extcon_register_notifier(info->cable.edev, EXTCON_NONE, &info->cable.nb);
852 if (ret) {
853 dev_err(&info->pdev->dev,
854 "failed to register extcon notifier %d\n", ret);
855 return ret;
858 platform_set_drvdata(pdev, info);
859 mutex_init(&info->lock);
861 /* Register with power supply class */
862 charger_cfg.drv_data = info;
863 info->psy_usb = power_supply_register(&pdev->dev, &axp288_charger_desc,
864 &charger_cfg);
865 if (IS_ERR(info->psy_usb)) {
866 dev_err(&pdev->dev, "failed to register power supply charger\n");
867 ret = PTR_ERR(info->psy_usb);
868 goto psy_reg_failed;
871 /* Register for OTG notification */
872 INIT_WORK(&info->otg.work, axp288_charger_otg_evt_worker);
873 info->otg.id_nb.notifier_call = axp288_charger_handle_otg_evt;
874 ret = extcon_register_interest(&info->otg.cable, NULL, "USB-Host",
875 &info->otg.id_nb);
876 if (ret)
877 dev_warn(&pdev->dev, "failed to register otg notifier\n");
879 if (info->otg.cable.edev)
880 info->otg.id_short = extcon_get_cable_state(
881 info->otg.cable.edev, "USB-Host");
883 /* Register charger interrupts */
884 for (i = 0; i < CHRG_INTR_END; i++) {
885 pirq = platform_get_irq(info->pdev, i);
886 info->irq[i] = regmap_irq_get_virq(info->regmap_irqc, pirq);
887 if (info->irq[i] < 0) {
888 dev_warn(&info->pdev->dev,
889 "failed to get virtual interrupt=%d\n", pirq);
890 ret = info->irq[i];
891 goto intr_reg_failed;
893 ret = devm_request_threaded_irq(&info->pdev->dev, info->irq[i],
894 NULL, axp288_charger_irq_thread_handler,
895 IRQF_ONESHOT, info->pdev->name, info);
896 if (ret) {
897 dev_err(&pdev->dev, "failed to request interrupt=%d\n",
898 info->irq[i]);
899 goto intr_reg_failed;
903 charger_init_hw_regs(info);
905 return 0;
907 intr_reg_failed:
908 if (info->otg.cable.edev)
909 extcon_unregister_interest(&info->otg.cable);
910 power_supply_unregister(info->psy_usb);
911 psy_reg_failed:
912 extcon_unregister_notifier(info->cable.edev, EXTCON_NONE, &info->cable.nb);
913 return ret;
916 static int axp288_charger_remove(struct platform_device *pdev)
918 struct axp288_chrg_info *info = dev_get_drvdata(&pdev->dev);
920 if (info->otg.cable.edev)
921 extcon_unregister_interest(&info->otg.cable);
923 extcon_unregister_notifier(info->cable.edev, EXTCON_NONE, &info->cable.nb);
924 power_supply_unregister(info->psy_usb);
926 return 0;
929 static struct platform_driver axp288_charger_driver = {
930 .probe = axp288_charger_probe,
931 .remove = axp288_charger_remove,
932 .driver = {
933 .name = "axp288_charger",
937 module_platform_driver(axp288_charger_driver);
939 MODULE_AUTHOR("Ramakrishna Pallala <ramakrishna.pallala@intel.com>");
940 MODULE_DESCRIPTION("X-power AXP288 Charger Driver");
941 MODULE_LICENSE("GPL v2");