1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * charger driver for the PF1550 4 * 5 * Copyright (C) 2016 Freescale Semiconductor, Inc. 6 * Robin Gong <yibin.gong@freescale.com> 7 * 8 * Portions Copyright (c) 2025 Savoir-faire Linux Inc. 9 * Samuel Kayode <samuel.kayode@savoirfairelinux.com> 10 */ 11 12 #include <linux/devm-helpers.h> 13 #include <linux/interrupt.h> 14 #include <linux/mfd/pf1550.h> 15 #include <linux/module.h> 16 #include <linux/platform_device.h> 17 #include <linux/power_supply.h> 18 19 #define PF1550_DEFAULT_CONSTANT_VOLT 4200000 20 #define PF1550_DEFAULT_MIN_SYSTEM_VOLT 3500000 21 #define PF1550_DEFAULT_THERMAL_TEMP 95 22 #define PF1550_CHARGER_IRQ_NR 5 23 24 struct pf1550_charger { 25 struct device *dev; 26 const struct pf1550_ddata *pf1550; 27 struct power_supply *charger; 28 struct power_supply *battery; 29 struct delayed_work vbus_sense_work; 30 struct delayed_work chg_sense_work; 31 struct delayed_work bat_sense_work; 32 int virqs[PF1550_CHARGER_IRQ_NR]; 33 34 u32 constant_volt; 35 u32 min_system_volt; 36 u32 thermal_regulation_temp; 37 }; 38 39 static int pf1550_get_charger_state(struct regmap *regmap, int *val) 40 { 41 unsigned int data; 42 int ret; 43 44 ret = regmap_read(regmap, PF1550_CHARG_REG_CHG_SNS, &data); 45 if (ret < 0) 46 return ret; 47 48 data &= PF1550_CHG_SNS_MASK; 49 50 switch (data) { 51 case PF1550_CHG_PRECHARGE: 52 case PF1550_CHG_CONSTANT_CURRENT: 53 case PF1550_CHG_CONSTANT_VOL: 54 case PF1550_CHG_EOC: 55 *val = POWER_SUPPLY_STATUS_CHARGING; 56 break; 57 case PF1550_CHG_DONE: 58 *val = POWER_SUPPLY_STATUS_FULL; 59 break; 60 case PF1550_CHG_TIMER_FAULT: 61 case PF1550_CHG_SUSPEND: 62 *val = POWER_SUPPLY_STATUS_NOT_CHARGING; 63 break; 64 case PF1550_CHG_OFF_INV: 65 case PF1550_CHG_OFF_TEMP: 66 case PF1550_CHG_LINEAR_ONLY: 67 *val = POWER_SUPPLY_STATUS_DISCHARGING; 68 break; 69 default: 70 *val = POWER_SUPPLY_STATUS_UNKNOWN; 71 } 72 73 return 0; 74 } 75 76 static int pf1550_get_charge_type(struct regmap *regmap, int *val) 77 { 78 unsigned int data; 79 int ret; 80 81 ret = regmap_read(regmap, PF1550_CHARG_REG_CHG_SNS, &data); 82 if (ret < 0) 83 return ret; 84 85 data &= PF1550_CHG_SNS_MASK; 86 87 switch (data) { 88 case PF1550_CHG_SNS_MASK: 89 *val = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; 90 break; 91 case PF1550_CHG_CONSTANT_CURRENT: 92 case PF1550_CHG_CONSTANT_VOL: 93 case PF1550_CHG_EOC: 94 *val = POWER_SUPPLY_CHARGE_TYPE_FAST; 95 break; 96 case PF1550_CHG_DONE: 97 case PF1550_CHG_TIMER_FAULT: 98 case PF1550_CHG_SUSPEND: 99 case PF1550_CHG_OFF_INV: 100 case PF1550_CHG_BAT_OVER: 101 case PF1550_CHG_OFF_TEMP: 102 case PF1550_CHG_LINEAR_ONLY: 103 *val = POWER_SUPPLY_CHARGE_TYPE_NONE; 104 break; 105 default: 106 *val = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN; 107 } 108 109 return 0; 110 } 111 112 /* 113 * Supported health statuses: 114 * - POWER_SUPPLY_HEALTH_DEAD 115 * - POWER_SUPPLY_HEALTH_GOOD 116 * - POWER_SUPPLY_HEALTH_OVERVOLTAGE 117 * - POWER_SUPPLY_HEALTH_UNKNOWN 118 */ 119 static int pf1550_get_battery_health(struct regmap *regmap, int *val) 120 { 121 unsigned int data; 122 int ret; 123 124 ret = regmap_read(regmap, PF1550_CHARG_REG_BATT_SNS, &data); 125 if (ret < 0) 126 return ret; 127 128 data &= PF1550_BAT_SNS_MASK; 129 130 switch (data) { 131 case PF1550_BAT_NO_DETECT: 132 *val = POWER_SUPPLY_HEALTH_NO_BATTERY; 133 break; 134 case PF1550_BAT_NO_VBUS: 135 case PF1550_BAT_LOW_THAN_PRECHARG: 136 case PF1550_BAT_CHARG_FAIL: 137 case PF1550_BAT_HIGH_THAN_PRECHARG: 138 *val = POWER_SUPPLY_HEALTH_GOOD; 139 break; 140 case PF1550_BAT_OVER_VOL: 141 *val = POWER_SUPPLY_HEALTH_OVERVOLTAGE; 142 break; 143 default: 144 *val = POWER_SUPPLY_HEALTH_UNKNOWN; 145 break; 146 } 147 148 return 0; 149 } 150 151 static int pf1550_get_present(struct regmap *regmap, int *val) 152 { 153 unsigned int data; 154 int ret; 155 156 ret = regmap_read(regmap, PF1550_CHARG_REG_BATT_SNS, &data); 157 if (ret < 0) 158 return ret; 159 160 data &= PF1550_BAT_SNS_MASK; 161 *val = (data == PF1550_BAT_NO_DETECT) ? 0 : 1; 162 163 return 0; 164 } 165 166 static int pf1550_get_online(struct regmap *regmap, int *val) 167 { 168 unsigned int data; 169 int ret; 170 171 ret = regmap_read(regmap, PF1550_CHARG_REG_VBUS_SNS, &data); 172 if (ret < 0) 173 return ret; 174 175 *val = (data & PF1550_VBUS_VALID) ? 1 : 0; 176 177 return 0; 178 } 179 180 static void pf1550_chg_bat_work(struct work_struct *work) 181 { 182 struct pf1550_charger *chg = container_of(to_delayed_work(work), 183 struct pf1550_charger, 184 bat_sense_work); 185 unsigned int data; 186 187 if (regmap_read(chg->pf1550->regmap, PF1550_CHARG_REG_BATT_SNS, &data)) { 188 dev_err(chg->dev, "Read BATT_SNS error.\n"); 189 return; 190 } 191 192 switch (data & PF1550_BAT_SNS_MASK) { 193 case PF1550_BAT_NO_VBUS: 194 dev_dbg(chg->dev, "No valid VBUS input.\n"); 195 break; 196 case PF1550_BAT_LOW_THAN_PRECHARG: 197 dev_dbg(chg->dev, "VBAT < VPRECHG.LB.\n"); 198 break; 199 case PF1550_BAT_CHARG_FAIL: 200 dev_dbg(chg->dev, "Battery charging failed.\n"); 201 break; 202 case PF1550_BAT_HIGH_THAN_PRECHARG: 203 dev_dbg(chg->dev, "VBAT > VPRECHG.LB.\n"); 204 break; 205 case PF1550_BAT_OVER_VOL: 206 dev_dbg(chg->dev, "VBAT > VBATOV.\n"); 207 break; 208 case PF1550_BAT_NO_DETECT: 209 dev_dbg(chg->dev, "Battery not detected.\n"); 210 break; 211 default: 212 dev_err(chg->dev, "Unknown value read:%x\n", 213 data & PF1550_CHG_SNS_MASK); 214 } 215 } 216 217 static void pf1550_chg_chg_work(struct work_struct *work) 218 { 219 struct pf1550_charger *chg = container_of(to_delayed_work(work), 220 struct pf1550_charger, 221 chg_sense_work); 222 unsigned int data; 223 224 if (regmap_read(chg->pf1550->regmap, PF1550_CHARG_REG_CHG_SNS, &data)) { 225 dev_err(chg->dev, "Read CHG_SNS error.\n"); 226 return; 227 } 228 229 switch (data & PF1550_CHG_SNS_MASK) { 230 case PF1550_CHG_PRECHARGE: 231 dev_dbg(chg->dev, "In pre-charger mode.\n"); 232 break; 233 case PF1550_CHG_CONSTANT_CURRENT: 234 dev_dbg(chg->dev, "In fast-charge constant current mode.\n"); 235 break; 236 case PF1550_CHG_CONSTANT_VOL: 237 dev_dbg(chg->dev, "In fast-charge constant voltage mode.\n"); 238 break; 239 case PF1550_CHG_EOC: 240 dev_dbg(chg->dev, "In EOC mode.\n"); 241 break; 242 case PF1550_CHG_DONE: 243 dev_dbg(chg->dev, "In DONE mode.\n"); 244 break; 245 case PF1550_CHG_TIMER_FAULT: 246 dev_info(chg->dev, "In timer fault mode.\n"); 247 break; 248 case PF1550_CHG_SUSPEND: 249 dev_info(chg->dev, "In thermistor suspend mode.\n"); 250 break; 251 case PF1550_CHG_OFF_INV: 252 dev_info(chg->dev, "Input invalid, charger off.\n"); 253 break; 254 case PF1550_CHG_BAT_OVER: 255 dev_warn(chg->dev, "Battery over-voltage.\n"); 256 break; 257 case PF1550_CHG_OFF_TEMP: 258 dev_info(chg->dev, "Temp high, charger off.\n"); 259 break; 260 case PF1550_CHG_LINEAR_ONLY: 261 dev_dbg(chg->dev, "In Linear mode, not charging.\n"); 262 break; 263 default: 264 dev_err(chg->dev, "Unknown value read:%x\n", 265 data & PF1550_CHG_SNS_MASK); 266 } 267 } 268 269 static void pf1550_chg_vbus_work(struct work_struct *work) 270 { 271 struct pf1550_charger *chg = container_of(to_delayed_work(work), 272 struct pf1550_charger, 273 vbus_sense_work); 274 unsigned int data; 275 276 if (regmap_read(chg->pf1550->regmap, PF1550_CHARG_REG_VBUS_SNS, &data)) { 277 dev_err(chg->dev, "Read VBUS_SNS error.\n"); 278 return; 279 } 280 281 if (data & PF1550_VBUS_UVLO) { 282 dev_dbg(chg->dev, "VBUS detached.\n"); 283 power_supply_changed(chg->battery); 284 } 285 if (data & PF1550_VBUS_IN2SYS) 286 dev_dbg(chg->dev, "VBUS_IN2SYS_SNS.\n"); 287 if (data & PF1550_VBUS_OVLO) 288 dev_dbg(chg->dev, "VBUS_OVLO_SNS.\n"); 289 if (data & PF1550_VBUS_VALID) { 290 dev_dbg(chg->dev, "VBUS attached.\n"); 291 power_supply_changed(chg->charger); 292 } 293 } 294 295 static irqreturn_t pf1550_charger_irq_handler(int irq, void *data) 296 { 297 struct pf1550_charger *chg = data; 298 struct device *dev = chg->dev; 299 int i, irq_type = -1; 300 301 for (i = 0; i < PF1550_CHARGER_IRQ_NR; i++) 302 if (irq == chg->virqs[i]) 303 irq_type = i; 304 305 switch (irq_type) { 306 case PF1550_CHARG_IRQ_BAT2SOCI: 307 dev_info(dev, "BAT to SYS Overcurrent interrupt.\n"); 308 break; 309 case PF1550_CHARG_IRQ_BATI: 310 schedule_delayed_work(&chg->bat_sense_work, 311 msecs_to_jiffies(10)); 312 break; 313 case PF1550_CHARG_IRQ_CHGI: 314 schedule_delayed_work(&chg->chg_sense_work, 315 msecs_to_jiffies(10)); 316 break; 317 case PF1550_CHARG_IRQ_VBUSI: 318 schedule_delayed_work(&chg->vbus_sense_work, 319 msecs_to_jiffies(10)); 320 break; 321 case PF1550_CHARG_IRQ_THMI: 322 dev_info(dev, "Thermal interrupt.\n"); 323 break; 324 default: 325 dev_err(dev, "unknown interrupt occurred.\n"); 326 } 327 328 return IRQ_HANDLED; 329 } 330 331 static enum power_supply_property pf1550_charger_props[] = { 332 POWER_SUPPLY_PROP_ONLINE, 333 POWER_SUPPLY_PROP_MODEL_NAME, 334 POWER_SUPPLY_PROP_MANUFACTURER, 335 }; 336 337 static enum power_supply_property pf1550_battery_props[] = { 338 POWER_SUPPLY_PROP_STATUS, 339 POWER_SUPPLY_PROP_CHARGE_TYPE, 340 POWER_SUPPLY_PROP_HEALTH, 341 POWER_SUPPLY_PROP_PRESENT, 342 POWER_SUPPLY_PROP_MODEL_NAME, 343 POWER_SUPPLY_PROP_MANUFACTURER, 344 }; 345 346 static int pf1550_charger_get_property(struct power_supply *psy, 347 enum power_supply_property psp, 348 union power_supply_propval *val) 349 { 350 struct pf1550_charger *chg = power_supply_get_drvdata(psy); 351 struct regmap *regmap = chg->pf1550->regmap; 352 int ret = 0; 353 354 switch (psp) { 355 case POWER_SUPPLY_PROP_STATUS: 356 ret = pf1550_get_charger_state(regmap, &val->intval); 357 break; 358 case POWER_SUPPLY_PROP_CHARGE_TYPE: 359 ret = pf1550_get_charge_type(regmap, &val->intval); 360 break; 361 case POWER_SUPPLY_PROP_HEALTH: 362 ret = pf1550_get_battery_health(regmap, &val->intval); 363 break; 364 case POWER_SUPPLY_PROP_PRESENT: 365 ret = pf1550_get_present(regmap, &val->intval); 366 break; 367 case POWER_SUPPLY_PROP_ONLINE: 368 ret = pf1550_get_online(regmap, &val->intval); 369 break; 370 case POWER_SUPPLY_PROP_MODEL_NAME: 371 val->strval = "PF1550"; 372 break; 373 case POWER_SUPPLY_PROP_MANUFACTURER: 374 val->strval = "NXP"; 375 break; 376 default: 377 return -EINVAL; 378 } 379 380 return ret; 381 } 382 383 static const struct power_supply_desc pf1550_charger_desc = { 384 .name = "pf1550-charger", 385 .type = POWER_SUPPLY_TYPE_MAINS, 386 .properties = pf1550_charger_props, 387 .num_properties = ARRAY_SIZE(pf1550_charger_props), 388 .get_property = pf1550_charger_get_property, 389 }; 390 391 static const struct power_supply_desc pf1550_battery_desc = { 392 .name = "pf1550-battery", 393 .type = POWER_SUPPLY_TYPE_BATTERY, 394 .properties = pf1550_battery_props, 395 .num_properties = ARRAY_SIZE(pf1550_battery_props), 396 .get_property = pf1550_charger_get_property, 397 }; 398 399 static int pf1550_set_constant_volt(struct pf1550_charger *chg, 400 unsigned int uvolt) 401 { 402 unsigned int data; 403 404 if (uvolt >= 3500000 && uvolt <= 4440000) 405 data = 8 + (uvolt - 3500000) / 20000; 406 else 407 return dev_err_probe(chg->dev, -EINVAL, 408 "Wrong value for constant voltage\n"); 409 410 dev_dbg(chg->dev, "Charging constant voltage: %u (0x%x)\n", uvolt, 411 data); 412 413 return regmap_update_bits(chg->pf1550->regmap, 414 PF1550_CHARG_REG_BATT_REG, 415 PF1550_CHARG_REG_BATT_REG_CHGCV_MASK, data); 416 } 417 418 static int pf1550_set_min_system_volt(struct pf1550_charger *chg, 419 unsigned int uvolt) 420 { 421 unsigned int data; 422 423 switch (uvolt) { 424 case 3500000: 425 data = 0x0; 426 break; 427 case 3700000: 428 data = 0x1; 429 break; 430 case 4300000: 431 data = 0x2; 432 break; 433 default: 434 return dev_err_probe(chg->dev, -EINVAL, 435 "Wrong value for minimum system voltage\n"); 436 } 437 438 data <<= PF1550_CHARG_REG_BATT_REG_VMINSYS_SHIFT; 439 440 dev_dbg(chg->dev, "Minimum system regulation voltage: %u (0x%x)\n", 441 uvolt, data); 442 443 return regmap_update_bits(chg->pf1550->regmap, 444 PF1550_CHARG_REG_BATT_REG, 445 PF1550_CHARG_REG_BATT_REG_VMINSYS_MASK, data); 446 } 447 448 static int pf1550_set_thermal_regulation_temp(struct pf1550_charger *chg, 449 unsigned int cells) 450 { 451 unsigned int data; 452 453 switch (cells) { 454 case 80: 455 data = 0x0; 456 break; 457 case 95: 458 data = 0x1; 459 break; 460 case 110: 461 data = 0x2; 462 break; 463 case 125: 464 data = 0x3; 465 break; 466 default: 467 return dev_err_probe(chg->dev, -EINVAL, 468 "Wrong value for thermal temperature\n"); 469 } 470 471 data <<= PF1550_CHARG_REG_THM_REG_CNFG_REGTEMP_SHIFT; 472 473 dev_dbg(chg->dev, "Thermal regulation loop temperature: %u (0x%x)\n", 474 cells, data); 475 476 return regmap_update_bits(chg->pf1550->regmap, 477 PF1550_CHARG_REG_THM_REG_CNFG, 478 PF1550_CHARG_REG_THM_REG_CNFG_REGTEMP_MASK, 479 data); 480 } 481 482 /* 483 * Sets charger registers to proper and safe default values. 484 */ 485 static int pf1550_reg_init(struct pf1550_charger *chg) 486 { 487 struct power_supply_battery_info *info; 488 struct device *dev = chg->dev; 489 int ret; 490 491 /* Unmask charger interrupt, mask DPMI and reserved bit */ 492 ret = regmap_write(chg->pf1550->regmap, PF1550_CHARG_REG_CHG_INT_MASK, 493 PF1550_CHG_INT_MASK); 494 if (ret) 495 return dev_err_probe(dev, ret, 496 "Error unmask charger interrupt\n"); 497 498 ret = pf1550_set_constant_volt(chg, chg->constant_volt); 499 if (ret) 500 return ret; 501 502 ret = pf1550_set_min_system_volt(chg, chg->min_system_volt); 503 if (ret) 504 return ret; 505 506 ret = pf1550_set_thermal_regulation_temp(chg, 507 chg->thermal_regulation_temp); 508 if (ret) 509 return ret; 510 511 /* 512 * The PF1550 charger has 3 modes of operation. By default, the charger 513 * is in mode 1; it remains off. Appropriate for applications not using 514 * a battery. The other supported mode is mode 2, the charger is turned 515 * on to charge a battery when present. 516 */ 517 if (power_supply_get_battery_info(chg->charger, &info)) { 518 ret = regmap_write(chg->pf1550->regmap, 519 PF1550_CHARG_REG_CHG_OPER, 520 PF1550_CHG_BAT_ON); 521 if (ret) 522 return dev_err_probe(dev, ret, 523 "Error turn on charger\n"); 524 } 525 526 return 0; 527 } 528 529 static void pf1550_dt_parse_dev_info(struct pf1550_charger *chg) 530 { 531 struct power_supply_battery_info *info; 532 struct device *dev = chg->dev; 533 534 if (device_property_read_u32(dev->parent, "nxp,min-system-microvolt", 535 &chg->min_system_volt)) 536 chg->min_system_volt = PF1550_DEFAULT_MIN_SYSTEM_VOLT; 537 538 if (device_property_read_u32(dev->parent, 539 "nxp,thermal-regulation-celsius", 540 &chg->thermal_regulation_temp)) 541 chg->thermal_regulation_temp = PF1550_DEFAULT_THERMAL_TEMP; 542 543 if (power_supply_get_battery_info(chg->charger, &info)) 544 chg->constant_volt = PF1550_DEFAULT_CONSTANT_VOLT; 545 else 546 chg->constant_volt = info->constant_charge_voltage_max_uv; 547 } 548 549 static int pf1550_charger_probe(struct platform_device *pdev) 550 { 551 const struct pf1550_ddata *pf1550 = dev_get_drvdata(pdev->dev.parent); 552 struct power_supply_config psy_cfg = {}; 553 struct pf1550_charger *chg; 554 int i, irq, ret; 555 556 chg = devm_kzalloc(&pdev->dev, sizeof(*chg), GFP_KERNEL); 557 if (!chg) 558 return -ENOMEM; 559 560 chg->dev = &pdev->dev; 561 chg->pf1550 = pf1550; 562 563 if (!chg->pf1550->regmap) 564 return dev_err_probe(&pdev->dev, -ENODEV, 565 "failed to get regmap\n"); 566 567 platform_set_drvdata(pdev, chg); 568 569 ret = devm_delayed_work_autocancel(chg->dev, &chg->vbus_sense_work, 570 pf1550_chg_vbus_work); 571 if (ret) 572 return dev_err_probe(chg->dev, ret, 573 "failed to add vbus sense work\n"); 574 575 ret = devm_delayed_work_autocancel(chg->dev, &chg->chg_sense_work, 576 pf1550_chg_chg_work); 577 if (ret) 578 return dev_err_probe(chg->dev, ret, 579 "failed to add charger sense work\n"); 580 581 ret = devm_delayed_work_autocancel(chg->dev, &chg->bat_sense_work, 582 pf1550_chg_bat_work); 583 if (ret) 584 return dev_err_probe(chg->dev, ret, 585 "failed to add battery sense work\n"); 586 587 for (i = 0; i < PF1550_CHARGER_IRQ_NR; i++) { 588 irq = platform_get_irq(pdev, i); 589 if (irq < 0) 590 return irq; 591 592 chg->virqs[i] = irq; 593 594 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, 595 pf1550_charger_irq_handler, 596 IRQF_NO_SUSPEND, 597 "pf1550-charger", chg); 598 if (ret) 599 return dev_err_probe(&pdev->dev, ret, 600 "failed irq request\n"); 601 } 602 603 psy_cfg.drv_data = chg; 604 605 chg->charger = devm_power_supply_register(&pdev->dev, 606 &pf1550_charger_desc, 607 &psy_cfg); 608 if (IS_ERR(chg->charger)) 609 return dev_err_probe(&pdev->dev, PTR_ERR(chg->charger), 610 "failed: power supply register\n"); 611 612 chg->battery = devm_power_supply_register(&pdev->dev, 613 &pf1550_battery_desc, 614 &psy_cfg); 615 if (IS_ERR(chg->battery)) 616 return dev_err_probe(&pdev->dev, PTR_ERR(chg->battery), 617 "failed: power supply register\n"); 618 619 pf1550_dt_parse_dev_info(chg); 620 621 return pf1550_reg_init(chg); 622 } 623 624 static const struct platform_device_id pf1550_charger_id[] = { 625 { "pf1550-charger", }, 626 { /* sentinel */ } 627 }; 628 MODULE_DEVICE_TABLE(platform, pf1550_charger_id); 629 630 static struct platform_driver pf1550_charger_driver = { 631 .driver = { 632 .name = "pf1550-charger", 633 }, 634 .probe = pf1550_charger_probe, 635 .id_table = pf1550_charger_id, 636 }; 637 module_platform_driver(pf1550_charger_driver); 638 639 MODULE_AUTHOR("Robin Gong <yibin.gong@freescale.com>"); 640 MODULE_DESCRIPTION("PF1550 charger driver"); 641 MODULE_LICENSE("GPL"); 642