Merge branch 'master' of git://git.denx.de/u-boot-samsung
[platform/kernel/u-boot.git] / drivers / power / regulator / rk8xx.c
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];
96         default:
97                 return &rk808_ldo[num];
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 }