Merge tag 'libata-5.14-2021-07-30' of git://git.kernel.dk/linux-block
[linux-2.6-microblaze.git] / drivers / power / supply / axp20x_battery.c
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, &reg);
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, &reg);
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, &reg);
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                                   &reg);
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                                   &reg);
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                                   &reg);
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                                   &reg);
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, &reg);
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, &reg);
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, &current_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");