Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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