Merge v5.14-rc3 into usb-next
[linux-2.6-microblaze.git] / drivers / power / supply / rn5t618_power.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Power supply driver for the RICOH RN5T618 power management chip family
4  *
5  * Copyright (C) 2020 Andreas Kemnade
6  */
7
8 #include <linux/kernel.h>
9 #include <linux/device.h>
10 #include <linux/bitops.h>
11 #include <linux/errno.h>
12 #include <linux/init.h>
13 #include <linux/interrupt.h>
14 #include <linux/module.h>
15 #include <linux/mfd/rn5t618.h>
16 #include <linux/platform_device.h>
17 #include <linux/power_supply.h>
18 #include <linux/regmap.h>
19 #include <linux/slab.h>
20
21 #define CHG_STATE_ADP_INPUT 0x40
22 #define CHG_STATE_USB_INPUT 0x80
23 #define CHG_STATE_MASK  0x1f
24 #define CHG_STATE_CHG_OFF       0
25 #define CHG_STATE_CHG_READY_VADP        1
26 #define CHG_STATE_CHG_TRICKLE   2
27 #define CHG_STATE_CHG_RAPID     3
28 #define CHG_STATE_CHG_COMPLETE  4
29 #define CHG_STATE_SUSPEND       5
30 #define CHG_STATE_VCHG_OVER_VOL 6
31 #define CHG_STATE_BAT_ERROR     7
32 #define CHG_STATE_NO_BAT        8
33 #define CHG_STATE_BAT_OVER_VOL  9
34 #define CHG_STATE_BAT_TEMP_ERR  10
35 #define CHG_STATE_DIE_ERR       11
36 #define CHG_STATE_DIE_SHUTDOWN  12
37 #define CHG_STATE_NO_BAT2       13
38 #define CHG_STATE_CHG_READY_VUSB        14
39
40 #define GCHGDET_TYPE_MASK 0x30
41 #define GCHGDET_TYPE_SDP 0x00
42 #define GCHGDET_TYPE_CDP 0x10
43 #define GCHGDET_TYPE_DCP 0x20
44
45 #define FG_ENABLE 1
46
47 /*
48  * Formula seems accurate for battery current, but for USB current around 70mA
49  * per step was seen on Kobo Clara HD but all sources show the same formula
50  * also fur USB current. To avoid accidentially unwanted high currents we stick
51  * to that formula
52  */
53 #define TO_CUR_REG(x) ((x) / 100000 - 1)
54 #define FROM_CUR_REG(x) ((((x) & 0x1f) + 1) * 100000)
55 #define CHG_MIN_CUR 100000
56 #define CHG_MAX_CUR 1800000
57 #define ADP_MAX_CUR 2500000
58 #define USB_MAX_CUR 1400000
59
60
61 struct rn5t618_power_info {
62         struct rn5t618 *rn5t618;
63         struct platform_device *pdev;
64         struct power_supply *battery;
65         struct power_supply *usb;
66         struct power_supply *adp;
67         int irq;
68 };
69
70 static enum power_supply_usb_type rn5t618_usb_types[] = {
71         POWER_SUPPLY_USB_TYPE_SDP,
72         POWER_SUPPLY_USB_TYPE_DCP,
73         POWER_SUPPLY_USB_TYPE_CDP,
74         POWER_SUPPLY_USB_TYPE_UNKNOWN
75 };
76
77 static enum power_supply_property rn5t618_usb_props[] = {
78         /* input current limit is not very accurate */
79         POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
80         POWER_SUPPLY_PROP_STATUS,
81         POWER_SUPPLY_PROP_USB_TYPE,
82         POWER_SUPPLY_PROP_ONLINE,
83 };
84
85 static enum power_supply_property rn5t618_adp_props[] = {
86         /* input current limit is not very accurate */
87         POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
88         POWER_SUPPLY_PROP_STATUS,
89         POWER_SUPPLY_PROP_ONLINE,
90 };
91
92
93 static enum power_supply_property rn5t618_battery_props[] = {
94         POWER_SUPPLY_PROP_STATUS,
95         POWER_SUPPLY_PROP_PRESENT,
96         POWER_SUPPLY_PROP_VOLTAGE_NOW,
97         POWER_SUPPLY_PROP_CURRENT_NOW,
98         POWER_SUPPLY_PROP_CAPACITY,
99         POWER_SUPPLY_PROP_TEMP,
100         POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
101         POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
102         POWER_SUPPLY_PROP_TECHNOLOGY,
103         POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
104         POWER_SUPPLY_PROP_CHARGE_FULL,
105         POWER_SUPPLY_PROP_CHARGE_NOW,
106 };
107
108 static int rn5t618_battery_read_doublereg(struct rn5t618_power_info *info,
109                                           u8 reg, u16 *result)
110 {
111         int ret, i;
112         u8 data[2];
113         u16 old, new;
114
115         old = 0;
116         /* Prevent races when registers are changing. */
117         for (i = 0; i < 3; i++) {
118                 ret = regmap_bulk_read(info->rn5t618->regmap,
119                                        reg, data, sizeof(data));
120                 if (ret)
121                         return ret;
122
123                 new = data[0] << 8;
124                 new |= data[1];
125                 if (new == old)
126                         break;
127
128                 old = new;
129         }
130
131         *result = new;
132
133         return 0;
134 }
135
136 static int rn5t618_decode_status(unsigned int status)
137 {
138         switch (status & CHG_STATE_MASK) {
139         case CHG_STATE_CHG_OFF:
140         case CHG_STATE_SUSPEND:
141         case CHG_STATE_VCHG_OVER_VOL:
142         case CHG_STATE_DIE_SHUTDOWN:
143                 return POWER_SUPPLY_STATUS_DISCHARGING;
144
145         case CHG_STATE_CHG_TRICKLE:
146         case CHG_STATE_CHG_RAPID:
147                 return POWER_SUPPLY_STATUS_CHARGING;
148
149         case CHG_STATE_CHG_COMPLETE:
150                 return POWER_SUPPLY_STATUS_FULL;
151
152         default:
153                 return POWER_SUPPLY_STATUS_NOT_CHARGING;
154         }
155 }
156
157 static int rn5t618_battery_status(struct rn5t618_power_info *info,
158                                   union power_supply_propval *val)
159 {
160         unsigned int v;
161         int ret;
162
163         ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGSTATE, &v);
164         if (ret)
165                 return ret;
166
167         val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
168
169         if (v & 0xc0) { /* USB or ADP plugged */
170                 val->intval = rn5t618_decode_status(v);
171         } else
172                 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
173
174         return ret;
175 }
176
177 static int rn5t618_battery_present(struct rn5t618_power_info *info,
178                                    union power_supply_propval *val)
179 {
180         unsigned int v;
181         int ret;
182
183         ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGSTATE, &v);
184         if (ret)
185                 return ret;
186
187         v &= CHG_STATE_MASK;
188         if ((v == CHG_STATE_NO_BAT) || (v == CHG_STATE_NO_BAT2))
189                 val->intval = 0;
190         else
191                 val->intval = 1;
192
193         return ret;
194 }
195
196 static int rn5t618_battery_voltage_now(struct rn5t618_power_info *info,
197                                        union power_supply_propval *val)
198 {
199         u16 res;
200         int ret;
201
202         ret = rn5t618_battery_read_doublereg(info, RN5T618_VOLTAGE_1, &res);
203         if (ret)
204                 return ret;
205
206         val->intval = res * 2 * 2500 / 4095 * 1000;
207
208         return 0;
209 }
210
211 static int rn5t618_battery_current_now(struct rn5t618_power_info *info,
212                                        union power_supply_propval *val)
213 {
214         u16 res;
215         int ret;
216
217         ret = rn5t618_battery_read_doublereg(info, RN5T618_CC_AVEREG1, &res);
218         if (ret)
219                 return ret;
220
221         /* current is negative when discharging */
222         val->intval = sign_extend32(res, 13) * 1000;
223
224         return 0;
225 }
226
227 static int rn5t618_battery_capacity(struct rn5t618_power_info *info,
228                                     union power_supply_propval *val)
229 {
230         unsigned int v;
231         int ret;
232
233         ret = regmap_read(info->rn5t618->regmap, RN5T618_SOC, &v);
234         if (ret)
235                 return ret;
236
237         val->intval = v;
238
239         return 0;
240 }
241
242 static int rn5t618_battery_temp(struct rn5t618_power_info *info,
243                                 union power_supply_propval *val)
244 {
245         u16 res;
246         int ret;
247
248         ret = rn5t618_battery_read_doublereg(info, RN5T618_TEMP_1, &res);
249         if (ret)
250                 return ret;
251
252         val->intval = sign_extend32(res, 11) * 10 / 16;
253
254         return 0;
255 }
256
257 static int rn5t618_battery_tte(struct rn5t618_power_info *info,
258                                union power_supply_propval *val)
259 {
260         u16 res;
261         int ret;
262
263         ret = rn5t618_battery_read_doublereg(info, RN5T618_TT_EMPTY_H, &res);
264         if (ret)
265                 return ret;
266
267         if (res == 65535)
268                 return -ENODATA;
269
270         val->intval = res * 60;
271
272         return 0;
273 }
274
275 static int rn5t618_battery_ttf(struct rn5t618_power_info *info,
276                                union power_supply_propval *val)
277 {
278         u16 res;
279         int ret;
280
281         ret = rn5t618_battery_read_doublereg(info, RN5T618_TT_FULL_H, &res);
282         if (ret)
283                 return ret;
284
285         if (res == 65535)
286                 return -ENODATA;
287
288         val->intval = res * 60;
289
290         return 0;
291 }
292
293 static int rn5t618_battery_set_current_limit(struct rn5t618_power_info *info,
294                                 const union power_supply_propval *val)
295 {
296         if (val->intval < CHG_MIN_CUR)
297                 return -EINVAL;
298
299         if (val->intval >= CHG_MAX_CUR)
300                 return -EINVAL;
301
302         return regmap_update_bits(info->rn5t618->regmap,
303                                   RN5T618_CHGISET,
304                                   0x1F, TO_CUR_REG(val->intval));
305 }
306
307 static int rn5t618_battery_get_current_limit(struct rn5t618_power_info *info,
308                                              union power_supply_propval *val)
309 {
310         unsigned int regval;
311         int ret;
312
313         ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGISET,
314                           &regval);
315         if (ret < 0)
316                 return ret;
317
318         val->intval = FROM_CUR_REG(regval);
319
320         return 0;
321 }
322
323 static int rn5t618_battery_charge_full(struct rn5t618_power_info *info,
324                                        union power_supply_propval *val)
325 {
326         u16 res;
327         int ret;
328
329         ret = rn5t618_battery_read_doublereg(info, RN5T618_FA_CAP_H, &res);
330         if (ret)
331                 return ret;
332
333         val->intval = res * 1000;
334
335         return 0;
336 }
337
338 static int rn5t618_battery_charge_now(struct rn5t618_power_info *info,
339                                       union power_supply_propval *val)
340 {
341         u16 res;
342         int ret;
343
344         ret = rn5t618_battery_read_doublereg(info, RN5T618_RE_CAP_H, &res);
345         if (ret)
346                 return ret;
347
348         val->intval = res * 1000;
349
350         return 0;
351 }
352
353 static int rn5t618_battery_get_property(struct power_supply *psy,
354                                         enum power_supply_property psp,
355                                         union power_supply_propval *val)
356 {
357         int ret = 0;
358         struct rn5t618_power_info *info = power_supply_get_drvdata(psy);
359
360         switch (psp) {
361         case POWER_SUPPLY_PROP_STATUS:
362                 ret = rn5t618_battery_status(info, val);
363                 break;
364         case POWER_SUPPLY_PROP_PRESENT:
365                 ret = rn5t618_battery_present(info, val);
366                 break;
367         case POWER_SUPPLY_PROP_VOLTAGE_NOW:
368                 ret = rn5t618_battery_voltage_now(info, val);
369                 break;
370         case POWER_SUPPLY_PROP_CURRENT_NOW:
371                 ret = rn5t618_battery_current_now(info, val);
372                 break;
373         case POWER_SUPPLY_PROP_CAPACITY:
374                 ret = rn5t618_battery_capacity(info, val);
375                 break;
376         case POWER_SUPPLY_PROP_TEMP:
377                 ret = rn5t618_battery_temp(info, val);
378                 break;
379         case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
380                 ret = rn5t618_battery_tte(info, val);
381                 break;
382         case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
383                 ret = rn5t618_battery_ttf(info, val);
384                 break;
385         case POWER_SUPPLY_PROP_TECHNOLOGY:
386                 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
387                 break;
388         case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
389                 ret = rn5t618_battery_get_current_limit(info, val);
390                 break;
391         case POWER_SUPPLY_PROP_CHARGE_FULL:
392                 ret = rn5t618_battery_charge_full(info, val);
393                 break;
394         case POWER_SUPPLY_PROP_CHARGE_NOW:
395                 ret = rn5t618_battery_charge_now(info, val);
396                 break;
397         default:
398                 return -EINVAL;
399         }
400
401         return ret;
402 }
403
404 static int rn5t618_battery_set_property(struct power_supply *psy,
405                                         enum power_supply_property psp,
406                                         const union power_supply_propval *val)
407 {
408         struct rn5t618_power_info *info = power_supply_get_drvdata(psy);
409
410         switch (psp) {
411         case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
412                 return rn5t618_battery_set_current_limit(info, val);
413         default:
414                 return -EINVAL;
415         }
416 }
417
418 static int rn5t618_battery_property_is_writeable(struct power_supply *psy,
419                                                 enum power_supply_property psp)
420 {
421         switch (psp) {
422         case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
423                 return true;
424         default:
425                 return false;
426         }
427 }
428
429 static int rn5t618_adp_get_property(struct power_supply *psy,
430                                     enum power_supply_property psp,
431                                     union power_supply_propval *val)
432 {
433         struct rn5t618_power_info *info = power_supply_get_drvdata(psy);
434         unsigned int chgstate;
435         unsigned int regval;
436         bool online;
437         int ret;
438
439         ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGSTATE, &chgstate);
440         if (ret)
441                 return ret;
442
443         online = !!(chgstate & CHG_STATE_ADP_INPUT);
444
445         switch (psp) {
446         case POWER_SUPPLY_PROP_ONLINE:
447                 val->intval = online;
448                 break;
449         case POWER_SUPPLY_PROP_STATUS:
450                 if (!online) {
451                         val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
452                         break;
453                 }
454                 val->intval = rn5t618_decode_status(chgstate);
455                 if (val->intval != POWER_SUPPLY_STATUS_CHARGING)
456                         val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
457
458                 break;
459         case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
460                 ret = regmap_read(info->rn5t618->regmap,
461                                   RN5T618_REGISET1, &regval);
462                 if (ret < 0)
463                         return ret;
464
465                 val->intval = FROM_CUR_REG(regval);
466                 break;
467         default:
468                 return -EINVAL;
469         }
470
471         return 0;
472 }
473
474 static int rn5t618_adp_set_property(struct power_supply *psy,
475                                     enum power_supply_property psp,
476                                     const union power_supply_propval *val)
477 {
478         struct rn5t618_power_info *info = power_supply_get_drvdata(psy);
479         int ret;
480
481         switch (psp) {
482         case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
483                 if (val->intval > ADP_MAX_CUR)
484                         return -EINVAL;
485
486                 if (val->intval < CHG_MIN_CUR)
487                         return -EINVAL;
488
489                 ret = regmap_write(info->rn5t618->regmap, RN5T618_REGISET1,
490                                    TO_CUR_REG(val->intval));
491                 if (ret < 0)
492                         return ret;
493
494                 break;
495         default:
496                 return -EINVAL;
497         }
498
499         return 0;
500 }
501
502 static int rn5t618_adp_property_is_writeable(struct power_supply *psy,
503                                              enum power_supply_property psp)
504 {
505         switch (psp) {
506         case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
507                 return true;
508         default:
509                 return false;
510         }
511 }
512
513 static int rc5t619_usb_get_type(struct rn5t618_power_info *info,
514                                 union power_supply_propval *val)
515 {
516         unsigned int regval;
517         int ret;
518
519         ret = regmap_read(info->rn5t618->regmap, RN5T618_GCHGDET, &regval);
520         if (ret < 0)
521                 return ret;
522
523         switch (regval & GCHGDET_TYPE_MASK) {
524         case GCHGDET_TYPE_SDP:
525                 val->intval = POWER_SUPPLY_USB_TYPE_SDP;
526                 break;
527         case GCHGDET_TYPE_CDP:
528                 val->intval = POWER_SUPPLY_USB_TYPE_CDP;
529                 break;
530         case GCHGDET_TYPE_DCP:
531                 val->intval = POWER_SUPPLY_USB_TYPE_DCP;
532                 break;
533         default:
534                 val->intval = POWER_SUPPLY_USB_TYPE_UNKNOWN;
535         }
536
537         return 0;
538 }
539
540 static int rn5t618_usb_get_property(struct power_supply *psy,
541                                     enum power_supply_property psp,
542                                     union power_supply_propval *val)
543 {
544         struct rn5t618_power_info *info = power_supply_get_drvdata(psy);
545         unsigned int chgstate;
546         unsigned int regval;
547         bool online;
548         int ret;
549
550         ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGSTATE, &chgstate);
551         if (ret)
552                 return ret;
553
554         online = !!(chgstate & CHG_STATE_USB_INPUT);
555
556         switch (psp) {
557         case POWER_SUPPLY_PROP_ONLINE:
558                 val->intval = online;
559                 break;
560         case POWER_SUPPLY_PROP_STATUS:
561                 if (!online) {
562                         val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
563                         break;
564                 }
565                 val->intval = rn5t618_decode_status(chgstate);
566                 if (val->intval != POWER_SUPPLY_STATUS_CHARGING)
567                         val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
568
569                 break;
570         case POWER_SUPPLY_PROP_USB_TYPE:
571                 if (!online || (info->rn5t618->variant != RC5T619))
572                         return -ENODATA;
573
574                 return rc5t619_usb_get_type(info, val);
575         case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
576                 ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGCTL1,
577                                   &regval);
578                 if (ret < 0)
579                         return ret;
580
581                 val->intval = 0;
582                 if (regval & 2) {
583                         ret = regmap_read(info->rn5t618->regmap,
584                                           RN5T618_REGISET2,
585                                           &regval);
586                         if (ret < 0)
587                                 return ret;
588
589                         val->intval = FROM_CUR_REG(regval);
590                 }
591                 break;
592         default:
593                 return -EINVAL;
594         }
595
596         return 0;
597 }
598
599 static int rn5t618_usb_set_property(struct power_supply *psy,
600                                     enum power_supply_property psp,
601                                     const union power_supply_propval *val)
602 {
603         struct rn5t618_power_info *info = power_supply_get_drvdata(psy);
604         int ret;
605
606         switch (psp) {
607         case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
608                 if (val->intval > USB_MAX_CUR)
609                         return -EINVAL;
610
611                 if (val->intval < CHG_MIN_CUR)
612                         return -EINVAL;
613
614                 ret = regmap_write(info->rn5t618->regmap, RN5T618_REGISET2,
615                                    0xE0 | TO_CUR_REG(val->intval));
616                 if (ret < 0)
617                         return ret;
618
619                 break;
620         default:
621                 return -EINVAL;
622         }
623
624         return 0;
625 }
626
627 static int rn5t618_usb_property_is_writeable(struct power_supply *psy,
628                                              enum power_supply_property psp)
629 {
630         switch (psp) {
631         case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
632                 return true;
633         default:
634                 return false;
635         }
636 }
637
638 static const struct power_supply_desc rn5t618_battery_desc = {
639         .name                   = "rn5t618-battery",
640         .type                   = POWER_SUPPLY_TYPE_BATTERY,
641         .properties             = rn5t618_battery_props,
642         .num_properties         = ARRAY_SIZE(rn5t618_battery_props),
643         .get_property           = rn5t618_battery_get_property,
644         .set_property           = rn5t618_battery_set_property,
645         .property_is_writeable  = rn5t618_battery_property_is_writeable,
646 };
647
648 static const struct power_supply_desc rn5t618_adp_desc = {
649         .name                   = "rn5t618-adp",
650         .type                   = POWER_SUPPLY_TYPE_MAINS,
651         .properties             = rn5t618_adp_props,
652         .num_properties         = ARRAY_SIZE(rn5t618_adp_props),
653         .get_property           = rn5t618_adp_get_property,
654         .set_property           = rn5t618_adp_set_property,
655         .property_is_writeable  = rn5t618_adp_property_is_writeable,
656 };
657
658 static const struct power_supply_desc rn5t618_usb_desc = {
659         .name                   = "rn5t618-usb",
660         .type                   = POWER_SUPPLY_TYPE_USB,
661         .usb_types              = rn5t618_usb_types,
662         .num_usb_types          = ARRAY_SIZE(rn5t618_usb_types),
663         .properties             = rn5t618_usb_props,
664         .num_properties         = ARRAY_SIZE(rn5t618_usb_props),
665         .get_property           = rn5t618_usb_get_property,
666         .set_property           = rn5t618_usb_set_property,
667         .property_is_writeable  = rn5t618_usb_property_is_writeable,
668 };
669
670 static irqreturn_t rn5t618_charger_irq(int irq, void *data)
671 {
672         struct device *dev = data;
673         struct rn5t618_power_info *info = dev_get_drvdata(dev);
674
675         unsigned int ctrl, stat1, stat2, err;
676
677         regmap_read(info->rn5t618->regmap, RN5T618_CHGERR_IRR, &err);
678         regmap_read(info->rn5t618->regmap, RN5T618_CHGCTRL_IRR, &ctrl);
679         regmap_read(info->rn5t618->regmap, RN5T618_CHGSTAT_IRR1, &stat1);
680         regmap_read(info->rn5t618->regmap, RN5T618_CHGSTAT_IRR2, &stat2);
681
682         regmap_write(info->rn5t618->regmap, RN5T618_CHGERR_IRR, 0);
683         regmap_write(info->rn5t618->regmap, RN5T618_CHGCTRL_IRR, 0);
684         regmap_write(info->rn5t618->regmap, RN5T618_CHGSTAT_IRR1, 0);
685         regmap_write(info->rn5t618->regmap, RN5T618_CHGSTAT_IRR2, 0);
686
687         dev_dbg(dev, "chgerr: %x chgctrl: %x chgstat: %x chgstat2: %x\n",
688                 err, ctrl, stat1, stat2);
689
690         power_supply_changed(info->usb);
691         power_supply_changed(info->adp);
692         power_supply_changed(info->battery);
693
694         return IRQ_HANDLED;
695 }
696
697 static int rn5t618_power_probe(struct platform_device *pdev)
698 {
699         int ret = 0;
700         unsigned int v;
701         struct power_supply_config psy_cfg = {};
702         struct rn5t618_power_info *info;
703
704         info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
705         if (!info)
706                 return -ENOMEM;
707
708         info->pdev = pdev;
709         info->rn5t618 = dev_get_drvdata(pdev->dev.parent);
710         info->irq = -1;
711
712         platform_set_drvdata(pdev, info);
713
714         ret = regmap_read(info->rn5t618->regmap, RN5T618_CONTROL, &v);
715         if (ret)
716                 return ret;
717
718         if (!(v & FG_ENABLE)) {
719                 /* E.g. the vendor kernels of various Kobo and Tolino Ebook
720                  * readers disable the fuel gauge on shutdown. If a kernel
721                  * without fuel gauge support is booted after that, the fuel
722                  * gauge will get decalibrated.
723                  */
724                 dev_info(&pdev->dev, "Fuel gauge not enabled, enabling now\n");
725                 dev_info(&pdev->dev, "Expect imprecise results\n");
726                 regmap_update_bits(info->rn5t618->regmap, RN5T618_CONTROL,
727                                    FG_ENABLE, FG_ENABLE);
728         }
729
730         psy_cfg.drv_data = info;
731         info->battery = devm_power_supply_register(&pdev->dev,
732                                                    &rn5t618_battery_desc,
733                                                    &psy_cfg);
734         if (IS_ERR(info->battery)) {
735                 ret = PTR_ERR(info->battery);
736                 dev_err(&pdev->dev, "failed to register battery: %d\n", ret);
737                 return ret;
738         }
739
740         info->adp = devm_power_supply_register(&pdev->dev,
741                                                &rn5t618_adp_desc,
742                                                &psy_cfg);
743         if (IS_ERR(info->adp)) {
744                 ret = PTR_ERR(info->adp);
745                 dev_err(&pdev->dev, "failed to register adp: %d\n", ret);
746                 return ret;
747         }
748
749         info->usb = devm_power_supply_register(&pdev->dev,
750                                                &rn5t618_usb_desc,
751                                                &psy_cfg);
752         if (IS_ERR(info->usb)) {
753                 ret = PTR_ERR(info->usb);
754                 dev_err(&pdev->dev, "failed to register usb: %d\n", ret);
755                 return ret;
756         }
757
758         if (info->rn5t618->irq_data)
759                 info->irq = regmap_irq_get_virq(info->rn5t618->irq_data,
760                                                 RN5T618_IRQ_CHG);
761
762         if (info->irq < 0)
763                 info->irq = -1;
764         else {
765                 ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
766                                                 rn5t618_charger_irq,
767                                                 IRQF_ONESHOT,
768                                                 "rn5t618_power",
769                                                 &pdev->dev);
770
771                 if (ret < 0) {
772                         dev_err(&pdev->dev, "request IRQ:%d fail\n",
773                                 info->irq);
774                         info->irq = -1;
775                 }
776         }
777
778         return 0;
779 }
780
781 static struct platform_driver rn5t618_power_driver = {
782         .driver = {
783                 .name   = "rn5t618-power",
784         },
785         .probe = rn5t618_power_probe,
786 };
787
788 module_platform_driver(rn5t618_power_driver);
789 MODULE_ALIAS("platform:rn5t618-power");
790 MODULE_DESCRIPTION("Power supply driver for RICOH RN5T618");
791 MODULE_LICENSE("GPL");