Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad...
[linux-2.6-microblaze.git] / drivers / power / supply / mp2629_charger.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * MP2629 battery charger driver
4  *
5  * Copyright 2020 Monolithic Power Systems, Inc
6  *
7  * Author: Saravanan Sekar <sravanhome@gmail.com>
8  */
9
10 #include <linux/bits.h>
11 #include <linux/iio/consumer.h>
12 #include <linux/iio/types.h>
13 #include <linux/interrupt.h>
14 #include <linux/mfd/mp2629.h>
15 #include <linux/module.h>
16 #include <linux/mod_devicetable.h>
17 #include <linux/platform_device.h>
18 #include <linux/power_supply.h>
19 #include <linux/regmap.h>
20
21 #define MP2629_REG_INPUT_ILIM           0x00
22 #define MP2629_REG_INPUT_VLIM           0x01
23 #define MP2629_REG_CHARGE_CTRL          0x04
24 #define MP2629_REG_CHARGE_ILIM          0x05
25 #define MP2629_REG_PRECHARGE            0x06
26 #define MP2629_REG_TERM_CURRENT         0x06
27 #define MP2629_REG_CHARGE_VLIM          0x07
28 #define MP2629_REG_TIMER_CTRL           0x08
29 #define MP2629_REG_IMPEDANCE_COMP       0x09
30 #define MP2629_REG_INTERRUPT            0x0b
31 #define MP2629_REG_STATUS               0x0c
32 #define MP2629_REG_FAULT                0x0d
33
34 #define MP2629_MASK_INPUT_TYPE          GENMASK(7, 5)
35 #define MP2629_MASK_CHARGE_TYPE         GENMASK(4, 3)
36 #define MP2629_MASK_CHARGE_CTRL         GENMASK(5, 4)
37 #define MP2629_MASK_WDOG_CTRL           GENMASK(5, 4)
38 #define MP2629_MASK_IMPEDANCE           GENMASK(7, 4)
39
40 #define MP2629_INPUTSOURCE_CHANGE       GENMASK(7, 5)
41 #define MP2629_CHARGING_CHANGE          GENMASK(4, 3)
42 #define MP2629_FAULT_BATTERY            BIT(3)
43 #define MP2629_FAULT_THERMAL            BIT(4)
44 #define MP2629_FAULT_INPUT              BIT(5)
45 #define MP2629_FAULT_OTG                BIT(6)
46
47 #define MP2629_MAX_BATT_CAPACITY        100
48
49 #define MP2629_PROPS(_idx, _min, _max, _step)           \
50         [_idx] = {                                      \
51                 .min    = _min,                         \
52                 .max    = _max,                         \
53                 .step   = _step,                        \
54 }
55
56 enum mp2629_source_type {
57         MP2629_SOURCE_TYPE_NO_INPUT,
58         MP2629_SOURCE_TYPE_NON_STD,
59         MP2629_SOURCE_TYPE_SDP,
60         MP2629_SOURCE_TYPE_CDP,
61         MP2629_SOURCE_TYPE_DCP,
62         MP2629_SOURCE_TYPE_OTG = 7,
63 };
64
65 enum mp2629_field {
66         INPUT_ILIM,
67         INPUT_VLIM,
68         CHARGE_ILIM,
69         CHARGE_VLIM,
70         PRECHARGE,
71         TERM_CURRENT,
72         MP2629_MAX_FIELD
73 };
74
75 struct mp2629_charger {
76         struct device *dev;
77         int status;
78         int fault;
79
80         struct regmap *regmap;
81         struct regmap_field *regmap_fields[MP2629_MAX_FIELD];
82         struct mutex lock;
83         struct power_supply *usb;
84         struct power_supply *battery;
85         struct iio_channel *iiochan[MP2629_ADC_CHAN_END];
86 };
87
88 struct mp2629_prop {
89         int reg;
90         int mask;
91         int min;
92         int max;
93         int step;
94         int shift;
95 };
96
97 static enum power_supply_usb_type mp2629_usb_types[] = {
98         POWER_SUPPLY_USB_TYPE_SDP,
99         POWER_SUPPLY_USB_TYPE_DCP,
100         POWER_SUPPLY_USB_TYPE_CDP,
101         POWER_SUPPLY_USB_TYPE_PD_DRP,
102         POWER_SUPPLY_USB_TYPE_UNKNOWN
103 };
104
105 static enum power_supply_property mp2629_charger_usb_props[] = {
106         POWER_SUPPLY_PROP_ONLINE,
107         POWER_SUPPLY_PROP_USB_TYPE,
108         POWER_SUPPLY_PROP_VOLTAGE_NOW,
109         POWER_SUPPLY_PROP_CURRENT_NOW,
110         POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
111         POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT,
112 };
113
114 static enum power_supply_property mp2629_charger_bat_props[] = {
115         POWER_SUPPLY_PROP_STATUS,
116         POWER_SUPPLY_PROP_HEALTH,
117         POWER_SUPPLY_PROP_CHARGE_TYPE,
118         POWER_SUPPLY_PROP_VOLTAGE_NOW,
119         POWER_SUPPLY_PROP_CURRENT_NOW,
120         POWER_SUPPLY_PROP_CAPACITY,
121         POWER_SUPPLY_PROP_PRECHARGE_CURRENT,
122         POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
123         POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
124         POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
125         POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
126         POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
127 };
128
129 static struct mp2629_prop props[] = {
130         MP2629_PROPS(INPUT_ILIM, 100000, 3250000, 50000),
131         MP2629_PROPS(INPUT_VLIM, 3800000, 5300000, 100000),
132         MP2629_PROPS(CHARGE_ILIM, 320000, 4520000, 40000),
133         MP2629_PROPS(CHARGE_VLIM, 3400000, 4670000, 10000),
134         MP2629_PROPS(PRECHARGE, 120000, 720000, 40000),
135         MP2629_PROPS(TERM_CURRENT, 80000, 680000, 40000),
136 };
137
138 static const struct reg_field mp2629_reg_fields[] = {
139         [INPUT_ILIM]    = REG_FIELD(MP2629_REG_INPUT_ILIM, 0, 5),
140         [INPUT_VLIM]    = REG_FIELD(MP2629_REG_INPUT_VLIM, 0, 3),
141         [CHARGE_ILIM]   = REG_FIELD(MP2629_REG_CHARGE_ILIM, 0, 6),
142         [CHARGE_VLIM]   = REG_FIELD(MP2629_REG_CHARGE_VLIM, 1, 7),
143         [PRECHARGE]     = REG_FIELD(MP2629_REG_PRECHARGE, 4, 7),
144         [TERM_CURRENT]  = REG_FIELD(MP2629_REG_TERM_CURRENT, 0, 3),
145 };
146
147 static char *adc_chan_name[] = {
148         "mp2629-batt-volt",
149         "mp2629-system-volt",
150         "mp2629-input-volt",
151         "mp2629-batt-current",
152         "mp2629-input-current",
153 };
154
155 static int mp2629_read_adc(struct mp2629_charger *charger,
156                            enum mp2629_adc_chan ch,
157                            union power_supply_propval *val)
158 {
159         int ret;
160         int chval;
161
162         ret = iio_read_channel_processed(charger->iiochan[ch], &chval);
163         if (ret)
164                 return ret;
165
166         val->intval = chval * 1000;
167
168         return 0;
169 }
170
171 static int mp2629_get_prop(struct mp2629_charger *charger,
172                            enum mp2629_field fld,
173                            union power_supply_propval *val)
174 {
175         int ret;
176         unsigned int rval;
177
178         ret = regmap_field_read(charger->regmap_fields[fld], &rval);
179         if (ret)
180                 return ret;
181
182         val->intval = rval * props[fld].step + props[fld].min;
183
184         return 0;
185 }
186
187 static int mp2629_set_prop(struct mp2629_charger *charger,
188                            enum mp2629_field fld,
189                            const union power_supply_propval *val)
190 {
191         unsigned int rval;
192
193         if (val->intval < props[fld].min || val->intval > props[fld].max)
194                 return -EINVAL;
195
196         rval = (val->intval - props[fld].min) / props[fld].step;
197         return regmap_field_write(charger->regmap_fields[fld], rval);
198 }
199
200 static int mp2629_get_battery_capacity(struct mp2629_charger *charger,
201                                        union power_supply_propval *val)
202 {
203         union power_supply_propval vnow, vlim;
204         int ret;
205
206         ret = mp2629_read_adc(charger, MP2629_BATT_VOLT, &vnow);
207         if (ret)
208                 return ret;
209
210         ret = mp2629_get_prop(charger, CHARGE_VLIM, &vlim);
211         if (ret)
212                 return ret;
213
214         val->intval = (vnow.intval * 100) / vlim.intval;
215         val->intval = min(val->intval, MP2629_MAX_BATT_CAPACITY);
216
217         return 0;
218 }
219
220 static int mp2629_charger_battery_get_prop(struct power_supply *psy,
221                                         enum power_supply_property psp,
222                                         union power_supply_propval *val)
223 {
224         struct mp2629_charger *charger = dev_get_drvdata(psy->dev.parent);
225         unsigned int rval;
226         int ret = 0;
227
228         switch (psp) {
229         case POWER_SUPPLY_PROP_VOLTAGE_NOW:
230                 ret = mp2629_read_adc(charger, MP2629_BATT_VOLT, val);
231                 break;
232
233         case POWER_SUPPLY_PROP_CURRENT_NOW:
234                 ret = mp2629_read_adc(charger, MP2629_BATT_CURRENT, val);
235                 break;
236
237         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
238                 val->intval = 4520000;
239                 break;
240
241         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
242                 val->intval = 4670000;
243                 break;
244
245         case POWER_SUPPLY_PROP_CAPACITY:
246                 ret = mp2629_get_battery_capacity(charger, val);
247                 break;
248
249         case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
250                 ret = mp2629_get_prop(charger, TERM_CURRENT, val);
251                 break;
252
253         case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
254                 ret = mp2629_get_prop(charger, PRECHARGE, val);
255                 break;
256
257         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
258                 ret = mp2629_get_prop(charger, CHARGE_VLIM, val);
259                 break;
260
261         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
262                 ret = mp2629_get_prop(charger, CHARGE_ILIM, val);
263                 break;
264
265         case POWER_SUPPLY_PROP_HEALTH:
266                 if (!charger->fault)
267                         val->intval = POWER_SUPPLY_HEALTH_GOOD;
268                 if (MP2629_FAULT_BATTERY & charger->fault)
269                         val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
270                 else if (MP2629_FAULT_THERMAL & charger->fault)
271                         val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
272                 else if (MP2629_FAULT_INPUT & charger->fault)
273                         val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
274                 break;
275
276         case POWER_SUPPLY_PROP_STATUS:
277                 ret = regmap_read(charger->regmap, MP2629_REG_STATUS, &rval);
278                 if (ret)
279                         break;
280
281                 rval = (rval & MP2629_MASK_CHARGE_TYPE) >> 3;
282                 switch (rval) {
283                 case 0x00:
284                         val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
285                         break;
286                 case 0x01:
287                 case 0x10:
288                         val->intval = POWER_SUPPLY_STATUS_CHARGING;
289                         break;
290                 case 0x11:
291                         val->intval = POWER_SUPPLY_STATUS_FULL;
292                 }
293                 break;
294
295         case POWER_SUPPLY_PROP_CHARGE_TYPE:
296                 ret = regmap_read(charger->regmap, MP2629_REG_STATUS, &rval);
297                 if (ret)
298                         break;
299
300                 rval = (rval & MP2629_MASK_CHARGE_TYPE) >> 3;
301                 switch (rval) {
302                 case 0x00:
303                         val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
304                         break;
305                 case 0x01:
306                         val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
307                         break;
308                 case 0x10:
309                         val->intval = POWER_SUPPLY_CHARGE_TYPE_STANDARD;
310                         break;
311                 default:
312                         val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
313                 }
314                 break;
315
316         default:
317                 return -EINVAL;
318         }
319
320         return ret;
321 }
322
323 static int mp2629_charger_battery_set_prop(struct power_supply *psy,
324                                         enum power_supply_property psp,
325                                         const union power_supply_propval *val)
326 {
327         struct mp2629_charger *charger = dev_get_drvdata(psy->dev.parent);
328
329         switch (psp) {
330         case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
331                 return mp2629_set_prop(charger, TERM_CURRENT, val);
332
333         case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
334                 return mp2629_set_prop(charger, PRECHARGE, val);
335
336         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
337                 return mp2629_set_prop(charger, CHARGE_VLIM, val);
338
339         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
340                 return mp2629_set_prop(charger, CHARGE_ILIM, val);
341
342         default:
343                 return -EINVAL;
344         }
345 }
346
347 static int mp2629_charger_usb_get_prop(struct power_supply *psy,
348                                 enum power_supply_property psp,
349                                 union power_supply_propval *val)
350 {
351         struct mp2629_charger *charger = dev_get_drvdata(psy->dev.parent);
352         unsigned int rval;
353         int ret;
354
355         switch (psp) {
356         case POWER_SUPPLY_PROP_ONLINE:
357                 ret = regmap_read(charger->regmap, MP2629_REG_STATUS, &rval);
358                 if (ret)
359                         break;
360
361                 val->intval = !!(rval & MP2629_MASK_INPUT_TYPE);
362                 break;
363
364         case POWER_SUPPLY_PROP_USB_TYPE:
365                 ret = regmap_read(charger->regmap, MP2629_REG_STATUS, &rval);
366                 if (ret)
367                         break;
368
369                 rval = (rval & MP2629_MASK_INPUT_TYPE) >> 5;
370                 switch (rval) {
371                 case MP2629_SOURCE_TYPE_SDP:
372                         val->intval = POWER_SUPPLY_USB_TYPE_SDP;
373                         break;
374                 case MP2629_SOURCE_TYPE_CDP:
375                         val->intval = POWER_SUPPLY_USB_TYPE_CDP;
376                         break;
377                 case MP2629_SOURCE_TYPE_DCP:
378                         val->intval = POWER_SUPPLY_USB_TYPE_DCP;
379                         break;
380                 case MP2629_SOURCE_TYPE_OTG:
381                         val->intval = POWER_SUPPLY_USB_TYPE_PD_DRP;
382                         break;
383                 default:
384                         val->intval = POWER_SUPPLY_USB_TYPE_UNKNOWN;
385                         break;
386                 }
387                 break;
388
389         case POWER_SUPPLY_PROP_VOLTAGE_NOW:
390                 ret = mp2629_read_adc(charger, MP2629_INPUT_VOLT, val);
391                 break;
392
393         case POWER_SUPPLY_PROP_CURRENT_NOW:
394                 ret = mp2629_read_adc(charger, MP2629_INPUT_CURRENT, val);
395                 break;
396
397         case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
398                 ret = mp2629_get_prop(charger, INPUT_VLIM, val);
399                 break;
400
401         case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
402                 ret = mp2629_get_prop(charger, INPUT_ILIM, val);
403                 break;
404
405         default:
406                 return -EINVAL;
407         }
408
409         return ret;
410 }
411
412 static int mp2629_charger_usb_set_prop(struct power_supply *psy,
413                                 enum power_supply_property psp,
414                                 const union power_supply_propval *val)
415 {
416         struct mp2629_charger *charger = dev_get_drvdata(psy->dev.parent);
417
418         switch (psp) {
419         case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
420                 return mp2629_set_prop(charger, INPUT_VLIM, val);
421
422         case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
423                 return mp2629_set_prop(charger, INPUT_ILIM, val);
424
425         default:
426                 return -EINVAL;
427         }
428 }
429
430 static int mp2629_charger_battery_prop_writeable(struct power_supply *psy,
431                                      enum power_supply_property psp)
432 {
433         return (psp == POWER_SUPPLY_PROP_PRECHARGE_CURRENT) ||
434                (psp == POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT) ||
435                (psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT) ||
436                (psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE);
437 }
438
439 static int mp2629_charger_usb_prop_writeable(struct power_supply *psy,
440                                      enum power_supply_property psp)
441 {
442         return (psp == POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT) ||
443                (psp == POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT);
444 }
445
446 static irqreturn_t mp2629_irq_handler(int irq, void *dev_id)
447 {
448         struct mp2629_charger *charger = dev_id;
449         unsigned int rval;
450         int ret;
451
452         mutex_lock(&charger->lock);
453
454         ret = regmap_read(charger->regmap, MP2629_REG_FAULT, &rval);
455         if (ret)
456                 goto unlock;
457
458         if (rval) {
459                 charger->fault = rval;
460                 if (MP2629_FAULT_BATTERY & rval)
461                         dev_err(charger->dev, "Battery fault OVP\n");
462                 else if (MP2629_FAULT_THERMAL & rval)
463                         dev_err(charger->dev, "Thermal shutdown fault\n");
464                 else if (MP2629_FAULT_INPUT & rval)
465                         dev_err(charger->dev, "no input or input OVP\n");
466                 else if (MP2629_FAULT_OTG & rval)
467                         dev_err(charger->dev, "VIN overloaded\n");
468
469                 goto unlock;
470         }
471
472         ret = regmap_read(charger->regmap, MP2629_REG_STATUS, &rval);
473         if (ret)
474                 goto unlock;
475
476         if (rval & MP2629_INPUTSOURCE_CHANGE)
477                 power_supply_changed(charger->usb);
478         else if (rval & MP2629_CHARGING_CHANGE)
479                 power_supply_changed(charger->battery);
480
481 unlock:
482         mutex_unlock(&charger->lock);
483
484         return IRQ_HANDLED;
485 }
486
487 static const struct power_supply_desc mp2629_usb_desc = {
488         .name           = "mp2629_usb",
489         .type           = POWER_SUPPLY_TYPE_USB,
490         .usb_types      = mp2629_usb_types,
491         .num_usb_types  = ARRAY_SIZE(mp2629_usb_types),
492         .properties     = mp2629_charger_usb_props,
493         .num_properties = ARRAY_SIZE(mp2629_charger_usb_props),
494         .get_property   = mp2629_charger_usb_get_prop,
495         .set_property   = mp2629_charger_usb_set_prop,
496         .property_is_writeable = mp2629_charger_usb_prop_writeable,
497 };
498
499 static const struct power_supply_desc mp2629_battery_desc = {
500         .name           = "mp2629_battery",
501         .type           = POWER_SUPPLY_TYPE_BATTERY,
502         .properties     = mp2629_charger_bat_props,
503         .num_properties = ARRAY_SIZE(mp2629_charger_bat_props),
504         .get_property   = mp2629_charger_battery_get_prop,
505         .set_property   = mp2629_charger_battery_set_prop,
506         .property_is_writeable = mp2629_charger_battery_prop_writeable,
507 };
508
509 static ssize_t batt_impedance_compensation_show(struct device *dev,
510                                            struct device_attribute *attr,
511                                            char *buf)
512 {
513         struct mp2629_charger *charger = dev_get_drvdata(dev->parent);
514         unsigned int rval;
515         int ret;
516
517         ret = regmap_read(charger->regmap, MP2629_REG_IMPEDANCE_COMP, &rval);
518         if (ret)
519                 return ret;
520
521         rval = (rval >> 4) * 10;
522         return sprintf(buf, "%d mohm\n", rval);
523 }
524
525 static ssize_t batt_impedance_compensation_store(struct device *dev,
526                                             struct device_attribute *attr,
527                                             const char *buf,
528                                             size_t count)
529 {
530         struct mp2629_charger *charger = dev_get_drvdata(dev->parent);
531         unsigned int val;
532         int ret;
533
534         ret = kstrtouint(buf, 10, &val);
535         if (ret)
536                 return ret;
537
538         if (val > 140)
539                 return -ERANGE;
540
541         /* multiples of 10 mohm so round off */
542         val = val / 10;
543         ret = regmap_update_bits(charger->regmap, MP2629_REG_IMPEDANCE_COMP,
544                                         MP2629_MASK_IMPEDANCE, val << 4);
545         if (ret)
546                 return ret;
547
548         return count;
549 }
550
551 static DEVICE_ATTR_RW(batt_impedance_compensation);
552
553 static struct attribute *mp2629_charger_sysfs_attrs[] = {
554         &dev_attr_batt_impedance_compensation.attr,
555         NULL
556 };
557 ATTRIBUTE_GROUPS(mp2629_charger_sysfs);
558
559 static void mp2629_charger_disable(void *data)
560 {
561         struct mp2629_charger *charger = data;
562
563         regmap_update_bits(charger->regmap, MP2629_REG_CHARGE_CTRL,
564                                         MP2629_MASK_CHARGE_CTRL, 0);
565 }
566
567 static int mp2629_charger_probe(struct platform_device *pdev)
568 {
569         struct device *dev = &pdev->dev;
570         struct mp2629_data *ddata = dev_get_drvdata(dev->parent);
571         struct mp2629_charger *charger;
572         struct power_supply_config psy_cfg = {};
573         int ret, i, irq;
574
575         charger = devm_kzalloc(dev, sizeof(*charger), GFP_KERNEL);
576         if (!charger)
577                 return -ENOMEM;
578
579         charger->regmap = ddata->regmap;
580         charger->dev = dev;
581         platform_set_drvdata(pdev, charger);
582
583         irq = platform_get_irq_optional(to_platform_device(dev->parent), 0);
584         if (irq < 0) {
585                 dev_err(dev, "get irq fail: %d\n", irq);
586                 return irq;
587         }
588
589         for (i = 0; i < MP2629_MAX_FIELD; i++) {
590                 charger->regmap_fields[i] = devm_regmap_field_alloc(dev,
591                                         charger->regmap, mp2629_reg_fields[i]);
592                 if (IS_ERR(charger->regmap_fields[i])) {
593                         dev_err(dev, "regmap field alloc fail %d\n", i);
594                         return PTR_ERR(charger->regmap_fields[i]);
595                 }
596         }
597
598         for (i = 0; i < MP2629_ADC_CHAN_END; i++) {
599                 charger->iiochan[i] = devm_iio_channel_get(dev,
600                                                         adc_chan_name[i]);
601                 if (IS_ERR(charger->iiochan[i])) {
602                         dev_err(dev, "iio chan get %s err\n", adc_chan_name[i]);
603                         return PTR_ERR(charger->iiochan[i]);
604                 }
605         }
606
607         ret = devm_add_action_or_reset(dev, mp2629_charger_disable, charger);
608         if (ret)
609                 return ret;
610
611         charger->usb = devm_power_supply_register(dev, &mp2629_usb_desc, NULL);
612         if (IS_ERR(charger->usb)) {
613                 dev_err(dev, "power supply register usb failed\n");
614                 return PTR_ERR(charger->usb);
615         }
616
617         psy_cfg.drv_data = charger;
618         psy_cfg.attr_grp = mp2629_charger_sysfs_groups;
619         charger->battery = devm_power_supply_register(dev,
620                                          &mp2629_battery_desc, &psy_cfg);
621         if (IS_ERR(charger->battery)) {
622                 dev_err(dev, "power supply register battery failed\n");
623                 return PTR_ERR(charger->battery);
624         }
625
626         ret = regmap_update_bits(charger->regmap, MP2629_REG_CHARGE_CTRL,
627                                         MP2629_MASK_CHARGE_CTRL, BIT(4));
628         if (ret) {
629                 dev_err(dev, "enable charge fail: %d\n", ret);
630                 return ret;
631         }
632
633         regmap_update_bits(charger->regmap, MP2629_REG_TIMER_CTRL,
634                                         MP2629_MASK_WDOG_CTRL, 0);
635
636         mutex_init(&charger->lock);
637
638         ret = devm_request_threaded_irq(dev, irq, NULL, mp2629_irq_handler,
639                                         IRQF_ONESHOT | IRQF_TRIGGER_RISING,
640                                         "mp2629-charger", charger);
641         if (ret) {
642                 dev_err(dev, "failed to request gpio IRQ\n");
643                 return ret;
644         }
645
646         regmap_update_bits(charger->regmap, MP2629_REG_INTERRUPT,
647                                 GENMASK(6, 5), BIT(6) | BIT(5));
648
649         return 0;
650 }
651
652 static const struct of_device_id mp2629_charger_of_match[] = {
653         { .compatible = "mps,mp2629_charger"},
654         {}
655 };
656 MODULE_DEVICE_TABLE(of, mp2629_charger_of_match);
657
658 static struct platform_driver mp2629_charger_driver = {
659         .driver = {
660                 .name = "mp2629_charger",
661                 .of_match_table = mp2629_charger_of_match,
662         },
663         .probe          = mp2629_charger_probe,
664 };
665 module_platform_driver(mp2629_charger_driver);
666
667 MODULE_AUTHOR("Saravanan Sekar <sravanhome@gmail.com>");
668 MODULE_DESCRIPTION("MP2629 Charger driver");
669 MODULE_LICENSE("GPL");