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