]>
Commit | Line | Data |
---|---|---|
1757df46 PM |
1 | /* |
2 | * Copyright (C) 2012-2015 Samsung Electronics | |
3 | * | |
4 | * Rajeshwari Shinde <[email protected]> | |
5 | * Przemyslaw Marczak <[email protected]> | |
6 | * | |
7 | * SPDX-License-Identifier: GPL-2.0+ | |
8 | */ | |
9 | ||
10 | #include <common.h> | |
11 | #include <fdtdec.h> | |
12 | #include <errno.h> | |
13 | #include <dm.h> | |
14 | #include <i2c.h> | |
15 | #include <power/pmic.h> | |
16 | #include <power/regulator.h> | |
17 | #include <power/max77686_pmic.h> | |
18 | ||
19 | DECLARE_GLOBAL_DATA_PTR; | |
20 | ||
21 | #define MODE(_id, _val, _name) { \ | |
22 | .id = _id, \ | |
23 | .register_value = _val, \ | |
24 | .name = _name, \ | |
25 | } | |
26 | ||
27 | /* LDO: 1,3,4,5,9,17,18,19,20,21,22,23,24,26,26,27 */ | |
28 | static struct dm_regulator_mode max77686_ldo_mode_standby1[] = { | |
29 | MODE(OPMODE_OFF, MAX77686_LDO_MODE_OFF, "OFF"), | |
30 | MODE(OPMODE_LPM, MAX77686_LDO_MODE_LPM, "LPM"), | |
31 | MODE(OPMODE_STANDBY_LPM, MAX77686_LDO_MODE_STANDBY_LPM, "ON/LPM"), | |
32 | MODE(OPMODE_ON, MAX77686_LDO_MODE_ON, "ON"), | |
33 | }; | |
34 | ||
35 | /* LDO: 2,6,7,8,10,11,12,14,15,16 */ | |
36 | static struct dm_regulator_mode max77686_ldo_mode_standby2[] = { | |
37 | MODE(OPMODE_OFF, MAX77686_LDO_MODE_OFF, "OFF"), | |
38 | MODE(OPMODE_STANDBY, MAX77686_LDO_MODE_STANDBY, "ON/OFF"), | |
39 | MODE(OPMODE_STANDBY_LPM, MAX77686_LDO_MODE_STANDBY_LPM, "ON/LPM"), | |
40 | MODE(OPMODE_ON, MAX77686_LDO_MODE_ON, "ON"), | |
41 | }; | |
42 | ||
43 | /* Buck: 1 */ | |
44 | static struct dm_regulator_mode max77686_buck_mode_standby[] = { | |
45 | MODE(OPMODE_OFF, MAX77686_BUCK_MODE_OFF, "OFF"), | |
46 | MODE(OPMODE_STANDBY, MAX77686_BUCK_MODE_STANDBY, "ON/OFF"), | |
47 | MODE(OPMODE_ON, MAX77686_BUCK_MODE_ON, "ON"), | |
48 | }; | |
49 | ||
50 | /* Buck: 2,3,4 */ | |
51 | static struct dm_regulator_mode max77686_buck_mode_lpm[] = { | |
52 | MODE(OPMODE_OFF, MAX77686_BUCK_MODE_OFF, "OFF"), | |
53 | MODE(OPMODE_STANDBY, MAX77686_BUCK_MODE_STANDBY, "ON/OFF"), | |
54 | MODE(OPMODE_LPM, MAX77686_BUCK_MODE_LPM, "LPM"), | |
55 | MODE(OPMODE_ON, MAX77686_BUCK_MODE_ON, "ON"), | |
56 | }; | |
57 | ||
58 | /* Buck: 5,6,7,8,9 */ | |
59 | static struct dm_regulator_mode max77686_buck_mode_onoff[] = { | |
60 | MODE(OPMODE_OFF, MAX77686_BUCK_MODE_OFF, "OFF"), | |
61 | MODE(OPMODE_ON, MAX77686_BUCK_MODE_ON, "ON"), | |
62 | }; | |
63 | ||
8c428709 | 64 | static const char max77686_buck_ctrl[] = { |
1757df46 PM |
65 | 0xff, 0x10, 0x12, 0x1c, 0x26, 0x30, 0x32, 0x34, 0x36, 0x38 |
66 | }; | |
67 | ||
8c428709 SG |
68 | static const char max77686_buck_out[] = { |
69 | 0xff, 0x11, 0x14, 0x1e, 0x28, 0x31, 0x33, 0x35, 0x37, 0x39 | |
70 | }; | |
71 | ||
1757df46 PM |
72 | static int max77686_buck_volt2hex(int buck, int uV) |
73 | { | |
74 | unsigned int hex = 0; | |
75 | unsigned int hex_max = 0; | |
76 | ||
77 | switch (buck) { | |
78 | case 2: | |
79 | case 3: | |
80 | case 4: | |
81 | /* hex = (uV - 600000) / 12500; */ | |
82 | hex = (uV - MAX77686_BUCK_UV_LMIN) / MAX77686_BUCK_UV_LSTEP; | |
83 | hex_max = MAX77686_BUCK234_VOLT_MAX_HEX; | |
84 | /** | |
85 | * Those use voltage scaller - temporary not implemented | |
86 | * so return just 0 | |
87 | */ | |
88 | return -ENOSYS; | |
89 | default: | |
90 | /* hex = (uV - 750000) / 50000; */ | |
91 | hex = (uV - MAX77686_BUCK_UV_HMIN) / MAX77686_BUCK_UV_HSTEP; | |
92 | hex_max = MAX77686_BUCK_VOLT_MAX_HEX; | |
93 | break; | |
94 | } | |
95 | ||
96 | if (hex >= 0 && hex <= hex_max) | |
97 | return hex; | |
98 | ||
99 | error("Value: %d uV is wrong for BUCK%d", uV, buck); | |
100 | return -EINVAL; | |
101 | } | |
102 | ||
103 | static int max77686_buck_hex2volt(int buck, int hex) | |
104 | { | |
105 | unsigned uV = 0; | |
106 | unsigned int hex_max = 0; | |
107 | ||
108 | if (hex < 0) | |
109 | goto bad_hex; | |
110 | ||
111 | switch (buck) { | |
112 | case 2: | |
113 | case 3: | |
114 | case 4: | |
115 | hex_max = MAX77686_BUCK234_VOLT_MAX_HEX; | |
116 | if (hex > hex_max) | |
117 | goto bad_hex; | |
118 | ||
119 | /* uV = hex * 12500 + 600000; */ | |
120 | uV = hex * MAX77686_BUCK_UV_LSTEP + MAX77686_BUCK_UV_LMIN; | |
121 | break; | |
122 | default: | |
123 | hex_max = MAX77686_BUCK_VOLT_MAX_HEX; | |
124 | if (hex > hex_max) | |
125 | goto bad_hex; | |
126 | ||
127 | /* uV = hex * 50000 + 750000; */ | |
128 | uV = hex * MAX77686_BUCK_UV_HSTEP + MAX77686_BUCK_UV_HMIN; | |
129 | break; | |
130 | } | |
131 | ||
132 | return uV; | |
133 | ||
134 | bad_hex: | |
135 | error("Value: %#x is wrong for BUCK%d", hex, buck); | |
136 | return -EINVAL; | |
137 | } | |
138 | ||
139 | static int max77686_ldo_volt2hex(int ldo, int uV) | |
140 | { | |
141 | unsigned int hex = 0; | |
142 | ||
143 | switch (ldo) { | |
144 | case 1: | |
145 | case 2: | |
146 | case 6: | |
147 | case 7: | |
148 | case 8: | |
149 | case 15: | |
150 | hex = (uV - MAX77686_LDO_UV_MIN) / MAX77686_LDO_UV_LSTEP; | |
151 | /* hex = (uV - 800000) / 25000; */ | |
152 | break; | |
153 | default: | |
154 | hex = (uV - MAX77686_LDO_UV_MIN) / MAX77686_LDO_UV_HSTEP; | |
155 | /* hex = (uV - 800000) / 50000; */ | |
156 | } | |
157 | ||
158 | if (hex >= 0 && hex <= MAX77686_LDO_VOLT_MAX_HEX) | |
159 | return hex; | |
160 | ||
161 | error("Value: %d uV is wrong for LDO%d", uV, ldo); | |
162 | return -EINVAL; | |
163 | } | |
164 | ||
165 | static int max77686_ldo_hex2volt(int ldo, int hex) | |
166 | { | |
167 | unsigned int uV = 0; | |
168 | ||
169 | if (hex > MAX77686_LDO_VOLT_MAX_HEX) | |
170 | goto bad_hex; | |
171 | ||
172 | switch (ldo) { | |
173 | case 1: | |
174 | case 2: | |
175 | case 6: | |
176 | case 7: | |
177 | case 8: | |
178 | case 15: | |
179 | /* uV = hex * 25000 + 800000; */ | |
180 | uV = hex * MAX77686_LDO_UV_LSTEP + MAX77686_LDO_UV_MIN; | |
181 | break; | |
182 | default: | |
183 | /* uV = hex * 50000 + 800000; */ | |
184 | uV = hex * MAX77686_LDO_UV_HSTEP + MAX77686_LDO_UV_MIN; | |
185 | } | |
186 | ||
187 | return uV; | |
188 | ||
189 | bad_hex: | |
190 | error("Value: %#x is wrong for ldo%d", hex, ldo); | |
191 | return -EINVAL; | |
192 | } | |
193 | ||
194 | static int max77686_ldo_hex2mode(int ldo, int hex) | |
195 | { | |
196 | if (hex > MAX77686_LDO_MODE_MASK) | |
197 | return -EINVAL; | |
198 | ||
199 | switch (hex) { | |
200 | case MAX77686_LDO_MODE_OFF: | |
201 | return OPMODE_OFF; | |
202 | case MAX77686_LDO_MODE_LPM: /* == MAX77686_LDO_MODE_STANDBY: */ | |
203 | /* The same mode values but different meaning for each ldo */ | |
204 | switch (ldo) { | |
205 | case 2: | |
206 | case 6: | |
207 | case 7: | |
208 | case 8: | |
209 | case 10: | |
210 | case 11: | |
211 | case 12: | |
212 | case 14: | |
213 | case 15: | |
214 | case 16: | |
215 | return OPMODE_STANDBY; | |
216 | default: | |
217 | return OPMODE_LPM; | |
218 | } | |
219 | case MAX77686_LDO_MODE_STANDBY_LPM: | |
220 | return OPMODE_STANDBY_LPM; | |
221 | case MAX77686_LDO_MODE_ON: | |
222 | return OPMODE_ON; | |
223 | default: | |
224 | return -EINVAL; | |
225 | } | |
226 | } | |
227 | ||
228 | static int max77686_buck_hex2mode(int buck, int hex) | |
229 | { | |
230 | if (hex > MAX77686_BUCK_MODE_MASK) | |
231 | return -EINVAL; | |
232 | ||
233 | switch (hex) { | |
234 | case MAX77686_BUCK_MODE_OFF: | |
235 | return OPMODE_OFF; | |
236 | case MAX77686_BUCK_MODE_ON: | |
237 | return OPMODE_ON; | |
238 | case MAX77686_BUCK_MODE_STANDBY: | |
239 | switch (buck) { | |
240 | case 1: | |
241 | case 2: | |
242 | case 3: | |
243 | case 4: | |
244 | return OPMODE_STANDBY; | |
245 | default: | |
246 | return -EINVAL; | |
247 | } | |
248 | case MAX77686_BUCK_MODE_LPM: | |
249 | switch (buck) { | |
250 | case 2: | |
251 | case 3: | |
252 | case 4: | |
253 | return OPMODE_LPM; | |
254 | default: | |
255 | return -EINVAL; | |
256 | } | |
257 | default: | |
258 | return -EINVAL; | |
259 | } | |
260 | } | |
261 | ||
262 | static int max77686_buck_modes(int buck, struct dm_regulator_mode **modesp) | |
263 | { | |
264 | int ret = -EINVAL; | |
265 | ||
266 | if (buck < 1 || buck > MAX77686_BUCK_NUM) | |
267 | return ret; | |
268 | ||
269 | switch (buck) { | |
270 | case 1: | |
271 | *modesp = max77686_buck_mode_standby; | |
272 | ret = ARRAY_SIZE(max77686_buck_mode_standby); | |
273 | break; | |
274 | case 2: | |
275 | case 3: | |
276 | case 4: | |
277 | *modesp = max77686_buck_mode_lpm; | |
278 | ret = ARRAY_SIZE(max77686_buck_mode_lpm); | |
279 | break; | |
280 | default: | |
281 | *modesp = max77686_buck_mode_onoff; | |
282 | ret = ARRAY_SIZE(max77686_buck_mode_onoff); | |
283 | } | |
284 | ||
285 | return ret; | |
286 | } | |
287 | ||
288 | static int max77686_ldo_modes(int ldo, struct dm_regulator_mode **modesp, | |
289 | struct udevice *dev) | |
290 | { | |
291 | int ret = -EINVAL; | |
292 | ||
293 | if (ldo < 1 || ldo > MAX77686_LDO_NUM) | |
294 | return ret; | |
295 | ||
296 | switch (ldo) { | |
297 | case 2: | |
298 | case 6: | |
299 | case 7: | |
300 | case 8: | |
301 | case 10: | |
302 | case 11: | |
303 | case 12: | |
304 | case 14: | |
305 | case 15: | |
306 | case 16: | |
307 | *modesp = max77686_ldo_mode_standby2; | |
308 | ret = ARRAY_SIZE(max77686_ldo_mode_standby2); | |
309 | break; | |
310 | default: | |
311 | *modesp = max77686_ldo_mode_standby1; | |
312 | ret = ARRAY_SIZE(max77686_ldo_mode_standby1); | |
313 | } | |
314 | ||
315 | return ret; | |
316 | } | |
317 | ||
318 | static int max77686_ldo_val(struct udevice *dev, int op, int *uV) | |
319 | { | |
320 | unsigned int ret, hex, adr; | |
321 | unsigned char val; | |
322 | int ldo; | |
323 | ||
324 | if (op == PMIC_OP_GET) | |
325 | *uV = 0; | |
326 | ||
327 | ldo = dev->driver_data; | |
328 | if (ldo < 1 || ldo > MAX77686_LDO_NUM) { | |
329 | error("Wrong ldo number: %d", ldo); | |
330 | return -EINVAL; | |
331 | } | |
332 | ||
333 | adr = MAX77686_REG_PMIC_LDO1CTRL1 + ldo - 1; | |
334 | ||
335 | ret = pmic_read(dev->parent, adr, &val, 1); | |
336 | if (ret) | |
337 | return ret; | |
338 | ||
339 | if (op == PMIC_OP_GET) { | |
340 | val &= MAX77686_LDO_VOLT_MASK; | |
341 | ret = max77686_ldo_hex2volt(ldo, val); | |
342 | if (ret < 0) | |
343 | return ret; | |
344 | *uV = ret; | |
345 | return 0; | |
346 | } | |
347 | ||
348 | hex = max77686_ldo_volt2hex(ldo, *uV); | |
349 | if (hex < 0) | |
350 | return hex; | |
351 | ||
352 | val &= ~MAX77686_LDO_VOLT_MASK; | |
353 | val |= hex; | |
354 | ret = pmic_write(dev->parent, adr, &val, 1); | |
355 | ||
356 | return ret; | |
357 | } | |
358 | ||
359 | static int max77686_buck_val(struct udevice *dev, int op, int *uV) | |
360 | { | |
361 | unsigned int hex, ret, mask, adr; | |
362 | unsigned char val; | |
363 | int buck; | |
364 | ||
365 | buck = dev->driver_data; | |
366 | if (buck < 1 || buck > MAX77686_BUCK_NUM) { | |
367 | error("Wrong buck number: %d", buck); | |
368 | return -EINVAL; | |
369 | } | |
370 | ||
371 | if (op == PMIC_OP_GET) | |
372 | *uV = 0; | |
373 | ||
374 | /* &buck_out = ctrl + 1 */ | |
8c428709 | 375 | adr = max77686_buck_out[buck]; |
1757df46 PM |
376 | |
377 | /* mask */ | |
378 | switch (buck) { | |
379 | case 2: | |
380 | case 3: | |
381 | case 4: | |
382 | /* Those use voltage scallers - will support in the future */ | |
383 | mask = MAX77686_BUCK234_VOLT_MASK; | |
384 | return -ENOSYS; | |
385 | default: | |
386 | mask = MAX77686_BUCK_VOLT_MASK; | |
387 | } | |
388 | ||
389 | ret = pmic_read(dev->parent, adr, &val, 1); | |
390 | if (ret) | |
391 | return ret; | |
392 | ||
393 | if (op == PMIC_OP_GET) { | |
394 | val &= mask; | |
395 | ret = max77686_buck_hex2volt(buck, val); | |
396 | if (ret < 0) | |
397 | return ret; | |
398 | *uV = ret; | |
399 | return 0; | |
400 | } | |
401 | ||
402 | hex = max77686_buck_volt2hex(buck, *uV); | |
403 | if (hex < 0) | |
404 | return hex; | |
405 | ||
406 | val &= ~mask; | |
407 | val |= hex; | |
408 | ret = pmic_write(dev->parent, adr, &val, 1); | |
409 | ||
410 | return ret; | |
411 | } | |
412 | ||
413 | static int max77686_ldo_mode(struct udevice *dev, int op, int *opmode) | |
414 | { | |
415 | unsigned int ret, adr, mode; | |
416 | unsigned char val; | |
417 | int ldo; | |
418 | ||
419 | if (op == PMIC_OP_GET) | |
420 | *opmode = -EINVAL; | |
421 | ||
422 | ldo = dev->driver_data; | |
423 | if (ldo < 1 || ldo > MAX77686_LDO_NUM) { | |
424 | error("Wrong ldo number: %d", ldo); | |
425 | return -EINVAL; | |
426 | } | |
427 | ||
428 | adr = MAX77686_REG_PMIC_LDO1CTRL1 + ldo - 1; | |
429 | ||
430 | ret = pmic_read(dev->parent, adr, &val, 1); | |
431 | if (ret) | |
432 | return ret; | |
433 | ||
434 | if (op == PMIC_OP_GET) { | |
435 | val &= MAX77686_LDO_MODE_MASK; | |
436 | ret = max77686_ldo_hex2mode(ldo, val); | |
437 | if (ret < 0) | |
438 | return ret; | |
439 | *opmode = ret; | |
440 | return 0; | |
441 | } | |
442 | ||
443 | /* mode */ | |
444 | switch (*opmode) { | |
445 | case OPMODE_OFF: | |
446 | mode = MAX77686_LDO_MODE_OFF; | |
447 | break; | |
448 | case OPMODE_LPM: | |
449 | switch (ldo) { | |
450 | case 2: | |
451 | case 6: | |
452 | case 7: | |
453 | case 8: | |
454 | case 10: | |
455 | case 11: | |
456 | case 12: | |
457 | case 14: | |
458 | case 15: | |
459 | case 16: | |
460 | return -EINVAL; | |
461 | default: | |
462 | mode = MAX77686_LDO_MODE_LPM; | |
463 | } | |
464 | break; | |
465 | case OPMODE_STANDBY: | |
466 | switch (ldo) { | |
467 | case 2: | |
468 | case 6: | |
469 | case 7: | |
470 | case 8: | |
471 | case 10: | |
472 | case 11: | |
473 | case 12: | |
474 | case 14: | |
475 | case 15: | |
476 | case 16: | |
477 | mode = MAX77686_LDO_MODE_STANDBY; | |
478 | break; | |
479 | default: | |
480 | return -EINVAL; | |
481 | } | |
482 | break; | |
483 | case OPMODE_STANDBY_LPM: | |
484 | mode = MAX77686_LDO_MODE_STANDBY_LPM; | |
485 | break; | |
486 | case OPMODE_ON: | |
487 | mode = MAX77686_LDO_MODE_ON; | |
488 | break; | |
489 | default: | |
490 | mode = 0xff; | |
491 | } | |
492 | ||
493 | if (mode == 0xff) { | |
494 | error("Wrong mode: %d for ldo%d", *opmode, ldo); | |
495 | return -EINVAL; | |
496 | } | |
497 | ||
498 | val &= ~MAX77686_LDO_MODE_MASK; | |
499 | val |= mode; | |
500 | ret = pmic_write(dev->parent, adr, &val, 1); | |
501 | ||
502 | return ret; | |
503 | } | |
504 | ||
505 | static int max77686_ldo_enable(struct udevice *dev, int op, bool *enable) | |
506 | { | |
507 | int ret, on_off; | |
508 | ||
509 | if (op == PMIC_OP_GET) { | |
510 | ret = max77686_ldo_mode(dev, op, &on_off); | |
511 | if (ret) | |
512 | return ret; | |
513 | ||
514 | switch (on_off) { | |
515 | case OPMODE_OFF: | |
516 | *enable = 0; | |
517 | break; | |
518 | case OPMODE_ON: | |
519 | *enable = 1; | |
520 | break; | |
521 | default: | |
522 | return -EINVAL; | |
523 | } | |
524 | } else if (op == PMIC_OP_SET) { | |
525 | switch (*enable) { | |
526 | case 0: | |
527 | on_off = OPMODE_OFF; | |
528 | break; | |
529 | case 1: | |
530 | on_off = OPMODE_ON; | |
531 | break; | |
532 | default: | |
533 | return -EINVAL; | |
534 | } | |
535 | ||
536 | ret = max77686_ldo_mode(dev, op, &on_off); | |
537 | if (ret) | |
538 | return ret; | |
539 | } | |
540 | ||
541 | return 0; | |
542 | } | |
543 | ||
544 | static int max77686_buck_mode(struct udevice *dev, int op, int *opmode) | |
545 | { | |
546 | unsigned int ret, mask, adr, mode, mode_shift; | |
547 | unsigned char val; | |
548 | int buck; | |
549 | ||
550 | buck = dev->driver_data; | |
551 | if (buck < 1 || buck > MAX77686_BUCK_NUM) { | |
552 | error("Wrong buck number: %d", buck); | |
553 | return -EINVAL; | |
554 | } | |
555 | ||
8c428709 | 556 | adr = max77686_buck_ctrl[buck]; |
1757df46 PM |
557 | |
558 | /* mask */ | |
559 | switch (buck) { | |
560 | case 2: | |
561 | case 3: | |
562 | case 4: | |
563 | mode_shift = MAX77686_BUCK_MODE_SHIFT_2; | |
564 | break; | |
565 | default: | |
566 | mode_shift = MAX77686_BUCK_MODE_SHIFT_1; | |
567 | } | |
568 | ||
569 | mask = MAX77686_BUCK_MODE_MASK << mode_shift; | |
570 | ||
571 | ret = pmic_read(dev->parent, adr, &val, 1); | |
572 | if (ret) | |
573 | return ret; | |
574 | ||
575 | if (op == PMIC_OP_GET) { | |
576 | val &= mask; | |
577 | val >>= mode_shift; | |
578 | ret = max77686_buck_hex2mode(buck, val); | |
579 | if (ret < 0) | |
580 | return ret; | |
581 | *opmode = ret; | |
582 | return 0; | |
583 | } | |
584 | ||
585 | /* mode */ | |
586 | switch (*opmode) { | |
587 | case OPMODE_OFF: | |
588 | mode = MAX77686_BUCK_MODE_OFF; | |
589 | break; | |
590 | case OPMODE_STANDBY: | |
591 | switch (buck) { | |
592 | case 1: | |
593 | case 2: | |
594 | case 3: | |
595 | case 4: | |
596 | mode = MAX77686_BUCK_MODE_STANDBY << mode_shift; | |
597 | break; | |
598 | default: | |
599 | mode = 0xff; | |
600 | } | |
601 | break; | |
602 | case OPMODE_LPM: | |
603 | switch (buck) { | |
604 | case 2: | |
605 | case 3: | |
606 | case 4: | |
607 | mode = MAX77686_BUCK_MODE_LPM << mode_shift; | |
608 | break; | |
609 | default: | |
610 | mode = 0xff; | |
611 | } | |
612 | break; | |
613 | case OPMODE_ON: | |
614 | mode = MAX77686_BUCK_MODE_ON << mode_shift; | |
615 | break; | |
616 | default: | |
617 | mode = 0xff; | |
618 | } | |
619 | ||
620 | if (mode == 0xff) { | |
621 | error("Wrong mode: %d for buck: %d\n", *opmode, buck); | |
622 | return -EINVAL; | |
623 | } | |
624 | ||
625 | val &= ~mask; | |
626 | val |= mode; | |
627 | ret = pmic_write(dev->parent, adr, &val, 1); | |
628 | ||
629 | return ret; | |
630 | } | |
631 | ||
632 | static int max77686_buck_enable(struct udevice *dev, int op, bool *enable) | |
633 | { | |
634 | int ret, on_off; | |
635 | ||
636 | if (op == PMIC_OP_GET) { | |
637 | ret = max77686_buck_mode(dev, op, &on_off); | |
638 | if (ret) | |
639 | return ret; | |
640 | ||
641 | switch (on_off) { | |
642 | case OPMODE_OFF: | |
643 | *enable = false; | |
644 | break; | |
645 | case OPMODE_ON: | |
646 | *enable = true; | |
647 | break; | |
648 | default: | |
649 | return -EINVAL; | |
650 | } | |
651 | } else if (op == PMIC_OP_SET) { | |
652 | switch (*enable) { | |
653 | case 0: | |
654 | on_off = OPMODE_OFF; | |
655 | break; | |
656 | case 1: | |
657 | on_off = OPMODE_ON; | |
658 | break; | |
659 | default: | |
660 | return -EINVAL; | |
661 | } | |
662 | ||
663 | ret = max77686_buck_mode(dev, op, &on_off); | |
664 | if (ret) | |
665 | return ret; | |
666 | } | |
667 | ||
668 | return 0; | |
669 | } | |
670 | ||
671 | static int max77686_ldo_probe(struct udevice *dev) | |
672 | { | |
673 | struct dm_regulator_uclass_platdata *uc_pdata; | |
674 | ||
675 | uc_pdata = dev_get_uclass_platdata(dev); | |
676 | ||
677 | uc_pdata->type = REGULATOR_TYPE_LDO; | |
678 | uc_pdata->mode_count = max77686_ldo_modes(dev->driver_data, | |
679 | &uc_pdata->mode, dev); | |
680 | ||
681 | return 0; | |
682 | } | |
683 | ||
684 | static int ldo_get_value(struct udevice *dev) | |
685 | { | |
686 | int uV; | |
687 | int ret; | |
688 | ||
689 | ret = max77686_ldo_val(dev, PMIC_OP_GET, &uV); | |
690 | if (ret) | |
691 | return ret; | |
692 | ||
693 | return uV; | |
694 | } | |
695 | ||
696 | static int ldo_set_value(struct udevice *dev, int uV) | |
697 | { | |
698 | return max77686_ldo_val(dev, PMIC_OP_SET, &uV); | |
699 | } | |
700 | ||
701 | static bool ldo_get_enable(struct udevice *dev) | |
702 | { | |
703 | bool enable = false; | |
704 | int ret; | |
705 | ||
706 | ret = max77686_ldo_enable(dev, PMIC_OP_GET, &enable); | |
707 | if (ret) | |
708 | return ret; | |
709 | ||
710 | return enable; | |
711 | } | |
712 | ||
713 | static int ldo_set_enable(struct udevice *dev, bool enable) | |
714 | { | |
715 | return max77686_ldo_enable(dev, PMIC_OP_SET, &enable); | |
716 | } | |
717 | ||
718 | static int ldo_get_mode(struct udevice *dev) | |
719 | { | |
720 | int mode; | |
721 | int ret; | |
722 | ||
723 | ret = max77686_ldo_mode(dev, PMIC_OP_GET, &mode); | |
724 | if (ret) | |
725 | return ret; | |
726 | ||
727 | return mode; | |
728 | } | |
729 | ||
730 | static int ldo_set_mode(struct udevice *dev, int mode) | |
731 | { | |
732 | return max77686_ldo_mode(dev, PMIC_OP_SET, &mode); | |
733 | } | |
734 | ||
735 | static int max77686_buck_probe(struct udevice *dev) | |
736 | { | |
737 | struct dm_regulator_uclass_platdata *uc_pdata; | |
738 | ||
739 | uc_pdata = dev_get_uclass_platdata(dev); | |
740 | ||
741 | uc_pdata->type = REGULATOR_TYPE_BUCK; | |
742 | uc_pdata->mode_count = max77686_buck_modes(dev->driver_data, | |
743 | &uc_pdata->mode); | |
744 | ||
745 | return 0; | |
746 | } | |
747 | ||
748 | static int buck_get_value(struct udevice *dev) | |
749 | { | |
750 | int uV; | |
751 | int ret; | |
752 | ||
753 | ret = max77686_buck_val(dev, PMIC_OP_GET, &uV); | |
754 | if (ret) | |
755 | return ret; | |
756 | ||
757 | return uV; | |
758 | } | |
759 | ||
760 | static int buck_set_value(struct udevice *dev, int uV) | |
761 | { | |
762 | return max77686_buck_val(dev, PMIC_OP_SET, &uV); | |
763 | } | |
764 | ||
765 | static bool buck_get_enable(struct udevice *dev) | |
766 | { | |
767 | bool enable = false; | |
768 | int ret; | |
769 | ||
770 | ret = max77686_buck_enable(dev, PMIC_OP_GET, &enable); | |
771 | if (ret) | |
772 | return ret; | |
773 | ||
774 | return enable; | |
775 | } | |
776 | ||
777 | static int buck_set_enable(struct udevice *dev, bool enable) | |
778 | { | |
779 | return max77686_buck_enable(dev, PMIC_OP_SET, &enable); | |
780 | } | |
781 | ||
782 | static int buck_get_mode(struct udevice *dev) | |
783 | { | |
784 | int mode; | |
785 | int ret; | |
786 | ||
787 | ret = max77686_buck_mode(dev, PMIC_OP_GET, &mode); | |
788 | if (ret) | |
789 | return ret; | |
790 | ||
791 | return mode; | |
792 | } | |
793 | ||
794 | static int buck_set_mode(struct udevice *dev, int mode) | |
795 | { | |
796 | return max77686_buck_mode(dev, PMIC_OP_SET, &mode); | |
797 | } | |
798 | ||
799 | static const struct dm_regulator_ops max77686_ldo_ops = { | |
800 | .get_value = ldo_get_value, | |
801 | .set_value = ldo_set_value, | |
802 | .get_enable = ldo_get_enable, | |
803 | .set_enable = ldo_set_enable, | |
804 | .get_mode = ldo_get_mode, | |
805 | .set_mode = ldo_set_mode, | |
806 | }; | |
807 | ||
808 | U_BOOT_DRIVER(max77686_ldo) = { | |
809 | .name = MAX77686_LDO_DRIVER, | |
810 | .id = UCLASS_REGULATOR, | |
811 | .ops = &max77686_ldo_ops, | |
812 | .probe = max77686_ldo_probe, | |
813 | }; | |
814 | ||
815 | static const struct dm_regulator_ops max77686_buck_ops = { | |
816 | .get_value = buck_get_value, | |
817 | .set_value = buck_set_value, | |
818 | .get_enable = buck_get_enable, | |
819 | .set_enable = buck_set_enable, | |
820 | .get_mode = buck_get_mode, | |
821 | .set_mode = buck_set_mode, | |
822 | }; | |
823 | ||
824 | U_BOOT_DRIVER(max77686_buck) = { | |
825 | .name = MAX77686_BUCK_DRIVER, | |
826 | .id = UCLASS_REGULATOR, | |
827 | .ops = &max77686_buck_ops, | |
828 | .probe = max77686_buck_probe, | |
829 | }; |