]> git.sur5r.net Git - u-boot/blob - drivers/power/regulator/sandbox.c
Merge branch 'master' of git://git.denx.de/u-boot-sunxi
[u-boot] / drivers / power / regulator / sandbox.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  *  Copyright (C) 2015 Samsung Electronics
4  *  Przemyslaw Marczak  <p.marczak@samsung.com>
5  */
6
7 #include <common.h>
8 #include <fdtdec.h>
9 #include <errno.h>
10 #include <dm.h>
11 #include <i2c.h>
12 #include <power/pmic.h>
13 #include <power/regulator.h>
14 #include <power/sandbox_pmic.h>
15
16 #define MODE(_id, _val, _name) [_id] = {  \
17         .id = _id,                \
18         .register_value = _val,   \
19         .name = _name,            \
20 }
21
22 #define RANGE(_min, _max, _step) { \
23         .min = _min,               \
24         .max = _max,               \
25         .step = _step,             \
26 }
27
28 /*
29  * struct output_range - helper structure type to define the range of output
30  * operating values (current/voltage), limited by the PMIC IC design.
31  *
32  * @min  - minimum value
33  * @max  - maximum value
34  * @step - step value
35 */
36 struct output_range {
37         int min;
38         int max;
39         int step;
40 };
41
42 /* BUCK: 1,2 - voltage range */
43 static struct output_range buck_voltage_range[] = {
44         RANGE(OUT_BUCK1_UV_MIN, OUT_BUCK1_UV_MAX, OUT_BUCK1_UV_STEP),
45         RANGE(OUT_BUCK2_UV_MIN, OUT_BUCK2_UV_MAX, OUT_BUCK2_UV_STEP),
46 };
47
48 /* BUCK: 1 - current range */
49 static struct output_range buck_current_range[] = {
50         RANGE(OUT_BUCK1_UA_MIN, OUT_BUCK1_UA_MAX, OUT_BUCK1_UA_STEP),
51 };
52
53 /* BUCK operating modes */
54 static struct dm_regulator_mode sandbox_buck_modes[] = {
55         MODE(BUCK_OM_OFF, OM2REG(BUCK_OM_OFF), "OFF"),
56         MODE(BUCK_OM_ON, OM2REG(BUCK_OM_ON), "ON"),
57         MODE(BUCK_OM_PWM, OM2REG(BUCK_OM_PWM), "PWM"),
58 };
59
60 /* LDO: 1,2 - voltage range */
61 static struct output_range ldo_voltage_range[] = {
62         RANGE(OUT_LDO1_UV_MIN, OUT_LDO1_UV_MAX, OUT_LDO1_UV_STEP),
63         RANGE(OUT_LDO2_UV_MIN, OUT_LDO2_UV_MAX, OUT_LDO2_UV_STEP),
64 };
65
66 /* LDO: 1 - current range */
67 static struct output_range ldo_current_range[] = {
68         RANGE(OUT_LDO1_UA_MIN, OUT_LDO1_UA_MAX, OUT_LDO1_UA_STEP),
69 };
70
71 /* LDO operating modes */
72 static struct dm_regulator_mode sandbox_ldo_modes[] = {
73         MODE(LDO_OM_OFF, OM2REG(LDO_OM_OFF), "OFF"),
74         MODE(LDO_OM_ON, OM2REG(LDO_OM_ON), "ON"),
75         MODE(LDO_OM_SLEEP, OM2REG(LDO_OM_SLEEP), "SLEEP"),
76         MODE(LDO_OM_STANDBY, OM2REG(LDO_OM_STANDBY), "STANDBY"),
77 };
78
79 int out_get_value(struct udevice *dev, int output_count, int reg_type,
80                   struct output_range *range)
81 {
82         uint8_t reg_val;
83         uint reg;
84         int ret;
85
86         if (dev->driver_data > output_count) {
87                 pr_err("Unknown regulator number: %lu for PMIC %s!",
88                       dev->driver_data, dev->name);
89                 return -EINVAL;
90         }
91
92         reg = (dev->driver_data - 1) * OUT_REG_COUNT + reg_type;
93         ret = pmic_read(dev->parent, reg, &reg_val, 1);
94         if (ret) {
95                 pr_err("PMIC read failed: %d\n",  ret);
96                 return ret;
97         }
98
99         ret =  REG2VAL(range[dev->driver_data - 1].min,
100                        range[dev->driver_data - 1].step,
101                        reg_val);
102
103         return ret;
104 }
105
106 static int out_set_value(struct udevice *dev, int output_count, int reg_type,
107                          struct output_range *range, int value)
108 {
109         uint8_t reg_val;
110         uint reg;
111         int ret;
112         int max_value;
113
114         if (dev->driver_data > output_count) {
115                 pr_err("Unknown regulator number: %lu for PMIC %s!",
116                       dev->driver_data, dev->name);
117                 return -EINVAL;
118         }
119
120         max_value = range[dev->driver_data - 1].max;
121         if (value > max_value) {
122                 pr_err("Wrong value for %s: %lu. Max is: %d.",
123                       dev->name, dev->driver_data, max_value);
124                 return -EINVAL;
125         }
126
127         reg_val = VAL2REG(range[dev->driver_data - 1].min,
128                           range[dev->driver_data - 1].step,
129                           value);
130
131         reg = (dev->driver_data - 1) * OUT_REG_COUNT + reg_type;
132         ret = pmic_write(dev->parent, reg, &reg_val, 1);
133         if (ret) {
134                 pr_err("PMIC write failed: %d\n",  ret);
135                 return ret;
136         }
137
138         return 0;
139 }
140
141 static int out_get_mode(struct udevice *dev)
142 {
143         struct dm_regulator_uclass_platdata *uc_pdata;
144         uint8_t reg_val;
145         uint reg;
146         int ret;
147         int i;
148
149         uc_pdata = dev_get_uclass_platdata(dev);
150
151         reg = (dev->driver_data - 1) * OUT_REG_COUNT + OUT_REG_OM;
152         ret = pmic_read(dev->parent, reg, &reg_val, 1);
153         if (ret) {
154                 pr_err("PMIC read failed: %d\n",  ret);
155                 return ret;
156         }
157
158         for (i = 0; i < uc_pdata->mode_count; i++) {
159                 if (reg_val == uc_pdata->mode[i].register_value)
160                         return uc_pdata->mode[i].id;
161         }
162
163         pr_err("Unknown operation mode for %s!", dev->name);
164         return -EINVAL;
165 }
166
167 static int out_set_mode(struct udevice *dev, int mode)
168 {
169         struct dm_regulator_uclass_platdata *uc_pdata;
170         int reg_val = -1;
171         uint reg;
172         int ret;
173         int i;
174
175         uc_pdata = dev_get_uclass_platdata(dev);
176
177         if (mode >= uc_pdata->mode_count)
178                 return -EINVAL;
179
180         for (i = 0; i < uc_pdata->mode_count; i++) {
181                 if (mode == uc_pdata->mode[i].id) {
182                         reg_val = uc_pdata->mode[i].register_value;
183                         break;
184                 }
185         }
186
187         if (reg_val == -1) {
188                 pr_err("Unknown operation mode for %s!", dev->name);
189                 return -EINVAL;
190         }
191
192         reg = (dev->driver_data - 1) * OUT_REG_COUNT + OUT_REG_OM;
193         ret = pmic_write(dev->parent, reg, (uint8_t *)&reg_val, 1);
194         if (ret) {
195                 pr_err("PMIC write failed: %d\n",  ret);
196                 return ret;
197         }
198
199         return 0;
200 }
201
202 static int buck_get_voltage(struct udevice *dev)
203 {
204         return out_get_value(dev, SANDBOX_BUCK_COUNT, OUT_REG_UV,
205                               buck_voltage_range);
206 }
207
208 static int buck_set_voltage(struct udevice *dev, int uV)
209 {
210         return out_set_value(dev, SANDBOX_BUCK_COUNT, OUT_REG_UV,
211                               buck_voltage_range, uV);
212 }
213
214 static int buck_get_current(struct udevice *dev)
215 {
216         /* BUCK2 - unsupported */
217         if (dev->driver_data == 2)
218                 return -ENOSYS;
219
220         return out_get_value(dev, SANDBOX_BUCK_COUNT, OUT_REG_UA,
221                               buck_current_range);
222 }
223
224 static int buck_set_current(struct udevice *dev, int uA)
225 {
226         /* BUCK2 - unsupported */
227         if (dev->driver_data == 2)
228                 return -ENOSYS;
229
230         return out_set_value(dev, SANDBOX_BUCK_COUNT, OUT_REG_UA,
231                               buck_current_range, uA);
232 }
233
234 static int buck_get_enable(struct udevice *dev)
235 {
236         if (out_get_mode(dev) == BUCK_OM_OFF)
237                 return false;
238
239         return true;
240 }
241
242 static int buck_set_enable(struct udevice *dev, bool enable)
243 {
244         return out_set_mode(dev, enable ? BUCK_OM_ON : BUCK_OM_OFF);
245 }
246
247 static int sandbox_buck_probe(struct udevice *dev)
248 {
249         struct dm_regulator_uclass_platdata *uc_pdata;
250
251         uc_pdata = dev_get_uclass_platdata(dev);
252
253         uc_pdata->type = REGULATOR_TYPE_BUCK;
254         uc_pdata->mode = sandbox_buck_modes;
255         uc_pdata->mode_count = ARRAY_SIZE(sandbox_buck_modes);
256
257         return 0;
258 }
259
260 static const struct dm_regulator_ops sandbox_buck_ops = {
261         .get_value   = buck_get_voltage,
262         .set_value   = buck_set_voltage,
263         .get_current = buck_get_current,
264         .set_current = buck_set_current,
265         .get_enable  = buck_get_enable,
266         .set_enable  = buck_set_enable,
267         .get_mode    = out_get_mode,
268         .set_mode    = out_set_mode,
269 };
270
271 U_BOOT_DRIVER(sandbox_buck) = {
272         .name = SANDBOX_BUCK_DRIVER,
273         .id = UCLASS_REGULATOR,
274         .ops = &sandbox_buck_ops,
275         .probe = sandbox_buck_probe,
276 };
277
278 static int ldo_get_voltage(struct udevice *dev)
279 {
280         return out_get_value(dev, SANDBOX_LDO_COUNT, OUT_REG_UV,
281                              ldo_voltage_range);
282 }
283
284 static int ldo_set_voltage(struct udevice *dev, int uV)
285 {
286         return out_set_value(dev, SANDBOX_LDO_COUNT, OUT_REG_UV,
287                              ldo_voltage_range, uV);
288 }
289
290 static int ldo_get_current(struct udevice *dev)
291 {
292         /* LDO2 - unsupported */
293         if (dev->driver_data == 2)
294                 return -ENOSYS;
295
296         return out_get_value(dev, SANDBOX_LDO_COUNT, OUT_REG_UA,
297                              ldo_current_range);
298 }
299
300 static int ldo_set_current(struct udevice *dev, int uA)
301 {
302         /* LDO2 - unsupported */
303         if (dev->driver_data == 2)
304                 return -ENOSYS;
305
306         return out_set_value(dev, SANDBOX_LDO_COUNT, OUT_REG_UA,
307                              ldo_current_range, uA);
308 }
309
310 static int ldo_get_enable(struct udevice *dev)
311 {
312         if (out_get_mode(dev) == LDO_OM_OFF)
313                 return false;
314
315         return true;
316 }
317
318 static int ldo_set_enable(struct udevice *dev, bool enable)
319 {
320         return out_set_mode(dev, enable ? LDO_OM_ON : LDO_OM_OFF);
321 }
322
323 static int sandbox_ldo_probe(struct udevice *dev)
324 {
325         struct dm_regulator_uclass_platdata *uc_pdata;
326
327         uc_pdata = dev_get_uclass_platdata(dev);
328
329         uc_pdata->type = REGULATOR_TYPE_LDO;
330         uc_pdata->mode = sandbox_ldo_modes;
331         uc_pdata->mode_count = ARRAY_SIZE(sandbox_ldo_modes);
332
333         return 0;
334 }
335
336 static const struct dm_regulator_ops sandbox_ldo_ops = {
337         .get_value   = ldo_get_voltage,
338         .set_value   = ldo_set_voltage,
339         .get_current = ldo_get_current,
340         .set_current = ldo_set_current,
341         .get_enable  = ldo_get_enable,
342         .set_enable  = ldo_set_enable,
343         .get_mode    = out_get_mode,
344         .set_mode    = out_set_mode,
345 };
346
347 U_BOOT_DRIVER(sandbox_ldo) = {
348         .name = SANDBOX_LDO_DRIVER,
349         .id = UCLASS_REGULATOR,
350         .ops = &sandbox_ldo_ops,
351         .probe = sandbox_ldo_probe,
352 };