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