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
mp2629_read_adc(struct mp2629_charger * charger,enum mp2629_adc_chan ch,union power_supply_propval * val)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
mp2629_get_prop(struct mp2629_charger * charger,enum mp2629_field fld,union power_supply_propval * val)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
mp2629_set_prop(struct mp2629_charger * charger,enum mp2629_field fld,const union power_supply_propval * val)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
mp2629_get_battery_capacity(struct mp2629_charger * charger,union power_supply_propval * val)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
mp2629_charger_battery_get_prop(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)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
mp2629_charger_battery_set_prop(struct power_supply * psy,enum power_supply_property psp,const union power_supply_propval * val)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
mp2629_charger_usb_get_prop(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)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
mp2629_charger_usb_set_prop(struct power_supply * psy,enum power_supply_property psp,const union power_supply_propval * val)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
mp2629_charger_battery_prop_writeable(struct power_supply * psy,enum power_supply_property psp)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
mp2629_charger_usb_prop_writeable(struct power_supply * psy,enum power_supply_property psp)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
mp2629_irq_handler(int irq,void * dev_id)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
batt_impedance_compensation_show(struct device * dev,struct device_attribute * attr,char * buf)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 sysfs_emit(buf, "%d mohm\n", rval);
523 }
524
batt_impedance_compensation_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
mp2629_charger_disable(void * data)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
mp2629_charger_probe(struct platform_device * pdev)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(to_platform_device(dev->parent), 0);
584 if (irq < 0)
585 return irq;
586
587 for (i = 0; i < MP2629_MAX_FIELD; i++) {
588 charger->regmap_fields[i] = devm_regmap_field_alloc(dev,
589 charger->regmap, mp2629_reg_fields[i]);
590 if (IS_ERR(charger->regmap_fields[i])) {
591 dev_err(dev, "regmap field alloc fail %d\n", i);
592 return PTR_ERR(charger->regmap_fields[i]);
593 }
594 }
595
596 for (i = 0; i < MP2629_ADC_CHAN_END; i++) {
597 charger->iiochan[i] = devm_iio_channel_get(dev,
598 adc_chan_name[i]);
599 if (IS_ERR(charger->iiochan[i])) {
600 dev_err(dev, "iio chan get %s err\n", adc_chan_name[i]);
601 return PTR_ERR(charger->iiochan[i]);
602 }
603 }
604
605 ret = devm_add_action_or_reset(dev, mp2629_charger_disable, charger);
606 if (ret)
607 return ret;
608
609 charger->usb = devm_power_supply_register(dev, &mp2629_usb_desc, NULL);
610 if (IS_ERR(charger->usb)) {
611 dev_err(dev, "power supply register usb failed\n");
612 return PTR_ERR(charger->usb);
613 }
614
615 psy_cfg.drv_data = charger;
616 psy_cfg.attr_grp = mp2629_charger_sysfs_groups;
617 charger->battery = devm_power_supply_register(dev,
618 &mp2629_battery_desc, &psy_cfg);
619 if (IS_ERR(charger->battery)) {
620 dev_err(dev, "power supply register battery failed\n");
621 return PTR_ERR(charger->battery);
622 }
623
624 ret = regmap_update_bits(charger->regmap, MP2629_REG_CHARGE_CTRL,
625 MP2629_MASK_CHARGE_CTRL, BIT(4));
626 if (ret) {
627 dev_err(dev, "enable charge fail: %d\n", ret);
628 return ret;
629 }
630
631 regmap_update_bits(charger->regmap, MP2629_REG_TIMER_CTRL,
632 MP2629_MASK_WDOG_CTRL, 0);
633
634 mutex_init(&charger->lock);
635
636 ret = devm_request_threaded_irq(dev, irq, NULL, mp2629_irq_handler,
637 IRQF_ONESHOT | IRQF_TRIGGER_RISING,
638 "mp2629-charger", charger);
639 if (ret) {
640 dev_err(dev, "failed to request gpio IRQ\n");
641 return ret;
642 }
643
644 regmap_update_bits(charger->regmap, MP2629_REG_INTERRUPT,
645 GENMASK(6, 5), BIT(6) | BIT(5));
646
647 return 0;
648 }
649
650 static const struct of_device_id mp2629_charger_of_match[] = {
651 { .compatible = "mps,mp2629_charger"},
652 {}
653 };
654 MODULE_DEVICE_TABLE(of, mp2629_charger_of_match);
655
656 static struct platform_driver mp2629_charger_driver = {
657 .driver = {
658 .name = "mp2629_charger",
659 .of_match_table = mp2629_charger_of_match,
660 },
661 .probe = mp2629_charger_probe,
662 };
663 module_platform_driver(mp2629_charger_driver);
664
665 MODULE_AUTHOR("Saravanan Sekar <sravanhome@gmail.com>");
666 MODULE_DESCRIPTION("MP2629 Charger driver");
667 MODULE_LICENSE("GPL");
668