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