xref: /rk3399_rockchip-uboot/drivers/power/regulator/rk8xx.c (revision c8147680fd339fa5809a50b88948aa324a822bfa)
1453c5a92SJacob Chen /*
2453c5a92SJacob Chen  * Copyright (C) 2015 Google, Inc
3453c5a92SJacob Chen  * Written by Simon Glass <sjg@chromium.org>
4453c5a92SJacob Chen  *
5453c5a92SJacob Chen  * Based on Rockchip's drivers/power/pmic/pmic_rk808.c:
6453c5a92SJacob Chen  * Copyright (C) 2012 rockchips
7453c5a92SJacob Chen  * zyw <zyw@rock-chips.com>
8453c5a92SJacob Chen  *
9453c5a92SJacob Chen  * SPDX-License-Identifier:	GPL-2.0+
10453c5a92SJacob Chen  */
11453c5a92SJacob Chen 
12453c5a92SJacob Chen #include <common.h>
13453c5a92SJacob Chen #include <dm.h>
14453c5a92SJacob Chen #include <errno.h>
15b509cd39SJonas Karlman #include <log.h>
16b509cd39SJonas Karlman #include <linux/delay.h>
17453c5a92SJacob Chen #include <power/rk8xx_pmic.h>
18453c5a92SJacob Chen #include <power/pmic.h>
19453c5a92SJacob Chen #include <power/regulator.h>
20453c5a92SJacob Chen 
21453c5a92SJacob Chen #ifndef CONFIG_SPL_BUILD
22453c5a92SJacob Chen #define ENABLE_DRIVER
23453c5a92SJacob Chen #endif
24453c5a92SJacob Chen 
2504d4208bSJoseph Chen /* Not used or exisit register and configure */
2604d4208bSJoseph Chen #define NA			-1
2704d4208bSJoseph Chen 
28453c5a92SJacob Chen /* Field Definitions */
29453c5a92SJacob Chen #define RK808_BUCK_VSEL_MASK	0x3f
30453c5a92SJacob Chen #define RK808_BUCK4_VSEL_MASK	0xf
31453c5a92SJacob Chen #define RK808_LDO_VSEL_MASK	0x1f
32453c5a92SJacob Chen 
33453c5a92SJacob Chen #define RK818_BUCK_VSEL_MASK		0x3f
34453c5a92SJacob Chen #define RK818_BUCK4_VSEL_MASK		0x1f
35453c5a92SJacob Chen #define RK818_LDO_VSEL_MASK		0x1f
36453c5a92SJacob Chen #define RK818_LDO3_ON_VSEL_MASK	0xf
37453c5a92SJacob Chen #define RK818_BOOST_ON_VSEL_MASK	0xe0
38ad98f882SWadim Egorov #define RK818_USB_ILIM_SEL_MASK		0x0f
39ad98f882SWadim Egorov #define RK818_USB_CHG_SD_VSEL_MASK	0x70
40ad98f882SWadim Egorov 
411b6b965cSJoseph Chen /* RK809 BUCK5 */
421b6b965cSJoseph Chen #define RK809_BUCK5_CONFIG(n)		(0xde + (n) * 1)
431b6b965cSJoseph Chen #define RK809_BUCK5_VSEL_MASK		0x07
441b6b965cSJoseph Chen 
457f18d96cSJoseph Chen /* RK817 BUCK */
467f18d96cSJoseph Chen #define RK817_BUCK_ON_VSEL(n)		(0xbb + 3 * (n - 1))
477f18d96cSJoseph Chen #define RK817_BUCK_SLP_VSEL(n)		(0xbc + 3 * (n - 1))
487f18d96cSJoseph Chen #define RK817_BUCK_VSEL_MASK		0x7f
49868bdcf3SJoseph Chen #define RK817_BUCK_CONFIG(i)		(0xba + (i) * 3)
507f18d96cSJoseph Chen 
517f18d96cSJoseph Chen /* RK817 LDO */
527f18d96cSJoseph Chen #define RK817_LDO_ON_VSEL(n)		(0xcc + 2 * (n - 1))
537f18d96cSJoseph Chen #define RK817_LDO_SLP_VSEL(n)		(0xcd + 2 * (n - 1))
547f18d96cSJoseph Chen #define RK817_LDO_VSEL_MASK		0x7f
557f18d96cSJoseph Chen 
567f18d96cSJoseph Chen /* RK817 ENABLE */
577f18d96cSJoseph Chen #define RK817_POWER_EN(n)		(0xb1 + (n))
587f18d96cSJoseph Chen #define RK817_POWER_SLP_EN(n)		(0xb5 + (n))
597f18d96cSJoseph Chen 
60*c8147680SShengfei Xu /* RK817 BOOST */
61*c8147680SShengfei Xu #define RK817_BOOST_OTG_CONFIG0		(0xde)
62*c8147680SShengfei Xu #define RK817_BOOST_CONFIG1		(0xdf)
63*c8147680SShengfei Xu #define RK817_BOOST_VSEL_MASK		0x07
64*c8147680SShengfei Xu 
65868bdcf3SJoseph Chen /*
66868bdcf3SJoseph Chen  * Ramp delay
67868bdcf3SJoseph Chen  */
68868bdcf3SJoseph Chen #define RK805_RAMP_RATE_OFFSET		3
69868bdcf3SJoseph Chen #define RK805_RAMP_RATE_MASK		(3 << RK805_RAMP_RATE_OFFSET)
70868bdcf3SJoseph Chen #define RK805_RAMP_RATE_3MV_PER_US	(0 << RK805_RAMP_RATE_OFFSET)
71868bdcf3SJoseph Chen #define RK805_RAMP_RATE_6MV_PER_US	(1 << RK805_RAMP_RATE_OFFSET)
72868bdcf3SJoseph Chen #define RK805_RAMP_RATE_12_5MV_PER_US	(2 << RK805_RAMP_RATE_OFFSET)
73868bdcf3SJoseph Chen #define RK805_RAMP_RATE_25MV_PER_US	(3 << RK805_RAMP_RATE_OFFSET)
74868bdcf3SJoseph Chen 
75868bdcf3SJoseph Chen #define RK808_RAMP_RATE_OFFSET		3
76868bdcf3SJoseph Chen #define RK808_RAMP_RATE_MASK		(3 << RK808_RAMP_RATE_OFFSET)
77868bdcf3SJoseph Chen #define RK808_RAMP_RATE_2MV_PER_US	(0 << RK808_RAMP_RATE_OFFSET)
78868bdcf3SJoseph Chen #define RK808_RAMP_RATE_4MV_PER_US	(1 << RK808_RAMP_RATE_OFFSET)
79868bdcf3SJoseph Chen #define RK808_RAMP_RATE_6MV_PER_US	(2 << RK808_RAMP_RATE_OFFSET)
80868bdcf3SJoseph Chen #define RK808_RAMP_RATE_10MV_PER_US	(3 << RK808_RAMP_RATE_OFFSET)
81868bdcf3SJoseph Chen 
82868bdcf3SJoseph Chen #define RK817_RAMP_RATE_OFFSET		6
83868bdcf3SJoseph Chen #define RK817_RAMP_RATE_MASK		(0x3 << RK817_RAMP_RATE_OFFSET)
84868bdcf3SJoseph Chen #define RK817_RAMP_RATE_3MV_PER_US	(0x0 << RK817_RAMP_RATE_OFFSET)
85868bdcf3SJoseph Chen #define RK817_RAMP_RATE_6_3MV_PER_US	(0x1 << RK817_RAMP_RATE_OFFSET)
86868bdcf3SJoseph Chen #define RK817_RAMP_RATE_12_5MV_PER_US	(0x2 << RK817_RAMP_RATE_OFFSET)
87868bdcf3SJoseph Chen #define RK817_RAMP_RATE_25MV_PER_US	(0x3 << RK817_RAMP_RATE_OFFSET)
88868bdcf3SJoseph Chen 
89453c5a92SJacob Chen struct rk8xx_reg_info {
90453c5a92SJacob Chen 	uint min_uv;
91453c5a92SJacob Chen 	uint step_uv;
927f18d96cSJoseph Chen 	u8 vsel_reg;
937f18d96cSJoseph Chen 	u8 vsel_sleep_reg;
94868bdcf3SJoseph Chen 	u8 config_reg;
95453c5a92SJacob Chen 	u8 vsel_mask;
967f18d96cSJoseph Chen 	u8 min_sel;
973fe21f02SJoseph Chen 	/* only for buck now */
983fe21f02SJoseph Chen 	u8 max_sel;
993fe21f02SJoseph Chen 	u8 range_num;
100453c5a92SJacob Chen };
101453c5a92SJacob Chen 
102ef9c5d10Sshengfei Xu static const struct rk8xx_reg_info rk806_buck[] = {
103ef9c5d10Sshengfei Xu 	/* buck 1 */
104ef9c5d10Sshengfei Xu 	{  500000,   6250, RK806_BUCK_ON_VSEL(1), RK806_BUCK_SLP_VSEL(1), RK806_BUCK_CONFIG(1), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3},
105ef9c5d10Sshengfei Xu 	{  1500000, 25000, RK806_BUCK_ON_VSEL(1), RK806_BUCK_SLP_VSEL(1), RK806_BUCK_CONFIG(1), RK806_BUCK_VSEL_MASK, 0xa0, 0xec, 3},
106ef9c5d10Sshengfei Xu 	{  3400000,     0, RK806_BUCK_ON_VSEL(1), RK806_BUCK_SLP_VSEL(1), RK806_BUCK_CONFIG(1), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3},
107ef9c5d10Sshengfei Xu 	/* buck 2 */
108ef9c5d10Sshengfei Xu 	{  500000,   6250, RK806_BUCK_ON_VSEL(2), RK806_BUCK_SLP_VSEL(2), RK806_BUCK_CONFIG(2), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3},
109ef9c5d10Sshengfei Xu 	{  1500000, 25000, RK806_BUCK_ON_VSEL(2), RK806_BUCK_SLP_VSEL(2), RK806_BUCK_CONFIG(2), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3},
110ef9c5d10Sshengfei Xu 	{  3400000,     0, RK806_BUCK_ON_VSEL(2), RK806_BUCK_SLP_VSEL(2), RK806_BUCK_CONFIG(2), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3},
111ef9c5d10Sshengfei Xu 	/* buck 3 */
112ef9c5d10Sshengfei Xu 	{  500000,   6250, RK806_BUCK_ON_VSEL(3), RK806_BUCK_SLP_VSEL(3), RK806_BUCK_CONFIG(3), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3},
113ef9c5d10Sshengfei Xu 	{  1500000, 25000, RK806_BUCK_ON_VSEL(3), RK806_BUCK_SLP_VSEL(3), RK806_BUCK_CONFIG(3), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3},
114ef9c5d10Sshengfei Xu 	{  3400000,     0, RK806_BUCK_ON_VSEL(3), RK806_BUCK_SLP_VSEL(3), RK806_BUCK_CONFIG(3), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3},
115ef9c5d10Sshengfei Xu 	/* buck 4 */
116ef9c5d10Sshengfei Xu 	{  500000,   6250, RK806_BUCK_ON_VSEL(4), RK806_BUCK_SLP_VSEL(4), RK806_BUCK_CONFIG(4), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3},
117ef9c5d10Sshengfei Xu 	{  1500000, 25000, RK806_BUCK_ON_VSEL(4), RK806_BUCK_SLP_VSEL(4), RK806_BUCK_CONFIG(4), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3},
118ef9c5d10Sshengfei Xu 	{  3400000,     0, RK806_BUCK_ON_VSEL(4), RK806_BUCK_SLP_VSEL(4), RK806_BUCK_CONFIG(4), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3},
119ef9c5d10Sshengfei Xu 	/* buck 5 */
120ef9c5d10Sshengfei Xu 	{  500000,   6250, RK806_BUCK_ON_VSEL(5), RK806_BUCK_SLP_VSEL(5), RK806_BUCK_CONFIG(5), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3},
121ef9c5d10Sshengfei Xu 	{  1500000, 25000, RK806_BUCK_ON_VSEL(5), RK806_BUCK_SLP_VSEL(5), RK806_BUCK_CONFIG(5), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3},
122ef9c5d10Sshengfei Xu 	{  3400000,     0, RK806_BUCK_ON_VSEL(5), RK806_BUCK_SLP_VSEL(5), RK806_BUCK_CONFIG(5), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3},
123ef9c5d10Sshengfei Xu 	/* buck 6 */
124ef9c5d10Sshengfei Xu 	{  500000,   6250, RK806_BUCK_ON_VSEL(6), RK806_BUCK_SLP_VSEL(6), RK806_BUCK_CONFIG(6), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3},
125ef9c5d10Sshengfei Xu 	{  1500000, 25000, RK806_BUCK_ON_VSEL(6), RK806_BUCK_SLP_VSEL(6), RK806_BUCK_CONFIG(6), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3},
126ef9c5d10Sshengfei Xu 	{  3400000,     0, RK806_BUCK_ON_VSEL(6), RK806_BUCK_SLP_VSEL(6), RK806_BUCK_CONFIG(6), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3},
127ef9c5d10Sshengfei Xu 	/* buck 7 */
128ef9c5d10Sshengfei Xu 	{  500000,   6250, RK806_BUCK_ON_VSEL(7), RK806_BUCK_SLP_VSEL(7), RK806_BUCK_CONFIG(7), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3},
129ef9c5d10Sshengfei Xu 	{  1500000, 25000, RK806_BUCK_ON_VSEL(7), RK806_BUCK_SLP_VSEL(7), RK806_BUCK_CONFIG(7), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3},
130ef9c5d10Sshengfei Xu 	{  3400000,     0, RK806_BUCK_ON_VSEL(7), RK806_BUCK_SLP_VSEL(7), RK806_BUCK_CONFIG(7), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3},
131ef9c5d10Sshengfei Xu 	/* buck 8 */
132ef9c5d10Sshengfei Xu 	{  500000,   6250, RK806_BUCK_ON_VSEL(8), RK806_BUCK_SLP_VSEL(8), RK806_BUCK_CONFIG(8), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3},
133ef9c5d10Sshengfei Xu 	{  1500000, 25000, RK806_BUCK_ON_VSEL(8), RK806_BUCK_SLP_VSEL(8), RK806_BUCK_CONFIG(8), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3},
134ef9c5d10Sshengfei Xu 	{  3400000,     0, RK806_BUCK_ON_VSEL(8), RK806_BUCK_SLP_VSEL(8), RK806_BUCK_CONFIG(8), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3},
135ef9c5d10Sshengfei Xu 	/* buck 9 */
136ef9c5d10Sshengfei Xu 	{  500000,   6250, RK806_BUCK_ON_VSEL(9), RK806_BUCK_SLP_VSEL(9), RK806_BUCK_CONFIG(9), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3},
137ef9c5d10Sshengfei Xu 	{  1500000, 25000, RK806_BUCK_ON_VSEL(9), RK806_BUCK_SLP_VSEL(9), RK806_BUCK_CONFIG(9), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3},
138ef9c5d10Sshengfei Xu 	{  3400000,     0, RK806_BUCK_ON_VSEL(9), RK806_BUCK_SLP_VSEL(9), RK806_BUCK_CONFIG(9), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3},
139ef9c5d10Sshengfei Xu 	/* buck 10 */
140ef9c5d10Sshengfei Xu 	{  500000,   6250, RK806_BUCK_ON_VSEL(10), RK806_BUCK_SLP_VSEL(10), RK806_BUCK_CONFIG(10), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3},
141ef9c5d10Sshengfei Xu 	{  1500000, 25000, RK806_BUCK_ON_VSEL(10), RK806_BUCK_SLP_VSEL(10), RK806_BUCK_CONFIG(10), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3},
142ef9c5d10Sshengfei Xu 	{  3400000,     0, RK806_BUCK_ON_VSEL(10), RK806_BUCK_SLP_VSEL(10), RK806_BUCK_CONFIG(10), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3},
143ef9c5d10Sshengfei Xu };
144ef9c5d10Sshengfei Xu 
145ef9c5d10Sshengfei Xu static const struct rk8xx_reg_info rk806_nldo[] = {
146ef9c5d10Sshengfei Xu 	/* nldo1 */
147ef9c5d10Sshengfei Xu 	{  500000, 12500, RK806_NLDO_ON_VSEL(1), RK806_NLDO_SLP_VSEL(1), NA, RK806_NLDO_VSEL_MASK, 0x00, },
148ef9c5d10Sshengfei Xu 	{  3400000,    0, RK806_NLDO_ON_VSEL(1), RK806_NLDO_SLP_VSEL(1), NA, RK806_NLDO_VSEL_MASK, 0xE8, },
149ef9c5d10Sshengfei Xu 	/* nldo2 */
150ef9c5d10Sshengfei Xu 	{  500000, 12500, RK806_NLDO_ON_VSEL(2), RK806_NLDO_SLP_VSEL(2), NA, RK806_NLDO_VSEL_MASK, 0x00, },
151ef9c5d10Sshengfei Xu 	{  3400000,    0, RK806_NLDO_ON_VSEL(2), RK806_NLDO_SLP_VSEL(2), NA, RK806_NLDO_VSEL_MASK, 0xE8, },
152ef9c5d10Sshengfei Xu 	/* nldo3 */
153ef9c5d10Sshengfei Xu 	{  500000, 12500, RK806_NLDO_ON_VSEL(3), RK806_NLDO_SLP_VSEL(3), NA, RK806_NLDO_VSEL_MASK, 0x00, },
154ef9c5d10Sshengfei Xu 	{  3400000,    0, RK806_NLDO_ON_VSEL(3), RK806_NLDO_SLP_VSEL(3), NA, RK806_NLDO_VSEL_MASK, 0xE8, },
155ef9c5d10Sshengfei Xu 	/* nldo4 */
156ef9c5d10Sshengfei Xu 	{  500000, 12500, RK806_NLDO_ON_VSEL(4), RK806_NLDO_SLP_VSEL(4), NA, RK806_NLDO_VSEL_MASK, 0x00, },
157ef9c5d10Sshengfei Xu 	{  3400000,    0, RK806_NLDO_ON_VSEL(4), RK806_NLDO_SLP_VSEL(4), NA, RK806_NLDO_VSEL_MASK, 0xE8, },
158ef9c5d10Sshengfei Xu 	/* nldo5 */
159ef9c5d10Sshengfei Xu 	{  500000, 12500, RK806_NLDO_ON_VSEL(5), RK806_NLDO_SLP_VSEL(5), NA, RK806_NLDO_VSEL_MASK, 0x00, },
160ef9c5d10Sshengfei Xu 	{  3400000,    0, RK806_NLDO_ON_VSEL(5), RK806_NLDO_SLP_VSEL(5), NA, RK806_NLDO_VSEL_MASK, 0xE8, },
161ef9c5d10Sshengfei Xu };
162ef9c5d10Sshengfei Xu 
163ef9c5d10Sshengfei Xu static const struct rk8xx_reg_info rk806_pldo[] = {
164ef9c5d10Sshengfei Xu 	/* pldo1 */
165ef9c5d10Sshengfei Xu 	{  500000, 12500, RK806_PLDO_ON_VSEL(1), RK806_PLDO_SLP_VSEL(1), NA, RK806_PLDO_VSEL_MASK, 0x00, },
166ef9c5d10Sshengfei Xu 	{  3400000,    0, RK806_PLDO_ON_VSEL(1), RK806_PLDO_SLP_VSEL(1), NA, RK806_PLDO_VSEL_MASK, 0xE8, },
167ef9c5d10Sshengfei Xu 	/* pldo2 */
168ef9c5d10Sshengfei Xu 	{  500000, 12500, RK806_PLDO_ON_VSEL(2), RK806_PLDO_SLP_VSEL(2), NA, RK806_PLDO_VSEL_MASK, 0x00, },
169ef9c5d10Sshengfei Xu 	{  3400000,    0, RK806_PLDO_ON_VSEL(2), RK806_PLDO_SLP_VSEL(2), NA, RK806_PLDO_VSEL_MASK, 0xE8, },
170ef9c5d10Sshengfei Xu 	/* pldo3 */
171ef9c5d10Sshengfei Xu 	{  500000, 12500, RK806_PLDO_ON_VSEL(3), RK806_PLDO_SLP_VSEL(3), NA, RK806_PLDO_VSEL_MASK, 0x00, },
172ef9c5d10Sshengfei Xu 	{  3400000,    0, RK806_PLDO_ON_VSEL(3), RK806_PLDO_SLP_VSEL(3), NA, RK806_PLDO_VSEL_MASK, 0xE8, },
173ef9c5d10Sshengfei Xu 	/* pldo4 */
174ef9c5d10Sshengfei Xu 	{  500000, 12500, RK806_PLDO_ON_VSEL(4), RK806_PLDO_SLP_VSEL(4), NA, RK806_PLDO_VSEL_MASK, 0x00, },
175ef9c5d10Sshengfei Xu 	{  3400000,    0, RK806_PLDO_ON_VSEL(4), RK806_PLDO_SLP_VSEL(4), NA, RK806_PLDO_VSEL_MASK, 0xE8, },
176ef9c5d10Sshengfei Xu 	/* pldo5 */
177ef9c5d10Sshengfei Xu 	{  500000, 12500, RK806_PLDO_ON_VSEL(5), RK806_PLDO_SLP_VSEL(5), NA, RK806_PLDO_VSEL_MASK, 0x00, },
178ef9c5d10Sshengfei Xu 	{  3400000,    0, RK806_PLDO_ON_VSEL(5), RK806_PLDO_SLP_VSEL(5), NA, RK806_PLDO_VSEL_MASK, 0xE8, },
179ef9c5d10Sshengfei Xu 	/* pldo6 */
180ef9c5d10Sshengfei Xu 	{  500000, 12500, RK806_PLDO_ON_VSEL(6), RK806_PLDO_SLP_VSEL(6), NA, RK806_PLDO_VSEL_MASK, 0x00, },
181ef9c5d10Sshengfei Xu 	{  3400000,    0, RK806_PLDO_ON_VSEL(6), RK806_PLDO_SLP_VSEL(6), NA, RK806_PLDO_VSEL_MASK, 0xE8, },
182ef9c5d10Sshengfei Xu };
183ef9c5d10Sshengfei Xu 
184453c5a92SJacob Chen static const struct rk8xx_reg_info rk808_buck[] = {
1853fe21f02SJoseph Chen 	{ 712500,   12500, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, REG_BUCK1_CONFIG, RK808_BUCK_VSEL_MASK, 0x00, 0x3f, 1},
1863fe21f02SJoseph Chen 	{ 712500,   12500, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, REG_BUCK2_CONFIG, RK808_BUCK_VSEL_MASK, 0x00, 0x3f, 1},
1873fe21f02SJoseph Chen 	{ NA,       NA,    NA,		      NA,		  REG_BUCK3_CONFIG, NA,                   NA,   NA,   1},
1883fe21f02SJoseph Chen 	{ 1800000, 100000, REG_BUCK4_ON_VSEL, REG_BUCK4_SLP_VSEL, REG_BUCK4_CONFIG, RK808_BUCK4_VSEL_MASK,0x00, 0x0f, 1},
189453c5a92SJacob Chen };
190453c5a92SJacob Chen 
1915e1bceeaSElaine Zhang static const struct rk8xx_reg_info rk816_buck[] = {
1925e1bceeaSElaine Zhang 	/* buck 1 */
1933fe21f02SJoseph Chen 	{  712500,  12500, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, REG_BUCK1_CONFIG, RK818_BUCK_VSEL_MASK, 0x00, 0x3b, 3},
1943fe21f02SJoseph Chen 	{ 1800000, 200000, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, REG_BUCK1_CONFIG, RK818_BUCK_VSEL_MASK, 0x3c, 0x3e, 3},
1953fe21f02SJoseph Chen 	{ 2300000,      0, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, REG_BUCK1_CONFIG, RK818_BUCK_VSEL_MASK, 0x3f, 0x3f, 3},
1965e1bceeaSElaine Zhang 	/* buck 2 */
1973fe21f02SJoseph Chen 	{  712500,  12500, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, REG_BUCK2_CONFIG, RK818_BUCK_VSEL_MASK, 0x00, 0x3b, 3},
1983fe21f02SJoseph Chen 	{ 1800000, 200000, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, REG_BUCK2_CONFIG, RK818_BUCK_VSEL_MASK, 0x3c, 0x3e, 3},
1993fe21f02SJoseph Chen 	{ 2300000,      0, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, REG_BUCK2_CONFIG, RK818_BUCK_VSEL_MASK, 0x3f, 0x3f, 3},
2005e1bceeaSElaine Zhang 	/* buck 3 */
2013fe21f02SJoseph Chen 	{  NA,     NA,     NA,		      NA,		  REG_BUCK3_CONFIG, NA,                   NA,   NA,   1},
2025e1bceeaSElaine Zhang 	/* buck 4 */
2033fe21f02SJoseph Chen 	{  800000, 100000, REG_BUCK4_ON_VSEL, REG_BUCK4_SLP_VSEL, REG_BUCK4_CONFIG, RK818_BUCK4_VSEL_MASK,0x00, 0x1b, 1},
2045e1bceeaSElaine Zhang };
2055e1bceeaSElaine Zhang 
2061b6b965cSJoseph Chen static const struct rk8xx_reg_info rk809_buck5[] = {
2071b6b965cSJoseph Chen 	/* buck 5 */
2083fe21f02SJoseph Chen 	{ 1500000,	0, RK809_BUCK5_CONFIG(0), RK809_BUCK5_CONFIG(1), NA, RK809_BUCK5_VSEL_MASK, 0x00, 0x00, 4},
2093fe21f02SJoseph Chen 	{ 1800000, 200000, RK809_BUCK5_CONFIG(0), RK809_BUCK5_CONFIG(1), NA, RK809_BUCK5_VSEL_MASK, 0x01, 0x03, 4},
2103fe21f02SJoseph Chen 	{ 2800000, 200000, RK809_BUCK5_CONFIG(0), RK809_BUCK5_CONFIG(1), NA, RK809_BUCK5_VSEL_MASK, 0x04, 0x05, 4},
2113fe21f02SJoseph Chen 	{ 3300000, 300000, RK809_BUCK5_CONFIG(0), RK809_BUCK5_CONFIG(1), NA, RK809_BUCK5_VSEL_MASK, 0x06, 0x07, 4},
2121b6b965cSJoseph Chen };
2131b6b965cSJoseph Chen 
2147f18d96cSJoseph Chen static const struct rk8xx_reg_info rk817_buck[] = {
2157f18d96cSJoseph Chen 	/* buck 1 */
2163fe21f02SJoseph Chen 	{  500000,  12500, RK817_BUCK_ON_VSEL(1), RK817_BUCK_SLP_VSEL(1), RK817_BUCK_CONFIG(1), RK817_BUCK_VSEL_MASK, 0x00, 0x4f, 3},
2173fe21f02SJoseph Chen 	{ 1500000, 100000, RK817_BUCK_ON_VSEL(1), RK817_BUCK_SLP_VSEL(1), RK817_BUCK_CONFIG(1), RK817_BUCK_VSEL_MASK, 0x50, 0x58, 3},
2183fe21f02SJoseph Chen 	{ 2400000,	0, RK817_BUCK_ON_VSEL(1), RK817_BUCK_SLP_VSEL(1), RK817_BUCK_CONFIG(1), RK817_BUCK_VSEL_MASK, 0x59, 0x59, 3},
2197f18d96cSJoseph Chen 	/* buck 2 */
2203fe21f02SJoseph Chen 	{  500000,  12500, RK817_BUCK_ON_VSEL(2), RK817_BUCK_SLP_VSEL(2), RK817_BUCK_CONFIG(2), RK817_BUCK_VSEL_MASK, 0x00, 0x4f, 3},
2213fe21f02SJoseph Chen 	{ 1500000, 100000, RK817_BUCK_ON_VSEL(2), RK817_BUCK_SLP_VSEL(2), RK817_BUCK_CONFIG(2), RK817_BUCK_VSEL_MASK, 0x50, 0x58, 3},
2223fe21f02SJoseph Chen 	{ 2400000,	0, RK817_BUCK_ON_VSEL(2), RK817_BUCK_SLP_VSEL(2), RK817_BUCK_CONFIG(2), RK817_BUCK_VSEL_MASK, 0x59, 0x59, 3},
2237f18d96cSJoseph Chen 	/* buck 3 */
2243fe21f02SJoseph Chen 	{  500000,  12500, RK817_BUCK_ON_VSEL(3), RK817_BUCK_SLP_VSEL(3), RK817_BUCK_CONFIG(3), RK817_BUCK_VSEL_MASK, 0x00, 0x4f, 3},
2253fe21f02SJoseph Chen 	{ 1500000, 100000, RK817_BUCK_ON_VSEL(3), RK817_BUCK_SLP_VSEL(3), RK817_BUCK_CONFIG(3), RK817_BUCK_VSEL_MASK, 0x50, 0x58, 3},
2263fe21f02SJoseph Chen 	{ 2400000,	0, RK817_BUCK_ON_VSEL(3), RK817_BUCK_SLP_VSEL(3), RK817_BUCK_CONFIG(3), RK817_BUCK_VSEL_MASK, 0x59, 0x59, 3},
2277f18d96cSJoseph Chen 	/* buck 4 */
2283fe21f02SJoseph Chen 	{  500000,  12500, RK817_BUCK_ON_VSEL(4), RK817_BUCK_SLP_VSEL(4), RK817_BUCK_CONFIG(4), RK817_BUCK_VSEL_MASK, 0x00, 0x4f, 3},
2293fe21f02SJoseph Chen 	{ 1500000, 100000, RK817_BUCK_ON_VSEL(4), RK817_BUCK_SLP_VSEL(4), RK817_BUCK_CONFIG(4), RK817_BUCK_VSEL_MASK, 0x50, 0x62, 3},
2303fe21f02SJoseph Chen 	{ 3400000,	0, RK817_BUCK_ON_VSEL(4), RK817_BUCK_SLP_VSEL(4), RK817_BUCK_CONFIG(4), RK817_BUCK_VSEL_MASK, 0x63, 0x63, 3},
2317f18d96cSJoseph Chen };
2327f18d96cSJoseph Chen 
2338926c2f5SWadim Egorov static const struct rk8xx_reg_info rk818_buck[] = {
2343fe21f02SJoseph Chen 	{ 712500,   12500, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, REG_BUCK1_CONFIG, RK818_BUCK_VSEL_MASK, 0x00, 0x3f, 1},
2353fe21f02SJoseph Chen 	{ 712500,   12500, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, REG_BUCK2_CONFIG, RK818_BUCK_VSEL_MASK, 0x00, 0x3f, 1},
2363fe21f02SJoseph Chen 	{ NA,       NA,    NA,		      NA,		  REG_BUCK3_CONFIG, NA,                   NA,   NA,   1},
2373fe21f02SJoseph Chen 	{ 1800000, 100000, REG_BUCK4_ON_VSEL, REG_BUCK4_SLP_VSEL, REG_BUCK4_CONFIG, RK818_BUCK4_VSEL_MASK,0x00, 0x10, 1},
2388926c2f5SWadim Egorov };
2398926c2f5SWadim Egorov 
2408926c2f5SWadim Egorov #ifdef ENABLE_DRIVER
241453c5a92SJacob Chen static const struct rk8xx_reg_info rk808_ldo[] = {
24204d4208bSJoseph Chen 	{ 1800000, 100000, REG_LDO1_ON_VSEL, REG_LDO1_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
24304d4208bSJoseph Chen 	{ 1800000, 100000, REG_LDO2_ON_VSEL, REG_LDO2_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
24404d4208bSJoseph Chen 	{  800000, 100000, REG_LDO3_ON_VSEL, REG_LDO3_SLP_VSEL, NA, RK808_BUCK4_VSEL_MASK, },
24504d4208bSJoseph Chen 	{ 1800000, 100000, REG_LDO4_ON_VSEL, REG_LDO4_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
24604d4208bSJoseph Chen 	{ 1800000, 100000, REG_LDO5_ON_VSEL, REG_LDO5_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
24704d4208bSJoseph Chen 	{  800000, 100000, REG_LDO6_ON_VSEL, REG_LDO6_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
24804d4208bSJoseph Chen 	{  800000, 100000, REG_LDO7_ON_VSEL, REG_LDO7_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
24904d4208bSJoseph Chen 	{ 1800000, 100000, REG_LDO8_ON_VSEL, REG_LDO8_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
250453c5a92SJacob Chen };
251453c5a92SJacob Chen 
2525e1bceeaSElaine Zhang static const struct rk8xx_reg_info rk816_ldo[] = {
25304d4208bSJoseph Chen 	{ 800000, 100000, REG_LDO1_ON_VSEL, REG_LDO1_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
25404d4208bSJoseph Chen 	{ 800000, 100000, REG_LDO2_ON_VSEL, REG_LDO2_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
25504d4208bSJoseph Chen 	{ 800000, 100000, REG_LDO3_ON_VSEL, REG_LDO3_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
25604d4208bSJoseph Chen 	{ 800000, 100000, REG_LDO4_ON_VSEL, REG_LDO4_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
25704d4208bSJoseph Chen 	{ 800000, 100000, REG_LDO5_ON_VSEL, REG_LDO5_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
25804d4208bSJoseph Chen 	{ 800000, 100000, REG_LDO6_ON_VSEL, REG_LDO6_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
2595e1bceeaSElaine Zhang };
2605e1bceeaSElaine Zhang 
2617f18d96cSJoseph Chen static const struct rk8xx_reg_info rk817_ldo[] = {
2627f18d96cSJoseph Chen 	/* ldo1 */
26304d4208bSJoseph Chen 	{  600000, 25000, RK817_LDO_ON_VSEL(1), RK817_LDO_SLP_VSEL(1), NA, RK817_LDO_VSEL_MASK, 0x00, },
26404d4208bSJoseph Chen 	{ 3400000,     0, RK817_LDO_ON_VSEL(1), RK817_LDO_SLP_VSEL(1), NA, RK817_LDO_VSEL_MASK, 0x70, },
2657f18d96cSJoseph Chen 	/* ldo2 */
26604d4208bSJoseph Chen 	{  600000, 25000, RK817_LDO_ON_VSEL(2), RK817_LDO_SLP_VSEL(2), NA, RK817_LDO_VSEL_MASK, 0x00, },
26704d4208bSJoseph Chen 	{ 3400000,     0, RK817_LDO_ON_VSEL(2), RK817_LDO_SLP_VSEL(2), NA, RK817_LDO_VSEL_MASK, 0x70, },
2687f18d96cSJoseph Chen 	/* ldo3 */
26904d4208bSJoseph Chen 	{  600000, 25000, RK817_LDO_ON_VSEL(3), RK817_LDO_SLP_VSEL(3), NA, RK817_LDO_VSEL_MASK, 0x00, },
27004d4208bSJoseph Chen 	{ 3400000,     0, RK817_LDO_ON_VSEL(3), RK817_LDO_SLP_VSEL(3), NA, RK817_LDO_VSEL_MASK, 0x70, },
2717f18d96cSJoseph Chen 	/* ldo4 */
27204d4208bSJoseph Chen 	{  600000, 25000, RK817_LDO_ON_VSEL(4), RK817_LDO_SLP_VSEL(4), NA, RK817_LDO_VSEL_MASK, 0x00, },
27304d4208bSJoseph Chen 	{ 3400000,     0, RK817_LDO_ON_VSEL(4), RK817_LDO_SLP_VSEL(4), NA, RK817_LDO_VSEL_MASK, 0x70, },
2747f18d96cSJoseph Chen 	/* ldo5 */
27504d4208bSJoseph Chen 	{  600000, 25000, RK817_LDO_ON_VSEL(5), RK817_LDO_SLP_VSEL(5), NA, RK817_LDO_VSEL_MASK, 0x00, },
27604d4208bSJoseph Chen 	{ 3400000,     0, RK817_LDO_ON_VSEL(5), RK817_LDO_SLP_VSEL(5), NA, RK817_LDO_VSEL_MASK, 0x70, },
2777f18d96cSJoseph Chen 	/* ldo6 */
27804d4208bSJoseph Chen 	{  600000, 25000, RK817_LDO_ON_VSEL(6), RK817_LDO_SLP_VSEL(6), NA, RK817_LDO_VSEL_MASK, 0x00, },
27904d4208bSJoseph Chen 	{ 3400000,     0, RK817_LDO_ON_VSEL(6), RK817_LDO_SLP_VSEL(6), NA, RK817_LDO_VSEL_MASK, 0x70, },
2807f18d96cSJoseph Chen 	/* ldo7 */
28104d4208bSJoseph Chen 	{  600000, 25000, RK817_LDO_ON_VSEL(7), RK817_LDO_SLP_VSEL(7), NA, RK817_LDO_VSEL_MASK, 0x00, },
28204d4208bSJoseph Chen 	{ 3400000,     0, RK817_LDO_ON_VSEL(7), RK817_LDO_SLP_VSEL(7), NA, RK817_LDO_VSEL_MASK, 0x70, },
2837f18d96cSJoseph Chen 	/* ldo8 */
28404d4208bSJoseph Chen 	{  600000, 25000, RK817_LDO_ON_VSEL(8), RK817_LDO_SLP_VSEL(8), NA, RK817_LDO_VSEL_MASK, 0x00, },
28504d4208bSJoseph Chen 	{ 3400000,     0, RK817_LDO_ON_VSEL(8), RK817_LDO_SLP_VSEL(8), NA, RK817_LDO_VSEL_MASK, 0x70, },
2867f18d96cSJoseph Chen 	/* ldo9 */
28704d4208bSJoseph Chen 	{  600000, 25000, RK817_LDO_ON_VSEL(9), RK817_LDO_SLP_VSEL(9), NA, RK817_LDO_VSEL_MASK, 0x00, },
28804d4208bSJoseph Chen 	{ 3400000,     0, RK817_LDO_ON_VSEL(9), RK817_LDO_SLP_VSEL(9), NA, RK817_LDO_VSEL_MASK, 0x70, },
2897f18d96cSJoseph Chen };
2907f18d96cSJoseph Chen 
291453c5a92SJacob Chen static const struct rk8xx_reg_info rk818_ldo[] = {
29204d4208bSJoseph Chen 	{ 1800000, 100000, REG_LDO1_ON_VSEL, REG_LDO1_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
29304d4208bSJoseph Chen 	{ 1800000, 100000, REG_LDO2_ON_VSEL, REG_LDO2_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
29404d4208bSJoseph Chen 	{  800000, 100000, REG_LDO3_ON_VSEL, REG_LDO3_SLP_VSEL, NA, RK818_LDO3_ON_VSEL_MASK, },
29504d4208bSJoseph Chen 	{ 1800000, 100000, REG_LDO4_ON_VSEL, REG_LDO4_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
29604d4208bSJoseph Chen 	{ 1800000, 100000, REG_LDO5_ON_VSEL, REG_LDO5_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
29704d4208bSJoseph Chen 	{  800000, 100000, REG_LDO6_ON_VSEL, REG_LDO6_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
29804d4208bSJoseph Chen 	{  800000, 100000, REG_LDO7_ON_VSEL, REG_LDO7_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
29904d4208bSJoseph Chen 	{ 1800000, 100000, REG_LDO8_ON_VSEL, REG_LDO8_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
300453c5a92SJacob Chen };
301*c8147680SShengfei Xu 
302*c8147680SShengfei Xu static const struct rk8xx_reg_info rk817_boost[] = {
303*c8147680SShengfei Xu 	/* boost */
304*c8147680SShengfei Xu 	{  4700000, 100, RK817_BOOST_OTG_CONFIG0, RK817_BOOST_CONFIG1, NA, RK817_BOOST_VSEL_MASK, 0x00, },
305*c8147680SShengfei Xu };
3068926c2f5SWadim Egorov #endif
307453c5a92SJacob Chen 
308ad98f882SWadim Egorov static const u16 rk818_chrg_cur_input_array[] = {
309ad98f882SWadim Egorov 	450, 800, 850, 1000, 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000
310ad98f882SWadim Egorov };
311ad98f882SWadim Egorov 
312ad98f882SWadim Egorov static const uint rk818_chrg_shutdown_vsel_array[] = {
313ad98f882SWadim Egorov 	2780000, 2850000, 2920000, 2990000, 3060000, 3130000, 3190000, 3260000
314ad98f882SWadim Egorov };
315ad98f882SWadim Egorov 
get_buck_reg(struct udevice * pmic,int num,int uvolt)316453c5a92SJacob Chen static const struct rk8xx_reg_info *get_buck_reg(struct udevice *pmic,
3175e1bceeaSElaine Zhang 						 int num, int uvolt)
318453c5a92SJacob Chen {
319453c5a92SJacob Chen 	struct rk8xx_priv *priv = dev_get_priv(pmic);
3205e1bceeaSElaine Zhang 
321453c5a92SJacob Chen 	switch (priv->variant) {
322ef9c5d10Sshengfei Xu 	case RK806_ID:
323ef9c5d10Sshengfei Xu 		switch (num) {
324ef9c5d10Sshengfei Xu 		case 0 ... 9:
325ef9c5d10Sshengfei Xu 			if (uvolt < 1500000)
326ef9c5d10Sshengfei Xu 				return &rk806_buck[num * 3 + 0];
327ef9c5d10Sshengfei Xu 			else if (uvolt < 3400000)
328ef9c5d10Sshengfei Xu 				return &rk806_buck[num * 3 + 1];
329ef9c5d10Sshengfei Xu 			else
330ef9c5d10Sshengfei Xu 				return &rk806_buck[num * 3 + 2];
331ef9c5d10Sshengfei Xu 		}
3324b6f5dc9SElaine Zhang 	case RK805_ID:
3335e1bceeaSElaine Zhang 	case RK816_ID:
3345e1bceeaSElaine Zhang 		switch (num) {
3355e1bceeaSElaine Zhang 		case 0:
3365e1bceeaSElaine Zhang 		case 1:
3375e1bceeaSElaine Zhang 			if (uvolt <= 1450000)
3385e1bceeaSElaine Zhang 				return &rk816_buck[num * 3 + 0];
3395e1bceeaSElaine Zhang 			else if (uvolt <= 2200000)
3405e1bceeaSElaine Zhang 				return &rk816_buck[num * 3 + 1];
3415e1bceeaSElaine Zhang 			else
3425e1bceeaSElaine Zhang 				return &rk816_buck[num * 3 + 2];
3435e1bceeaSElaine Zhang 		default:
3445e1bceeaSElaine Zhang 			return &rk816_buck[num + 4];
3455e1bceeaSElaine Zhang 		}
3467f18d96cSJoseph Chen 
3471b6b965cSJoseph Chen 	case RK809_ID:
3487f18d96cSJoseph Chen 	case RK817_ID:
3497f18d96cSJoseph Chen 		switch (num) {
3507f18d96cSJoseph Chen 		case 0 ... 2:
3517f18d96cSJoseph Chen 			if (uvolt < 1500000)
3527f18d96cSJoseph Chen 				return &rk817_buck[num * 3 + 0];
3537f18d96cSJoseph Chen 			else if (uvolt < 2400000)
3547f18d96cSJoseph Chen 				return &rk817_buck[num * 3 + 1];
3557f18d96cSJoseph Chen 			else
3567f18d96cSJoseph Chen 				return &rk817_buck[num * 3 + 2];
3571b6b965cSJoseph Chen 		case 3:
3587f18d96cSJoseph Chen 			if (uvolt < 1500000)
3597f18d96cSJoseph Chen 				return &rk817_buck[num * 3 + 0];
3607f18d96cSJoseph Chen 			else if (uvolt < 3400000)
3617f18d96cSJoseph Chen 				return &rk817_buck[num * 3 + 1];
3627f18d96cSJoseph Chen 			else
3637f18d96cSJoseph Chen 				return &rk817_buck[num * 3 + 2];
3641b6b965cSJoseph Chen 		/* BUCK5 for RK809 */
3651b6b965cSJoseph Chen 		default:
3661b6b965cSJoseph Chen 			if (uvolt < 1800000)
3671b6b965cSJoseph Chen 				return &rk809_buck5[0];
3681b6b965cSJoseph Chen 			else if (uvolt < 2800000)
3691b6b965cSJoseph Chen 				return &rk809_buck5[1];
3701b6b965cSJoseph Chen 			else if (uvolt < 3300000)
3711b6b965cSJoseph Chen 				return &rk809_buck5[2];
3721b6b965cSJoseph Chen 			else
3731b6b965cSJoseph Chen 				return &rk809_buck5[3];
3747f18d96cSJoseph Chen 		}
375453c5a92SJacob Chen 	case RK818_ID:
376453c5a92SJacob Chen 		return &rk818_buck[num];
377453c5a92SJacob Chen 	default:
378453c5a92SJacob Chen 		return &rk808_buck[num];
379453c5a92SJacob Chen 	}
380453c5a92SJacob Chen }
381453c5a92SJacob Chen 
_buck_set_value(struct udevice * pmic,int buck,int uvolt)382453c5a92SJacob Chen static int _buck_set_value(struct udevice *pmic, int buck, int uvolt)
383453c5a92SJacob Chen {
3845e1bceeaSElaine Zhang 	const struct rk8xx_reg_info *info = get_buck_reg(pmic, buck, uvolt);
3855e347befSElaine Zhang 	struct rk8xx_priv *priv = dev_get_priv(pmic);
386453c5a92SJacob Chen 	int mask = info->vsel_mask;
387453c5a92SJacob Chen 	int val;
388453c5a92SJacob Chen 
38904d4208bSJoseph Chen 	if (info->vsel_reg == NA)
390453c5a92SJacob Chen 		return -ENOSYS;
3917f18d96cSJoseph Chen 
3927f18d96cSJoseph Chen 	if (info->step_uv == 0)	/* Fixed voltage */
3937f18d96cSJoseph Chen 		val = info->min_sel;
3947f18d96cSJoseph Chen 	else
3957f18d96cSJoseph Chen 		val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel;
3967f18d96cSJoseph Chen 
3977f18d96cSJoseph Chen 	debug("%s: volt=%d, buck=%d, reg=0x%x, mask=0x%x, val=0x%x\n",
3987f18d96cSJoseph Chen 	      __func__, uvolt, buck + 1, info->vsel_reg, mask, val);
399453c5a92SJacob Chen 
4005e347befSElaine Zhang 	if (priv->variant == RK816_ID) {
4015e347befSElaine Zhang 		pmic_clrsetbits(pmic, info->vsel_reg, mask, val);
4025e347befSElaine Zhang 		return pmic_clrsetbits(pmic, RK816_REG_DCDC_EN2, 1 << 7, 1 << 7);
4035e347befSElaine Zhang 	} else {
404453c5a92SJacob Chen 		return pmic_clrsetbits(pmic, info->vsel_reg, mask, val);
405453c5a92SJacob Chen 	}
4065e347befSElaine Zhang }
407453c5a92SJacob Chen 
_buck_set_enable(struct udevice * pmic,int buck,bool enable)408453c5a92SJacob Chen static int _buck_set_enable(struct udevice *pmic, int buck, bool enable)
409453c5a92SJacob Chen {
4105e1bceeaSElaine Zhang 	uint mask, value, en_reg;
411453c5a92SJacob Chen 	int ret;
4125e1bceeaSElaine Zhang 	struct rk8xx_priv *priv = dev_get_priv(pmic);
413453c5a92SJacob Chen 
4145e1bceeaSElaine Zhang 	switch (priv->variant) {
415ef9c5d10Sshengfei Xu 	case RK806_ID:
416ef9c5d10Sshengfei Xu 		en_reg = RK806_POWER_EN(buck / 4);
417ef9c5d10Sshengfei Xu 		if (enable)
418ef9c5d10Sshengfei Xu 			value = ((1 << buck % 4) | (1 << (buck % 4 + 4)));
419ef9c5d10Sshengfei Xu 		else
420ef9c5d10Sshengfei Xu 			value = ((0 << buck % 4) | (1 << (buck % 4 + 4)));
421ef9c5d10Sshengfei Xu 
422ef9c5d10Sshengfei Xu 		ret = pmic_reg_write(pmic, en_reg, value);
423ef9c5d10Sshengfei Xu 		break;
4244b6f5dc9SElaine Zhang 	case RK805_ID:
4255e1bceeaSElaine Zhang 	case RK816_ID:
4265e1bceeaSElaine Zhang 		if (buck >= 4) {
4275e1bceeaSElaine Zhang 			buck -= 4;
4285e1bceeaSElaine Zhang 			en_reg = RK816_REG_DCDC_EN2;
4295e1bceeaSElaine Zhang 		} else {
4305e1bceeaSElaine Zhang 			en_reg = RK816_REG_DCDC_EN1;
4315e1bceeaSElaine Zhang 		}
4325e1bceeaSElaine Zhang 		if (enable)
4335e1bceeaSElaine Zhang 			value = ((1 << buck) | (1 << (buck + 4)));
4345e1bceeaSElaine Zhang 		else
4355e1bceeaSElaine Zhang 			value = ((0 << buck) | (1 << (buck + 4)));
4365e1bceeaSElaine Zhang 		ret = pmic_reg_write(pmic, en_reg, value);
4375e1bceeaSElaine Zhang 		break;
4385e1bceeaSElaine Zhang 
4395e1bceeaSElaine Zhang 	case RK808_ID:
4405e1bceeaSElaine Zhang 	case RK818_ID:
441453c5a92SJacob Chen 		mask = 1 << buck;
442453c5a92SJacob Chen 		if (enable) {
4435e1bceeaSElaine Zhang 			ret = pmic_clrsetbits(pmic, REG_DCDC_ILMAX,
4445e1bceeaSElaine Zhang 					      0, 3 << (buck * 2));
445453c5a92SJacob Chen 			if (ret)
446453c5a92SJacob Chen 				return ret;
447453c5a92SJacob Chen 		}
4485e1bceeaSElaine Zhang 		ret = pmic_clrsetbits(pmic, REG_DCDC_EN, mask,
4495e1bceeaSElaine Zhang 				      enable ? mask : 0);
4505e1bceeaSElaine Zhang 		break;
4511b6b965cSJoseph Chen 	case RK809_ID:
4527f18d96cSJoseph Chen 	case RK817_ID:
4531b6b965cSJoseph Chen 		if (buck < 4) {
4547f18d96cSJoseph Chen 			if (enable)
4557f18d96cSJoseph Chen 				value = ((1 << buck) | (1 << (buck + 4)));
4567f18d96cSJoseph Chen 			else
4577f18d96cSJoseph Chen 				value = ((0 << buck) | (1 << (buck + 4)));
4587f18d96cSJoseph Chen 			ret = pmic_reg_write(pmic, RK817_POWER_EN(0), value);
4591b6b965cSJoseph Chen 		/* BUCK5 for RK809 */
4601b6b965cSJoseph Chen 		} else {
4611b6b965cSJoseph Chen 			if (enable)
4621b6b965cSJoseph Chen 				value = ((1 << 1) | (1 << 5));
4631b6b965cSJoseph Chen 			else
4641b6b965cSJoseph Chen 				value = ((0 << 1) | (1 << 5));
4651b6b965cSJoseph Chen 			ret = pmic_reg_write(pmic, RK817_POWER_EN(3), value);
4661b6b965cSJoseph Chen 		}
4677f18d96cSJoseph Chen 		break;
4685e1bceeaSElaine Zhang 	default:
4695e1bceeaSElaine Zhang 		ret = -EINVAL;
4705e1bceeaSElaine Zhang 	}
471453c5a92SJacob Chen 
4725e1bceeaSElaine Zhang 	return ret;
473453c5a92SJacob Chen }
474453c5a92SJacob Chen 
47548e66864SKever Yang #ifdef ENABLE_DRIVER
_buck_set_suspend_value(struct udevice * pmic,int buck,int uvolt)47648e66864SKever Yang static int _buck_set_suspend_value(struct udevice *pmic, int buck, int uvolt)
47748e66864SKever Yang {
47848e66864SKever Yang 	const struct rk8xx_reg_info *info = get_buck_reg(pmic, buck, uvolt);
47948e66864SKever Yang 	int mask = info->vsel_mask;
48048e66864SKever Yang 	int val;
48148e66864SKever Yang 
48204d4208bSJoseph Chen 	if (info->vsel_sleep_reg == NA)
48348e66864SKever Yang 		return -ENOSYS;
4847f18d96cSJoseph Chen 
4857f18d96cSJoseph Chen 	if (info->step_uv == 0)
4867f18d96cSJoseph Chen 		val = info->min_sel;
4877f18d96cSJoseph Chen 	else
4887f18d96cSJoseph Chen 		val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel;
4897f18d96cSJoseph Chen 
4907f18d96cSJoseph Chen 	debug("%s: volt=%d, buck=%d, reg=0x%x, mask=0x%x, val=0x%x\n",
4917f18d96cSJoseph Chen 	      __func__, uvolt, buck + 1, info->vsel_sleep_reg, mask, val);
49248e66864SKever Yang 
49348e66864SKever Yang 	return pmic_clrsetbits(pmic, info->vsel_sleep_reg, mask, val);
49448e66864SKever Yang }
49548e66864SKever Yang 
_buck_get_enable(struct udevice * pmic,int buck)49648e66864SKever Yang static int _buck_get_enable(struct udevice *pmic, int buck)
49748e66864SKever Yang {
49848e66864SKever Yang 	struct rk8xx_priv *priv = dev_get_priv(pmic);
49948e66864SKever Yang 	uint mask = 0;
50048e66864SKever Yang 	int ret = 0;
50148e66864SKever Yang 
50248e66864SKever Yang 	switch (priv->variant) {
503ef9c5d10Sshengfei Xu 	case RK806_ID:
504ef9c5d10Sshengfei Xu 		mask = 1 << buck % 4;
505ef9c5d10Sshengfei Xu 		ret = pmic_reg_read(pmic, RK806_POWER_EN(buck / 4));
506ef9c5d10Sshengfei Xu 		break;
50748e66864SKever Yang 	case RK805_ID:
50848e66864SKever Yang 	case RK816_ID:
50948e66864SKever Yang 		if (buck >= 4) {
51048e66864SKever Yang 			mask = 1 << (buck - 4);
51148e66864SKever Yang 			ret = pmic_reg_read(pmic, RK816_REG_DCDC_EN2);
51248e66864SKever Yang 		} else {
51348e66864SKever Yang 			mask = 1 << buck;
51448e66864SKever Yang 			ret = pmic_reg_read(pmic, RK816_REG_DCDC_EN1);
51548e66864SKever Yang 		}
51648e66864SKever Yang 		break;
51748e66864SKever Yang 	case RK808_ID:
51848e66864SKever Yang 	case RK818_ID:
51948e66864SKever Yang 		mask = 1 << buck;
52048e66864SKever Yang 		ret = pmic_reg_read(pmic, REG_DCDC_EN);
52148e66864SKever Yang 		if (ret < 0)
52248e66864SKever Yang 			return ret;
52348e66864SKever Yang 		break;
5241b6b965cSJoseph Chen 	case RK809_ID:
5257f18d96cSJoseph Chen 	case RK817_ID:
5261b6b965cSJoseph Chen 		if (buck < 4) {
5277f18d96cSJoseph Chen 			mask = 1 << buck;
5287f18d96cSJoseph Chen 			ret = pmic_reg_read(pmic, RK817_POWER_EN(0));
5291b6b965cSJoseph Chen 		/* BUCK5 for RK809 */
5301b6b965cSJoseph Chen 		} else {
5311b6b965cSJoseph Chen 			mask = 1 << 1;
5321b6b965cSJoseph Chen 			ret = pmic_reg_read(pmic, RK817_POWER_EN(3));
5331b6b965cSJoseph Chen 		}
5347f18d96cSJoseph Chen 		break;
53548e66864SKever Yang 	}
5361b6b965cSJoseph Chen 
5371b6b965cSJoseph Chen 	if (ret < 0)
5381b6b965cSJoseph Chen 		return ret;
5391b6b965cSJoseph Chen 
54048e66864SKever Yang 	return ret & mask ? true : false;
54148e66864SKever Yang }
54248e66864SKever Yang 
_buck_set_ramp_delay(struct udevice * pmic,int buck,u32 ramp_delay)543868bdcf3SJoseph Chen static int _buck_set_ramp_delay(struct udevice *pmic, int buck, u32 ramp_delay)
544868bdcf3SJoseph Chen {
545868bdcf3SJoseph Chen 	const struct rk8xx_reg_info *info = get_buck_reg(pmic, buck, 0);
546868bdcf3SJoseph Chen 	struct rk8xx_priv *priv = dev_get_priv(pmic);
547868bdcf3SJoseph Chen 	u32 ramp_value, ramp_mask;
548ef9c5d10Sshengfei Xu 	int reg_value, ramp_reg1, ramp_reg2;
549868bdcf3SJoseph Chen 
55004d4208bSJoseph Chen 	if (info->config_reg == NA)
551868bdcf3SJoseph Chen 		return -ENOSYS;
552868bdcf3SJoseph Chen 
553868bdcf3SJoseph Chen 	switch (priv->variant) {
554868bdcf3SJoseph Chen 	case RK805_ID:
555868bdcf3SJoseph Chen 		ramp_mask = RK805_RAMP_RATE_MASK;
556868bdcf3SJoseph Chen 		ramp_value = RK805_RAMP_RATE_12_5MV_PER_US;
557868bdcf3SJoseph Chen 		switch (ramp_delay) {
558868bdcf3SJoseph Chen 		case 0 ... 3000:
559868bdcf3SJoseph Chen 			ramp_value = RK805_RAMP_RATE_3MV_PER_US;
560868bdcf3SJoseph Chen 			break;
561868bdcf3SJoseph Chen 		case 3001 ... 6000:
562868bdcf3SJoseph Chen 			ramp_value = RK805_RAMP_RATE_6MV_PER_US;
563868bdcf3SJoseph Chen 			break;
564868bdcf3SJoseph Chen 		case 6001 ... 12500:
565868bdcf3SJoseph Chen 			ramp_value = RK805_RAMP_RATE_12_5MV_PER_US;
566868bdcf3SJoseph Chen 			break;
567868bdcf3SJoseph Chen 		case 12501 ... 25000:
568868bdcf3SJoseph Chen 			ramp_value = RK805_RAMP_RATE_25MV_PER_US;
569868bdcf3SJoseph Chen 			break;
570868bdcf3SJoseph Chen 		default:
571868bdcf3SJoseph Chen 			printf("buck%d ramp_delay: %d not supported\n",
572868bdcf3SJoseph Chen 			       buck, ramp_delay);
573868bdcf3SJoseph Chen 		}
574868bdcf3SJoseph Chen 		break;
575ef9c5d10Sshengfei Xu 	case RK806_ID:
576ef9c5d10Sshengfei Xu 		switch (ramp_delay) {
577ef9c5d10Sshengfei Xu 		case 1 ... 390:
578ef9c5d10Sshengfei Xu 			ramp_value = RK806_RAMP_RATE_1LSB_PER_32CLK;
579ef9c5d10Sshengfei Xu 			break;
580ef9c5d10Sshengfei Xu 		case 391 ... 961:
581ef9c5d10Sshengfei Xu 			ramp_value = RK806_RAMP_RATE_1LSB_PER_13CLK;
582ef9c5d10Sshengfei Xu 			break;
583ef9c5d10Sshengfei Xu 		case 962 ... 1560:
584ef9c5d10Sshengfei Xu 			ramp_value = RK806_RAMP_RATE_1LSB_PER_8CLK;
585ef9c5d10Sshengfei Xu 			break;
586ef9c5d10Sshengfei Xu 		case 1561 ... 3125:
587ef9c5d10Sshengfei Xu 			ramp_value = RK806_RAMP_RATE_1LSB_PER_4CLK;
588ef9c5d10Sshengfei Xu 			break;
589ef9c5d10Sshengfei Xu 		case 3126 ... 6250:
590ef9c5d10Sshengfei Xu 			ramp_value = RK806_RAMP_RATE_1LSB_PER_2CLK;
591ef9c5d10Sshengfei Xu 			break;
592ef9c5d10Sshengfei Xu 		case 6251 ... 12500:
593ef9c5d10Sshengfei Xu 			ramp_value = RK806_RAMP_RATE_1LSB_PER_1CLK;
594ef9c5d10Sshengfei Xu 			break;
595ef9c5d10Sshengfei Xu 		case 12501 ... 25000:
596ef9c5d10Sshengfei Xu 			ramp_value = RK806_RAMP_RATE_2LSB_PER_1CLK;
597ef9c5d10Sshengfei Xu 			break;
598ef9c5d10Sshengfei Xu 		case 25001 ... 50000: /* 50mV/us */
599ef9c5d10Sshengfei Xu 			ramp_value = RK806_RAMP_RATE_4LSB_PER_1CLK;
600ef9c5d10Sshengfei Xu 			break;
601ef9c5d10Sshengfei Xu 		default:
602ef9c5d10Sshengfei Xu 			ramp_value = RK806_RAMP_RATE_1LSB_PER_32CLK;
603ef9c5d10Sshengfei Xu 			printf("buck%d ramp_delay: %d not supported\n",
604ef9c5d10Sshengfei Xu 			       buck, ramp_delay);
605ef9c5d10Sshengfei Xu 			return -EINVAL;
606ef9c5d10Sshengfei Xu 		}
607ef9c5d10Sshengfei Xu 		ramp_reg1 = RK806_RAMP_RATE_REG1(buck);
608ef9c5d10Sshengfei Xu 		if (buck < 8)
609ef9c5d10Sshengfei Xu 			ramp_reg2 = RK806_RAMP_RATE_REG1_8;
610ef9c5d10Sshengfei Xu 		else
611ef9c5d10Sshengfei Xu 			ramp_reg2 = RK806_RAMP_RATE_REG9_10;
612ef9c5d10Sshengfei Xu 
613ef9c5d10Sshengfei Xu 		reg_value = pmic_reg_read(pmic, ramp_reg1);
614ef9c5d10Sshengfei Xu 		if (reg_value < 0) {
615ef9c5d10Sshengfei Xu 			printf("buck%d read ramp reg(0x%x) error: %d", buck, ramp_reg1, reg_value);
616ef9c5d10Sshengfei Xu 			return reg_value;
617ef9c5d10Sshengfei Xu 		}
618ef9c5d10Sshengfei Xu 		reg_value &= 0x3f;
619ef9c5d10Sshengfei Xu 
620ef9c5d10Sshengfei Xu 		pmic_reg_write(pmic,
621ef9c5d10Sshengfei Xu 			       ramp_reg1,
622ef9c5d10Sshengfei Xu 			       reg_value | (ramp_value & 0x03) << 0x06);
623ef9c5d10Sshengfei Xu 
624ef9c5d10Sshengfei Xu 		reg_value = pmic_reg_read(pmic, ramp_reg2);
625ef9c5d10Sshengfei Xu 		if (reg_value < 0) {
626ef9c5d10Sshengfei Xu 			printf("buck%d read ramp reg(0x%x) error: %d", buck, ramp_reg2, reg_value);
627ef9c5d10Sshengfei Xu 			return reg_value;
628ef9c5d10Sshengfei Xu 		}
629ef9c5d10Sshengfei Xu 
630ef9c5d10Sshengfei Xu 		return pmic_reg_write(pmic,
631ef9c5d10Sshengfei Xu 				      ramp_reg2,
632ef9c5d10Sshengfei Xu 				      reg_value | (ramp_value & 0x04) << (buck % 8));
633868bdcf3SJoseph Chen 	case RK808_ID:
634868bdcf3SJoseph Chen 	case RK816_ID:
635868bdcf3SJoseph Chen 	case RK818_ID:
636868bdcf3SJoseph Chen 		ramp_value = RK808_RAMP_RATE_6MV_PER_US;
637868bdcf3SJoseph Chen 		ramp_mask = RK808_RAMP_RATE_MASK;
638868bdcf3SJoseph Chen 		switch (ramp_delay) {
639868bdcf3SJoseph Chen 		case 1 ... 2000:
640868bdcf3SJoseph Chen 			ramp_value = RK808_RAMP_RATE_2MV_PER_US;
641868bdcf3SJoseph Chen 			break;
642868bdcf3SJoseph Chen 		case 2001 ... 4000:
643868bdcf3SJoseph Chen 			ramp_value = RK808_RAMP_RATE_4MV_PER_US;
644868bdcf3SJoseph Chen 			break;
645868bdcf3SJoseph Chen 		case 4001 ... 6000:
646868bdcf3SJoseph Chen 			ramp_value = RK808_RAMP_RATE_6MV_PER_US;
647868bdcf3SJoseph Chen 			break;
648868bdcf3SJoseph Chen 		case 6001 ... 10000:
649868bdcf3SJoseph Chen 			ramp_value = RK808_RAMP_RATE_6MV_PER_US;
650868bdcf3SJoseph Chen 			break;
651868bdcf3SJoseph Chen 		default:
652868bdcf3SJoseph Chen 			printf("buck%d ramp_delay: %d not supported\n",
653868bdcf3SJoseph Chen 			       buck, ramp_delay);
654868bdcf3SJoseph Chen 		}
655868bdcf3SJoseph Chen 		break;
656868bdcf3SJoseph Chen 	case RK809_ID:
657868bdcf3SJoseph Chen 	case RK817_ID:
658868bdcf3SJoseph Chen 		ramp_mask = RK817_RAMP_RATE_MASK;
659868bdcf3SJoseph Chen 		ramp_value = RK817_RAMP_RATE_12_5MV_PER_US;
660868bdcf3SJoseph Chen 		switch (ramp_delay) {
661868bdcf3SJoseph Chen 		case 0 ... 3000:
662868bdcf3SJoseph Chen 			ramp_value = RK817_RAMP_RATE_3MV_PER_US;
663868bdcf3SJoseph Chen 			break;
664868bdcf3SJoseph Chen 		case 3001 ... 6300:
665868bdcf3SJoseph Chen 			ramp_value = RK817_RAMP_RATE_6_3MV_PER_US;
666868bdcf3SJoseph Chen 			break;
667868bdcf3SJoseph Chen 		case 6301 ... 12500:
668868bdcf3SJoseph Chen 			ramp_value = RK817_RAMP_RATE_12_5MV_PER_US;
669868bdcf3SJoseph Chen 			break;
670868bdcf3SJoseph Chen 		case 12501 ... 25000:
671868bdcf3SJoseph Chen 			ramp_value = RK817_RAMP_RATE_12_5MV_PER_US;
672868bdcf3SJoseph Chen 			break;
673868bdcf3SJoseph Chen 		default:
674868bdcf3SJoseph Chen 			printf("buck%d ramp_delay: %d not supported\n",
675868bdcf3SJoseph Chen 			       buck, ramp_delay);
676868bdcf3SJoseph Chen 		}
677868bdcf3SJoseph Chen 		break;
678868bdcf3SJoseph Chen 	default:
679868bdcf3SJoseph Chen 		return -EINVAL;
680868bdcf3SJoseph Chen 	}
681868bdcf3SJoseph Chen 
682868bdcf3SJoseph Chen 	return pmic_clrsetbits(pmic, info->config_reg, ramp_mask, ramp_value);
683868bdcf3SJoseph Chen }
684868bdcf3SJoseph Chen 
_buck_set_suspend_enable(struct udevice * pmic,int buck,bool enable)685e917b032SJoseph Chen static int _buck_set_suspend_enable(struct udevice *pmic, int buck, bool enable)
686e917b032SJoseph Chen {
687e917b032SJoseph Chen 	uint mask;
688e917b032SJoseph Chen 	int ret;
689e917b032SJoseph Chen 	struct rk8xx_priv *priv = dev_get_priv(pmic);
690e917b032SJoseph Chen 
691e917b032SJoseph Chen 	switch (priv->variant) {
692e917b032SJoseph Chen 	case RK805_ID:
693e917b032SJoseph Chen 	case RK816_ID:
694e917b032SJoseph Chen 		mask = 1 << buck;
695e917b032SJoseph Chen 		ret = pmic_clrsetbits(pmic, RK816_REG_DCDC_SLP_EN, mask,
696e917b032SJoseph Chen 				      enable ? mask : 0);
697e917b032SJoseph Chen 		break;
698ef9c5d10Sshengfei Xu 	case RK806_ID:
699ef9c5d10Sshengfei Xu 		if (buck <= 7) {
700ef9c5d10Sshengfei Xu 			mask = 1 << buck;
701ef9c5d10Sshengfei Xu 			ret = pmic_clrsetbits(pmic, RK806_BUCK_SUSPEND_EN, mask,
702ef9c5d10Sshengfei Xu 					      enable ? mask : 0);
703ef9c5d10Sshengfei Xu 		} else {
704ef9c5d10Sshengfei Xu 			if (buck == 8)
705ef9c5d10Sshengfei Xu 				mask = 0x40;
706ef9c5d10Sshengfei Xu 			else
707ef9c5d10Sshengfei Xu 				mask = 0x80;
708ef9c5d10Sshengfei Xu 			ret = pmic_clrsetbits(pmic, RK806_NLDO_SUSPEND_EN, mask,
709ef9c5d10Sshengfei Xu 					      enable ? mask : 0);
710ef9c5d10Sshengfei Xu 		}
711ef9c5d10Sshengfei Xu 		break;
712e917b032SJoseph Chen 	case RK808_ID:
713e917b032SJoseph Chen 	case RK818_ID:
714e917b032SJoseph Chen 		mask = 1 << buck;
715e917b032SJoseph Chen 		ret = pmic_clrsetbits(pmic, REG_SLEEP_SET_OFF1, mask,
716e917b032SJoseph Chen 				      enable ? 0 : mask);
717e917b032SJoseph Chen 		break;
7181b6b965cSJoseph Chen 	case RK809_ID:
7197f18d96cSJoseph Chen 	case RK817_ID:
7201b6b965cSJoseph Chen 		if (buck < 4)
7217f18d96cSJoseph Chen 			mask = 1 << buck;
7221b6b965cSJoseph Chen 		else
7231b6b965cSJoseph Chen 			mask = 1 << 5;	/* BUCK5 for RK809 */
7247f18d96cSJoseph Chen 		ret = pmic_clrsetbits(pmic, RK817_POWER_SLP_EN(0), mask,
7257f18d96cSJoseph Chen 				      enable ? mask : 0);
7267f18d96cSJoseph Chen 		break;
727e917b032SJoseph Chen 	default:
728e917b032SJoseph Chen 		ret = -EINVAL;
729e917b032SJoseph Chen 	}
730e917b032SJoseph Chen 
731e917b032SJoseph Chen 	return ret;
732e917b032SJoseph Chen }
733e917b032SJoseph Chen 
_buck_get_suspend_enable(struct udevice * pmic,int buck)734712b6f80SJoseph Chen static int _buck_get_suspend_enable(struct udevice *pmic, int buck)
735712b6f80SJoseph Chen {
736712b6f80SJoseph Chen 	struct rk8xx_priv *priv = dev_get_priv(pmic);
737712b6f80SJoseph Chen 	int ret, val;
738712b6f80SJoseph Chen 	uint mask;
739712b6f80SJoseph Chen 
740712b6f80SJoseph Chen 	switch (priv->variant) {
741712b6f80SJoseph Chen 	case RK805_ID:
742712b6f80SJoseph Chen 	case RK816_ID:
743712b6f80SJoseph Chen 		mask = 1 << buck;
744712b6f80SJoseph Chen 		val = pmic_reg_read(pmic, RK816_REG_DCDC_SLP_EN);
745712b6f80SJoseph Chen 		if (val < 0)
746712b6f80SJoseph Chen 			return val;
747712b6f80SJoseph Chen 		ret = val & mask ? 1 : 0;
748712b6f80SJoseph Chen 		break;
749ef9c5d10Sshengfei Xu 	case RK806_ID:
750ef9c5d10Sshengfei Xu 		if (buck <= 7) {
751ef9c5d10Sshengfei Xu 			mask = 1 << buck % 7;
752ef9c5d10Sshengfei Xu 			val = pmic_reg_read(pmic, RK806_BUCK_SUSPEND_EN);
753ef9c5d10Sshengfei Xu 		} else {
754ef9c5d10Sshengfei Xu 			mask = 1 << ((buck - 7) + 6);
755ef9c5d10Sshengfei Xu 			val = pmic_reg_read(pmic, RK806_NLDO_SUSPEND_EN);
756ef9c5d10Sshengfei Xu 		}
757ef9c5d10Sshengfei Xu 
758ef9c5d10Sshengfei Xu 		if (val < 0)
759ef9c5d10Sshengfei Xu 			return val;
760ef9c5d10Sshengfei Xu 		ret = val & mask ? 1 : 0;
761ef9c5d10Sshengfei Xu 		break;
762712b6f80SJoseph Chen 	case RK808_ID:
763712b6f80SJoseph Chen 	case RK818_ID:
764712b6f80SJoseph Chen 		mask = 1 << buck;
765712b6f80SJoseph Chen 		val = pmic_reg_read(pmic, REG_SLEEP_SET_OFF1);
766712b6f80SJoseph Chen 		if (val < 0)
767712b6f80SJoseph Chen 			return val;
768712b6f80SJoseph Chen 		ret = val & mask ? 0 : 1;
769712b6f80SJoseph Chen 		break;
770712b6f80SJoseph Chen 	case RK809_ID:
771712b6f80SJoseph Chen 	case RK817_ID:
772712b6f80SJoseph Chen 		if (buck < 4)
773712b6f80SJoseph Chen 			mask = 1 << buck;
774712b6f80SJoseph Chen 		else
775712b6f80SJoseph Chen 			mask = 1 << 5;	/* BUCK5 for RK809 */
776712b6f80SJoseph Chen 
777712b6f80SJoseph Chen 		val = pmic_reg_read(pmic, RK817_POWER_SLP_EN(0));
778712b6f80SJoseph Chen 		if (val < 0)
779712b6f80SJoseph Chen 			return val;
780712b6f80SJoseph Chen 		ret = val & mask ? 1 : 0;
781712b6f80SJoseph Chen 		break;
782712b6f80SJoseph Chen 	default:
783712b6f80SJoseph Chen 		ret = -EINVAL;
784712b6f80SJoseph Chen 	}
785712b6f80SJoseph Chen 
786712b6f80SJoseph Chen 	return ret;
787712b6f80SJoseph Chen }
788712b6f80SJoseph Chen 
get_ldo_reg(struct udevice * pmic,int num,int uvolt)7898926c2f5SWadim Egorov static const struct rk8xx_reg_info *get_ldo_reg(struct udevice *pmic,
7907f18d96cSJoseph Chen 						int num, int uvolt)
7918926c2f5SWadim Egorov {
7928926c2f5SWadim Egorov 	struct rk8xx_priv *priv = dev_get_priv(pmic);
7935e1bceeaSElaine Zhang 
7948926c2f5SWadim Egorov 	switch (priv->variant) {
7954b6f5dc9SElaine Zhang 	case RK805_ID:
7965e1bceeaSElaine Zhang 	case RK816_ID:
7975e1bceeaSElaine Zhang 		return &rk816_ldo[num];
798ef9c5d10Sshengfei Xu 	case RK806_ID:
799ef9c5d10Sshengfei Xu 		if (uvolt < 3400000)
800ef9c5d10Sshengfei Xu 			return &rk806_nldo[num * 2];
801ef9c5d10Sshengfei Xu 		else
802ef9c5d10Sshengfei Xu 			return &rk806_nldo[num * 2 + 1];
8031b6b965cSJoseph Chen 	case RK809_ID:
8047f18d96cSJoseph Chen 	case RK817_ID:
8057f18d96cSJoseph Chen 		if (uvolt < 3400000)
8067f18d96cSJoseph Chen 			return &rk817_ldo[num * 2 + 0];
8077f18d96cSJoseph Chen 		else
8087f18d96cSJoseph Chen 			return &rk817_ldo[num * 2 + 1];
8098926c2f5SWadim Egorov 	case RK818_ID:
8108926c2f5SWadim Egorov 		return &rk818_ldo[num];
8118926c2f5SWadim Egorov 	default:
8128926c2f5SWadim Egorov 		return &rk808_ldo[num];
8138926c2f5SWadim Egorov 	}
8148926c2f5SWadim Egorov }
8158926c2f5SWadim Egorov 
_ldo_get_enable(struct udevice * pmic,int ldo)8165e1bceeaSElaine Zhang static int _ldo_get_enable(struct udevice *pmic, int ldo)
8175e1bceeaSElaine Zhang {
8185e1bceeaSElaine Zhang 	struct rk8xx_priv *priv = dev_get_priv(pmic);
8195e1bceeaSElaine Zhang 	uint mask = 0;
8205e1bceeaSElaine Zhang 	int ret = 0;
8215e1bceeaSElaine Zhang 
8225e1bceeaSElaine Zhang 	switch (priv->variant) {
8234b6f5dc9SElaine Zhang 	case RK805_ID:
8245e1bceeaSElaine Zhang 	case RK816_ID:
8255e1bceeaSElaine Zhang 		if (ldo >= 4) {
8265e1bceeaSElaine Zhang 			mask = 1 << (ldo - 4);
8275e1bceeaSElaine Zhang 			ret = pmic_reg_read(pmic, RK816_REG_LDO_EN2);
8285e1bceeaSElaine Zhang 		} else {
8295e1bceeaSElaine Zhang 			mask = 1 << ldo;
8305e1bceeaSElaine Zhang 			ret = pmic_reg_read(pmic, RK816_REG_LDO_EN1);
8315e1bceeaSElaine Zhang 		}
8325e1bceeaSElaine Zhang 		break;
833ef9c5d10Sshengfei Xu 	case RK806_ID:
834ef9c5d10Sshengfei Xu 		if (ldo < 4) {
835ef9c5d10Sshengfei Xu 			mask = 1 << ldo % 4;
836ef9c5d10Sshengfei Xu 			ret = pmic_reg_read(pmic, RK806_NLDO_EN(ldo / 4));
837ef9c5d10Sshengfei Xu 		} else {
838ef9c5d10Sshengfei Xu 			mask = 1 << 2;
839ef9c5d10Sshengfei Xu 			ret = pmic_reg_read(pmic, RK806_NLDO_EN(2));
840ef9c5d10Sshengfei Xu 		}
841ef9c5d10Sshengfei Xu 		break;
8425e1bceeaSElaine Zhang 	case RK808_ID:
8435e1bceeaSElaine Zhang 	case RK818_ID:
8445e1bceeaSElaine Zhang 		mask = 1 << ldo;
8455e1bceeaSElaine Zhang 		ret = pmic_reg_read(pmic, REG_LDO_EN);
8465e1bceeaSElaine Zhang 		if (ret < 0)
8475e1bceeaSElaine Zhang 			return ret;
8485e1bceeaSElaine Zhang 		break;
8491b6b965cSJoseph Chen 	case RK809_ID:
8507f18d96cSJoseph Chen 	case RK817_ID:
8517f18d96cSJoseph Chen 		if (ldo < 4) {
8527f18d96cSJoseph Chen 			mask = 1 << ldo;
8537f18d96cSJoseph Chen 			ret = pmic_reg_read(pmic, RK817_POWER_EN(1));
8547f18d96cSJoseph Chen 		} else if (ldo < 8) {
8557f18d96cSJoseph Chen 			mask = 1 << (ldo - 4);
8567f18d96cSJoseph Chen 			ret = pmic_reg_read(pmic, RK817_POWER_EN(2));
8577f18d96cSJoseph Chen 		} else if (ldo == 8) {
8587f18d96cSJoseph Chen 			mask = 1 << 0;
8597f18d96cSJoseph Chen 			ret = pmic_reg_read(pmic, RK817_POWER_EN(3));
8607f18d96cSJoseph Chen 		} else {
8617f18d96cSJoseph Chen 			return false;
8627f18d96cSJoseph Chen 		}
8637f18d96cSJoseph Chen 		break;
8645e1bceeaSElaine Zhang 	}
8651b6b965cSJoseph Chen 
8661b6b965cSJoseph Chen 	if (ret < 0)
8671b6b965cSJoseph Chen 		return ret;
8681b6b965cSJoseph Chen 
8695e1bceeaSElaine Zhang 	return ret & mask ? true : false;
8705e1bceeaSElaine Zhang }
8715e1bceeaSElaine Zhang 
_ldo_set_enable(struct udevice * pmic,int ldo,bool enable)8725e1bceeaSElaine Zhang static int _ldo_set_enable(struct udevice *pmic, int ldo, bool enable)
8735e1bceeaSElaine Zhang {
8745e1bceeaSElaine Zhang 	struct rk8xx_priv *priv = dev_get_priv(pmic);
8755e1bceeaSElaine Zhang 	uint mask, value, en_reg;
8765e1bceeaSElaine Zhang 	int ret = 0;
8775e1bceeaSElaine Zhang 
8785e1bceeaSElaine Zhang 	switch (priv->variant) {
8794b6f5dc9SElaine Zhang 	case RK805_ID:
8805e1bceeaSElaine Zhang 	case RK816_ID:
8815e1bceeaSElaine Zhang 		if (ldo >= 4) {
8825e1bceeaSElaine Zhang 			ldo -= 4;
8835e1bceeaSElaine Zhang 			en_reg = RK816_REG_LDO_EN2;
8845e1bceeaSElaine Zhang 		} else {
8855e1bceeaSElaine Zhang 			en_reg = RK816_REG_LDO_EN1;
8865e1bceeaSElaine Zhang 		}
8875e1bceeaSElaine Zhang 		if (enable)
8885e1bceeaSElaine Zhang 			value = ((1 << ldo) | (1 << (ldo + 4)));
8895e1bceeaSElaine Zhang 		else
8905e1bceeaSElaine Zhang 			value = ((0 << ldo) | (1 << (ldo + 4)));
8915e1bceeaSElaine Zhang 
8925e1bceeaSElaine Zhang 		ret = pmic_reg_write(pmic, en_reg, value);
8935e1bceeaSElaine Zhang 		break;
894ef9c5d10Sshengfei Xu 	case RK806_ID:
895ef9c5d10Sshengfei Xu 		if (ldo < 4) {
896ef9c5d10Sshengfei Xu 			en_reg = RK806_NLDO_EN(0);
897ef9c5d10Sshengfei Xu 			if (enable)
898ef9c5d10Sshengfei Xu 				value = ((1 << ldo % 4) | (1 << (ldo % 4 + 4)));
899ef9c5d10Sshengfei Xu 			else
900ef9c5d10Sshengfei Xu 				value = ((0 << ldo % 4) | (1 << (ldo % 4 + 4)));
901ef9c5d10Sshengfei Xu 			ret = pmic_reg_write(pmic, en_reg, value);
902ef9c5d10Sshengfei Xu 		} else {
903ef9c5d10Sshengfei Xu 			en_reg = RK806_NLDO_EN(2);
904ef9c5d10Sshengfei Xu 			if (enable)
905ef9c5d10Sshengfei Xu 				value = 0x44;
906ef9c5d10Sshengfei Xu 			else
907ef9c5d10Sshengfei Xu 				value = 0x40;
908ef9c5d10Sshengfei Xu 			ret = pmic_reg_write(pmic, en_reg, value);
909ef9c5d10Sshengfei Xu 		}
910ef9c5d10Sshengfei Xu 		break;
9115e1bceeaSElaine Zhang 	case RK808_ID:
9125e1bceeaSElaine Zhang 	case RK818_ID:
9135e1bceeaSElaine Zhang 		mask = 1 << ldo;
9145e1bceeaSElaine Zhang 		ret = pmic_clrsetbits(pmic, REG_LDO_EN, mask,
9155e1bceeaSElaine Zhang 				      enable ? mask : 0);
9165e1bceeaSElaine Zhang 		break;
9171b6b965cSJoseph Chen 	case RK809_ID:
9187f18d96cSJoseph Chen 	case RK817_ID:
9197f18d96cSJoseph Chen 		if (ldo < 4) {
9207f18d96cSJoseph Chen 			en_reg = RK817_POWER_EN(1);
9217f18d96cSJoseph Chen 		} else if (ldo < 8) {
9227f18d96cSJoseph Chen 			ldo -= 4;
9237f18d96cSJoseph Chen 			en_reg = RK817_POWER_EN(2);
9247f18d96cSJoseph Chen 		} else if (ldo == 8) {
9257f18d96cSJoseph Chen 			ldo = 0;	/* BIT 0 */
9267f18d96cSJoseph Chen 			en_reg = RK817_POWER_EN(3);
9277f18d96cSJoseph Chen 		} else {
9287f18d96cSJoseph Chen 			return -EINVAL;
9297f18d96cSJoseph Chen 		}
9307f18d96cSJoseph Chen 		if (enable)
9317f18d96cSJoseph Chen 			value = ((1 << ldo) | (1 << (ldo + 4)));
9327f18d96cSJoseph Chen 		else
9337f18d96cSJoseph Chen 			value = ((0 << ldo) | (1 << (ldo + 4)));
9347f18d96cSJoseph Chen 		ret = pmic_reg_write(pmic, en_reg, value);
9357f18d96cSJoseph Chen 		break;
9365e1bceeaSElaine Zhang 	}
9375e1bceeaSElaine Zhang 
938b509cd39SJonas Karlman 	if (enable)
939b509cd39SJonas Karlman 		udelay(500);
940b509cd39SJonas Karlman 
9415e1bceeaSElaine Zhang 	return ret;
9425e1bceeaSElaine Zhang }
9435e1bceeaSElaine Zhang 
_ldo_set_suspend_enable(struct udevice * pmic,int ldo,bool enable)944e917b032SJoseph Chen static int _ldo_set_suspend_enable(struct udevice *pmic, int ldo, bool enable)
945e917b032SJoseph Chen {
946e917b032SJoseph Chen 	struct rk8xx_priv *priv = dev_get_priv(pmic);
947e917b032SJoseph Chen 	uint mask;
948e917b032SJoseph Chen 	int ret = 0;
949e917b032SJoseph Chen 
950e917b032SJoseph Chen 	switch (priv->variant) {
951e917b032SJoseph Chen 	case RK805_ID:
952e917b032SJoseph Chen 	case RK816_ID:
953e917b032SJoseph Chen 		mask = 1 << ldo;
954e917b032SJoseph Chen 		ret = pmic_clrsetbits(pmic, RK816_REG_LDO_SLP_EN, mask,
955e917b032SJoseph Chen 				      enable ? mask : 0);
956e917b032SJoseph Chen 		break;
957ef9c5d10Sshengfei Xu 	case RK806_ID:
958ef9c5d10Sshengfei Xu 		mask = 1 << ldo;
959ef9c5d10Sshengfei Xu 		ret = pmic_clrsetbits(pmic, RK806_NLDO_SUSPEND_EN, mask,
960ef9c5d10Sshengfei Xu 				      enable ? mask : 0);
961ef9c5d10Sshengfei Xu 		break;
962e917b032SJoseph Chen 	case RK808_ID:
963e917b032SJoseph Chen 	case RK818_ID:
964e917b032SJoseph Chen 		mask = 1 << ldo;
965e917b032SJoseph Chen 		ret = pmic_clrsetbits(pmic, REG_SLEEP_SET_OFF2, mask,
966e917b032SJoseph Chen 				      enable ? 0 : mask);
967e917b032SJoseph Chen 		break;
9681b6b965cSJoseph Chen 	case RK809_ID:
9697f18d96cSJoseph Chen 	case RK817_ID:
9707f18d96cSJoseph Chen 		if (ldo == 8) {
9717f18d96cSJoseph Chen 			mask = 1 << 4;	/* LDO9 */
9727f18d96cSJoseph Chen 			ret = pmic_clrsetbits(pmic, RK817_POWER_SLP_EN(0), mask,
9737f18d96cSJoseph Chen 					      enable ? mask : 0);
9747f18d96cSJoseph Chen 		} else {
9757f18d96cSJoseph Chen 			mask = 1 << ldo;
9767f18d96cSJoseph Chen 			ret = pmic_clrsetbits(pmic, RK817_POWER_SLP_EN(1), mask,
9777f18d96cSJoseph Chen 					      enable ? mask : 0);
9787f18d96cSJoseph Chen 		}
9797f18d96cSJoseph Chen 		break;
980e917b032SJoseph Chen 	}
981e917b032SJoseph Chen 
982e917b032SJoseph Chen 	return ret;
983e917b032SJoseph Chen }
984e917b032SJoseph Chen 
_ldo_get_suspend_enable(struct udevice * pmic,int ldo)985712b6f80SJoseph Chen static int _ldo_get_suspend_enable(struct udevice *pmic, int ldo)
986712b6f80SJoseph Chen {
987712b6f80SJoseph Chen 	struct rk8xx_priv *priv = dev_get_priv(pmic);
988712b6f80SJoseph Chen 	int val, ret = 0;
989712b6f80SJoseph Chen 	uint mask;
990712b6f80SJoseph Chen 
991712b6f80SJoseph Chen 	switch (priv->variant) {
992712b6f80SJoseph Chen 	case RK805_ID:
993712b6f80SJoseph Chen 	case RK816_ID:
994712b6f80SJoseph Chen 		mask = 1 << ldo;
995712b6f80SJoseph Chen 		val = pmic_reg_read(pmic, RK816_REG_LDO_SLP_EN);
996712b6f80SJoseph Chen 		if (val < 0)
997712b6f80SJoseph Chen 			return val;
998712b6f80SJoseph Chen 		ret = val & mask ? 1 : 0;
999712b6f80SJoseph Chen 		break;
1000ef9c5d10Sshengfei Xu 	case RK806_ID:
1001ef9c5d10Sshengfei Xu 		mask = 1 << ldo;
1002ef9c5d10Sshengfei Xu 		val = pmic_reg_read(pmic, RK806_NLDO_SUSPEND_EN);
1003ef9c5d10Sshengfei Xu 
1004ef9c5d10Sshengfei Xu 		if (val < 0)
1005ef9c5d10Sshengfei Xu 			return val;
1006ef9c5d10Sshengfei Xu 		ret = val & mask ? 1 : 0;
1007ef9c5d10Sshengfei Xu 		break;
1008712b6f80SJoseph Chen 	case RK808_ID:
1009712b6f80SJoseph Chen 	case RK818_ID:
1010712b6f80SJoseph Chen 		mask = 1 << ldo;
1011712b6f80SJoseph Chen 		val = pmic_reg_read(pmic, REG_SLEEP_SET_OFF2);
1012712b6f80SJoseph Chen 		if (val < 0)
1013712b6f80SJoseph Chen 			return val;
1014712b6f80SJoseph Chen 		ret = val & mask ? 0 : 1;
1015712b6f80SJoseph Chen 		break;
1016712b6f80SJoseph Chen 	case RK809_ID:
1017712b6f80SJoseph Chen 	case RK817_ID:
1018712b6f80SJoseph Chen 		if (ldo == 8) {
1019712b6f80SJoseph Chen 			mask = 1 << 4;	/* LDO9 */
1020712b6f80SJoseph Chen 			val = pmic_reg_read(pmic, RK817_POWER_SLP_EN(0));
1021712b6f80SJoseph Chen 			if (val < 0)
1022712b6f80SJoseph Chen 				return val;
1023712b6f80SJoseph Chen 			ret = val & mask ? 1 : 0;
1024712b6f80SJoseph Chen 		} else {
1025712b6f80SJoseph Chen 			mask = 1 << ldo;
1026712b6f80SJoseph Chen 			val = pmic_reg_read(pmic, RK817_POWER_SLP_EN(1));
1027712b6f80SJoseph Chen 			if (val < 0)
1028712b6f80SJoseph Chen 				return val;
1029712b6f80SJoseph Chen 			ret = val & mask ? 1 : 0;
1030712b6f80SJoseph Chen 		}
1031712b6f80SJoseph Chen 		break;
1032712b6f80SJoseph Chen 	}
1033712b6f80SJoseph Chen 
1034712b6f80SJoseph Chen 	return ret;
1035712b6f80SJoseph Chen }
1036712b6f80SJoseph Chen 
buck_get_value(struct udevice * dev)1037453c5a92SJacob Chen static int buck_get_value(struct udevice *dev)
1038453c5a92SJacob Chen {
1039453c5a92SJacob Chen 	int buck = dev->driver_data - 1;
10405e1bceeaSElaine Zhang 	const struct rk8xx_reg_info *info = get_buck_reg(dev->parent, buck, 0);
1041453c5a92SJacob Chen 	int mask = info->vsel_mask;
10423fe21f02SJoseph Chen 	int i, ret, val;
1043453c5a92SJacob Chen 
104404d4208bSJoseph Chen 	if (info->vsel_reg == NA)
1045453c5a92SJacob Chen 		return -ENOSYS;
10467f18d96cSJoseph Chen 
1047453c5a92SJacob Chen 	ret = pmic_reg_read(dev->parent, info->vsel_reg);
1048453c5a92SJacob Chen 	if (ret < 0)
1049453c5a92SJacob Chen 		return ret;
1050453c5a92SJacob Chen 
10513fe21f02SJoseph Chen 	val = ret & mask;
10523fe21f02SJoseph Chen 	if (val >= info->min_sel && val <= info->max_sel)
10533fe21f02SJoseph Chen 		goto finish;
10543fe21f02SJoseph Chen 
10553fe21f02SJoseph Chen 	/* unlucky to try */
10563fe21f02SJoseph Chen 	for (i = 1; i < info->range_num; i++) {
10573fe21f02SJoseph Chen 		info++;
10583fe21f02SJoseph Chen 		if (val <= info->max_sel && val >= info->min_sel)
10593fe21f02SJoseph Chen 			break;
10603fe21f02SJoseph Chen 	}
10613fe21f02SJoseph Chen 
10623fe21f02SJoseph Chen finish:
10633fe21f02SJoseph Chen 	return info->min_uv + (val - info->min_sel) * info->step_uv;
1064453c5a92SJacob Chen }
1065453c5a92SJacob Chen 
buck_set_value(struct udevice * dev,int uvolt)1066453c5a92SJacob Chen static int buck_set_value(struct udevice *dev, int uvolt)
1067453c5a92SJacob Chen {
10685e1bceeaSElaine Zhang 	int buck = dev->driver_data - 1;
1069453c5a92SJacob Chen 
1070453c5a92SJacob Chen 	return _buck_set_value(dev->parent, buck, uvolt);
1071453c5a92SJacob Chen }
1072453c5a92SJacob Chen 
buck_get_suspend_value(struct udevice * dev)1073712b6f80SJoseph Chen static int buck_get_suspend_value(struct udevice *dev)
1074712b6f80SJoseph Chen {
1075712b6f80SJoseph Chen 	int buck = dev->driver_data - 1;
1076712b6f80SJoseph Chen 	const struct rk8xx_reg_info *info = get_buck_reg(dev->parent, buck, 0);
1077712b6f80SJoseph Chen 	int mask = info->vsel_mask;
10783fe21f02SJoseph Chen 	int i, ret, val;
1079712b6f80SJoseph Chen 
1080712b6f80SJoseph Chen 	if (info->vsel_sleep_reg == NA)
1081712b6f80SJoseph Chen 		return -ENOSYS;
1082712b6f80SJoseph Chen 
1083712b6f80SJoseph Chen 	ret = pmic_reg_read(dev->parent, info->vsel_sleep_reg);
1084712b6f80SJoseph Chen 	if (ret < 0)
1085712b6f80SJoseph Chen 		return ret;
1086712b6f80SJoseph Chen 
1087712b6f80SJoseph Chen 	val = ret & mask;
10883fe21f02SJoseph Chen 	if (val <= info->max_sel && val >= info->min_sel)
10893fe21f02SJoseph Chen 		goto finish;
1090712b6f80SJoseph Chen 
10913fe21f02SJoseph Chen 	/* unlucky to try */
10923fe21f02SJoseph Chen 	for (i = 1; i < info->range_num; i++) {
10933fe21f02SJoseph Chen 		info++;
10943fe21f02SJoseph Chen 		if (val <= info->max_sel && val >= info->min_sel)
10953fe21f02SJoseph Chen 			break;
10963fe21f02SJoseph Chen 	}
10973fe21f02SJoseph Chen 
10983fe21f02SJoseph Chen finish:
10993fe21f02SJoseph Chen 	return info->min_uv + (val - info->min_sel) * info->step_uv;
1100712b6f80SJoseph Chen }
1101712b6f80SJoseph Chen 
buck_set_suspend_value(struct udevice * dev,int uvolt)1102e917b032SJoseph Chen static int buck_set_suspend_value(struct udevice *dev, int uvolt)
1103e917b032SJoseph Chen {
1104e917b032SJoseph Chen 	int buck = dev->driver_data - 1;
1105e917b032SJoseph Chen 
1106e917b032SJoseph Chen 	return _buck_set_suspend_value(dev->parent, buck, uvolt);
1107e917b032SJoseph Chen }
1108e917b032SJoseph Chen 
buck_set_enable(struct udevice * dev,bool enable)1109453c5a92SJacob Chen static int buck_set_enable(struct udevice *dev, bool enable)
1110453c5a92SJacob Chen {
11115e1bceeaSElaine Zhang 	int buck = dev->driver_data - 1;
1112453c5a92SJacob Chen 
1113453c5a92SJacob Chen 	return _buck_set_enable(dev->parent, buck, enable);
1114453c5a92SJacob Chen }
1115453c5a92SJacob Chen 
buck_set_suspend_enable(struct udevice * dev,bool enable)1116e917b032SJoseph Chen static int buck_set_suspend_enable(struct udevice *dev, bool enable)
1117e917b032SJoseph Chen {
1118e917b032SJoseph Chen 	int buck = dev->driver_data - 1;
1119e917b032SJoseph Chen 
1120e917b032SJoseph Chen 	return _buck_set_suspend_enable(dev->parent, buck, enable);
1121e917b032SJoseph Chen }
1122e917b032SJoseph Chen 
buck_get_suspend_enable(struct udevice * dev)1123712b6f80SJoseph Chen static int buck_get_suspend_enable(struct udevice *dev)
1124712b6f80SJoseph Chen {
1125712b6f80SJoseph Chen 	int buck = dev->driver_data - 1;
1126712b6f80SJoseph Chen 
1127712b6f80SJoseph Chen 	return _buck_get_suspend_enable(dev->parent, buck);
1128712b6f80SJoseph Chen }
1129712b6f80SJoseph Chen 
buck_set_ramp_delay(struct udevice * dev,u32 ramp_delay)1130868bdcf3SJoseph Chen static int buck_set_ramp_delay(struct udevice *dev, u32 ramp_delay)
1131868bdcf3SJoseph Chen {
1132868bdcf3SJoseph Chen 	int buck = dev->driver_data - 1;
1133868bdcf3SJoseph Chen 
1134868bdcf3SJoseph Chen 	return _buck_set_ramp_delay(dev->parent, buck, ramp_delay);
1135868bdcf3SJoseph Chen }
1136868bdcf3SJoseph Chen 
buck_get_enable(struct udevice * dev)1137585c7032SKeerthy static int buck_get_enable(struct udevice *dev)
1138453c5a92SJacob Chen {
1139453c5a92SJacob Chen 	int buck = dev->driver_data - 1;
1140453c5a92SJacob Chen 
11415e1bceeaSElaine Zhang 	return _buck_get_enable(dev->parent, buck);
1142453c5a92SJacob Chen }
1143453c5a92SJacob Chen 
ldo_get_value(struct udevice * dev)1144453c5a92SJacob Chen static int ldo_get_value(struct udevice *dev)
1145453c5a92SJacob Chen {
1146453c5a92SJacob Chen 	int ldo = dev->driver_data - 1;
11477f18d96cSJoseph Chen 	const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, 0);
1148453c5a92SJacob Chen 	int mask = info->vsel_mask;
1149453c5a92SJacob Chen 	int ret, val;
1150453c5a92SJacob Chen 
115104d4208bSJoseph Chen 	if (info->vsel_reg == NA)
1152453c5a92SJacob Chen 		return -ENOSYS;
1153453c5a92SJacob Chen 	ret = pmic_reg_read(dev->parent, info->vsel_reg);
1154453c5a92SJacob Chen 	if (ret < 0)
1155453c5a92SJacob Chen 		return ret;
1156453c5a92SJacob Chen 	val = ret & mask;
1157453c5a92SJacob Chen 
1158453c5a92SJacob Chen 	return info->min_uv + val * info->step_uv;
1159453c5a92SJacob Chen }
1160453c5a92SJacob Chen 
ldo_set_value(struct udevice * dev,int uvolt)1161453c5a92SJacob Chen static int ldo_set_value(struct udevice *dev, int uvolt)
1162453c5a92SJacob Chen {
1163453c5a92SJacob Chen 	int ldo = dev->driver_data - 1;
11647f18d96cSJoseph Chen 	const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, uvolt);
1165453c5a92SJacob Chen 	int mask = info->vsel_mask;
1166453c5a92SJacob Chen 	int val;
1167453c5a92SJacob Chen 
116804d4208bSJoseph Chen 	if (info->vsel_reg == NA)
1169453c5a92SJacob Chen 		return -ENOSYS;
11707f18d96cSJoseph Chen 
11717f18d96cSJoseph Chen 	if (info->step_uv == 0)
11727f18d96cSJoseph Chen 		val = info->min_sel;
11737f18d96cSJoseph Chen 	else
11747f18d96cSJoseph Chen 		val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel;
11757f18d96cSJoseph Chen 
11767f18d96cSJoseph Chen 	debug("%s: volt=%d, ldo=%d, reg=0x%x, mask=0x%x, val=0x%x\n",
11777f18d96cSJoseph Chen 	      __func__, uvolt, ldo + 1, info->vsel_reg, mask, val);
1178453c5a92SJacob Chen 
1179453c5a92SJacob Chen 	return pmic_clrsetbits(dev->parent, info->vsel_reg, mask, val);
1180453c5a92SJacob Chen }
1181453c5a92SJacob Chen 
ldo_set_suspend_value(struct udevice * dev,int uvolt)1182e917b032SJoseph Chen static int ldo_set_suspend_value(struct udevice *dev, int uvolt)
1183e917b032SJoseph Chen {
1184e917b032SJoseph Chen 	int ldo = dev->driver_data - 1;
11857f18d96cSJoseph Chen 	const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, uvolt);
1186e917b032SJoseph Chen 	int mask = info->vsel_mask;
1187e917b032SJoseph Chen 	int val;
1188e917b032SJoseph Chen 
118904d4208bSJoseph Chen 	if (info->vsel_sleep_reg == NA)
1190e917b032SJoseph Chen 		return -ENOSYS;
11917f18d96cSJoseph Chen 
11927f18d96cSJoseph Chen 	if (info->step_uv == 0)
11937f18d96cSJoseph Chen 		val = info->min_sel;
11947f18d96cSJoseph Chen 	else
11957f18d96cSJoseph Chen 		val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel;
11967f18d96cSJoseph Chen 
11977f18d96cSJoseph Chen 	debug("%s: volt=%d, ldo=%d, reg=0x%x, mask=0x%x, val=0x%x\n",
11987f18d96cSJoseph Chen 	      __func__, uvolt, ldo + 1, info->vsel_sleep_reg, mask, val);
1199e917b032SJoseph Chen 
1200e917b032SJoseph Chen 	return pmic_clrsetbits(dev->parent, info->vsel_sleep_reg, mask, val);
1201e917b032SJoseph Chen }
1202e917b032SJoseph Chen 
ldo_get_suspend_value(struct udevice * dev)1203712b6f80SJoseph Chen static int ldo_get_suspend_value(struct udevice *dev)
1204712b6f80SJoseph Chen {
1205712b6f80SJoseph Chen 	int ldo = dev->driver_data - 1;
1206712b6f80SJoseph Chen 	const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, 0);
1207712b6f80SJoseph Chen 	int mask = info->vsel_mask;
1208712b6f80SJoseph Chen 	int val, ret;
1209712b6f80SJoseph Chen 
1210712b6f80SJoseph Chen 	if (info->vsel_sleep_reg == NA)
1211712b6f80SJoseph Chen 		return -ENOSYS;
1212712b6f80SJoseph Chen 
1213712b6f80SJoseph Chen 	ret = pmic_reg_read(dev->parent, info->vsel_sleep_reg);
1214712b6f80SJoseph Chen 	if (ret < 0)
1215712b6f80SJoseph Chen 		return ret;
1216712b6f80SJoseph Chen 
1217712b6f80SJoseph Chen 	val = ret & mask;
1218712b6f80SJoseph Chen 
1219712b6f80SJoseph Chen 	return info->min_uv + val * info->step_uv;
1220712b6f80SJoseph Chen }
1221712b6f80SJoseph Chen 
ldo_set_enable(struct udevice * dev,bool enable)1222453c5a92SJacob Chen static int ldo_set_enable(struct udevice *dev, bool enable)
1223453c5a92SJacob Chen {
1224453c5a92SJacob Chen 	int ldo = dev->driver_data - 1;
1225453c5a92SJacob Chen 
12265e1bceeaSElaine Zhang 	return _ldo_set_enable(dev->parent, ldo, enable);
1227453c5a92SJacob Chen }
1228453c5a92SJacob Chen 
ldo_set_suspend_enable(struct udevice * dev,bool enable)1229e917b032SJoseph Chen static int ldo_set_suspend_enable(struct udevice *dev, bool enable)
1230e917b032SJoseph Chen {
1231e917b032SJoseph Chen 	int ldo = dev->driver_data - 1;
1232e917b032SJoseph Chen 
1233e917b032SJoseph Chen 	return _ldo_set_suspend_enable(dev->parent, ldo, enable);
1234e917b032SJoseph Chen }
1235e917b032SJoseph Chen 
ldo_get_suspend_enable(struct udevice * dev)1236712b6f80SJoseph Chen static int ldo_get_suspend_enable(struct udevice *dev)
1237712b6f80SJoseph Chen {
1238712b6f80SJoseph Chen 	int ldo = dev->driver_data - 1;
1239712b6f80SJoseph Chen 
1240712b6f80SJoseph Chen 	return _ldo_get_suspend_enable(dev->parent, ldo);
1241712b6f80SJoseph Chen }
1242712b6f80SJoseph Chen 
ldo_get_enable(struct udevice * dev)1243585c7032SKeerthy static int ldo_get_enable(struct udevice *dev)
1244453c5a92SJacob Chen {
1245453c5a92SJacob Chen 	int ldo = dev->driver_data - 1;
1246453c5a92SJacob Chen 
12475e1bceeaSElaine Zhang 	return _ldo_get_enable(dev->parent, ldo);
1248453c5a92SJacob Chen }
1249453c5a92SJacob Chen 
switch_set_enable(struct udevice * dev,bool enable)1250453c5a92SJacob Chen static int switch_set_enable(struct udevice *dev, bool enable)
1251453c5a92SJacob Chen {
12521b6b965cSJoseph Chen 	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
1253*c8147680SShengfei Xu 	const char *supply_name = { "vcc9-supply"};
12541b6b965cSJoseph Chen 	int ret = 0, sw = dev->driver_data - 1;
1255*c8147680SShengfei Xu 	struct udevice *supply;
12561b6b965cSJoseph Chen 	uint mask = 0;
1257453c5a92SJacob Chen 
12581b6b965cSJoseph Chen 	switch (priv->variant) {
12591b6b965cSJoseph Chen 	case RK808_ID:
1260453c5a92SJacob Chen 		mask = 1 << (sw + 5);
12611b6b965cSJoseph Chen 		ret = pmic_clrsetbits(dev->parent, REG_DCDC_EN, mask,
1262453c5a92SJacob Chen 				      enable ? mask : 0);
12631b6b965cSJoseph Chen 		break;
1264*c8147680SShengfei Xu 	case RK817_ID:
1265*c8147680SShengfei Xu 		sw = 0;
1266*c8147680SShengfei Xu 		mask = (1 << (sw + 2)) | (1 << (sw + 6));
1267*c8147680SShengfei Xu 		ret = pmic_clrsetbits(dev->parent, RK817_POWER_EN(3), mask,
1268*c8147680SShengfei Xu 				      enable ? mask : (1 << (sw + 6)));
1269*c8147680SShengfei Xu 		if (enable)
1270*c8147680SShengfei Xu 			if (!uclass_get_device_by_phandle(UCLASS_REGULATOR,
1271*c8147680SShengfei Xu 							  dev_get_parent(dev),
1272*c8147680SShengfei Xu 							  supply_name,
1273*c8147680SShengfei Xu 							  &supply))
1274*c8147680SShengfei Xu 				ret = regulator_set_enable(supply, enable);
1275*c8147680SShengfei Xu 		break;
12761b6b965cSJoseph Chen 	case RK809_ID:
12771b6b965cSJoseph Chen 		mask = (1 << (sw + 2)) | (1 << (sw + 6));
12781b6b965cSJoseph Chen 		ret = pmic_clrsetbits(dev->parent, RK817_POWER_EN(3), mask,
1279293182c3SWilliam Wu 				      enable ? mask : (1 << (sw + 6)));
12801b6b965cSJoseph Chen 		break;
12811b6b965cSJoseph Chen 	case RK818_ID:
12821b6b965cSJoseph Chen 		mask = 1 << 6;
12831b6b965cSJoseph Chen 		ret = pmic_clrsetbits(dev->parent, REG_DCDC_EN, mask,
12841b6b965cSJoseph Chen 				      enable ? mask : 0);
12851b6b965cSJoseph Chen 		break;
12861b6b965cSJoseph Chen 	}
12871b6b965cSJoseph Chen 
12881b6b965cSJoseph Chen 	debug("%s: switch%d, enable=%d, mask=0x%x\n",
12891b6b965cSJoseph Chen 	      __func__, sw + 1, enable, mask);
12901b6b965cSJoseph Chen 
12911b6b965cSJoseph Chen 	return ret;
1292453c5a92SJacob Chen }
1293453c5a92SJacob Chen 
switch_get_enable(struct udevice * dev)1294585c7032SKeerthy static int switch_get_enable(struct udevice *dev)
1295453c5a92SJacob Chen {
12961b6b965cSJoseph Chen 	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
1297*c8147680SShengfei Xu 	const char *supply_name = { "vcc9-supply"};
12981b6b965cSJoseph Chen 	int ret = 0, sw = dev->driver_data - 1;
1299*c8147680SShengfei Xu 	struct udevice *supply;
13001b6b965cSJoseph Chen 	uint mask = 0;
1301453c5a92SJacob Chen 
13021b6b965cSJoseph Chen 	switch (priv->variant) {
13031b6b965cSJoseph Chen 	case RK808_ID:
1304453c5a92SJacob Chen 		mask = 1 << (sw + 5);
1305453c5a92SJacob Chen 		ret = pmic_reg_read(dev->parent, REG_DCDC_EN);
13061b6b965cSJoseph Chen 		break;
1307*c8147680SShengfei Xu 	case RK817_ID:
1308*c8147680SShengfei Xu 		if (!uclass_get_device_by_phandle(UCLASS_REGULATOR,
1309*c8147680SShengfei Xu 						  dev_get_parent(dev),
1310*c8147680SShengfei Xu 						  supply_name,
1311*c8147680SShengfei Xu 						  &supply)) {
1312*c8147680SShengfei Xu 			ret = regulator_get_enable(supply);
1313*c8147680SShengfei Xu 			if (ret) {
1314*c8147680SShengfei Xu 				sw = 0;
1315*c8147680SShengfei Xu 				mask = 1 << (sw + 2);
1316*c8147680SShengfei Xu 				ret = pmic_reg_read(dev->parent, RK817_POWER_EN(3));
1317*c8147680SShengfei Xu 			} else
1318*c8147680SShengfei Xu 				ret = 0;
1319*c8147680SShengfei Xu 		}
1320*c8147680SShengfei Xu 		break;
13211b6b965cSJoseph Chen 	case RK809_ID:
13221b6b965cSJoseph Chen 		mask = 1 << (sw + 2);
13231b6b965cSJoseph Chen 		ret = pmic_reg_read(dev->parent, RK817_POWER_EN(3));
13241b6b965cSJoseph Chen 		break;
13251b6b965cSJoseph Chen 	case RK818_ID:
13261b6b965cSJoseph Chen 		mask = 1 << 6;
13271b6b965cSJoseph Chen 		ret = pmic_reg_read(dev->parent, REG_DCDC_EN);
13281b6b965cSJoseph Chen 		break;
13291b6b965cSJoseph Chen 	}
13301b6b965cSJoseph Chen 
1331453c5a92SJacob Chen 	if (ret < 0)
1332453c5a92SJacob Chen 		return ret;
1333453c5a92SJacob Chen 
1334453c5a92SJacob Chen 	return ret & mask ? true : false;
1335453c5a92SJacob Chen }
1336453c5a92SJacob Chen 
switch_set_suspend_value(struct udevice * dev,int uvolt)13371b6b965cSJoseph Chen static int switch_set_suspend_value(struct udevice *dev, int uvolt)
13381b6b965cSJoseph Chen {
13391b6b965cSJoseph Chen 	return 0;
13401b6b965cSJoseph Chen }
13411b6b965cSJoseph Chen 
switch_get_suspend_value(struct udevice * dev)1342712b6f80SJoseph Chen static int switch_get_suspend_value(struct udevice *dev)
1343712b6f80SJoseph Chen {
1344712b6f80SJoseph Chen 	return 0;
1345712b6f80SJoseph Chen }
1346712b6f80SJoseph Chen 
switch_set_suspend_enable(struct udevice * dev,bool enable)13471b6b965cSJoseph Chen static int switch_set_suspend_enable(struct udevice *dev, bool enable)
13481b6b965cSJoseph Chen {
13491b6b965cSJoseph Chen 	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
1350*c8147680SShengfei Xu 	const char *supply_name = { "vcc9-supply"};
13511b6b965cSJoseph Chen 	int ret = 0, sw = dev->driver_data - 1;
1352*c8147680SShengfei Xu 	struct udevice *supply;
13531b6b965cSJoseph Chen 	uint mask = 0;
13541b6b965cSJoseph Chen 
13551b6b965cSJoseph Chen 	switch (priv->variant) {
13561b6b965cSJoseph Chen 	case RK808_ID:
13571b6b965cSJoseph Chen 		mask = 1 << (sw + 5);
13581b6b965cSJoseph Chen 		ret = pmic_clrsetbits(dev->parent, REG_SLEEP_SET_OFF1, mask,
13591b6b965cSJoseph Chen 				      enable ? 0 : mask);
13601b6b965cSJoseph Chen 		break;
1361*c8147680SShengfei Xu 	case RK817_ID:
1362*c8147680SShengfei Xu 		sw = 0;
1363*c8147680SShengfei Xu 		mask = 1 << (sw + 6);
1364*c8147680SShengfei Xu 		ret = pmic_clrsetbits(dev->parent, RK817_POWER_SLP_EN(0), mask,
1365*c8147680SShengfei Xu 				      enable ? mask : 0);
1366*c8147680SShengfei Xu 		if (!uclass_get_device_by_phandle(UCLASS_REGULATOR,
1367*c8147680SShengfei Xu 						  dev_get_parent(dev),
1368*c8147680SShengfei Xu 						  supply_name,
1369*c8147680SShengfei Xu 						  &supply))
1370*c8147680SShengfei Xu 			ret = regulator_set_suspend_enable(supply, enable);
1371*c8147680SShengfei Xu 		break;
13721b6b965cSJoseph Chen 	case RK809_ID:
13731b6b965cSJoseph Chen 		mask = 1 << (sw + 6);
13741b6b965cSJoseph Chen 		ret = pmic_clrsetbits(dev->parent, RK817_POWER_SLP_EN(0), mask,
13751b6b965cSJoseph Chen 				      enable ? mask : 0);
13761b6b965cSJoseph Chen 		break;
13771b6b965cSJoseph Chen 	case RK818_ID:
13781b6b965cSJoseph Chen 		mask = 1 << 6;
13791b6b965cSJoseph Chen 		ret = pmic_clrsetbits(dev->parent, REG_SLEEP_SET_OFF1, mask,
13801b6b965cSJoseph Chen 				      enable ? 0 : mask);
13811b6b965cSJoseph Chen 		break;
13821b6b965cSJoseph Chen 	}
13831b6b965cSJoseph Chen 
13841b6b965cSJoseph Chen 	debug("%s: switch%d, enable=%d, mask=0x%x\n",
13851b6b965cSJoseph Chen 	      __func__, sw + 1, enable, mask);
13861b6b965cSJoseph Chen 
13871b6b965cSJoseph Chen 	return ret;
13881b6b965cSJoseph Chen }
13891b6b965cSJoseph Chen 
switch_get_suspend_enable(struct udevice * dev)1390712b6f80SJoseph Chen static int switch_get_suspend_enable(struct udevice *dev)
1391712b6f80SJoseph Chen {
1392712b6f80SJoseph Chen 	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
1393*c8147680SShengfei Xu 	const char *supply_name = { "vcc9-supply"};
1394712b6f80SJoseph Chen 	int val, ret = 0, sw = dev->driver_data - 1;
1395*c8147680SShengfei Xu 	struct udevice *supply;
1396712b6f80SJoseph Chen 	uint mask = 0;
1397712b6f80SJoseph Chen 
1398712b6f80SJoseph Chen 	switch (priv->variant) {
1399712b6f80SJoseph Chen 	case RK808_ID:
1400712b6f80SJoseph Chen 		mask = 1 << (sw + 5);
1401712b6f80SJoseph Chen 		val = pmic_reg_read(dev->parent, REG_SLEEP_SET_OFF1);
1402712b6f80SJoseph Chen 		if (val < 0)
1403712b6f80SJoseph Chen 			return val;
1404712b6f80SJoseph Chen 		ret = val & mask ? 0 : 1;
1405712b6f80SJoseph Chen 		break;
1406712b6f80SJoseph Chen 	case RK809_ID:
1407712b6f80SJoseph Chen 		mask = 1 << (sw + 6);
1408712b6f80SJoseph Chen 		val = pmic_reg_read(dev->parent, RK817_POWER_SLP_EN(0));
1409712b6f80SJoseph Chen 		if (val < 0)
1410712b6f80SJoseph Chen 			return val;
1411712b6f80SJoseph Chen 		ret = val & mask ? 1 : 0;
1412712b6f80SJoseph Chen 		break;
1413*c8147680SShengfei Xu 	case RK817_ID:
1414*c8147680SShengfei Xu 		if (!uclass_get_device_by_phandle(UCLASS_REGULATOR,
1415*c8147680SShengfei Xu 						  dev_get_parent(dev),
1416*c8147680SShengfei Xu 						  supply_name,
1417*c8147680SShengfei Xu 						  &supply)) {
1418*c8147680SShengfei Xu 			ret = regulator_get_suspend_enable(supply);
1419*c8147680SShengfei Xu 			if (ret) {
1420*c8147680SShengfei Xu 				sw = 0;
1421*c8147680SShengfei Xu 				mask = 1 << (sw + 6);
1422*c8147680SShengfei Xu 				val = pmic_reg_read(dev->parent, RK817_POWER_SLP_EN(0));
1423*c8147680SShengfei Xu 				if (val < 0)
1424*c8147680SShengfei Xu 					return val;
1425*c8147680SShengfei Xu 				ret = val & mask ? 1 : 0;
1426*c8147680SShengfei Xu 			}
1427*c8147680SShengfei Xu 		}
1428*c8147680SShengfei Xu 		break;
1429712b6f80SJoseph Chen 	case RK818_ID:
1430712b6f80SJoseph Chen 		mask = 1 << 6;
1431712b6f80SJoseph Chen 		val = pmic_reg_read(dev->parent, REG_SLEEP_SET_OFF1);
1432712b6f80SJoseph Chen 		if (val < 0)
1433712b6f80SJoseph Chen 			return val;
1434712b6f80SJoseph Chen 		ret = val & mask ? 0 : 1;
1435712b6f80SJoseph Chen 		break;
1436712b6f80SJoseph Chen 	}
1437712b6f80SJoseph Chen 
1438712b6f80SJoseph Chen 	return ret;
1439712b6f80SJoseph Chen }
1440712b6f80SJoseph Chen 
1441573b2cceSShunqing Chen /*
1442573b2cceSShunqing Chen  * RK8xx switch does not need to set the voltage,
1443573b2cceSShunqing Chen  * but if dts set regulator-min-microvolt/regulator-max-microvolt,
1444573b2cceSShunqing Chen  * will cause regulator set value fail and not to enable this switch.
1445573b2cceSShunqing Chen  * So add an empty function to return success.
1446573b2cceSShunqing Chen  */
switch_get_value(struct udevice * dev)1447573b2cceSShunqing Chen static int switch_get_value(struct udevice *dev)
1448573b2cceSShunqing Chen {
144968a90c31Sshengfei Xu 	const char *supply_name[] = { "vcc9-supply", "vcc8-supply", };
145068a90c31Sshengfei Xu 	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
145168a90c31Sshengfei Xu 	struct udevice *supply;
145268a90c31Sshengfei Xu 	int id = dev->driver_data - 1;
145368a90c31Sshengfei Xu 
145468a90c31Sshengfei Xu 	if (!switch_get_enable(dev))
145568a90c31Sshengfei Xu 		return 0;
145668a90c31Sshengfei Xu 
145768a90c31Sshengfei Xu 	/* note: rk817 only contains switch0 */
145868a90c31Sshengfei Xu 	if ((priv->variant == RK809_ID) || (priv->variant == RK817_ID)) {
145968a90c31Sshengfei Xu 		if (!uclass_get_device_by_phandle(UCLASS_REGULATOR,
146068a90c31Sshengfei Xu 						  dev_get_parent(dev),
146168a90c31Sshengfei Xu 						  supply_name[id],
146268a90c31Sshengfei Xu 						  &supply))
146368a90c31Sshengfei Xu 			return regulator_get_value(supply);
146468a90c31Sshengfei Xu 	}
146568a90c31Sshengfei Xu 
1466573b2cceSShunqing Chen 	return 0;
1467573b2cceSShunqing Chen }
1468573b2cceSShunqing Chen 
switch_set_value(struct udevice * dev,int uvolt)1469573b2cceSShunqing Chen static int switch_set_value(struct udevice *dev, int uvolt)
1470573b2cceSShunqing Chen {
1471573b2cceSShunqing Chen 	return 0;
1472573b2cceSShunqing Chen }
1473573b2cceSShunqing Chen 
get_pldo_reg(struct udevice * pmic,int num,int uvolt)1474ef9c5d10Sshengfei Xu static const struct rk8xx_reg_info *get_pldo_reg(struct udevice *pmic,
1475ef9c5d10Sshengfei Xu 						 int num, int uvolt)
1476ef9c5d10Sshengfei Xu {
1477ef9c5d10Sshengfei Xu 	struct rk8xx_priv *priv = dev_get_priv(pmic);
1478ef9c5d10Sshengfei Xu 
1479ef9c5d10Sshengfei Xu 	switch (priv->variant) {
1480ef9c5d10Sshengfei Xu 	case RK806_ID:
1481ef9c5d10Sshengfei Xu 		if (uvolt < 3400000)
1482ef9c5d10Sshengfei Xu 			return &rk806_pldo[num * 2];
1483ef9c5d10Sshengfei Xu 		else
1484ef9c5d10Sshengfei Xu 			return &rk806_pldo[num * 2 + 1];
1485ef9c5d10Sshengfei Xu 	default:
1486ef9c5d10Sshengfei Xu 		return &rk806_pldo[num * 2];
1487ef9c5d10Sshengfei Xu 	}
1488ef9c5d10Sshengfei Xu }
1489ef9c5d10Sshengfei Xu 
_pldo_get_enable(struct udevice * pmic,int pldo)1490ef9c5d10Sshengfei Xu static int _pldo_get_enable(struct udevice *pmic, int pldo)
1491ef9c5d10Sshengfei Xu {
1492ef9c5d10Sshengfei Xu 	struct rk8xx_priv *priv = dev_get_priv(pmic);
1493ef9c5d10Sshengfei Xu 	uint mask = 0, en_reg;
1494ef9c5d10Sshengfei Xu 	int ret = 0;
1495ef9c5d10Sshengfei Xu 
1496ef9c5d10Sshengfei Xu 	switch (priv->variant) {
1497ef9c5d10Sshengfei Xu 	case RK806_ID:
1498ef9c5d10Sshengfei Xu 		if ((pldo < 3) || (pldo == 5)) {
1499ef9c5d10Sshengfei Xu 			en_reg = RK806_PLDO_EN(0);
1500ef9c5d10Sshengfei Xu 			mask = RK806_PLDO0_2_SET(pldo);
1501ef9c5d10Sshengfei Xu 			if (pldo == 5)
1502ef9c5d10Sshengfei Xu 				mask = (1 << 0);
1503ef9c5d10Sshengfei Xu 			ret = pmic_reg_read(pmic, en_reg);
1504ef9c5d10Sshengfei Xu 		} else if ((pldo == 3) || (pldo == 4)) {
1505ef9c5d10Sshengfei Xu 			en_reg = RK806_PLDO_EN(1);
1506ef9c5d10Sshengfei Xu 			if (pldo == 3)
1507ef9c5d10Sshengfei Xu 				mask = (1 << 0);
1508ef9c5d10Sshengfei Xu 			else
1509ef9c5d10Sshengfei Xu 				mask = (1 << 1);
1510ef9c5d10Sshengfei Xu 			ret = pmic_reg_read(pmic, en_reg);
1511ef9c5d10Sshengfei Xu 		}
1512ef9c5d10Sshengfei Xu 		break;
1513ef9c5d10Sshengfei Xu 
1514ef9c5d10Sshengfei Xu 	default:
1515ef9c5d10Sshengfei Xu 		return -EINVAL;
1516ef9c5d10Sshengfei Xu 	}
1517ef9c5d10Sshengfei Xu 
1518ef9c5d10Sshengfei Xu 	if (ret < 0)
1519ef9c5d10Sshengfei Xu 		return ret;
1520ef9c5d10Sshengfei Xu 
1521ef9c5d10Sshengfei Xu 	return ret & mask ? true : false;
1522ef9c5d10Sshengfei Xu }
1523ef9c5d10Sshengfei Xu 
_pldo_set_enable(struct udevice * pmic,int pldo,bool enable)1524ef9c5d10Sshengfei Xu static int _pldo_set_enable(struct udevice *pmic, int pldo, bool enable)
1525ef9c5d10Sshengfei Xu {
1526ef9c5d10Sshengfei Xu 	struct rk8xx_priv *priv = dev_get_priv(pmic);
1527ef9c5d10Sshengfei Xu 	uint value, en_reg;
1528ef9c5d10Sshengfei Xu 	int ret = 0;
1529ef9c5d10Sshengfei Xu 
1530ef9c5d10Sshengfei Xu 	switch (priv->variant) {
1531ef9c5d10Sshengfei Xu 	case RK806_ID:
1532ef9c5d10Sshengfei Xu 		if (pldo < 3) {
1533ef9c5d10Sshengfei Xu 			en_reg = RK806_PLDO_EN(0);
1534ef9c5d10Sshengfei Xu 			if (enable)
1535ef9c5d10Sshengfei Xu 				value = RK806_PLDO0_2_SET(pldo);
1536ef9c5d10Sshengfei Xu 			else
1537ef9c5d10Sshengfei Xu 				value = RK806_PLDO0_2_CLR(pldo);
1538ef9c5d10Sshengfei Xu 			ret = pmic_reg_write(pmic, en_reg, value);
1539ef9c5d10Sshengfei Xu 		} else if (pldo == 3) {
1540ef9c5d10Sshengfei Xu 			en_reg = RK806_PLDO_EN(1);
1541ef9c5d10Sshengfei Xu 			if (enable)
1542ef9c5d10Sshengfei Xu 				value = ((1 << 0) | (1 << 4));
1543ef9c5d10Sshengfei Xu 			else
1544ef9c5d10Sshengfei Xu 				value = (1 << 4);
1545ef9c5d10Sshengfei Xu 			ret = pmic_reg_write(pmic, en_reg, value);
1546ef9c5d10Sshengfei Xu 		} else if (pldo == 4) {
1547ef9c5d10Sshengfei Xu 			en_reg = RK806_PLDO_EN(1);
1548ef9c5d10Sshengfei Xu 			if (enable)
1549ef9c5d10Sshengfei Xu 				value = ((1 << 1) | (1 << 5));
1550ef9c5d10Sshengfei Xu 			else
1551ef9c5d10Sshengfei Xu 				value = ((0 << 1) | (1 << 5));
1552ef9c5d10Sshengfei Xu 			ret = pmic_reg_write(pmic, en_reg, value);
1553ef9c5d10Sshengfei Xu 		} else if (pldo == 5) {
1554ef9c5d10Sshengfei Xu 			en_reg = RK806_PLDO_EN(0);
1555ef9c5d10Sshengfei Xu 			if (enable)
1556ef9c5d10Sshengfei Xu 				value = ((1 << 0) | (1 << 4));
1557ef9c5d10Sshengfei Xu 			else
1558ef9c5d10Sshengfei Xu 				value = ((0 << 0) | (1 << 4));
1559ef9c5d10Sshengfei Xu 			ret = pmic_reg_write(pmic, en_reg, value);
1560ef9c5d10Sshengfei Xu 		}
1561ef9c5d10Sshengfei Xu 
1562ef9c5d10Sshengfei Xu 		break;
1563ef9c5d10Sshengfei Xu 	default:
1564ef9c5d10Sshengfei Xu 		return -EINVAL;
1565ef9c5d10Sshengfei Xu 	}
1566ef9c5d10Sshengfei Xu 
1567ef9c5d10Sshengfei Xu 	return ret;
1568ef9c5d10Sshengfei Xu }
1569ef9c5d10Sshengfei Xu 
pldo_get_value(struct udevice * dev)1570ef9c5d10Sshengfei Xu static int pldo_get_value(struct udevice *dev)
1571ef9c5d10Sshengfei Xu {
1572ef9c5d10Sshengfei Xu 	int ldo = dev->driver_data - 1;
1573ef9c5d10Sshengfei Xu 	const struct rk8xx_reg_info *info = get_pldo_reg(dev->parent, ldo, 0);
1574ef9c5d10Sshengfei Xu 	int mask = info->vsel_mask;
1575ef9c5d10Sshengfei Xu 	int ret, val;
1576ef9c5d10Sshengfei Xu 
1577ef9c5d10Sshengfei Xu 	if (info->vsel_reg == NA)
1578ef9c5d10Sshengfei Xu 		return -EINVAL;
1579ef9c5d10Sshengfei Xu 
1580ef9c5d10Sshengfei Xu 	ret = pmic_reg_read(dev->parent, info->vsel_reg);
1581ef9c5d10Sshengfei Xu 	if (ret < 0)
1582ef9c5d10Sshengfei Xu 		return ret;
1583ef9c5d10Sshengfei Xu 	val = ret & mask;
1584ef9c5d10Sshengfei Xu 
1585ef9c5d10Sshengfei Xu 	return info->min_uv + val * info->step_uv;
1586ef9c5d10Sshengfei Xu }
1587ef9c5d10Sshengfei Xu 
pldo_set_value(struct udevice * dev,int uvolt)1588ef9c5d10Sshengfei Xu static int pldo_set_value(struct udevice *dev, int uvolt)
1589ef9c5d10Sshengfei Xu {
1590ef9c5d10Sshengfei Xu 	int ldo = dev->driver_data - 1;
1591ef9c5d10Sshengfei Xu 	const struct rk8xx_reg_info *info = get_pldo_reg(dev->parent, ldo, uvolt);
1592ef9c5d10Sshengfei Xu 	int mask = info->vsel_mask;
1593ef9c5d10Sshengfei Xu 	int val;
1594ef9c5d10Sshengfei Xu 
1595ef9c5d10Sshengfei Xu 	if (info->vsel_reg == NA)
1596ef9c5d10Sshengfei Xu 		return -EINVAL;
1597ef9c5d10Sshengfei Xu 
1598ef9c5d10Sshengfei Xu 	if (info->step_uv == 0)
1599ef9c5d10Sshengfei Xu 		val = info->min_sel;
1600ef9c5d10Sshengfei Xu 	else
1601ef9c5d10Sshengfei Xu 		val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel;
1602ef9c5d10Sshengfei Xu 
1603ef9c5d10Sshengfei Xu 	debug("%s: volt=%d, ldo=%d, reg=0x%x, mask=0x%x, val=0x%x\n",
1604ef9c5d10Sshengfei Xu 	      __func__, uvolt, ldo + 1, info->vsel_reg, mask, val);
1605ef9c5d10Sshengfei Xu 
1606ef9c5d10Sshengfei Xu 	return pmic_clrsetbits(dev->parent, info->vsel_reg, mask, val);
1607ef9c5d10Sshengfei Xu }
1608ef9c5d10Sshengfei Xu 
pldo_set_enable(struct udevice * dev,bool enable)1609ef9c5d10Sshengfei Xu static int pldo_set_enable(struct udevice *dev, bool enable)
1610ef9c5d10Sshengfei Xu {
1611ef9c5d10Sshengfei Xu 	int ldo = dev->driver_data - 1;
1612ef9c5d10Sshengfei Xu 
1613ef9c5d10Sshengfei Xu 	return _pldo_set_enable(dev->parent, ldo, enable);
1614ef9c5d10Sshengfei Xu }
1615ef9c5d10Sshengfei Xu 
pldo_get_enable(struct udevice * dev)1616ef9c5d10Sshengfei Xu static int pldo_get_enable(struct udevice *dev)
1617ef9c5d10Sshengfei Xu {
1618ef9c5d10Sshengfei Xu 	int ldo = dev->driver_data - 1;
1619ef9c5d10Sshengfei Xu 
1620ef9c5d10Sshengfei Xu 	return _pldo_get_enable(dev->parent, ldo);
1621ef9c5d10Sshengfei Xu }
1622ef9c5d10Sshengfei Xu 
pldo_set_suspend_value(struct udevice * dev,int uvolt)1623ef9c5d10Sshengfei Xu static int pldo_set_suspend_value(struct udevice *dev, int uvolt)
1624ef9c5d10Sshengfei Xu {
1625ef9c5d10Sshengfei Xu 	int ldo = dev->driver_data - 1;
1626ef9c5d10Sshengfei Xu 	const struct rk8xx_reg_info *info = get_pldo_reg(dev->parent, ldo, uvolt);;
1627ef9c5d10Sshengfei Xu 	int mask = info->vsel_mask;
1628ef9c5d10Sshengfei Xu 	int val;
1629ef9c5d10Sshengfei Xu 
1630ef9c5d10Sshengfei Xu 	if (info->vsel_sleep_reg == NA)
1631ef9c5d10Sshengfei Xu 		return -EINVAL;
1632ef9c5d10Sshengfei Xu 
1633ef9c5d10Sshengfei Xu 	if (info->step_uv == 0)
1634ef9c5d10Sshengfei Xu 		val = info->min_sel;
1635ef9c5d10Sshengfei Xu 	else
1636ef9c5d10Sshengfei Xu 		val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel;
1637ef9c5d10Sshengfei Xu 
1638ef9c5d10Sshengfei Xu 	return pmic_clrsetbits(dev->parent, info->vsel_sleep_reg, mask, val);
1639ef9c5d10Sshengfei Xu }
1640ef9c5d10Sshengfei Xu 
pldo_get_suspend_value(struct udevice * dev)1641ef9c5d10Sshengfei Xu static int pldo_get_suspend_value(struct udevice *dev)
1642ef9c5d10Sshengfei Xu {
1643ef9c5d10Sshengfei Xu 	int ldo = dev->driver_data - 1;
1644ef9c5d10Sshengfei Xu 	const struct rk8xx_reg_info *info = get_pldo_reg(dev->parent, ldo, 0);
1645ef9c5d10Sshengfei Xu 	int mask = info->vsel_mask;
1646ef9c5d10Sshengfei Xu 	int val, ret;
1647ef9c5d10Sshengfei Xu 
1648ef9c5d10Sshengfei Xu 	if (info->vsel_sleep_reg == NA)
1649ef9c5d10Sshengfei Xu 		return -EINVAL;
1650ef9c5d10Sshengfei Xu 
1651ef9c5d10Sshengfei Xu 	ret = pmic_reg_read(dev->parent, info->vsel_sleep_reg);
1652ef9c5d10Sshengfei Xu 	if (ret < 0)
1653ef9c5d10Sshengfei Xu 		return ret;
1654ef9c5d10Sshengfei Xu 
1655ef9c5d10Sshengfei Xu 	val = ret & mask;
1656ef9c5d10Sshengfei Xu 
1657ef9c5d10Sshengfei Xu 	return info->min_uv + val * info->step_uv;
1658ef9c5d10Sshengfei Xu }
1659ef9c5d10Sshengfei Xu 
_pldo_set_suspend_enable(struct udevice * pmic,int ldo,bool enable)1660ef9c5d10Sshengfei Xu static int _pldo_set_suspend_enable(struct udevice *pmic, int ldo, bool enable)
1661ef9c5d10Sshengfei Xu {
1662ef9c5d10Sshengfei Xu 	uint mask;
1663ef9c5d10Sshengfei Xu 	int ret;
1664ef9c5d10Sshengfei Xu 
1665ef9c5d10Sshengfei Xu 	if (ldo < 5)
1666ef9c5d10Sshengfei Xu 		mask = 1 << (ldo + 1);
1667ef9c5d10Sshengfei Xu 	else
1668ef9c5d10Sshengfei Xu 		mask = 1;
1669ef9c5d10Sshengfei Xu 	ret = pmic_clrsetbits(pmic, RK806_PLDO_SUSPEND_EN, mask,
1670ef9c5d10Sshengfei Xu 			      enable ? mask : 0);
1671ef9c5d10Sshengfei Xu 
1672ef9c5d10Sshengfei Xu 	return ret;
1673ef9c5d10Sshengfei Xu }
1674ef9c5d10Sshengfei Xu 
_pldo_get_suspend_enable(struct udevice * pmic,int ldo)1675ef9c5d10Sshengfei Xu static int _pldo_get_suspend_enable(struct udevice *pmic, int ldo)
1676ef9c5d10Sshengfei Xu {
1677ef9c5d10Sshengfei Xu 	uint mask, val;
1678ef9c5d10Sshengfei Xu 	int ret;
1679ef9c5d10Sshengfei Xu 
1680ef9c5d10Sshengfei Xu 	if (ldo < 5)
1681ef9c5d10Sshengfei Xu 		mask = 1 << (ldo + 1);
1682ef9c5d10Sshengfei Xu 	else
1683ef9c5d10Sshengfei Xu 		mask = 1;
1684ef9c5d10Sshengfei Xu 	val = pmic_reg_read(pmic, RK806_PLDO_SUSPEND_EN);
1685ef9c5d10Sshengfei Xu 
1686ef9c5d10Sshengfei Xu 	if (val < 0)
1687ef9c5d10Sshengfei Xu 		return val;
1688ef9c5d10Sshengfei Xu 	ret = val & mask ? 1 : 0;
1689ef9c5d10Sshengfei Xu 
1690ef9c5d10Sshengfei Xu 	return ret;
1691ef9c5d10Sshengfei Xu }
pldo_set_suspend_enable(struct udevice * dev,bool enable)1692ef9c5d10Sshengfei Xu static int pldo_set_suspend_enable(struct udevice *dev, bool enable)
1693ef9c5d10Sshengfei Xu {
1694ef9c5d10Sshengfei Xu 	int ldo = dev->driver_data - 1;
1695ef9c5d10Sshengfei Xu 
1696ef9c5d10Sshengfei Xu 	return _pldo_set_suspend_enable(dev->parent, ldo, enable);
1697ef9c5d10Sshengfei Xu }
1698ef9c5d10Sshengfei Xu 
pldo_get_suspend_enable(struct udevice * dev)1699ef9c5d10Sshengfei Xu static int pldo_get_suspend_enable(struct udevice *dev)
1700ef9c5d10Sshengfei Xu {
1701ef9c5d10Sshengfei Xu 	int ldo = dev->driver_data - 1;
1702ef9c5d10Sshengfei Xu 
1703ef9c5d10Sshengfei Xu 	return _pldo_get_suspend_enable(dev->parent, ldo);
1704ef9c5d10Sshengfei Xu }
1705ef9c5d10Sshengfei Xu 
get_boost_reg(struct udevice * pmic,int num,int uvolt)1706*c8147680SShengfei Xu static const struct rk8xx_reg_info *get_boost_reg(struct udevice *pmic,
1707*c8147680SShengfei Xu 						  int num,
1708*c8147680SShengfei Xu 						  int uvolt)
1709*c8147680SShengfei Xu {
1710*c8147680SShengfei Xu 	struct rk8xx_priv *priv = dev_get_priv(pmic);
1711*c8147680SShengfei Xu 
1712*c8147680SShengfei Xu 	switch (priv->variant) {
1713*c8147680SShengfei Xu 	case RK817_ID:
1714*c8147680SShengfei Xu 		return &rk817_boost[0];
1715*c8147680SShengfei Xu 	}
1716*c8147680SShengfei Xu 
1717*c8147680SShengfei Xu 	return NULL;
1718*c8147680SShengfei Xu }
1719*c8147680SShengfei Xu 
boost_set_enable(struct udevice * dev,bool enable)1720*c8147680SShengfei Xu static int boost_set_enable(struct udevice *dev, bool enable)
1721*c8147680SShengfei Xu {
1722*c8147680SShengfei Xu 	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
1723*c8147680SShengfei Xu 	uint mask = 0;
1724*c8147680SShengfei Xu 	int ret = 0;
1725*c8147680SShengfei Xu 
1726*c8147680SShengfei Xu 	switch (priv->variant) {
1727*c8147680SShengfei Xu 	case RK817_ID:
1728*c8147680SShengfei Xu 		mask = 0x22;
1729*c8147680SShengfei Xu 		ret = pmic_clrsetbits(dev->parent, RK817_POWER_EN(3), mask,
1730*c8147680SShengfei Xu 				      enable ? 0x22 : 0x20);
1731*c8147680SShengfei Xu 		break;
1732*c8147680SShengfei Xu 	}
1733*c8147680SShengfei Xu 
1734*c8147680SShengfei Xu 	debug("%s: boost enable=%d, mask=0x%x\n",
1735*c8147680SShengfei Xu 	      __func__, enable, mask);
1736*c8147680SShengfei Xu 
1737*c8147680SShengfei Xu 	return ret;
1738*c8147680SShengfei Xu }
1739*c8147680SShengfei Xu 
boost_get_enable(struct udevice * dev)1740*c8147680SShengfei Xu static int boost_get_enable(struct udevice *dev)
1741*c8147680SShengfei Xu {
1742*c8147680SShengfei Xu 	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
1743*c8147680SShengfei Xu 	uint mask = 0;
1744*c8147680SShengfei Xu 	int ret = 0;
1745*c8147680SShengfei Xu 
1746*c8147680SShengfei Xu 	switch (priv->variant) {
1747*c8147680SShengfei Xu 	case RK817_ID:
1748*c8147680SShengfei Xu 		mask = 0x02;
1749*c8147680SShengfei Xu 		ret = pmic_reg_read(dev->parent, RK817_POWER_EN(3));
1750*c8147680SShengfei Xu 		break;
1751*c8147680SShengfei Xu 	}
1752*c8147680SShengfei Xu 
1753*c8147680SShengfei Xu 	if (ret < 0)
1754*c8147680SShengfei Xu 		return ret;
1755*c8147680SShengfei Xu 
1756*c8147680SShengfei Xu 	return ret & mask ? true : false;
1757*c8147680SShengfei Xu }
1758*c8147680SShengfei Xu 
boost_set_suspend_value(struct udevice * dev,int uvolt)1759*c8147680SShengfei Xu static int boost_set_suspend_value(struct udevice *dev, int uvolt)
1760*c8147680SShengfei Xu {
1761*c8147680SShengfei Xu 	int boost = dev->driver_data - 1;
1762*c8147680SShengfei Xu 	const struct rk8xx_reg_info *info = get_boost_reg(dev->parent, boost, 0);
1763*c8147680SShengfei Xu 	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
1764*c8147680SShengfei Xu 	int mask = info->vsel_mask;
1765*c8147680SShengfei Xu 	int val;
1766*c8147680SShengfei Xu 
1767*c8147680SShengfei Xu 	switch (priv->variant) {
1768*c8147680SShengfei Xu 	case RK817_ID:
1769*c8147680SShengfei Xu 		if (!info)
1770*c8147680SShengfei Xu 			return -ENOSYS;
1771*c8147680SShengfei Xu 		if (info->vsel_sleep_reg == NA)
1772*c8147680SShengfei Xu 			return -ENOSYS;
1773*c8147680SShengfei Xu 
1774*c8147680SShengfei Xu 		if (info->step_uv == 0)
1775*c8147680SShengfei Xu 			val = info->min_sel;
1776*c8147680SShengfei Xu 		else
1777*c8147680SShengfei Xu 			val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel;
1778*c8147680SShengfei Xu 
1779*c8147680SShengfei Xu 		debug("%s: volt=%d, reg=0x%x, mask=0x%x, val=0x%x\n",
1780*c8147680SShengfei Xu 		      __func__, uvolt, info->vsel_sleep_reg, mask, val);
1781*c8147680SShengfei Xu 
1782*c8147680SShengfei Xu 		return pmic_clrsetbits(dev->parent, info->vsel_sleep_reg, mask, val);
1783*c8147680SShengfei Xu 	}
1784*c8147680SShengfei Xu 	return 0;
1785*c8147680SShengfei Xu }
1786*c8147680SShengfei Xu 
boost_get_suspend_value(struct udevice * dev)1787*c8147680SShengfei Xu static int boost_get_suspend_value(struct udevice *dev)
1788*c8147680SShengfei Xu {
1789*c8147680SShengfei Xu 	int boost = dev->driver_data - 1;
1790*c8147680SShengfei Xu 	const struct rk8xx_reg_info *info = get_boost_reg(dev->parent, boost, 0);
1791*c8147680SShengfei Xu 	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
1792*c8147680SShengfei Xu 	int mask = info->vsel_mask;
1793*c8147680SShengfei Xu 	int ret, val;
1794*c8147680SShengfei Xu 
1795*c8147680SShengfei Xu 	switch (priv->variant) {
1796*c8147680SShengfei Xu 	case RK817_ID:
1797*c8147680SShengfei Xu 		if (info->vsel_reg == NA)
1798*c8147680SShengfei Xu 			return -ENOSYS;
1799*c8147680SShengfei Xu 		ret = pmic_reg_read(dev->parent, info->vsel_sleep_reg);
1800*c8147680SShengfei Xu 		if (ret < 0)
1801*c8147680SShengfei Xu 			return ret;
1802*c8147680SShengfei Xu 		val = ret & mask;
1803*c8147680SShengfei Xu 
1804*c8147680SShengfei Xu 		return info->min_uv + val * info->step_uv;
1805*c8147680SShengfei Xu 	}
1806*c8147680SShengfei Xu 	return 0;
1807*c8147680SShengfei Xu }
1808*c8147680SShengfei Xu 
boost_set_suspend_enable(struct udevice * dev,bool enable)1809*c8147680SShengfei Xu static int boost_set_suspend_enable(struct udevice *dev, bool enable)
1810*c8147680SShengfei Xu {
1811*c8147680SShengfei Xu 	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
1812*c8147680SShengfei Xu 	uint mask = 0;
1813*c8147680SShengfei Xu 	int ret = 0;
1814*c8147680SShengfei Xu 
1815*c8147680SShengfei Xu 	switch (priv->variant) {
1816*c8147680SShengfei Xu 	case RK817_ID:
1817*c8147680SShengfei Xu 		mask = 1 << 5;
1818*c8147680SShengfei Xu 		ret = pmic_clrsetbits(dev->parent, RK817_POWER_SLP_EN(0), mask,
1819*c8147680SShengfei Xu 				      enable ? mask : 0);
1820*c8147680SShengfei Xu 		break;
1821*c8147680SShengfei Xu 	}
1822*c8147680SShengfei Xu 
1823*c8147680SShengfei Xu 	debug("%s: boost enable=%d, mask=0x%x\n",
1824*c8147680SShengfei Xu 	      __func__, enable, mask);
1825*c8147680SShengfei Xu 
1826*c8147680SShengfei Xu 	return ret;
1827*c8147680SShengfei Xu }
1828*c8147680SShengfei Xu 
boost_get_suspend_enable(struct udevice * dev)1829*c8147680SShengfei Xu static int boost_get_suspend_enable(struct udevice *dev)
1830*c8147680SShengfei Xu {
1831*c8147680SShengfei Xu 	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
1832*c8147680SShengfei Xu 	int val, ret = 0;
1833*c8147680SShengfei Xu 	uint mask = 0;
1834*c8147680SShengfei Xu 
1835*c8147680SShengfei Xu 	switch (priv->variant) {
1836*c8147680SShengfei Xu 	case RK817_ID:
1837*c8147680SShengfei Xu 		mask = 1 << 5;
1838*c8147680SShengfei Xu 		val = pmic_reg_read(dev->parent, RK817_POWER_SLP_EN(0));
1839*c8147680SShengfei Xu 		if (val < 0)
1840*c8147680SShengfei Xu 			return val;
1841*c8147680SShengfei Xu 		ret = val & mask ? 1 : 0;
1842*c8147680SShengfei Xu 		break;
1843*c8147680SShengfei Xu 	}
1844*c8147680SShengfei Xu 
1845*c8147680SShengfei Xu 	return ret;
1846*c8147680SShengfei Xu }
1847*c8147680SShengfei Xu 
boost_get_value(struct udevice * dev)1848*c8147680SShengfei Xu static int boost_get_value(struct udevice *dev)
1849*c8147680SShengfei Xu {
1850*c8147680SShengfei Xu 	int boost = dev->driver_data - 1;
1851*c8147680SShengfei Xu 	const struct rk8xx_reg_info *info = get_boost_reg(dev->parent, boost, 0);
1852*c8147680SShengfei Xu 	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
1853*c8147680SShengfei Xu 	int mask = info->vsel_mask;
1854*c8147680SShengfei Xu 	int ret, val;
1855*c8147680SShengfei Xu 
1856*c8147680SShengfei Xu 	switch (priv->variant) {
1857*c8147680SShengfei Xu 	case RK817_ID:
1858*c8147680SShengfei Xu 		if (info->vsel_reg == NA)
1859*c8147680SShengfei Xu 			return -ENOSYS;
1860*c8147680SShengfei Xu 		ret = pmic_reg_read(dev->parent, info->vsel_reg);
1861*c8147680SShengfei Xu 		if (ret < 0)
1862*c8147680SShengfei Xu 			return ret;
1863*c8147680SShengfei Xu 		val = ret & mask;
1864*c8147680SShengfei Xu 
1865*c8147680SShengfei Xu 		return info->min_uv + val * info->step_uv;
1866*c8147680SShengfei Xu 	}
1867*c8147680SShengfei Xu 
1868*c8147680SShengfei Xu 	return 0;
1869*c8147680SShengfei Xu }
1870*c8147680SShengfei Xu 
boost_set_value(struct udevice * dev,int uvolt)1871*c8147680SShengfei Xu static int boost_set_value(struct udevice *dev, int uvolt)
1872*c8147680SShengfei Xu {
1873*c8147680SShengfei Xu 	int boost = dev->driver_data - 1;
1874*c8147680SShengfei Xu 	const struct rk8xx_reg_info *info = get_boost_reg(dev->parent, boost, 0);
1875*c8147680SShengfei Xu 	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
1876*c8147680SShengfei Xu 	int mask = info->vsel_mask;
1877*c8147680SShengfei Xu 	int val;
1878*c8147680SShengfei Xu 
1879*c8147680SShengfei Xu 	switch (priv->variant) {
1880*c8147680SShengfei Xu 	case RK817_ID:
1881*c8147680SShengfei Xu 		if (!info)
1882*c8147680SShengfei Xu 			return -ENOSYS;
1883*c8147680SShengfei Xu 
1884*c8147680SShengfei Xu 		if (info->vsel_reg == NA)
1885*c8147680SShengfei Xu 			return -ENOSYS;
1886*c8147680SShengfei Xu 
1887*c8147680SShengfei Xu 		if (info->step_uv == 0)
1888*c8147680SShengfei Xu 			val = info->min_sel;
1889*c8147680SShengfei Xu 		else
1890*c8147680SShengfei Xu 			val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel;
1891*c8147680SShengfei Xu 
1892*c8147680SShengfei Xu 		debug("%s: volt=%d, reg=0x%x, mask=0x%x, val=0x%x\n",
1893*c8147680SShengfei Xu 		      __func__, uvolt, info->vsel_reg, mask, val);
1894*c8147680SShengfei Xu 
1895*c8147680SShengfei Xu 		return pmic_clrsetbits(dev->parent, info->vsel_reg, mask, val);
1896*c8147680SShengfei Xu 	}
1897*c8147680SShengfei Xu 
1898*c8147680SShengfei Xu 	return 0;
1899*c8147680SShengfei Xu }
1900*c8147680SShengfei Xu 
rk8xx_buck_probe(struct udevice * dev)1901453c5a92SJacob Chen static int rk8xx_buck_probe(struct udevice *dev)
1902453c5a92SJacob Chen {
1903453c5a92SJacob Chen 	struct dm_regulator_uclass_platdata *uc_pdata;
1904453c5a92SJacob Chen 
1905453c5a92SJacob Chen 	uc_pdata = dev_get_uclass_platdata(dev);
1906453c5a92SJacob Chen 
1907453c5a92SJacob Chen 	uc_pdata->type = REGULATOR_TYPE_BUCK;
1908453c5a92SJacob Chen 	uc_pdata->mode_count = 0;
1909453c5a92SJacob Chen 
1910453c5a92SJacob Chen 	return 0;
1911453c5a92SJacob Chen }
1912453c5a92SJacob Chen 
rk8xx_ldo_probe(struct udevice * dev)1913453c5a92SJacob Chen static int rk8xx_ldo_probe(struct udevice *dev)
1914453c5a92SJacob Chen {
1915453c5a92SJacob Chen 	struct dm_regulator_uclass_platdata *uc_pdata;
1916453c5a92SJacob Chen 
1917453c5a92SJacob Chen 	uc_pdata = dev_get_uclass_platdata(dev);
1918453c5a92SJacob Chen 
1919453c5a92SJacob Chen 	uc_pdata->type = REGULATOR_TYPE_LDO;
1920453c5a92SJacob Chen 	uc_pdata->mode_count = 0;
1921453c5a92SJacob Chen 
1922453c5a92SJacob Chen 	return 0;
1923453c5a92SJacob Chen }
1924453c5a92SJacob Chen 
rk8xx_switch_probe(struct udevice * dev)1925453c5a92SJacob Chen static int rk8xx_switch_probe(struct udevice *dev)
1926453c5a92SJacob Chen {
1927453c5a92SJacob Chen 	struct dm_regulator_uclass_platdata *uc_pdata;
1928453c5a92SJacob Chen 
1929453c5a92SJacob Chen 	uc_pdata = dev_get_uclass_platdata(dev);
1930453c5a92SJacob Chen 
1931453c5a92SJacob Chen 	uc_pdata->type = REGULATOR_TYPE_FIXED;
1932453c5a92SJacob Chen 	uc_pdata->mode_count = 0;
1933453c5a92SJacob Chen 
1934453c5a92SJacob Chen 	return 0;
1935453c5a92SJacob Chen }
1936453c5a92SJacob Chen 
rk8xx_pldo_probe(struct udevice * dev)1937ef9c5d10Sshengfei Xu static int rk8xx_pldo_probe(struct udevice *dev)
1938ef9c5d10Sshengfei Xu {
1939ef9c5d10Sshengfei Xu 	struct dm_regulator_uclass_platdata *uc_pdata;
1940ef9c5d10Sshengfei Xu 
1941ef9c5d10Sshengfei Xu 	uc_pdata = dev_get_uclass_platdata(dev);
1942ef9c5d10Sshengfei Xu 	uc_pdata->type = REGULATOR_TYPE_LDO;
1943ef9c5d10Sshengfei Xu 	uc_pdata->mode_count = 0;
1944ef9c5d10Sshengfei Xu 
1945ef9c5d10Sshengfei Xu 	return 0;
1946ef9c5d10Sshengfei Xu }
1947ef9c5d10Sshengfei Xu 
rk8xx_boost_probe(struct udevice * dev)1948*c8147680SShengfei Xu static int rk8xx_boost_probe(struct udevice *dev)
1949*c8147680SShengfei Xu {
1950*c8147680SShengfei Xu 	struct dm_regulator_uclass_platdata *uc_pdata;
1951*c8147680SShengfei Xu 
1952*c8147680SShengfei Xu 	uc_pdata = dev_get_uclass_platdata(dev);
1953*c8147680SShengfei Xu 
1954*c8147680SShengfei Xu 	uc_pdata->type = REGULATOR_TYPE_FIXED;
1955*c8147680SShengfei Xu 	uc_pdata->mode_count = 0;
1956*c8147680SShengfei Xu 
1957*c8147680SShengfei Xu 	return 0;
1958*c8147680SShengfei Xu }
1959*c8147680SShengfei Xu 
1960453c5a92SJacob Chen static const struct dm_regulator_ops rk8xx_buck_ops = {
1961453c5a92SJacob Chen 	.get_value  = buck_get_value,
1962453c5a92SJacob Chen 	.set_value  = buck_set_value,
1963e917b032SJoseph Chen 	.set_suspend_value = buck_set_suspend_value,
1964712b6f80SJoseph Chen 	.get_suspend_value = buck_get_suspend_value,
1965453c5a92SJacob Chen 	.get_enable = buck_get_enable,
1966453c5a92SJacob Chen 	.set_enable = buck_set_enable,
1967e917b032SJoseph Chen 	.set_suspend_enable = buck_set_suspend_enable,
1968712b6f80SJoseph Chen 	.get_suspend_enable = buck_get_suspend_enable,
1969868bdcf3SJoseph Chen 	.set_ramp_delay = buck_set_ramp_delay,
1970453c5a92SJacob Chen };
1971453c5a92SJacob Chen 
1972453c5a92SJacob Chen static const struct dm_regulator_ops rk8xx_ldo_ops = {
1973453c5a92SJacob Chen 	.get_value  = ldo_get_value,
1974453c5a92SJacob Chen 	.set_value  = ldo_set_value,
1975e917b032SJoseph Chen 	.set_suspend_value = ldo_set_suspend_value,
1976712b6f80SJoseph Chen 	.get_suspend_value = ldo_get_suspend_value,
1977453c5a92SJacob Chen 	.get_enable = ldo_get_enable,
1978453c5a92SJacob Chen 	.set_enable = ldo_set_enable,
1979e917b032SJoseph Chen 	.set_suspend_enable = ldo_set_suspend_enable,
1980712b6f80SJoseph Chen 	.get_suspend_enable = ldo_get_suspend_enable,
1981453c5a92SJacob Chen };
1982453c5a92SJacob Chen 
1983453c5a92SJacob Chen static const struct dm_regulator_ops rk8xx_switch_ops = {
1984573b2cceSShunqing Chen 	.get_value  = switch_get_value,
1985573b2cceSShunqing Chen 	.set_value  = switch_set_value,
1986453c5a92SJacob Chen 	.get_enable = switch_get_enable,
1987453c5a92SJacob Chen 	.set_enable = switch_set_enable,
19881b6b965cSJoseph Chen 	.set_suspend_enable = switch_set_suspend_enable,
1989712b6f80SJoseph Chen 	.get_suspend_enable = switch_get_suspend_enable,
19901b6b965cSJoseph Chen 	.set_suspend_value = switch_set_suspend_value,
1991712b6f80SJoseph Chen 	.get_suspend_value = switch_get_suspend_value,
1992453c5a92SJacob Chen };
1993453c5a92SJacob Chen 
1994ef9c5d10Sshengfei Xu static const struct dm_regulator_ops rk8xx_pldo_ops = {
1995ef9c5d10Sshengfei Xu 	.get_value  = pldo_get_value,
1996ef9c5d10Sshengfei Xu 	.set_value  = pldo_set_value,
1997ef9c5d10Sshengfei Xu 	.set_suspend_value = pldo_set_suspend_value,
1998ef9c5d10Sshengfei Xu 	.get_suspend_value = pldo_get_suspend_value,
1999ef9c5d10Sshengfei Xu 	.get_enable = pldo_get_enable,
2000ef9c5d10Sshengfei Xu 	.set_enable = pldo_set_enable,
2001ef9c5d10Sshengfei Xu 	.set_suspend_enable = pldo_set_suspend_enable,
2002ef9c5d10Sshengfei Xu 	.get_suspend_enable = pldo_get_suspend_enable,
2003ef9c5d10Sshengfei Xu };
2004ef9c5d10Sshengfei Xu 
2005*c8147680SShengfei Xu static const struct dm_regulator_ops rk8xx_boost_ops = {
2006*c8147680SShengfei Xu 	.get_value  = boost_get_value,
2007*c8147680SShengfei Xu 	.set_value  = boost_set_value,
2008*c8147680SShengfei Xu 	.get_enable = boost_get_enable,
2009*c8147680SShengfei Xu 	.set_enable = boost_set_enable,
2010*c8147680SShengfei Xu 	.set_suspend_enable = boost_set_suspend_enable,
2011*c8147680SShengfei Xu 	.get_suspend_enable = boost_get_suspend_enable,
2012*c8147680SShengfei Xu 	.set_suspend_value = boost_set_suspend_value,
2013*c8147680SShengfei Xu 	.get_suspend_value = boost_get_suspend_value,
2014*c8147680SShengfei Xu };
2015*c8147680SShengfei Xu 
2016453c5a92SJacob Chen U_BOOT_DRIVER(rk8xx_buck) = {
2017453c5a92SJacob Chen 	.name = "rk8xx_buck",
2018453c5a92SJacob Chen 	.id = UCLASS_REGULATOR,
2019453c5a92SJacob Chen 	.ops = &rk8xx_buck_ops,
2020453c5a92SJacob Chen 	.probe = rk8xx_buck_probe,
2021453c5a92SJacob Chen };
2022453c5a92SJacob Chen 
2023453c5a92SJacob Chen U_BOOT_DRIVER(rk8xx_ldo) = {
2024453c5a92SJacob Chen 	.name = "rk8xx_ldo",
2025453c5a92SJacob Chen 	.id = UCLASS_REGULATOR,
2026453c5a92SJacob Chen 	.ops = &rk8xx_ldo_ops,
2027453c5a92SJacob Chen 	.probe = rk8xx_ldo_probe,
2028453c5a92SJacob Chen };
2029453c5a92SJacob Chen 
2030453c5a92SJacob Chen U_BOOT_DRIVER(rk8xx_switch) = {
2031453c5a92SJacob Chen 	.name = "rk8xx_switch",
2032453c5a92SJacob Chen 	.id = UCLASS_REGULATOR,
2033453c5a92SJacob Chen 	.ops = &rk8xx_switch_ops,
2034453c5a92SJacob Chen 	.probe = rk8xx_switch_probe,
2035453c5a92SJacob Chen };
2036ef9c5d10Sshengfei Xu 
2037ef9c5d10Sshengfei Xu U_BOOT_DRIVER(rk8xx_spi_pldo) = {
2038ef9c5d10Sshengfei Xu 	.name = "rk8xx_pldo",
2039ef9c5d10Sshengfei Xu 	.id = UCLASS_REGULATOR,
2040ef9c5d10Sshengfei Xu 	.ops = &rk8xx_pldo_ops,
2041ef9c5d10Sshengfei Xu 	.probe = rk8xx_pldo_probe,
2042ef9c5d10Sshengfei Xu };
2043*c8147680SShengfei Xu 
2044*c8147680SShengfei Xu U_BOOT_DRIVER(rk8xx_boost) = {
2045*c8147680SShengfei Xu 	.name = "rk8xx_boost",
2046*c8147680SShengfei Xu 	.id = UCLASS_REGULATOR,
2047*c8147680SShengfei Xu 	.ops = &rk8xx_boost_ops,
2048*c8147680SShengfei Xu 	.probe = rk8xx_boost_probe,
2049*c8147680SShengfei Xu };
2050453c5a92SJacob Chen #endif
2051453c5a92SJacob Chen 
rk8xx_spl_configure_buck(struct udevice * pmic,int buck,int uvolt)2052453c5a92SJacob Chen int rk8xx_spl_configure_buck(struct udevice *pmic, int buck, int uvolt)
2053453c5a92SJacob Chen {
2054453c5a92SJacob Chen 	int ret;
2055453c5a92SJacob Chen 
2056453c5a92SJacob Chen 	ret = _buck_set_value(pmic, buck, uvolt);
2057453c5a92SJacob Chen 	if (ret)
2058453c5a92SJacob Chen 		return ret;
2059453c5a92SJacob Chen 
2060453c5a92SJacob Chen 	return _buck_set_enable(pmic, buck, true);
2061453c5a92SJacob Chen }
2062ad98f882SWadim Egorov 
rk818_spl_configure_usb_input_current(struct udevice * pmic,int current_ma)2063ad98f882SWadim Egorov int rk818_spl_configure_usb_input_current(struct udevice *pmic, int current_ma)
2064ad98f882SWadim Egorov {
2065ad98f882SWadim Egorov 	uint i;
2066ad98f882SWadim Egorov 
2067ad98f882SWadim Egorov 	for (i = 0; i < ARRAY_SIZE(rk818_chrg_cur_input_array); i++)
2068ad98f882SWadim Egorov 		if (current_ma <= rk818_chrg_cur_input_array[i])
2069ad98f882SWadim Egorov 			break;
2070ad98f882SWadim Egorov 
2071ad98f882SWadim Egorov 	return pmic_clrsetbits(pmic, REG_USB_CTRL, RK818_USB_ILIM_SEL_MASK, i);
2072ad98f882SWadim Egorov }
2073ad98f882SWadim Egorov 
rk818_spl_configure_usb_chrg_shutdown(struct udevice * pmic,int uvolt)2074ad98f882SWadim Egorov int rk818_spl_configure_usb_chrg_shutdown(struct udevice *pmic, int uvolt)
2075ad98f882SWadim Egorov {
2076ad98f882SWadim Egorov 	uint i;
2077ad98f882SWadim Egorov 
2078ad98f882SWadim Egorov 	for (i = 0; i < ARRAY_SIZE(rk818_chrg_shutdown_vsel_array); i++)
2079ad98f882SWadim Egorov 		if (uvolt <= rk818_chrg_shutdown_vsel_array[i])
2080ad98f882SWadim Egorov 			break;
2081ad98f882SWadim Egorov 
2082ad98f882SWadim Egorov 	return pmic_clrsetbits(pmic, REG_USB_CTRL, RK818_USB_CHG_SD_VSEL_MASK,
2083ad98f882SWadim Egorov 			       i);
2084ad98f882SWadim Egorov }
2085