1 /* 2 * Battery power supply driver for X-Powers AXP20X and AXP22X PMICs 3 * 4 * Copyright 2016 Free Electrons NextThing Co. 5 * Quentin Schulz <quentin.schulz@free-electrons.com> 6 * 7 * This driver is based on a previous upstreaming attempt by: 8 * Bruno Prémont <bonbons@linux-vserver.org> 9 * 10 * This file is subject to the terms and conditions of the GNU General 11 * Public License. See the file "COPYING" in the main directory of this 12 * archive for more details. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 */ 19 20 #include <linux/err.h> 21 #include <linux/interrupt.h> 22 #include <linux/irq.h> 23 #include <linux/module.h> 24 #include <linux/of.h> 25 #include <linux/of_device.h> 26 #include <linux/platform_device.h> 27 #include <linux/power_supply.h> 28 #include <linux/regmap.h> 29 #include <linux/slab.h> 30 #include <linux/time.h> 31 #include <linux/iio/iio.h> 32 #include <linux/iio/consumer.h> 33 #include <linux/mfd/axp20x.h> 34 35 #define AXP20X_PWR_STATUS_BAT_CHARGING BIT(2) 36 37 #define AXP20X_PWR_OP_BATT_PRESENT BIT(5) 38 #define AXP20X_PWR_OP_BATT_ACTIVATED BIT(3) 39 40 #define AXP209_FG_PERCENT GENMASK(6, 0) 41 #define AXP22X_FG_VALID BIT(7) 42 43 #define AXP20X_CHRG_CTRL1_ENABLE BIT(7) 44 #define AXP20X_CHRG_CTRL1_TGT_VOLT GENMASK(6, 5) 45 #define AXP20X_CHRG_CTRL1_TGT_4_1V (0 << 5) 46 #define AXP20X_CHRG_CTRL1_TGT_4_15V (1 << 5) 47 #define AXP20X_CHRG_CTRL1_TGT_4_2V (2 << 5) 48 #define AXP20X_CHRG_CTRL1_TGT_4_36V (3 << 5) 49 50 #define AXP22X_CHRG_CTRL1_TGT_4_22V (1 << 5) 51 #define AXP22X_CHRG_CTRL1_TGT_4_24V (3 << 5) 52 53 #define AXP813_CHRG_CTRL1_TGT_4_35V (3 << 5) 54 55 #define AXP20X_CHRG_CTRL1_TGT_CURR GENMASK(3, 0) 56 57 #define AXP20X_V_OFF_MASK GENMASK(2, 0) 58 59 struct axp20x_batt_ps; 60 61 struct axp_data { 62 int ccc_scale; 63 int ccc_offset; 64 bool has_fg_valid; 65 int (*get_max_voltage)(struct axp20x_batt_ps *batt, int *val); 66 int (*set_max_voltage)(struct axp20x_batt_ps *batt, int val); 67 }; 68 69 struct axp20x_batt_ps { 70 struct regmap *regmap; 71 struct power_supply *batt; 72 struct device *dev; 73 struct iio_channel *batt_chrg_i; 74 struct iio_channel *batt_dischrg_i; 75 struct iio_channel *batt_v; 76 /* Maximum constant charge current */ 77 unsigned int max_ccc; 78 const struct axp_data *data; 79 }; 80 81 static int axp20x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt, 82 int *val) 83 { 84 int ret, reg; 85 86 ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, ®); 87 if (ret) 88 return ret; 89 90 switch (reg & AXP20X_CHRG_CTRL1_TGT_VOLT) { 91 case AXP20X_CHRG_CTRL1_TGT_4_1V: 92 *val = 4100000; 93 break; 94 case AXP20X_CHRG_CTRL1_TGT_4_15V: 95 *val = 4150000; 96 break; 97 case AXP20X_CHRG_CTRL1_TGT_4_2V: 98 *val = 4200000; 99 break; 100 case AXP20X_CHRG_CTRL1_TGT_4_36V: 101 *val = 4360000; 102 break; 103 default: 104 return -EINVAL; 105 } 106 107 return 0; 108 } 109 110 static int axp22x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt, 111 int *val) 112 { 113 int ret, reg; 114 115 ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, ®); 116 if (ret) 117 return ret; 118 119 switch (reg & AXP20X_CHRG_CTRL1_TGT_VOLT) { 120 case AXP20X_CHRG_CTRL1_TGT_4_1V: 121 *val = 4100000; 122 break; 123 case AXP20X_CHRG_CTRL1_TGT_4_2V: 124 *val = 4200000; 125 break; 126 case AXP22X_CHRG_CTRL1_TGT_4_22V: 127 *val = 4220000; 128 break; 129 case AXP22X_CHRG_CTRL1_TGT_4_24V: 130 *val = 4240000; 131 break; 132 default: 133 return -EINVAL; 134 } 135 136 return 0; 137 } 138 139 static int axp813_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt, 140 int *val) 141 { 142 int ret, reg; 143 144 ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, ®); 145 if (ret) 146 return ret; 147 148 switch (reg & AXP20X_CHRG_CTRL1_TGT_VOLT) { 149 case AXP20X_CHRG_CTRL1_TGT_4_1V: 150 *val = 4100000; 151 break; 152 case AXP20X_CHRG_CTRL1_TGT_4_15V: 153 *val = 4150000; 154 break; 155 case AXP20X_CHRG_CTRL1_TGT_4_2V: 156 *val = 4200000; 157 break; 158 case AXP813_CHRG_CTRL1_TGT_4_35V: 159 *val = 4350000; 160 break; 161 default: 162 return -EINVAL; 163 } 164 165 return 0; 166 } 167 168 static int axp20x_get_constant_charge_current(struct axp20x_batt_ps *axp, 169 int *val) 170 { 171 int ret; 172 173 ret = regmap_read(axp->regmap, AXP20X_CHRG_CTRL1, val); 174 if (ret) 175 return ret; 176 177 *val &= AXP20X_CHRG_CTRL1_TGT_CURR; 178 179 *val = *val * axp->data->ccc_scale + axp->data->ccc_offset; 180 181 return 0; 182 } 183 184 static int axp20x_battery_get_prop(struct power_supply *psy, 185 enum power_supply_property psp, 186 union power_supply_propval *val) 187 { 188 struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy); 189 struct iio_channel *chan; 190 int ret = 0, reg, val1; 191 192 switch (psp) { 193 case POWER_SUPPLY_PROP_PRESENT: 194 case POWER_SUPPLY_PROP_ONLINE: 195 ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_OP_MODE, 196 ®); 197 if (ret) 198 return ret; 199 200 val->intval = !!(reg & AXP20X_PWR_OP_BATT_PRESENT); 201 break; 202 203 case POWER_SUPPLY_PROP_STATUS: 204 ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_INPUT_STATUS, 205 ®); 206 if (ret) 207 return ret; 208 209 if (reg & AXP20X_PWR_STATUS_BAT_CHARGING) { 210 val->intval = POWER_SUPPLY_STATUS_CHARGING; 211 return 0; 212 } 213 214 ret = iio_read_channel_processed(axp20x_batt->batt_dischrg_i, 215 &val1); 216 if (ret) 217 return ret; 218 219 if (val1) { 220 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 221 return 0; 222 } 223 224 ret = regmap_read(axp20x_batt->regmap, AXP20X_FG_RES, &val1); 225 if (ret) 226 return ret; 227 228 /* 229 * Fuel Gauge data takes 7 bits but the stored value seems to be 230 * directly the raw percentage without any scaling to 7 bits. 231 */ 232 if ((val1 & AXP209_FG_PERCENT) == 100) 233 val->intval = POWER_SUPPLY_STATUS_FULL; 234 else 235 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; 236 break; 237 238 case POWER_SUPPLY_PROP_HEALTH: 239 ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_OP_MODE, 240 &val1); 241 if (ret) 242 return ret; 243 244 if (val1 & AXP20X_PWR_OP_BATT_ACTIVATED) { 245 val->intval = POWER_SUPPLY_HEALTH_DEAD; 246 return 0; 247 } 248 249 val->intval = POWER_SUPPLY_HEALTH_GOOD; 250 break; 251 252 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 253 ret = axp20x_get_constant_charge_current(axp20x_batt, 254 &val->intval); 255 if (ret) 256 return ret; 257 break; 258 259 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: 260 val->intval = axp20x_batt->max_ccc; 261 break; 262 263 case POWER_SUPPLY_PROP_CURRENT_NOW: 264 ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_INPUT_STATUS, 265 ®); 266 if (ret) 267 return ret; 268 269 if (reg & AXP20X_PWR_STATUS_BAT_CHARGING) 270 chan = axp20x_batt->batt_chrg_i; 271 else 272 chan = axp20x_batt->batt_dischrg_i; 273 274 ret = iio_read_channel_processed(chan, &val->intval); 275 if (ret) 276 return ret; 277 278 /* IIO framework gives mA but Power Supply framework gives uA */ 279 val->intval *= 1000; 280 break; 281 282 case POWER_SUPPLY_PROP_CAPACITY: 283 /* When no battery is present, return capacity is 100% */ 284 ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_OP_MODE, 285 ®); 286 if (ret) 287 return ret; 288 289 if (!(reg & AXP20X_PWR_OP_BATT_PRESENT)) { 290 val->intval = 100; 291 return 0; 292 } 293 294 ret = regmap_read(axp20x_batt->regmap, AXP20X_FG_RES, ®); 295 if (ret) 296 return ret; 297 298 if (axp20x_batt->data->has_fg_valid && !(reg & AXP22X_FG_VALID)) 299 return -EINVAL; 300 301 /* 302 * Fuel Gauge data takes 7 bits but the stored value seems to be 303 * directly the raw percentage without any scaling to 7 bits. 304 */ 305 val->intval = reg & AXP209_FG_PERCENT; 306 break; 307 308 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: 309 return axp20x_batt->data->get_max_voltage(axp20x_batt, 310 &val->intval); 311 312 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 313 ret = regmap_read(axp20x_batt->regmap, AXP20X_V_OFF, ®); 314 if (ret) 315 return ret; 316 317 val->intval = 2600000 + 100000 * (reg & AXP20X_V_OFF_MASK); 318 break; 319 320 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 321 ret = iio_read_channel_processed(axp20x_batt->batt_v, 322 &val->intval); 323 if (ret) 324 return ret; 325 326 /* IIO framework gives mV but Power Supply framework gives uV */ 327 val->intval *= 1000; 328 break; 329 330 default: 331 return -EINVAL; 332 } 333 334 return 0; 335 } 336 337 static int axp22x_battery_set_max_voltage(struct axp20x_batt_ps *axp20x_batt, 338 int val) 339 { 340 switch (val) { 341 case 4100000: 342 val = AXP20X_CHRG_CTRL1_TGT_4_1V; 343 break; 344 345 case 4200000: 346 val = AXP20X_CHRG_CTRL1_TGT_4_2V; 347 break; 348 349 default: 350 /* 351 * AXP20x max voltage can be set to 4.36V and AXP22X max voltage 352 * can be set to 4.22V and 4.24V, but these voltages are too 353 * high for Lithium based batteries (AXP PMICs are supposed to 354 * be used with these kinds of battery). 355 */ 356 return -EINVAL; 357 } 358 359 return regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, 360 AXP20X_CHRG_CTRL1_TGT_VOLT, val); 361 } 362 363 static int axp20x_battery_set_max_voltage(struct axp20x_batt_ps *axp20x_batt, 364 int val) 365 { 366 switch (val) { 367 case 4100000: 368 val = AXP20X_CHRG_CTRL1_TGT_4_1V; 369 break; 370 371 case 4150000: 372 val = AXP20X_CHRG_CTRL1_TGT_4_15V; 373 break; 374 375 case 4200000: 376 val = AXP20X_CHRG_CTRL1_TGT_4_2V; 377 break; 378 379 default: 380 /* 381 * AXP20x max voltage can be set to 4.36V and AXP22X max voltage 382 * can be set to 4.22V and 4.24V, but these voltages are too 383 * high for Lithium based batteries (AXP PMICs are supposed to 384 * be used with these kinds of battery). 385 */ 386 return -EINVAL; 387 } 388 389 return regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, 390 AXP20X_CHRG_CTRL1_TGT_VOLT, val); 391 } 392 393 static int axp20x_set_constant_charge_current(struct axp20x_batt_ps *axp_batt, 394 int charge_current) 395 { 396 if (charge_current > axp_batt->max_ccc) 397 return -EINVAL; 398 399 charge_current = (charge_current - axp_batt->data->ccc_offset) / 400 axp_batt->data->ccc_scale; 401 402 if (charge_current > AXP20X_CHRG_CTRL1_TGT_CURR || charge_current < 0) 403 return -EINVAL; 404 405 return regmap_update_bits(axp_batt->regmap, AXP20X_CHRG_CTRL1, 406 AXP20X_CHRG_CTRL1_TGT_CURR, charge_current); 407 } 408 409 static int axp20x_set_max_constant_charge_current(struct axp20x_batt_ps *axp, 410 int charge_current) 411 { 412 bool lower_max = false; 413 414 charge_current = (charge_current - axp->data->ccc_offset) / 415 axp->data->ccc_scale; 416 417 if (charge_current > AXP20X_CHRG_CTRL1_TGT_CURR || charge_current < 0) 418 return -EINVAL; 419 420 charge_current = charge_current * axp->data->ccc_scale + 421 axp->data->ccc_offset; 422 423 if (charge_current > axp->max_ccc) 424 dev_warn(axp->dev, 425 "Setting max constant charge current higher than previously defined. Note that increasing the constant charge current may damage your battery.\n"); 426 else 427 lower_max = true; 428 429 axp->max_ccc = charge_current; 430 431 if (lower_max) { 432 int current_cc; 433 434 axp20x_get_constant_charge_current(axp, ¤t_cc); 435 if (current_cc > charge_current) 436 axp20x_set_constant_charge_current(axp, charge_current); 437 } 438 439 return 0; 440 } 441 static int axp20x_set_voltage_min_design(struct axp20x_batt_ps *axp_batt, 442 int min_voltage) 443 { 444 int val1 = (min_voltage - 2600000) / 100000; 445 446 if (val1 < 0 || val1 > AXP20X_V_OFF_MASK) 447 return -EINVAL; 448 449 return regmap_update_bits(axp_batt->regmap, AXP20X_V_OFF, 450 AXP20X_V_OFF_MASK, val1); 451 } 452 453 static int axp20x_battery_set_prop(struct power_supply *psy, 454 enum power_supply_property psp, 455 const union power_supply_propval *val) 456 { 457 struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy); 458 459 switch (psp) { 460 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 461 return axp20x_set_voltage_min_design(axp20x_batt, val->intval); 462 463 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: 464 return axp20x_batt->data->set_max_voltage(axp20x_batt, val->intval); 465 466 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 467 return axp20x_set_constant_charge_current(axp20x_batt, 468 val->intval); 469 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: 470 return axp20x_set_max_constant_charge_current(axp20x_batt, 471 val->intval); 472 case POWER_SUPPLY_PROP_STATUS: 473 switch (val->intval) { 474 case POWER_SUPPLY_STATUS_CHARGING: 475 return regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, 476 AXP20X_CHRG_CTRL1_ENABLE, AXP20X_CHRG_CTRL1_ENABLE); 477 478 case POWER_SUPPLY_STATUS_DISCHARGING: 479 case POWER_SUPPLY_STATUS_NOT_CHARGING: 480 return regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, 481 AXP20X_CHRG_CTRL1_ENABLE, 0); 482 } 483 fallthrough; 484 default: 485 return -EINVAL; 486 } 487 } 488 489 static enum power_supply_property axp20x_battery_props[] = { 490 POWER_SUPPLY_PROP_PRESENT, 491 POWER_SUPPLY_PROP_ONLINE, 492 POWER_SUPPLY_PROP_STATUS, 493 POWER_SUPPLY_PROP_VOLTAGE_NOW, 494 POWER_SUPPLY_PROP_CURRENT_NOW, 495 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, 496 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, 497 POWER_SUPPLY_PROP_HEALTH, 498 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 499 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, 500 POWER_SUPPLY_PROP_CAPACITY, 501 }; 502 503 static int axp20x_battery_prop_writeable(struct power_supply *psy, 504 enum power_supply_property psp) 505 { 506 return psp == POWER_SUPPLY_PROP_STATUS || 507 psp == POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN || 508 psp == POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN || 509 psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT || 510 psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX; 511 } 512 513 static const struct power_supply_desc axp20x_batt_ps_desc = { 514 .name = "axp20x-battery", 515 .type = POWER_SUPPLY_TYPE_BATTERY, 516 .properties = axp20x_battery_props, 517 .num_properties = ARRAY_SIZE(axp20x_battery_props), 518 .property_is_writeable = axp20x_battery_prop_writeable, 519 .get_property = axp20x_battery_get_prop, 520 .set_property = axp20x_battery_set_prop, 521 }; 522 523 static const struct axp_data axp209_data = { 524 .ccc_scale = 100000, 525 .ccc_offset = 300000, 526 .get_max_voltage = axp20x_battery_get_max_voltage, 527 .set_max_voltage = axp20x_battery_set_max_voltage, 528 }; 529 530 static const struct axp_data axp221_data = { 531 .ccc_scale = 150000, 532 .ccc_offset = 300000, 533 .has_fg_valid = true, 534 .get_max_voltage = axp22x_battery_get_max_voltage, 535 .set_max_voltage = axp22x_battery_set_max_voltage, 536 }; 537 538 static const struct axp_data axp813_data = { 539 .ccc_scale = 200000, 540 .ccc_offset = 200000, 541 .has_fg_valid = true, 542 .get_max_voltage = axp813_battery_get_max_voltage, 543 .set_max_voltage = axp20x_battery_set_max_voltage, 544 }; 545 546 static const struct of_device_id axp20x_battery_ps_id[] = { 547 { 548 .compatible = "x-powers,axp209-battery-power-supply", 549 .data = (void *)&axp209_data, 550 }, { 551 .compatible = "x-powers,axp221-battery-power-supply", 552 .data = (void *)&axp221_data, 553 }, { 554 .compatible = "x-powers,axp813-battery-power-supply", 555 .data = (void *)&axp813_data, 556 }, { /* sentinel */ }, 557 }; 558 MODULE_DEVICE_TABLE(of, axp20x_battery_ps_id); 559 560 static int axp20x_power_probe(struct platform_device *pdev) 561 { 562 struct axp20x_batt_ps *axp20x_batt; 563 struct power_supply_config psy_cfg = {}; 564 struct power_supply_battery_info info; 565 struct device *dev = &pdev->dev; 566 567 if (!of_device_is_available(pdev->dev.of_node)) 568 return -ENODEV; 569 570 axp20x_batt = devm_kzalloc(&pdev->dev, sizeof(*axp20x_batt), 571 GFP_KERNEL); 572 if (!axp20x_batt) 573 return -ENOMEM; 574 575 axp20x_batt->dev = &pdev->dev; 576 577 axp20x_batt->batt_v = devm_iio_channel_get(&pdev->dev, "batt_v"); 578 if (IS_ERR(axp20x_batt->batt_v)) { 579 if (PTR_ERR(axp20x_batt->batt_v) == -ENODEV) 580 return -EPROBE_DEFER; 581 return PTR_ERR(axp20x_batt->batt_v); 582 } 583 584 axp20x_batt->batt_chrg_i = devm_iio_channel_get(&pdev->dev, 585 "batt_chrg_i"); 586 if (IS_ERR(axp20x_batt->batt_chrg_i)) { 587 if (PTR_ERR(axp20x_batt->batt_chrg_i) == -ENODEV) 588 return -EPROBE_DEFER; 589 return PTR_ERR(axp20x_batt->batt_chrg_i); 590 } 591 592 axp20x_batt->batt_dischrg_i = devm_iio_channel_get(&pdev->dev, 593 "batt_dischrg_i"); 594 if (IS_ERR(axp20x_batt->batt_dischrg_i)) { 595 if (PTR_ERR(axp20x_batt->batt_dischrg_i) == -ENODEV) 596 return -EPROBE_DEFER; 597 return PTR_ERR(axp20x_batt->batt_dischrg_i); 598 } 599 600 axp20x_batt->regmap = dev_get_regmap(pdev->dev.parent, NULL); 601 platform_set_drvdata(pdev, axp20x_batt); 602 603 psy_cfg.drv_data = axp20x_batt; 604 psy_cfg.of_node = pdev->dev.of_node; 605 606 axp20x_batt->data = (struct axp_data *)of_device_get_match_data(dev); 607 608 axp20x_batt->batt = devm_power_supply_register(&pdev->dev, 609 &axp20x_batt_ps_desc, 610 &psy_cfg); 611 if (IS_ERR(axp20x_batt->batt)) { 612 dev_err(&pdev->dev, "failed to register power supply: %ld\n", 613 PTR_ERR(axp20x_batt->batt)); 614 return PTR_ERR(axp20x_batt->batt); 615 } 616 617 if (!power_supply_get_battery_info(axp20x_batt->batt, &info)) { 618 int vmin = info.voltage_min_design_uv; 619 int ccc = info.constant_charge_current_max_ua; 620 621 if (vmin > 0 && axp20x_set_voltage_min_design(axp20x_batt, 622 vmin)) 623 dev_err(&pdev->dev, 624 "couldn't set voltage_min_design\n"); 625 626 /* Set max to unverified value to be able to set CCC */ 627 axp20x_batt->max_ccc = ccc; 628 629 if (ccc <= 0 || axp20x_set_constant_charge_current(axp20x_batt, 630 ccc)) { 631 dev_err(&pdev->dev, 632 "couldn't set constant charge current from DT: fallback to minimum value\n"); 633 ccc = 300000; 634 axp20x_batt->max_ccc = ccc; 635 axp20x_set_constant_charge_current(axp20x_batt, ccc); 636 } 637 } 638 639 /* 640 * Update max CCC to a valid value if battery info is present or set it 641 * to current register value by default. 642 */ 643 axp20x_get_constant_charge_current(axp20x_batt, 644 &axp20x_batt->max_ccc); 645 646 return 0; 647 } 648 649 static struct platform_driver axp20x_batt_driver = { 650 .probe = axp20x_power_probe, 651 .driver = { 652 .name = "axp20x-battery-power-supply", 653 .of_match_table = axp20x_battery_ps_id, 654 }, 655 }; 656 657 module_platform_driver(axp20x_batt_driver); 658 659 MODULE_DESCRIPTION("Battery power supply driver for AXP20X and AXP22X PMICs"); 660 MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>"); 661 MODULE_LICENSE("GPL"); 662