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
out_get_value(struct udevice * dev,int output_count,int reg_type,struct output_range * range)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, ®_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
out_set_value(struct udevice * dev,int output_count,int reg_type,struct output_range * range,int value)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, ®_val, 1);
133 if (ret) {
134 pr_err("PMIC write failed: %d\n", ret);
135 return ret;
136 }
137
138 return 0;
139 }
140
out_get_mode(struct udevice * dev)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, ®_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
out_set_mode(struct udevice * dev,int mode)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 *)®_val, 1);
194 if (ret) {
195 pr_err("PMIC write failed: %d\n", ret);
196 return ret;
197 }
198
199 return 0;
200 }
201
buck_get_voltage(struct udevice * dev)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
buck_set_voltage(struct udevice * dev,int uV)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
buck_get_current(struct udevice * dev)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
buck_set_current(struct udevice * dev,int uA)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
buck_get_enable(struct udevice * dev)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
buck_set_enable(struct udevice * dev,bool enable)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
sandbox_buck_probe(struct udevice * dev)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
ldo_get_voltage(struct udevice * dev)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
ldo_set_voltage(struct udevice * dev,int uV)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
ldo_get_current(struct udevice * dev)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
ldo_set_current(struct udevice * dev,int uA)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
ldo_get_enable(struct udevice * dev)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
ldo_set_enable(struct udevice * dev,bool enable)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
sandbox_ldo_probe(struct udevice * dev)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 };
353