xref: /rk3399_rockchip-uboot/drivers/power/pmic/rk8xx.c (revision 063fcc919b3240627577bda8d106e539c8b167d6)
1453c5a92SJacob Chen /*
2453c5a92SJacob Chen  * Copyright (C) 2015 Google, Inc
3453c5a92SJacob Chen  * Written by Simon Glass <sjg@chromium.org>
4453c5a92SJacob Chen  *
5453c5a92SJacob Chen  * SPDX-License-Identifier:	GPL-2.0+
6453c5a92SJacob Chen  */
7453c5a92SJacob Chen 
8453c5a92SJacob Chen #include <common.h>
9453c5a92SJacob Chen #include <dm.h>
10453c5a92SJacob Chen #include <errno.h>
11ded32713SJoseph Chen #include <irq-generic.h>
12453c5a92SJacob Chen #include <power/rk8xx_pmic.h>
13453c5a92SJacob Chen #include <power/pmic.h>
14453c5a92SJacob Chen 
15453c5a92SJacob Chen DECLARE_GLOBAL_DATA_PTR;
16453c5a92SJacob Chen 
177cef7918SJoseph Chen #if CONFIG_IS_ENABLED(IRQ)
18ded32713SJoseph Chen /* RK805 */
19ded32713SJoseph Chen static const struct virq_reg rk805_irqs[] = {
20ded32713SJoseph Chen 	[RK8XX_IRQ_PWRON_FALL] = {
21ded32713SJoseph Chen 		.mask = RK805_IRQ_PWRON_FALL_MSK,
22ded32713SJoseph Chen 		.reg_offset = 0,
23ded32713SJoseph Chen 	},
24ded32713SJoseph Chen 	[RK8XX_IRQ_PWRON_RISE] = {
25ded32713SJoseph Chen 		.mask = RK805_IRQ_PWRON_RISE_MSK,
26ded32713SJoseph Chen 		.reg_offset = 0,
27ded32713SJoseph Chen 	},
28*063fcc91SShengfei Xu 	[RK8XX_IRQ_RTC_ALARM] = {
29*063fcc91SShengfei Xu 		.mask = RK805_IRQ_RTC_ALARM_MSK,
30*063fcc91SShengfei Xu 		.reg_offset = 0,
31*063fcc91SShengfei Xu 	},
32ded32713SJoseph Chen };
33ded32713SJoseph Chen 
34ded32713SJoseph Chen static struct virq_chip rk805_irq_chip = {
35ded32713SJoseph Chen 	.status_base		= RK805_INT_STS_REG,
36ded32713SJoseph Chen 	.mask_base		= RK805_INT_MSK_REG,
37ded32713SJoseph Chen 	.num_regs		= 1,
3806c1e6d7SJoseph Chen 	.read			= pmic_reg_read,
3906c1e6d7SJoseph Chen 	.write			= pmic_reg_write,
40ded32713SJoseph Chen 	.irqs			= rk805_irqs,
41ded32713SJoseph Chen 	.num_irqs		= ARRAY_SIZE(rk805_irqs),
42ded32713SJoseph Chen };
43ded32713SJoseph Chen 
44ef9c5d10Sshengfei Xu /* RK806 */
45ef9c5d10Sshengfei Xu static const struct virq_reg rk806_irqs[] = {
46ef9c5d10Sshengfei Xu 	[RK8XX_IRQ_PWRON_FALL] = {
47ef9c5d10Sshengfei Xu 		.mask = RK806_IRQ_PWRON_FALL_MSK,
48ef9c5d10Sshengfei Xu 		.reg_offset = 0,
49ef9c5d10Sshengfei Xu 	},
50ef9c5d10Sshengfei Xu 	[RK8XX_IRQ_PWRON_RISE] = {
51ef9c5d10Sshengfei Xu 		.mask = RK806_IRQ_PWRON_RISE_MSK,
52ef9c5d10Sshengfei Xu 		.reg_offset = 0,
53ef9c5d10Sshengfei Xu 	},
54ef9c5d10Sshengfei Xu };
55ef9c5d10Sshengfei Xu 
56ef9c5d10Sshengfei Xu static struct virq_chip rk806_irq_chip = {
57ef9c5d10Sshengfei Xu 	.status_base		= RK806_INT_STS0,
58ef9c5d10Sshengfei Xu 	.mask_base		= RK806_INT_MSK0,
59ece79c0fSshengfei Xu 	.irq_reg_stride		= 2,
60ece79c0fSshengfei Xu 	.num_regs		= 2,
61ef9c5d10Sshengfei Xu 	.read			= pmic_reg_read,
62ef9c5d10Sshengfei Xu 	.write			= pmic_reg_write,
63ef9c5d10Sshengfei Xu 	.irqs			= rk806_irqs,
64ef9c5d10Sshengfei Xu 	.num_irqs		= ARRAY_SIZE(rk806_irqs),
65ef9c5d10Sshengfei Xu };
66ef9c5d10Sshengfei Xu 
67ded32713SJoseph Chen /* RK808 */
68ded32713SJoseph Chen static const struct virq_reg rk808_irqs[] = {
69ded32713SJoseph Chen 	[RK8XX_IRQ_PLUG_OUT] = {
70ded32713SJoseph Chen 		.mask = RK808_IRQ_PLUG_OUT_MSK,
71ded32713SJoseph Chen 		.reg_offset = 1,
72ded32713SJoseph Chen 	},
73*063fcc91SShengfei Xu 	[RK8XX_IRQ_RTC_ALARM] = {
74*063fcc91SShengfei Xu 		.mask = RK808_IRQ_RTC_ALARM_MSK,
75*063fcc91SShengfei Xu 		.reg_offset = 0,
76*063fcc91SShengfei Xu 	},
77ded32713SJoseph Chen };
78ded32713SJoseph Chen 
79ded32713SJoseph Chen static struct virq_chip rk808_irq_chip = {
80ded32713SJoseph Chen 	.status_base		= RK808_INT_STS_REG1,
81ded32713SJoseph Chen 	.mask_base		= RK808_INT_MSK_REG1,
82ded32713SJoseph Chen 	.irq_reg_stride		= 2,
83ded32713SJoseph Chen 	.num_regs		= 2,
8406c1e6d7SJoseph Chen 	.read			= pmic_reg_read,
8506c1e6d7SJoseph Chen 	.write			= pmic_reg_write,
86ded32713SJoseph Chen 	.irqs			= rk808_irqs,
87ded32713SJoseph Chen 	.num_irqs		= ARRAY_SIZE(rk808_irqs),
88ded32713SJoseph Chen };
89ded32713SJoseph Chen 
90ded32713SJoseph Chen /* RK816 */
91ded32713SJoseph Chen static const struct virq_reg rk816_irqs[] = {
92ded32713SJoseph Chen 	[RK8XX_IRQ_PWRON_FALL] = {
93ded32713SJoseph Chen 		.mask = RK816_IRQ_PWRON_FALL_MSK,
94ded32713SJoseph Chen 		.reg_offset = 0,
95ded32713SJoseph Chen 	},
96ded32713SJoseph Chen 	[RK8XX_IRQ_PWRON_RISE] = {
97ded32713SJoseph Chen 		.mask = RK816_IRQ_PWRON_RISE_MSK,
98ded32713SJoseph Chen 		.reg_offset = 0,
99ded32713SJoseph Chen 	},
100ded32713SJoseph Chen 	[RK8XX_IRQ_PLUG_OUT] = {
101ded32713SJoseph Chen 		.mask = RK816_IRQ_PLUG_OUT_MSK,
102ded32713SJoseph Chen 		.reg_offset = 2,
103ded32713SJoseph Chen 	},
104ded32713SJoseph Chen 	[RK8XX_IRQ_CHG_OK] = {
105ded32713SJoseph Chen 		.mask = RK816_IRQ_CHR_OK_MSK,
106ded32713SJoseph Chen 		.reg_offset = 2,
107ded32713SJoseph Chen 	},
108*063fcc91SShengfei Xu 	[RK8XX_IRQ_RTC_ALARM] = {
109*063fcc91SShengfei Xu 		.mask = RK816_IRQ_RTC_ALARM_MSK,
110*063fcc91SShengfei Xu 		.reg_offset = 1,
111*063fcc91SShengfei Xu 	},
112ded32713SJoseph Chen };
113ded32713SJoseph Chen 
114ded32713SJoseph Chen static struct virq_chip rk816_irq_chip = {
115ded32713SJoseph Chen 	.status_base		= RK816_INT_STS_REG1,
116ded32713SJoseph Chen 	.mask_base		= RK816_INT_MSK_REG1,
117ded32713SJoseph Chen 	.irq_unalign_reg_idx	= 1,	/* idx <= 1, stride = 3 */
118ded32713SJoseph Chen 	.irq_unalign_reg_stride	= 3,
119ded32713SJoseph Chen 	.irq_reg_stride		= 2,	/* idx > 1, stride = 2 */
120ded32713SJoseph Chen 	.num_regs		= 3,
12106c1e6d7SJoseph Chen 	.read			= pmic_reg_read,
12206c1e6d7SJoseph Chen 	.write			= pmic_reg_write,
123ded32713SJoseph Chen 	.irqs			= rk816_irqs,
124ded32713SJoseph Chen 	.num_irqs		= ARRAY_SIZE(rk816_irqs),
125ded32713SJoseph Chen };
126ded32713SJoseph Chen 
127ded32713SJoseph Chen /* RK818 */
128ded32713SJoseph Chen static const struct virq_reg rk818_irqs[] = {
129ded32713SJoseph Chen 	[RK8XX_IRQ_PLUG_OUT] = {
130ded32713SJoseph Chen 		.mask = RK818_IRQ_PLUG_OUT_MSK,
131ded32713SJoseph Chen 		.reg_offset = 1,
132ded32713SJoseph Chen 	},
133ded32713SJoseph Chen 	[RK8XX_IRQ_CHG_OK] = {
134ded32713SJoseph Chen 		.mask = RK818_IRQ_CHR_OK_MSK,
135ded32713SJoseph Chen 		.reg_offset = 1,
136ded32713SJoseph Chen 	},
137*063fcc91SShengfei Xu 	[RK8XX_IRQ_RTC_ALARM] = {
138*063fcc91SShengfei Xu 		.mask = RK818_IRQ_RTC_ALARM_MSK,
139*063fcc91SShengfei Xu 		.reg_offset = 0,
140*063fcc91SShengfei Xu 	},
141ded32713SJoseph Chen };
142ded32713SJoseph Chen 
143ded32713SJoseph Chen static struct virq_chip rk818_irq_chip = {
144ded32713SJoseph Chen 	.status_base		= RK818_INT_STS_REG1,
145ded32713SJoseph Chen 	.mask_base		= RK818_INT_MSK_REG1,
146ded32713SJoseph Chen 	.irq_reg_stride		= 2,
147ded32713SJoseph Chen 	.num_regs		= 2,
14806c1e6d7SJoseph Chen 	.read			= pmic_reg_read,
14906c1e6d7SJoseph Chen 	.write			= pmic_reg_write,
150ded32713SJoseph Chen 	.irqs			= rk818_irqs,
151ded32713SJoseph Chen 	.num_irqs		= ARRAY_SIZE(rk818_irqs),
152ded32713SJoseph Chen };
153ded32713SJoseph Chen 
154ded32713SJoseph Chen /* RK817/RK809 */
155ded32713SJoseph Chen static const struct virq_reg rk817_irqs[] = {
156ded32713SJoseph Chen 	[RK8XX_IRQ_PWRON_FALL] = {
157ded32713SJoseph Chen 		.mask = RK817_IRQ_PWRON_FALL_MSK,
158ded32713SJoseph Chen 		.reg_offset = 0,
159ded32713SJoseph Chen 	},
160ded32713SJoseph Chen 	[RK8XX_IRQ_PWRON_RISE] = {
161ded32713SJoseph Chen 		.mask = RK817_IRQ_PWRON_RISE_MSK,
162ded32713SJoseph Chen 		.reg_offset = 0,
163ded32713SJoseph Chen 	},
164ded32713SJoseph Chen 	[RK8XX_IRQ_PLUG_OUT] = {
165ded32713SJoseph Chen 		.mask = RK817_IRQ_PLUG_OUT_MSK,
166ded32713SJoseph Chen 		.reg_offset = 1,
167ded32713SJoseph Chen 	},
168ded32713SJoseph Chen 	[RK8XX_IRQ_PLUG_IN] = {
169ded32713SJoseph Chen 		.mask = RK817_IRQ_PLUG_IN_MSK,
170ded32713SJoseph Chen 		.reg_offset = 1,
171ded32713SJoseph Chen 	},
172*063fcc91SShengfei Xu 	[RK8XX_IRQ_RTC_ALARM] = {
173*063fcc91SShengfei Xu 		.mask = RK817_IRQ_RTC_ALARM_MSK,
174*063fcc91SShengfei Xu 		.reg_offset = 0,
175*063fcc91SShengfei Xu 	},
176ded32713SJoseph Chen };
177ded32713SJoseph Chen 
178ded32713SJoseph Chen static struct virq_chip rk817_irq_chip = {
179ded32713SJoseph Chen 	.status_base		= RK817_INT_STS_REG0,
180ded32713SJoseph Chen 	.mask_base		= RK817_INT_MSK_REG0,
181ded32713SJoseph Chen 	.irq_reg_stride		= 2,
182ded32713SJoseph Chen 	.num_regs		= 3,
18306c1e6d7SJoseph Chen 	.read			= pmic_reg_read,
18406c1e6d7SJoseph Chen 	.write			= pmic_reg_write,
185ded32713SJoseph Chen 	.irqs			= rk817_irqs,
186ded32713SJoseph Chen 	.num_irqs		= ARRAY_SIZE(rk817_irqs),
187ded32713SJoseph Chen };
188ded32713SJoseph Chen #endif
189ded32713SJoseph Chen 
190ba76dc00SShengfei Xu static struct reg_data rk817_init_reg[] = {
191ba76dc00SShengfei Xu /* enable the under-voltage protection,
192ba76dc00SShengfei Xu  * the under-voltage protection will shutdown the LDO3 and reset the PMIC
193ba76dc00SShengfei Xu  */
1942bf9e6abSShengfei Xu 	{ RK817_BUCK4_CMIN, 0x6e, 0x6e},
19508f6c114Sshengfei Xu 	{ RK817_PMIC_SYS_CFG1, 0x20, 0x70},
196b978e52cSJoseph Chen 	/* Set pmic_sleep as none function */
197b978e52cSJoseph Chen 	{ RK817_PMIC_SYS_CFG3, 0x00, 0x18 },
198ef3bd067Sshengfei Xu 	/* GATE pin function: gate function */
199ef3bd067Sshengfei Xu 	{ RK817_GPIO_INT_CFG, 0x00, 0x20 },
200be8db310SJoseph Chen #if CONFIG_IS_ENABLED(IRQ)
2011c223666SJoseph Chen 	/* Set pmic_int active low */
2021c223666SJoseph Chen 	{ RK817_GPIO_INT_CFG,  0x00, 0x02 },
2031c223666SJoseph Chen #endif
204ba76dc00SShengfei Xu };
2051c223666SJoseph Chen 
20643e3c846SJoseph Chen static struct reg_data rk818_init_current[] = {
20743e3c846SJoseph Chen 	{ REG_USB_CTRL, 0x07, 0x0f}, /* 2A */
20843e3c846SJoseph Chen };
20943e3c846SJoseph Chen 
210608a8de8SJoseph Chen /*
211608a8de8SJoseph Chen  * Order WARNING: Must put "LDO" after the "NLDO" and "PLDO" !
212608a8de8SJoseph Chen  *
213608a8de8SJoseph Chen  * See: pmic_bind_children()
214608a8de8SJoseph Chen  *	    if (!strstr(node_name, info->prefix)) {
215608a8de8SJoseph Chen  *		    ......
216608a8de8SJoseph Chen  *	    }
217608a8de8SJoseph Chen  *
218608a8de8SJoseph Chen  * Without this order, the prefix "LDO" will be matched if a regulator
219608a8de8SJoseph Chen  * dts node name contains "NLDO" or "PLDO".
220608a8de8SJoseph Chen  */
221453c5a92SJacob Chen static const struct pmic_child_info pmic_children_info[] = {
22203af66d3SJoseph Chen 	{ .prefix = "DCDC", .driver = "rk8xx_buck"},
223ef9c5d10Sshengfei Xu 	{ .prefix = "NLDO", .driver = "rk8xx_ldo"},
224ef9c5d10Sshengfei Xu 	{ .prefix = "PLDO", .driver = "rk8xx_pldo"},
225608a8de8SJoseph Chen 	{ .prefix = "LDO", .driver = "rk8xx_ldo"},
22603af66d3SJoseph Chen 	{ .prefix = "SWITCH", .driver = "rk8xx_switch"},
227c8147680SShengfei Xu 	{ .prefix = "BOOST", .driver = "rk8xx_boost"},
228c8147680SShengfei Xu 
229453c5a92SJacob Chen 	{ },
230453c5a92SJacob Chen };
231453c5a92SJacob Chen 
2326d747531SJoseph Chen static const struct pmic_child_info power_key_info[] = {
2336d747531SJoseph Chen 	{ .prefix = "pwrkey", .driver = "rk8xx_pwrkey"},
2346d747531SJoseph Chen 	{ },
2356d747531SJoseph Chen };
2366d747531SJoseph Chen 
23747bc0dadSElaine Zhang static const struct pmic_child_info rtc_info[] = {
23847bc0dadSElaine Zhang 	{ .prefix = "rtc", .driver = "rk8xx_rtc"},
23947bc0dadSElaine Zhang 	{ },
24047bc0dadSElaine Zhang };
24147bc0dadSElaine Zhang 
2426a367335SJoseph Chen static const struct pmic_child_info fuel_gauge_info[] = {
243ed71c655SJoseph Chen 	{ .addr = "1c", .prefix = "battery", .driver = "rk818_fg"},
244ed71c655SJoseph Chen 	{ .addr = "20", .prefix = "battery", .driver = "rk817_fg"},
245ed71c655SJoseph Chen 	{ .addr = "1a", .prefix = "battery", .driver = "rk816_fg"},
2466a367335SJoseph Chen 	{ },
2476a367335SJoseph Chen };
2486a367335SJoseph Chen 
2497a5efcbdSSugar Zhang static const struct pmic_child_info rk817_codec_info[] = {
2507a5efcbdSSugar Zhang 	{ .prefix = "codec", .driver = "rk817_codec"},
2517a5efcbdSSugar Zhang 	{ },
2527a5efcbdSSugar Zhang };
2537a5efcbdSSugar Zhang 
rk8xx_reg_count(struct udevice * dev)254453c5a92SJacob Chen static int rk8xx_reg_count(struct udevice *dev)
255453c5a92SJacob Chen {
2563ec172baSJoseph Chen 	struct rk8xx_priv *priv = dev_get_priv(dev);
2573ec172baSJoseph Chen 
2583ec172baSJoseph Chen 	switch (priv->variant) {
2593ec172baSJoseph Chen 	case RK809_ID:
2603ec172baSJoseph Chen 	case RK817_ID:
2613ec172baSJoseph Chen 		return RK817_NUM_OF_REGS;
2623ec172baSJoseph Chen 	default:
263453c5a92SJacob Chen 		return RK808_NUM_OF_REGS;
264453c5a92SJacob Chen 	}
2653ec172baSJoseph Chen }
266453c5a92SJacob Chen 
rk8xx_write(struct udevice * dev,uint reg,const uint8_t * buff,int len)267453c5a92SJacob Chen static int rk8xx_write(struct udevice *dev, uint reg, const uint8_t *buff,
268453c5a92SJacob Chen 			  int len)
269453c5a92SJacob Chen {
270453c5a92SJacob Chen 	int ret;
271453c5a92SJacob Chen 
272453c5a92SJacob Chen 	ret = dm_i2c_write(dev, reg, buff, len);
273453c5a92SJacob Chen 	if (ret) {
2745cfdc123SJoseph Chen 		printf("%s: write reg 0x%02x failed, ret=%d\n", __func__, reg, ret);
275453c5a92SJacob Chen 		return ret;
276453c5a92SJacob Chen 	}
277453c5a92SJacob Chen 
278453c5a92SJacob Chen 	return 0;
279453c5a92SJacob Chen }
280453c5a92SJacob Chen 
rk8xx_read(struct udevice * dev,uint reg,uint8_t * buff,int len)281453c5a92SJacob Chen static int rk8xx_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
282453c5a92SJacob Chen {
283453c5a92SJacob Chen 	int ret;
284453c5a92SJacob Chen 
285453c5a92SJacob Chen 	ret = dm_i2c_read(dev, reg, buff, len);
286453c5a92SJacob Chen 	if (ret) {
2875cfdc123SJoseph Chen 		printf("%s: read reg 0x%02x failed, ret=%d\n", __func__, reg, ret);
288453c5a92SJacob Chen 		return ret;
289453c5a92SJacob Chen 	}
290453c5a92SJacob Chen 
291453c5a92SJacob Chen 	return 0;
292453c5a92SJacob Chen }
293453c5a92SJacob Chen 
rk806_shutdown_seq(struct udevice * dev)2941eb4ab17SShengfei Xu static void rk806_shutdown_seq(struct udevice *dev)
2951eb4ab17SShengfei Xu {
2961eb4ab17SShengfei Xu 	struct rk8xx_priv *rk8xx = dev_get_priv(dev);
2971eb4ab17SShengfei Xu 	uint8_t value;
2981eb4ab17SShengfei Xu 	int i;
2991eb4ab17SShengfei Xu 
3001eb4ab17SShengfei Xu 	if (!rk8xx->shutdown_sequence)
3011eb4ab17SShengfei Xu 		return;
3021eb4ab17SShengfei Xu 
3031eb4ab17SShengfei Xu 	for (i = RK806_ID_DCDC1; i <= RK806_ID_DCDC10; i++) {
3041eb4ab17SShengfei Xu 		value = rk8xx->shutdown_sequence[RK806_ID_DCDC1 + i];
3051eb4ab17SShengfei Xu 		rk8xx_write(dev, RK806_SHUTDOWN_SEQ_REG0 + i, &value, 1);
3061eb4ab17SShengfei Xu 	}
3071eb4ab17SShengfei Xu 
3081eb4ab17SShengfei Xu 	for (i = RK806_ID_NLDO1; i <= RK806_ID_NLDO5; i++) {
3091eb4ab17SShengfei Xu 		value = rk8xx->shutdown_sequence[RK806_ID_NLDO1 + i];
3101eb4ab17SShengfei Xu 		rk8xx_write(dev, RK806_SHUTDOWN_SEQ_REG0 + i, &value, 1);
3111eb4ab17SShengfei Xu 	}
3121eb4ab17SShengfei Xu 
3131eb4ab17SShengfei Xu 	rk8xx_read(dev, RK806_SHUTDOWN_SEQ_REG8, &value, 1);
3141eb4ab17SShengfei Xu 	value |= rk8xx->shutdown_sequence[RK806_ID_PLDO1] << 6;
3151eb4ab17SShengfei Xu 	rk8xx_write(dev, RK806_SHUTDOWN_SEQ_REG8, &value, 1);
3161eb4ab17SShengfei Xu 
3171eb4ab17SShengfei Xu 	rk8xx_read(dev, RK806_SHUTDOWN_SEQ_REG11, &value, 1);
3181eb4ab17SShengfei Xu 	value |= rk8xx->shutdown_sequence[RK806_ID_PLDO2] << 6;
3191eb4ab17SShengfei Xu 	rk8xx_write(dev, RK806_SHUTDOWN_SEQ_REG11, &value, 1);
3201eb4ab17SShengfei Xu 
3211eb4ab17SShengfei Xu 	rk8xx_read(dev, RK806_SHUTDOWN_SEQ_REG14, &value, 1);
3221eb4ab17SShengfei Xu 	value |= rk8xx->shutdown_sequence[RK806_ID_PLDO3] << 6;
3231eb4ab17SShengfei Xu 	rk8xx_write(dev, RK806_SHUTDOWN_SEQ_REG14, &value, 1);
3241eb4ab17SShengfei Xu 
3251eb4ab17SShengfei Xu 	rk8xx_read(dev, RK806_SHUTDOWN_SEQ_REG15, &value, 1);
3261eb4ab17SShengfei Xu 	value |= rk8xx->shutdown_sequence[RK806_ID_PLDO4];
3271eb4ab17SShengfei Xu 	rk8xx_write(dev, RK806_SHUTDOWN_SEQ_REG15, &value, 1);
3281eb4ab17SShengfei Xu 
3291eb4ab17SShengfei Xu 	rk8xx_read(dev, RK806_SHUTDOWN_SEQ_REG16, &value, 1);
3301eb4ab17SShengfei Xu 	value |= rk8xx->shutdown_sequence[RK806_ID_PLDO5];
3311eb4ab17SShengfei Xu 	rk8xx_write(dev, RK806_SHUTDOWN_SEQ_REG16, &value, 1);
3321eb4ab17SShengfei Xu 
3331eb4ab17SShengfei Xu 	rk8xx_read(dev, RK806_SHUTDOWN_SEQ_REG5, &value, 1);
3341eb4ab17SShengfei Xu 	value |= rk8xx->shutdown_sequence[RK806_ID_PLDO6] << 6;
3351eb4ab17SShengfei Xu 	rk8xx_write(dev, RK806_SHUTDOWN_SEQ_REG5, &value, 1);
3361eb4ab17SShengfei Xu }
3371eb4ab17SShengfei Xu 
rk806_vb_shutdown_seq(struct udevice * dev)3381eb4ab17SShengfei Xu static void rk806_vb_shutdown_seq(struct udevice *dev)
3391eb4ab17SShengfei Xu {
3401eb4ab17SShengfei Xu 	struct rk8xx_priv *rk8xx = dev_get_priv(dev);
3411eb4ab17SShengfei Xu 	uint8_t value;
3421eb4ab17SShengfei Xu 	int i;
3431eb4ab17SShengfei Xu 
3441eb4ab17SShengfei Xu 	if (!rk8xx->vb_shutdown_sequence)
3451eb4ab17SShengfei Xu 		return;
3461eb4ab17SShengfei Xu 
3471eb4ab17SShengfei Xu 	for (i = RK806_ID_DCDC1; i <= RK806_ID_DCDC10; i++) {
3481eb4ab17SShengfei Xu 		value = rk8xx->vb_shutdown_sequence[RK806_ID_DCDC1 + i];
3491eb4ab17SShengfei Xu 		rk8xx_write(dev, RK806_SHUTDOWN_SEQ_REG0 + i, &value, 1);
3501eb4ab17SShengfei Xu 	}
3511eb4ab17SShengfei Xu 
3521eb4ab17SShengfei Xu 	for (i = RK806_ID_NLDO1; i <= RK806_ID_NLDO5; i++) {
3531eb4ab17SShengfei Xu 		value = rk8xx->vb_shutdown_sequence[i];
3541eb4ab17SShengfei Xu 		rk8xx_write(dev, RK806_SHUTDOWN_SEQ_REG0 + i, &value, 1);
3551eb4ab17SShengfei Xu 	}
3561eb4ab17SShengfei Xu 
3571eb4ab17SShengfei Xu 	rk8xx_read(dev, RK806_SHUTDOWN_SEQ_REG8, &value, 1);
3581eb4ab17SShengfei Xu 	value |= rk8xx->vb_shutdown_sequence[RK806_ID_PLDO1] << 6;
3591eb4ab17SShengfei Xu 	rk8xx_write(dev, RK806_SHUTDOWN_SEQ_REG8, &value, 1);
3601eb4ab17SShengfei Xu 
3611eb4ab17SShengfei Xu 	rk8xx_read(dev, RK806_SHUTDOWN_SEQ_REG11, &value, 1);
3621eb4ab17SShengfei Xu 	value |= rk8xx->vb_shutdown_sequence[RK806_ID_PLDO2] << 6;
3631eb4ab17SShengfei Xu 	rk8xx_write(dev, RK806_SHUTDOWN_SEQ_REG11, &value, 1);
3641eb4ab17SShengfei Xu 
3651eb4ab17SShengfei Xu 	rk8xx_read(dev, RK806_SHUTDOWN_SEQ_REG14, &value, 1);
3661eb4ab17SShengfei Xu 	value |= rk8xx->vb_shutdown_sequence[RK806_ID_PLDO3] << 6;
3671eb4ab17SShengfei Xu 	rk8xx_write(dev, RK806_SHUTDOWN_SEQ_REG14, &value, 1);
3681eb4ab17SShengfei Xu 
3691eb4ab17SShengfei Xu 	rk8xx_read(dev, RK806_SHUTDOWN_SEQ_REG15, &value, 1);
3701eb4ab17SShengfei Xu 	value |= rk8xx->vb_shutdown_sequence[RK806_ID_PLDO4];
3711eb4ab17SShengfei Xu 	rk8xx_write(dev, RK806_SHUTDOWN_SEQ_REG15, &value, 1);
3721eb4ab17SShengfei Xu 
3731eb4ab17SShengfei Xu 	rk8xx_read(dev, RK806_SHUTDOWN_SEQ_REG16, &value, 1);
3741eb4ab17SShengfei Xu 	value |= rk8xx->vb_shutdown_sequence[RK806_ID_PLDO5];
3751eb4ab17SShengfei Xu 	rk8xx_write(dev, RK806_SHUTDOWN_SEQ_REG16, &value, 1);
3761eb4ab17SShengfei Xu 
3771eb4ab17SShengfei Xu 	rk8xx_read(dev, RK806_SHUTDOWN_SEQ_REG5, &value, 1);
3781eb4ab17SShengfei Xu 	value |= rk8xx->vb_shutdown_sequence[RK806_ID_PLDO6] << 6;
3791eb4ab17SShengfei Xu 	rk8xx_write(dev, RK806_SHUTDOWN_SEQ_REG5, &value, 1);
3801eb4ab17SShengfei Xu }
3811eb4ab17SShengfei Xu 
rk8xx_suspend(struct udevice * dev)38240db7404SJoseph Chen static int rk8xx_suspend(struct udevice *dev)
38340db7404SJoseph Chen {
38440db7404SJoseph Chen 	struct rk8xx_priv *priv = dev_get_priv(dev);
38540db7404SJoseph Chen 	int ret = 0;
386ef9c5d10Sshengfei Xu 	u8 i, val;
38740db7404SJoseph Chen 
38840db7404SJoseph Chen 	switch (priv->variant) {
389ef9c5d10Sshengfei Xu 	case RK806_ID:
390ef9c5d10Sshengfei Xu 		ret = rk8xx_read(dev, RK806_PWRCTRL_CONFIG0, &val, 1);
391ef9c5d10Sshengfei Xu 		if (ret)
392ef9c5d10Sshengfei Xu 			return ret;
393ef9c5d10Sshengfei Xu 		val &= RK806_PWRCTRL_FUN_MSK;
394ef9c5d10Sshengfei Xu 		ret = rk8xx_write(dev, RK806_PWRCTRL_CONFIG0, &val, 1);
395ef9c5d10Sshengfei Xu 		if (ret)
396ef9c5d10Sshengfei Xu 			return ret;
397ef9c5d10Sshengfei Xu 
398ef9c5d10Sshengfei Xu 		ret = rk8xx_read(dev, RK806_PWRCTRL_CONFIG1, &val, 1);
399ef9c5d10Sshengfei Xu 		if (ret)
400ef9c5d10Sshengfei Xu 			return ret;
401ef9c5d10Sshengfei Xu 
402ef9c5d10Sshengfei Xu 		val &= RK806_PWRCTRL_FUN_MSK;
403ef9c5d10Sshengfei Xu 		ret = rk8xx_write(dev, RK806_PWRCTRL_CONFIG1, &val, 1);
404ef9c5d10Sshengfei Xu 		if (ret)
405ef9c5d10Sshengfei Xu 			return ret;
406ef9c5d10Sshengfei Xu 
407ef9c5d10Sshengfei Xu 		for (i = RK806_VSEL_CTR_SEL0; i <= RK806_DVS_CTR_SEL4; i++) {
408ef9c5d10Sshengfei Xu 			ret = rk8xx_read(dev, i, &val, 1);
409ef9c5d10Sshengfei Xu 			if (ret)
410ef9c5d10Sshengfei Xu 				return ret;
411ef9c5d10Sshengfei Xu 			val &= RK806_VSEL_CTRL_MSK;
412ef9c5d10Sshengfei Xu 			ret = rk8xx_write(dev, i, &val, 1);
413ef9c5d10Sshengfei Xu 			if (ret)
414ef9c5d10Sshengfei Xu 				return ret;
415ef9c5d10Sshengfei Xu 		}
416ef9c5d10Sshengfei Xu 
417ef9c5d10Sshengfei Xu 		ret = rk8xx_read(dev, RK806_PWRCTRL_CONFIG0, &val, 1);
418ef9c5d10Sshengfei Xu 		if (ret)
419ef9c5d10Sshengfei Xu 			return ret;
420ef9c5d10Sshengfei Xu 		val &= RK806_PWRCTRL_FUN_MSK;
421ef9c5d10Sshengfei Xu 		val |= RK806_ENABLE_PWRCTRL;
422ef9c5d10Sshengfei Xu 		ret = rk8xx_write(dev, RK806_PWRCTRL_CONFIG0, &val, 1);
423ef9c5d10Sshengfei Xu 		if (ret)
424ef9c5d10Sshengfei Xu 			return ret;
425ef9c5d10Sshengfei Xu 
426ef9c5d10Sshengfei Xu 		for (i = RK806_VSEL_CTR_SEL0; i <= RK806_DVS_CTR_SEL4; i++) {
427ef9c5d10Sshengfei Xu 			ret = rk8xx_read(dev, i, &val, 1);
428ef9c5d10Sshengfei Xu 			if (ret)
429ef9c5d10Sshengfei Xu 				return ret;
430ef9c5d10Sshengfei Xu 			val &= RK806_VSEL_CTRL_MSK;
431ef9c5d10Sshengfei Xu 			val |= RK806_VSEL_PWRCTRL1;
432ef9c5d10Sshengfei Xu 			ret = rk8xx_write(dev, i, &val, 1);
433ef9c5d10Sshengfei Xu 			if (ret)
434ef9c5d10Sshengfei Xu 				return ret;
435ef9c5d10Sshengfei Xu 		}
436ef9c5d10Sshengfei Xu 		break;
43740db7404SJoseph Chen 	case RK809_ID:
43840db7404SJoseph Chen 	case RK817_ID:
43940db7404SJoseph Chen 		/* pmic_sleep active high */
44040db7404SJoseph Chen 		ret = rk8xx_read(dev, RK817_PMIC_SYS_CFG3, &val, 1);
44140db7404SJoseph Chen 		if (ret)
44240db7404SJoseph Chen 			return ret;
44340db7404SJoseph Chen 		priv->sleep_pin = val;
44440db7404SJoseph Chen 		val &= ~0x38;
44540db7404SJoseph Chen 		val |= 0x28;
44640db7404SJoseph Chen 		ret = rk8xx_write(dev, RK817_PMIC_SYS_CFG3, &val, 1);
44740db7404SJoseph Chen 		break;
44840db7404SJoseph Chen 	default:
44940db7404SJoseph Chen 		return 0;
45040db7404SJoseph Chen 	}
45140db7404SJoseph Chen 
45240db7404SJoseph Chen 	return ret;
45340db7404SJoseph Chen }
45440db7404SJoseph Chen 
rk8xx_resume(struct udevice * dev)45540db7404SJoseph Chen static int rk8xx_resume(struct udevice *dev)
45640db7404SJoseph Chen {
45740db7404SJoseph Chen 	struct rk8xx_priv *priv = dev_get_priv(dev);
45840db7404SJoseph Chen 	int ret = 0;
459ef9c5d10Sshengfei Xu 	u8 i, val;
46040db7404SJoseph Chen 
46140db7404SJoseph Chen 	switch (priv->variant) {
462ef9c5d10Sshengfei Xu 	case RK806_ID:
463ef9c5d10Sshengfei Xu 		for (i = RK806_VSEL_CTR_SEL0; i <= RK806_DVS_CTR_SEL4; i++) {
464ef9c5d10Sshengfei Xu 			ret = rk8xx_read(dev, i, &val, 1);
465ef9c5d10Sshengfei Xu 			if (ret)
466ef9c5d10Sshengfei Xu 				return ret;
467ef9c5d10Sshengfei Xu 			val &= RK806_VSEL_CTRL_MSK;
468ef9c5d10Sshengfei Xu 			ret = rk8xx_write(dev, i, &val, 1);
469ef9c5d10Sshengfei Xu 			if (ret)
470ef9c5d10Sshengfei Xu 				return ret;
471ef9c5d10Sshengfei Xu 		}
472ef9c5d10Sshengfei Xu 
473ef9c5d10Sshengfei Xu 		ret = rk8xx_read(dev, RK806_PWRCTRL_CONFIG0, &val, 1);
474ef9c5d10Sshengfei Xu 		if (ret)
475ef9c5d10Sshengfei Xu 			return ret;
476ef9c5d10Sshengfei Xu 		val &= RK806_PWRCTRL_FUN_MSK;
477ef9c5d10Sshengfei Xu 		ret = rk8xx_write(dev, RK806_PWRCTRL_CONFIG0, &val, 1);
478ef9c5d10Sshengfei Xu 		if (ret)
479ef9c5d10Sshengfei Xu 			return ret;
480ef9c5d10Sshengfei Xu 
481ef9c5d10Sshengfei Xu 		ret = rk8xx_read(dev, RK806_PWRCTRL_CONFIG1, &val, 1);
482ef9c5d10Sshengfei Xu 		if (ret)
483ef9c5d10Sshengfei Xu 			return ret;
484ef9c5d10Sshengfei Xu 		val &= RK806_PWRCTRL_FUN_MSK;
485ef9c5d10Sshengfei Xu 		ret = rk8xx_write(dev, RK806_PWRCTRL_CONFIG1, &val, 1);
486ef9c5d10Sshengfei Xu 		break;
48740db7404SJoseph Chen 	case RK809_ID:
48840db7404SJoseph Chen 	case RK817_ID:
48940db7404SJoseph Chen 		ret = rk8xx_write(dev, RK817_PMIC_SYS_CFG3, &priv->sleep_pin, 1);
49040db7404SJoseph Chen 		break;
49140db7404SJoseph Chen 	default:
49240db7404SJoseph Chen 		return 0;
49340db7404SJoseph Chen 	}
49440db7404SJoseph Chen 
49540db7404SJoseph Chen 	return ret;
49640db7404SJoseph Chen }
49740db7404SJoseph Chen 
rk8xx_shutdown(struct udevice * dev)498282d550aSJoseph Chen static int rk8xx_shutdown(struct udevice *dev)
499282d550aSJoseph Chen {
500282d550aSJoseph Chen 	struct rk8xx_priv *priv = dev_get_priv(dev);
5017f18d96cSJoseph Chen 	u8 val, dev_off, devctrl_reg;
502282d550aSJoseph Chen 	int ret = 0;
503282d550aSJoseph Chen 
504282d550aSJoseph Chen 	switch (priv->variant) {
505ef9c5d10Sshengfei Xu 	case RK806_ID:
5061eb4ab17SShengfei Xu 		rk806_shutdown_seq(dev);
507ef9c5d10Sshengfei Xu 		devctrl_reg = RK806_SYS_CFG3;
508ef9c5d10Sshengfei Xu 		dev_off = RK806_DEV_OFF;
509ef9c5d10Sshengfei Xu 		break;
510282d550aSJoseph Chen 	case RK808_ID:
5117f18d96cSJoseph Chen 		devctrl_reg = REG_DEVCTRL;
512282d550aSJoseph Chen 		dev_off = BIT(3);
513282d550aSJoseph Chen 		break;
514282d550aSJoseph Chen 	case RK805_ID:
515282d550aSJoseph Chen 	case RK816_ID:
516282d550aSJoseph Chen 	case RK818_ID:
5177f18d96cSJoseph Chen 		devctrl_reg = REG_DEVCTRL;
5187f18d96cSJoseph Chen 		dev_off = BIT(0);
5197f18d96cSJoseph Chen 		break;
5201b6b965cSJoseph Chen 	case RK809_ID:
5217f18d96cSJoseph Chen 	case RK817_ID:
5227f18d96cSJoseph Chen 		devctrl_reg = RK817_REG_SYS_CFG3;
523282d550aSJoseph Chen 		dev_off = BIT(0);
524282d550aSJoseph Chen 		break;
525282d550aSJoseph Chen 	default:
526282d550aSJoseph Chen 		printf("Unknown PMIC: RK%x\n", priv->variant);
527282d550aSJoseph Chen 		return -EINVAL;
528282d550aSJoseph Chen 	}
529282d550aSJoseph Chen 
530a9ee0047SJoseph Chen 	ret = rk8xx_read(dev, devctrl_reg, &val, 1);
531a9ee0047SJoseph Chen 	if (ret)
532282d550aSJoseph Chen 		return ret;
533282d550aSJoseph Chen 
534282d550aSJoseph Chen 	val |= dev_off;
535a9ee0047SJoseph Chen 	ret = rk8xx_write(dev, devctrl_reg, &val, 1);
536a9ee0047SJoseph Chen 	if (ret)
537282d550aSJoseph Chen 		return ret;
538282d550aSJoseph Chen 
539282d550aSJoseph Chen 	return 0;
540282d550aSJoseph Chen }
541282d550aSJoseph Chen 
542453c5a92SJacob Chen #if CONFIG_IS_ENABLED(PMIC_CHILDREN)
rk8xx_bind(struct udevice * dev)543453c5a92SJacob Chen static int rk8xx_bind(struct udevice *dev)
544453c5a92SJacob Chen {
5457a869e6cSSimon Glass 	ofnode regulators_node;
546453c5a92SJacob Chen 	int children;
547453c5a92SJacob Chen 
5487a869e6cSSimon Glass 	regulators_node = dev_read_subnode(dev, "regulators");
5497a869e6cSSimon Glass 	if (!ofnode_valid(regulators_node)) {
5505cfdc123SJoseph Chen 		debug("%s: %s regulators subnode not found!\n", __func__,
551453c5a92SJacob Chen 		      dev->name);
552453c5a92SJacob Chen 		return -ENXIO;
553453c5a92SJacob Chen 	}
554453c5a92SJacob Chen 
555453c5a92SJacob Chen 	debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
556453c5a92SJacob Chen 
557453c5a92SJacob Chen 	children = pmic_bind_children(dev, regulators_node, pmic_children_info);
558453c5a92SJacob Chen 	if (!children)
559453c5a92SJacob Chen 		debug("%s: %s - no child found\n", __func__, dev->name);
560453c5a92SJacob Chen 
5616d747531SJoseph Chen 	children = pmic_bind_children(dev, dev->node, power_key_info);
5626d747531SJoseph Chen 	if (!children)
5636d747531SJoseph Chen 		debug("%s: %s - no child found\n", __func__, dev->name);
5646d747531SJoseph Chen 
56547bc0dadSElaine Zhang 	children = pmic_bind_children(dev, dev->node, rtc_info);
56647bc0dadSElaine Zhang 	if (!children)
56747bc0dadSElaine Zhang 		debug("%s: %s - no child found\n", __func__, dev->name);
56847bc0dadSElaine Zhang 
5696a367335SJoseph Chen 	children = pmic_bind_children(dev, dev->node, fuel_gauge_info);
5706a367335SJoseph Chen 	if (!children)
5716a367335SJoseph Chen 		debug("%s: %s - no child found\n", __func__, dev->name);
5726a367335SJoseph Chen 
5737a5efcbdSSugar Zhang 	children = pmic_bind_children(dev, dev->node, rk817_codec_info);
5747a5efcbdSSugar Zhang 	if (!children)
5757a5efcbdSSugar Zhang 		debug("%s: %s - no child found\n", __func__, dev->name);
5767a5efcbdSSugar Zhang 
577453c5a92SJacob Chen 	/* Always return success for this device */
578453c5a92SJacob Chen 	return 0;
579453c5a92SJacob Chen }
580453c5a92SJacob Chen #endif
581453c5a92SJacob Chen 
5827cef7918SJoseph Chen #if CONFIG_IS_ENABLED(IRQ)
5832833da14SJoseph Chen /*
5842833da14SJoseph Chen  * When system suspend during U-Boot charge, make sure the plugout event
5852833da14SJoseph Chen  * be able to wakeup cpu in wfi/wfe state.
5862833da14SJoseph Chen  */
5872833da14SJoseph Chen #ifdef CONFIG_DM_CHARGE_DISPLAY
rk8xx_plug_out_handler(int irq,void * data)5882833da14SJoseph Chen static void rk8xx_plug_out_handler(int irq, void *data)
5892833da14SJoseph Chen {
5902833da14SJoseph Chen 	printf("Plug out interrupt\n");
5912833da14SJoseph Chen }
5922833da14SJoseph Chen #endif
5932833da14SJoseph Chen 
rk8xx_irq_chip_init(struct udevice * dev)594ded32713SJoseph Chen static int rk8xx_irq_chip_init(struct udevice *dev)
595ded32713SJoseph Chen {
596ded32713SJoseph Chen 	struct rk8xx_priv *priv = dev_get_priv(dev);
597ded32713SJoseph Chen 	struct virq_chip *irq_chip = NULL;
59822ff4ccaSJoseph Chen 	__maybe_unused int irq_plugout = 1;
599ece79c0fSshengfei Xu 	uint8_t value;
600ded32713SJoseph Chen 	int ret;
601ded32713SJoseph Chen 
602ded32713SJoseph Chen 	switch (priv->variant) {
603ef9c5d10Sshengfei Xu 	case RK806_ID:
604ef9c5d10Sshengfei Xu 		irq_chip = &rk806_irq_chip;
605ef9c5d10Sshengfei Xu 		irq_plugout = 0;
606ece79c0fSshengfei Xu 		ret = rk8xx_read(dev, RK806_GPIO_INT_CONFIG, &value, 1);
607ece79c0fSshengfei Xu 		if (ret)
608ece79c0fSshengfei Xu 			return ret;
609ece79c0fSshengfei Xu 		/* set INT polarity active low */
610ece79c0fSshengfei Xu 		value &= (~RK806_INT_POL_HIGH);
611ece79c0fSshengfei Xu 		ret = rk8xx_write(dev, RK806_GPIO_INT_CONFIG, &value, 1);
612ece79c0fSshengfei Xu 		if (ret)
613ece79c0fSshengfei Xu 			return ret;
614ef9c5d10Sshengfei Xu 		break;
615ded32713SJoseph Chen 	case RK808_ID:
616ded32713SJoseph Chen 		irq_chip = &rk808_irq_chip;
617ded32713SJoseph Chen 		break;
618ded32713SJoseph Chen 	case RK805_ID:
619ded32713SJoseph Chen 		irq_chip = &rk805_irq_chip;
62022ff4ccaSJoseph Chen 		irq_plugout = 0;
621ded32713SJoseph Chen 		break;
622ded32713SJoseph Chen 	case RK816_ID:
623ded32713SJoseph Chen 		irq_chip = &rk816_irq_chip;
624ded32713SJoseph Chen 		break;
625ded32713SJoseph Chen 	case RK818_ID:
626ded32713SJoseph Chen 		irq_chip = &rk818_irq_chip;
627ded32713SJoseph Chen 		break;
628ded32713SJoseph Chen 	case RK809_ID:
629ded32713SJoseph Chen 	case RK817_ID:
630ded32713SJoseph Chen 		irq_chip = &rk817_irq_chip;
631ded32713SJoseph Chen 		break;
632ded32713SJoseph Chen 	default:
633ded32713SJoseph Chen 		return -EINVAL;
634ded32713SJoseph Chen 	}
635ded32713SJoseph Chen 
636ded32713SJoseph Chen 	if (irq_chip) {
637871b6686SJoseph Chen 		ret = virq_add_chip(dev, irq_chip, priv->irq);
638ded32713SJoseph Chen 		if (ret) {
639ded32713SJoseph Chen 			printf("Failed to add irqchip(irq=%d), ret=%d\n",
640ded32713SJoseph Chen 			       priv->irq, ret);
641ded32713SJoseph Chen 			return ret;
642ded32713SJoseph Chen 		}
643ded32713SJoseph Chen 
644ded32713SJoseph Chen 		priv->irq_chip = irq_chip;
645ded32713SJoseph Chen 
646ded32713SJoseph Chen #ifdef CONFIG_DM_CHARGE_DISPLAY
647ded32713SJoseph Chen 		int irq;
648ded32713SJoseph Chen 
64922ff4ccaSJoseph Chen 		if (irq_plugout) {
650ded32713SJoseph Chen 			irq = virq_to_irq(irq_chip, RK8XX_IRQ_PLUG_OUT);
651ded32713SJoseph Chen 			if (irq < 0) {
652ded32713SJoseph Chen 				printf("Failed to register plugout irq, ret=%d\n", irq);
653ded32713SJoseph Chen 				return irq;
654ded32713SJoseph Chen 			}
655ded32713SJoseph Chen 			irq_install_handler(irq, rk8xx_plug_out_handler, dev);
656ded32713SJoseph Chen 			irq_handler_enable_suspend_only(irq);
65722ff4ccaSJoseph Chen 		}
658ded32713SJoseph Chen #endif
659ded32713SJoseph Chen 	}
660ded32713SJoseph Chen 
661ded32713SJoseph Chen 	return 0;
662ded32713SJoseph Chen }
663ded32713SJoseph Chen #else
rk8xx_irq_chip_init(struct udevice * dev)664ded32713SJoseph Chen static inline int rk8xx_irq_chip_init(struct udevice *dev) { return 0; }
665ded32713SJoseph Chen #endif
666ded32713SJoseph Chen 
rk8xx_ofdata_to_platdata(struct udevice * dev)667bebba31cSJoseph Chen static int rk8xx_ofdata_to_platdata(struct udevice *dev)
668bebba31cSJoseph Chen {
669bebba31cSJoseph Chen 	struct rk8xx_priv *rk8xx = dev_get_priv(dev);
670bebba31cSJoseph Chen 	u32 interrupt, phandle, val;
6711eb4ab17SShengfei Xu 	int ret, len;
672bebba31cSJoseph Chen 
673bebba31cSJoseph Chen 	phandle = dev_read_u32_default(dev, "interrupt-parent", -ENODATA);
674bebba31cSJoseph Chen 	if (phandle == -ENODATA) {
675bebba31cSJoseph Chen 		printf("Read 'interrupt-parent' failed, ret=%d\n", phandle);
676bebba31cSJoseph Chen 		return phandle;
677bebba31cSJoseph Chen 	}
678bebba31cSJoseph Chen 
679bebba31cSJoseph Chen 	ret = dev_read_u32_array(dev, "interrupts", &interrupt, 1);
680bebba31cSJoseph Chen 	if (ret) {
681bebba31cSJoseph Chen 		printf("Read 'interrupts' failed, ret=%d\n", ret);
682bebba31cSJoseph Chen 		return ret;
683bebba31cSJoseph Chen 	}
684bebba31cSJoseph Chen 
685bebba31cSJoseph Chen #if CONFIG_IS_ENABLED(IRQ)
686bebba31cSJoseph Chen 	rk8xx->irq = phandle_gpio_to_irq(phandle, interrupt);
687bebba31cSJoseph Chen 	if (rk8xx->irq < 0) {
688bebba31cSJoseph Chen 		printf("Failed to request rk8xx irq, ret=%d\n", rk8xx->irq);
689bebba31cSJoseph Chen 		return rk8xx->irq;
690bebba31cSJoseph Chen 	}
691bebba31cSJoseph Chen #endif
692bebba31cSJoseph Chen 	val = dev_read_u32_default(dev, "long-press-off-time-sec", 0);
693bebba31cSJoseph Chen 	if (val <= 6)
694bebba31cSJoseph Chen 		rk8xx->lp_off_time = RK8XX_LP_TIME_6S;
695bebba31cSJoseph Chen 	else if (val <= 8)
696bebba31cSJoseph Chen 		rk8xx->lp_off_time = RK8XX_LP_TIME_8S;
697bebba31cSJoseph Chen 	else if (val <= 10)
698bebba31cSJoseph Chen 		rk8xx->lp_off_time = RK8XX_LP_TIME_10S;
699bebba31cSJoseph Chen 	else
700bebba31cSJoseph Chen 		rk8xx->lp_off_time = RK8XX_LP_TIME_12S;
701bebba31cSJoseph Chen 
702bebba31cSJoseph Chen 	val = dev_read_u32_default(dev, "long-press-restart", 0);
703bebba31cSJoseph Chen 	if (val)
704bebba31cSJoseph Chen 		rk8xx->lp_action = RK8XX_LP_RESTART;
705bebba31cSJoseph Chen 	else
706bebba31cSJoseph Chen 		rk8xx->lp_action = RK8XX_LP_OFF;
707bebba31cSJoseph Chen 
708bebba31cSJoseph Chen 	rk8xx->not_save_power_en = dev_read_u32_default(dev, "not-save-power-en", 0);
709bebba31cSJoseph Chen 	rk8xx->sys_can_sd = dev_read_bool(dev, "vsys-off-shutdown");
710bebba31cSJoseph Chen 	rk8xx->rst_fun = dev_read_u32_default(dev, "pmic-reset-func", 0);
711f335f73cSshengfei Xu 	/* buck5 external feedback resister disable */
712f335f73cSshengfei Xu 	rk8xx->buck5_feedback_dis = dev_read_bool(dev, "buck5-feedback-disable");
713bebba31cSJoseph Chen 
7144e54e501Sshengfei Xu 	rk8xx->pwr_ctr[0] = dev_read_u32_default(dev, "pwrctrl1_output", -1);
7154e54e501Sshengfei Xu 	rk8xx->pwr_ctr[1] = dev_read_u32_default(dev, "pwrctrl2_output", -1);
7164e54e501Sshengfei Xu 	rk8xx->pwr_ctr[2] = dev_read_u32_default(dev, "pwrctrl3_output", -1);
7174e54e501Sshengfei Xu 
7181eb4ab17SShengfei Xu 	if (!dev_read_prop(dev, "shutdown-sequence", &len)) {
7191eb4ab17SShengfei Xu 		printf("can't find shutdown-sequence prop\n");
7201eb4ab17SShengfei Xu 	} else {
7211eb4ab17SShengfei Xu 		if (len / 4 != RK806_ID_END)
7221eb4ab17SShengfei Xu 			return 0;
7231eb4ab17SShengfei Xu 		rk8xx->shutdown_sequence = calloc(len, 1);
7241eb4ab17SShengfei Xu 		if (!rk8xx->shutdown_sequence) {
7251eb4ab17SShengfei Xu 			printf("can't calloc shutdown_sequence\n");
7261eb4ab17SShengfei Xu 			return 0;
7271eb4ab17SShengfei Xu 		}
7281eb4ab17SShengfei Xu 
7291eb4ab17SShengfei Xu 		if (dev_read_u32_array(dev, "shutdown-sequence",
7301eb4ab17SShengfei Xu 				       rk8xx->shutdown_sequence,
7311eb4ab17SShengfei Xu 				       RK806_ID_END)) {
7321eb4ab17SShengfei Xu 			printf("can't read shutdown_sequence\n");
7331eb4ab17SShengfei Xu 			free(rk8xx->shutdown_sequence);
7341eb4ab17SShengfei Xu 			return 0;
7351eb4ab17SShengfei Xu 		}
7361eb4ab17SShengfei Xu 	}
7371eb4ab17SShengfei Xu 
7381eb4ab17SShengfei Xu 	if (!dev_read_prop(dev, "vb-shutdown-sequence", &len)) {
7391eb4ab17SShengfei Xu 		printf("can't find vb-shutdown-sequence prop\n");
7401eb4ab17SShengfei Xu 	} else {
7411eb4ab17SShengfei Xu 		if (len / 4 != RK806_ID_END)
7421eb4ab17SShengfei Xu 			return 0;
7431eb4ab17SShengfei Xu 		rk8xx->vb_shutdown_sequence = calloc(len, 1);
7441eb4ab17SShengfei Xu 		if (!rk8xx->vb_shutdown_sequence) {
7451eb4ab17SShengfei Xu 			printf("can't calloc vb_shutdown_sequence\n");
7461eb4ab17SShengfei Xu 			return 0;
7471eb4ab17SShengfei Xu 		}
7481eb4ab17SShengfei Xu 
7491eb4ab17SShengfei Xu 		if (dev_read_u32_array(dev, "vb-shutdown-sequence",
7501eb4ab17SShengfei Xu 				       rk8xx->vb_shutdown_sequence,
7511eb4ab17SShengfei Xu 				       RK806_ID_END)) {
7521eb4ab17SShengfei Xu 			printf("can't read vb-shutdown-sequence\n");
7531eb4ab17SShengfei Xu 			free(rk8xx->vb_shutdown_sequence);
7541eb4ab17SShengfei Xu 			return 0;
7551eb4ab17SShengfei Xu 		}
7561eb4ab17SShengfei Xu 	}
7571eb4ab17SShengfei Xu 
758bebba31cSJoseph Chen 	return 0;
759bebba31cSJoseph Chen }
760bebba31cSJoseph Chen 
rk806_pwrctrl_output_value(struct udevice * dev,int pin,int output_value)7614e54e501Sshengfei Xu static void rk806_pwrctrl_output_value(struct udevice *dev,
7624e54e501Sshengfei Xu 				       int pin,
7634e54e501Sshengfei Xu 				       int output_value)
7644e54e501Sshengfei Xu {
7654e54e501Sshengfei Xu 	u8 value;
7664e54e501Sshengfei Xu 
7674e54e501Sshengfei Xu 	rk8xx_read(dev, RK806_PWRCTRL_CONFIG0 + pin / 3, &value, 1);
7684e54e501Sshengfei Xu 	if ((pin == RK806_PWRCTRL1) || (pin == RK806_PWRCTRL3)) {
7694e54e501Sshengfei Xu 		value &= ~RK806_PWRCTR_MSK_FUN;
7704e54e501Sshengfei Xu 		value |= RK806_PWRCTR_GPIO_FUN;
7714e54e501Sshengfei Xu 	} else {
7724e54e501Sshengfei Xu 		value &= ~(RK806_PWRCTR_MSK_FUN << 4);
7734e54e501Sshengfei Xu 		value |= RK806_PWRCTR_GPIO_FUN << 4;
7744e54e501Sshengfei Xu 	}
7754e54e501Sshengfei Xu 	rk8xx_write(dev, RK806_PWRCTRL_CONFIG0 + pin / 3, &value, 1);
7764e54e501Sshengfei Xu 
7774e54e501Sshengfei Xu 	rk8xx_read(dev, RK806_PWRCTRL_GPIO, &value, 1);
7784e54e501Sshengfei Xu 	value &= ~(RK806_PWRCTR_OUTPUT_MSK << (pin - 1));
7794e54e501Sshengfei Xu 	if (output_value)
7804e54e501Sshengfei Xu 		value |= (RK806_PWRCTR_OUTPUT1 << (pin - 1));
7814e54e501Sshengfei Xu 	else
7824e54e501Sshengfei Xu 		value |= (RK806_PWRCTR_OUTPUT0 << (pin - 1));
7834e54e501Sshengfei Xu 	rk8xx_write(dev, RK806_PWRCTRL_GPIO, &value, 1);
7844e54e501Sshengfei Xu }
7854e54e501Sshengfei Xu 
rk8xx_probe(struct udevice * dev)786453c5a92SJacob Chen static int rk8xx_probe(struct udevice *dev)
787453c5a92SJacob Chen {
788453c5a92SJacob Chen 	struct rk8xx_priv *priv = dev_get_priv(dev);
78943e3c846SJoseph Chen 	struct reg_data *init_current = NULL;
7901c223666SJoseph Chen 	struct reg_data *init_data = NULL;
79143e3c846SJoseph Chen 	int init_current_num = 0;
7921c223666SJoseph Chen 	int init_data_num = 0;
7935cfdc123SJoseph Chen 	int ret = 0, i, show_variant;
7947f18d96cSJoseph Chen 	uint8_t msb, lsb, id_msb, id_lsb;
7957623c170SJoseph Chen 	uint8_t on_source = 0, off_source = 0;
79600d11ef2SShunqing Chen 	uint8_t pwron_key = 0, lp_off_msk = 0, lp_act_msk = 0;
7979e9e0e07SShengfei Xu 	uint8_t power_en0, power_en1, power_en2, power_en3;
798a9ee0047SJoseph Chen 	uint8_t on, off;
7999e9e0e07SShengfei Xu 	uint8_t value;
800453c5a92SJacob Chen 
801453c5a92SJacob Chen 	/* read Chip variant */
8021b6b965cSJoseph Chen 	if (device_is_compatible(dev, "rockchip,rk817") ||
8031b6b965cSJoseph Chen 	    device_is_compatible(dev, "rockchip,rk809")) {
8047f18d96cSJoseph Chen 		id_msb = RK817_ID_MSB;
8057f18d96cSJoseph Chen 		id_lsb = RK817_ID_LSB;
806ef9c5d10Sshengfei Xu 	} else if (device_is_compatible(dev, "rockchip,rk806")) {
807ef9c5d10Sshengfei Xu 		id_msb = RK806_CHIP_NAME;
808ef9c5d10Sshengfei Xu 		id_lsb = RK806_CHIP_VER;
8097f18d96cSJoseph Chen 	} else {
8107f18d96cSJoseph Chen 		id_msb = ID_MSB;
8117f18d96cSJoseph Chen 		id_lsb = ID_LSB;
8127f18d96cSJoseph Chen 	}
8137f18d96cSJoseph Chen 
8145cfdc123SJoseph Chen 	ret = rk8xx_read(dev, id_msb, &msb, 1);
8155cfdc123SJoseph Chen 	if (ret)
8165cfdc123SJoseph Chen 		return ret;
8175cfdc123SJoseph Chen 	ret = rk8xx_read(dev, id_lsb, &lsb, 1);
8185cfdc123SJoseph Chen 	if (ret)
8195cfdc123SJoseph Chen 		return ret;
820453c5a92SJacob Chen 
821453c5a92SJacob Chen 	priv->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK;
8225cfdc123SJoseph Chen 	show_variant = priv->variant;
8231c223666SJoseph Chen 	switch (priv->variant) {
824ef9c5d10Sshengfei Xu 	case RK806_ID:
825ef9c5d10Sshengfei Xu 		on_source = RK806_ON_SOURCE;
826ef9c5d10Sshengfei Xu 		off_source = RK806_OFF_SOURCE;
827ef9c5d10Sshengfei Xu 		ret = rk8xx_read(dev, RK806_HW_VER, &value, 1);
828ef9c5d10Sshengfei Xu 		if (ret)
829ef9c5d10Sshengfei Xu 			panic("RK806: read RK806_HW_VER error!\n");
830ef9c5d10Sshengfei Xu 
831ef9c5d10Sshengfei Xu 		if ((lsb & RK806_VERSION_MSK) == RK806_VERSION_AB) {
832ef9c5d10Sshengfei Xu 			ret = rk8xx_read(dev, RK806_SYS_CFG1, &value, 1);
833ef9c5d10Sshengfei Xu 			if (ret) {
834ef9c5d10Sshengfei Xu 				dev_err(dev, "rk806 RK806_SYS_CFG1 read error: %d\n", ret);
835ef9c5d10Sshengfei Xu 				return ret;
836ef9c5d10Sshengfei Xu 			}
837ef9c5d10Sshengfei Xu 			value |= RK806_ABNORDET_EN;
838ef9c5d10Sshengfei Xu 			rk8xx_write(dev, RK806_SYS_CFG1, &value, 1);
839ef9c5d10Sshengfei Xu 		}
840ef9c5d10Sshengfei Xu 
8414e54e501Sshengfei Xu 		for (i = 0; i < 3; i++)
8424e54e501Sshengfei Xu 			if (priv->pwr_ctr[i] >= 0 && priv->pwr_ctr[i] <= 1)
8434e54e501Sshengfei Xu 				rk806_pwrctrl_output_value(dev,
8444e54e501Sshengfei Xu 							   i + 1,
8454e54e501Sshengfei Xu 							   priv->pwr_ctr[i]);
8464e54e501Sshengfei Xu 
847ef9c5d10Sshengfei Xu 		if (priv->rst_fun) {
848ef9c5d10Sshengfei Xu 			rk8xx_read(dev, RK806_SYS_CFG3, &value, 1);
849ef9c5d10Sshengfei Xu 			value &= RK806_RESET_FUN_CLR;
850ef9c5d10Sshengfei Xu 			if (priv->rst_fun == RK806_RST_MODE1) {
851ef9c5d10Sshengfei Xu 				value |= (RK806_RST_MODE1 << 6);
852ef9c5d10Sshengfei Xu 				rk8xx_write(dev, RK806_SYS_CFG3, &value, 1);
853ef9c5d10Sshengfei Xu 			} else if (priv->rst_fun == RK806_RST_MODE2) {
854ef9c5d10Sshengfei Xu 				value |= (RK806_RST_MODE2 << 6);
855ef9c5d10Sshengfei Xu 				rk8xx_write(dev, RK806_SYS_CFG3, &value, 1);
856ef9c5d10Sshengfei Xu 			}
857ef9c5d10Sshengfei Xu 		}
858f335f73cSshengfei Xu 
859f335f73cSshengfei Xu 		if (priv->buck5_feedback_dis) {
860f335f73cSshengfei Xu 			rk8xx_read(dev, RK806_BUCK_RSERVE_REG3, &value, 1);
861f335f73cSshengfei Xu 			value &= (~RK806_BUCK5_EX_RES_EN);
862f335f73cSshengfei Xu 			rk8xx_write(dev, RK806_BUCK_RSERVE_REG3, &value, 1);
863f335f73cSshengfei Xu 		}
8641eb4ab17SShengfei Xu 		rk806_vb_shutdown_seq(dev);
865ef9c5d10Sshengfei Xu 		break;
8661c223666SJoseph Chen 	case RK808_ID:
8675cfdc123SJoseph Chen 		show_variant = 0x808;	/* RK808 hardware ID is 0 */
86800d11ef2SShunqing Chen 		pwron_key = RK8XX_DEVCTRL_REG;
86900d11ef2SShunqing Chen 		lp_off_msk = RK8XX_LP_OFF_MSK;
8705cfdc123SJoseph Chen 		break;
8715cfdc123SJoseph Chen 	case RK805_ID:
8721c223666SJoseph Chen 	case RK816_ID:
87343e3c846SJoseph Chen 		on_source = RK8XX_ON_SOURCE;
87443e3c846SJoseph Chen 		off_source = RK8XX_OFF_SOURCE;
87500d11ef2SShunqing Chen 		pwron_key = RK8XX_DEVCTRL_REG;
87600d11ef2SShunqing Chen 		lp_off_msk = RK8XX_LP_OFF_MSK;
87700d11ef2SShunqing Chen 		lp_act_msk = RK8XX_LP_ACTION_MSK;
87843e3c846SJoseph Chen 		break;
8791c223666SJoseph Chen 	case RK818_ID:
8807623c170SJoseph Chen 		on_source = RK8XX_ON_SOURCE;
8817623c170SJoseph Chen 		off_source = RK8XX_OFF_SOURCE;
88200d11ef2SShunqing Chen 		pwron_key = RK8XX_DEVCTRL_REG;
88300d11ef2SShunqing Chen 		lp_off_msk = RK8XX_LP_OFF_MSK;
88400d11ef2SShunqing Chen 		lp_act_msk = RK8XX_LP_ACTION_MSK;
88543e3c846SJoseph Chen 		/* set current if no fuel gauge */
88643e3c846SJoseph Chen 		if (!ofnode_valid(dev_read_subnode(dev, "battery"))) {
88743e3c846SJoseph Chen 			init_current = rk818_init_current;
88843e3c846SJoseph Chen 			init_current_num = ARRAY_SIZE(rk818_init_current);
88943e3c846SJoseph Chen 		}
8901c223666SJoseph Chen 		break;
8911b6b965cSJoseph Chen 	case RK809_ID:
8921c223666SJoseph Chen 	case RK817_ID:
893b3285496Sshengfei Xu 		if (device_is_compatible(dev, "rockchip,rk809") && (priv->variant != RK809_ID)) {
894b3285496Sshengfei Xu 			dev_err(dev, "the dts is RK809, the hardware is RK817\n");
895b3285496Sshengfei Xu 			run_command("download", 0);
896b3285496Sshengfei Xu 		}
897b3285496Sshengfei Xu 
898b3285496Sshengfei Xu 		if (device_is_compatible(dev, "rockchip,rk817") && (priv->variant != RK817_ID)) {
899b3285496Sshengfei Xu 			dev_err(dev, "the dts is RK817, the hardware is RK809\n");
900b3285496Sshengfei Xu 			run_command("download", 0);
901b3285496Sshengfei Xu 		}
902b3285496Sshengfei Xu 
9037623c170SJoseph Chen 		on_source = RK817_ON_SOURCE;
9047623c170SJoseph Chen 		off_source = RK817_OFF_SOURCE;
90500d11ef2SShunqing Chen 		pwron_key = RK817_PWRON_KEY;
90600d11ef2SShunqing Chen 		lp_off_msk = RK8XX_LP_OFF_MSK;
90700d11ef2SShunqing Chen 		lp_act_msk = RK8XX_LP_ACTION_MSK;
9081c223666SJoseph Chen 		init_data = rk817_init_reg;
9091c223666SJoseph Chen 		init_data_num = ARRAY_SIZE(rk817_init_reg);
910d76e1bedSshengfei Xu 
911d76e1bedSshengfei Xu 		/* whether the system voltage can be shutdown in PWR_off mode */
912d76e1bedSshengfei Xu 		if (priv->sys_can_sd) {
913d76e1bedSshengfei Xu 			ret = rk8xx_read(dev, RK817_PMIC_CHRG_TERM, &value, 1);
914d76e1bedSshengfei Xu 			if (ret)
915d76e1bedSshengfei Xu 				return ret;
916d76e1bedSshengfei Xu 			value |= 0x80;
917d76e1bedSshengfei Xu 			ret = rk8xx_write(dev, RK817_PMIC_CHRG_TERM, &value, 1);
918d76e1bedSshengfei Xu 			if (ret)
919d76e1bedSshengfei Xu 				return ret;
920d76e1bedSshengfei Xu 		} else {
921d76e1bedSshengfei Xu 			ret = rk8xx_read(dev, RK817_PMIC_CHRG_TERM, &value, 1);
922d76e1bedSshengfei Xu 			if (ret)
923d76e1bedSshengfei Xu 				return ret;
924d76e1bedSshengfei Xu 			value &= 0x7f;
925d76e1bedSshengfei Xu 			ret = rk8xx_write(dev, RK817_PMIC_CHRG_TERM, &value, 1);
926d76e1bedSshengfei Xu 			if (ret)
927d76e1bedSshengfei Xu 				return ret;
928d76e1bedSshengfei Xu 		}
929d76e1bedSshengfei Xu 
930f8797432SShengfei Xu 		if ((priv->rst_fun > RK8xx_RST_MODE0) &&
931f8797432SShengfei Xu 		    (priv->rst_fun <= RK8xx_RST_MODE2)) {
932f8797432SShengfei Xu 			rk8xx_read(dev, RK817_PMIC_SYS_CFG3, &value, 1);
933f8797432SShengfei Xu 			value &=  RK8xx_RESET_FUN_CLR;
934f8797432SShengfei Xu 			value |= (priv->rst_fun << 6);
935f8797432SShengfei Xu 			rk8xx_write(dev, RK817_PMIC_SYS_CFG3, &value, 1);
936f8797432SShengfei Xu 		}
937b9e9168cSshengfei Xu 		/* judge whether save the PMIC_POWER_EN register */
938ef3bd067Sshengfei Xu 		if (!priv->not_save_power_en) {
939a9ee0047SJoseph Chen 			ret = rk8xx_read(dev, RK817_POWER_EN0, &power_en0, 1);
940a9ee0047SJoseph Chen 			if (ret)
941a9ee0047SJoseph Chen 				return ret;
942a9ee0047SJoseph Chen 			ret = rk8xx_read(dev, RK817_POWER_EN1, &power_en1, 1);
943a9ee0047SJoseph Chen 			if (ret)
944a9ee0047SJoseph Chen 				return ret;
945a9ee0047SJoseph Chen 			ret = rk8xx_read(dev, RK817_POWER_EN2, &power_en2, 1);
946a9ee0047SJoseph Chen 			if (ret)
947a9ee0047SJoseph Chen 				return ret;
948a9ee0047SJoseph Chen 			ret = rk8xx_read(dev, RK817_POWER_EN3, &power_en3, 1);
949a9ee0047SJoseph Chen 			if (ret)
950a9ee0047SJoseph Chen 				return ret;
9519e9e0e07SShengfei Xu 
9529e9e0e07SShengfei Xu 			value = (power_en0 & 0x0f) | ((power_en1 & 0x0f) << 4);
953a9ee0047SJoseph Chen 			rk8xx_write(dev, RK817_POWER_EN_SAVE0, &value, 1);
9549e9e0e07SShengfei Xu 			value = (power_en2 & 0x0f) | ((power_en3 & 0x0f) << 4);
955a9ee0047SJoseph Chen 			rk8xx_write(dev, RK817_POWER_EN_SAVE1, &value, 1);
956ef3bd067Sshengfei Xu 		}
9571c223666SJoseph Chen 		break;
9581c223666SJoseph Chen 	default:
9596ba708bcSJoseph Chen 		printf("Unknown PMIC: RK%x!!\n", priv->variant);
9606ba708bcSJoseph Chen 		return -EINVAL;
9616ba708bcSJoseph Chen 	}
962453c5a92SJacob Chen 
96343e3c846SJoseph Chen 	/* common init */
9641c223666SJoseph Chen 	for (i = 0; i < init_data_num; i++) {
9651c223666SJoseph Chen 		ret = pmic_clrsetbits(dev,
9661c223666SJoseph Chen 				      init_data[i].reg,
9671c223666SJoseph Chen 				      init_data[i].mask,
9681c223666SJoseph Chen 				      init_data[i].val);
9691c223666SJoseph Chen 		if (ret < 0) {
9701c223666SJoseph Chen 			printf("%s: i2c set reg 0x%x failed, ret=%d\n",
9711c223666SJoseph Chen 			       __func__, init_data[i].reg, ret);
9721c223666SJoseph Chen 		}
97343e3c846SJoseph Chen 	}
9741c223666SJoseph Chen 
97543e3c846SJoseph Chen 	/* current init */
97643e3c846SJoseph Chen 	for (i = 0; i < init_current_num; i++) {
97743e3c846SJoseph Chen 		ret = pmic_clrsetbits(dev,
97843e3c846SJoseph Chen 				      init_current[i].reg,
97943e3c846SJoseph Chen 				      init_current[i].mask,
98043e3c846SJoseph Chen 				      init_current[i].val);
98143e3c846SJoseph Chen 		if (ret < 0) {
98243e3c846SJoseph Chen 			printf("%s: i2c set reg 0x%x failed, ret=%d\n",
98343e3c846SJoseph Chen 			       __func__, init_current[i].reg, ret);
98443e3c846SJoseph Chen 		}
9851c223666SJoseph Chen 	}
9861c223666SJoseph Chen 
9877623c170SJoseph Chen 	printf("PMIC:  RK%x ", show_variant);
9887623c170SJoseph Chen 
989a9ee0047SJoseph Chen 	if (on_source && off_source) {
990a9ee0047SJoseph Chen 		rk8xx_read(dev, on_source, &on, 1);
991a9ee0047SJoseph Chen 		rk8xx_read(dev, off_source, &off, 1);
992a9ee0047SJoseph Chen 		printf("(on=0x%02x, off=0x%02x)", on, off);
993a9ee0047SJoseph Chen 	}
9947623c170SJoseph Chen 	printf("\n");
9957f18d96cSJoseph Chen 
99600d11ef2SShunqing Chen 	if (pwron_key) {
997a9ee0047SJoseph Chen 		ret = rk8xx_read(dev, pwron_key, &value, 1);
998a9ee0047SJoseph Chen 		if (ret)
999a9ee0047SJoseph Chen 			return ret;
100000d11ef2SShunqing Chen 		value &= ~(lp_off_msk | lp_act_msk);
100100d11ef2SShunqing Chen 		if (lp_off_msk)
100200d11ef2SShunqing Chen 			value |= priv->lp_off_time;
100300d11ef2SShunqing Chen 		if (lp_act_msk)
100400d11ef2SShunqing Chen 			value |= priv->lp_action;
1005a9ee0047SJoseph Chen 		rk8xx_write(dev, pwron_key, &value, 1);
100600d11ef2SShunqing Chen 	}
100700d11ef2SShunqing Chen 
1008ded32713SJoseph Chen 	ret = rk8xx_irq_chip_init(dev);
1009ded32713SJoseph Chen 	if (ret) {
1010ded32713SJoseph Chen 		printf("IRQ chip initial failed\n");
1011ded32713SJoseph Chen 		return ret;
1012ded32713SJoseph Chen 	}
1013ded32713SJoseph Chen 
1014453c5a92SJacob Chen 	return 0;
1015453c5a92SJacob Chen }
1016453c5a92SJacob Chen 
1017453c5a92SJacob Chen static struct dm_pmic_ops rk8xx_ops = {
1018453c5a92SJacob Chen 	.reg_count = rk8xx_reg_count,
1019453c5a92SJacob Chen 	.read = rk8xx_read,
1020453c5a92SJacob Chen 	.write = rk8xx_write,
102140db7404SJoseph Chen 	.suspend = rk8xx_suspend,
102240db7404SJoseph Chen 	.resume = rk8xx_resume,
1023282d550aSJoseph Chen 	.shutdown = rk8xx_shutdown,
1024453c5a92SJacob Chen };
1025453c5a92SJacob Chen 
1026453c5a92SJacob Chen static const struct udevice_id rk8xx_ids[] = {
10274b6f5dc9SElaine Zhang 	{ .compatible = "rockchip,rk805" },
1028ef9c5d10Sshengfei Xu 	{ .compatible = "rockchip,rk806" },
1029453c5a92SJacob Chen 	{ .compatible = "rockchip,rk808" },
10301b6b965cSJoseph Chen 	{ .compatible = "rockchip,rk809" },
10315e1bceeaSElaine Zhang 	{ .compatible = "rockchip,rk816" },
10327f18d96cSJoseph Chen 	{ .compatible = "rockchip,rk817" },
1033453c5a92SJacob Chen 	{ .compatible = "rockchip,rk818" },
1034453c5a92SJacob Chen 	{ }
1035453c5a92SJacob Chen };
1036453c5a92SJacob Chen 
1037453c5a92SJacob Chen U_BOOT_DRIVER(pmic_rk8xx) = {
1038453c5a92SJacob Chen 	.name = "rk8xx pmic",
1039453c5a92SJacob Chen 	.id = UCLASS_PMIC,
1040453c5a92SJacob Chen 	.of_match = rk8xx_ids,
1041453c5a92SJacob Chen #if CONFIG_IS_ENABLED(PMIC_CHILDREN)
1042453c5a92SJacob Chen 	.bind = rk8xx_bind,
1043453c5a92SJacob Chen #endif
1044ded32713SJoseph Chen 	.ofdata_to_platdata = rk8xx_ofdata_to_platdata,
10457c1fb0a7SKever Yang 	.priv_auto_alloc_size = sizeof(struct rk8xx_priv),
1046453c5a92SJacob Chen 	.probe = rk8xx_probe,
1047453c5a92SJacob Chen 	.ops = &rk8xx_ops,
1048453c5a92SJacob Chen };
1049