axp288_charger.c (27579B)
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 0x38 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_4400MV 0x4 /* 4400mV */ 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 105enum { 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 118struct 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 153static 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 176static 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 207static 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 237static 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 270static 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 288static 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 305static 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 320static 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 360out: 361 mutex_unlock(&info->lock); 362 return ret; 363} 364 365static 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 379static 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; 406out: 407 iosf_mbi_unblock_punit_i2c_access(); 408 return ret; 409} 410 411static 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 462out: 463 mutex_unlock(&info->lock); 464 return ret; 465} 466 467static 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 485static 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 497static 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 507static 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); 564out: 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 */ 599static 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 617static 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 675static 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 684static 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 706static 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 717static 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 } else { 773 /* Set Vhold to the factory default / recommended 4.4V */ 774 val = VBUS_ISPOUT_VHOLD_SET_4400MV << VBUS_ISPOUT_VHOLD_SET_BIT_POS; 775 ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT, 776 VBUS_ISPOUT_VHOLD_SET_MASK, val); 777 if (ret < 0) { 778 dev_err(&info->pdev->dev, "register(%x) write error(%d)\n", 779 AXP20X_VBUS_IPSOUT_MGMT, ret); 780 return ret; 781 } 782 } 783 784 /* Read current charge voltage and current limit */ 785 ret = regmap_read(info->regmap, AXP20X_CHRG_CTRL1, &val); 786 if (ret < 0) { 787 dev_err(&info->pdev->dev, "register(%x) read error(%d)\n", 788 AXP20X_CHRG_CTRL1, ret); 789 return ret; 790 } 791 792 /* Determine charge voltage */ 793 cv = (val & CHRG_CCCV_CV_MASK) >> CHRG_CCCV_CV_BIT_POS; 794 switch (cv) { 795 case CHRG_CCCV_CV_4100MV: 796 info->cv = CV_4100MV; 797 break; 798 case CHRG_CCCV_CV_4150MV: 799 info->cv = CV_4150MV; 800 break; 801 case CHRG_CCCV_CV_4200MV: 802 info->cv = CV_4200MV; 803 break; 804 case CHRG_CCCV_CV_4350MV: 805 info->cv = CV_4350MV; 806 break; 807 } 808 809 /* Determine charge current limit */ 810 cc = (val & CHRG_CCCV_CC_MASK) >> CHRG_CCCV_CC_BIT_POS; 811 cc = (cc * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET; 812 info->cc = cc; 813 814 /* 815 * Do not allow the user to configure higher settings then those 816 * set by the firmware 817 */ 818 info->max_cv = info->cv; 819 info->max_cc = info->cc; 820 821 return 0; 822} 823 824static void axp288_charger_cancel_work(void *data) 825{ 826 struct axp288_chrg_info *info = data; 827 828 cancel_work_sync(&info->otg.work); 829 cancel_work_sync(&info->cable.work); 830} 831 832static int axp288_charger_probe(struct platform_device *pdev) 833{ 834 int ret, i, pirq; 835 struct axp288_chrg_info *info; 836 struct device *dev = &pdev->dev; 837 struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); 838 struct power_supply_config charger_cfg = {}; 839 unsigned int val; 840 841 /* 842 * Normally the native AXP288 fg/charger drivers are preferred but 843 * on some devices the ACPI drivers should be used instead. 844 */ 845 if (!acpi_quirk_skip_acpi_ac_and_battery()) 846 return -ENODEV; 847 848 /* 849 * On some devices the fuelgauge and charger parts of the axp288 are 850 * not used, check that the fuelgauge is enabled (CC_CTRL != 0). 851 */ 852 ret = regmap_read(axp20x->regmap, AXP20X_CC_CTRL, &val); 853 if (ret < 0) 854 return ret; 855 if (val == 0) 856 return -ENODEV; 857 858 info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); 859 if (!info) 860 return -ENOMEM; 861 862 mutex_init(&info->lock); 863 info->pdev = pdev; 864 info->regmap = axp20x->regmap; 865 info->regmap_irqc = axp20x->regmap_irqc; 866 867 info->cable.edev = extcon_get_extcon_dev(AXP288_EXTCON_DEV_NAME); 868 if (IS_ERR(info->cable.edev)) { 869 dev_err_probe(dev, PTR_ERR(info->cable.edev), 870 "extcon_get_extcon_dev(%s) failed\n", 871 AXP288_EXTCON_DEV_NAME); 872 return PTR_ERR(info->cable.edev); 873 } 874 875 if (acpi_dev_present(USB_HOST_EXTCON_HID, NULL, -1)) { 876 info->otg.cable = extcon_get_extcon_dev(USB_HOST_EXTCON_NAME); 877 if (IS_ERR(info->otg.cable)) { 878 dev_err_probe(dev, PTR_ERR(info->otg.cable), 879 "extcon_get_extcon_dev(%s) failed\n", 880 USB_HOST_EXTCON_NAME); 881 return PTR_ERR(info->otg.cable); 882 } 883 dev_info(dev, "Using " USB_HOST_EXTCON_HID " extcon for usb-id\n"); 884 } 885 886 platform_set_drvdata(pdev, info); 887 888 ret = charger_init_hw_regs(info); 889 if (ret) 890 return ret; 891 892 /* Register with power supply class */ 893 charger_cfg.drv_data = info; 894 info->psy_usb = devm_power_supply_register(dev, &axp288_charger_desc, 895 &charger_cfg); 896 if (IS_ERR(info->psy_usb)) { 897 ret = PTR_ERR(info->psy_usb); 898 dev_err(dev, "failed to register power supply: %d\n", ret); 899 return ret; 900 } 901 902 /* Cancel our work on cleanup, register this before the notifiers */ 903 ret = devm_add_action(dev, axp288_charger_cancel_work, info); 904 if (ret) 905 return ret; 906 907 /* Register for extcon notification */ 908 INIT_WORK(&info->cable.work, axp288_charger_extcon_evt_worker); 909 info->cable.nb.notifier_call = axp288_charger_handle_cable_evt; 910 ret = devm_extcon_register_notifier_all(dev, info->cable.edev, 911 &info->cable.nb); 912 if (ret) { 913 dev_err(dev, "failed to register cable extcon notifier\n"); 914 return ret; 915 } 916 schedule_work(&info->cable.work); 917 918 /* Register for OTG notification */ 919 INIT_WORK(&info->otg.work, axp288_charger_otg_evt_worker); 920 info->otg.id_nb.notifier_call = axp288_charger_handle_otg_evt; 921 if (info->otg.cable) { 922 ret = devm_extcon_register_notifier(dev, info->otg.cable, 923 EXTCON_USB_HOST, &info->otg.id_nb); 924 if (ret) { 925 dev_err(dev, "failed to register EXTCON_USB_HOST notifier\n"); 926 return ret; 927 } 928 schedule_work(&info->otg.work); 929 } 930 931 /* Register charger interrupts */ 932 for (i = 0; i < CHRG_INTR_END; i++) { 933 pirq = platform_get_irq(info->pdev, i); 934 if (pirq < 0) 935 return pirq; 936 937 info->irq[i] = regmap_irq_get_virq(info->regmap_irqc, pirq); 938 if (info->irq[i] < 0) { 939 dev_warn(&info->pdev->dev, 940 "failed to get virtual interrupt=%d\n", pirq); 941 return info->irq[i]; 942 } 943 ret = devm_request_threaded_irq(&info->pdev->dev, info->irq[i], 944 NULL, axp288_charger_irq_thread_handler, 945 IRQF_ONESHOT, info->pdev->name, info); 946 if (ret) { 947 dev_err(dev, "failed to request interrupt=%d\n", 948 info->irq[i]); 949 return ret; 950 } 951 } 952 953 return 0; 954} 955 956static const struct platform_device_id axp288_charger_id_table[] = { 957 { .name = "axp288_charger" }, 958 {}, 959}; 960MODULE_DEVICE_TABLE(platform, axp288_charger_id_table); 961 962static struct platform_driver axp288_charger_driver = { 963 .probe = axp288_charger_probe, 964 .id_table = axp288_charger_id_table, 965 .driver = { 966 .name = "axp288_charger", 967 }, 968}; 969 970module_platform_driver(axp288_charger_driver); 971 972MODULE_AUTHOR("Ramakrishna Pallala <ramakrishna.pallala@intel.com>"); 973MODULE_DESCRIPTION("X-power AXP288 Charger Driver"); 974MODULE_LICENSE("GPL v2");