Merge tag 'block-5.11-2021-01-10' of git://git.kernel.dk/linux-block
[linux/fpc-iii.git] / drivers / power / supply / axp20x_battery.c
blobe84b6e4da14a8a9e522c18dffad341a403301c88
1 /*
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>
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>
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;
60 struct axp_data {
61 int ccc_scale;
62 int ccc_offset;
63 bool has_fg_valid;
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;
71 struct device *dev;
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 */
76 unsigned int max_ccc;
77 const struct axp_data *data;
80 static int axp20x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
81 int *val)
83 int ret, reg;
85 ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, &reg);
86 if (ret)
87 return ret;
89 switch (reg & AXP20X_CHRG_CTRL1_TGT_VOLT) {
90 case AXP20X_CHRG_CTRL1_TGT_4_1V:
91 *val = 4100000;
92 break;
93 case AXP20X_CHRG_CTRL1_TGT_4_15V:
94 *val = 4150000;
95 break;
96 case AXP20X_CHRG_CTRL1_TGT_4_2V:
97 *val = 4200000;
98 break;
99 case AXP20X_CHRG_CTRL1_TGT_4_36V:
100 *val = 4360000;
101 break;
102 default:
103 return -EINVAL;
106 return 0;
109 static int axp22x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
110 int *val)
112 int ret, reg;
114 ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, &reg);
115 if (ret)
116 return ret;
118 switch (reg & AXP20X_CHRG_CTRL1_TGT_VOLT) {
119 case AXP20X_CHRG_CTRL1_TGT_4_1V:
120 *val = 4100000;
121 break;
122 case AXP20X_CHRG_CTRL1_TGT_4_2V:
123 *val = 4200000;
124 break;
125 case AXP22X_CHRG_CTRL1_TGT_4_22V:
126 *val = 4220000;
127 break;
128 case AXP22X_CHRG_CTRL1_TGT_4_24V:
129 *val = 4240000;
130 break;
131 default:
132 return -EINVAL;
135 return 0;
138 static int axp813_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
139 int *val)
141 int ret, reg;
143 ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, &reg);
144 if (ret)
145 return ret;
147 switch (reg & AXP20X_CHRG_CTRL1_TGT_VOLT) {
148 case AXP20X_CHRG_CTRL1_TGT_4_1V:
149 *val = 4100000;
150 break;
151 case AXP20X_CHRG_CTRL1_TGT_4_15V:
152 *val = 4150000;
153 break;
154 case AXP20X_CHRG_CTRL1_TGT_4_2V:
155 *val = 4200000;
156 break;
157 case AXP813_CHRG_CTRL1_TGT_4_35V:
158 *val = 4350000;
159 break;
160 default:
161 return -EINVAL;
164 return 0;
167 static int axp20x_get_constant_charge_current(struct axp20x_batt_ps *axp,
168 int *val)
170 int ret;
172 ret = regmap_read(axp->regmap, AXP20X_CHRG_CTRL1, val);
173 if (ret)
174 return ret;
176 *val &= AXP20X_CHRG_CTRL1_TGT_CURR;
178 *val = *val * axp->data->ccc_scale + axp->data->ccc_offset;
180 return 0;
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;
191 switch (psp) {
192 case POWER_SUPPLY_PROP_PRESENT:
193 case POWER_SUPPLY_PROP_ONLINE:
194 ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_OP_MODE,
195 &reg);
196 if (ret)
197 return ret;
199 val->intval = !!(reg & AXP20X_PWR_OP_BATT_PRESENT);
200 break;
202 case POWER_SUPPLY_PROP_STATUS:
203 ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_INPUT_STATUS,
204 &reg);
205 if (ret)
206 return ret;
208 if (reg & AXP20X_PWR_STATUS_BAT_CHARGING) {
209 val->intval = POWER_SUPPLY_STATUS_CHARGING;
210 return 0;
213 ret = iio_read_channel_processed(axp20x_batt->batt_dischrg_i,
214 &val1);
215 if (ret)
216 return ret;
218 if (val1) {
219 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
220 return 0;
223 ret = regmap_read(axp20x_batt->regmap, AXP20X_FG_RES, &val1);
224 if (ret)
225 return ret;
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;
233 else
234 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
235 break;
237 case POWER_SUPPLY_PROP_HEALTH:
238 ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_OP_MODE,
239 &val1);
240 if (ret)
241 return ret;
243 if (val1 & AXP20X_PWR_OP_BATT_ACTIVATED) {
244 val->intval = POWER_SUPPLY_HEALTH_DEAD;
245 return 0;
248 val->intval = POWER_SUPPLY_HEALTH_GOOD;
249 break;
251 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
252 ret = axp20x_get_constant_charge_current(axp20x_batt,
253 &val->intval);
254 if (ret)
255 return ret;
256 break;
258 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
259 val->intval = axp20x_batt->max_ccc;
260 break;
262 case POWER_SUPPLY_PROP_CURRENT_NOW:
263 ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_INPUT_STATUS,
264 &reg);
265 if (ret)
266 return ret;
268 if (reg & AXP20X_PWR_STATUS_BAT_CHARGING)
269 chan = axp20x_batt->batt_chrg_i;
270 else
271 chan = axp20x_batt->batt_dischrg_i;
273 ret = iio_read_channel_processed(chan, &val->intval);
274 if (ret)
275 return ret;
277 /* IIO framework gives mA but Power Supply framework gives uA */
278 val->intval *= 1000;
279 break;
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,
284 &reg);
285 if (ret)
286 return ret;
288 if (!(reg & AXP20X_PWR_OP_BATT_PRESENT)) {
289 val->intval = 100;
290 return 0;
293 ret = regmap_read(axp20x_batt->regmap, AXP20X_FG_RES, &reg);
294 if (ret)
295 return ret;
297 if (axp20x_batt->data->has_fg_valid && !(reg & AXP22X_FG_VALID))
298 return -EINVAL;
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;
305 break;
307 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
308 return axp20x_batt->data->get_max_voltage(axp20x_batt,
309 &val->intval);
311 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
312 ret = regmap_read(axp20x_batt->regmap, AXP20X_V_OFF, &reg);
313 if (ret)
314 return ret;
316 val->intval = 2600000 + 100000 * (reg & AXP20X_V_OFF_MASK);
317 break;
319 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
320 ret = iio_read_channel_processed(axp20x_batt->batt_v,
321 &val->intval);
322 if (ret)
323 return ret;
325 /* IIO framework gives mV but Power Supply framework gives uV */
326 val->intval *= 1000;
327 break;
329 default:
330 return -EINVAL;
333 return 0;
336 static int axp22x_battery_set_max_voltage(struct axp20x_batt_ps *axp20x_batt,
337 int val)
339 switch (val) {
340 case 4100000:
341 val = AXP20X_CHRG_CTRL1_TGT_4_1V;
342 break;
344 case 4200000:
345 val = AXP20X_CHRG_CTRL1_TGT_4_2V;
346 break;
348 default:
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).
355 return -EINVAL;
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,
363 int val)
365 switch (val) {
366 case 4100000:
367 val = AXP20X_CHRG_CTRL1_TGT_4_1V;
368 break;
370 case 4150000:
371 val = AXP20X_CHRG_CTRL1_TGT_4_15V;
372 break;
374 case 4200000:
375 val = AXP20X_CHRG_CTRL1_TGT_4_2V;
376 break;
378 default:
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).
385 return -EINVAL;
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,
393 int charge_current)
395 if (charge_current > axp_batt->max_ccc)
396 return -EINVAL;
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)
402 return -EINVAL;
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,
409 int charge_current)
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)
417 return -EINVAL;
419 charge_current = charge_current * axp->data->ccc_scale +
420 axp->data->ccc_offset;
422 if (charge_current > axp->max_ccc)
423 dev_warn(axp->dev,
424 "Setting max constant charge current higher than previously defined. Note that increasing the constant charge current may damage your battery.\n");
425 else
426 lower_max = true;
428 axp->max_ccc = charge_current;
430 if (lower_max) {
431 int current_cc;
433 axp20x_get_constant_charge_current(axp, &current_cc);
434 if (current_cc > charge_current)
435 axp20x_set_constant_charge_current(axp, charge_current);
438 return 0;
440 static int axp20x_set_voltage_min_design(struct axp20x_batt_ps *axp_batt,
441 int min_voltage)
443 int val1 = (min_voltage - 2600000) / 100000;
445 if (val1 < 0 || val1 > AXP20X_V_OFF_MASK)
446 return -EINVAL;
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);
458 switch (psp) {
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,
467 val->intval);
468 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
469 return axp20x_set_max_constant_charge_current(axp20x_batt,
470 val->intval);
472 default:
473 return -EINVAL;
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 = {
511 .ccc_scale = 100000,
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 = {
518 .ccc_scale = 150000,
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 = {
526 .ccc_scale = 200000,
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,
537 }, {
538 .compatible = "x-powers,axp221-battery-power-supply",
539 .data = (void *)&axp221_data,
540 }, {
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))
555 return -ENODEV;
557 axp20x_batt = devm_kzalloc(&pdev->dev, sizeof(*axp20x_batt),
558 GFP_KERNEL);
559 if (!axp20x_batt)
560 return -ENOMEM;
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,
572 "batt_chrg_i");
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,
580 "batt_dischrg_i");
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,
597 &psy_cfg);
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,
609 vmin))
610 dev_err(&pdev->dev,
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,
617 ccc)) {
618 dev_err(&pdev->dev,
619 "couldn't set constant charge current from DT: fallback to minimum value\n");
620 ccc = 300000;
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);
633 return 0;
636 static struct platform_driver axp20x_batt_driver = {
637 .probe = axp20x_power_probe,
638 .driver = {
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");