xref: /OK3568_Linux_fs/u-boot/drivers/power/pmic/rk8xx.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (C) 2015 Google, Inc
3*4882a593Smuzhiyun  * Written by Simon Glass <sjg@chromium.org>
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <common.h>
9*4882a593Smuzhiyun #include <dm.h>
10*4882a593Smuzhiyun #include <errno.h>
11*4882a593Smuzhiyun #include <irq-generic.h>
12*4882a593Smuzhiyun #include <power/rk8xx_pmic.h>
13*4882a593Smuzhiyun #include <power/pmic.h>
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(IRQ)
18*4882a593Smuzhiyun /* RK805 */
19*4882a593Smuzhiyun static const struct virq_reg rk805_irqs[] = {
20*4882a593Smuzhiyun 	[RK8XX_IRQ_PWRON_FALL] = {
21*4882a593Smuzhiyun 		.mask = RK805_IRQ_PWRON_FALL_MSK,
22*4882a593Smuzhiyun 		.reg_offset = 0,
23*4882a593Smuzhiyun 	},
24*4882a593Smuzhiyun 	[RK8XX_IRQ_PWRON_RISE] = {
25*4882a593Smuzhiyun 		.mask = RK805_IRQ_PWRON_RISE_MSK,
26*4882a593Smuzhiyun 		.reg_offset = 0,
27*4882a593Smuzhiyun 	},
28*4882a593Smuzhiyun };
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun static struct virq_chip rk805_irq_chip = {
31*4882a593Smuzhiyun 	.status_base		= RK805_INT_STS_REG,
32*4882a593Smuzhiyun 	.mask_base		= RK805_INT_MSK_REG,
33*4882a593Smuzhiyun 	.num_regs		= 1,
34*4882a593Smuzhiyun 	.read			= pmic_reg_read,
35*4882a593Smuzhiyun 	.write			= pmic_reg_write,
36*4882a593Smuzhiyun 	.irqs			= rk805_irqs,
37*4882a593Smuzhiyun 	.num_irqs		= ARRAY_SIZE(rk805_irqs),
38*4882a593Smuzhiyun };
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun /* RK808 */
41*4882a593Smuzhiyun static const struct virq_reg rk808_irqs[] = {
42*4882a593Smuzhiyun 	[RK8XX_IRQ_PLUG_OUT] = {
43*4882a593Smuzhiyun 		.mask = RK808_IRQ_PLUG_OUT_MSK,
44*4882a593Smuzhiyun 		.reg_offset = 1,
45*4882a593Smuzhiyun 	},
46*4882a593Smuzhiyun };
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun static struct virq_chip rk808_irq_chip = {
49*4882a593Smuzhiyun 	.status_base		= RK808_INT_STS_REG1,
50*4882a593Smuzhiyun 	.mask_base		= RK808_INT_MSK_REG1,
51*4882a593Smuzhiyun 	.irq_reg_stride		= 2,
52*4882a593Smuzhiyun 	.num_regs		= 2,
53*4882a593Smuzhiyun 	.read			= pmic_reg_read,
54*4882a593Smuzhiyun 	.write			= pmic_reg_write,
55*4882a593Smuzhiyun 	.irqs			= rk808_irqs,
56*4882a593Smuzhiyun 	.num_irqs		= ARRAY_SIZE(rk808_irqs),
57*4882a593Smuzhiyun };
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun /* RK816 */
60*4882a593Smuzhiyun static const struct virq_reg rk816_irqs[] = {
61*4882a593Smuzhiyun 	[RK8XX_IRQ_PWRON_FALL] = {
62*4882a593Smuzhiyun 		.mask = RK816_IRQ_PWRON_FALL_MSK,
63*4882a593Smuzhiyun 		.reg_offset = 0,
64*4882a593Smuzhiyun 	},
65*4882a593Smuzhiyun 	[RK8XX_IRQ_PWRON_RISE] = {
66*4882a593Smuzhiyun 		.mask = RK816_IRQ_PWRON_RISE_MSK,
67*4882a593Smuzhiyun 		.reg_offset = 0,
68*4882a593Smuzhiyun 	},
69*4882a593Smuzhiyun 	[RK8XX_IRQ_PLUG_OUT] = {
70*4882a593Smuzhiyun 		.mask = RK816_IRQ_PLUG_OUT_MSK,
71*4882a593Smuzhiyun 		.reg_offset = 2,
72*4882a593Smuzhiyun 	},
73*4882a593Smuzhiyun 	[RK8XX_IRQ_CHG_OK] = {
74*4882a593Smuzhiyun 		.mask = RK816_IRQ_CHR_OK_MSK,
75*4882a593Smuzhiyun 		.reg_offset = 2,
76*4882a593Smuzhiyun 	},
77*4882a593Smuzhiyun };
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun static struct virq_chip rk816_irq_chip = {
80*4882a593Smuzhiyun 	.status_base		= RK816_INT_STS_REG1,
81*4882a593Smuzhiyun 	.mask_base		= RK816_INT_MSK_REG1,
82*4882a593Smuzhiyun 	.irq_unalign_reg_idx	= 1,	/* idx <= 1, stride = 3 */
83*4882a593Smuzhiyun 	.irq_unalign_reg_stride	= 3,
84*4882a593Smuzhiyun 	.irq_reg_stride		= 2,	/* idx > 1, stride = 2 */
85*4882a593Smuzhiyun 	.num_regs		= 3,
86*4882a593Smuzhiyun 	.read			= pmic_reg_read,
87*4882a593Smuzhiyun 	.write			= pmic_reg_write,
88*4882a593Smuzhiyun 	.irqs			= rk816_irqs,
89*4882a593Smuzhiyun 	.num_irqs		= ARRAY_SIZE(rk816_irqs),
90*4882a593Smuzhiyun };
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun /* RK818 */
93*4882a593Smuzhiyun static const struct virq_reg rk818_irqs[] = {
94*4882a593Smuzhiyun 	[RK8XX_IRQ_PLUG_OUT] = {
95*4882a593Smuzhiyun 		.mask = RK818_IRQ_PLUG_OUT_MSK,
96*4882a593Smuzhiyun 		.reg_offset = 1,
97*4882a593Smuzhiyun 	},
98*4882a593Smuzhiyun 	[RK8XX_IRQ_CHG_OK] = {
99*4882a593Smuzhiyun 		.mask = RK818_IRQ_CHR_OK_MSK,
100*4882a593Smuzhiyun 		.reg_offset = 1,
101*4882a593Smuzhiyun 	},
102*4882a593Smuzhiyun };
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun static struct virq_chip rk818_irq_chip = {
105*4882a593Smuzhiyun 	.status_base		= RK818_INT_STS_REG1,
106*4882a593Smuzhiyun 	.mask_base		= RK818_INT_MSK_REG1,
107*4882a593Smuzhiyun 	.irq_reg_stride		= 2,
108*4882a593Smuzhiyun 	.num_regs		= 2,
109*4882a593Smuzhiyun 	.read			= pmic_reg_read,
110*4882a593Smuzhiyun 	.write			= pmic_reg_write,
111*4882a593Smuzhiyun 	.irqs			= rk818_irqs,
112*4882a593Smuzhiyun 	.num_irqs		= ARRAY_SIZE(rk818_irqs),
113*4882a593Smuzhiyun };
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun /* RK817/RK809 */
116*4882a593Smuzhiyun static const struct virq_reg rk817_irqs[] = {
117*4882a593Smuzhiyun 	[RK8XX_IRQ_PWRON_FALL] = {
118*4882a593Smuzhiyun 		.mask = RK817_IRQ_PWRON_FALL_MSK,
119*4882a593Smuzhiyun 		.reg_offset = 0,
120*4882a593Smuzhiyun 	},
121*4882a593Smuzhiyun 	[RK8XX_IRQ_PWRON_RISE] = {
122*4882a593Smuzhiyun 		.mask = RK817_IRQ_PWRON_RISE_MSK,
123*4882a593Smuzhiyun 		.reg_offset = 0,
124*4882a593Smuzhiyun 	},
125*4882a593Smuzhiyun 	[RK8XX_IRQ_PLUG_OUT] = {
126*4882a593Smuzhiyun 		.mask = RK817_IRQ_PLUG_OUT_MSK,
127*4882a593Smuzhiyun 		.reg_offset = 1,
128*4882a593Smuzhiyun 	},
129*4882a593Smuzhiyun 	[RK8XX_IRQ_PLUG_IN] = {
130*4882a593Smuzhiyun 		.mask = RK817_IRQ_PLUG_IN_MSK,
131*4882a593Smuzhiyun 		.reg_offset = 1,
132*4882a593Smuzhiyun 	},
133*4882a593Smuzhiyun };
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun static struct virq_chip rk817_irq_chip = {
136*4882a593Smuzhiyun 	.status_base		= RK817_INT_STS_REG0,
137*4882a593Smuzhiyun 	.mask_base		= RK817_INT_MSK_REG0,
138*4882a593Smuzhiyun 	.irq_reg_stride		= 2,
139*4882a593Smuzhiyun 	.num_regs		= 3,
140*4882a593Smuzhiyun 	.read			= pmic_reg_read,
141*4882a593Smuzhiyun 	.write			= pmic_reg_write,
142*4882a593Smuzhiyun 	.irqs			= rk817_irqs,
143*4882a593Smuzhiyun 	.num_irqs		= ARRAY_SIZE(rk817_irqs),
144*4882a593Smuzhiyun };
145*4882a593Smuzhiyun #endif
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun static struct reg_data rk817_init_reg[] = {
148*4882a593Smuzhiyun /* enable the under-voltage protection,
149*4882a593Smuzhiyun  * the under-voltage protection will shutdown the LDO3 and reset the PMIC
150*4882a593Smuzhiyun  */
151*4882a593Smuzhiyun 	{ RK817_BUCK4_CMIN, 0x6b, 0x6e},
152*4882a593Smuzhiyun 	{ RK817_PMIC_SYS_CFG1, 0x20, 0x70},
153*4882a593Smuzhiyun 	/* Set pmic_sleep as none function */
154*4882a593Smuzhiyun 	{ RK817_PMIC_SYS_CFG3, 0x00, 0x18 },
155*4882a593Smuzhiyun 	/* GATE pin function: gate function */
156*4882a593Smuzhiyun 	{ RK817_GPIO_INT_CFG, 0x00, 0x20 },
157*4882a593Smuzhiyun #ifdef CONFIG_DM_CHARGE_DISPLAY
158*4882a593Smuzhiyun 	/* Set pmic_int active low */
159*4882a593Smuzhiyun 	{ RK817_GPIO_INT_CFG,  0x00, 0x02 },
160*4882a593Smuzhiyun #endif
161*4882a593Smuzhiyun };
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun static struct reg_data rk818_init_current[] = {
164*4882a593Smuzhiyun 	{ REG_USB_CTRL, 0x07, 0x0f}, /* 2A */
165*4882a593Smuzhiyun };
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun static const struct pmic_child_info pmic_children_info[] = {
168*4882a593Smuzhiyun 	{ .prefix = "DCDC", .driver = "rk8xx_buck"},
169*4882a593Smuzhiyun 	{ .prefix = "LDO", .driver = "rk8xx_ldo"},
170*4882a593Smuzhiyun 	{ .prefix = "SWITCH", .driver = "rk8xx_switch"},
171*4882a593Smuzhiyun 	{ },
172*4882a593Smuzhiyun };
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun static const struct pmic_child_info power_key_info[] = {
175*4882a593Smuzhiyun 	{ .prefix = "pwrkey", .driver = "rk8xx_pwrkey"},
176*4882a593Smuzhiyun 	{ },
177*4882a593Smuzhiyun };
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun static const struct pmic_child_info rtc_info[] = {
180*4882a593Smuzhiyun 	{ .prefix = "rtc", .driver = "rk8xx_rtc"},
181*4882a593Smuzhiyun 	{ },
182*4882a593Smuzhiyun };
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun static const struct pmic_child_info fuel_gauge_info[] = {
185*4882a593Smuzhiyun 	{ .addr = "1c", .prefix = "battery", .driver = "rk818_fg"},
186*4882a593Smuzhiyun 	{ .addr = "20", .prefix = "battery", .driver = "rk817_fg"},
187*4882a593Smuzhiyun 	{ .addr = "1a", .prefix = "battery", .driver = "rk816_fg"},
188*4882a593Smuzhiyun 	{ },
189*4882a593Smuzhiyun };
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun static const struct pmic_child_info rk817_codec_info[] = {
192*4882a593Smuzhiyun 	{ .prefix = "codec", .driver = "rk817_codec"},
193*4882a593Smuzhiyun 	{ },
194*4882a593Smuzhiyun };
195*4882a593Smuzhiyun 
rk8xx_reg_count(struct udevice * dev)196*4882a593Smuzhiyun static int rk8xx_reg_count(struct udevice *dev)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun 	struct rk8xx_priv *priv = dev_get_priv(dev);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	switch (priv->variant) {
201*4882a593Smuzhiyun 	case RK809_ID:
202*4882a593Smuzhiyun 	case RK817_ID:
203*4882a593Smuzhiyun 		return RK817_NUM_OF_REGS;
204*4882a593Smuzhiyun 	default:
205*4882a593Smuzhiyun 		return RK808_NUM_OF_REGS;
206*4882a593Smuzhiyun 	}
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun 
rk8xx_write(struct udevice * dev,uint reg,const uint8_t * buff,int len)209*4882a593Smuzhiyun static int rk8xx_write(struct udevice *dev, uint reg, const uint8_t *buff,
210*4882a593Smuzhiyun 			  int len)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun 	int ret;
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 	ret = dm_i2c_write(dev, reg, buff, len);
215*4882a593Smuzhiyun 	if (ret) {
216*4882a593Smuzhiyun 		printf("%s: write reg 0x%02x failed, ret=%d\n", __func__, reg, ret);
217*4882a593Smuzhiyun 		return ret;
218*4882a593Smuzhiyun 	}
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	return 0;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun 
rk8xx_read(struct udevice * dev,uint reg,uint8_t * buff,int len)223*4882a593Smuzhiyun static int rk8xx_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
224*4882a593Smuzhiyun {
225*4882a593Smuzhiyun 	int ret;
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	ret = dm_i2c_read(dev, reg, buff, len);
228*4882a593Smuzhiyun 	if (ret) {
229*4882a593Smuzhiyun 		printf("%s: read reg 0x%02x failed, ret=%d\n", __func__, reg, ret);
230*4882a593Smuzhiyun 		return ret;
231*4882a593Smuzhiyun 	}
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	return 0;
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun 
rk8xx_suspend(struct udevice * dev)236*4882a593Smuzhiyun static int rk8xx_suspend(struct udevice *dev)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun 	struct rk8xx_priv *priv = dev_get_priv(dev);
239*4882a593Smuzhiyun 	int ret = 0;
240*4882a593Smuzhiyun 	u8 val;
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	switch (priv->variant) {
243*4882a593Smuzhiyun 	case RK809_ID:
244*4882a593Smuzhiyun 	case RK817_ID:
245*4882a593Smuzhiyun 		/* pmic_sleep active high */
246*4882a593Smuzhiyun 		ret = rk8xx_read(dev, RK817_PMIC_SYS_CFG3, &val, 1);
247*4882a593Smuzhiyun 		if (ret)
248*4882a593Smuzhiyun 			return ret;
249*4882a593Smuzhiyun 		priv->sleep_pin = val;
250*4882a593Smuzhiyun 		val &= ~0x38;
251*4882a593Smuzhiyun 		val |= 0x28;
252*4882a593Smuzhiyun 		ret = rk8xx_write(dev, RK817_PMIC_SYS_CFG3, &val, 1);
253*4882a593Smuzhiyun 		break;
254*4882a593Smuzhiyun 	default:
255*4882a593Smuzhiyun 		return 0;
256*4882a593Smuzhiyun 	}
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	return ret;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun 
rk8xx_resume(struct udevice * dev)261*4882a593Smuzhiyun static int rk8xx_resume(struct udevice *dev)
262*4882a593Smuzhiyun {
263*4882a593Smuzhiyun 	struct rk8xx_priv *priv = dev_get_priv(dev);
264*4882a593Smuzhiyun 	int ret = 0;
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	switch (priv->variant) {
267*4882a593Smuzhiyun 	case RK809_ID:
268*4882a593Smuzhiyun 	case RK817_ID:
269*4882a593Smuzhiyun 		ret = rk8xx_write(dev, RK817_PMIC_SYS_CFG3, &priv->sleep_pin, 1);
270*4882a593Smuzhiyun 		break;
271*4882a593Smuzhiyun 	default:
272*4882a593Smuzhiyun 		return 0;
273*4882a593Smuzhiyun 	}
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 	return ret;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun 
rk8xx_shutdown(struct udevice * dev)278*4882a593Smuzhiyun static int rk8xx_shutdown(struct udevice *dev)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun 	struct rk8xx_priv *priv = dev_get_priv(dev);
281*4882a593Smuzhiyun 	u8 val, dev_off, devctrl_reg;
282*4882a593Smuzhiyun 	int ret = 0;
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	switch (priv->variant) {
285*4882a593Smuzhiyun 	case RK808_ID:
286*4882a593Smuzhiyun 		devctrl_reg = REG_DEVCTRL;
287*4882a593Smuzhiyun 		dev_off = BIT(3);
288*4882a593Smuzhiyun 		break;
289*4882a593Smuzhiyun 	case RK805_ID:
290*4882a593Smuzhiyun 	case RK816_ID:
291*4882a593Smuzhiyun 	case RK818_ID:
292*4882a593Smuzhiyun 		devctrl_reg = REG_DEVCTRL;
293*4882a593Smuzhiyun 		dev_off = BIT(0);
294*4882a593Smuzhiyun 		break;
295*4882a593Smuzhiyun 	case RK809_ID:
296*4882a593Smuzhiyun 	case RK817_ID:
297*4882a593Smuzhiyun 		devctrl_reg = RK817_REG_SYS_CFG3;
298*4882a593Smuzhiyun 		dev_off = BIT(0);
299*4882a593Smuzhiyun 		break;
300*4882a593Smuzhiyun 	default:
301*4882a593Smuzhiyun 		printf("Unknown PMIC: RK%x\n", priv->variant);
302*4882a593Smuzhiyun 		return -EINVAL;
303*4882a593Smuzhiyun 	}
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	ret = rk8xx_read(dev, devctrl_reg, &val, 1);
306*4882a593Smuzhiyun 	if (ret)
307*4882a593Smuzhiyun 		return ret;
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	val |= dev_off;
310*4882a593Smuzhiyun 	ret = rk8xx_write(dev, devctrl_reg, &val, 1);
311*4882a593Smuzhiyun 	if (ret)
312*4882a593Smuzhiyun 		return ret;
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	return 0;
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(PMIC_CHILDREN)
rk8xx_bind(struct udevice * dev)318*4882a593Smuzhiyun static int rk8xx_bind(struct udevice *dev)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun 	ofnode regulators_node;
321*4882a593Smuzhiyun 	int children;
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 	regulators_node = dev_read_subnode(dev, "regulators");
324*4882a593Smuzhiyun 	if (!ofnode_valid(regulators_node)) {
325*4882a593Smuzhiyun 		debug("%s: %s regulators subnode not found!\n", __func__,
326*4882a593Smuzhiyun 		      dev->name);
327*4882a593Smuzhiyun 		return -ENXIO;
328*4882a593Smuzhiyun 	}
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	children = pmic_bind_children(dev, regulators_node, pmic_children_info);
333*4882a593Smuzhiyun 	if (!children)
334*4882a593Smuzhiyun 		debug("%s: %s - no child found\n", __func__, dev->name);
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	children = pmic_bind_children(dev, dev->node, power_key_info);
337*4882a593Smuzhiyun 	if (!children)
338*4882a593Smuzhiyun 		debug("%s: %s - no child found\n", __func__, dev->name);
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	children = pmic_bind_children(dev, dev->node, rtc_info);
341*4882a593Smuzhiyun 	if (!children)
342*4882a593Smuzhiyun 		debug("%s: %s - no child found\n", __func__, dev->name);
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 	children = pmic_bind_children(dev, dev->node, fuel_gauge_info);
345*4882a593Smuzhiyun 	if (!children)
346*4882a593Smuzhiyun 		debug("%s: %s - no child found\n", __func__, dev->name);
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	children = pmic_bind_children(dev, dev->node, rk817_codec_info);
349*4882a593Smuzhiyun 	if (!children)
350*4882a593Smuzhiyun 		debug("%s: %s - no child found\n", __func__, dev->name);
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	/* Always return success for this device */
353*4882a593Smuzhiyun 	return 0;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun #endif
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(IRQ)
358*4882a593Smuzhiyun /*
359*4882a593Smuzhiyun  * When system suspend during U-Boot charge, make sure the plugout event
360*4882a593Smuzhiyun  * be able to wakeup cpu in wfi/wfe state.
361*4882a593Smuzhiyun  */
362*4882a593Smuzhiyun #ifdef CONFIG_DM_CHARGE_DISPLAY
rk8xx_plug_out_handler(int irq,void * data)363*4882a593Smuzhiyun static void rk8xx_plug_out_handler(int irq, void *data)
364*4882a593Smuzhiyun {
365*4882a593Smuzhiyun 	printf("Plug out interrupt\n");
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun #endif
368*4882a593Smuzhiyun 
rk8xx_ofdata_to_platdata(struct udevice * dev)369*4882a593Smuzhiyun static int rk8xx_ofdata_to_platdata(struct udevice *dev)
370*4882a593Smuzhiyun {
371*4882a593Smuzhiyun 	struct rk8xx_priv *rk8xx = dev_get_priv(dev);
372*4882a593Smuzhiyun 	u32 interrupt, phandle, val;
373*4882a593Smuzhiyun 	int ret;
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	phandle = dev_read_u32_default(dev, "interrupt-parent", -ENODATA);
376*4882a593Smuzhiyun 	if (phandle == -ENODATA) {
377*4882a593Smuzhiyun 		printf("Read 'interrupt-parent' failed, ret=%d\n", phandle);
378*4882a593Smuzhiyun 		return phandle;
379*4882a593Smuzhiyun 	}
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun 	ret = dev_read_u32_array(dev, "interrupts", &interrupt, 1);
382*4882a593Smuzhiyun 	if (ret) {
383*4882a593Smuzhiyun 		printf("Read 'interrupts' failed, ret=%d\n", ret);
384*4882a593Smuzhiyun 		return ret;
385*4882a593Smuzhiyun 	}
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	rk8xx->irq = phandle_gpio_to_irq(phandle, interrupt);
388*4882a593Smuzhiyun 	if (rk8xx->irq < 0) {
389*4882a593Smuzhiyun 		printf("Failed to request rk8xx irq, ret=%d\n", rk8xx->irq);
390*4882a593Smuzhiyun 		return rk8xx->irq;
391*4882a593Smuzhiyun 	}
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun 	val = dev_read_u32_default(dev, "long-press-off-time-sec", 0);
394*4882a593Smuzhiyun 	if (val <= 6)
395*4882a593Smuzhiyun 		rk8xx->lp_off_time = RK8XX_LP_TIME_6S;
396*4882a593Smuzhiyun 	else if (val <= 8)
397*4882a593Smuzhiyun 		rk8xx->lp_off_time = RK8XX_LP_TIME_8S;
398*4882a593Smuzhiyun 	else if (val <= 10)
399*4882a593Smuzhiyun 		rk8xx->lp_off_time = RK8XX_LP_TIME_10S;
400*4882a593Smuzhiyun 	else
401*4882a593Smuzhiyun 		rk8xx->lp_off_time = RK8XX_LP_TIME_12S;
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 	val = dev_read_u32_default(dev, "long-press-restart", 0);
404*4882a593Smuzhiyun 	if (val)
405*4882a593Smuzhiyun 		rk8xx->lp_action = RK8XX_LP_RESTART;
406*4882a593Smuzhiyun 	else
407*4882a593Smuzhiyun 		rk8xx->lp_action = RK8XX_LP_OFF;
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 	val = dev_read_u32_default(dev, "not-save-power-en", 0);
410*4882a593Smuzhiyun 	rk8xx->not_save_power_en = val;
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun 	val = dev_read_bool(dev, "vsys-off-shutdown");
413*4882a593Smuzhiyun 	rk8xx->sys_can_sd = val;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 	return 0;
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun 
rk8xx_irq_chip_init(struct udevice * dev)418*4882a593Smuzhiyun static int rk8xx_irq_chip_init(struct udevice *dev)
419*4882a593Smuzhiyun {
420*4882a593Smuzhiyun 	struct rk8xx_priv *priv = dev_get_priv(dev);
421*4882a593Smuzhiyun 	struct virq_chip *irq_chip = NULL;
422*4882a593Smuzhiyun 	__maybe_unused int irq_plugout = 1;
423*4882a593Smuzhiyun 	int ret;
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	switch (priv->variant) {
426*4882a593Smuzhiyun 	case RK808_ID:
427*4882a593Smuzhiyun 		irq_chip = &rk808_irq_chip;
428*4882a593Smuzhiyun 		break;
429*4882a593Smuzhiyun 	case RK805_ID:
430*4882a593Smuzhiyun 		irq_chip = &rk805_irq_chip;
431*4882a593Smuzhiyun 		irq_plugout = 0;
432*4882a593Smuzhiyun 		break;
433*4882a593Smuzhiyun 	case RK816_ID:
434*4882a593Smuzhiyun 		irq_chip = &rk816_irq_chip;
435*4882a593Smuzhiyun 		break;
436*4882a593Smuzhiyun 	case RK818_ID:
437*4882a593Smuzhiyun 		irq_chip = &rk818_irq_chip;
438*4882a593Smuzhiyun 		break;
439*4882a593Smuzhiyun 	case RK809_ID:
440*4882a593Smuzhiyun 	case RK817_ID:
441*4882a593Smuzhiyun 		irq_chip = &rk817_irq_chip;
442*4882a593Smuzhiyun 		break;
443*4882a593Smuzhiyun 	default:
444*4882a593Smuzhiyun 		return -EINVAL;
445*4882a593Smuzhiyun 	}
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	if (irq_chip) {
448*4882a593Smuzhiyun 		ret = virq_add_chip(dev, irq_chip, priv->irq);
449*4882a593Smuzhiyun 		if (ret) {
450*4882a593Smuzhiyun 			printf("Failed to add irqchip(irq=%d), ret=%d\n",
451*4882a593Smuzhiyun 			       priv->irq, ret);
452*4882a593Smuzhiyun 			return ret;
453*4882a593Smuzhiyun 		}
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 		priv->irq_chip = irq_chip;
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun #ifdef CONFIG_DM_CHARGE_DISPLAY
458*4882a593Smuzhiyun 		int irq;
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 		if (irq_plugout) {
461*4882a593Smuzhiyun 			irq = virq_to_irq(irq_chip, RK8XX_IRQ_PLUG_OUT);
462*4882a593Smuzhiyun 			if (irq < 0) {
463*4882a593Smuzhiyun 				printf("Failed to register plugout irq, ret=%d\n", irq);
464*4882a593Smuzhiyun 				return irq;
465*4882a593Smuzhiyun 			}
466*4882a593Smuzhiyun 			irq_install_handler(irq, rk8xx_plug_out_handler, dev);
467*4882a593Smuzhiyun 			irq_handler_enable_suspend_only(irq);
468*4882a593Smuzhiyun 		}
469*4882a593Smuzhiyun #endif
470*4882a593Smuzhiyun 	}
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun 	return 0;
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun #else
rk8xx_ofdata_to_platdata(struct udevice * dev)475*4882a593Smuzhiyun static inline int rk8xx_ofdata_to_platdata(struct udevice *dev) { return 0; }
rk8xx_irq_chip_init(struct udevice * dev)476*4882a593Smuzhiyun static inline int rk8xx_irq_chip_init(struct udevice *dev) { return 0; }
477*4882a593Smuzhiyun #endif
478*4882a593Smuzhiyun 
rk8xx_probe(struct udevice * dev)479*4882a593Smuzhiyun static int rk8xx_probe(struct udevice *dev)
480*4882a593Smuzhiyun {
481*4882a593Smuzhiyun 	struct rk8xx_priv *priv = dev_get_priv(dev);
482*4882a593Smuzhiyun 	struct reg_data *init_current = NULL;
483*4882a593Smuzhiyun 	struct reg_data *init_data = NULL;
484*4882a593Smuzhiyun 	int init_current_num = 0;
485*4882a593Smuzhiyun 	int init_data_num = 0;
486*4882a593Smuzhiyun 	int ret = 0, i, show_variant;
487*4882a593Smuzhiyun 	uint8_t msb, lsb, id_msb, id_lsb;
488*4882a593Smuzhiyun 	uint8_t on_source = 0, off_source = 0;
489*4882a593Smuzhiyun 	uint8_t pwron_key = 0, lp_off_msk = 0, lp_act_msk = 0;
490*4882a593Smuzhiyun 	uint8_t power_en0, power_en1, power_en2, power_en3;
491*4882a593Smuzhiyun 	uint8_t on, off;
492*4882a593Smuzhiyun 	uint8_t value;
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	/* read Chip variant */
495*4882a593Smuzhiyun 	if (device_is_compatible(dev, "rockchip,rk817") ||
496*4882a593Smuzhiyun 	    device_is_compatible(dev, "rockchip,rk809")) {
497*4882a593Smuzhiyun 		id_msb = RK817_ID_MSB;
498*4882a593Smuzhiyun 		id_lsb = RK817_ID_LSB;
499*4882a593Smuzhiyun 	} else {
500*4882a593Smuzhiyun 		id_msb = ID_MSB;
501*4882a593Smuzhiyun 		id_lsb = ID_LSB;
502*4882a593Smuzhiyun 	}
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun 	ret = rk8xx_read(dev, id_msb, &msb, 1);
505*4882a593Smuzhiyun 	if (ret)
506*4882a593Smuzhiyun 		return ret;
507*4882a593Smuzhiyun 	ret = rk8xx_read(dev, id_lsb, &lsb, 1);
508*4882a593Smuzhiyun 	if (ret)
509*4882a593Smuzhiyun 		return ret;
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun 	priv->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK;
512*4882a593Smuzhiyun 	show_variant = priv->variant;
513*4882a593Smuzhiyun 	switch (priv->variant) {
514*4882a593Smuzhiyun 	case RK808_ID:
515*4882a593Smuzhiyun 		show_variant = 0x808;	/* RK808 hardware ID is 0 */
516*4882a593Smuzhiyun 		pwron_key = RK8XX_DEVCTRL_REG;
517*4882a593Smuzhiyun 		lp_off_msk = RK8XX_LP_OFF_MSK;
518*4882a593Smuzhiyun 		break;
519*4882a593Smuzhiyun 	case RK805_ID:
520*4882a593Smuzhiyun 	case RK816_ID:
521*4882a593Smuzhiyun 		on_source = RK8XX_ON_SOURCE;
522*4882a593Smuzhiyun 		off_source = RK8XX_OFF_SOURCE;
523*4882a593Smuzhiyun 		pwron_key = RK8XX_DEVCTRL_REG;
524*4882a593Smuzhiyun 		lp_off_msk = RK8XX_LP_OFF_MSK;
525*4882a593Smuzhiyun 		lp_act_msk = RK8XX_LP_ACTION_MSK;
526*4882a593Smuzhiyun 		break;
527*4882a593Smuzhiyun 	case RK818_ID:
528*4882a593Smuzhiyun 		on_source = RK8XX_ON_SOURCE;
529*4882a593Smuzhiyun 		off_source = RK8XX_OFF_SOURCE;
530*4882a593Smuzhiyun 		pwron_key = RK8XX_DEVCTRL_REG;
531*4882a593Smuzhiyun 		lp_off_msk = RK8XX_LP_OFF_MSK;
532*4882a593Smuzhiyun 		lp_act_msk = RK8XX_LP_ACTION_MSK;
533*4882a593Smuzhiyun 		/* set current if no fuel gauge */
534*4882a593Smuzhiyun 		if (!ofnode_valid(dev_read_subnode(dev, "battery"))) {
535*4882a593Smuzhiyun 			init_current = rk818_init_current;
536*4882a593Smuzhiyun 			init_current_num = ARRAY_SIZE(rk818_init_current);
537*4882a593Smuzhiyun 		}
538*4882a593Smuzhiyun 		break;
539*4882a593Smuzhiyun 	case RK809_ID:
540*4882a593Smuzhiyun 	case RK817_ID:
541*4882a593Smuzhiyun 		if (device_is_compatible(dev, "rockchip,rk809") && (priv->variant != RK809_ID)) {
542*4882a593Smuzhiyun 			dev_err(dev, "the dts is RK809, the hardware is RK817\n");
543*4882a593Smuzhiyun 			run_command("download", 0);
544*4882a593Smuzhiyun 		}
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun 		if (device_is_compatible(dev, "rockchip,rk817") && (priv->variant != RK817_ID)) {
547*4882a593Smuzhiyun 			dev_err(dev, "the dts is RK817, the hardware is RK809\n");
548*4882a593Smuzhiyun 			run_command("download", 0);
549*4882a593Smuzhiyun 		}
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 		on_source = RK817_ON_SOURCE;
552*4882a593Smuzhiyun 		off_source = RK817_OFF_SOURCE;
553*4882a593Smuzhiyun 		pwron_key = RK817_PWRON_KEY;
554*4882a593Smuzhiyun 		lp_off_msk = RK8XX_LP_OFF_MSK;
555*4882a593Smuzhiyun 		lp_act_msk = RK8XX_LP_ACTION_MSK;
556*4882a593Smuzhiyun 		init_data = rk817_init_reg;
557*4882a593Smuzhiyun 		init_data_num = ARRAY_SIZE(rk817_init_reg);
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun 		/* whether the system voltage can be shutdown in PWR_off mode */
560*4882a593Smuzhiyun 		if (priv->sys_can_sd) {
561*4882a593Smuzhiyun 			ret = rk8xx_read(dev, RK817_PMIC_CHRG_TERM, &value, 1);
562*4882a593Smuzhiyun 			if (ret)
563*4882a593Smuzhiyun 				return ret;
564*4882a593Smuzhiyun 			value |= 0x80;
565*4882a593Smuzhiyun 			ret = rk8xx_write(dev, RK817_PMIC_CHRG_TERM, &value, 1);
566*4882a593Smuzhiyun 			if (ret)
567*4882a593Smuzhiyun 				return ret;
568*4882a593Smuzhiyun 		} else {
569*4882a593Smuzhiyun 			ret = rk8xx_read(dev, RK817_PMIC_CHRG_TERM, &value, 1);
570*4882a593Smuzhiyun 			if (ret)
571*4882a593Smuzhiyun 				return ret;
572*4882a593Smuzhiyun 			value &= 0x7f;
573*4882a593Smuzhiyun 			ret = rk8xx_write(dev, RK817_PMIC_CHRG_TERM, &value, 1);
574*4882a593Smuzhiyun 			if (ret)
575*4882a593Smuzhiyun 				return ret;
576*4882a593Smuzhiyun 		}
577*4882a593Smuzhiyun 
578*4882a593Smuzhiyun 		/* judge whether save the PMIC_POWER_EN register */
579*4882a593Smuzhiyun 		if (!priv->not_save_power_en) {
580*4882a593Smuzhiyun 			ret = rk8xx_read(dev, RK817_POWER_EN0, &power_en0, 1);
581*4882a593Smuzhiyun 			if (ret)
582*4882a593Smuzhiyun 				return ret;
583*4882a593Smuzhiyun 			ret = rk8xx_read(dev, RK817_POWER_EN1, &power_en1, 1);
584*4882a593Smuzhiyun 			if (ret)
585*4882a593Smuzhiyun 				return ret;
586*4882a593Smuzhiyun 			ret = rk8xx_read(dev, RK817_POWER_EN2, &power_en2, 1);
587*4882a593Smuzhiyun 			if (ret)
588*4882a593Smuzhiyun 				return ret;
589*4882a593Smuzhiyun 			ret = rk8xx_read(dev, RK817_POWER_EN3, &power_en3, 1);
590*4882a593Smuzhiyun 			if (ret)
591*4882a593Smuzhiyun 				return ret;
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun 			value = (power_en0 & 0x0f) | ((power_en1 & 0x0f) << 4);
594*4882a593Smuzhiyun 			rk8xx_write(dev, RK817_POWER_EN_SAVE0, &value, 1);
595*4882a593Smuzhiyun 			value = (power_en2 & 0x0f) | ((power_en3 & 0x0f) << 4);
596*4882a593Smuzhiyun 			rk8xx_write(dev, RK817_POWER_EN_SAVE1, &value, 1);
597*4882a593Smuzhiyun 		}
598*4882a593Smuzhiyun 		break;
599*4882a593Smuzhiyun 	default:
600*4882a593Smuzhiyun 		printf("Unknown PMIC: RK%x!!\n", priv->variant);
601*4882a593Smuzhiyun 		return -EINVAL;
602*4882a593Smuzhiyun 	}
603*4882a593Smuzhiyun 
604*4882a593Smuzhiyun 	/* common init */
605*4882a593Smuzhiyun 	for (i = 0; i < init_data_num; i++) {
606*4882a593Smuzhiyun 		ret = pmic_clrsetbits(dev,
607*4882a593Smuzhiyun 				      init_data[i].reg,
608*4882a593Smuzhiyun 				      init_data[i].mask,
609*4882a593Smuzhiyun 				      init_data[i].val);
610*4882a593Smuzhiyun 		if (ret < 0) {
611*4882a593Smuzhiyun 			printf("%s: i2c set reg 0x%x failed, ret=%d\n",
612*4882a593Smuzhiyun 			       __func__, init_data[i].reg, ret);
613*4882a593Smuzhiyun 		}
614*4882a593Smuzhiyun 	}
615*4882a593Smuzhiyun 
616*4882a593Smuzhiyun 	/* current init */
617*4882a593Smuzhiyun 	for (i = 0; i < init_current_num; i++) {
618*4882a593Smuzhiyun 		ret = pmic_clrsetbits(dev,
619*4882a593Smuzhiyun 				      init_current[i].reg,
620*4882a593Smuzhiyun 				      init_current[i].mask,
621*4882a593Smuzhiyun 				      init_current[i].val);
622*4882a593Smuzhiyun 		if (ret < 0) {
623*4882a593Smuzhiyun 			printf("%s: i2c set reg 0x%x failed, ret=%d\n",
624*4882a593Smuzhiyun 			       __func__, init_current[i].reg, ret);
625*4882a593Smuzhiyun 		}
626*4882a593Smuzhiyun 	}
627*4882a593Smuzhiyun 
628*4882a593Smuzhiyun 	printf("PMIC:  RK%x ", show_variant);
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun 	if (on_source && off_source) {
631*4882a593Smuzhiyun 		rk8xx_read(dev, on_source, &on, 1);
632*4882a593Smuzhiyun 		rk8xx_read(dev, off_source, &off, 1);
633*4882a593Smuzhiyun 		printf("(on=0x%02x, off=0x%02x)", on, off);
634*4882a593Smuzhiyun 	}
635*4882a593Smuzhiyun 	printf("\n");
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun 	if (pwron_key) {
638*4882a593Smuzhiyun 		ret = rk8xx_read(dev, pwron_key, &value, 1);
639*4882a593Smuzhiyun 		if (ret)
640*4882a593Smuzhiyun 			return ret;
641*4882a593Smuzhiyun 		value &= ~(lp_off_msk | lp_act_msk);
642*4882a593Smuzhiyun 		if (lp_off_msk)
643*4882a593Smuzhiyun 			value |= priv->lp_off_time;
644*4882a593Smuzhiyun 		if (lp_act_msk)
645*4882a593Smuzhiyun 			value |= priv->lp_action;
646*4882a593Smuzhiyun 		rk8xx_write(dev, pwron_key, &value, 1);
647*4882a593Smuzhiyun 	}
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun 	ret = rk8xx_irq_chip_init(dev);
650*4882a593Smuzhiyun 	if (ret) {
651*4882a593Smuzhiyun 		printf("IRQ chip initial failed\n");
652*4882a593Smuzhiyun 		return ret;
653*4882a593Smuzhiyun 	}
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun 	return 0;
656*4882a593Smuzhiyun }
657*4882a593Smuzhiyun 
658*4882a593Smuzhiyun static struct dm_pmic_ops rk8xx_ops = {
659*4882a593Smuzhiyun 	.reg_count = rk8xx_reg_count,
660*4882a593Smuzhiyun 	.read = rk8xx_read,
661*4882a593Smuzhiyun 	.write = rk8xx_write,
662*4882a593Smuzhiyun 	.suspend = rk8xx_suspend,
663*4882a593Smuzhiyun 	.resume = rk8xx_resume,
664*4882a593Smuzhiyun 	.shutdown = rk8xx_shutdown,
665*4882a593Smuzhiyun };
666*4882a593Smuzhiyun 
667*4882a593Smuzhiyun static const struct udevice_id rk8xx_ids[] = {
668*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk805" },
669*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk808" },
670*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk809" },
671*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk816" },
672*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk817" },
673*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk818" },
674*4882a593Smuzhiyun 	{ }
675*4882a593Smuzhiyun };
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun U_BOOT_DRIVER(pmic_rk8xx) = {
678*4882a593Smuzhiyun 	.name = "rk8xx pmic",
679*4882a593Smuzhiyun 	.id = UCLASS_PMIC,
680*4882a593Smuzhiyun 	.of_match = rk8xx_ids,
681*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(PMIC_CHILDREN)
682*4882a593Smuzhiyun 	.bind = rk8xx_bind,
683*4882a593Smuzhiyun #endif
684*4882a593Smuzhiyun 	.ofdata_to_platdata = rk8xx_ofdata_to_platdata,
685*4882a593Smuzhiyun 	.priv_auto_alloc_size = sizeof(struct rk8xx_priv),
686*4882a593Smuzhiyun 	.probe = rk8xx_probe,
687*4882a593Smuzhiyun 	.ops = &rk8xx_ops,
688*4882a593Smuzhiyun };
689