xref: /linux/drivers/power/supply/bd71828-power.c (revision cf1b04aaef8b83f668fac10bfc4d4d76ba6e6fa1)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* ROHM BD71815, BD71828 and BD71878 Charger driver */
3 
4 #include <linux/interrupt.h>
5 #include <linux/kernel.h>
6 #include <linux/mfd/rohm-bd71815.h>
7 #include <linux/mfd/rohm-bd71828.h>
8 #include <linux/mfd/rohm-bd72720.h>
9 #include <linux/module.h>
10 #include <linux/mod_devicetable.h>
11 #include <linux/platform_device.h>
12 #include <linux/property.h>
13 #include <linux/power_supply.h>
14 #include <linux/slab.h>
15 
16 /* common defines */
17 #define BD7182x_MASK_VBAT_U			0x1f
18 #define BD7182x_MASK_VDCIN_U			0x0f
19 #define BD7182x_MASK_IBAT_U			0x3f
20 #define BD7182x_MASK_CURDIR_DISCHG		0x80
21 #define BD7182x_MASK_CHG_STATE			0x7f
22 #define BD7182x_MASK_BAT_TEMP			0x07
23 #define BD7182x_MASK_DCIN_DET			BIT(0)
24 #define BD7182x_MASK_CONF_PON			BIT(0)
25 #define BD71815_MASK_CONF_XSTB			BIT(1)
26 #define BD7182x_MASK_BAT_STAT			0x3f
27 #define BD7182x_MASK_ILIM			0x3f
28 #define BD7182x_MASK_DCIN_STAT			0x07
29 
30 #define BD7182x_MASK_WDT_AUTO			0x40
31 #define BD7182x_MASK_VBAT_ALM_LIMIT_U		0x01
32 #define BD7182x_MASK_CHG_EN			0x01
33 
34 #define BD7182x_DCIN_COLLAPSE_DEFAULT		0x36
35 
36 #define MAX_CURRENT_DEFAULT			890000		/* uA */
37 #define AC_NAME					"bd71828_ac"
38 #define BAT_NAME				"bd71828_bat"
39 
40 #define BAT_OPEN	0x7
41 
42 /*
43  * VBAT Low voltage detection Threshold
44  * 0x00D4*16mV = 212*0.016 = 3.392v
45  */
46 #define VBAT_LOW_TH			0x00D4
47 
48 struct pwr_regs {
49 	unsigned int vbat_avg;
50 	unsigned int ibat;
51 	unsigned int ibat_avg;
52 	unsigned int ilim_stat;
53 	unsigned int btemp_vth;
54 	unsigned int chg_state;
55 	unsigned int bat_temp;
56 	unsigned int dcin_set;
57 	unsigned int dcin_stat;
58 	unsigned int dcin_online_mask;
59 	unsigned int dcin_collapse_limit;
60 	unsigned int chg_set1;
61 	unsigned int chg_en;
62 	unsigned int vbat_alm_limit_u;
63 	unsigned int conf;
64 	unsigned int vdcin;
65 	unsigned int vdcin_himask;
66 };
67 
68 static const struct pwr_regs pwr_regs_bd71828 = {
69 	.vbat_avg = BD71828_REG_VBAT_U,
70 	.ibat = BD71828_REG_IBAT_U,
71 	.ibat_avg = BD71828_REG_IBAT_AVG_U,
72 	.ilim_stat = BD71828_REG_ILIM_STAT,
73 	.btemp_vth = BD71828_REG_VM_BTMP_U,
74 	.chg_state = BD71828_REG_CHG_STATE,
75 	.bat_temp = BD71828_REG_BAT_TEMP,
76 	.dcin_set = BD71828_REG_DCIN_SET,
77 	.dcin_stat = BD71828_REG_DCIN_STAT,
78 	.dcin_online_mask = BD7182x_MASK_DCIN_DET,
79 	.dcin_collapse_limit = BD71828_REG_DCIN_CLPS,
80 	.chg_set1 = BD71828_REG_CHG_SET1,
81 	.chg_en   = BD71828_REG_CHG_EN,
82 	.vbat_alm_limit_u = BD71828_REG_ALM_VBAT_LIMIT_U,
83 	.conf = BD71828_REG_CONF,
84 	.vdcin = BD71828_REG_VDCIN_U,
85 	.vdcin_himask = BD7182x_MASK_VDCIN_U,
86 };
87 
88 static const struct pwr_regs pwr_regs_bd71815 = {
89 	.vbat_avg = BD71815_REG_VM_SA_VBAT_U,
90 	/* BD71815 does not have separate current and current avg */
91 	.ibat = BD71815_REG_CC_CURCD_U,
92 	.ibat_avg = BD71815_REG_CC_CURCD_U,
93 
94 	.btemp_vth = BD71815_REG_VM_BTMP,
95 	.chg_state = BD71815_REG_CHG_STATE,
96 	.bat_temp = BD71815_REG_BAT_TEMP,
97 	.dcin_stat = BD71815_REG_DCIN_STAT,
98 	.dcin_online_mask = BD7182x_MASK_DCIN_DET,
99 	.dcin_collapse_limit = BD71815_REG_DCIN_CLPS,
100 	.chg_set1 = BD71815_REG_CHG_SET1,
101 	.chg_en   = BD71815_REG_CHG_SET1,
102 	.vbat_alm_limit_u = BD71815_REG_ALM_VBAT_TH_U,
103 	.conf = BD71815_REG_CONF,
104 
105 	.vdcin = BD71815_REG_VM_DCIN_U,
106 	.vdcin_himask = BD7182x_MASK_VDCIN_U,
107 };
108 
109 static struct pwr_regs pwr_regs_bd72720 = {
110 	.vbat_avg = BD72720_REG_VM_SA_VBAT_U,
111 	.ibat = BD72720_REG_CC_CURCD_U,
112 	.ibat_avg = BD72720_REG_CC_SA_CURCD_U,
113 	.btemp_vth = BD72720_REG_VM_BTMP_U,
114 	/*
115 	 * Note, state 0x40 IMP_CHK. not documented
116 	 * on other variants but was still handled in
117 	 * existing code. No memory traces as to why.
118 	 */
119 	.chg_state = BD72720_REG_CHG_STATE,
120 	.bat_temp = BD72720_REG_CHG_BAT_TEMP_STAT,
121 	.dcin_stat = BD72720_REG_INT_VBUS_SRC,
122 	.dcin_online_mask = BD72720_MASK_DCIN_DET,
123 	.dcin_collapse_limit = -1, /* Automatic. Setting not supported */
124 	.chg_set1 = BD72720_REG_CHG_SET_1,
125 	.chg_en = BD72720_REG_CHG_EN,
126 	/* 15mV note in data-sheet */
127 	.vbat_alm_limit_u = BD72720_REG_ALM_VBAT_TH_U,
128 	.conf = BD72720_REG_CONF, /* o XSTB, only PON. Seprate slave addr */
129 	.vdcin = BD72720_REG_VM_VBUS_U, /* 10 bits not 11 as with other ICs */
130 	.vdcin_himask = BD72720_MASK_VDCIN_U,
131 };
132 
133 struct bd71828_power {
134 	struct regmap *regmap;
135 	enum rohm_chip_type chip_type;
136 	struct device *dev;
137 	struct power_supply *ac;
138 	struct power_supply *bat;
139 
140 	const struct pwr_regs *regs;
141 	/* Reg val to uA */
142 	int curr_factor;
143 	int rsens;
144 	int (*get_temp)(struct bd71828_power *pwr, int *temp);
145 	int (*bat_inserted)(struct bd71828_power *pwr);
146 };
147 
148 static int bd7182x_write16(struct bd71828_power *pwr, int reg, u16 val)
149 {
150 	__be16 tmp;
151 
152 	tmp = cpu_to_be16(val);
153 
154 	return regmap_bulk_write(pwr->regmap, reg, &tmp, sizeof(tmp));
155 }
156 
157 static int bd7182x_read16_himask(struct bd71828_power *pwr, int reg, int himask,
158 				 u16 *val)
159 {
160 	struct regmap *regmap = pwr->regmap;
161 	int ret;
162 	__be16 rvals;
163 	u8 *tmp = (u8 *)&rvals;
164 
165 	ret = regmap_bulk_read(regmap, reg, &rvals, sizeof(*val));
166 	if (!ret) {
167 		*tmp &= himask;
168 		*val = be16_to_cpu(rvals);
169 	}
170 
171 	return ret;
172 }
173 
174 static int bd71828_get_vbat(struct bd71828_power *pwr, int *vcell)
175 {
176 	u16 tmp_vcell;
177 	int ret;
178 
179 	ret = bd7182x_read16_himask(pwr, pwr->regs->vbat_avg,
180 				    BD7182x_MASK_VBAT_U, &tmp_vcell);
181 	if (ret)
182 		dev_err(pwr->dev, "Failed to read battery average voltage\n");
183 	else
184 		*vcell = ((int)tmp_vcell) * 1000;
185 
186 	return ret;
187 }
188 
189 static int bd71828_get_current_ds_adc(struct bd71828_power *pwr, int *curr, int *curr_avg)
190 {
191 	__be16 tmp_curr;
192 	char *tmp = (char *)&tmp_curr;
193 	int dir = 1;
194 	int regs[] = { pwr->regs->ibat, pwr->regs->ibat_avg };
195 	int *vals[] = { curr, curr_avg };
196 	int ret, i;
197 
198 	for (dir = 1, i = 0; i < ARRAY_SIZE(regs); i++) {
199 		ret = regmap_bulk_read(pwr->regmap, regs[i], &tmp_curr,
200 				       sizeof(tmp_curr));
201 		if (ret)
202 			break;
203 
204 		if (*tmp & BD7182x_MASK_CURDIR_DISCHG)
205 			dir = -1;
206 
207 		*tmp &= BD7182x_MASK_IBAT_U;
208 
209 		*vals[i] = dir * ((int)be16_to_cpu(tmp_curr)) * pwr->curr_factor;
210 	}
211 
212 	return ret;
213 }
214 
215 /* Unit is tenths of degree C */
216 static int bd71815_get_temp(struct bd71828_power *pwr, int *temp)
217 {
218 	struct regmap *regmap = pwr->regmap;
219 	int ret;
220 	int t;
221 
222 	ret = regmap_read(regmap, pwr->regs->btemp_vth, &t);
223 	if (ret)
224 		return ret;
225 
226 	t = 200 - t;
227 
228 	if (t > 200) {
229 		dev_err(pwr->dev, "Failed to read battery temperature\n");
230 		return -ENODATA;
231 	}
232 
233 	return 0;
234 }
235 
236 /* Unit is tenths of degree C */
237 static int bd71828_get_temp(struct bd71828_power *pwr, int *temp)
238 {
239 	u16 t;
240 	int ret;
241 	int tmp = 200 * 10000;
242 
243 	ret = bd7182x_read16_himask(pwr, pwr->regs->btemp_vth,
244 				    BD71828_MASK_VM_BTMP_U, &t);
245 	if (ret)
246 		return ret;
247 
248 	if (t > 3200) {
249 		dev_err(pwr->dev,
250 			"Failed to read battery temperature\n");
251 		return -ENODATA;
252 	}
253 
254 	tmp -= 625ULL * (unsigned int)t;
255 	*temp = tmp / 1000;
256 
257 	return ret;
258 }
259 
260 static int bd71828_charge_status(struct bd71828_power *pwr,
261 				 int *s, int *h)
262 {
263 	unsigned int state;
264 	int status, health;
265 	int ret = 1;
266 
267 	ret = regmap_read(pwr->regmap, pwr->regs->chg_state, &state);
268 	if (ret) {
269 		dev_err(pwr->dev, "charger status reading failed (%d)\n", ret);
270 		return ret;
271 	}
272 
273 	state &= BD7182x_MASK_CHG_STATE;
274 
275 	dev_dbg(pwr->dev, "CHG_STATE %d\n", state);
276 
277 	switch (state) {
278 	case 0x00:
279 		status = POWER_SUPPLY_STATUS_DISCHARGING;
280 		health = POWER_SUPPLY_HEALTH_GOOD;
281 		break;
282 	case 0x01:
283 	case 0x02:
284 	case 0x03:
285 	case 0x0E:
286 		status = POWER_SUPPLY_STATUS_CHARGING;
287 		health = POWER_SUPPLY_HEALTH_GOOD;
288 		break;
289 	case 0x0F:
290 		status = POWER_SUPPLY_STATUS_FULL;
291 		health = POWER_SUPPLY_HEALTH_GOOD;
292 		break;
293 	case 0x10:
294 	case 0x11:
295 	case 0x12:
296 	case 0x13:
297 	case 0x14:
298 	case 0x20:
299 	case 0x21:
300 	case 0x22:
301 	case 0x23:
302 	case 0x24:
303 		status = POWER_SUPPLY_STATUS_NOT_CHARGING;
304 		health = POWER_SUPPLY_HEALTH_OVERHEAT;
305 		break;
306 	case 0x30:
307 	case 0x31:
308 	case 0x32:
309 	case 0x40:
310 		status = POWER_SUPPLY_STATUS_DISCHARGING;
311 		health = POWER_SUPPLY_HEALTH_GOOD;
312 		break;
313 	case 0x7f:
314 	default:
315 		status = POWER_SUPPLY_STATUS_NOT_CHARGING;
316 		health = POWER_SUPPLY_HEALTH_DEAD;
317 		break;
318 	}
319 
320 	if (s)
321 		*s = status;
322 	if (h)
323 		*h = health;
324 
325 	return ret;
326 }
327 
328 static int get_chg_online(struct bd71828_power *pwr, int *chg_online)
329 {
330 	int r, ret;
331 
332 	ret = regmap_read(pwr->regmap, pwr->regs->dcin_stat, &r);
333 	if (ret) {
334 		dev_err(pwr->dev, "Failed to read DCIN status\n");
335 		return ret;
336 	}
337 	*chg_online = ((r & pwr->regs->dcin_online_mask) != 0);
338 
339 	return 0;
340 }
341 
342 static int get_bat_online(struct bd71828_power *pwr, int *bat_online)
343 {
344 	int r, ret;
345 
346 	ret = regmap_read(pwr->regmap, pwr->regs->bat_temp, &r);
347 	if (ret) {
348 		dev_err(pwr->dev, "Failed to read battery temperature\n");
349 		return ret;
350 	}
351 	*bat_online = ((r & BD7182x_MASK_BAT_TEMP) != BAT_OPEN);
352 
353 	return 0;
354 }
355 
356 static int bd71828_bat_inserted(struct bd71828_power *pwr)
357 {
358 	int ret, val;
359 
360 	ret = regmap_read(pwr->regmap, pwr->regs->conf, &val);
361 	if (ret) {
362 		dev_err(pwr->dev, "Failed to read CONF register\n");
363 		return 0;
364 	}
365 	ret = val & BD7182x_MASK_CONF_PON;
366 
367 	if (ret)
368 		if (regmap_update_bits(pwr->regmap, pwr->regs->conf, BD7182x_MASK_CONF_PON, 0))
369 			dev_err(pwr->dev, "Failed to write CONF register\n");
370 
371 	return ret;
372 }
373 
374 static int bd71815_bat_inserted(struct bd71828_power *pwr)
375 {
376 	int ret, val;
377 
378 	ret = regmap_read(pwr->regmap, pwr->regs->conf, &val);
379 	if (ret) {
380 		dev_err(pwr->dev, "Failed to read CONF register\n");
381 		return ret;
382 	}
383 
384 	ret = !(val & BD71815_MASK_CONF_XSTB);
385 	if (ret)
386 		regmap_write(pwr->regmap, pwr->regs->conf,  val |
387 			     BD71815_MASK_CONF_XSTB);
388 
389 	return ret;
390 }
391 
392 static int bd71828_init_hardware(struct bd71828_power *pwr)
393 {
394 	int ret;
395 
396 	/* TODO: Collapse limit should come from device-tree ? */
397 	if (pwr->regs->dcin_collapse_limit != (unsigned int)-1) {
398 		ret = regmap_write(pwr->regmap, pwr->regs->dcin_collapse_limit,
399 				   BD7182x_DCIN_COLLAPSE_DEFAULT);
400 		if (ret) {
401 			dev_err(pwr->dev, "Failed to write DCIN collapse limit\n");
402 			return ret;
403 		}
404 	}
405 
406 	ret = pwr->bat_inserted(pwr);
407 	if (ret < 0)
408 		return ret;
409 
410 	if (ret) {
411 		/* WDT_FST auto set */
412 		ret = regmap_update_bits(pwr->regmap, pwr->regs->chg_set1,
413 					 BD7182x_MASK_WDT_AUTO,
414 					 BD7182x_MASK_WDT_AUTO);
415 		if (ret)
416 			return ret;
417 
418 		ret = bd7182x_write16(pwr, pwr->regs->vbat_alm_limit_u,
419 				      VBAT_LOW_TH);
420 		if (ret)
421 			return ret;
422 
423 		/*
424 		 * On BD71815 "we mask the power-state" from relax detection.
425 		 * I am unsure what the impact of the power-state would be if
426 		 * we didn't - but this is what the vendor driver did - and
427 		 * that driver has been used in few projects so I just assume
428 		 * this is needed.
429 		 */
430 		if (pwr->chip_type == ROHM_CHIP_TYPE_BD71815) {
431 			ret = regmap_set_bits(pwr->regmap,
432 					      BD71815_REG_REX_CTRL_1,
433 					      REX_PMU_STATE_MASK);
434 			if (ret)
435 				return ret;
436 		}
437 	}
438 
439 	return 0;
440 }
441 
442 static int bd71828_charger_get_property(struct power_supply *psy,
443 					enum power_supply_property psp,
444 					union power_supply_propval *val)
445 {
446 	struct bd71828_power *pwr = dev_get_drvdata(psy->dev.parent);
447 	u32 vot;
448 	u16 tmp;
449 	int t;
450 	int online;
451 	int ret;
452 
453 	switch (psp) {
454 	case POWER_SUPPLY_PROP_ONLINE:
455 		ret = get_chg_online(pwr, &online);
456 		if (!ret)
457 			val->intval = online;
458 		break;
459 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
460 		ret = bd7182x_read16_himask(pwr, pwr->regs->vdcin,
461 					    pwr->regs->vdcin_himask, &tmp);
462 		if (ret)
463 			return ret;
464 
465 		vot = tmp;
466 		/* 5 milli volt steps */
467 		val->intval = 5000 * vot;
468 		break;
469 	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
470 		if (!pwr->regs->ilim_stat)
471 			return -ENODATA;
472 
473 		ret = regmap_read(pwr->regmap, pwr->regs->ilim_stat, &t);
474 		if (ret)
475 			return ret;
476 
477 		t++;
478 		val->intval = (t & BD7182x_MASK_ILIM) * 50000;
479 		if (val->intval > 2000000)
480 			val->intval = 2000000;
481 
482 		break;
483 	default:
484 		return -EINVAL;
485 	}
486 
487 	return 0;
488 }
489 
490 static int bd71828_charger_set_property(struct power_supply *psy,
491 					enum power_supply_property psp,
492 					const union power_supply_propval *val)
493 {
494 	struct bd71828_power *pwr = dev_get_drvdata(psy->dev.parent);
495 
496 	switch (psp) {
497 	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
498 		if (val->intval > 2000000)
499 			return -EINVAL;
500 
501 		if (val->intval < 50000)
502 			return -EINVAL;
503 
504 		if (!pwr->regs->dcin_set)
505 			return -EINVAL;
506 
507 		return regmap_update_bits(pwr->regmap, pwr->regs->dcin_set,
508 					  BD7182x_MASK_ILIM,
509 					  val->intval / 50000 - 1);
510 		break;
511 	default:
512 		return -EINVAL;
513 	}
514 }
515 
516 static int bd71828_charger_property_is_writeable(struct power_supply *psy,
517 						 enum power_supply_property psp)
518 {
519 	struct bd71828_power *pwr = dev_get_drvdata(psy->dev.parent);
520 
521 	switch (psp) {
522 	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
523 		return !!(pwr->regs->dcin_set);
524 	default:
525 		return false;
526 	}
527 }
528 
529 static int bd71828_battery_get_property(struct power_supply *psy,
530 					enum power_supply_property psp,
531 					union power_supply_propval *val)
532 {
533 	struct bd71828_power *pwr = dev_get_drvdata(psy->dev.parent);
534 	int ret = 0;
535 	int status, health, tmp, curr, curr_avg, chg_en;
536 
537 	if (psp == POWER_SUPPLY_PROP_STATUS ||
538 	    psp == POWER_SUPPLY_PROP_HEALTH ||
539 	    psp == POWER_SUPPLY_PROP_CHARGE_TYPE)
540 		ret = bd71828_charge_status(pwr, &status, &health);
541 	else if (psp == POWER_SUPPLY_PROP_CURRENT_AVG ||
542 		 psp == POWER_SUPPLY_PROP_CURRENT_NOW)
543 		ret = bd71828_get_current_ds_adc(pwr, &curr, &curr_avg);
544 	if (ret)
545 		return ret;
546 
547 	switch (psp) {
548 	case POWER_SUPPLY_PROP_STATUS:
549 		val->intval = status;
550 		break;
551 	case POWER_SUPPLY_PROP_HEALTH:
552 		val->intval = health;
553 		break;
554 	case POWER_SUPPLY_PROP_PRESENT:
555 		ret = get_bat_online(pwr, &tmp);
556 		if (!ret)
557 			val->intval = tmp;
558 		break;
559 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
560 		ret = bd71828_get_vbat(pwr, &tmp);
561 		val->intval = tmp;
562 		break;
563 	case POWER_SUPPLY_PROP_TECHNOLOGY:
564 		val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
565 		break;
566 	case POWER_SUPPLY_PROP_CURRENT_AVG:
567 		val->intval = curr_avg;
568 		break;
569 	case POWER_SUPPLY_PROP_CURRENT_NOW:
570 		val->intval = curr;
571 		break;
572 	case POWER_SUPPLY_PROP_CURRENT_MAX:
573 		val->intval = MAX_CURRENT_DEFAULT;
574 		break;
575 	case POWER_SUPPLY_PROP_TEMP:
576 		ret = pwr->get_temp(pwr, &val->intval);
577 		break;
578 	case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
579 		ret = regmap_read(pwr->regmap, pwr->regs->chg_en, &chg_en);
580 		if (ret)
581 			return ret;
582 
583 		val->intval = (chg_en & BD7182x_MASK_CHG_EN) ?
584 			POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO :
585 			POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE;
586 		break;
587 	default:
588 		ret = -EINVAL;
589 		break;
590 	}
591 
592 	return ret;
593 }
594 
595 static int bd71828_battery_set_property(struct power_supply *psy,
596 					enum power_supply_property psp,
597 					const union power_supply_propval *val)
598 {
599 	struct bd71828_power *pwr = dev_get_drvdata(psy->dev.parent);
600 	int ret = 0;
601 
602 	switch (psp) {
603 	case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
604 		if (val->intval == POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO)
605 			ret = regmap_update_bits(pwr->regmap, pwr->regs->chg_en,
606 						 BD7182x_MASK_CHG_EN,
607 						 BD7182x_MASK_CHG_EN);
608 		else
609 			ret = regmap_update_bits(pwr->regmap, pwr->regs->chg_en,
610 						 BD7182x_MASK_CHG_EN,
611 						 0);
612 		break;
613 	default:
614 		return -EINVAL;
615 	}
616 
617 	return ret;
618 }
619 
620 static int bd71828_battery_property_is_writeable(struct power_supply *psy,
621 						 enum power_supply_property psp)
622 {
623 	switch (psp) {
624 	case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
625 		return true;
626 	default:
627 		return false;
628 	}
629 }
630 
631 /** @brief ac properties */
632 static const enum power_supply_property bd71828_charger_props[] = {
633 	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
634 	POWER_SUPPLY_PROP_ONLINE,
635 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
636 };
637 
638 static const enum power_supply_property bd71828_battery_props[] = {
639 	POWER_SUPPLY_PROP_STATUS,
640 	POWER_SUPPLY_PROP_HEALTH,
641 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
642 	POWER_SUPPLY_PROP_HEALTH,
643 	POWER_SUPPLY_PROP_PRESENT,
644 	POWER_SUPPLY_PROP_TECHNOLOGY,
645 	POWER_SUPPLY_PROP_TEMP,
646 	POWER_SUPPLY_PROP_CURRENT_AVG,
647 	POWER_SUPPLY_PROP_CURRENT_NOW,
648 	POWER_SUPPLY_PROP_CURRENT_MAX,
649 	POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR,
650 };
651 
652 /** @brief powers supplied by bd71828_ac */
653 static char *bd71828_ac_supplied_to[] = {
654 	BAT_NAME,
655 };
656 
657 static const struct power_supply_desc bd71828_ac_desc = {
658 	.name		= AC_NAME,
659 	.type		= POWER_SUPPLY_TYPE_MAINS,
660 	.properties	= bd71828_charger_props,
661 	.num_properties	= ARRAY_SIZE(bd71828_charger_props),
662 	.get_property	= bd71828_charger_get_property,
663 	.set_property	= bd71828_charger_set_property,
664 	.property_is_writeable   = bd71828_charger_property_is_writeable,
665 };
666 
667 static const struct power_supply_desc bd71828_bat_desc = {
668 	.name		= BAT_NAME,
669 	.type		= POWER_SUPPLY_TYPE_BATTERY,
670 	.charge_behaviours = BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO) |
671 			     BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE),
672 	.properties	= bd71828_battery_props,
673 	.num_properties = ARRAY_SIZE(bd71828_battery_props),
674 	.get_property	= bd71828_battery_get_property,
675 	.set_property	= bd71828_battery_set_property,
676 	.property_is_writeable   = bd71828_battery_property_is_writeable,
677 };
678 
679 #define RSENS_CURR 10000000LLU
680 
681 #define BD_ISR_NAME(name) \
682 bd7181x_##name##_isr
683 
684 #define BD_ISR_BAT(name, print, run_gauge)				\
685 static irqreturn_t BD_ISR_NAME(name)(int irq, void *data)		\
686 {									\
687 	struct bd71828_power *pwr = (struct bd71828_power *)data;	\
688 									\
689 	dev_dbg(pwr->dev, "%s\n", print);				\
690 	power_supply_changed(pwr->bat);				\
691 									\
692 	return IRQ_HANDLED;						\
693 }
694 
695 #define BD_ISR_AC(name, print, run_gauge)				\
696 static irqreturn_t BD_ISR_NAME(name)(int irq, void *data)		\
697 {									\
698 	struct bd71828_power *pwr = (struct bd71828_power *)data;	\
699 									\
700 	power_supply_changed(pwr->ac);					\
701 	dev_dbg(pwr->dev, "%s\n", print);				\
702 	power_supply_changed(pwr->bat);				\
703 									\
704 	return IRQ_HANDLED;						\
705 }
706 
707 #define BD_ISR_DUMMY(name, print)					\
708 static irqreturn_t BD_ISR_NAME(name)(int irq, void *data)		\
709 {									\
710 	struct bd71828_power *pwr = (struct bd71828_power *)data;	\
711 									\
712 	dev_dbg(pwr->dev, "%s\n", print);				\
713 									\
714 	return IRQ_HANDLED;						\
715 }
716 
717 BD_ISR_BAT(chg_state_changed, "CHG state changed", true)
718 /* DCIN voltage changes */
719 BD_ISR_AC(dcin_removed, "DCIN removed", true)
720 BD_ISR_AC(clps_out, "DCIN voltage back to normal", true)
721 BD_ISR_AC(clps_in, "DCIN voltage collapsed", false)
722 BD_ISR_AC(dcin_ovp_res, "DCIN voltage normal", true)
723 BD_ISR_AC(dcin_ovp_det, "DCIN OVER VOLTAGE", true)
724 
725 BD_ISR_DUMMY(dcin_mon_det, "DCIN voltage below threshold")
726 BD_ISR_DUMMY(dcin_mon_res, "DCIN voltage above threshold")
727 
728 BD_ISR_DUMMY(vbus_curr_limit, "VBUS current limited")
729 BD_ISR_DUMMY(vsys_ov_res, "VSYS over-voltage cleared")
730 BD_ISR_DUMMY(vsys_ov_det, "VSYS over-voltage")
731 BD_ISR_DUMMY(vsys_uv_res, "VSYS under-voltage cleared")
732 BD_ISR_DUMMY(vsys_uv_det, "VSYS under-voltage")
733 BD_ISR_DUMMY(vsys_low_res, "'VSYS low' cleared")
734 BD_ISR_DUMMY(vsys_low_det, "VSYS low")
735 BD_ISR_DUMMY(vsys_mon_res, "VSYS mon - resumed")
736 BD_ISR_DUMMY(vsys_mon_det, "VSYS mon - detected")
737 BD_ISR_BAT(chg_wdg_temp, "charger temperature watchdog triggered", true)
738 BD_ISR_BAT(chg_wdg, "charging watchdog triggered", true)
739 BD_ISR_BAT(bat_removed, "Battery removed", true)
740 BD_ISR_BAT(bat_det, "Battery detected", true)
741 /* TODO: Verify the meaning of these interrupts */
742 BD_ISR_BAT(rechg_det, "Recharging", true)
743 BD_ISR_BAT(rechg_res, "Recharge ending", true)
744 BD_ISR_DUMMY(temp_transit, "Temperature transition")
745 BD_ISR_BAT(therm_rmv, "bd71815-therm-rmv", false)
746 BD_ISR_BAT(therm_det, "bd71815-therm-det", true)
747 BD_ISR_BAT(bat_dead, "bd71815-bat-dead", false)
748 BD_ISR_BAT(bat_short_res, "bd71815-bat-short-res", true)
749 BD_ISR_BAT(bat_short, "bd71815-bat-short-det", false)
750 BD_ISR_BAT(bat_low_res, "bd71815-bat-low-res", true)
751 BD_ISR_BAT(bat_low, "bd71815-bat-low-det", true)
752 BD_ISR_BAT(bat_ov_res, "bd71815-bat-over-res", true)
753 /* What should we do here? */
754 BD_ISR_BAT(bat_ov, "bd71815-bat-over-det", false)
755 BD_ISR_BAT(bat_mon_res, "bd71815-bat-mon-res", true)
756 BD_ISR_BAT(bat_mon, "bd71815-bat-mon-det", true)
757 BD_ISR_BAT(bat_cc_mon, "bd71815-bat-cc-mon2", false)
758 BD_ISR_BAT(bat_oc1_res, "bd71815-bat-oc1-res", true)
759 BD_ISR_BAT(bat_oc1, "bd71815-bat-oc1-det", false)
760 BD_ISR_BAT(bat_oc2_res, "bd71815-bat-oc2-res", true)
761 BD_ISR_BAT(bat_oc2, "bd71815-bat-oc2-det", false)
762 BD_ISR_BAT(bat_oc3_res, "bd71815-bat-oc3-res", true)
763 BD_ISR_BAT(bat_oc3, "bd71815-bat-oc3-det", false)
764 BD_ISR_BAT(temp_bat_low_res, "bd71815-temp-bat-low-res", true)
765 BD_ISR_BAT(temp_bat_low, "bd71815-temp-bat-low-det", true)
766 BD_ISR_BAT(temp_bat_hi_res, "bd71815-temp-bat-hi-res", true)
767 BD_ISR_BAT(temp_bat_hi, "bd71815-temp-bat-hi-det", true)
768 
769 static irqreturn_t bd7182x_dcin_removed(int irq, void *data)
770 {
771 	struct bd71828_power *pwr = (struct bd71828_power *)data;
772 
773 	power_supply_changed(pwr->ac);
774 	dev_dbg(pwr->dev, "DCIN removed\n");
775 
776 	return IRQ_HANDLED;
777 }
778 
779 static irqreturn_t bd718x7_chg_done(int irq, void *data)
780 {
781 	struct bd71828_power *pwr = (struct bd71828_power *)data;
782 
783 	power_supply_changed(pwr->bat);
784 
785 	return IRQ_HANDLED;
786 }
787 
788 static irqreturn_t bd7182x_dcin_detected(int irq, void *data)
789 {
790 	struct bd71828_power *pwr = (struct bd71828_power *)data;
791 
792 	dev_dbg(pwr->dev, "DCIN inserted\n");
793 	power_supply_changed(pwr->ac);
794 
795 	return IRQ_HANDLED;
796 }
797 
798 static irqreturn_t bd71828_vbat_low_res(int irq, void *data)
799 {
800 	struct bd71828_power *pwr = (struct bd71828_power *)data;
801 
802 	dev_dbg(pwr->dev, "VBAT LOW Resumed\n");
803 
804 	return IRQ_HANDLED;
805 }
806 
807 static irqreturn_t bd71828_vbat_low_det(int irq, void *data)
808 {
809 	struct bd71828_power *pwr = (struct bd71828_power *)data;
810 
811 	dev_dbg(pwr->dev, "VBAT LOW Detected\n");
812 
813 	return IRQ_HANDLED;
814 }
815 
816 static irqreturn_t bd71828_temp_bat_hi_det(int irq, void *data)
817 {
818 	struct bd71828_power *pwr = (struct bd71828_power *)data;
819 
820 	dev_warn(pwr->dev, "Overtemp Detected\n");
821 	power_supply_changed(pwr->bat);
822 
823 	return IRQ_HANDLED;
824 }
825 
826 static irqreturn_t bd71828_temp_bat_hi_res(int irq, void *data)
827 {
828 	struct bd71828_power *pwr = (struct bd71828_power *)data;
829 
830 	dev_dbg(pwr->dev, "Overtemp Resumed\n");
831 	power_supply_changed(pwr->bat);
832 
833 	return IRQ_HANDLED;
834 }
835 
836 static irqreturn_t bd71828_temp_bat_low_det(int irq, void *data)
837 {
838 	struct bd71828_power *pwr = (struct bd71828_power *)data;
839 
840 	dev_dbg(pwr->dev, "Lowtemp Detected\n");
841 	power_supply_changed(pwr->bat);
842 
843 	return IRQ_HANDLED;
844 }
845 
846 static irqreturn_t bd71828_temp_bat_low_res(int irq, void *data)
847 {
848 	struct bd71828_power *pwr = (struct bd71828_power *)data;
849 
850 	dev_dbg(pwr->dev, "Lowtemp Resumed\n");
851 	power_supply_changed(pwr->bat);
852 
853 	return IRQ_HANDLED;
854 }
855 
856 static irqreturn_t bd71828_temp_vf_det(int irq, void *data)
857 {
858 	struct bd71828_power *pwr = (struct bd71828_power *)data;
859 
860 	dev_dbg(pwr->dev, "VF Detected\n");
861 	power_supply_changed(pwr->bat);
862 
863 	return IRQ_HANDLED;
864 }
865 
866 static irqreturn_t bd71828_temp_vf_res(int irq, void *data)
867 {
868 	struct bd71828_power *pwr = (struct bd71828_power *)data;
869 
870 	dev_dbg(pwr->dev, "VF Resumed\n");
871 	power_supply_changed(pwr->bat);
872 
873 	return IRQ_HANDLED;
874 }
875 
876 static irqreturn_t bd71828_temp_vf125_det(int irq, void *data)
877 {
878 	struct bd71828_power *pwr = (struct bd71828_power *)data;
879 
880 	dev_dbg(pwr->dev, "VF125 Detected\n");
881 	power_supply_changed(pwr->bat);
882 
883 	return IRQ_HANDLED;
884 }
885 
886 static irqreturn_t bd71828_temp_vf125_res(int irq, void *data)
887 {
888 	struct bd71828_power *pwr = (struct bd71828_power *)data;
889 
890 	dev_dbg(pwr->dev, "VF125 Resumed\n");
891 	power_supply_changed(pwr->bat);
892 
893 	return IRQ_HANDLED;
894 }
895 
896 struct bd7182x_irq_res {
897 	const char *name;
898 	irq_handler_t handler;
899 };
900 
901 #define BDIRQ(na, hn) { .name = (na), .handler = (hn) }
902 
903 static int bd7182x_get_irqs(struct platform_device *pdev,
904 			    struct bd71828_power *pwr)
905 {
906 	int i, irq, ret;
907 	static const struct bd7182x_irq_res bd71815_irqs[] = {
908 		BDIRQ("bd71815-dcin-rmv", BD_ISR_NAME(dcin_removed)),
909 		BDIRQ("bd71815-dcin-clps-out", BD_ISR_NAME(clps_out)),
910 		BDIRQ("bd71815-dcin-clps-in", BD_ISR_NAME(clps_in)),
911 		BDIRQ("bd71815-dcin-ovp-res", BD_ISR_NAME(dcin_ovp_res)),
912 		BDIRQ("bd71815-dcin-ovp-det", BD_ISR_NAME(dcin_ovp_det)),
913 		BDIRQ("bd71815-dcin-mon-res", BD_ISR_NAME(dcin_mon_res)),
914 		BDIRQ("bd71815-dcin-mon-det", BD_ISR_NAME(dcin_mon_det)),
915 
916 		BDIRQ("bd71815-vsys-uv-res", BD_ISR_NAME(vsys_uv_res)),
917 		BDIRQ("bd71815-vsys-uv-det", BD_ISR_NAME(vsys_uv_det)),
918 		BDIRQ("bd71815-vsys-low-res", BD_ISR_NAME(vsys_low_res)),
919 		BDIRQ("bd71815-vsys-low-det",  BD_ISR_NAME(vsys_low_det)),
920 		BDIRQ("bd71815-vsys-mon-res",  BD_ISR_NAME(vsys_mon_res)),
921 		BDIRQ("bd71815-vsys-mon-det",  BD_ISR_NAME(vsys_mon_det)),
922 		BDIRQ("bd71815-chg-wdg-temp", BD_ISR_NAME(chg_wdg_temp)),
923 		BDIRQ("bd71815-chg-wdg",  BD_ISR_NAME(chg_wdg)),
924 		BDIRQ("bd71815-rechg-det", BD_ISR_NAME(rechg_det)),
925 		BDIRQ("bd71815-rechg-res", BD_ISR_NAME(rechg_res)),
926 		BDIRQ("bd71815-ranged-temp-transit", BD_ISR_NAME(temp_transit)),
927 		BDIRQ("bd71815-chg-state-change", BD_ISR_NAME(chg_state_changed)),
928 		BDIRQ("bd71815-bat-temp-normal", bd71828_temp_bat_hi_res),
929 		BDIRQ("bd71815-bat-temp-erange", bd71828_temp_bat_hi_det),
930 		BDIRQ("bd71815-bat-rmv", BD_ISR_NAME(bat_removed)),
931 		BDIRQ("bd71815-bat-det", BD_ISR_NAME(bat_det)),
932 
933 		/* Add ISRs for these */
934 		BDIRQ("bd71815-therm-rmv", BD_ISR_NAME(therm_rmv)),
935 		BDIRQ("bd71815-therm-det", BD_ISR_NAME(therm_det)),
936 		BDIRQ("bd71815-bat-dead", BD_ISR_NAME(bat_dead)),
937 		BDIRQ("bd71815-bat-short-res", BD_ISR_NAME(bat_short_res)),
938 		BDIRQ("bd71815-bat-short-det", BD_ISR_NAME(bat_short)),
939 		BDIRQ("bd71815-bat-low-res", BD_ISR_NAME(bat_low_res)),
940 		BDIRQ("bd71815-bat-low-det", BD_ISR_NAME(bat_low)),
941 		BDIRQ("bd71815-bat-over-res", BD_ISR_NAME(bat_ov_res)),
942 		BDIRQ("bd71815-bat-over-det", BD_ISR_NAME(bat_ov)),
943 		BDIRQ("bd71815-bat-mon-res", BD_ISR_NAME(bat_mon_res)),
944 		BDIRQ("bd71815-bat-mon-det", BD_ISR_NAME(bat_mon)),
945 		/* cc-mon 1 & 3 ? */
946 		BDIRQ("bd71815-bat-cc-mon2", BD_ISR_NAME(bat_cc_mon)),
947 		BDIRQ("bd71815-bat-oc1-res", BD_ISR_NAME(bat_oc1_res)),
948 		BDIRQ("bd71815-bat-oc1-det", BD_ISR_NAME(bat_oc1)),
949 		BDIRQ("bd71815-bat-oc2-res", BD_ISR_NAME(bat_oc2_res)),
950 		BDIRQ("bd71815-bat-oc2-det", BD_ISR_NAME(bat_oc2)),
951 		BDIRQ("bd71815-bat-oc3-res", BD_ISR_NAME(bat_oc3_res)),
952 		BDIRQ("bd71815-bat-oc3-det", BD_ISR_NAME(bat_oc3)),
953 		BDIRQ("bd71815-temp-bat-low-res", BD_ISR_NAME(temp_bat_low_res)),
954 		BDIRQ("bd71815-temp-bat-low-det", BD_ISR_NAME(temp_bat_low)),
955 		BDIRQ("bd71815-temp-bat-hi-res", BD_ISR_NAME(temp_bat_hi_res)),
956 		BDIRQ("bd71815-temp-bat-hi-det", BD_ISR_NAME(temp_bat_hi)),
957 		/*
958 		 * TODO: add rest of the IRQs and re-check the handling.
959 		 * Check the bd71815-bat-cc-mon1, bd71815-bat-cc-mon3,
960 		 * bd71815-bat-low-res, bd71815-bat-low-det,
961 		 * bd71815-bat-hi-res, bd71815-bat-hi-det.
962 		 */
963 	};
964 	static const struct bd7182x_irq_res bd71828_irqs[] = {
965 		BDIRQ("bd71828-chg-done", bd718x7_chg_done),
966 		BDIRQ("bd71828-pwr-dcin-in", bd7182x_dcin_detected),
967 		BDIRQ("bd71828-pwr-dcin-out", bd7182x_dcin_removed),
968 		BDIRQ("bd71828-vbat-normal", bd71828_vbat_low_res),
969 		BDIRQ("bd71828-vbat-low", bd71828_vbat_low_det),
970 		BDIRQ("bd71828-btemp-hi", bd71828_temp_bat_hi_det),
971 		BDIRQ("bd71828-btemp-cool", bd71828_temp_bat_hi_res),
972 		BDIRQ("bd71828-btemp-lo", bd71828_temp_bat_low_det),
973 		BDIRQ("bd71828-btemp-warm", bd71828_temp_bat_low_res),
974 		BDIRQ("bd71828-temp-hi", bd71828_temp_vf_det),
975 		BDIRQ("bd71828-temp-norm", bd71828_temp_vf_res),
976 		BDIRQ("bd71828-temp-125-over", bd71828_temp_vf125_det),
977 		BDIRQ("bd71828-temp-125-under", bd71828_temp_vf125_res),
978 	};
979 	static const struct bd7182x_irq_res bd72720_irqs[] = {
980 		BDIRQ("bd72720_int_vbus_rmv", BD_ISR_NAME(dcin_removed)),
981 		BDIRQ("bd72720_int_vbus_det", bd7182x_dcin_detected),
982 		BDIRQ("bd72720_int_vbus_mon_res", BD_ISR_NAME(dcin_mon_res)),
983 		BDIRQ("bd72720_int_vbus_mon_det", BD_ISR_NAME(dcin_mon_det)),
984 		BDIRQ("bd72720_int_vsys_mon_res", BD_ISR_NAME(vsys_mon_res)),
985 		BDIRQ("bd72720_int_vsys_mon_det", BD_ISR_NAME(vsys_mon_det)),
986 		BDIRQ("bd72720_int_vsys_uv_res", BD_ISR_NAME(vsys_uv_res)),
987 		BDIRQ("bd72720_int_vsys_uv_det", BD_ISR_NAME(vsys_uv_det)),
988 		BDIRQ("bd72720_int_vsys_lo_res", BD_ISR_NAME(vsys_low_res)),
989 		BDIRQ("bd72720_int_vsys_lo_det", BD_ISR_NAME(vsys_low_det)),
990 		BDIRQ("bd72720_int_vsys_ov_res", BD_ISR_NAME(vsys_ov_res)),
991 		BDIRQ("bd72720_int_vsys_ov_det", BD_ISR_NAME(vsys_ov_det)),
992 		BDIRQ("bd72720_int_bat_ilim", BD_ISR_NAME(vbus_curr_limit)),
993 		BDIRQ("bd72720_int_chg_done", bd718x7_chg_done),
994 		BDIRQ("bd72720_int_extemp_tout", BD_ISR_NAME(chg_wdg_temp)),
995 		BDIRQ("bd72720_int_chg_wdt_exp", BD_ISR_NAME(chg_wdg)),
996 		BDIRQ("bd72720_int_bat_mnt_out", BD_ISR_NAME(rechg_res)),
997 		BDIRQ("bd72720_int_bat_mnt_in", BD_ISR_NAME(rechg_det)),
998 		BDIRQ("bd72720_int_chg_trns", BD_ISR_NAME(chg_state_changed)),
999 
1000 		BDIRQ("bd72720_int_vbat_mon_res", BD_ISR_NAME(bat_mon_res)),
1001 		BDIRQ("bd72720_int_vbat_mon_det", BD_ISR_NAME(bat_mon)),
1002 		BDIRQ("bd72720_int_vbat_sht_res", BD_ISR_NAME(bat_short_res)),
1003 		BDIRQ("bd72720_int_vbat_sht_det", BD_ISR_NAME(bat_short)),
1004 		BDIRQ("bd72720_int_vbat_lo_res", BD_ISR_NAME(bat_low_res)),
1005 		BDIRQ("bd72720_int_vbat_lo_det", BD_ISR_NAME(bat_low)),
1006 		BDIRQ("bd72720_int_vbat_ov_res", BD_ISR_NAME(bat_ov_res)),
1007 		BDIRQ("bd72720_int_vbat_ov_det", BD_ISR_NAME(bat_ov)),
1008 		BDIRQ("bd72720_int_bat_rmv", BD_ISR_NAME(bat_removed)),
1009 		BDIRQ("bd72720_int_bat_det", BD_ISR_NAME(bat_det)),
1010 		BDIRQ("bd72720_int_dbat_det", BD_ISR_NAME(bat_dead)),
1011 		BDIRQ("bd72720_int_bat_temp_trns", BD_ISR_NAME(temp_transit)),
1012 		BDIRQ("bd72720_int_lobtmp_res", BD_ISR_NAME(temp_bat_low_res)),
1013 		BDIRQ("bd72720_int_lobtmp_det", BD_ISR_NAME(temp_bat_low)),
1014 		BDIRQ("bd72720_int_ovbtmp_res", BD_ISR_NAME(temp_bat_hi_res)),
1015 		BDIRQ("bd72720_int_ovbtmp_det", BD_ISR_NAME(temp_bat_hi)),
1016 		BDIRQ("bd72720_int_ocur1_res", BD_ISR_NAME(bat_oc1_res)),
1017 		BDIRQ("bd72720_int_ocur1_det", BD_ISR_NAME(bat_oc1)),
1018 		BDIRQ("bd72720_int_ocur2_res", BD_ISR_NAME(bat_oc2_res)),
1019 		BDIRQ("bd72720_int_ocur2_det", BD_ISR_NAME(bat_oc2)),
1020 		BDIRQ("bd72720_int_ocur3_res", BD_ISR_NAME(bat_oc3_res)),
1021 		BDIRQ("bd72720_int_ocur3_det", BD_ISR_NAME(bat_oc3)),
1022 		BDIRQ("bd72720_int_cc_mon2_det", BD_ISR_NAME(bat_cc_mon)),
1023 	};
1024 	int num_irqs;
1025 	const struct bd7182x_irq_res *irqs;
1026 
1027 	switch (pwr->chip_type) {
1028 	case ROHM_CHIP_TYPE_BD71828:
1029 		irqs = &bd71828_irqs[0];
1030 		num_irqs = ARRAY_SIZE(bd71828_irqs);
1031 		break;
1032 	case ROHM_CHIP_TYPE_BD71815:
1033 		irqs = &bd71815_irqs[0];
1034 		num_irqs = ARRAY_SIZE(bd71815_irqs);
1035 		break;
1036 	case ROHM_CHIP_TYPE_BD72720:
1037 		irqs = &bd72720_irqs[0];
1038 		num_irqs = ARRAY_SIZE(bd72720_irqs);
1039 		break;
1040 	default:
1041 		return -EINVAL;
1042 	}
1043 
1044 	for (i = 0; i < num_irqs; i++) {
1045 		irq = platform_get_irq_byname(pdev, irqs[i].name);
1046 
1047 		ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
1048 						irqs[i].handler, 0,
1049 						irqs[i].name, pwr);
1050 		if (ret)
1051 			break;
1052 	}
1053 
1054 	return ret;
1055 }
1056 
1057 #define RSENS_DEFAULT_30MOHM 30000 /* 30 mOhm in uOhms*/
1058 
1059 static int bd7182x_get_rsens(struct bd71828_power *pwr)
1060 {
1061 	u64 tmp = RSENS_CURR;
1062 	int rsens_ohm = RSENS_DEFAULT_30MOHM;
1063 	struct fwnode_handle *node = NULL;
1064 
1065 	if (pwr->dev->parent)
1066 		node = dev_fwnode(pwr->dev->parent);
1067 
1068 	if (node) {
1069 		int ret;
1070 		u32 rs;
1071 
1072 		ret = fwnode_property_read_u32(node,
1073 					       "rohm,charger-sense-resistor-micro-ohms",
1074 					       &rs);
1075 		if (ret) {
1076 			if (ret == -EINVAL) {
1077 				rs = RSENS_DEFAULT_30MOHM;
1078 			} else {
1079 				dev_err(pwr->dev, "Bad RSENS dt property\n");
1080 				return ret;
1081 			}
1082 		}
1083 		if (!rs) {
1084 			dev_err(pwr->dev, "Bad RSENS value\n");
1085 			return -EINVAL;
1086 		}
1087 
1088 		rsens_ohm = (int)rs;
1089 	}
1090 
1091 	/* Reg val to uA */
1092 	do_div(tmp, rsens_ohm);
1093 
1094 	pwr->curr_factor = tmp;
1095 	pwr->rsens = rsens_ohm;
1096 	dev_dbg(pwr->dev, "Setting rsens to %u micro ohm\n", pwr->rsens);
1097 	dev_dbg(pwr->dev, "Setting curr-factor to %u\n", pwr->curr_factor);
1098 
1099 	return 0;
1100 }
1101 
1102 static int bd71828_power_probe(struct platform_device *pdev)
1103 {
1104 	struct bd71828_power *pwr;
1105 	struct power_supply_config ac_cfg = {};
1106 	struct power_supply_config bat_cfg = {};
1107 	int ret;
1108 
1109 	pwr = devm_kzalloc(&pdev->dev, sizeof(*pwr), GFP_KERNEL);
1110 	if (!pwr)
1111 		return -ENOMEM;
1112 
1113 	/*
1114 	 * The BD72720 MFD device registers two regmaps. Power-supply driver
1115 	 * uses the "wrap-map", which provides access to both of the I2C slave
1116 	 * addresses used by the BD72720
1117 	 */
1118 	pwr->chip_type = platform_get_device_id(pdev)->driver_data;
1119 	if (pwr->chip_type != ROHM_CHIP_TYPE_BD72720)
1120 		pwr->regmap = dev_get_regmap(pdev->dev.parent, NULL);
1121 	else
1122 		pwr->regmap = dev_get_regmap(pdev->dev.parent, "wrap-map");
1123 	if (!pwr->regmap)
1124 		return dev_err_probe(&pdev->dev, -EINVAL, "No parent regmap\n");
1125 
1126 	pwr->dev = &pdev->dev;
1127 
1128 	switch (pwr->chip_type) {
1129 	case ROHM_CHIP_TYPE_BD71828:
1130 		pwr->bat_inserted = bd71828_bat_inserted;
1131 		pwr->get_temp = bd71828_get_temp;
1132 		pwr->regs = &pwr_regs_bd71828;
1133 		break;
1134 	case ROHM_CHIP_TYPE_BD71815:
1135 		pwr->bat_inserted = bd71815_bat_inserted;
1136 		pwr->get_temp = bd71815_get_temp;
1137 		pwr->regs = &pwr_regs_bd71815;
1138 		break;
1139 	case ROHM_CHIP_TYPE_BD72720:
1140 		pwr->bat_inserted = bd71828_bat_inserted;
1141 		pwr->regs = &pwr_regs_bd72720;
1142 		pwr->get_temp = bd71828_get_temp;
1143 		dev_dbg(pwr->dev, "Found ROHM BD72720\n");
1144 		break;
1145 	default:
1146 		return dev_err_probe(pwr->dev, -EINVAL, "Unknown PMIC\n");
1147 	}
1148 
1149 	ret = bd7182x_get_rsens(pwr);
1150 	if (ret)
1151 		return dev_err_probe(&pdev->dev, ret, "sense resistor missing\n");
1152 
1153 	dev_set_drvdata(&pdev->dev, pwr);
1154 	bd71828_init_hardware(pwr);
1155 
1156 	bat_cfg.drv_data	= pwr;
1157 	bat_cfg.fwnode		= dev_fwnode(&pdev->dev);
1158 
1159 	ac_cfg.supplied_to	= bd71828_ac_supplied_to;
1160 	ac_cfg.num_supplicants	= ARRAY_SIZE(bd71828_ac_supplied_to);
1161 	ac_cfg.drv_data		= pwr;
1162 
1163 	pwr->ac = devm_power_supply_register(&pdev->dev, &bd71828_ac_desc,
1164 					     &ac_cfg);
1165 	if (IS_ERR(pwr->ac))
1166 		return dev_err_probe(&pdev->dev, PTR_ERR(pwr->ac),
1167 				     "failed to register ac\n");
1168 
1169 	pwr->bat = devm_power_supply_register(&pdev->dev, &bd71828_bat_desc,
1170 					      &bat_cfg);
1171 	if (IS_ERR(pwr->bat))
1172 		return dev_err_probe(&pdev->dev, PTR_ERR(pwr->bat),
1173 				     "failed to register bat\n");
1174 
1175 	ret = bd7182x_get_irqs(pdev, pwr);
1176 	if (ret)
1177 		return dev_err_probe(&pdev->dev, ret, "failed to request IRQs");
1178 
1179 	/* Configure wakeup capable */
1180 	device_set_wakeup_capable(pwr->dev, 1);
1181 	device_set_wakeup_enable(pwr->dev, 1);
1182 
1183 	return 0;
1184 }
1185 
1186 static const struct platform_device_id bd71828_charger_id[] = {
1187 	{ "bd71815-power", ROHM_CHIP_TYPE_BD71815 },
1188 	{ "bd71828-power", ROHM_CHIP_TYPE_BD71828 },
1189 	{ "bd72720-power", ROHM_CHIP_TYPE_BD72720 },
1190 	{ },
1191 };
1192 MODULE_DEVICE_TABLE(platform, bd71828_charger_id);
1193 
1194 static struct platform_driver bd71828_power_driver = {
1195 	.driver = {
1196 		.name = "bd718xx-power",
1197 	},
1198 	.probe = bd71828_power_probe,
1199 	.id_table = bd71828_charger_id,
1200 };
1201 
1202 module_platform_driver(bd71828_power_driver);
1203 
1204 MODULE_AUTHOR("Cong Pham <cpham2403@gmail.com>");
1205 MODULE_DESCRIPTION("ROHM BD718(15/28/78) PMIC Battery Charger driver");
1206 MODULE_LICENSE("GPL");
1207