xref: /openbmc/u-boot/drivers/power/regulator/rk8xx.c (revision 00fc38ae)
1 /*
2  * Copyright (C) 2015 Google, Inc
3  * Written by Simon Glass <sjg@chromium.org>
4  *
5  * Based on Rockchip's drivers/power/pmic/pmic_rk808.c:
6  * Copyright (C) 2012 rockchips
7  * zyw <zyw@rock-chips.com>
8  *
9  * SPDX-License-Identifier:	GPL-2.0+
10  */
11 
12 #include <common.h>
13 #include <dm.h>
14 #include <errno.h>
15 #include <power/rk8xx_pmic.h>
16 #include <power/pmic.h>
17 #include <power/regulator.h>
18 
19 #ifndef CONFIG_SPL_BUILD
20 #define ENABLE_DRIVER
21 #endif
22 
23 /* Field Definitions */
24 #define RK808_BUCK_VSEL_MASK	0x3f
25 #define RK808_BUCK4_VSEL_MASK	0xf
26 #define RK808_LDO_VSEL_MASK	0x1f
27 
28 #define RK818_BUCK_VSEL_MASK		0x3f
29 #define RK818_BUCK4_VSEL_MASK		0x1f
30 #define RK818_LDO_VSEL_MASK		0x1f
31 #define RK818_LDO3_ON_VSEL_MASK	0xf
32 #define RK818_BOOST_ON_VSEL_MASK	0xe0
33 
34 struct rk8xx_reg_info {
35 	uint min_uv;
36 	uint step_uv;
37 	s8 vsel_reg;
38 	u8 vsel_mask;
39 };
40 
41 static const struct rk8xx_reg_info rk808_buck[] = {
42 	{ 712500, 12500, REG_BUCK1_ON_VSEL, RK808_BUCK_VSEL_MASK, },
43 	{ 712500, 12500, REG_BUCK2_ON_VSEL, RK808_BUCK_VSEL_MASK, },
44 	{ 712500, 12500, -1, RK808_BUCK_VSEL_MASK, },
45 	{ 1800000, 100000, REG_BUCK4_ON_VSEL, RK808_BUCK4_VSEL_MASK, },
46 };
47 
48 static const struct rk8xx_reg_info rk808_ldo[] = {
49 	{ 1800000, 100000, REG_LDO1_ON_VSEL, RK808_LDO_VSEL_MASK, },
50 	{ 1800000, 100000, REG_LDO2_ON_VSEL, RK808_LDO_VSEL_MASK, },
51 	{ 800000, 100000, REG_LDO3_ON_VSEL, RK808_BUCK4_VSEL_MASK, },
52 	{ 1800000, 100000, REG_LDO4_ON_VSEL, RK808_LDO_VSEL_MASK, },
53 	{ 1800000, 100000, REG_LDO5_ON_VSEL, RK808_LDO_VSEL_MASK, },
54 	{ 800000, 100000, REG_LDO6_ON_VSEL, RK808_LDO_VSEL_MASK, },
55 	{ 800000, 100000, REG_LDO7_ON_VSEL, RK808_LDO_VSEL_MASK, },
56 	{ 1800000, 100000, REG_LDO8_ON_VSEL, RK808_LDO_VSEL_MASK, },
57 };
58 
59 static const struct rk8xx_reg_info rk818_buck[] = {
60 	{ 712500, 12500, REG_BUCK1_ON_VSEL, RK818_BUCK_VSEL_MASK, },
61 	{ 712500, 12500, REG_BUCK2_ON_VSEL, RK818_BUCK_VSEL_MASK, },
62 	{ 712500, 12500, -1, RK818_BUCK_VSEL_MASK, },
63 	{ 1800000, 100000, REG_BUCK4_ON_VSEL, RK818_BUCK4_VSEL_MASK, },
64 };
65 
66 static const struct rk8xx_reg_info rk818_ldo[] = {
67 	{ 1800000, 100000, REG_LDO1_ON_VSEL, RK818_LDO_VSEL_MASK, },
68 	{ 1800000, 100000, REG_LDO2_ON_VSEL, RK818_LDO_VSEL_MASK, },
69 	{ 800000, 100000, REG_LDO3_ON_VSEL, RK818_LDO3_ON_VSEL_MASK, },
70 	{ 1800000, 100000, REG_LDO4_ON_VSEL, RK818_LDO_VSEL_MASK, },
71 	{ 1800000, 100000, REG_LDO5_ON_VSEL, RK818_LDO_VSEL_MASK, },
72 	{ 800000, 100000, REG_LDO6_ON_VSEL, RK818_LDO_VSEL_MASK, },
73 	{ 800000, 100000, REG_LDO7_ON_VSEL, RK818_LDO_VSEL_MASK, },
74 	{ 1800000, 100000, REG_LDO8_ON_VSEL, RK818_LDO_VSEL_MASK, },
75 };
76 
77 static const struct rk8xx_reg_info *get_buck_reg(struct udevice *pmic,
78 					     int num)
79 {
80 	struct rk8xx_priv *priv = dev_get_priv(pmic);
81 	switch (priv->variant) {
82 	case RK818_ID:
83 		return &rk818_buck[num];
84 	default:
85 		return &rk808_buck[num];
86 	}
87 }
88 
89 static const struct rk8xx_reg_info *get_ldo_reg(struct udevice *pmic,
90 					     int num)
91 {
92 	struct rk8xx_priv *priv = dev_get_priv(pmic);
93 	switch (priv->variant) {
94 	case RK818_ID:
95 		return &rk818_ldo[num - 1];
96 	default:
97 		return &rk808_ldo[num - 1];
98 	}
99 }
100 
101 static int _buck_set_value(struct udevice *pmic, int buck, int uvolt)
102 {
103 	const struct rk8xx_reg_info *info = get_buck_reg(pmic, buck - 1);
104 	int mask = info->vsel_mask;
105 	int val;
106 
107 	if (info->vsel_reg == -1)
108 		return -ENOSYS;
109 	val = (uvolt - info->min_uv) / info->step_uv;
110 	debug("%s: reg=%x, mask=%x, val=%x\n", __func__, info->vsel_reg, mask,
111 	      val);
112 
113 	return pmic_clrsetbits(pmic, info->vsel_reg, mask, val);
114 }
115 
116 static int _buck_set_enable(struct udevice *pmic, int buck, bool enable)
117 {
118 	uint mask;
119 	int ret;
120 
121 	buck--;
122 	mask = 1 << buck;
123 	if (enable) {
124 		ret = pmic_clrsetbits(pmic, REG_DCDC_ILMAX, 0, 3 << (buck * 2));
125 		if (ret)
126 			return ret;
127 		ret = pmic_clrsetbits(pmic, REG_DCDC_UV_ACT, 1 << buck, 0);
128 		if (ret)
129 			return ret;
130 	}
131 
132 	return pmic_clrsetbits(pmic, REG_DCDC_EN, mask, enable ? mask : 0);
133 }
134 
135 #ifdef ENABLE_DRIVER
136 static int buck_get_value(struct udevice *dev)
137 {
138 	int buck = dev->driver_data - 1;
139 	const struct rk8xx_reg_info *info = get_buck_reg(dev->parent, buck);
140 	int mask = info->vsel_mask;
141 	int ret, val;
142 
143 	if (info->vsel_reg == -1)
144 		return -ENOSYS;
145 	ret = pmic_reg_read(dev->parent, info->vsel_reg);
146 	if (ret < 0)
147 		return ret;
148 	val = ret & mask;
149 
150 	return info->min_uv + val * info->step_uv;
151 }
152 
153 static int buck_set_value(struct udevice *dev, int uvolt)
154 {
155 	int buck = dev->driver_data;
156 
157 	return _buck_set_value(dev->parent, buck, uvolt);
158 }
159 
160 static int buck_set_enable(struct udevice *dev, bool enable)
161 {
162 	int buck = dev->driver_data;
163 
164 	return _buck_set_enable(dev->parent, buck, enable);
165 }
166 
167 static bool buck_get_enable(struct udevice *dev)
168 {
169 	int buck = dev->driver_data - 1;
170 	int ret;
171 	uint mask;
172 
173 	mask = 1 << buck;
174 
175 	ret = pmic_reg_read(dev->parent, REG_DCDC_EN);
176 	if (ret < 0)
177 		return ret;
178 
179 	return ret & mask ? true : false;
180 }
181 
182 static int ldo_get_value(struct udevice *dev)
183 {
184 	int ldo = dev->driver_data - 1;
185 	const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo);
186 	int mask = info->vsel_mask;
187 	int ret, val;
188 
189 	if (info->vsel_reg == -1)
190 		return -ENOSYS;
191 	ret = pmic_reg_read(dev->parent, info->vsel_reg);
192 	if (ret < 0)
193 		return ret;
194 	val = ret & mask;
195 
196 	return info->min_uv + val * info->step_uv;
197 }
198 
199 static int ldo_set_value(struct udevice *dev, int uvolt)
200 {
201 	int ldo = dev->driver_data - 1;
202 	const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo);
203 	int mask = info->vsel_mask;
204 	int val;
205 
206 	if (info->vsel_reg == -1)
207 		return -ENOSYS;
208 	val = (uvolt - info->min_uv) / info->step_uv;
209 	debug("%s: reg=%x, mask=%x, val=%x\n", __func__, info->vsel_reg, mask,
210 	      val);
211 
212 	return pmic_clrsetbits(dev->parent, info->vsel_reg, mask, val);
213 }
214 
215 static int ldo_set_enable(struct udevice *dev, bool enable)
216 {
217 	int ldo = dev->driver_data - 1;
218 	uint mask;
219 
220 	mask = 1 << ldo;
221 
222 	return pmic_clrsetbits(dev->parent, REG_LDO_EN, mask,
223 			       enable ? mask : 0);
224 }
225 
226 static bool ldo_get_enable(struct udevice *dev)
227 {
228 	int ldo = dev->driver_data - 1;
229 	int ret;
230 	uint mask;
231 
232 	mask = 1 << ldo;
233 
234 	ret = pmic_reg_read(dev->parent, REG_LDO_EN);
235 	if (ret < 0)
236 		return ret;
237 
238 	return ret & mask ? true : false;
239 }
240 
241 static int switch_set_enable(struct udevice *dev, bool enable)
242 {
243 	int sw = dev->driver_data - 1;
244 	uint mask;
245 
246 	mask = 1 << (sw + 5);
247 
248 	return pmic_clrsetbits(dev->parent, REG_DCDC_EN, mask,
249 			       enable ? mask : 0);
250 }
251 
252 static bool switch_get_enable(struct udevice *dev)
253 {
254 	int sw = dev->driver_data - 1;
255 	int ret;
256 	uint mask;
257 
258 	mask = 1 << (sw + 5);
259 
260 	ret = pmic_reg_read(dev->parent, REG_DCDC_EN);
261 	if (ret < 0)
262 		return ret;
263 
264 	return ret & mask ? true : false;
265 }
266 
267 static int rk8xx_buck_probe(struct udevice *dev)
268 {
269 	struct dm_regulator_uclass_platdata *uc_pdata;
270 
271 	uc_pdata = dev_get_uclass_platdata(dev);
272 
273 	uc_pdata->type = REGULATOR_TYPE_BUCK;
274 	uc_pdata->mode_count = 0;
275 
276 	return 0;
277 }
278 
279 static int rk8xx_ldo_probe(struct udevice *dev)
280 {
281 	struct dm_regulator_uclass_platdata *uc_pdata;
282 
283 	uc_pdata = dev_get_uclass_platdata(dev);
284 
285 	uc_pdata->type = REGULATOR_TYPE_LDO;
286 	uc_pdata->mode_count = 0;
287 
288 	return 0;
289 }
290 
291 static int rk8xx_switch_probe(struct udevice *dev)
292 {
293 	struct dm_regulator_uclass_platdata *uc_pdata;
294 
295 	uc_pdata = dev_get_uclass_platdata(dev);
296 
297 	uc_pdata->type = REGULATOR_TYPE_FIXED;
298 	uc_pdata->mode_count = 0;
299 
300 	return 0;
301 }
302 
303 static const struct dm_regulator_ops rk8xx_buck_ops = {
304 	.get_value  = buck_get_value,
305 	.set_value  = buck_set_value,
306 	.get_enable = buck_get_enable,
307 	.set_enable = buck_set_enable,
308 };
309 
310 static const struct dm_regulator_ops rk8xx_ldo_ops = {
311 	.get_value  = ldo_get_value,
312 	.set_value  = ldo_set_value,
313 	.get_enable = ldo_get_enable,
314 	.set_enable = ldo_set_enable,
315 };
316 
317 static const struct dm_regulator_ops rk8xx_switch_ops = {
318 	.get_enable = switch_get_enable,
319 	.set_enable = switch_set_enable,
320 };
321 
322 U_BOOT_DRIVER(rk8xx_buck) = {
323 	.name = "rk8xx_buck",
324 	.id = UCLASS_REGULATOR,
325 	.ops = &rk8xx_buck_ops,
326 	.probe = rk8xx_buck_probe,
327 };
328 
329 U_BOOT_DRIVER(rk8xx_ldo) = {
330 	.name = "rk8xx_ldo",
331 	.id = UCLASS_REGULATOR,
332 	.ops = &rk8xx_ldo_ops,
333 	.probe = rk8xx_ldo_probe,
334 };
335 
336 U_BOOT_DRIVER(rk8xx_switch) = {
337 	.name = "rk8xx_switch",
338 	.id = UCLASS_REGULATOR,
339 	.ops = &rk8xx_switch_ops,
340 	.probe = rk8xx_switch_probe,
341 };
342 #endif
343 
344 int rk8xx_spl_configure_buck(struct udevice *pmic, int buck, int uvolt)
345 {
346 	int ret;
347 
348 	ret = _buck_set_value(pmic, buck, uvolt);
349 	if (ret)
350 		return ret;
351 
352 	return _buck_set_enable(pmic, buck, true);
353 }
354