1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright (c) 2014, Sony Mobile Communications Inc. 3 * 4 * This driver is for the multi-block Switch-Mode Battery Charger and Boost 5 * (SMBB) hardware, found in Qualcomm PM8941 PMICs. The charger is an 6 * integrated, single-cell lithium-ion battery charger. 7 * 8 * Sub-components: 9 * - Charger core 10 * - Buck 11 * - DC charge-path 12 * - USB charge-path 13 * - Battery interface 14 * - Boost (not implemented) 15 * - Misc 16 * - HF-Buck 17 */ 18 19 #include <linux/errno.h> 20 #include <linux/interrupt.h> 21 #include <linux/kernel.h> 22 #include <linux/module.h> 23 #include <linux/mutex.h> 24 #include <linux/of.h> 25 #include <linux/platform_device.h> 26 #include <linux/power_supply.h> 27 #include <linux/regmap.h> 28 #include <linux/slab.h> 29 #include <linux/extcon-provider.h> 30 #include <linux/regulator/driver.h> 31 32 #define SMBB_CHG_VMAX 0x040 33 #define SMBB_CHG_VSAFE 0x041 34 #define SMBB_CHG_CFG 0x043 35 #define SMBB_CHG_IMAX 0x044 36 #define SMBB_CHG_ISAFE 0x045 37 #define SMBB_CHG_VIN_MIN 0x047 38 #define SMBB_CHG_CTRL 0x049 39 #define CTRL_EN BIT(7) 40 #define SMBB_CHG_VBAT_WEAK 0x052 41 #define SMBB_CHG_IBAT_TERM_CHG 0x05b 42 #define IBAT_TERM_CHG_IEOC BIT(7) 43 #define IBAT_TERM_CHG_IEOC_BMS BIT(7) 44 #define IBAT_TERM_CHG_IEOC_CHG 0 45 #define SMBB_CHG_VBAT_DET 0x05d 46 #define SMBB_CHG_TCHG_MAX_EN 0x060 47 #define TCHG_MAX_EN BIT(7) 48 #define SMBB_CHG_WDOG_TIME 0x062 49 #define SMBB_CHG_WDOG_EN 0x065 50 #define WDOG_EN BIT(7) 51 52 #define SMBB_BUCK_REG_MODE 0x174 53 #define BUCK_REG_MODE BIT(0) 54 #define BUCK_REG_MODE_VBAT BIT(0) 55 #define BUCK_REG_MODE_VSYS 0 56 57 #define SMBB_BAT_PRES_STATUS 0x208 58 #define PRES_STATUS_BAT_PRES BIT(7) 59 #define SMBB_BAT_TEMP_STATUS 0x209 60 #define TEMP_STATUS_OK BIT(7) 61 #define TEMP_STATUS_HOT BIT(6) 62 #define SMBB_BAT_BTC_CTRL 0x249 63 #define BTC_CTRL_COMP_EN BIT(7) 64 #define BTC_CTRL_COLD_EXT BIT(1) 65 #define BTC_CTRL_HOT_EXT_N BIT(0) 66 67 #define SMBB_USB_IMAX 0x344 68 #define SMBB_USB_OTG_CTL 0x348 69 #define OTG_CTL_EN BIT(0) 70 #define SMBB_USB_ENUM_TIMER_STOP 0x34e 71 #define ENUM_TIMER_STOP BIT(0) 72 #define SMBB_USB_SEC_ACCESS 0x3d0 73 #define SEC_ACCESS_MAGIC 0xa5 74 #define SMBB_USB_REV_BST 0x3ed 75 #define REV_BST_CHG_GONE BIT(7) 76 77 #define SMBB_DC_IMAX 0x444 78 79 #define SMBB_MISC_REV2 0x601 80 #define SMBB_MISC_BOOT_DONE 0x642 81 #define BOOT_DONE BIT(7) 82 83 #define STATUS_USBIN_VALID BIT(0) /* USB connection is valid */ 84 #define STATUS_DCIN_VALID BIT(1) /* DC connection is valid */ 85 #define STATUS_BAT_HOT BIT(2) /* Battery temp 1=Hot, 0=Cold */ 86 #define STATUS_BAT_OK BIT(3) /* Battery temp OK */ 87 #define STATUS_BAT_PRESENT BIT(4) /* Battery is present */ 88 #define STATUS_CHG_DONE BIT(5) /* Charge cycle is complete */ 89 #define STATUS_CHG_TRKL BIT(6) /* Trickle charging */ 90 #define STATUS_CHG_FAST BIT(7) /* Fast charging */ 91 #define STATUS_CHG_GONE BIT(8) /* No charger is connected */ 92 93 enum smbb_attr { 94 ATTR_BAT_ISAFE, 95 ATTR_BAT_IMAX, 96 ATTR_USBIN_IMAX, 97 ATTR_DCIN_IMAX, 98 ATTR_BAT_VSAFE, 99 ATTR_BAT_VMAX, 100 ATTR_BAT_VMIN, 101 ATTR_CHG_VDET, 102 ATTR_VIN_MIN, 103 _ATTR_CNT, 104 }; 105 106 struct smbb_charger { 107 unsigned int revision; 108 unsigned int addr; 109 struct device *dev; 110 struct extcon_dev *edev; 111 112 bool dc_disabled; 113 bool jeita_ext_temp; 114 unsigned long status; 115 struct mutex statlock; 116 117 unsigned int attr[_ATTR_CNT]; 118 119 struct power_supply *usb_psy; 120 struct power_supply *dc_psy; 121 struct power_supply *bat_psy; 122 struct regmap *regmap; 123 124 struct regulator_desc otg_rdesc; 125 struct regulator_dev *otg_reg; 126 }; 127 128 static const unsigned int smbb_usb_extcon_cable[] = { 129 EXTCON_USB, 130 EXTCON_NONE, 131 }; 132 133 static int smbb_vbat_weak_fn(unsigned int index) 134 { 135 return 2100000 + index * 100000; 136 } 137 138 static int smbb_vin_fn(unsigned int index) 139 { 140 if (index > 42) 141 return 5600000 + (index - 43) * 200000; 142 return 3400000 + index * 50000; 143 } 144 145 static int smbb_vmax_fn(unsigned int index) 146 { 147 return 3240000 + index * 10000; 148 } 149 150 static int smbb_vbat_det_fn(unsigned int index) 151 { 152 return 3240000 + index * 20000; 153 } 154 155 static int smbb_imax_fn(unsigned int index) 156 { 157 if (index < 2) 158 return 100000 + index * 50000; 159 return index * 100000; 160 } 161 162 static int smbb_bat_imax_fn(unsigned int index) 163 { 164 return index * 50000; 165 } 166 167 static unsigned int smbb_hw_lookup(unsigned int val, int (*fn)(unsigned int)) 168 { 169 unsigned int widx; 170 unsigned int sel; 171 172 for (widx = sel = 0; (*fn)(widx) <= val; ++widx) 173 sel = widx; 174 175 return sel; 176 } 177 178 static const struct smbb_charger_attr { 179 const char *name; 180 unsigned int reg; 181 unsigned int safe_reg; 182 unsigned int max; 183 unsigned int min; 184 unsigned int fail_ok; 185 int (*hw_fn)(unsigned int); 186 } smbb_charger_attrs[] = { 187 [ATTR_BAT_ISAFE] = { 188 .name = "qcom,fast-charge-safe-current", 189 .reg = SMBB_CHG_ISAFE, 190 .max = 3000000, 191 .min = 200000, 192 .hw_fn = smbb_bat_imax_fn, 193 .fail_ok = 1, 194 }, 195 [ATTR_BAT_IMAX] = { 196 .name = "qcom,fast-charge-current-limit", 197 .reg = SMBB_CHG_IMAX, 198 .safe_reg = SMBB_CHG_ISAFE, 199 .max = 3000000, 200 .min = 200000, 201 .hw_fn = smbb_bat_imax_fn, 202 }, 203 [ATTR_DCIN_IMAX] = { 204 .name = "qcom,dc-current-limit", 205 .reg = SMBB_DC_IMAX, 206 .max = 2500000, 207 .min = 100000, 208 .hw_fn = smbb_imax_fn, 209 }, 210 [ATTR_BAT_VSAFE] = { 211 .name = "qcom,fast-charge-safe-voltage", 212 .reg = SMBB_CHG_VSAFE, 213 .max = 5000000, 214 .min = 3240000, 215 .hw_fn = smbb_vmax_fn, 216 .fail_ok = 1, 217 }, 218 [ATTR_BAT_VMAX] = { 219 .name = "qcom,fast-charge-high-threshold-voltage", 220 .reg = SMBB_CHG_VMAX, 221 .safe_reg = SMBB_CHG_VSAFE, 222 .max = 5000000, 223 .min = 3240000, 224 .hw_fn = smbb_vmax_fn, 225 }, 226 [ATTR_BAT_VMIN] = { 227 .name = "qcom,fast-charge-low-threshold-voltage", 228 .reg = SMBB_CHG_VBAT_WEAK, 229 .max = 3600000, 230 .min = 2100000, 231 .hw_fn = smbb_vbat_weak_fn, 232 }, 233 [ATTR_CHG_VDET] = { 234 .name = "qcom,auto-recharge-threshold-voltage", 235 .reg = SMBB_CHG_VBAT_DET, 236 .max = 5000000, 237 .min = 3240000, 238 .hw_fn = smbb_vbat_det_fn, 239 }, 240 [ATTR_VIN_MIN] = { 241 .name = "qcom,minimum-input-voltage", 242 .reg = SMBB_CHG_VIN_MIN, 243 .max = 9600000, 244 .min = 4200000, 245 .hw_fn = smbb_vin_fn, 246 }, 247 [ATTR_USBIN_IMAX] = { 248 .name = "usb-charge-current-limit", 249 .reg = SMBB_USB_IMAX, 250 .max = 2500000, 251 .min = 100000, 252 .hw_fn = smbb_imax_fn, 253 }, 254 }; 255 256 static int smbb_charger_attr_write(struct smbb_charger *chg, 257 enum smbb_attr which, unsigned int val) 258 { 259 const struct smbb_charger_attr *prop; 260 unsigned int wval; 261 unsigned int out; 262 int rc; 263 264 prop = &smbb_charger_attrs[which]; 265 266 if (val > prop->max || val < prop->min) { 267 dev_err(chg->dev, "value out of range for %s [%u:%u]\n", 268 prop->name, prop->min, prop->max); 269 return -EINVAL; 270 } 271 272 if (prop->safe_reg) { 273 rc = regmap_read(chg->regmap, 274 chg->addr + prop->safe_reg, &wval); 275 if (rc) { 276 dev_err(chg->dev, 277 "unable to read safe value for '%s'\n", 278 prop->name); 279 return rc; 280 } 281 282 wval = prop->hw_fn(wval); 283 284 if (val > wval) { 285 dev_warn(chg->dev, 286 "%s above safe value, clamping at %u\n", 287 prop->name, wval); 288 val = wval; 289 } 290 } 291 292 wval = smbb_hw_lookup(val, prop->hw_fn); 293 294 rc = regmap_write(chg->regmap, chg->addr + prop->reg, wval); 295 if (rc) { 296 dev_err(chg->dev, "unable to update %s", prop->name); 297 return rc; 298 } 299 out = prop->hw_fn(wval); 300 if (out != val) { 301 dev_warn(chg->dev, 302 "%s inaccurate, rounded to %u\n", 303 prop->name, out); 304 } 305 306 dev_dbg(chg->dev, "%s <= %d\n", prop->name, out); 307 308 chg->attr[which] = out; 309 310 return 0; 311 } 312 313 static int smbb_charger_attr_read(struct smbb_charger *chg, 314 enum smbb_attr which) 315 { 316 const struct smbb_charger_attr *prop; 317 unsigned int val; 318 int rc; 319 320 prop = &smbb_charger_attrs[which]; 321 322 rc = regmap_read(chg->regmap, chg->addr + prop->reg, &val); 323 if (rc) { 324 dev_err(chg->dev, "failed to read %s\n", prop->name); 325 return rc; 326 } 327 val = prop->hw_fn(val); 328 dev_dbg(chg->dev, "%s => %d\n", prop->name, val); 329 330 chg->attr[which] = val; 331 332 return 0; 333 } 334 335 static int smbb_charger_attr_parse(struct smbb_charger *chg, 336 enum smbb_attr which) 337 { 338 const struct smbb_charger_attr *prop; 339 unsigned int val; 340 int rc; 341 342 prop = &smbb_charger_attrs[which]; 343 344 rc = of_property_read_u32(chg->dev->of_node, prop->name, &val); 345 if (rc == 0) { 346 rc = smbb_charger_attr_write(chg, which, val); 347 if (!rc || !prop->fail_ok) 348 return rc; 349 } 350 return smbb_charger_attr_read(chg, which); 351 } 352 353 static void smbb_set_line_flag(struct smbb_charger *chg, int irq, int flag) 354 { 355 bool state; 356 int ret; 357 358 ret = irq_get_irqchip_state(irq, IRQCHIP_STATE_LINE_LEVEL, &state); 359 if (ret < 0) { 360 dev_err(chg->dev, "failed to read irq line\n"); 361 return; 362 } 363 364 mutex_lock(&chg->statlock); 365 if (state) 366 chg->status |= flag; 367 else 368 chg->status &= ~flag; 369 mutex_unlock(&chg->statlock); 370 371 dev_dbg(chg->dev, "status = %03lx\n", chg->status); 372 } 373 374 static irqreturn_t smbb_usb_valid_handler(int irq, void *_data) 375 { 376 struct smbb_charger *chg = _data; 377 378 smbb_set_line_flag(chg, irq, STATUS_USBIN_VALID); 379 extcon_set_state_sync(chg->edev, EXTCON_USB, 380 chg->status & STATUS_USBIN_VALID); 381 power_supply_changed(chg->usb_psy); 382 383 return IRQ_HANDLED; 384 } 385 386 static irqreturn_t smbb_dc_valid_handler(int irq, void *_data) 387 { 388 struct smbb_charger *chg = _data; 389 390 smbb_set_line_flag(chg, irq, STATUS_DCIN_VALID); 391 if (!chg->dc_disabled) 392 power_supply_changed(chg->dc_psy); 393 394 return IRQ_HANDLED; 395 } 396 397 static irqreturn_t smbb_bat_temp_handler(int irq, void *_data) 398 { 399 struct smbb_charger *chg = _data; 400 unsigned int val; 401 int rc; 402 403 rc = regmap_read(chg->regmap, chg->addr + SMBB_BAT_TEMP_STATUS, &val); 404 if (rc) 405 return IRQ_HANDLED; 406 407 mutex_lock(&chg->statlock); 408 if (val & TEMP_STATUS_OK) { 409 chg->status |= STATUS_BAT_OK; 410 } else { 411 chg->status &= ~STATUS_BAT_OK; 412 if (val & TEMP_STATUS_HOT) 413 chg->status |= STATUS_BAT_HOT; 414 } 415 mutex_unlock(&chg->statlock); 416 417 power_supply_changed(chg->bat_psy); 418 return IRQ_HANDLED; 419 } 420 421 static irqreturn_t smbb_bat_present_handler(int irq, void *_data) 422 { 423 struct smbb_charger *chg = _data; 424 425 smbb_set_line_flag(chg, irq, STATUS_BAT_PRESENT); 426 power_supply_changed(chg->bat_psy); 427 428 return IRQ_HANDLED; 429 } 430 431 static irqreturn_t smbb_chg_done_handler(int irq, void *_data) 432 { 433 struct smbb_charger *chg = _data; 434 435 smbb_set_line_flag(chg, irq, STATUS_CHG_DONE); 436 power_supply_changed(chg->bat_psy); 437 438 return IRQ_HANDLED; 439 } 440 441 static irqreturn_t smbb_chg_gone_handler(int irq, void *_data) 442 { 443 struct smbb_charger *chg = _data; 444 445 smbb_set_line_flag(chg, irq, STATUS_CHG_GONE); 446 power_supply_changed(chg->bat_psy); 447 power_supply_changed(chg->usb_psy); 448 if (!chg->dc_disabled) 449 power_supply_changed(chg->dc_psy); 450 451 return IRQ_HANDLED; 452 } 453 454 static irqreturn_t smbb_chg_fast_handler(int irq, void *_data) 455 { 456 struct smbb_charger *chg = _data; 457 458 smbb_set_line_flag(chg, irq, STATUS_CHG_FAST); 459 power_supply_changed(chg->bat_psy); 460 461 return IRQ_HANDLED; 462 } 463 464 static irqreturn_t smbb_chg_trkl_handler(int irq, void *_data) 465 { 466 struct smbb_charger *chg = _data; 467 468 smbb_set_line_flag(chg, irq, STATUS_CHG_TRKL); 469 power_supply_changed(chg->bat_psy); 470 471 return IRQ_HANDLED; 472 } 473 474 static const struct smbb_irq { 475 const char *name; 476 irqreturn_t (*handler)(int, void *); 477 } smbb_charger_irqs[] = { 478 { "chg-done", smbb_chg_done_handler }, 479 { "chg-fast", smbb_chg_fast_handler }, 480 { "chg-trkl", smbb_chg_trkl_handler }, 481 { "bat-temp-ok", smbb_bat_temp_handler }, 482 { "bat-present", smbb_bat_present_handler }, 483 { "chg-gone", smbb_chg_gone_handler }, 484 { "usb-valid", smbb_usb_valid_handler }, 485 { "dc-valid", smbb_dc_valid_handler }, 486 }; 487 488 static int smbb_usbin_get_property(struct power_supply *psy, 489 enum power_supply_property psp, 490 union power_supply_propval *val) 491 { 492 struct smbb_charger *chg = power_supply_get_drvdata(psy); 493 int rc = 0; 494 495 switch (psp) { 496 case POWER_SUPPLY_PROP_ONLINE: 497 mutex_lock(&chg->statlock); 498 val->intval = !(chg->status & STATUS_CHG_GONE) && 499 (chg->status & STATUS_USBIN_VALID); 500 mutex_unlock(&chg->statlock); 501 break; 502 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: 503 val->intval = chg->attr[ATTR_USBIN_IMAX]; 504 break; 505 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX: 506 val->intval = 2500000; 507 break; 508 default: 509 rc = -EINVAL; 510 break; 511 } 512 513 return rc; 514 } 515 516 static int smbb_usbin_set_property(struct power_supply *psy, 517 enum power_supply_property psp, 518 const union power_supply_propval *val) 519 { 520 struct smbb_charger *chg = power_supply_get_drvdata(psy); 521 int rc; 522 523 switch (psp) { 524 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: 525 rc = smbb_charger_attr_write(chg, ATTR_USBIN_IMAX, 526 val->intval); 527 break; 528 default: 529 rc = -EINVAL; 530 break; 531 } 532 533 return rc; 534 } 535 536 static int smbb_dcin_get_property(struct power_supply *psy, 537 enum power_supply_property psp, 538 union power_supply_propval *val) 539 { 540 struct smbb_charger *chg = power_supply_get_drvdata(psy); 541 int rc = 0; 542 543 switch (psp) { 544 case POWER_SUPPLY_PROP_ONLINE: 545 mutex_lock(&chg->statlock); 546 val->intval = !(chg->status & STATUS_CHG_GONE) && 547 (chg->status & STATUS_DCIN_VALID); 548 mutex_unlock(&chg->statlock); 549 break; 550 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: 551 val->intval = chg->attr[ATTR_DCIN_IMAX]; 552 break; 553 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX: 554 val->intval = 2500000; 555 break; 556 default: 557 rc = -EINVAL; 558 break; 559 } 560 561 return rc; 562 } 563 564 static int smbb_dcin_set_property(struct power_supply *psy, 565 enum power_supply_property psp, 566 const union power_supply_propval *val) 567 { 568 struct smbb_charger *chg = power_supply_get_drvdata(psy); 569 int rc; 570 571 switch (psp) { 572 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: 573 rc = smbb_charger_attr_write(chg, ATTR_DCIN_IMAX, 574 val->intval); 575 break; 576 default: 577 rc = -EINVAL; 578 break; 579 } 580 581 return rc; 582 } 583 584 static int smbb_charger_writable_property(struct power_supply *psy, 585 enum power_supply_property psp) 586 { 587 return psp == POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT; 588 } 589 590 static int smbb_battery_get_property(struct power_supply *psy, 591 enum power_supply_property psp, 592 union power_supply_propval *val) 593 { 594 struct smbb_charger *chg = power_supply_get_drvdata(psy); 595 unsigned long status; 596 int rc = 0; 597 598 mutex_lock(&chg->statlock); 599 status = chg->status; 600 mutex_unlock(&chg->statlock); 601 602 switch (psp) { 603 case POWER_SUPPLY_PROP_STATUS: 604 if (status & STATUS_CHG_GONE) 605 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 606 else if (!(status & (STATUS_DCIN_VALID | STATUS_USBIN_VALID))) 607 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 608 else if (status & STATUS_CHG_DONE) 609 val->intval = POWER_SUPPLY_STATUS_FULL; 610 else if (!(status & STATUS_BAT_OK)) 611 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 612 else if (status & (STATUS_CHG_FAST | STATUS_CHG_TRKL)) 613 val->intval = POWER_SUPPLY_STATUS_CHARGING; 614 else /* everything is ok for charging, but we are not... */ 615 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 616 break; 617 case POWER_SUPPLY_PROP_HEALTH: 618 if (status & STATUS_BAT_OK) 619 val->intval = POWER_SUPPLY_HEALTH_GOOD; 620 else if (status & STATUS_BAT_HOT) 621 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; 622 else 623 val->intval = POWER_SUPPLY_HEALTH_COLD; 624 break; 625 case POWER_SUPPLY_PROP_CHARGE_TYPE: 626 if (status & STATUS_CHG_FAST) 627 val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; 628 else if (status & STATUS_CHG_TRKL) 629 val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; 630 else 631 val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; 632 break; 633 case POWER_SUPPLY_PROP_PRESENT: 634 val->intval = !!(status & STATUS_BAT_PRESENT); 635 break; 636 case POWER_SUPPLY_PROP_CURRENT_MAX: 637 val->intval = chg->attr[ATTR_BAT_IMAX]; 638 break; 639 case POWER_SUPPLY_PROP_VOLTAGE_MAX: 640 val->intval = chg->attr[ATTR_BAT_VMAX]; 641 break; 642 case POWER_SUPPLY_PROP_TECHNOLOGY: 643 /* this charger is a single-cell lithium-ion battery charger 644 * only. If you hook up some other technology, there will be 645 * fireworks. 646 */ 647 val->intval = POWER_SUPPLY_TECHNOLOGY_LION; 648 break; 649 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 650 val->intval = 3000000; /* single-cell li-ion low end */ 651 break; 652 default: 653 rc = -EINVAL; 654 break; 655 } 656 657 return rc; 658 } 659 660 static int smbb_battery_set_property(struct power_supply *psy, 661 enum power_supply_property psp, 662 const union power_supply_propval *val) 663 { 664 struct smbb_charger *chg = power_supply_get_drvdata(psy); 665 int rc; 666 667 switch (psp) { 668 case POWER_SUPPLY_PROP_CURRENT_MAX: 669 rc = smbb_charger_attr_write(chg, ATTR_BAT_IMAX, val->intval); 670 break; 671 case POWER_SUPPLY_PROP_VOLTAGE_MAX: 672 rc = smbb_charger_attr_write(chg, ATTR_BAT_VMAX, val->intval); 673 break; 674 default: 675 rc = -EINVAL; 676 break; 677 } 678 679 return rc; 680 } 681 682 static int smbb_battery_writable_property(struct power_supply *psy, 683 enum power_supply_property psp) 684 { 685 switch (psp) { 686 case POWER_SUPPLY_PROP_CURRENT_MAX: 687 case POWER_SUPPLY_PROP_VOLTAGE_MAX: 688 return 1; 689 default: 690 return 0; 691 } 692 } 693 694 static enum power_supply_property smbb_charger_properties[] = { 695 POWER_SUPPLY_PROP_ONLINE, 696 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, 697 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, 698 }; 699 700 static enum power_supply_property smbb_battery_properties[] = { 701 POWER_SUPPLY_PROP_STATUS, 702 POWER_SUPPLY_PROP_HEALTH, 703 POWER_SUPPLY_PROP_PRESENT, 704 POWER_SUPPLY_PROP_CHARGE_TYPE, 705 POWER_SUPPLY_PROP_CURRENT_MAX, 706 POWER_SUPPLY_PROP_VOLTAGE_MAX, 707 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, 708 POWER_SUPPLY_PROP_TECHNOLOGY, 709 }; 710 711 static const struct reg_off_mask_default { 712 unsigned int offset; 713 unsigned int mask; 714 unsigned int value; 715 unsigned int rev_mask; 716 } smbb_charger_setup[] = { 717 /* The bootloader is supposed to set this... make sure anyway. */ 718 { SMBB_MISC_BOOT_DONE, BOOT_DONE, BOOT_DONE }, 719 720 /* Disable software timer */ 721 { SMBB_CHG_TCHG_MAX_EN, TCHG_MAX_EN, 0 }, 722 723 /* Clear and disable watchdog */ 724 { SMBB_CHG_WDOG_TIME, 0xff, 160 }, 725 { SMBB_CHG_WDOG_EN, WDOG_EN, 0 }, 726 727 /* Use charger based EoC detection */ 728 { SMBB_CHG_IBAT_TERM_CHG, IBAT_TERM_CHG_IEOC, IBAT_TERM_CHG_IEOC_CHG }, 729 730 /* Disable GSM PA load adjustment. 731 * The PA signal is incorrectly connected on v2. 732 */ 733 { SMBB_CHG_CFG, 0xff, 0x00, BIT(3) }, 734 735 /* Use VBAT (not VSYS) to compensate for IR drop during fast charging */ 736 { SMBB_BUCK_REG_MODE, BUCK_REG_MODE, BUCK_REG_MODE_VBAT }, 737 738 /* Enable battery temperature comparators */ 739 { SMBB_BAT_BTC_CTRL, BTC_CTRL_COMP_EN, BTC_CTRL_COMP_EN }, 740 741 /* Stop USB enumeration timer */ 742 { SMBB_USB_ENUM_TIMER_STOP, ENUM_TIMER_STOP, ENUM_TIMER_STOP }, 743 744 #if 0 /* FIXME supposedly only to disable hardware ARB termination */ 745 { SMBB_USB_SEC_ACCESS, SEC_ACCESS_MAGIC }, 746 { SMBB_USB_REV_BST, 0xff, REV_BST_CHG_GONE }, 747 #endif 748 749 /* Stop USB enumeration timer, again */ 750 { SMBB_USB_ENUM_TIMER_STOP, ENUM_TIMER_STOP, ENUM_TIMER_STOP }, 751 752 /* Enable charging */ 753 { SMBB_CHG_CTRL, CTRL_EN, CTRL_EN }, 754 }; 755 756 static char *smbb_bif[] = { "smbb-bif" }; 757 758 static const struct power_supply_desc bat_psy_desc = { 759 .name = "smbb-bif", 760 .type = POWER_SUPPLY_TYPE_BATTERY, 761 .properties = smbb_battery_properties, 762 .num_properties = ARRAY_SIZE(smbb_battery_properties), 763 .get_property = smbb_battery_get_property, 764 .set_property = smbb_battery_set_property, 765 .property_is_writeable = smbb_battery_writable_property, 766 }; 767 768 static const struct power_supply_desc usb_psy_desc = { 769 .name = "smbb-usbin", 770 .type = POWER_SUPPLY_TYPE_USB, 771 .properties = smbb_charger_properties, 772 .num_properties = ARRAY_SIZE(smbb_charger_properties), 773 .get_property = smbb_usbin_get_property, 774 .set_property = smbb_usbin_set_property, 775 .property_is_writeable = smbb_charger_writable_property, 776 }; 777 778 static const struct power_supply_desc dc_psy_desc = { 779 .name = "smbb-dcin", 780 .type = POWER_SUPPLY_TYPE_MAINS, 781 .properties = smbb_charger_properties, 782 .num_properties = ARRAY_SIZE(smbb_charger_properties), 783 .get_property = smbb_dcin_get_property, 784 .set_property = smbb_dcin_set_property, 785 .property_is_writeable = smbb_charger_writable_property, 786 }; 787 788 static int smbb_chg_otg_enable(struct regulator_dev *rdev) 789 { 790 struct smbb_charger *chg = rdev_get_drvdata(rdev); 791 int rc; 792 793 rc = regmap_update_bits(chg->regmap, chg->addr + SMBB_USB_OTG_CTL, 794 OTG_CTL_EN, OTG_CTL_EN); 795 if (rc) 796 dev_err(chg->dev, "failed to update OTG_CTL\n"); 797 return rc; 798 } 799 800 static int smbb_chg_otg_disable(struct regulator_dev *rdev) 801 { 802 struct smbb_charger *chg = rdev_get_drvdata(rdev); 803 int rc; 804 805 rc = regmap_update_bits(chg->regmap, chg->addr + SMBB_USB_OTG_CTL, 806 OTG_CTL_EN, 0); 807 if (rc) 808 dev_err(chg->dev, "failed to update OTG_CTL\n"); 809 return rc; 810 } 811 812 static int smbb_chg_otg_is_enabled(struct regulator_dev *rdev) 813 { 814 struct smbb_charger *chg = rdev_get_drvdata(rdev); 815 unsigned int value = 0; 816 int rc; 817 818 rc = regmap_read(chg->regmap, chg->addr + SMBB_USB_OTG_CTL, &value); 819 if (rc) 820 dev_err(chg->dev, "failed to read OTG_CTL\n"); 821 822 return !!(value & OTG_CTL_EN); 823 } 824 825 static const struct regulator_ops smbb_chg_otg_ops = { 826 .enable = smbb_chg_otg_enable, 827 .disable = smbb_chg_otg_disable, 828 .is_enabled = smbb_chg_otg_is_enabled, 829 }; 830 831 static int smbb_charger_probe(struct platform_device *pdev) 832 { 833 struct power_supply_config bat_cfg = {}; 834 struct power_supply_config usb_cfg = {}; 835 struct power_supply_config dc_cfg = {}; 836 struct smbb_charger *chg; 837 struct regulator_config config = { }; 838 int rc, i; 839 840 chg = devm_kzalloc(&pdev->dev, sizeof(*chg), GFP_KERNEL); 841 if (!chg) 842 return -ENOMEM; 843 844 chg->dev = &pdev->dev; 845 mutex_init(&chg->statlock); 846 847 chg->regmap = dev_get_regmap(pdev->dev.parent, NULL); 848 if (!chg->regmap) { 849 dev_err(&pdev->dev, "failed to locate regmap\n"); 850 return -ENODEV; 851 } 852 853 rc = of_property_read_u32(pdev->dev.of_node, "reg", &chg->addr); 854 if (rc) { 855 dev_err(&pdev->dev, "missing or invalid 'reg' property\n"); 856 return rc; 857 } 858 859 rc = regmap_read(chg->regmap, chg->addr + SMBB_MISC_REV2, &chg->revision); 860 if (rc) { 861 dev_err(&pdev->dev, "unable to read revision\n"); 862 return rc; 863 } 864 865 chg->revision += 1; 866 if (chg->revision != 1 && chg->revision != 2 && chg->revision != 3) { 867 dev_err(&pdev->dev, "v%d hardware not supported\n", chg->revision); 868 return -ENODEV; 869 } 870 dev_info(&pdev->dev, "Initializing SMBB rev %u", chg->revision); 871 872 chg->dc_disabled = of_property_read_bool(pdev->dev.of_node, "qcom,disable-dc"); 873 874 for (i = 0; i < _ATTR_CNT; ++i) { 875 rc = smbb_charger_attr_parse(chg, i); 876 if (rc) { 877 dev_err(&pdev->dev, "failed to parse/apply settings\n"); 878 return rc; 879 } 880 } 881 882 bat_cfg.drv_data = chg; 883 bat_cfg.of_node = pdev->dev.of_node; 884 chg->bat_psy = devm_power_supply_register(&pdev->dev, 885 &bat_psy_desc, 886 &bat_cfg); 887 if (IS_ERR(chg->bat_psy)) { 888 dev_err(&pdev->dev, "failed to register battery\n"); 889 return PTR_ERR(chg->bat_psy); 890 } 891 892 usb_cfg.drv_data = chg; 893 usb_cfg.supplied_to = smbb_bif; 894 usb_cfg.num_supplicants = ARRAY_SIZE(smbb_bif); 895 chg->usb_psy = devm_power_supply_register(&pdev->dev, 896 &usb_psy_desc, 897 &usb_cfg); 898 if (IS_ERR(chg->usb_psy)) { 899 dev_err(&pdev->dev, "failed to register USB power supply\n"); 900 return PTR_ERR(chg->usb_psy); 901 } 902 903 chg->edev = devm_extcon_dev_allocate(&pdev->dev, smbb_usb_extcon_cable); 904 if (IS_ERR(chg->edev)) { 905 dev_err(&pdev->dev, "failed to allocate extcon device\n"); 906 return -ENOMEM; 907 } 908 909 rc = devm_extcon_dev_register(&pdev->dev, chg->edev); 910 if (rc < 0) { 911 dev_err(&pdev->dev, "failed to register extcon device\n"); 912 return rc; 913 } 914 915 if (!chg->dc_disabled) { 916 dc_cfg.drv_data = chg; 917 dc_cfg.supplied_to = smbb_bif; 918 dc_cfg.num_supplicants = ARRAY_SIZE(smbb_bif); 919 chg->dc_psy = devm_power_supply_register(&pdev->dev, 920 &dc_psy_desc, 921 &dc_cfg); 922 if (IS_ERR(chg->dc_psy)) { 923 dev_err(&pdev->dev, "failed to register DC power supply\n"); 924 return PTR_ERR(chg->dc_psy); 925 } 926 } 927 928 for (i = 0; i < ARRAY_SIZE(smbb_charger_irqs); ++i) { 929 int irq; 930 931 irq = platform_get_irq_byname(pdev, smbb_charger_irqs[i].name); 932 if (irq < 0) 933 return irq; 934 935 smbb_charger_irqs[i].handler(irq, chg); 936 937 rc = devm_request_threaded_irq(&pdev->dev, irq, NULL, 938 smbb_charger_irqs[i].handler, IRQF_ONESHOT, 939 smbb_charger_irqs[i].name, chg); 940 if (rc) { 941 dev_err(&pdev->dev, "failed to request irq '%s'\n", 942 smbb_charger_irqs[i].name); 943 return rc; 944 } 945 } 946 947 /* 948 * otg regulator is used to control VBUS voltage direction 949 * when USB switches between host and gadget mode 950 */ 951 chg->otg_rdesc.id = -1; 952 chg->otg_rdesc.name = "otg-vbus"; 953 chg->otg_rdesc.ops = &smbb_chg_otg_ops; 954 chg->otg_rdesc.owner = THIS_MODULE; 955 chg->otg_rdesc.type = REGULATOR_VOLTAGE; 956 chg->otg_rdesc.supply_name = "usb-otg-in"; 957 chg->otg_rdesc.of_match = "otg-vbus"; 958 959 config.dev = &pdev->dev; 960 config.driver_data = chg; 961 962 chg->otg_reg = devm_regulator_register(&pdev->dev, &chg->otg_rdesc, 963 &config); 964 if (IS_ERR(chg->otg_reg)) 965 return PTR_ERR(chg->otg_reg); 966 967 chg->jeita_ext_temp = of_property_read_bool(pdev->dev.of_node, 968 "qcom,jeita-extended-temp-range"); 969 970 /* Set temperature range to [35%:70%] or [25%:80%] accordingly */ 971 rc = regmap_update_bits(chg->regmap, chg->addr + SMBB_BAT_BTC_CTRL, 972 BTC_CTRL_COLD_EXT | BTC_CTRL_HOT_EXT_N, 973 chg->jeita_ext_temp ? 974 BTC_CTRL_COLD_EXT : 975 BTC_CTRL_HOT_EXT_N); 976 if (rc) { 977 dev_err(&pdev->dev, 978 "unable to set %s temperature range\n", 979 chg->jeita_ext_temp ? "JEITA extended" : "normal"); 980 return rc; 981 } 982 983 for (i = 0; i < ARRAY_SIZE(smbb_charger_setup); ++i) { 984 const struct reg_off_mask_default *r = &smbb_charger_setup[i]; 985 986 if (r->rev_mask & BIT(chg->revision)) 987 continue; 988 989 rc = regmap_update_bits(chg->regmap, chg->addr + r->offset, 990 r->mask, r->value); 991 if (rc) { 992 dev_err(&pdev->dev, 993 "unable to initializing charging, bailing\n"); 994 return rc; 995 } 996 } 997 998 platform_set_drvdata(pdev, chg); 999 1000 return 0; 1001 } 1002 1003 static void smbb_charger_remove(struct platform_device *pdev) 1004 { 1005 struct smbb_charger *chg; 1006 1007 chg = platform_get_drvdata(pdev); 1008 1009 regmap_update_bits(chg->regmap, chg->addr + SMBB_CHG_CTRL, CTRL_EN, 0); 1010 } 1011 1012 static const struct of_device_id smbb_charger_id_table[] = { 1013 { .compatible = "qcom,pm8226-charger" }, 1014 { .compatible = "qcom,pm8941-charger" }, 1015 { } 1016 }; 1017 MODULE_DEVICE_TABLE(of, smbb_charger_id_table); 1018 1019 static struct platform_driver smbb_charger_driver = { 1020 .probe = smbb_charger_probe, 1021 .remove_new = smbb_charger_remove, 1022 .driver = { 1023 .name = "qcom-smbb", 1024 .of_match_table = smbb_charger_id_table, 1025 }, 1026 }; 1027 module_platform_driver(smbb_charger_driver); 1028 1029 MODULE_DESCRIPTION("Qualcomm Switch-Mode Battery Charger and Boost driver"); 1030 MODULE_LICENSE("GPL v2"); 1031