This source file includes following definitions.
- axp20x_battery_get_max_voltage
- axp22x_battery_get_max_voltage
- axp813_battery_get_max_voltage
- axp20x_get_constant_charge_current
- axp20x_battery_get_prop
- axp22x_battery_set_max_voltage
- axp20x_battery_set_max_voltage
- axp20x_set_constant_charge_current
- axp20x_set_max_constant_charge_current
- axp20x_set_voltage_min_design
- axp20x_battery_set_prop
- axp20x_battery_prop_writeable
- axp20x_power_probe
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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_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)
48
49 #define AXP22X_CHRG_CTRL1_TGT_4_22V (1 << 5)
50 #define AXP22X_CHRG_CTRL1_TGT_4_24V (3 << 5)
51
52 #define AXP813_CHRG_CTRL1_TGT_4_35V (3 << 5)
53
54 #define AXP20X_CHRG_CTRL1_TGT_CURR GENMASK(3, 0)
55
56 #define AXP20X_V_OFF_MASK GENMASK(2, 0)
57
58 struct axp20x_batt_ps;
59
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);
66 };
67
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
76 unsigned int max_ccc;
77 const struct axp_data *data;
78 };
79
80 static int axp20x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
81 int *val)
82 {
83 int ret, reg;
84
85 ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, ®);
86 if (ret)
87 return ret;
88
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;
104 }
105
106 return 0;
107 }
108
109 static int axp22x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
110 int *val)
111 {
112 int ret, reg;
113
114 ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, ®);
115 if (ret)
116 return ret;
117
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;
133 }
134
135 return 0;
136 }
137
138 static int axp813_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
139 int *val)
140 {
141 int ret, reg;
142
143 ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, ®);
144 if (ret)
145 return ret;
146
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;
162 }
163
164 return 0;
165 }
166
167 static int axp20x_get_constant_charge_current(struct axp20x_batt_ps *axp,
168 int *val)
169 {
170 int ret;
171
172 ret = regmap_read(axp->regmap, AXP20X_CHRG_CTRL1, val);
173 if (ret)
174 return ret;
175
176 *val &= AXP20X_CHRG_CTRL1_TGT_CURR;
177
178 *val = *val * axp->data->ccc_scale + axp->data->ccc_offset;
179
180 return 0;
181 }
182
183 static int axp20x_battery_get_prop(struct power_supply *psy,
184 enum power_supply_property psp,
185 union power_supply_propval *val)
186 {
187 struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy);
188 struct iio_channel *chan;
189 int ret = 0, reg, val1;
190
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 ®);
196 if (ret)
197 return ret;
198
199 val->intval = !!(reg & AXP20X_PWR_OP_BATT_PRESENT);
200 break;
201
202 case POWER_SUPPLY_PROP_STATUS:
203 ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_INPUT_STATUS,
204 ®);
205 if (ret)
206 return ret;
207
208 if (reg & AXP20X_PWR_STATUS_BAT_CHARGING) {
209 val->intval = POWER_SUPPLY_STATUS_CHARGING;
210 return 0;
211 }
212
213 ret = iio_read_channel_processed(axp20x_batt->batt_dischrg_i,
214 &val1);
215 if (ret)
216 return ret;
217
218 if (val1) {
219 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
220 return 0;
221 }
222
223 ret = regmap_read(axp20x_batt->regmap, AXP20X_FG_RES, &val1);
224 if (ret)
225 return ret;
226
227
228
229
230
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;
236
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;
242
243 if (val1 & AXP20X_PWR_OP_BATT_ACTIVATED) {
244 val->intval = POWER_SUPPLY_HEALTH_DEAD;
245 return 0;
246 }
247
248 val->intval = POWER_SUPPLY_HEALTH_GOOD;
249 break;
250
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;
257
258 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
259 val->intval = axp20x_batt->max_ccc;
260 break;
261
262 case POWER_SUPPLY_PROP_CURRENT_NOW:
263 ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_INPUT_STATUS,
264 ®);
265 if (ret)
266 return ret;
267
268 if (reg & AXP20X_PWR_STATUS_BAT_CHARGING)
269 chan = axp20x_batt->batt_chrg_i;
270 else
271 chan = axp20x_batt->batt_dischrg_i;
272
273 ret = iio_read_channel_processed(chan, &val->intval);
274 if (ret)
275 return ret;
276
277
278 val->intval *= 1000;
279 break;
280
281 case POWER_SUPPLY_PROP_CAPACITY:
282
283 ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_OP_MODE,
284 ®);
285 if (ret)
286 return ret;
287
288 if (!(reg & AXP20X_PWR_OP_BATT_PRESENT)) {
289 val->intval = 100;
290 return 0;
291 }
292
293 ret = regmap_read(axp20x_batt->regmap, AXP20X_FG_RES, ®);
294 if (ret)
295 return ret;
296
297 if (axp20x_batt->data->has_fg_valid && !(reg & AXP22X_FG_VALID))
298 return -EINVAL;
299
300
301
302
303
304 val->intval = reg & AXP209_FG_PERCENT;
305 break;
306
307 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
308 return axp20x_batt->data->get_max_voltage(axp20x_batt,
309 &val->intval);
310
311 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
312 ret = regmap_read(axp20x_batt->regmap, AXP20X_V_OFF, ®);
313 if (ret)
314 return ret;
315
316 val->intval = 2600000 + 100000 * (reg & AXP20X_V_OFF_MASK);
317 break;
318
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;
324
325
326 val->intval *= 1000;
327 break;
328
329 default:
330 return -EINVAL;
331 }
332
333 return 0;
334 }
335
336 static int axp22x_battery_set_max_voltage(struct axp20x_batt_ps *axp20x_batt,
337 int val)
338 {
339 switch (val) {
340 case 4100000:
341 val = AXP20X_CHRG_CTRL1_TGT_4_1V;
342 break;
343
344 case 4200000:
345 val = AXP20X_CHRG_CTRL1_TGT_4_2V;
346 break;
347
348 default:
349
350
351
352
353
354
355 return -EINVAL;
356 }
357
358 return regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL1,
359 AXP20X_CHRG_CTRL1_TGT_VOLT, val);
360 }
361
362 static int axp20x_battery_set_max_voltage(struct axp20x_batt_ps *axp20x_batt,
363 int val)
364 {
365 switch (val) {
366 case 4100000:
367 val = AXP20X_CHRG_CTRL1_TGT_4_1V;
368 break;
369
370 case 4150000:
371 val = AXP20X_CHRG_CTRL1_TGT_4_15V;
372 break;
373
374 case 4200000:
375 val = AXP20X_CHRG_CTRL1_TGT_4_2V;
376 break;
377
378 default:
379
380
381
382
383
384
385 return -EINVAL;
386 }
387
388 return regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL1,
389 AXP20X_CHRG_CTRL1_TGT_VOLT, val);
390 }
391
392 static int axp20x_set_constant_charge_current(struct axp20x_batt_ps *axp_batt,
393 int charge_current)
394 {
395 if (charge_current > axp_batt->max_ccc)
396 return -EINVAL;
397
398 charge_current = (charge_current - axp_batt->data->ccc_offset) /
399 axp_batt->data->ccc_scale;
400
401 if (charge_current > AXP20X_CHRG_CTRL1_TGT_CURR || charge_current < 0)
402 return -EINVAL;
403
404 return regmap_update_bits(axp_batt->regmap, AXP20X_CHRG_CTRL1,
405 AXP20X_CHRG_CTRL1_TGT_CURR, charge_current);
406 }
407
408 static int axp20x_set_max_constant_charge_current(struct axp20x_batt_ps *axp,
409 int charge_current)
410 {
411 bool lower_max = false;
412
413 charge_current = (charge_current - axp->data->ccc_offset) /
414 axp->data->ccc_scale;
415
416 if (charge_current > AXP20X_CHRG_CTRL1_TGT_CURR || charge_current < 0)
417 return -EINVAL;
418
419 charge_current = charge_current * axp->data->ccc_scale +
420 axp->data->ccc_offset;
421
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;
427
428 axp->max_ccc = charge_current;
429
430 if (lower_max) {
431 int current_cc;
432
433 axp20x_get_constant_charge_current(axp, ¤t_cc);
434 if (current_cc > charge_current)
435 axp20x_set_constant_charge_current(axp, charge_current);
436 }
437
438 return 0;
439 }
440 static int axp20x_set_voltage_min_design(struct axp20x_batt_ps *axp_batt,
441 int min_voltage)
442 {
443 int val1 = (min_voltage - 2600000) / 100000;
444
445 if (val1 < 0 || val1 > AXP20X_V_OFF_MASK)
446 return -EINVAL;
447
448 return regmap_update_bits(axp_batt->regmap, AXP20X_V_OFF,
449 AXP20X_V_OFF_MASK, val1);
450 }
451
452 static int axp20x_battery_set_prop(struct power_supply *psy,
453 enum power_supply_property psp,
454 const union power_supply_propval *val)
455 {
456 struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy);
457
458 switch (psp) {
459 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
460 return axp20x_set_voltage_min_design(axp20x_batt, val->intval);
461
462 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
463 return axp20x_batt->data->set_max_voltage(axp20x_batt, val->intval);
464
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);
471
472 default:
473 return -EINVAL;
474 }
475 }
476
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,
489 };
490
491 static int axp20x_battery_prop_writeable(struct power_supply *psy,
492 enum power_supply_property psp)
493 {
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;
498 }
499
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,
508 };
509
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,
515 };
516
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,
523 };
524
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,
531 };
532
533 static const struct of_device_id axp20x_battery_ps_id[] = {
534 {
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 }, { },
544 };
545 MODULE_DEVICE_TABLE(of, axp20x_battery_ps_id);
546
547 static int axp20x_power_probe(struct platform_device *pdev)
548 {
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;
553
554 if (!of_device_is_available(pdev->dev.of_node))
555 return -ENODEV;
556
557 axp20x_batt = devm_kzalloc(&pdev->dev, sizeof(*axp20x_batt),
558 GFP_KERNEL);
559 if (!axp20x_batt)
560 return -ENOMEM;
561
562 axp20x_batt->dev = &pdev->dev;
563
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);
569 }
570
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);
577 }
578
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);
585 }
586
587 axp20x_batt->regmap = dev_get_regmap(pdev->dev.parent, NULL);
588 platform_set_drvdata(pdev, axp20x_batt);
589
590 psy_cfg.drv_data = axp20x_batt;
591 psy_cfg.of_node = pdev->dev.of_node;
592
593 axp20x_batt->data = (struct axp_data *)of_device_get_match_data(dev);
594
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);
602 }
603
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;
607
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");
612
613
614 axp20x_batt->max_ccc = ccc;
615
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);
623 }
624 }
625
626
627
628
629
630 axp20x_get_constant_charge_current(axp20x_batt,
631 &axp20x_batt->max_ccc);
632
633 return 0;
634 }
635
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,
641 },
642 };
643
644 module_platform_driver(axp20x_batt_driver);
645
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");