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