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