GNU Linux-libre 4.14.290-gnu1
[releases.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_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 AXP20X_CHRG_CTRL1_TGT_CURR      GENMASK(3, 0)
53
54 #define AXP20X_V_OFF_MASK               GENMASK(2, 0)
55
56 struct axp20x_batt_ps {
57         struct regmap *regmap;
58         struct power_supply *batt;
59         struct device *dev;
60         struct iio_channel *batt_chrg_i;
61         struct iio_channel *batt_dischrg_i;
62         struct iio_channel *batt_v;
63         /* Maximum constant charge current */
64         unsigned int max_ccc;
65         u8 axp_id;
66 };
67
68 static int axp20x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
69                                           int *val)
70 {
71         int ret, reg;
72
73         ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, &reg);
74         if (ret)
75                 return ret;
76
77         switch (reg & AXP20X_CHRG_CTRL1_TGT_VOLT) {
78         case AXP20X_CHRG_CTRL1_TGT_4_1V:
79                 *val = 4100000;
80                 break;
81         case AXP20X_CHRG_CTRL1_TGT_4_15V:
82                 *val = 4150000;
83                 break;
84         case AXP20X_CHRG_CTRL1_TGT_4_2V:
85                 *val = 4200000;
86                 break;
87         case AXP20X_CHRG_CTRL1_TGT_4_36V:
88                 *val = 4360000;
89                 break;
90         default:
91                 return -EINVAL;
92         }
93
94         return 0;
95 }
96
97 static int axp22x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
98                                           int *val)
99 {
100         int ret, reg;
101
102         ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, &reg);
103         if (ret)
104                 return ret;
105
106         switch (reg & AXP20X_CHRG_CTRL1_TGT_VOLT) {
107         case AXP20X_CHRG_CTRL1_TGT_4_1V:
108                 *val = 4100000;
109                 break;
110         case AXP20X_CHRG_CTRL1_TGT_4_2V:
111                 *val = 4200000;
112                 break;
113         case AXP22X_CHRG_CTRL1_TGT_4_22V:
114                 *val = 4220000;
115                 break;
116         case AXP22X_CHRG_CTRL1_TGT_4_24V:
117                 *val = 4240000;
118                 break;
119         default:
120                 return -EINVAL;
121         }
122
123         return 0;
124 }
125
126 static void raw_to_constant_charge_current(struct axp20x_batt_ps *axp, int *val)
127 {
128         if (axp->axp_id == AXP209_ID)
129                 *val = *val * 100000 + 300000;
130         else
131                 *val = *val * 150000 + 300000;
132 }
133
134 static void constant_charge_current_to_raw(struct axp20x_batt_ps *axp, int *val)
135 {
136         if (axp->axp_id == AXP209_ID)
137                 *val = (*val - 300000) / 100000;
138         else
139                 *val = (*val - 300000) / 150000;
140 }
141
142 static int axp20x_get_constant_charge_current(struct axp20x_batt_ps *axp,
143                                               int *val)
144 {
145         int ret;
146
147         ret = regmap_read(axp->regmap, AXP20X_CHRG_CTRL1, val);
148         if (ret)
149                 return ret;
150
151         *val &= AXP20X_CHRG_CTRL1_TGT_CURR;
152
153         raw_to_constant_charge_current(axp, val);
154
155         return 0;
156 }
157
158 static int axp20x_battery_get_prop(struct power_supply *psy,
159                                    enum power_supply_property psp,
160                                    union power_supply_propval *val)
161 {
162         struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy);
163         int ret = 0, reg, val1;
164
165         switch (psp) {
166         case POWER_SUPPLY_PROP_PRESENT:
167         case POWER_SUPPLY_PROP_ONLINE:
168                 ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_OP_MODE,
169                                   &reg);
170                 if (ret)
171                         return ret;
172
173                 val->intval = !!(reg & AXP20X_PWR_OP_BATT_PRESENT);
174                 break;
175
176         case POWER_SUPPLY_PROP_STATUS:
177                 ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_INPUT_STATUS,
178                                   &reg);
179                 if (ret)
180                         return ret;
181
182                 if (reg & AXP20X_PWR_STATUS_BAT_CHARGING) {
183                         val->intval = POWER_SUPPLY_STATUS_CHARGING;
184                         return 0;
185                 }
186
187                 ret = iio_read_channel_processed(axp20x_batt->batt_dischrg_i,
188                                                  &val1);
189                 if (ret)
190                         return ret;
191
192                 if (val1) {
193                         val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
194                         return 0;
195                 }
196
197                 ret = regmap_read(axp20x_batt->regmap, AXP20X_FG_RES, &val1);
198                 if (ret)
199                         return ret;
200
201                 /*
202                  * Fuel Gauge data takes 7 bits but the stored value seems to be
203                  * directly the raw percentage without any scaling to 7 bits.
204                  */
205                 if ((val1 & AXP209_FG_PERCENT) == 100)
206                         val->intval = POWER_SUPPLY_STATUS_FULL;
207                 else
208                         val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
209                 break;
210
211         case POWER_SUPPLY_PROP_HEALTH:
212                 ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_OP_MODE,
213                                   &val1);
214                 if (ret)
215                         return ret;
216
217                 if (val1 & AXP20X_PWR_OP_BATT_ACTIVATED) {
218                         val->intval = POWER_SUPPLY_HEALTH_DEAD;
219                         return 0;
220                 }
221
222                 val->intval = POWER_SUPPLY_HEALTH_GOOD;
223                 break;
224
225         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
226                 ret = axp20x_get_constant_charge_current(axp20x_batt,
227                                                          &val->intval);
228                 if (ret)
229                         return ret;
230                 break;
231
232         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
233                 val->intval = axp20x_batt->max_ccc;
234                 break;
235
236         case POWER_SUPPLY_PROP_CURRENT_NOW:
237                 ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_INPUT_STATUS,
238                                   &reg);
239                 if (ret)
240                         return ret;
241
242                 if (reg & AXP20X_PWR_STATUS_BAT_CHARGING) {
243                         ret = iio_read_channel_processed(axp20x_batt->batt_chrg_i, &val->intval);
244                 } else {
245                         ret = iio_read_channel_processed(axp20x_batt->batt_dischrg_i, &val1);
246                         val->intval = -val1;
247                 }
248                 if (ret)
249                         return ret;
250
251                 /* IIO framework gives mA but Power Supply framework gives uA */
252                 val->intval *= 1000;
253                 break;
254
255         case POWER_SUPPLY_PROP_CAPACITY:
256                 /* When no battery is present, return capacity is 100% */
257                 ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_OP_MODE,
258                                   &reg);
259                 if (ret)
260                         return ret;
261
262                 if (!(reg & AXP20X_PWR_OP_BATT_PRESENT)) {
263                         val->intval = 100;
264                         return 0;
265                 }
266
267                 ret = regmap_read(axp20x_batt->regmap, AXP20X_FG_RES, &reg);
268                 if (ret)
269                         return ret;
270
271                 if (axp20x_batt->axp_id == AXP221_ID &&
272                     !(reg & AXP22X_FG_VALID))
273                         return -EINVAL;
274
275                 /*
276                  * Fuel Gauge data takes 7 bits but the stored value seems to be
277                  * directly the raw percentage without any scaling to 7 bits.
278                  */
279                 val->intval = reg & AXP209_FG_PERCENT;
280                 break;
281
282         case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
283                 if (axp20x_batt->axp_id == AXP209_ID)
284                         return axp20x_battery_get_max_voltage(axp20x_batt,
285                                                               &val->intval);
286                 return axp22x_battery_get_max_voltage(axp20x_batt,
287                                                       &val->intval);
288
289         case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
290                 ret = regmap_read(axp20x_batt->regmap, AXP20X_V_OFF, &reg);
291                 if (ret)
292                         return ret;
293
294                 val->intval = 2600000 + 100000 * (reg & AXP20X_V_OFF_MASK);
295                 break;
296
297         case POWER_SUPPLY_PROP_VOLTAGE_NOW:
298                 ret = iio_read_channel_processed(axp20x_batt->batt_v,
299                                                  &val->intval);
300                 if (ret)
301                         return ret;
302
303                 /* IIO framework gives mV but Power Supply framework gives uV */
304                 val->intval *= 1000;
305                 break;
306
307         default:
308                 return -EINVAL;
309         }
310
311         return 0;
312 }
313
314 static int axp20x_battery_set_max_voltage(struct axp20x_batt_ps *axp20x_batt,
315                                           int val)
316 {
317         switch (val) {
318         case 4100000:
319                 val = AXP20X_CHRG_CTRL1_TGT_4_1V;
320                 break;
321
322         case 4150000:
323                 if (axp20x_batt->axp_id == AXP221_ID)
324                         return -EINVAL;
325
326                 val = AXP20X_CHRG_CTRL1_TGT_4_15V;
327                 break;
328
329         case 4200000:
330                 val = AXP20X_CHRG_CTRL1_TGT_4_2V;
331                 break;
332
333         default:
334                 /*
335                  * AXP20x max voltage can be set to 4.36V and AXP22X max voltage
336                  * can be set to 4.22V and 4.24V, but these voltages are too
337                  * high for Lithium based batteries (AXP PMICs are supposed to
338                  * be used with these kinds of battery).
339                  */
340                 return -EINVAL;
341         }
342
343         return regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL1,
344                                   AXP20X_CHRG_CTRL1_TGT_VOLT, val);
345 }
346
347 static int axp20x_set_constant_charge_current(struct axp20x_batt_ps *axp_batt,
348                                               int charge_current)
349 {
350         if (charge_current > axp_batt->max_ccc)
351                 return -EINVAL;
352
353         constant_charge_current_to_raw(axp_batt, &charge_current);
354
355         if (charge_current > AXP20X_CHRG_CTRL1_TGT_CURR || charge_current < 0)
356                 return -EINVAL;
357
358         return regmap_update_bits(axp_batt->regmap, AXP20X_CHRG_CTRL1,
359                                   AXP20X_CHRG_CTRL1_TGT_CURR, charge_current);
360 }
361
362 static int axp20x_set_max_constant_charge_current(struct axp20x_batt_ps *axp,
363                                                   int charge_current)
364 {
365         bool lower_max = false;
366
367         constant_charge_current_to_raw(axp, &charge_current);
368
369         if (charge_current > AXP20X_CHRG_CTRL1_TGT_CURR || charge_current < 0)
370                 return -EINVAL;
371
372         raw_to_constant_charge_current(axp, &charge_current);
373
374         if (charge_current > axp->max_ccc)
375                 dev_warn(axp->dev,
376                          "Setting max constant charge current higher than previously defined. Note that increasing the constant charge current may damage your battery.\n");
377         else
378                 lower_max = true;
379
380         axp->max_ccc = charge_current;
381
382         if (lower_max) {
383                 int current_cc;
384
385                 axp20x_get_constant_charge_current(axp, &current_cc);
386                 if (current_cc > charge_current)
387                         axp20x_set_constant_charge_current(axp, charge_current);
388         }
389
390         return 0;
391 }
392 static int axp20x_set_voltage_min_design(struct axp20x_batt_ps *axp_batt,
393                                          int min_voltage)
394 {
395         int val1 = (min_voltage - 2600000) / 100000;
396
397         if (val1 < 0 || val1 > AXP20X_V_OFF_MASK)
398                 return -EINVAL;
399
400         return regmap_update_bits(axp_batt->regmap, AXP20X_V_OFF,
401                                   AXP20X_V_OFF_MASK, val1);
402 }
403
404 static int axp20x_battery_set_prop(struct power_supply *psy,
405                                    enum power_supply_property psp,
406                                    const union power_supply_propval *val)
407 {
408         struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy);
409
410         switch (psp) {
411         case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
412                 return axp20x_set_voltage_min_design(axp20x_batt, val->intval);
413
414         case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
415                 return axp20x_battery_set_max_voltage(axp20x_batt, val->intval);
416
417         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
418                 return axp20x_set_constant_charge_current(axp20x_batt,
419                                                           val->intval);
420         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
421                 return axp20x_set_max_constant_charge_current(axp20x_batt,
422                                                               val->intval);
423
424         default:
425                 return -EINVAL;
426         }
427 }
428
429 static enum power_supply_property axp20x_battery_props[] = {
430         POWER_SUPPLY_PROP_PRESENT,
431         POWER_SUPPLY_PROP_ONLINE,
432         POWER_SUPPLY_PROP_STATUS,
433         POWER_SUPPLY_PROP_VOLTAGE_NOW,
434         POWER_SUPPLY_PROP_CURRENT_NOW,
435         POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
436         POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
437         POWER_SUPPLY_PROP_HEALTH,
438         POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
439         POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
440         POWER_SUPPLY_PROP_CAPACITY,
441 };
442
443 static int axp20x_battery_prop_writeable(struct power_supply *psy,
444                                          enum power_supply_property psp)
445 {
446         return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN ||
447                psp == POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN ||
448                psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT ||
449                psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX;
450 }
451
452 static const struct power_supply_desc axp20x_batt_ps_desc = {
453         .name = "axp20x-battery",
454         .type = POWER_SUPPLY_TYPE_BATTERY,
455         .properties = axp20x_battery_props,
456         .num_properties = ARRAY_SIZE(axp20x_battery_props),
457         .property_is_writeable = axp20x_battery_prop_writeable,
458         .get_property = axp20x_battery_get_prop,
459         .set_property = axp20x_battery_set_prop,
460 };
461
462 static const struct of_device_id axp20x_battery_ps_id[] = {
463         {
464                 .compatible = "x-powers,axp209-battery-power-supply",
465                 .data = (void *)AXP209_ID,
466         }, {
467                 .compatible = "x-powers,axp221-battery-power-supply",
468                 .data = (void *)AXP221_ID,
469         }, { /* sentinel */ },
470 };
471 MODULE_DEVICE_TABLE(of, axp20x_battery_ps_id);
472
473 static int axp20x_power_probe(struct platform_device *pdev)
474 {
475         struct axp20x_batt_ps *axp20x_batt;
476         struct power_supply_config psy_cfg = {};
477         struct power_supply_battery_info info;
478
479         if (!of_device_is_available(pdev->dev.of_node))
480                 return -ENODEV;
481
482         axp20x_batt = devm_kzalloc(&pdev->dev, sizeof(*axp20x_batt),
483                                    GFP_KERNEL);
484         if (!axp20x_batt)
485                 return -ENOMEM;
486
487         axp20x_batt->dev = &pdev->dev;
488
489         axp20x_batt->batt_v = devm_iio_channel_get(&pdev->dev, "batt_v");
490         if (IS_ERR(axp20x_batt->batt_v)) {
491                 if (PTR_ERR(axp20x_batt->batt_v) == -ENODEV)
492                         return -EPROBE_DEFER;
493                 return PTR_ERR(axp20x_batt->batt_v);
494         }
495
496         axp20x_batt->batt_chrg_i = devm_iio_channel_get(&pdev->dev,
497                                                         "batt_chrg_i");
498         if (IS_ERR(axp20x_batt->batt_chrg_i)) {
499                 if (PTR_ERR(axp20x_batt->batt_chrg_i) == -ENODEV)
500                         return -EPROBE_DEFER;
501                 return PTR_ERR(axp20x_batt->batt_chrg_i);
502         }
503
504         axp20x_batt->batt_dischrg_i = devm_iio_channel_get(&pdev->dev,
505                                                            "batt_dischrg_i");
506         if (IS_ERR(axp20x_batt->batt_dischrg_i)) {
507                 if (PTR_ERR(axp20x_batt->batt_dischrg_i) == -ENODEV)
508                         return -EPROBE_DEFER;
509                 return PTR_ERR(axp20x_batt->batt_dischrg_i);
510         }
511
512         axp20x_batt->regmap = dev_get_regmap(pdev->dev.parent, NULL);
513         platform_set_drvdata(pdev, axp20x_batt);
514
515         psy_cfg.drv_data = axp20x_batt;
516         psy_cfg.of_node = pdev->dev.of_node;
517
518         axp20x_batt->axp_id = (uintptr_t)of_device_get_match_data(&pdev->dev);
519
520         axp20x_batt->batt = devm_power_supply_register(&pdev->dev,
521                                                        &axp20x_batt_ps_desc,
522                                                        &psy_cfg);
523         if (IS_ERR(axp20x_batt->batt)) {
524                 dev_err(&pdev->dev, "failed to register power supply: %ld\n",
525                         PTR_ERR(axp20x_batt->batt));
526                 return PTR_ERR(axp20x_batt->batt);
527         }
528
529         if (!power_supply_get_battery_info(axp20x_batt->batt, &info)) {
530                 int vmin = info.voltage_min_design_uv;
531                 int ccc = info.constant_charge_current_max_ua;
532
533                 if (vmin > 0 && axp20x_set_voltage_min_design(axp20x_batt,
534                                                               vmin))
535                         dev_err(&pdev->dev,
536                                 "couldn't set voltage_min_design\n");
537
538                 /* Set max to unverified value to be able to set CCC */
539                 axp20x_batt->max_ccc = ccc;
540
541                 if (ccc <= 0 || axp20x_set_constant_charge_current(axp20x_batt,
542                                                                    ccc)) {
543                         dev_err(&pdev->dev,
544                                 "couldn't set constant charge current from DT: fallback to minimum value\n");
545                         ccc = 300000;
546                         axp20x_batt->max_ccc = ccc;
547                         axp20x_set_constant_charge_current(axp20x_batt, ccc);
548                 }
549         }
550
551         /*
552          * Update max CCC to a valid value if battery info is present or set it
553          * to current register value by default.
554          */
555         axp20x_get_constant_charge_current(axp20x_batt,
556                                            &axp20x_batt->max_ccc);
557
558         return 0;
559 }
560
561 static struct platform_driver axp20x_batt_driver = {
562         .probe    = axp20x_power_probe,
563         .driver   = {
564                 .name  = "axp20x-battery-power-supply",
565                 .of_match_table = axp20x_battery_ps_id,
566         },
567 };
568
569 module_platform_driver(axp20x_batt_driver);
570
571 MODULE_DESCRIPTION("Battery power supply driver for AXP20X and AXP22X PMICs");
572 MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>");
573 MODULE_LICENSE("GPL");