2 * Battery power supply driver for X-Powers AXP20X and AXP22X PMICs
4 * Copyright 2016 Free Electrons NextThing Co.
5 * Quentin Schulz <quentin.schulz@free-electrons.com>
7 * This driver is based on a previous upstreaming attempt by:
8 * Bruno Prémont <bonbons@linux-vserver.org>
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.
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.
20 #include <linux/err.h>
21 #include <linux/interrupt.h>
22 #include <linux/irq.h>
23 #include <linux/module.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>
35 #define AXP20X_PWR_STATUS_BAT_CHARGING BIT(2)
37 #define AXP20X_PWR_OP_BATT_PRESENT BIT(5)
38 #define AXP20X_PWR_OP_BATT_ACTIVATED BIT(3)
40 #define AXP209_FG_PERCENT GENMASK(6, 0)
41 #define AXP22X_FG_VALID BIT(7)
43 #define AXP20X_CHRG_CTRL1_TGT_VOLT GENMASK(6, 5)
44 #define AXP20X_CHRG_CTRL1_TGT_4_1V (0 << 5)
45 #define AXP20X_CHRG_CTRL1_TGT_4_15V (1 << 5)
46 #define AXP20X_CHRG_CTRL1_TGT_4_2V (2 << 5)
47 #define AXP20X_CHRG_CTRL1_TGT_4_36V (3 << 5)
49 #define AXP22X_CHRG_CTRL1_TGT_4_22V (1 << 5)
50 #define AXP22X_CHRG_CTRL1_TGT_4_24V (3 << 5)
52 #define AXP813_CHRG_CTRL1_TGT_4_35V (3 << 5)
54 #define AXP20X_CHRG_CTRL1_TGT_CURR GENMASK(3, 0)
56 #define AXP20X_V_OFF_MASK GENMASK(2, 0)
58 struct axp20x_batt_ps
;
64 int (*get_max_voltage
)(struct axp20x_batt_ps
*batt
, int *val
);
65 int (*set_max_voltage
)(struct axp20x_batt_ps
*batt
, int val
);
68 struct axp20x_batt_ps
{
69 struct regmap
*regmap
;
70 struct power_supply
*batt
;
72 struct iio_channel
*batt_chrg_i
;
73 struct iio_channel
*batt_dischrg_i
;
74 struct iio_channel
*batt_v
;
75 /* Maximum constant charge current */
77 const struct axp_data
*data
;
80 static int axp20x_battery_get_max_voltage(struct axp20x_batt_ps
*axp20x_batt
,
85 ret
= regmap_read(axp20x_batt
->regmap
, AXP20X_CHRG_CTRL1
, ®
);
89 switch (reg
& AXP20X_CHRG_CTRL1_TGT_VOLT
) {
90 case AXP20X_CHRG_CTRL1_TGT_4_1V
:
93 case AXP20X_CHRG_CTRL1_TGT_4_15V
:
96 case AXP20X_CHRG_CTRL1_TGT_4_2V
:
99 case AXP20X_CHRG_CTRL1_TGT_4_36V
:
109 static int axp22x_battery_get_max_voltage(struct axp20x_batt_ps
*axp20x_batt
,
114 ret
= regmap_read(axp20x_batt
->regmap
, AXP20X_CHRG_CTRL1
, ®
);
118 switch (reg
& AXP20X_CHRG_CTRL1_TGT_VOLT
) {
119 case AXP20X_CHRG_CTRL1_TGT_4_1V
:
122 case AXP20X_CHRG_CTRL1_TGT_4_2V
:
125 case AXP22X_CHRG_CTRL1_TGT_4_22V
:
128 case AXP22X_CHRG_CTRL1_TGT_4_24V
:
138 static int axp813_battery_get_max_voltage(struct axp20x_batt_ps
*axp20x_batt
,
143 ret
= regmap_read(axp20x_batt
->regmap
, AXP20X_CHRG_CTRL1
, ®
);
147 switch (reg
& AXP20X_CHRG_CTRL1_TGT_VOLT
) {
148 case AXP20X_CHRG_CTRL1_TGT_4_1V
:
151 case AXP20X_CHRG_CTRL1_TGT_4_15V
:
154 case AXP20X_CHRG_CTRL1_TGT_4_2V
:
157 case AXP813_CHRG_CTRL1_TGT_4_35V
:
167 static int axp20x_get_constant_charge_current(struct axp20x_batt_ps
*axp
,
172 ret
= regmap_read(axp
->regmap
, AXP20X_CHRG_CTRL1
, val
);
176 *val
&= AXP20X_CHRG_CTRL1_TGT_CURR
;
178 *val
= *val
* axp
->data
->ccc_scale
+ axp
->data
->ccc_offset
;
183 static int axp20x_battery_get_prop(struct power_supply
*psy
,
184 enum power_supply_property psp
,
185 union power_supply_propval
*val
)
187 struct axp20x_batt_ps
*axp20x_batt
= power_supply_get_drvdata(psy
);
188 struct iio_channel
*chan
;
189 int ret
= 0, reg
, val1
;
192 case POWER_SUPPLY_PROP_PRESENT
:
193 case POWER_SUPPLY_PROP_ONLINE
:
194 ret
= regmap_read(axp20x_batt
->regmap
, AXP20X_PWR_OP_MODE
,
199 val
->intval
= !!(reg
& AXP20X_PWR_OP_BATT_PRESENT
);
202 case POWER_SUPPLY_PROP_STATUS
:
203 ret
= regmap_read(axp20x_batt
->regmap
, AXP20X_PWR_INPUT_STATUS
,
208 if (reg
& AXP20X_PWR_STATUS_BAT_CHARGING
) {
209 val
->intval
= POWER_SUPPLY_STATUS_CHARGING
;
213 ret
= iio_read_channel_processed(axp20x_batt
->batt_dischrg_i
,
219 val
->intval
= POWER_SUPPLY_STATUS_DISCHARGING
;
223 ret
= regmap_read(axp20x_batt
->regmap
, AXP20X_FG_RES
, &val1
);
228 * Fuel Gauge data takes 7 bits but the stored value seems to be
229 * directly the raw percentage without any scaling to 7 bits.
231 if ((val1
& AXP209_FG_PERCENT
) == 100)
232 val
->intval
= POWER_SUPPLY_STATUS_FULL
;
234 val
->intval
= POWER_SUPPLY_STATUS_NOT_CHARGING
;
237 case POWER_SUPPLY_PROP_HEALTH
:
238 ret
= regmap_read(axp20x_batt
->regmap
, AXP20X_PWR_OP_MODE
,
243 if (val1
& AXP20X_PWR_OP_BATT_ACTIVATED
) {
244 val
->intval
= POWER_SUPPLY_HEALTH_DEAD
;
248 val
->intval
= POWER_SUPPLY_HEALTH_GOOD
;
251 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT
:
252 ret
= axp20x_get_constant_charge_current(axp20x_batt
,
258 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX
:
259 val
->intval
= axp20x_batt
->max_ccc
;
262 case POWER_SUPPLY_PROP_CURRENT_NOW
:
263 ret
= regmap_read(axp20x_batt
->regmap
, AXP20X_PWR_INPUT_STATUS
,
268 if (reg
& AXP20X_PWR_STATUS_BAT_CHARGING
)
269 chan
= axp20x_batt
->batt_chrg_i
;
271 chan
= axp20x_batt
->batt_dischrg_i
;
273 ret
= iio_read_channel_processed(chan
, &val
->intval
);
277 /* IIO framework gives mA but Power Supply framework gives uA */
281 case POWER_SUPPLY_PROP_CAPACITY
:
282 /* When no battery is present, return capacity is 100% */
283 ret
= regmap_read(axp20x_batt
->regmap
, AXP20X_PWR_OP_MODE
,
288 if (!(reg
& AXP20X_PWR_OP_BATT_PRESENT
)) {
293 ret
= regmap_read(axp20x_batt
->regmap
, AXP20X_FG_RES
, ®
);
297 if (axp20x_batt
->data
->has_fg_valid
&& !(reg
& AXP22X_FG_VALID
))
301 * Fuel Gauge data takes 7 bits but the stored value seems to be
302 * directly the raw percentage without any scaling to 7 bits.
304 val
->intval
= reg
& AXP209_FG_PERCENT
;
307 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN
:
308 return axp20x_batt
->data
->get_max_voltage(axp20x_batt
,
311 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
:
312 ret
= regmap_read(axp20x_batt
->regmap
, AXP20X_V_OFF
, ®
);
316 val
->intval
= 2600000 + 100000 * (reg
& AXP20X_V_OFF_MASK
);
319 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
320 ret
= iio_read_channel_processed(axp20x_batt
->batt_v
,
325 /* IIO framework gives mV but Power Supply framework gives uV */
336 static int axp22x_battery_set_max_voltage(struct axp20x_batt_ps
*axp20x_batt
,
341 val
= AXP20X_CHRG_CTRL1_TGT_4_1V
;
345 val
= AXP20X_CHRG_CTRL1_TGT_4_2V
;
350 * AXP20x max voltage can be set to 4.36V and AXP22X max voltage
351 * can be set to 4.22V and 4.24V, but these voltages are too
352 * high for Lithium based batteries (AXP PMICs are supposed to
353 * be used with these kinds of battery).
358 return regmap_update_bits(axp20x_batt
->regmap
, AXP20X_CHRG_CTRL1
,
359 AXP20X_CHRG_CTRL1_TGT_VOLT
, val
);
362 static int axp20x_battery_set_max_voltage(struct axp20x_batt_ps
*axp20x_batt
,
367 val
= AXP20X_CHRG_CTRL1_TGT_4_1V
;
371 val
= AXP20X_CHRG_CTRL1_TGT_4_15V
;
375 val
= AXP20X_CHRG_CTRL1_TGT_4_2V
;
380 * AXP20x max voltage can be set to 4.36V and AXP22X max voltage
381 * can be set to 4.22V and 4.24V, but these voltages are too
382 * high for Lithium based batteries (AXP PMICs are supposed to
383 * be used with these kinds of battery).
388 return regmap_update_bits(axp20x_batt
->regmap
, AXP20X_CHRG_CTRL1
,
389 AXP20X_CHRG_CTRL1_TGT_VOLT
, val
);
392 static int axp20x_set_constant_charge_current(struct axp20x_batt_ps
*axp_batt
,
395 if (charge_current
> axp_batt
->max_ccc
)
398 charge_current
= (charge_current
- axp_batt
->data
->ccc_offset
) /
399 axp_batt
->data
->ccc_scale
;
401 if (charge_current
> AXP20X_CHRG_CTRL1_TGT_CURR
|| charge_current
< 0)
404 return regmap_update_bits(axp_batt
->regmap
, AXP20X_CHRG_CTRL1
,
405 AXP20X_CHRG_CTRL1_TGT_CURR
, charge_current
);
408 static int axp20x_set_max_constant_charge_current(struct axp20x_batt_ps
*axp
,
411 bool lower_max
= false;
413 charge_current
= (charge_current
- axp
->data
->ccc_offset
) /
414 axp
->data
->ccc_scale
;
416 if (charge_current
> AXP20X_CHRG_CTRL1_TGT_CURR
|| charge_current
< 0)
419 charge_current
= charge_current
* axp
->data
->ccc_scale
+
420 axp
->data
->ccc_offset
;
422 if (charge_current
> axp
->max_ccc
)
424 "Setting max constant charge current higher than previously defined. Note that increasing the constant charge current may damage your battery.\n");
428 axp
->max_ccc
= charge_current
;
433 axp20x_get_constant_charge_current(axp
, ¤t_cc
);
434 if (current_cc
> charge_current
)
435 axp20x_set_constant_charge_current(axp
, charge_current
);
440 static int axp20x_set_voltage_min_design(struct axp20x_batt_ps
*axp_batt
,
443 int val1
= (min_voltage
- 2600000) / 100000;
445 if (val1
< 0 || val1
> AXP20X_V_OFF_MASK
)
448 return regmap_update_bits(axp_batt
->regmap
, AXP20X_V_OFF
,
449 AXP20X_V_OFF_MASK
, val1
);
452 static int axp20x_battery_set_prop(struct power_supply
*psy
,
453 enum power_supply_property psp
,
454 const union power_supply_propval
*val
)
456 struct axp20x_batt_ps
*axp20x_batt
= power_supply_get_drvdata(psy
);
459 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
:
460 return axp20x_set_voltage_min_design(axp20x_batt
, val
->intval
);
462 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN
:
463 return axp20x_batt
->data
->set_max_voltage(axp20x_batt
, val
->intval
);
465 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT
:
466 return axp20x_set_constant_charge_current(axp20x_batt
,
468 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX
:
469 return axp20x_set_max_constant_charge_current(axp20x_batt
,
477 static enum power_supply_property axp20x_battery_props
[] = {
478 POWER_SUPPLY_PROP_PRESENT
,
479 POWER_SUPPLY_PROP_ONLINE
,
480 POWER_SUPPLY_PROP_STATUS
,
481 POWER_SUPPLY_PROP_VOLTAGE_NOW
,
482 POWER_SUPPLY_PROP_CURRENT_NOW
,
483 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT
,
484 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX
,
485 POWER_SUPPLY_PROP_HEALTH
,
486 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN
,
487 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
,
488 POWER_SUPPLY_PROP_CAPACITY
,
491 static int axp20x_battery_prop_writeable(struct power_supply
*psy
,
492 enum power_supply_property psp
)
494 return psp
== POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
||
495 psp
== POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN
||
496 psp
== POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT
||
497 psp
== POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX
;
500 static const struct power_supply_desc axp20x_batt_ps_desc
= {
501 .name
= "axp20x-battery",
502 .type
= POWER_SUPPLY_TYPE_BATTERY
,
503 .properties
= axp20x_battery_props
,
504 .num_properties
= ARRAY_SIZE(axp20x_battery_props
),
505 .property_is_writeable
= axp20x_battery_prop_writeable
,
506 .get_property
= axp20x_battery_get_prop
,
507 .set_property
= axp20x_battery_set_prop
,
510 static const struct axp_data axp209_data
= {
512 .ccc_offset
= 300000,
513 .get_max_voltage
= axp20x_battery_get_max_voltage
,
514 .set_max_voltage
= axp20x_battery_set_max_voltage
,
517 static const struct axp_data axp221_data
= {
519 .ccc_offset
= 300000,
520 .has_fg_valid
= true,
521 .get_max_voltage
= axp22x_battery_get_max_voltage
,
522 .set_max_voltage
= axp22x_battery_set_max_voltage
,
525 static const struct axp_data axp813_data
= {
527 .ccc_offset
= 200000,
528 .has_fg_valid
= true,
529 .get_max_voltage
= axp813_battery_get_max_voltage
,
530 .set_max_voltage
= axp20x_battery_set_max_voltage
,
533 static const struct of_device_id axp20x_battery_ps_id
[] = {
535 .compatible
= "x-powers,axp209-battery-power-supply",
536 .data
= (void *)&axp209_data
,
538 .compatible
= "x-powers,axp221-battery-power-supply",
539 .data
= (void *)&axp221_data
,
541 .compatible
= "x-powers,axp813-battery-power-supply",
542 .data
= (void *)&axp813_data
,
543 }, { /* sentinel */ },
545 MODULE_DEVICE_TABLE(of
, axp20x_battery_ps_id
);
547 static int axp20x_power_probe(struct platform_device
*pdev
)
549 struct axp20x_batt_ps
*axp20x_batt
;
550 struct power_supply_config psy_cfg
= {};
551 struct power_supply_battery_info info
;
552 struct device
*dev
= &pdev
->dev
;
554 if (!of_device_is_available(pdev
->dev
.of_node
))
557 axp20x_batt
= devm_kzalloc(&pdev
->dev
, sizeof(*axp20x_batt
),
562 axp20x_batt
->dev
= &pdev
->dev
;
564 axp20x_batt
->batt_v
= devm_iio_channel_get(&pdev
->dev
, "batt_v");
565 if (IS_ERR(axp20x_batt
->batt_v
)) {
566 if (PTR_ERR(axp20x_batt
->batt_v
) == -ENODEV
)
567 return -EPROBE_DEFER
;
568 return PTR_ERR(axp20x_batt
->batt_v
);
571 axp20x_batt
->batt_chrg_i
= devm_iio_channel_get(&pdev
->dev
,
573 if (IS_ERR(axp20x_batt
->batt_chrg_i
)) {
574 if (PTR_ERR(axp20x_batt
->batt_chrg_i
) == -ENODEV
)
575 return -EPROBE_DEFER
;
576 return PTR_ERR(axp20x_batt
->batt_chrg_i
);
579 axp20x_batt
->batt_dischrg_i
= devm_iio_channel_get(&pdev
->dev
,
581 if (IS_ERR(axp20x_batt
->batt_dischrg_i
)) {
582 if (PTR_ERR(axp20x_batt
->batt_dischrg_i
) == -ENODEV
)
583 return -EPROBE_DEFER
;
584 return PTR_ERR(axp20x_batt
->batt_dischrg_i
);
587 axp20x_batt
->regmap
= dev_get_regmap(pdev
->dev
.parent
, NULL
);
588 platform_set_drvdata(pdev
, axp20x_batt
);
590 psy_cfg
.drv_data
= axp20x_batt
;
591 psy_cfg
.of_node
= pdev
->dev
.of_node
;
593 axp20x_batt
->data
= (struct axp_data
*)of_device_get_match_data(dev
);
595 axp20x_batt
->batt
= devm_power_supply_register(&pdev
->dev
,
596 &axp20x_batt_ps_desc
,
598 if (IS_ERR(axp20x_batt
->batt
)) {
599 dev_err(&pdev
->dev
, "failed to register power supply: %ld\n",
600 PTR_ERR(axp20x_batt
->batt
));
601 return PTR_ERR(axp20x_batt
->batt
);
604 if (!power_supply_get_battery_info(axp20x_batt
->batt
, &info
)) {
605 int vmin
= info
.voltage_min_design_uv
;
606 int ccc
= info
.constant_charge_current_max_ua
;
608 if (vmin
> 0 && axp20x_set_voltage_min_design(axp20x_batt
,
611 "couldn't set voltage_min_design\n");
613 /* Set max to unverified value to be able to set CCC */
614 axp20x_batt
->max_ccc
= ccc
;
616 if (ccc
<= 0 || axp20x_set_constant_charge_current(axp20x_batt
,
619 "couldn't set constant charge current from DT: fallback to minimum value\n");
621 axp20x_batt
->max_ccc
= ccc
;
622 axp20x_set_constant_charge_current(axp20x_batt
, ccc
);
627 * Update max CCC to a valid value if battery info is present or set it
628 * to current register value by default.
630 axp20x_get_constant_charge_current(axp20x_batt
,
631 &axp20x_batt
->max_ccc
);
636 static struct platform_driver axp20x_batt_driver
= {
637 .probe
= axp20x_power_probe
,
639 .name
= "axp20x-battery-power-supply",
640 .of_match_table
= axp20x_battery_ps_id
,
644 module_platform_driver(axp20x_batt_driver
);
646 MODULE_DESCRIPTION("Battery power supply driver for AXP20X and AXP22X PMICs");
647 MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>");
648 MODULE_LICENSE("GPL");