FILE
bq257xx_charger.c
File preview with syntax highlighting.
linux-6.19.14/drivers/power/supply/bq257xx_charger.c
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * BQ257XX Battery Charger Driver 4 * Copyright (C) 2025 Chris Morgan <macromorgan@hotmail.com> 5 */ 6 7#include <linux/bitfield.h> 8#include <linux/i2c.h> 9#include <linux/interrupt.h> 10#include <linux/mfd/bq257xx.h> 11#include <linux/platform_device.h> 12#include <linux/power_supply.h> 13#include <linux/property.h> 14#include <linux/regmap.h> 15 16/* Forward declaration of driver data. */ 17struct bq257xx_chg; 18 19/** 20 * struct bq257xx_chip_info - chip specific routines 21 * @bq257xx_hw_init: init function for hw 22 * @bq257xx_hw_shutdown: shutdown function for hw 23 * @bq257xx_get_state: get and update state of hardware 24 * @bq257xx_set_ichg: set maximum charge current (in uA) 25 * @bq257xx_set_vbatreg: set maximum charge voltage (in uV) 26 * @bq257xx_set_iindpm: set maximum input current (in uA) 27 */ 28struct bq257xx_chip_info { 29 int (*bq257xx_hw_init)(struct bq257xx_chg *pdata); 30 void (*bq257xx_hw_shutdown)(struct bq257xx_chg *pdata); 31 int (*bq257xx_get_state)(struct bq257xx_chg *pdata); 32 int (*bq257xx_set_ichg)(struct bq257xx_chg *pdata, int ichg); 33 int (*bq257xx_set_vbatreg)(struct bq257xx_chg *pdata, int vbatreg); 34 int (*bq257xx_set_iindpm)(struct bq257xx_chg *pdata, int iindpm); 35}; 36 37/** 38 * struct bq257xx_chg - driver data for charger 39 * @chip: hw specific functions 40 * @bq: parent MFD device 41 * @charger: power supply device 42 * @online: charger input is present 43 * @fast_charge: charger is in fast charge mode 44 * @pre_charge: charger is in pre-charge mode 45 * @ov_fault: charger reports over voltage fault 46 * @batoc_fault: charger reports battery over current fault 47 * @oc_fault: charger reports over current fault 48 * @usb_type: USB type reported from parent power supply 49 * @supplied: Status of parent power supply 50 * @iindpm_max: maximum input current limit (uA) 51 * @vbat_max: maximum charge voltage (uV) 52 * @ichg_max: maximum charge current (uA) 53 * @vsys_min: minimum system voltage (uV) 54 */ 55struct bq257xx_chg { 56 const struct bq257xx_chip_info *chip; 57 struct bq257xx_device *bq; 58 struct power_supply *charger; 59 bool online; 60 bool fast_charge; 61 bool pre_charge; 62 bool ov_fault; 63 bool batoc_fault; 64 bool oc_fault; 65 int usb_type; 66 int supplied; 67 u32 iindpm_max; 68 u32 vbat_max; 69 u32 ichg_max; 70 u32 vsys_min; 71}; 72 73/** 74 * bq25703_get_state() - Get the current state of the device 75 * @pdata: driver platform data 76 * 77 * Get the current state of the charger. Check if the charger is 78 * powered, what kind of charge state (if any) the device is in, 79 * and if there are any active faults. 80 * 81 * Return: Returns 0 on success, or error on failure to read device. 82 */ 83static int bq25703_get_state(struct bq257xx_chg *pdata) 84{ 85 unsigned int reg; 86 int ret; 87 88 ret = regmap_read(pdata->bq->regmap, BQ25703_CHARGER_STATUS, ®); 89 if (ret) 90 return ret; 91 92 pdata->online = reg & BQ25703_STS_AC_STAT; 93 pdata->fast_charge = reg & BQ25703_STS_IN_FCHRG; 94 pdata->pre_charge = reg & BQ25703_STS_IN_PCHRG; 95 pdata->ov_fault = reg & BQ25703_STS_FAULT_ACOV; 96 pdata->batoc_fault = reg & BQ25703_STS_FAULT_BATOC; 97 pdata->oc_fault = reg & BQ25703_STS_FAULT_ACOC; 98 99 return 0; 100} 101 102/** 103 * bq25703_get_min_vsys() - Get the minimum system voltage 104 * @pdata: driver platform data 105 * @intval: value for minimum voltage 106 * 107 * Return: Returns 0 on success or error on failure to read. 108 */ 109static int bq25703_get_min_vsys(struct bq257xx_chg *pdata, int *intval) 110{ 111 unsigned int reg; 112 int ret; 113 114 ret = regmap_read(pdata->bq->regmap, BQ25703_MIN_VSYS, 115 ®); 116 if (ret) 117 return ret; 118 119 reg = FIELD_GET(BQ25703_MINVSYS_MASK, reg); 120 *intval = (reg * BQ25703_MINVSYS_STEP_UV) + BQ25703_MINVSYS_MIN_UV; 121 122 return ret; 123} 124 125/** 126 * bq25703_set_min_vsys() - Set the minimum system voltage 127 * @pdata: driver platform data 128 * @vsys: voltage value to set in uV. 129 * 130 * This function takes a requested minimum system voltage value, clamps 131 * it between the minimum supported value by the charger and a user 132 * defined minimum system value, and then writes the value to the 133 * appropriate register. 134 * 135 * Return: Returns 0 on success or error if an error occurs. 136 */ 137static int bq25703_set_min_vsys(struct bq257xx_chg *pdata, int vsys) 138{ 139 unsigned int reg; 140 int vsys_min = pdata->vsys_min; 141 142 vsys = clamp(vsys, BQ25703_MINVSYS_MIN_UV, vsys_min); 143 reg = ((vsys - BQ25703_MINVSYS_MIN_UV) / BQ25703_MINVSYS_STEP_UV); 144 reg = FIELD_PREP(BQ25703_MINVSYS_MASK, reg); 145 146 return regmap_write(pdata->bq->regmap, BQ25703_MIN_VSYS, 147 reg); 148} 149 150/** 151 * bq25703_get_cur() - Get the reported current from the battery 152 * @pdata: driver platform data 153 * @intval: value of reported battery current 154 * 155 * Read the reported current from the battery. Since value is always 156 * positive set sign to negative if discharging. 157 * 158 * Return: Returns 0 on success or error if unable to read value. 159 */ 160static int bq25703_get_cur(struct bq257xx_chg *pdata, int *intval) 161{ 162 unsigned int reg; 163 int ret; 164 165 ret = regmap_read(pdata->bq->regmap, BQ25703_ADCIBAT_CHG, ®); 166 if (ret < 0) 167 return ret; 168 169 if (pdata->online) 170 *intval = FIELD_GET(BQ25703_ADCIBAT_CHG_MASK, reg) * 171 BQ25703_ADCIBAT_CHG_STEP_UA; 172 else 173 *intval = -(FIELD_GET(BQ25703_ADCIBAT_DISCHG_MASK, reg) * 174 BQ25703_ADCIBAT_DIS_STEP_UA); 175 176 return ret; 177} 178 179/** 180 * bq25703_get_ichg_cur() - Get the maximum reported charge current 181 * @pdata: driver platform data 182 * @intval: value of maximum reported charge current 183 * 184 * Get the maximum reported charge current from the battery. 185 * 186 * Return: Returns 0 on success or error if unable to read value. 187 */ 188static int bq25703_get_ichg_cur(struct bq257xx_chg *pdata, int *intval) 189{ 190 unsigned int reg; 191 int ret; 192 193 ret = regmap_read(pdata->bq->regmap, BQ25703_CHARGE_CURRENT, ®); 194 if (ret) 195 return ret; 196 197 *intval = FIELD_GET(BQ25703_ICHG_MASK, reg) * BQ25703_ICHG_STEP_UA; 198 199 return ret; 200} 201 202/** 203 * bq25703_set_ichg_cur() - Set the maximum charge current 204 * @pdata: driver platform data 205 * @ichg: current value to set in uA. 206 * 207 * This function takes a requested maximum charge current value, clamps 208 * it between the minimum supported value by the charger and a user 209 * defined maximum charging value, and then writes the value to the 210 * appropriate register. 211 * 212 * Return: Returns 0 on success or error if an error occurs. 213 */ 214static int bq25703_set_ichg_cur(struct bq257xx_chg *pdata, int ichg) 215{ 216 unsigned int reg; 217 int ichg_max = pdata->ichg_max; 218 219 ichg = clamp(ichg, BQ25703_ICHG_MIN_UA, ichg_max); 220 reg = FIELD_PREP(BQ25703_ICHG_MASK, (ichg / BQ25703_ICHG_STEP_UA)); 221 222 return regmap_write(pdata->bq->regmap, BQ25703_CHARGE_CURRENT, 223 reg); 224} 225 226/** 227 * bq25703_get_chrg_volt() - Get the maximum set charge voltage 228 * @pdata: driver platform data 229 * @intval: maximum charge voltage value 230 * 231 * Return: Returns 0 on success or error if unable to read value. 232 */ 233static int bq25703_get_chrg_volt(struct bq257xx_chg *pdata, int *intval) 234{ 235 unsigned int reg; 236 int ret; 237 238 ret = regmap_read(pdata->bq->regmap, BQ25703_MAX_CHARGE_VOLT, 239 ®); 240 if (ret) 241 return ret; 242 243 *intval = FIELD_GET(BQ25703_MAX_CHARGE_VOLT_MASK, reg) * 244 BQ25703_VBATREG_STEP_UV; 245 246 return ret; 247} 248 249/** 250 * bq25703_set_chrg_volt() - Set the maximum charge voltage 251 * @pdata: driver platform data 252 * @vbat: voltage value to set in uV. 253 * 254 * This function takes a requested maximum charge voltage value, clamps 255 * it between the minimum supported value by the charger and a user 256 * defined maximum charging value, and then writes the value to the 257 * appropriate register. 258 * 259 * Return: Returns 0 on success or error if an error occurs. 260 */ 261static int bq25703_set_chrg_volt(struct bq257xx_chg *pdata, int vbat) 262{ 263 unsigned int reg; 264 int vbat_max = pdata->vbat_max; 265 266 vbat = clamp(vbat, BQ25703_VBATREG_MIN_UV, vbat_max); 267 268 reg = FIELD_PREP(BQ25703_MAX_CHARGE_VOLT_MASK, 269 (vbat / BQ25703_VBATREG_STEP_UV)); 270 271 return regmap_write(pdata->bq->regmap, BQ25703_MAX_CHARGE_VOLT, 272 reg); 273} 274 275/** 276 * bq25703_get_iindpm() - Get the maximum set input current 277 * @pdata: driver platform data 278 * @intval: maximum input current value 279 * 280 * Read the actual input current limit from the device into intval. 281 * This can differ from the value programmed due to some autonomous 282 * functions that may be enabled (but are not currently). This is why 283 * there is a different register used. 284 * 285 * Return: Returns 0 on success or error if unable to read register 286 * value. 287 */ 288static int bq25703_get_iindpm(struct bq257xx_chg *pdata, int *intval) 289{ 290 unsigned int reg; 291 int ret; 292 293 ret = regmap_read(pdata->bq->regmap, BQ25703_IIN_DPM, ®); 294 if (ret) 295 return ret; 296 297 reg = FIELD_GET(BQ25703_IINDPM_MASK, reg); 298 *intval = (reg * BQ25703_IINDPM_STEP_UA) + BQ25703_IINDPM_OFFSET_UA; 299 300 return ret; 301} 302 303/** 304 * bq25703_set_iindpm() - Set the maximum input current 305 * @pdata: driver platform data 306 * @iindpm: current value in uA. 307 * 308 * This function takes a requested maximum input current value, clamps 309 * it between the minimum supported value by the charger and a user 310 * defined maximum input value, and then writes the value to the 311 * appropriate register. 312 * 313 * Return: Returns 0 on success or error if an error occurs. 314 */ 315static int bq25703_set_iindpm(struct bq257xx_chg *pdata, int iindpm) 316{ 317 unsigned int reg; 318 int iindpm_max = pdata->iindpm_max; 319 320 iindpm = clamp(iindpm, BQ25703_IINDPM_MIN_UA, iindpm_max); 321 322 reg = ((iindpm - BQ25703_IINDPM_OFFSET_UA) / BQ25703_IINDPM_STEP_UA); 323 324 return regmap_write(pdata->bq->regmap, BQ25703_IIN_HOST, 325 FIELD_PREP(BQ25703_IINDPM_MASK, reg)); 326} 327 328/** 329 * bq25703_get_vbat() - Get the reported voltage from the battery 330 * @pdata: driver platform data 331 * @intval: value of reported battery voltage 332 * 333 * Read value of battery voltage into intval. 334 * 335 * Return: Returns 0 on success or error if unable to read value. 336 */ 337static int bq25703_get_vbat(struct bq257xx_chg *pdata, int *intval) 338{ 339 unsigned int reg; 340 int ret; 341 342 ret = regmap_read(pdata->bq->regmap, BQ25703_ADCVSYSVBAT, ®); 343 if (ret) 344 return ret; 345 346 reg = FIELD_GET(BQ25703_ADCVBAT_MASK, reg); 347 *intval = (reg * BQ25703_ADCVSYSVBAT_STEP) + BQ25703_ADCVSYSVBAT_OFFSET_UV; 348 349 return ret; 350} 351 352/** 353 * bq25703_hw_init() - Set all the required registers to init the charger 354 * @pdata: driver platform data 355 * 356 * Initialize the BQ25703 by first disabling the watchdog timer (which 357 * shuts off the charger in the absence of periodic writes). Then, set 358 * the charge current, charge voltage, minimum system voltage, and 359 * input current limit. Disable low power mode to allow ADCs and 360 * interrupts. Enable the ADC, start the ADC, set the ADC scale to 361 * full, and enable each individual ADC channel. 362 * 363 * Return: Returns 0 on success or error code on error. 364 */ 365static int bq25703_hw_init(struct bq257xx_chg *pdata) 366{ 367 struct regmap *regmap = pdata->bq->regmap; 368 int ret = 0; 369 370 regmap_update_bits(regmap, BQ25703_CHARGE_OPTION_0, 371 BQ25703_WDTMR_ADJ_MASK, 372 FIELD_PREP(BQ25703_WDTMR_ADJ_MASK, 373 BQ25703_WDTMR_DISABLE)); 374 375 ret = pdata->chip->bq257xx_set_ichg(pdata, pdata->ichg_max); 376 if (ret) 377 return ret; 378 379 ret = pdata->chip->bq257xx_set_vbatreg(pdata, pdata->vbat_max); 380 if (ret) 381 return ret; 382 383 ret = bq25703_set_min_vsys(pdata, pdata->vsys_min); 384 if (ret) 385 return ret; 386 387 ret = pdata->chip->bq257xx_set_iindpm(pdata, pdata->iindpm_max); 388 if (ret) 389 return ret; 390 391 /* Disable low power mode by writing 0 to the register. */ 392 regmap_update_bits(regmap, BQ25703_CHARGE_OPTION_0, 393 BQ25703_EN_LWPWR, 0); 394 395 /* Enable the ADC. */ 396 regmap_update_bits(regmap, BQ25703_ADC_OPTION, 397 BQ25703_ADC_CONV_EN, BQ25703_ADC_CONV_EN); 398 399 /* Start the ADC. */ 400 regmap_update_bits(regmap, BQ25703_ADC_OPTION, 401 BQ25703_ADC_START, BQ25703_ADC_START); 402 403 /* Set the scale of the ADC. */ 404 regmap_update_bits(regmap, BQ25703_ADC_OPTION, 405 BQ25703_ADC_FULL_SCALE, BQ25703_ADC_FULL_SCALE); 406 407 /* Enable each of the ADC channels available. */ 408 regmap_update_bits(regmap, BQ25703_ADC_OPTION, 409 BQ25703_ADC_CH_MASK, 410 (BQ25703_ADC_CMPIN_EN | BQ25703_ADC_VBUS_EN | 411 BQ25703_ADC_PSYS_EN | BQ25703_ADC_IIN_EN | 412 BQ25703_ADC_IDCHG_EN | BQ25703_ADC_ICHG_EN | 413 BQ25703_ADC_VSYS_EN | BQ25703_ADC_VBAT_EN)); 414 415 return ret; 416} 417 418/** 419 * bq25703_hw_shutdown() - Set registers for shutdown 420 * @pdata: driver platform data 421 * 422 * Enable low power mode for the device while in shutdown. 423 */ 424static void bq25703_hw_shutdown(struct bq257xx_chg *pdata) 425{ 426 regmap_update_bits(pdata->bq->regmap, BQ25703_CHARGE_OPTION_0, 427 BQ25703_EN_LWPWR, BQ25703_EN_LWPWR); 428} 429 430static int bq257xx_set_charger_property(struct power_supply *psy, 431 enum power_supply_property prop, 432 const union power_supply_propval *val) 433{ 434 struct bq257xx_chg *pdata = power_supply_get_drvdata(psy); 435 436 switch (prop) { 437 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: 438 return pdata->chip->bq257xx_set_iindpm(pdata, val->intval); 439 440 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: 441 return pdata->chip->bq257xx_set_vbatreg(pdata, val->intval); 442 443 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: 444 return pdata->chip->bq257xx_set_ichg(pdata, val->intval); 445 446 default: 447 break; 448 } 449 450 return -EINVAL; 451} 452 453static int bq257xx_get_charger_property(struct power_supply *psy, 454 enum power_supply_property psp, 455 union power_supply_propval *val) 456{ 457 struct bq257xx_chg *pdata = power_supply_get_drvdata(psy); 458 int ret = 0; 459 460 ret = pdata->chip->bq257xx_get_state(pdata); 461 if (ret) 462 return ret; 463 464 switch (psp) { 465 case POWER_SUPPLY_PROP_STATUS: 466 if (!pdata->online) 467 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 468 else if (pdata->fast_charge || pdata->pre_charge) 469 val->intval = POWER_SUPPLY_STATUS_CHARGING; 470 else 471 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; 472 break; 473 474 case POWER_SUPPLY_PROP_HEALTH: 475 if (pdata->ov_fault || pdata->batoc_fault) 476 val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; 477 else if (pdata->oc_fault) 478 val->intval = POWER_SUPPLY_HEALTH_OVERCURRENT; 479 else 480 val->intval = POWER_SUPPLY_HEALTH_GOOD; 481 break; 482 483 case POWER_SUPPLY_PROP_MANUFACTURER: 484 val->strval = "Texas Instruments"; 485 break; 486 487 case POWER_SUPPLY_PROP_ONLINE: 488 val->intval = pdata->online; 489 break; 490 491 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: 492 return bq25703_get_iindpm(pdata, &val->intval); 493 494 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: 495 return bq25703_get_chrg_volt(pdata, &val->intval); 496 497 case POWER_SUPPLY_PROP_CURRENT_NOW: 498 return bq25703_get_cur(pdata, &val->intval); 499 500 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 501 return bq25703_get_vbat(pdata, &val->intval); 502 503 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: 504 return bq25703_get_ichg_cur(pdata, &val->intval); 505 506 case POWER_SUPPLY_PROP_VOLTAGE_MIN: 507 return bq25703_get_min_vsys(pdata, &val->intval); 508 509 case POWER_SUPPLY_PROP_USB_TYPE: 510 val->intval = pdata->usb_type; 511 break; 512 513 default: 514 return -EINVAL; 515 } 516 517 return ret; 518} 519 520static enum power_supply_property bq257xx_power_supply_props[] = { 521 POWER_SUPPLY_PROP_MANUFACTURER, 522 POWER_SUPPLY_PROP_STATUS, 523 POWER_SUPPLY_PROP_ONLINE, 524 POWER_SUPPLY_PROP_HEALTH, 525 POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, 526 POWER_SUPPLY_PROP_CURRENT_NOW, 527 POWER_SUPPLY_PROP_VOLTAGE_NOW, 528 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, 529 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, 530 POWER_SUPPLY_PROP_VOLTAGE_MIN, 531 POWER_SUPPLY_PROP_USB_TYPE, 532}; 533 534static int bq257xx_property_is_writeable(struct power_supply *psy, 535 enum power_supply_property prop) 536{ 537 switch (prop) { 538 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: 539 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: 540 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: 541 return true; 542 default: 543 return false; 544 } 545} 546 547/** 548 * bq257xx_external_power_changed() - Handler for external power change 549 * @psy: Power supply data 550 * 551 * When the external power into the charger is changed, check the USB 552 * type so that it can be reported. Additionally, update the max input 553 * current and max charging current to the value reported if it is a 554 * USB PD charger, otherwise use the default value. Note that each time 555 * a charger is removed the max charge current register is erased, so 556 * it must be set again each time the input changes or the device will 557 * not charge. 558 */ 559static void bq257xx_external_power_changed(struct power_supply *psy) 560{ 561 struct bq257xx_chg *pdata = power_supply_get_drvdata(psy); 562 union power_supply_propval val; 563 int ret; 564 int imax = pdata->iindpm_max; 565 566 pdata->chip->bq257xx_get_state(pdata); 567 568 pdata->supplied = power_supply_am_i_supplied(pdata->charger); 569 if (pdata->supplied < 0) 570 return; 571 572 if (pdata->supplied == 0) 573 goto out; 574 575 ret = power_supply_get_property_from_supplier(psy, 576 POWER_SUPPLY_PROP_USB_TYPE, 577 &val); 578 if (ret) 579 return; 580 581 pdata->usb_type = val.intval; 582 583 if ((pdata->usb_type == POWER_SUPPLY_USB_TYPE_PD) || 584 (pdata->usb_type == POWER_SUPPLY_USB_TYPE_PD_DRP) || 585 (pdata->usb_type == POWER_SUPPLY_USB_TYPE_PD_PPS)) { 586 ret = power_supply_get_property_from_supplier(psy, 587 POWER_SUPPLY_PROP_CURRENT_MAX, 588 &val); 589 if (ret) 590 return; 591 592 if (val.intval) 593 imax = val.intval; 594 } 595 596 if (pdata->supplied) { 597 pdata->chip->bq257xx_set_ichg(pdata, pdata->ichg_max); 598 pdata->chip->bq257xx_set_iindpm(pdata, imax); 599 pdata->chip->bq257xx_set_vbatreg(pdata, pdata->vbat_max); 600 } 601 602out: 603 power_supply_changed(psy); 604} 605 606static irqreturn_t bq257xx_irq_handler_thread(int irq, void *private) 607{ 608 struct bq257xx_chg *pdata = private; 609 610 bq257xx_external_power_changed(pdata->charger); 611 return IRQ_HANDLED; 612} 613 614static const struct power_supply_desc bq257xx_power_supply_desc = { 615 .name = "bq257xx-charger", 616 .type = POWER_SUPPLY_TYPE_USB, 617 .usb_types = BIT(POWER_SUPPLY_USB_TYPE_C) | 618 BIT(POWER_SUPPLY_USB_TYPE_PD) | 619 BIT(POWER_SUPPLY_USB_TYPE_PD_DRP) | 620 BIT(POWER_SUPPLY_USB_TYPE_PD_PPS) | 621 BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN), 622 .properties = bq257xx_power_supply_props, 623 .num_properties = ARRAY_SIZE(bq257xx_power_supply_props), 624 .get_property = bq257xx_get_charger_property, 625 .set_property = bq257xx_set_charger_property, 626 .property_is_writeable = bq257xx_property_is_writeable, 627 .external_power_changed = bq257xx_external_power_changed, 628}; 629 630static const struct bq257xx_chip_info bq25703_chip_info = { 631 .bq257xx_hw_init = &bq25703_hw_init, 632 .bq257xx_hw_shutdown = &bq25703_hw_shutdown, 633 .bq257xx_get_state = &bq25703_get_state, 634 .bq257xx_set_ichg = &bq25703_set_ichg_cur, 635 .bq257xx_set_vbatreg = &bq25703_set_chrg_volt, 636 .bq257xx_set_iindpm = &bq25703_set_iindpm, 637}; 638 639/** 640 * bq257xx_parse_dt() - Parse the device tree for required properties 641 * @pdata: driver platform data 642 * @psy_cfg: power supply config data 643 * @dev: device struct 644 * 645 * Read the device tree to identify the minimum system voltage, the 646 * maximum charge current, the maximum charge voltage, and the maximum 647 * input current. 648 * 649 * Return: Returns 0 on success or error code on error. 650 */ 651static int bq257xx_parse_dt(struct bq257xx_chg *pdata, 652 struct power_supply_config *psy_cfg, struct device *dev) 653{ 654 struct power_supply_battery_info *bat_info; 655 int ret; 656 657 ret = power_supply_get_battery_info(pdata->charger, 658 &bat_info); 659 if (ret) 660 return dev_err_probe(dev, ret, 661 "Unable to get battery info\n"); 662 663 if ((bat_info->voltage_min_design_uv <= 0) || 664 (bat_info->constant_charge_voltage_max_uv <= 0) || 665 (bat_info->constant_charge_current_max_ua <= 0)) 666 return dev_err_probe(dev, -EINVAL, 667 "Required bat info missing or invalid\n"); 668 669 pdata->vsys_min = bat_info->voltage_min_design_uv; 670 pdata->vbat_max = bat_info->constant_charge_voltage_max_uv; 671 pdata->ichg_max = bat_info->constant_charge_current_max_ua; 672 673 power_supply_put_battery_info(pdata->charger, bat_info); 674 675 ret = device_property_read_u32(dev, 676 "input-current-limit-microamp", 677 &pdata->iindpm_max); 678 if (ret) 679 pdata->iindpm_max = BQ25703_IINDPM_DEFAULT_UA; 680 681 return 0; 682} 683 684static int bq257xx_charger_probe(struct platform_device *pdev) 685{ 686 struct device *dev = &pdev->dev; 687 struct bq257xx_device *bq = dev_get_drvdata(pdev->dev.parent); 688 struct bq257xx_chg *pdata; 689 struct power_supply_config psy_cfg = { }; 690 int ret; 691 692 device_set_of_node_from_dev(dev, pdev->dev.parent); 693 694 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); 695 if (!pdata) 696 return -ENOMEM; 697 698 pdata->bq = bq; 699 pdata->chip = &bq25703_chip_info; 700 701 platform_set_drvdata(pdev, pdata); 702 703 psy_cfg.drv_data = pdata; 704 psy_cfg.fwnode = dev_fwnode(dev); 705 706 pdata->charger = devm_power_supply_register(dev, 707 &bq257xx_power_supply_desc, 708 &psy_cfg); 709 if (IS_ERR(pdata->charger)) 710 return dev_err_probe(dev, PTR_ERR(pdata->charger), 711 "Power supply register charger failed\n"); 712 713 ret = bq257xx_parse_dt(pdata, &psy_cfg, dev); 714 if (ret) 715 return ret; 716 717 ret = pdata->chip->bq257xx_hw_init(pdata); 718 if (ret) 719 return dev_err_probe(dev, ret, "Cannot initialize the charger\n"); 720 721 platform_set_drvdata(pdev, pdata); 722 723 if (bq->client->irq) { 724 ret = devm_request_threaded_irq(dev, bq->client->irq, NULL, 725 bq257xx_irq_handler_thread, 726 IRQF_TRIGGER_RISING | 727 IRQF_TRIGGER_FALLING | 728 IRQF_ONESHOT, 729 dev_name(&bq->client->dev), pdata); 730 if (ret < 0) 731 dev_err_probe(dev, ret, "Charger get irq failed\n"); 732 } 733 734 return ret; 735} 736 737static void bq257xx_charger_shutdown(struct platform_device *pdev) 738{ 739 struct bq257xx_chg *pdata = platform_get_drvdata(pdev); 740 741 pdata->chip->bq257xx_hw_shutdown(pdata); 742} 743 744static struct platform_driver bq257xx_chg_driver = { 745 .driver = { 746 .name = "bq257xx-charger", 747 }, 748 .probe = bq257xx_charger_probe, 749 .shutdown = bq257xx_charger_shutdown, 750}; 751module_platform_driver(bq257xx_chg_driver); 752 753MODULE_DESCRIPTION("bq257xx charger driver"); 754MODULE_AUTHOR("Chris Morgan <macromorgan@hotmail.com>"); 755MODULE_LICENSE("GPL");
~/
Read-only file preview.