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