blob: e95640a39b0a59618f9ec9c9220e33c019b516ca [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glassadecfef2016-01-21 19:43:30 -07002/*
3 * Copyright (C) 2015 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
5 *
6 * Based on Rockchip's drivers/power/pmic/pmic_rk808.c:
7 * Copyright (C) 2012 rockchips
8 * zyw <zyw@rock-chips.com>
Simon Glassadecfef2016-01-21 19:43:30 -07009 */
10
11#include <common.h>
12#include <dm.h>
13#include <errno.h>
Simon Glass0f2af882020-05-10 11:40:05 -060014#include <log.h>
Jonas Karlman31c3c802023-07-02 12:41:15 +000015#include <linux/delay.h>
Jacob Chen614704b2017-05-02 14:54:52 +080016#include <power/rk8xx_pmic.h>
Simon Glassadecfef2016-01-21 19:43:30 -070017#include <power/pmic.h>
18#include <power/regulator.h>
19
20#ifndef CONFIG_SPL_BUILD
21#define ENABLE_DRIVER
22#endif
23
Elaine Zhangfa9cccc2019-09-26 15:43:53 +080024/* Not used or exisit register and configure */
25#define NA 0xff
26
Jacob Chen21a6a252017-05-02 14:54:50 +080027/* Field Definitions */
28#define RK808_BUCK_VSEL_MASK 0x3f
29#define RK808_BUCK4_VSEL_MASK 0xf
30#define RK808_LDO_VSEL_MASK 0x1f
31
Joseph Chend6b3e832019-09-26 15:45:07 +080032/* RK809 BUCK5 */
33#define RK809_BUCK5_CONFIG(n) (0xde + (n) * 1)
34#define RK809_BUCK5_VSEL_MASK 0x07
35
Joseph Chen4a1ae182019-09-26 15:44:55 +080036/* RK817 BUCK */
37#define RK817_BUCK_ON_VSEL(n) (0xbb + 3 * ((n) - 1))
38#define RK817_BUCK_SLP_VSEL(n) (0xbc + 3 * ((n) - 1))
39#define RK817_BUCK_VSEL_MASK 0x7f
40#define RK817_BUCK_CONFIG(i) (0xba + (i) * 3)
41
42/* RK817 LDO */
43#define RK817_LDO_ON_VSEL(n) (0xcc + 2 * ((n) - 1))
44#define RK817_LDO_SLP_VSEL(n) (0xcd + 2 * ((n) - 1))
45#define RK817_LDO_VSEL_MASK 0x7f
46
47/* RK817 ENABLE */
48#define RK817_POWER_EN(n) (0xb1 + (n))
49#define RK817_POWER_SLP_EN(n) (0xb5 + (n))
50
Jacob Chen36163e32017-05-02 14:54:51 +080051#define RK818_BUCK_VSEL_MASK 0x3f
52#define RK818_BUCK4_VSEL_MASK 0x1f
53#define RK818_LDO_VSEL_MASK 0x1f
54#define RK818_LDO3_ON_VSEL_MASK 0xf
55#define RK818_BOOST_ON_VSEL_MASK 0xe0
Wadim Egorovc2581052017-06-19 12:36:39 +020056#define RK818_USB_ILIM_SEL_MASK 0x0f
57#define RK818_USB_CHG_SD_VSEL_MASK 0x70
58
Elaine Zhangfa9cccc2019-09-26 15:43:53 +080059/*
60 * Ramp delay
61 */
Elaine Zhang1d9077e2019-09-26 15:43:55 +080062#define RK805_RAMP_RATE_OFFSET 3
63#define RK805_RAMP_RATE_MASK (3 << RK805_RAMP_RATE_OFFSET)
64#define RK805_RAMP_RATE_3MV_PER_US (0 << RK805_RAMP_RATE_OFFSET)
65#define RK805_RAMP_RATE_6MV_PER_US (1 << RK805_RAMP_RATE_OFFSET)
66#define RK805_RAMP_RATE_12_5MV_PER_US (2 << RK805_RAMP_RATE_OFFSET)
67#define RK805_RAMP_RATE_25MV_PER_US (3 << RK805_RAMP_RATE_OFFSET)
Joseph Chend6b3e832019-09-26 15:45:07 +080068
Elaine Zhangfa9cccc2019-09-26 15:43:53 +080069#define RK808_RAMP_RATE_OFFSET 3
70#define RK808_RAMP_RATE_MASK (3 << RK808_RAMP_RATE_OFFSET)
71#define RK808_RAMP_RATE_2MV_PER_US (0 << RK808_RAMP_RATE_OFFSET)
72#define RK808_RAMP_RATE_4MV_PER_US (1 << RK808_RAMP_RATE_OFFSET)
73#define RK808_RAMP_RATE_6MV_PER_US (2 << RK808_RAMP_RATE_OFFSET)
74#define RK808_RAMP_RATE_10MV_PER_US (3 << RK808_RAMP_RATE_OFFSET)
Jacob Chen36163e32017-05-02 14:54:51 +080075
Joseph Chen4a1ae182019-09-26 15:44:55 +080076#define RK817_RAMP_RATE_OFFSET 6
77#define RK817_RAMP_RATE_MASK (0x3 << RK817_RAMP_RATE_OFFSET)
78#define RK817_RAMP_RATE_3MV_PER_US (0x0 << RK817_RAMP_RATE_OFFSET)
79#define RK817_RAMP_RATE_6_3MV_PER_US (0x1 << RK817_RAMP_RATE_OFFSET)
80#define RK817_RAMP_RATE_12_5MV_PER_US (0x2 << RK817_RAMP_RATE_OFFSET)
81#define RK817_RAMP_RATE_25MV_PER_US (0x3 << RK817_RAMP_RATE_OFFSET)
82
Jacob Chen614704b2017-05-02 14:54:52 +080083struct rk8xx_reg_info {
Simon Glassadecfef2016-01-21 19:43:30 -070084 uint min_uv;
85 uint step_uv;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +080086 u8 vsel_reg;
87 u8 vsel_sleep_reg;
88 u8 config_reg;
Jacob Chen21a6a252017-05-02 14:54:50 +080089 u8 vsel_mask;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +080090 u8 min_sel;
Simon Glassadecfef2016-01-21 19:43:30 -070091};
92
Jacob Chen614704b2017-05-02 14:54:52 +080093static const struct rk8xx_reg_info rk808_buck[] = {
Elaine Zhangfa9cccc2019-09-26 15:43:53 +080094 { 712500, 12500, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, REG_BUCK1_CONFIG, RK808_BUCK_VSEL_MASK, },
95 { 712500, 12500, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, REG_BUCK2_CONFIG, RK808_BUCK_VSEL_MASK, },
96 { 712500, 12500, NA, NA, REG_BUCK3_CONFIG, RK808_BUCK_VSEL_MASK, },
97 { 1800000, 100000, REG_BUCK4_ON_VSEL, REG_BUCK4_SLP_VSEL, REG_BUCK4_CONFIG, RK808_BUCK4_VSEL_MASK, },
Simon Glassadecfef2016-01-21 19:43:30 -070098};
99
Elaine Zhang04e5a432019-09-26 15:43:54 +0800100static const struct rk8xx_reg_info rk816_buck[] = {
101 /* buck 1 */
102 { 712500, 12500, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, REG_BUCK1_CONFIG, RK818_BUCK_VSEL_MASK, 0x00, },
103 { 1800000, 200000, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, REG_BUCK1_CONFIG, RK818_BUCK_VSEL_MASK, 0x3c, },
104 { 2300000, 0, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, REG_BUCK1_CONFIG, RK818_BUCK_VSEL_MASK, 0x3f, },
105 /* buck 2 */
106 { 712500, 12500, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, REG_BUCK2_CONFIG, RK818_BUCK_VSEL_MASK, 0x00, },
107 { 1800000, 200000, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, REG_BUCK2_CONFIG, RK818_BUCK_VSEL_MASK, 0x3c, },
108 { 2300000, 0, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, REG_BUCK2_CONFIG, RK818_BUCK_VSEL_MASK, 0x3f, },
109 /* buck 3 */
110 { 712500, 12500, NA, NA, REG_BUCK3_CONFIG, RK818_BUCK_VSEL_MASK, },
111 /* buck 4 */
112 { 800000, 100000, REG_BUCK4_ON_VSEL, REG_BUCK4_SLP_VSEL, REG_BUCK4_CONFIG, RK818_BUCK4_VSEL_MASK, },
113};
114
Joseph Chend6b3e832019-09-26 15:45:07 +0800115static const struct rk8xx_reg_info rk809_buck5[] = {
116 /* buck 5 */
117 { 1500000, 0, RK809_BUCK5_CONFIG(0), RK809_BUCK5_CONFIG(1), NA, RK809_BUCK5_VSEL_MASK, 0x00, },
118 { 1800000, 200000, RK809_BUCK5_CONFIG(0), RK809_BUCK5_CONFIG(1), NA, RK809_BUCK5_VSEL_MASK, 0x01, },
119 { 2800000, 200000, RK809_BUCK5_CONFIG(0), RK809_BUCK5_CONFIG(1), NA, RK809_BUCK5_VSEL_MASK, 0x04, },
120 { 3300000, 300000, RK809_BUCK5_CONFIG(0), RK809_BUCK5_CONFIG(1), NA, RK809_BUCK5_VSEL_MASK, 0x06, },
121};
122
Joseph Chen4a1ae182019-09-26 15:44:55 +0800123static const struct rk8xx_reg_info rk817_buck[] = {
124 /* buck 1 */
125 { 500000, 12500, RK817_BUCK_ON_VSEL(1), RK817_BUCK_SLP_VSEL(1), RK817_BUCK_CONFIG(1), RK817_BUCK_VSEL_MASK, 0x00, },
126 { 1500000, 100000, RK817_BUCK_ON_VSEL(1), RK817_BUCK_SLP_VSEL(1), RK817_BUCK_CONFIG(1), RK817_BUCK_VSEL_MASK, 0x50, },
127 { 2400000, 0, RK817_BUCK_ON_VSEL(1), RK817_BUCK_SLP_VSEL(1), RK817_BUCK_CONFIG(1), RK817_BUCK_VSEL_MASK, 0x59, },
128 /* buck 2 */
129 { 500000, 12500, RK817_BUCK_ON_VSEL(2), RK817_BUCK_SLP_VSEL(2), RK817_BUCK_CONFIG(2), RK817_BUCK_VSEL_MASK, 0x00, },
130 { 1500000, 100000, RK817_BUCK_ON_VSEL(2), RK817_BUCK_SLP_VSEL(2), RK817_BUCK_CONFIG(2), RK817_BUCK_VSEL_MASK, 0x50, },
131 { 2400000, 0, RK817_BUCK_ON_VSEL(2), RK817_BUCK_SLP_VSEL(2), RK817_BUCK_CONFIG(2), RK817_BUCK_VSEL_MASK, 0x59, },
132 /* buck 3 */
133 { 500000, 12500, RK817_BUCK_ON_VSEL(3), RK817_BUCK_SLP_VSEL(3), RK817_BUCK_CONFIG(3), RK817_BUCK_VSEL_MASK, 0x00, },
134 { 1500000, 100000, RK817_BUCK_ON_VSEL(3), RK817_BUCK_SLP_VSEL(3), RK817_BUCK_CONFIG(3), RK817_BUCK_VSEL_MASK, 0x50, },
135 { 2400000, 0, RK817_BUCK_ON_VSEL(3), RK817_BUCK_SLP_VSEL(3), RK817_BUCK_CONFIG(3), RK817_BUCK_VSEL_MASK, 0x59, },
136 /* buck 4 */
137 { 500000, 12500, RK817_BUCK_ON_VSEL(4), RK817_BUCK_SLP_VSEL(4), RK817_BUCK_CONFIG(4), RK817_BUCK_VSEL_MASK, 0x00, },
138 { 1500000, 100000, RK817_BUCK_ON_VSEL(4), RK817_BUCK_SLP_VSEL(4), RK817_BUCK_CONFIG(4), RK817_BUCK_VSEL_MASK, 0x50, },
139 { 3400000, 0, RK817_BUCK_ON_VSEL(4), RK817_BUCK_SLP_VSEL(4), RK817_BUCK_CONFIG(4), RK817_BUCK_VSEL_MASK, 0x63, },
140};
141
Wadim Egorov4c4905f2017-06-19 12:36:38 +0200142static const struct rk8xx_reg_info rk818_buck[] = {
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800143 { 712500, 12500, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, REG_BUCK1_CONFIG, RK818_BUCK_VSEL_MASK, },
144 { 712500, 12500, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, REG_BUCK2_CONFIG, RK818_BUCK_VSEL_MASK, },
145 { 712500, 12500, NA, NA, REG_BUCK3_CONFIG, RK818_BUCK_VSEL_MASK, },
146 { 1800000, 100000, REG_BUCK4_ON_VSEL, REG_BUCK4_SLP_VSEL, REG_BUCK4_CONFIG, RK818_BUCK4_VSEL_MASK, },
Wadim Egorov4c4905f2017-06-19 12:36:38 +0200147};
148
149#ifdef ENABLE_DRIVER
Jacob Chen614704b2017-05-02 14:54:52 +0800150static const struct rk8xx_reg_info rk808_ldo[] = {
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800151 { 1800000, 100000, REG_LDO1_ON_VSEL, REG_LDO1_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
152 { 1800000, 100000, REG_LDO2_ON_VSEL, REG_LDO2_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
153 { 800000, 100000, REG_LDO3_ON_VSEL, REG_LDO3_SLP_VSEL, NA, RK808_BUCK4_VSEL_MASK, },
154 { 1800000, 100000, REG_LDO4_ON_VSEL, REG_LDO4_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
155 { 1800000, 100000, REG_LDO5_ON_VSEL, REG_LDO5_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
156 { 800000, 100000, REG_LDO6_ON_VSEL, REG_LDO6_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
157 { 800000, 100000, REG_LDO7_ON_VSEL, REG_LDO7_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
158 { 1800000, 100000, REG_LDO8_ON_VSEL, REG_LDO8_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
Simon Glassadecfef2016-01-21 19:43:30 -0700159};
160
Elaine Zhang04e5a432019-09-26 15:43:54 +0800161static const struct rk8xx_reg_info rk816_ldo[] = {
162 { 800000, 100000, REG_LDO1_ON_VSEL, REG_LDO1_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
163 { 800000, 100000, REG_LDO2_ON_VSEL, REG_LDO2_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
164 { 800000, 100000, REG_LDO3_ON_VSEL, REG_LDO3_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
165 { 800000, 100000, REG_LDO4_ON_VSEL, REG_LDO4_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
166 { 800000, 100000, REG_LDO5_ON_VSEL, REG_LDO5_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
167 { 800000, 100000, REG_LDO6_ON_VSEL, REG_LDO6_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
168};
169
Joseph Chen4a1ae182019-09-26 15:44:55 +0800170static const struct rk8xx_reg_info rk817_ldo[] = {
171 /* ldo1 */
172 { 600000, 25000, RK817_LDO_ON_VSEL(1), RK817_LDO_SLP_VSEL(1), NA, RK817_LDO_VSEL_MASK, 0x00, },
173 { 3400000, 0, RK817_LDO_ON_VSEL(1), RK817_LDO_SLP_VSEL(1), NA, RK817_LDO_VSEL_MASK, 0x70, },
174 /* ldo2 */
175 { 600000, 25000, RK817_LDO_ON_VSEL(2), RK817_LDO_SLP_VSEL(2), NA, RK817_LDO_VSEL_MASK, 0x00, },
176 { 3400000, 0, RK817_LDO_ON_VSEL(2), RK817_LDO_SLP_VSEL(2), NA, RK817_LDO_VSEL_MASK, 0x70, },
177 /* ldo3 */
178 { 600000, 25000, RK817_LDO_ON_VSEL(3), RK817_LDO_SLP_VSEL(3), NA, RK817_LDO_VSEL_MASK, 0x00, },
179 { 3400000, 0, RK817_LDO_ON_VSEL(3), RK817_LDO_SLP_VSEL(3), NA, RK817_LDO_VSEL_MASK, 0x70, },
180 /* ldo4 */
181 { 600000, 25000, RK817_LDO_ON_VSEL(4), RK817_LDO_SLP_VSEL(4), NA, RK817_LDO_VSEL_MASK, 0x00, },
182 { 3400000, 0, RK817_LDO_ON_VSEL(4), RK817_LDO_SLP_VSEL(4), NA, RK817_LDO_VSEL_MASK, 0x70, },
183 /* ldo5 */
184 { 600000, 25000, RK817_LDO_ON_VSEL(5), RK817_LDO_SLP_VSEL(5), NA, RK817_LDO_VSEL_MASK, 0x00, },
185 { 3400000, 0, RK817_LDO_ON_VSEL(5), RK817_LDO_SLP_VSEL(5), NA, RK817_LDO_VSEL_MASK, 0x70, },
186 /* ldo6 */
187 { 600000, 25000, RK817_LDO_ON_VSEL(6), RK817_LDO_SLP_VSEL(6), NA, RK817_LDO_VSEL_MASK, 0x00, },
188 { 3400000, 0, RK817_LDO_ON_VSEL(6), RK817_LDO_SLP_VSEL(6), NA, RK817_LDO_VSEL_MASK, 0x70, },
189 /* ldo7 */
190 { 600000, 25000, RK817_LDO_ON_VSEL(7), RK817_LDO_SLP_VSEL(7), NA, RK817_LDO_VSEL_MASK, 0x00, },
191 { 3400000, 0, RK817_LDO_ON_VSEL(7), RK817_LDO_SLP_VSEL(7), NA, RK817_LDO_VSEL_MASK, 0x70, },
192 /* ldo8 */
193 { 600000, 25000, RK817_LDO_ON_VSEL(8), RK817_LDO_SLP_VSEL(8), NA, RK817_LDO_VSEL_MASK, 0x00, },
194 { 3400000, 0, RK817_LDO_ON_VSEL(8), RK817_LDO_SLP_VSEL(8), NA, RK817_LDO_VSEL_MASK, 0x70, },
195 /* ldo9 */
196 { 600000, 25000, RK817_LDO_ON_VSEL(9), RK817_LDO_SLP_VSEL(9), NA, RK817_LDO_VSEL_MASK, 0x00, },
197 { 3400000, 0, RK817_LDO_ON_VSEL(9), RK817_LDO_SLP_VSEL(9), NA, RK817_LDO_VSEL_MASK, 0x70, },
198};
199
Jacob Chen614704b2017-05-02 14:54:52 +0800200static const struct rk8xx_reg_info rk818_ldo[] = {
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800201 { 1800000, 100000, REG_LDO1_ON_VSEL, REG_LDO1_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
202 { 1800000, 100000, REG_LDO2_ON_VSEL, REG_LDO2_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
203 { 800000, 100000, REG_LDO3_ON_VSEL, REG_LDO3_SLP_VSEL, NA, RK818_LDO3_ON_VSEL_MASK, },
204 { 1800000, 100000, REG_LDO4_ON_VSEL, REG_LDO4_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
205 { 1800000, 100000, REG_LDO5_ON_VSEL, REG_LDO5_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
206 { 800000, 100000, REG_LDO6_ON_VSEL, REG_LDO6_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
207 { 800000, 100000, REG_LDO7_ON_VSEL, REG_LDO7_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
208 { 1800000, 100000, REG_LDO8_ON_VSEL, REG_LDO8_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
Jacob Chen36163e32017-05-02 14:54:51 +0800209};
Wadim Egorov4c4905f2017-06-19 12:36:38 +0200210#endif
Jacob Chen36163e32017-05-02 14:54:51 +0800211
Wadim Egorovc2581052017-06-19 12:36:39 +0200212static const u16 rk818_chrg_cur_input_array[] = {
213 450, 800, 850, 1000, 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000
214};
215
216static const uint rk818_chrg_shutdown_vsel_array[] = {
217 2780000, 2850000, 2920000, 2990000, 3060000, 3130000, 3190000, 3260000
218};
219
Jacob Chen614704b2017-05-02 14:54:52 +0800220static const struct rk8xx_reg_info *get_buck_reg(struct udevice *pmic,
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800221 int num, int uvolt)
Jacob Chen36163e32017-05-02 14:54:51 +0800222{
Jacob Chen614704b2017-05-02 14:54:52 +0800223 struct rk8xx_priv *priv = dev_get_priv(pmic);
Elaine Zhang04e5a432019-09-26 15:43:54 +0800224
Jacob Chen614704b2017-05-02 14:54:52 +0800225 switch (priv->variant) {
Elaine Zhang1d9077e2019-09-26 15:43:55 +0800226 case RK805_ID:
Elaine Zhang04e5a432019-09-26 15:43:54 +0800227 case RK816_ID:
228 switch (num) {
229 case 0:
230 case 1:
231 if (uvolt <= 1450000)
232 return &rk816_buck[num * 3 + 0];
233 else if (uvolt <= 2200000)
234 return &rk816_buck[num * 3 + 1];
235 else
236 return &rk816_buck[num * 3 + 2];
237 default:
238 return &rk816_buck[num + 4];
239 }
Joseph Chen4a1ae182019-09-26 15:44:55 +0800240
Joseph Chend6b3e832019-09-26 15:45:07 +0800241 case RK809_ID:
Joseph Chen4a1ae182019-09-26 15:44:55 +0800242 case RK817_ID:
243 switch (num) {
244 case 0 ... 2:
245 if (uvolt < 1500000)
246 return &rk817_buck[num * 3 + 0];
247 else if (uvolt < 2400000)
248 return &rk817_buck[num * 3 + 1];
249 else
250 return &rk817_buck[num * 3 + 2];
251 case 3:
252 if (uvolt < 1500000)
253 return &rk817_buck[num * 3 + 0];
254 else if (uvolt < 3400000)
255 return &rk817_buck[num * 3 + 1];
256 else
257 return &rk817_buck[num * 3 + 2];
Joseph Chend6b3e832019-09-26 15:45:07 +0800258 /* BUCK5 for RK809 */
259 default:
260 if (uvolt < 1800000)
261 return &rk809_buck5[0];
262 else if (uvolt < 2800000)
263 return &rk809_buck5[1];
264 else if (uvolt < 3300000)
265 return &rk809_buck5[2];
266 else
267 return &rk809_buck5[3];
Joseph Chen4a1ae182019-09-26 15:44:55 +0800268 }
Jacob Chen36163e32017-05-02 14:54:51 +0800269 case RK818_ID:
270 return &rk818_buck[num];
271 default:
272 return &rk808_buck[num];
273 }
274}
275
Simon Glassadecfef2016-01-21 19:43:30 -0700276static int _buck_set_value(struct udevice *pmic, int buck, int uvolt)
277{
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800278 const struct rk8xx_reg_info *info = get_buck_reg(pmic, buck, uvolt);
Elaine Zhang04e5a432019-09-26 15:43:54 +0800279 struct rk8xx_priv *priv = dev_get_priv(pmic);
Jacob Chen21a6a252017-05-02 14:54:50 +0800280 int mask = info->vsel_mask;
Simon Glassadecfef2016-01-21 19:43:30 -0700281 int val;
282
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800283 if (info->vsel_reg == NA)
Simon Glassadecfef2016-01-21 19:43:30 -0700284 return -ENOSYS;
Elaine Zhang04e5a432019-09-26 15:43:54 +0800285
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800286 if (info->step_uv == 0) /* Fixed voltage */
287 val = info->min_sel;
288 else
289 val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel;
290
291 debug("%s: volt=%d, buck=%d, reg=0x%x, mask=0x%x, val=0x%x\n",
292 __func__, uvolt, buck + 1, info->vsel_reg, mask, val);
293
Elaine Zhang04e5a432019-09-26 15:43:54 +0800294 if (priv->variant == RK816_ID) {
295 pmic_clrsetbits(pmic, info->vsel_reg, mask, val);
296 return pmic_clrsetbits(pmic, RK816_REG_DCDC_EN2,
297 1 << 7, 1 << 7);
298 } else {
299 return pmic_clrsetbits(pmic, info->vsel_reg, mask, val);
300 }
Simon Glassadecfef2016-01-21 19:43:30 -0700301}
302
303static int _buck_set_enable(struct udevice *pmic, int buck, bool enable)
304{
Elaine Zhang04e5a432019-09-26 15:43:54 +0800305 uint mask, value, en_reg;
Joseph Chen4a1ae182019-09-26 15:44:55 +0800306 int ret = 0;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800307 struct rk8xx_priv *priv = dev_get_priv(pmic);
Simon Glassadecfef2016-01-21 19:43:30 -0700308
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800309 switch (priv->variant) {
Elaine Zhang1d9077e2019-09-26 15:43:55 +0800310 case RK805_ID:
Elaine Zhang04e5a432019-09-26 15:43:54 +0800311 case RK816_ID:
312 if (buck >= 4) {
313 buck -= 4;
314 en_reg = RK816_REG_DCDC_EN2;
315 } else {
316 en_reg = RK816_REG_DCDC_EN1;
317 }
318 if (enable)
319 value = ((1 << buck) | (1 << (buck + 4)));
320 else
321 value = ((0 << buck) | (1 << (buck + 4)));
322 ret = pmic_reg_write(pmic, en_reg, value);
323 break;
324
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800325 case RK808_ID:
326 case RK818_ID:
327 mask = 1 << buck;
328 if (enable) {
329 ret = pmic_clrsetbits(pmic, REG_DCDC_ILMAX,
330 0, 3 << (buck * 2));
331 if (ret)
332 return ret;
333 }
334 ret = pmic_clrsetbits(pmic, REG_DCDC_EN, mask,
335 enable ? mask : 0);
336 break;
Joseph Chend6b3e832019-09-26 15:45:07 +0800337 case RK809_ID:
Joseph Chen4a1ae182019-09-26 15:44:55 +0800338 case RK817_ID:
339 if (buck < 4) {
340 if (enable)
341 value = ((1 << buck) | (1 << (buck + 4)));
342 else
343 value = ((0 << buck) | (1 << (buck + 4)));
344 ret = pmic_reg_write(pmic, RK817_POWER_EN(0), value);
Joseph Chend6b3e832019-09-26 15:45:07 +0800345 /* BUCK5 for RK809 */
346 } else {
347 if (enable)
348 value = ((1 << 1) | (1 << 5));
349 else
350 value = ((0 << 1) | (1 << 5));
351 ret = pmic_reg_write(pmic, RK817_POWER_EN(3), value);
Joseph Chen4a1ae182019-09-26 15:44:55 +0800352 }
353 break;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800354 default:
355 ret = -EINVAL;
Simon Glassadecfef2016-01-21 19:43:30 -0700356 }
357
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800358 return ret;
Simon Glassadecfef2016-01-21 19:43:30 -0700359}
360
361#ifdef ENABLE_DRIVER
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800362static int _buck_set_suspend_value(struct udevice *pmic, int buck, int uvolt)
363{
364 const struct rk8xx_reg_info *info = get_buck_reg(pmic, buck, uvolt);
365 int mask = info->vsel_mask;
366 int val;
367
368 if (info->vsel_sleep_reg == NA)
369 return -ENOSYS;
370
371 if (info->step_uv == 0)
372 val = info->min_sel;
373 else
374 val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel;
375
376 debug("%s: volt=%d, buck=%d, reg=0x%x, mask=0x%x, val=0x%x\n",
377 __func__, uvolt, buck + 1, info->vsel_sleep_reg, mask, val);
378
379 return pmic_clrsetbits(pmic, info->vsel_sleep_reg, mask, val);
380}
381
382static int _buck_get_enable(struct udevice *pmic, int buck)
383{
384 struct rk8xx_priv *priv = dev_get_priv(pmic);
385 uint mask = 0;
386 int ret = 0;
387
388 switch (priv->variant) {
Elaine Zhang1d9077e2019-09-26 15:43:55 +0800389 case RK805_ID:
Elaine Zhang04e5a432019-09-26 15:43:54 +0800390 case RK816_ID:
391 if (buck >= 4) {
392 mask = 1 << (buck - 4);
393 ret = pmic_reg_read(pmic, RK816_REG_DCDC_EN2);
394 } else {
395 mask = 1 << buck;
396 ret = pmic_reg_read(pmic, RK816_REG_DCDC_EN1);
397 }
398 break;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800399 case RK808_ID:
400 case RK818_ID:
401 mask = 1 << buck;
402 ret = pmic_reg_read(pmic, REG_DCDC_EN);
403 if (ret < 0)
404 return ret;
405 break;
Joseph Chend6b3e832019-09-26 15:45:07 +0800406 case RK809_ID:
Joseph Chen4a1ae182019-09-26 15:44:55 +0800407 case RK817_ID:
408 if (buck < 4) {
409 mask = 1 << buck;
410 ret = pmic_reg_read(pmic, RK817_POWER_EN(0));
Joseph Chend6b3e832019-09-26 15:45:07 +0800411 /* BUCK5 for RK809 */
412 } else {
413 mask = 1 << 1;
414 ret = pmic_reg_read(pmic, RK817_POWER_EN(3));
Joseph Chen4a1ae182019-09-26 15:44:55 +0800415 }
416 break;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800417 }
418
419 if (ret < 0)
420 return ret;
421
422 return ret & mask ? true : false;
423}
424
425static int _buck_set_suspend_enable(struct udevice *pmic, int buck, bool enable)
426{
Joseph Chen4a1ae182019-09-26 15:44:55 +0800427 uint mask = 0;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800428 int ret;
429 struct rk8xx_priv *priv = dev_get_priv(pmic);
430
431 switch (priv->variant) {
Elaine Zhang1d9077e2019-09-26 15:43:55 +0800432 case RK805_ID:
Elaine Zhang04e5a432019-09-26 15:43:54 +0800433 case RK816_ID:
434 mask = 1 << buck;
435 ret = pmic_clrsetbits(pmic, RK816_REG_DCDC_SLP_EN, mask,
436 enable ? mask : 0);
437 break;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800438 case RK808_ID:
439 case RK818_ID:
440 mask = 1 << buck;
441 ret = pmic_clrsetbits(pmic, REG_SLEEP_SET_OFF1, mask,
442 enable ? 0 : mask);
443 break;
Joseph Chend6b3e832019-09-26 15:45:07 +0800444 case RK809_ID:
Joseph Chen4a1ae182019-09-26 15:44:55 +0800445 case RK817_ID:
446 if (buck < 4)
447 mask = 1 << buck;
Joseph Chend6b3e832019-09-26 15:45:07 +0800448 else
449 mask = 1 << 5; /* BUCK5 for RK809 */
Joseph Chen4a1ae182019-09-26 15:44:55 +0800450 ret = pmic_clrsetbits(pmic, RK817_POWER_SLP_EN(0), mask,
451 enable ? mask : 0);
452 break;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800453 default:
454 ret = -EINVAL;
455 }
456
457 return ret;
458}
459
460static int _buck_get_suspend_enable(struct udevice *pmic, int buck)
461{
462 struct rk8xx_priv *priv = dev_get_priv(pmic);
463 int ret, val;
Joseph Chen4a1ae182019-09-26 15:44:55 +0800464 uint mask = 0;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800465
466 switch (priv->variant) {
Elaine Zhang1d9077e2019-09-26 15:43:55 +0800467 case RK805_ID:
Elaine Zhang04e5a432019-09-26 15:43:54 +0800468 case RK816_ID:
469 mask = 1 << buck;
470 val = pmic_reg_read(pmic, RK816_REG_DCDC_SLP_EN);
471 if (val < 0)
472 return val;
473 ret = val & mask ? 1 : 0;
474 break;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800475 case RK808_ID:
476 case RK818_ID:
477 mask = 1 << buck;
478 val = pmic_reg_read(pmic, REG_SLEEP_SET_OFF1);
479 if (val < 0)
480 return val;
481 ret = val & mask ? 0 : 1;
482 break;
Joseph Chend6b3e832019-09-26 15:45:07 +0800483 case RK809_ID:
Joseph Chen4a1ae182019-09-26 15:44:55 +0800484 case RK817_ID:
485 if (buck < 4)
486 mask = 1 << buck;
Joseph Chend6b3e832019-09-26 15:45:07 +0800487 else
488 mask = 1 << 5; /* BUCK5 for RK809 */
Joseph Chen4a1ae182019-09-26 15:44:55 +0800489
490 val = pmic_reg_read(pmic, RK817_POWER_SLP_EN(0));
491 if (val < 0)
492 return val;
493 ret = val & mask ? 1 : 0;
494 break;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800495 default:
496 ret = -EINVAL;
497 }
498
499 return ret;
500}
501
Wadim Egorov4c4905f2017-06-19 12:36:38 +0200502static const struct rk8xx_reg_info *get_ldo_reg(struct udevice *pmic,
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800503 int num, int uvolt)
Wadim Egorov4c4905f2017-06-19 12:36:38 +0200504{
505 struct rk8xx_priv *priv = dev_get_priv(pmic);
Elaine Zhang04e5a432019-09-26 15:43:54 +0800506
Wadim Egorov4c4905f2017-06-19 12:36:38 +0200507 switch (priv->variant) {
Elaine Zhang1d9077e2019-09-26 15:43:55 +0800508 case RK805_ID:
Elaine Zhang04e5a432019-09-26 15:43:54 +0800509 case RK816_ID:
510 return &rk816_ldo[num];
Joseph Chend6b3e832019-09-26 15:45:07 +0800511 case RK809_ID:
Joseph Chen4a1ae182019-09-26 15:44:55 +0800512 case RK817_ID:
513 if (uvolt < 3400000)
514 return &rk817_ldo[num * 2 + 0];
515 else
516 return &rk817_ldo[num * 2 + 1];
Wadim Egorov4c4905f2017-06-19 12:36:38 +0200517 case RK818_ID:
518 return &rk818_ldo[num];
519 default:
520 return &rk808_ldo[num];
521 }
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800522}
523
524static int _ldo_get_enable(struct udevice *pmic, int ldo)
525{
526 struct rk8xx_priv *priv = dev_get_priv(pmic);
527 uint mask = 0;
528 int ret = 0;
529
530 switch (priv->variant) {
Elaine Zhang1d9077e2019-09-26 15:43:55 +0800531 case RK805_ID:
Elaine Zhang04e5a432019-09-26 15:43:54 +0800532 case RK816_ID:
533 if (ldo >= 4) {
534 mask = 1 << (ldo - 4);
535 ret = pmic_reg_read(pmic, RK816_REG_LDO_EN2);
536 } else {
537 mask = 1 << ldo;
538 ret = pmic_reg_read(pmic, RK816_REG_LDO_EN1);
539 }
540 break;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800541 case RK808_ID:
542 case RK818_ID:
543 mask = 1 << ldo;
544 ret = pmic_reg_read(pmic, REG_LDO_EN);
545 if (ret < 0)
546 return ret;
547 break;
Joseph Chend6b3e832019-09-26 15:45:07 +0800548 case RK809_ID:
Joseph Chen4a1ae182019-09-26 15:44:55 +0800549 case RK817_ID:
550 if (ldo < 4) {
551 mask = 1 << ldo;
552 ret = pmic_reg_read(pmic, RK817_POWER_EN(1));
553 } else if (ldo < 8) {
554 mask = 1 << (ldo - 4);
555 ret = pmic_reg_read(pmic, RK817_POWER_EN(2));
556 } else if (ldo == 8) {
557 mask = 1 << 0;
558 ret = pmic_reg_read(pmic, RK817_POWER_EN(3));
559 } else {
560 return false;
561 }
562 break;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800563 }
564
565 if (ret < 0)
566 return ret;
567
568 return ret & mask ? true : false;
569}
570
571static int _ldo_set_enable(struct udevice *pmic, int ldo, bool enable)
572{
573 struct rk8xx_priv *priv = dev_get_priv(pmic);
Elaine Zhang04e5a432019-09-26 15:43:54 +0800574 uint mask, value, en_reg;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800575 int ret = 0;
576
577 switch (priv->variant) {
Elaine Zhang1d9077e2019-09-26 15:43:55 +0800578 case RK805_ID:
Elaine Zhang04e5a432019-09-26 15:43:54 +0800579 case RK816_ID:
580 if (ldo >= 4) {
581 ldo -= 4;
582 en_reg = RK816_REG_LDO_EN2;
583 } else {
584 en_reg = RK816_REG_LDO_EN1;
585 }
586 if (enable)
587 value = ((1 << ldo) | (1 << (ldo + 4)));
588 else
589 value = ((0 << ldo) | (1 << (ldo + 4)));
590
591 ret = pmic_reg_write(pmic, en_reg, value);
592 break;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800593 case RK808_ID:
594 case RK818_ID:
595 mask = 1 << ldo;
596 ret = pmic_clrsetbits(pmic, REG_LDO_EN, mask,
Elaine Zhang04e5a432019-09-26 15:43:54 +0800597 enable ? mask : 0);
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800598 break;
Joseph Chend6b3e832019-09-26 15:45:07 +0800599 case RK809_ID:
Joseph Chen4a1ae182019-09-26 15:44:55 +0800600 case RK817_ID:
601 if (ldo < 4) {
602 en_reg = RK817_POWER_EN(1);
603 } else if (ldo < 8) {
604 ldo -= 4;
605 en_reg = RK817_POWER_EN(2);
606 } else if (ldo == 8) {
607 ldo = 0; /* BIT 0 */
608 en_reg = RK817_POWER_EN(3);
609 } else {
610 return -EINVAL;
611 }
612 if (enable)
613 value = ((1 << ldo) | (1 << (ldo + 4)));
614 else
615 value = ((0 << ldo) | (1 << (ldo + 4)));
616 ret = pmic_reg_write(pmic, en_reg, value);
617 break;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800618 }
619
Jonas Karlman31c3c802023-07-02 12:41:15 +0000620 if (enable)
621 udelay(500);
622
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800623 return ret;
Wadim Egorov4c4905f2017-06-19 12:36:38 +0200624}
625
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800626static int _ldo_set_suspend_enable(struct udevice *pmic, int ldo, bool enable)
627{
628 struct rk8xx_priv *priv = dev_get_priv(pmic);
629 uint mask;
630 int ret = 0;
631
632 switch (priv->variant) {
Elaine Zhang1d9077e2019-09-26 15:43:55 +0800633 case RK805_ID:
Elaine Zhang04e5a432019-09-26 15:43:54 +0800634 case RK816_ID:
635 mask = 1 << ldo;
636 ret = pmic_clrsetbits(pmic, RK816_REG_LDO_SLP_EN, mask,
637 enable ? mask : 0);
638 break;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800639 case RK808_ID:
640 case RK818_ID:
641 mask = 1 << ldo;
642 ret = pmic_clrsetbits(pmic, REG_SLEEP_SET_OFF2, mask,
643 enable ? 0 : mask);
644 break;
Joseph Chend6b3e832019-09-26 15:45:07 +0800645 case RK809_ID:
Joseph Chen4a1ae182019-09-26 15:44:55 +0800646 case RK817_ID:
647 if (ldo == 8) {
648 mask = 1 << 4; /* LDO9 */
649 ret = pmic_clrsetbits(pmic, RK817_POWER_SLP_EN(0), mask,
650 enable ? mask : 0);
651 } else {
652 mask = 1 << ldo;
653 ret = pmic_clrsetbits(pmic, RK817_POWER_SLP_EN(1), mask,
654 enable ? mask : 0);
655 }
656 break;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800657 }
658
659 return ret;
660}
661
662static int _ldo_get_suspend_enable(struct udevice *pmic, int ldo)
663{
664 struct rk8xx_priv *priv = dev_get_priv(pmic);
665 int val, ret = 0;
666 uint mask;
667
668 switch (priv->variant) {
Elaine Zhang1d9077e2019-09-26 15:43:55 +0800669 case RK805_ID:
Elaine Zhang04e5a432019-09-26 15:43:54 +0800670 case RK816_ID:
671 mask = 1 << ldo;
672 val = pmic_reg_read(pmic, RK816_REG_LDO_SLP_EN);
673 if (val < 0)
674 return val;
675 ret = val & mask ? 1 : 0;
676 break;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800677 case RK808_ID:
678 case RK818_ID:
679 mask = 1 << ldo;
680 val = pmic_reg_read(pmic, REG_SLEEP_SET_OFF2);
681 if (val < 0)
682 return val;
683 ret = val & mask ? 0 : 1;
684 break;
Joseph Chend6b3e832019-09-26 15:45:07 +0800685 case RK809_ID:
Joseph Chen4a1ae182019-09-26 15:44:55 +0800686 case RK817_ID:
687 if (ldo == 8) {
688 mask = 1 << 4; /* LDO9 */
689 val = pmic_reg_read(pmic, RK817_POWER_SLP_EN(0));
690 if (val < 0)
691 return val;
692 ret = val & mask ? 1 : 0;
693 } else {
694 mask = 1 << ldo;
695 val = pmic_reg_read(pmic, RK817_POWER_SLP_EN(1));
696 if (val < 0)
697 return val;
698 ret = val & mask ? 1 : 0;
699 }
700 break;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800701 }
702
703 return ret;
704}
705
Simon Glassadecfef2016-01-21 19:43:30 -0700706static int buck_get_value(struct udevice *dev)
707{
708 int buck = dev->driver_data - 1;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800709 /* We assume level-1 voltage is enough for usage in U-Boot */
710 const struct rk8xx_reg_info *info = get_buck_reg(dev->parent, buck, 0);
Jacob Chen21a6a252017-05-02 14:54:50 +0800711 int mask = info->vsel_mask;
Simon Glassadecfef2016-01-21 19:43:30 -0700712 int ret, val;
713
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800714 if (info->vsel_reg == NA)
Simon Glassadecfef2016-01-21 19:43:30 -0700715 return -ENOSYS;
Elaine Zhang04e5a432019-09-26 15:43:54 +0800716
Simon Glassadecfef2016-01-21 19:43:30 -0700717 ret = pmic_reg_read(dev->parent, info->vsel_reg);
718 if (ret < 0)
719 return ret;
720 val = ret & mask;
721
722 return info->min_uv + val * info->step_uv;
723}
724
725static int buck_set_value(struct udevice *dev, int uvolt)
726{
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800727 int buck = dev->driver_data - 1;
Simon Glassadecfef2016-01-21 19:43:30 -0700728
729 return _buck_set_value(dev->parent, buck, uvolt);
730}
731
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800732static int buck_get_suspend_value(struct udevice *dev)
733{
734 int buck = dev->driver_data - 1;
735 /* We assume level-1 voltage is enough for usage in U-Boot */
736 const struct rk8xx_reg_info *info = get_buck_reg(dev->parent, buck, 0);
737 int mask = info->vsel_mask;
738 int ret, val;
739
740 if (info->vsel_sleep_reg == NA)
741 return -ENOSYS;
742
743 ret = pmic_reg_read(dev->parent, info->vsel_sleep_reg);
744 if (ret < 0)
745 return ret;
746
747 val = ret & mask;
748
749 return info->min_uv + val * info->step_uv;
750}
751
752static int buck_set_suspend_value(struct udevice *dev, int uvolt)
753{
754 int buck = dev->driver_data - 1;
755
756 return _buck_set_suspend_value(dev->parent, buck, uvolt);
757}
758
Simon Glassadecfef2016-01-21 19:43:30 -0700759static int buck_set_enable(struct udevice *dev, bool enable)
760{
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800761 int buck = dev->driver_data - 1;
Simon Glassadecfef2016-01-21 19:43:30 -0700762
763 return _buck_set_enable(dev->parent, buck, enable);
764}
765
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800766static int buck_set_suspend_enable(struct udevice *dev, bool enable)
Simon Glassadecfef2016-01-21 19:43:30 -0700767{
768 int buck = dev->driver_data - 1;
Simon Glassadecfef2016-01-21 19:43:30 -0700769
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800770 return _buck_set_suspend_enable(dev->parent, buck, enable);
771}
Simon Glassadecfef2016-01-21 19:43:30 -0700772
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800773static int buck_get_suspend_enable(struct udevice *dev)
774{
775 int buck = dev->driver_data - 1;
Simon Glassadecfef2016-01-21 19:43:30 -0700776
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800777 return _buck_get_suspend_enable(dev->parent, buck);
Simon Glassadecfef2016-01-21 19:43:30 -0700778}
779
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800780static int buck_get_enable(struct udevice *dev)
781{
782 int buck = dev->driver_data - 1;
783
784 return _buck_get_enable(dev->parent, buck);
785}
786
Simon Glassadecfef2016-01-21 19:43:30 -0700787static int ldo_get_value(struct udevice *dev)
788{
789 int ldo = dev->driver_data - 1;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800790 const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, 0);
Jacob Chen21a6a252017-05-02 14:54:50 +0800791 int mask = info->vsel_mask;
Simon Glassadecfef2016-01-21 19:43:30 -0700792 int ret, val;
793
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800794 if (info->vsel_reg == NA)
Simon Glassadecfef2016-01-21 19:43:30 -0700795 return -ENOSYS;
796 ret = pmic_reg_read(dev->parent, info->vsel_reg);
797 if (ret < 0)
798 return ret;
799 val = ret & mask;
800
801 return info->min_uv + val * info->step_uv;
802}
803
804static int ldo_set_value(struct udevice *dev, int uvolt)
805{
806 int ldo = dev->driver_data - 1;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800807 const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, uvolt);
Jacob Chen21a6a252017-05-02 14:54:50 +0800808 int mask = info->vsel_mask;
Simon Glassadecfef2016-01-21 19:43:30 -0700809 int val;
810
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800811 if (info->vsel_reg == NA)
Simon Glassadecfef2016-01-21 19:43:30 -0700812 return -ENOSYS;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800813
814 if (info->step_uv == 0)
815 val = info->min_sel;
816 else
817 val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel;
818
819 debug("%s: volt=%d, ldo=%d, reg=0x%x, mask=0x%x, val=0x%x\n",
820 __func__, uvolt, ldo + 1, info->vsel_reg, mask, val);
Simon Glassadecfef2016-01-21 19:43:30 -0700821
822 return pmic_clrsetbits(dev->parent, info->vsel_reg, mask, val);
823}
824
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800825static int ldo_set_suspend_value(struct udevice *dev, int uvolt)
Simon Glassadecfef2016-01-21 19:43:30 -0700826{
827 int ldo = dev->driver_data - 1;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800828 const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, uvolt);
829 int mask = info->vsel_mask;
830 int val;
831
832 if (info->vsel_sleep_reg == NA)
833 return -ENOSYS;
Simon Glassadecfef2016-01-21 19:43:30 -0700834
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800835 if (info->step_uv == 0)
836 val = info->min_sel;
837 else
838 val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel;
Simon Glassadecfef2016-01-21 19:43:30 -0700839
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800840 debug("%s: volt=%d, ldo=%d, reg=0x%x, mask=0x%x, val=0x%x\n",
841 __func__, uvolt, ldo + 1, info->vsel_sleep_reg, mask, val);
842
843 return pmic_clrsetbits(dev->parent, info->vsel_sleep_reg, mask, val);
Simon Glassadecfef2016-01-21 19:43:30 -0700844}
845
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800846static int ldo_get_suspend_value(struct udevice *dev)
Simon Glassadecfef2016-01-21 19:43:30 -0700847{
848 int ldo = dev->driver_data - 1;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800849 const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, 0);
850 int mask = info->vsel_mask;
851 int val, ret;
Simon Glassadecfef2016-01-21 19:43:30 -0700852
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800853 if (info->vsel_sleep_reg == NA)
854 return -ENOSYS;
Simon Glassadecfef2016-01-21 19:43:30 -0700855
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800856 ret = pmic_reg_read(dev->parent, info->vsel_sleep_reg);
Simon Glassadecfef2016-01-21 19:43:30 -0700857 if (ret < 0)
858 return ret;
859
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800860 val = ret & mask;
861
862 return info->min_uv + val * info->step_uv;
863}
864
865static int ldo_set_enable(struct udevice *dev, bool enable)
866{
867 int ldo = dev->driver_data - 1;
868
869 return _ldo_set_enable(dev->parent, ldo, enable);
870}
871
872static int ldo_set_suspend_enable(struct udevice *dev, bool enable)
873{
874 int ldo = dev->driver_data - 1;
875
876 return _ldo_set_suspend_enable(dev->parent, ldo, enable);
877}
878
879static int ldo_get_suspend_enable(struct udevice *dev)
880{
881 int ldo = dev->driver_data - 1;
882
883 return _ldo_get_suspend_enable(dev->parent, ldo);
884}
885
886static int ldo_get_enable(struct udevice *dev)
887{
888 int ldo = dev->driver_data - 1;
889
890 return _ldo_get_enable(dev->parent, ldo);
Simon Glassadecfef2016-01-21 19:43:30 -0700891}
892
893static int switch_set_enable(struct udevice *dev, bool enable)
894{
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800895 struct rk8xx_priv *priv = dev_get_priv(dev->parent);
896 int ret = 0, sw = dev->driver_data - 1;
897 uint mask = 0;
898
899 switch (priv->variant) {
900 case RK808_ID:
901 mask = 1 << (sw + 5);
902 ret = pmic_clrsetbits(dev->parent, REG_DCDC_EN, mask,
903 enable ? mask : 0);
904 break;
Joseph Chend6b3e832019-09-26 15:45:07 +0800905 case RK809_ID:
906 mask = (1 << (sw + 2)) | (1 << (sw + 6));
907 ret = pmic_clrsetbits(dev->parent, RK817_POWER_EN(3), mask,
908 enable ? mask : 0);
909 break;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800910 case RK818_ID:
911 mask = 1 << 6;
912 ret = pmic_clrsetbits(dev->parent, REG_DCDC_EN, mask,
913 enable ? mask : 0);
914 break;
915 }
Simon Glassadecfef2016-01-21 19:43:30 -0700916
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800917 debug("%s: switch%d, enable=%d, mask=0x%x\n",
918 __func__, sw + 1, enable, mask);
Simon Glassadecfef2016-01-21 19:43:30 -0700919
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800920 return ret;
Simon Glassadecfef2016-01-21 19:43:30 -0700921}
922
Keerthyc8f82fb2017-06-13 09:53:52 +0530923static int switch_get_enable(struct udevice *dev)
Simon Glassadecfef2016-01-21 19:43:30 -0700924{
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800925 struct rk8xx_priv *priv = dev_get_priv(dev->parent);
926 int ret = 0, sw = dev->driver_data - 1;
927 uint mask = 0;
Simon Glassadecfef2016-01-21 19:43:30 -0700928
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800929 switch (priv->variant) {
930 case RK808_ID:
931 mask = 1 << (sw + 5);
932 ret = pmic_reg_read(dev->parent, REG_DCDC_EN);
933 break;
Joseph Chend6b3e832019-09-26 15:45:07 +0800934 case RK809_ID:
935 mask = 1 << (sw + 2);
936 ret = pmic_reg_read(dev->parent, RK817_POWER_EN(3));
937 break;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800938 case RK818_ID:
939 mask = 1 << 6;
940 ret = pmic_reg_read(dev->parent, REG_DCDC_EN);
941 break;
942 }
Simon Glassadecfef2016-01-21 19:43:30 -0700943
Simon Glassadecfef2016-01-21 19:43:30 -0700944 if (ret < 0)
945 return ret;
946
947 return ret & mask ? true : false;
948}
949
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800950static int switch_set_suspend_value(struct udevice *dev, int uvolt)
951{
952 return 0;
953}
954
955static int switch_get_suspend_value(struct udevice *dev)
956{
957 return 0;
958}
959
960static int switch_set_suspend_enable(struct udevice *dev, bool enable)
961{
962 struct rk8xx_priv *priv = dev_get_priv(dev->parent);
963 int ret = 0, sw = dev->driver_data - 1;
964 uint mask = 0;
965
966 switch (priv->variant) {
967 case RK808_ID:
968 mask = 1 << (sw + 5);
969 ret = pmic_clrsetbits(dev->parent, REG_SLEEP_SET_OFF1, mask,
970 enable ? 0 : mask);
971 break;
Joseph Chend6b3e832019-09-26 15:45:07 +0800972 case RK809_ID:
973 mask = 1 << (sw + 6);
974 ret = pmic_clrsetbits(dev->parent, RK817_POWER_SLP_EN(0), mask,
975 enable ? mask : 0);
976 break;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +0800977 case RK818_ID:
978 mask = 1 << 6;
979 ret = pmic_clrsetbits(dev->parent, REG_SLEEP_SET_OFF1, mask,
980 enable ? 0 : mask);
981 break;
982 }
983
984 debug("%s: switch%d, enable=%d, mask=0x%x\n",
985 __func__, sw + 1, enable, mask);
986
987 return ret;
988}
989
990static int switch_get_suspend_enable(struct udevice *dev)
991{
992 struct rk8xx_priv *priv = dev_get_priv(dev->parent);
993 int val, ret = 0, sw = dev->driver_data - 1;
994 uint mask = 0;
995
996 switch (priv->variant) {
997 case RK808_ID:
998 mask = 1 << (sw + 5);
999 val = pmic_reg_read(dev->parent, REG_SLEEP_SET_OFF1);
1000 if (val < 0)
1001 return val;
1002 ret = val & mask ? 0 : 1;
1003 break;
Joseph Chend6b3e832019-09-26 15:45:07 +08001004 case RK809_ID:
1005 mask = 1 << (sw + 6);
1006 val = pmic_reg_read(dev->parent, RK817_POWER_SLP_EN(0));
1007 if (val < 0)
1008 return val;
1009 ret = val & mask ? 1 : 0;
1010 break;
Elaine Zhangfa9cccc2019-09-26 15:43:53 +08001011 case RK818_ID:
1012 mask = 1 << 6;
1013 val = pmic_reg_read(dev->parent, REG_SLEEP_SET_OFF1);
1014 if (val < 0)
1015 return val;
1016 ret = val & mask ? 0 : 1;
1017 break;
1018 }
1019
1020 return ret;
1021}
1022
1023/*
1024 * RK8xx switch does not need to set the voltage,
1025 * but if dts set regulator-min-microvolt/regulator-max-microvolt,
1026 * will cause regulator set value fail and not to enable this switch.
1027 * So add an empty function to return success.
1028 */
1029static int switch_get_value(struct udevice *dev)
1030{
1031 return 0;
1032}
1033
1034static int switch_set_value(struct udevice *dev, int uvolt)
1035{
1036 return 0;
1037}
1038
Jacob Chen614704b2017-05-02 14:54:52 +08001039static int rk8xx_buck_probe(struct udevice *dev)
Simon Glassadecfef2016-01-21 19:43:30 -07001040{
Simon Glass71fa5b42020-12-03 16:55:18 -07001041 struct dm_regulator_uclass_plat *uc_pdata;
Simon Glassadecfef2016-01-21 19:43:30 -07001042
Simon Glass71fa5b42020-12-03 16:55:18 -07001043 uc_pdata = dev_get_uclass_plat(dev);
Simon Glassadecfef2016-01-21 19:43:30 -07001044
1045 uc_pdata->type = REGULATOR_TYPE_BUCK;
1046 uc_pdata->mode_count = 0;
1047
1048 return 0;
1049}
1050
Jacob Chen614704b2017-05-02 14:54:52 +08001051static int rk8xx_ldo_probe(struct udevice *dev)
Simon Glassadecfef2016-01-21 19:43:30 -07001052{
Simon Glass71fa5b42020-12-03 16:55:18 -07001053 struct dm_regulator_uclass_plat *uc_pdata;
Simon Glassadecfef2016-01-21 19:43:30 -07001054
Simon Glass71fa5b42020-12-03 16:55:18 -07001055 uc_pdata = dev_get_uclass_plat(dev);
Simon Glassadecfef2016-01-21 19:43:30 -07001056
1057 uc_pdata->type = REGULATOR_TYPE_LDO;
1058 uc_pdata->mode_count = 0;
1059
1060 return 0;
1061}
1062
Jacob Chen614704b2017-05-02 14:54:52 +08001063static int rk8xx_switch_probe(struct udevice *dev)
Simon Glassadecfef2016-01-21 19:43:30 -07001064{
Simon Glass71fa5b42020-12-03 16:55:18 -07001065 struct dm_regulator_uclass_plat *uc_pdata;
Simon Glassadecfef2016-01-21 19:43:30 -07001066
Simon Glass71fa5b42020-12-03 16:55:18 -07001067 uc_pdata = dev_get_uclass_plat(dev);
Simon Glassadecfef2016-01-21 19:43:30 -07001068
1069 uc_pdata->type = REGULATOR_TYPE_FIXED;
1070 uc_pdata->mode_count = 0;
1071
1072 return 0;
1073}
1074
Jacob Chen614704b2017-05-02 14:54:52 +08001075static const struct dm_regulator_ops rk8xx_buck_ops = {
Simon Glassadecfef2016-01-21 19:43:30 -07001076 .get_value = buck_get_value,
1077 .set_value = buck_set_value,
Elaine Zhangfa9cccc2019-09-26 15:43:53 +08001078 .set_suspend_value = buck_set_suspend_value,
1079 .get_suspend_value = buck_get_suspend_value,
Simon Glassadecfef2016-01-21 19:43:30 -07001080 .get_enable = buck_get_enable,
1081 .set_enable = buck_set_enable,
Elaine Zhangfa9cccc2019-09-26 15:43:53 +08001082 .set_suspend_enable = buck_set_suspend_enable,
1083 .get_suspend_enable = buck_get_suspend_enable,
Simon Glassadecfef2016-01-21 19:43:30 -07001084};
1085
Jacob Chen614704b2017-05-02 14:54:52 +08001086static const struct dm_regulator_ops rk8xx_ldo_ops = {
Simon Glassadecfef2016-01-21 19:43:30 -07001087 .get_value = ldo_get_value,
1088 .set_value = ldo_set_value,
Elaine Zhangfa9cccc2019-09-26 15:43:53 +08001089 .set_suspend_value = ldo_set_suspend_value,
1090 .get_suspend_value = ldo_get_suspend_value,
Simon Glassadecfef2016-01-21 19:43:30 -07001091 .get_enable = ldo_get_enable,
1092 .set_enable = ldo_set_enable,
Elaine Zhangfa9cccc2019-09-26 15:43:53 +08001093 .set_suspend_enable = ldo_set_suspend_enable,
1094 .get_suspend_enable = ldo_get_suspend_enable,
Simon Glassadecfef2016-01-21 19:43:30 -07001095};
1096
Jacob Chen614704b2017-05-02 14:54:52 +08001097static const struct dm_regulator_ops rk8xx_switch_ops = {
Elaine Zhangfa9cccc2019-09-26 15:43:53 +08001098 .get_value = switch_get_value,
1099 .set_value = switch_set_value,
Simon Glassadecfef2016-01-21 19:43:30 -07001100 .get_enable = switch_get_enable,
1101 .set_enable = switch_set_enable,
Elaine Zhangfa9cccc2019-09-26 15:43:53 +08001102 .set_suspend_enable = switch_set_suspend_enable,
1103 .get_suspend_enable = switch_get_suspend_enable,
1104 .set_suspend_value = switch_set_suspend_value,
1105 .get_suspend_value = switch_get_suspend_value,
Simon Glassadecfef2016-01-21 19:43:30 -07001106};
1107
Jacob Chen614704b2017-05-02 14:54:52 +08001108U_BOOT_DRIVER(rk8xx_buck) = {
1109 .name = "rk8xx_buck",
Simon Glassadecfef2016-01-21 19:43:30 -07001110 .id = UCLASS_REGULATOR,
Jacob Chen614704b2017-05-02 14:54:52 +08001111 .ops = &rk8xx_buck_ops,
1112 .probe = rk8xx_buck_probe,
Simon Glassadecfef2016-01-21 19:43:30 -07001113};
1114
Jacob Chen614704b2017-05-02 14:54:52 +08001115U_BOOT_DRIVER(rk8xx_ldo) = {
1116 .name = "rk8xx_ldo",
Simon Glassadecfef2016-01-21 19:43:30 -07001117 .id = UCLASS_REGULATOR,
Jacob Chen614704b2017-05-02 14:54:52 +08001118 .ops = &rk8xx_ldo_ops,
1119 .probe = rk8xx_ldo_probe,
Simon Glassadecfef2016-01-21 19:43:30 -07001120};
1121
Jacob Chen614704b2017-05-02 14:54:52 +08001122U_BOOT_DRIVER(rk8xx_switch) = {
1123 .name = "rk8xx_switch",
Simon Glassadecfef2016-01-21 19:43:30 -07001124 .id = UCLASS_REGULATOR,
Jacob Chen614704b2017-05-02 14:54:52 +08001125 .ops = &rk8xx_switch_ops,
1126 .probe = rk8xx_switch_probe,
Simon Glassadecfef2016-01-21 19:43:30 -07001127};
1128#endif
1129
Jacob Chen614704b2017-05-02 14:54:52 +08001130int rk8xx_spl_configure_buck(struct udevice *pmic, int buck, int uvolt)
Simon Glassadecfef2016-01-21 19:43:30 -07001131{
1132 int ret;
1133
1134 ret = _buck_set_value(pmic, buck, uvolt);
1135 if (ret)
1136 return ret;
1137
1138 return _buck_set_enable(pmic, buck, true);
1139}
Wadim Egorovc2581052017-06-19 12:36:39 +02001140
1141int rk818_spl_configure_usb_input_current(struct udevice *pmic, int current_ma)
1142{
1143 uint i;
1144
1145 for (i = 0; i < ARRAY_SIZE(rk818_chrg_cur_input_array); i++)
1146 if (current_ma <= rk818_chrg_cur_input_array[i])
1147 break;
1148
1149 return pmic_clrsetbits(pmic, REG_USB_CTRL, RK818_USB_ILIM_SEL_MASK, i);
1150}
1151
1152int rk818_spl_configure_usb_chrg_shutdown(struct udevice *pmic, int uvolt)
1153{
1154 uint i;
1155
1156 for (i = 0; i < ARRAY_SIZE(rk818_chrg_shutdown_vsel_array); i++)
1157 if (uvolt <= rk818_chrg_shutdown_vsel_array[i])
1158 break;
1159
1160 return pmic_clrsetbits(pmic, REG_USB_CTRL, RK818_USB_CHG_SD_VSEL_MASK,
1161 i);
1162}