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