blob: 5e5815f3978986619cb7cc30ec6f31ae9447f564 [file] [log] [blame]
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +02001/*
2 * Copyright (C) 2012-2015 Samsung Electronics
3 *
4 * Rajeshwari Shinde <rajeshwari.s@samsung.com>
5 * Przemyslaw Marczak <p.marczak@samsung.com>
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
19DECLARE_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 */
28static 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 */
36static 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 */
44static 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 */
51static 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 */
59static 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
Simon Glass2ede0052015-07-02 18:16:04 -060064static const char max77686_buck_ctrl[] = {
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +020065 0xff, 0x10, 0x12, 0x1c, 0x26, 0x30, 0x32, 0x34, 0x36, 0x38
66};
67
Simon Glass2ede0052015-07-02 18:16:04 -060068static const char max77686_buck_out[] = {
69 0xff, 0x11, 0x14, 0x1e, 0x28, 0x31, 0x33, 0x35, 0x37, 0x39
70};
71
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +020072static int max77686_buck_volt2hex(int buck, int uV)
73{
Tom Rini4776c642017-05-10 15:20:17 -040074 int hex = 0;
75 int hex_max = 0;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +020076
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;
Simon Glassfdcc59b2015-08-03 08:19:25 -060084 break;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +020085 default:
Simon Glassfdcc59b2015-08-03 08:19:25 -060086 /*
87 * hex = (uV - 750000) / 50000. We assume that dynamic voltage
88 * scaling via GPIOs is not enabled and don't support that.
89 * If this is enabled then the driver will need to take that
Simon Glass7fc93c42015-08-09 09:10:57 -060090 * into account and check different registers depending on
91 * the current setting. See the datasheet for details.
Simon Glassfdcc59b2015-08-03 08:19:25 -060092 */
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +020093 hex = (uV - MAX77686_BUCK_UV_HMIN) / MAX77686_BUCK_UV_HSTEP;
94 hex_max = MAX77686_BUCK_VOLT_MAX_HEX;
95 break;
96 }
97
98 if (hex >= 0 && hex <= hex_max)
99 return hex;
100
101 error("Value: %d uV is wrong for BUCK%d", uV, buck);
102 return -EINVAL;
103}
104
105static int max77686_buck_hex2volt(int buck, int hex)
106{
107 unsigned uV = 0;
Tom Rini4776c642017-05-10 15:20:17 -0400108 int hex_max = 0;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200109
110 if (hex < 0)
111 goto bad_hex;
112
113 switch (buck) {
114 case 2:
115 case 3:
116 case 4:
117 hex_max = MAX77686_BUCK234_VOLT_MAX_HEX;
118 if (hex > hex_max)
119 goto bad_hex;
120
121 /* uV = hex * 12500 + 600000; */
122 uV = hex * MAX77686_BUCK_UV_LSTEP + MAX77686_BUCK_UV_LMIN;
123 break;
124 default:
125 hex_max = MAX77686_BUCK_VOLT_MAX_HEX;
126 if (hex > hex_max)
127 goto bad_hex;
128
129 /* uV = hex * 50000 + 750000; */
130 uV = hex * MAX77686_BUCK_UV_HSTEP + MAX77686_BUCK_UV_HMIN;
131 break;
132 }
133
134 return uV;
135
136bad_hex:
137 error("Value: %#x is wrong for BUCK%d", hex, buck);
138 return -EINVAL;
139}
140
141static int max77686_ldo_volt2hex(int ldo, int uV)
142{
Tom Rini4776c642017-05-10 15:20:17 -0400143 int hex = 0;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200144
145 switch (ldo) {
146 case 1:
147 case 2:
148 case 6:
149 case 7:
150 case 8:
151 case 15:
152 hex = (uV - MAX77686_LDO_UV_MIN) / MAX77686_LDO_UV_LSTEP;
153 /* hex = (uV - 800000) / 25000; */
154 break;
155 default:
156 hex = (uV - MAX77686_LDO_UV_MIN) / MAX77686_LDO_UV_HSTEP;
157 /* hex = (uV - 800000) / 50000; */
158 }
159
160 if (hex >= 0 && hex <= MAX77686_LDO_VOLT_MAX_HEX)
161 return hex;
162
163 error("Value: %d uV is wrong for LDO%d", uV, ldo);
164 return -EINVAL;
165}
166
167static int max77686_ldo_hex2volt(int ldo, int hex)
168{
169 unsigned int uV = 0;
170
171 if (hex > MAX77686_LDO_VOLT_MAX_HEX)
172 goto bad_hex;
173
174 switch (ldo) {
175 case 1:
176 case 2:
177 case 6:
178 case 7:
179 case 8:
180 case 15:
181 /* uV = hex * 25000 + 800000; */
182 uV = hex * MAX77686_LDO_UV_LSTEP + MAX77686_LDO_UV_MIN;
183 break;
184 default:
185 /* uV = hex * 50000 + 800000; */
186 uV = hex * MAX77686_LDO_UV_HSTEP + MAX77686_LDO_UV_MIN;
187 }
188
189 return uV;
190
191bad_hex:
192 error("Value: %#x is wrong for ldo%d", hex, ldo);
193 return -EINVAL;
194}
195
196static int max77686_ldo_hex2mode(int ldo, int hex)
197{
198 if (hex > MAX77686_LDO_MODE_MASK)
199 return -EINVAL;
200
201 switch (hex) {
202 case MAX77686_LDO_MODE_OFF:
203 return OPMODE_OFF;
204 case MAX77686_LDO_MODE_LPM: /* == MAX77686_LDO_MODE_STANDBY: */
205 /* The same mode values but different meaning for each ldo */
206 switch (ldo) {
207 case 2:
208 case 6:
209 case 7:
210 case 8:
211 case 10:
212 case 11:
213 case 12:
214 case 14:
215 case 15:
216 case 16:
217 return OPMODE_STANDBY;
218 default:
219 return OPMODE_LPM;
220 }
221 case MAX77686_LDO_MODE_STANDBY_LPM:
222 return OPMODE_STANDBY_LPM;
223 case MAX77686_LDO_MODE_ON:
224 return OPMODE_ON;
225 default:
226 return -EINVAL;
227 }
228}
229
230static int max77686_buck_hex2mode(int buck, int hex)
231{
232 if (hex > MAX77686_BUCK_MODE_MASK)
233 return -EINVAL;
234
235 switch (hex) {
236 case MAX77686_BUCK_MODE_OFF:
237 return OPMODE_OFF;
238 case MAX77686_BUCK_MODE_ON:
239 return OPMODE_ON;
240 case MAX77686_BUCK_MODE_STANDBY:
241 switch (buck) {
242 case 1:
243 case 2:
244 case 3:
245 case 4:
246 return OPMODE_STANDBY;
247 default:
248 return -EINVAL;
249 }
250 case MAX77686_BUCK_MODE_LPM:
251 switch (buck) {
252 case 2:
253 case 3:
254 case 4:
255 return OPMODE_LPM;
256 default:
257 return -EINVAL;
258 }
259 default:
260 return -EINVAL;
261 }
262}
263
264static int max77686_buck_modes(int buck, struct dm_regulator_mode **modesp)
265{
266 int ret = -EINVAL;
267
268 if (buck < 1 || buck > MAX77686_BUCK_NUM)
269 return ret;
270
271 switch (buck) {
272 case 1:
273 *modesp = max77686_buck_mode_standby;
274 ret = ARRAY_SIZE(max77686_buck_mode_standby);
275 break;
276 case 2:
277 case 3:
278 case 4:
279 *modesp = max77686_buck_mode_lpm;
280 ret = ARRAY_SIZE(max77686_buck_mode_lpm);
281 break;
282 default:
283 *modesp = max77686_buck_mode_onoff;
284 ret = ARRAY_SIZE(max77686_buck_mode_onoff);
285 }
286
287 return ret;
288}
289
290static int max77686_ldo_modes(int ldo, struct dm_regulator_mode **modesp,
291 struct udevice *dev)
292{
293 int ret = -EINVAL;
294
295 if (ldo < 1 || ldo > MAX77686_LDO_NUM)
296 return ret;
297
298 switch (ldo) {
299 case 2:
300 case 6:
301 case 7:
302 case 8:
303 case 10:
304 case 11:
305 case 12:
306 case 14:
307 case 15:
308 case 16:
309 *modesp = max77686_ldo_mode_standby2;
310 ret = ARRAY_SIZE(max77686_ldo_mode_standby2);
311 break;
312 default:
313 *modesp = max77686_ldo_mode_standby1;
314 ret = ARRAY_SIZE(max77686_ldo_mode_standby1);
315 }
316
317 return ret;
318}
319
320static int max77686_ldo_val(struct udevice *dev, int op, int *uV)
321{
Tom Rini4776c642017-05-10 15:20:17 -0400322 unsigned int adr;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200323 unsigned char val;
Tom Rini4776c642017-05-10 15:20:17 -0400324 int hex, ldo, ret;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200325
326 if (op == PMIC_OP_GET)
327 *uV = 0;
328
329 ldo = dev->driver_data;
330 if (ldo < 1 || ldo > MAX77686_LDO_NUM) {
331 error("Wrong ldo number: %d", ldo);
332 return -EINVAL;
333 }
334
335 adr = MAX77686_REG_PMIC_LDO1CTRL1 + ldo - 1;
336
337 ret = pmic_read(dev->parent, adr, &val, 1);
338 if (ret)
339 return ret;
340
341 if (op == PMIC_OP_GET) {
342 val &= MAX77686_LDO_VOLT_MASK;
343 ret = max77686_ldo_hex2volt(ldo, val);
344 if (ret < 0)
345 return ret;
346 *uV = ret;
347 return 0;
348 }
349
350 hex = max77686_ldo_volt2hex(ldo, *uV);
351 if (hex < 0)
352 return hex;
353
354 val &= ~MAX77686_LDO_VOLT_MASK;
355 val |= hex;
356 ret = pmic_write(dev->parent, adr, &val, 1);
357
358 return ret;
359}
360
361static int max77686_buck_val(struct udevice *dev, int op, int *uV)
362{
Tom Rini4776c642017-05-10 15:20:17 -0400363 unsigned int mask, adr;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200364 unsigned char val;
Tom Rini4776c642017-05-10 15:20:17 -0400365 int hex, buck, ret;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200366
367 buck = dev->driver_data;
368 if (buck < 1 || buck > MAX77686_BUCK_NUM) {
369 error("Wrong buck number: %d", buck);
370 return -EINVAL;
371 }
372
373 if (op == PMIC_OP_GET)
374 *uV = 0;
375
376 /* &buck_out = ctrl + 1 */
Simon Glass2ede0052015-07-02 18:16:04 -0600377 adr = max77686_buck_out[buck];
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200378
379 /* mask */
380 switch (buck) {
381 case 2:
382 case 3:
383 case 4:
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200384 mask = MAX77686_BUCK234_VOLT_MASK;
Simon Glassfdcc59b2015-08-03 08:19:25 -0600385 break;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200386 default:
387 mask = MAX77686_BUCK_VOLT_MASK;
Simon Glassfdcc59b2015-08-03 08:19:25 -0600388 break;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200389 }
390
391 ret = pmic_read(dev->parent, adr, &val, 1);
392 if (ret)
393 return ret;
394
395 if (op == PMIC_OP_GET) {
396 val &= mask;
397 ret = max77686_buck_hex2volt(buck, val);
398 if (ret < 0)
399 return ret;
400 *uV = ret;
401 return 0;
402 }
403
404 hex = max77686_buck_volt2hex(buck, *uV);
405 if (hex < 0)
406 return hex;
407
408 val &= ~mask;
409 val |= hex;
410 ret = pmic_write(dev->parent, adr, &val, 1);
411
412 return ret;
413}
414
415static int max77686_ldo_mode(struct udevice *dev, int op, int *opmode)
416{
Peng Fane4cbfa62015-07-28 22:47:08 +0800417 unsigned int adr, mode;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200418 unsigned char val;
Peng Fane4cbfa62015-07-28 22:47:08 +0800419 int ldo, ret;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200420
421 if (op == PMIC_OP_GET)
422 *opmode = -EINVAL;
423
424 ldo = dev->driver_data;
425 if (ldo < 1 || ldo > MAX77686_LDO_NUM) {
426 error("Wrong ldo number: %d", ldo);
427 return -EINVAL;
428 }
429
430 adr = MAX77686_REG_PMIC_LDO1CTRL1 + ldo - 1;
431
432 ret = pmic_read(dev->parent, adr, &val, 1);
433 if (ret)
434 return ret;
435
436 if (op == PMIC_OP_GET) {
437 val &= MAX77686_LDO_MODE_MASK;
438 ret = max77686_ldo_hex2mode(ldo, val);
439 if (ret < 0)
440 return ret;
441 *opmode = ret;
442 return 0;
443 }
444
445 /* mode */
446 switch (*opmode) {
447 case OPMODE_OFF:
448 mode = MAX77686_LDO_MODE_OFF;
449 break;
450 case OPMODE_LPM:
451 switch (ldo) {
452 case 2:
453 case 6:
454 case 7:
455 case 8:
456 case 10:
457 case 11:
458 case 12:
459 case 14:
460 case 15:
461 case 16:
462 return -EINVAL;
463 default:
464 mode = MAX77686_LDO_MODE_LPM;
465 }
466 break;
467 case OPMODE_STANDBY:
468 switch (ldo) {
469 case 2:
470 case 6:
471 case 7:
472 case 8:
473 case 10:
474 case 11:
475 case 12:
476 case 14:
477 case 15:
478 case 16:
479 mode = MAX77686_LDO_MODE_STANDBY;
480 break;
481 default:
482 return -EINVAL;
483 }
484 break;
485 case OPMODE_STANDBY_LPM:
486 mode = MAX77686_LDO_MODE_STANDBY_LPM;
487 break;
488 case OPMODE_ON:
489 mode = MAX77686_LDO_MODE_ON;
490 break;
491 default:
492 mode = 0xff;
493 }
494
495 if (mode == 0xff) {
496 error("Wrong mode: %d for ldo%d", *opmode, ldo);
497 return -EINVAL;
498 }
499
500 val &= ~MAX77686_LDO_MODE_MASK;
501 val |= mode;
502 ret = pmic_write(dev->parent, adr, &val, 1);
503
504 return ret;
505}
506
507static int max77686_ldo_enable(struct udevice *dev, int op, bool *enable)
508{
509 int ret, on_off;
510
511 if (op == PMIC_OP_GET) {
512 ret = max77686_ldo_mode(dev, op, &on_off);
513 if (ret)
514 return ret;
515
516 switch (on_off) {
517 case OPMODE_OFF:
Tom Rinie6cf0aa2016-01-17 02:44:37 +0000518 *enable = false;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200519 break;
520 case OPMODE_ON:
Tom Rinie6cf0aa2016-01-17 02:44:37 +0000521 *enable = true;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200522 break;
523 default:
524 return -EINVAL;
525 }
526 } else if (op == PMIC_OP_SET) {
Tom Rinie6cf0aa2016-01-17 02:44:37 +0000527 if (*enable)
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200528 on_off = OPMODE_ON;
Tom Rinie6cf0aa2016-01-17 02:44:37 +0000529 else
530 on_off = OPMODE_OFF;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200531
532 ret = max77686_ldo_mode(dev, op, &on_off);
533 if (ret)
534 return ret;
535 }
536
537 return 0;
538}
539
540static int max77686_buck_mode(struct udevice *dev, int op, int *opmode)
541{
Peng Fane4cbfa62015-07-28 22:47:08 +0800542 unsigned int mask, adr, mode, mode_shift;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200543 unsigned char val;
Peng Fane4cbfa62015-07-28 22:47:08 +0800544 int buck, ret;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200545
546 buck = dev->driver_data;
547 if (buck < 1 || buck > MAX77686_BUCK_NUM) {
548 error("Wrong buck number: %d", buck);
549 return -EINVAL;
550 }
551
Simon Glass2ede0052015-07-02 18:16:04 -0600552 adr = max77686_buck_ctrl[buck];
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200553
554 /* mask */
555 switch (buck) {
556 case 2:
557 case 3:
558 case 4:
559 mode_shift = MAX77686_BUCK_MODE_SHIFT_2;
560 break;
561 default:
562 mode_shift = MAX77686_BUCK_MODE_SHIFT_1;
563 }
564
565 mask = MAX77686_BUCK_MODE_MASK << mode_shift;
566
567 ret = pmic_read(dev->parent, adr, &val, 1);
568 if (ret)
569 return ret;
570
571 if (op == PMIC_OP_GET) {
572 val &= mask;
573 val >>= mode_shift;
574 ret = max77686_buck_hex2mode(buck, val);
575 if (ret < 0)
576 return ret;
577 *opmode = ret;
578 return 0;
579 }
580
581 /* mode */
582 switch (*opmode) {
583 case OPMODE_OFF:
584 mode = MAX77686_BUCK_MODE_OFF;
585 break;
586 case OPMODE_STANDBY:
587 switch (buck) {
588 case 1:
589 case 2:
590 case 3:
591 case 4:
592 mode = MAX77686_BUCK_MODE_STANDBY << mode_shift;
593 break;
594 default:
595 mode = 0xff;
596 }
597 break;
598 case OPMODE_LPM:
599 switch (buck) {
600 case 2:
601 case 3:
602 case 4:
603 mode = MAX77686_BUCK_MODE_LPM << mode_shift;
604 break;
605 default:
606 mode = 0xff;
607 }
608 break;
609 case OPMODE_ON:
610 mode = MAX77686_BUCK_MODE_ON << mode_shift;
611 break;
612 default:
613 mode = 0xff;
614 }
615
616 if (mode == 0xff) {
617 error("Wrong mode: %d for buck: %d\n", *opmode, buck);
618 return -EINVAL;
619 }
620
621 val &= ~mask;
622 val |= mode;
623 ret = pmic_write(dev->parent, adr, &val, 1);
624
625 return ret;
626}
627
628static int max77686_buck_enable(struct udevice *dev, int op, bool *enable)
629{
630 int ret, on_off;
631
632 if (op == PMIC_OP_GET) {
633 ret = max77686_buck_mode(dev, op, &on_off);
634 if (ret)
635 return ret;
636
637 switch (on_off) {
638 case OPMODE_OFF:
639 *enable = false;
640 break;
641 case OPMODE_ON:
642 *enable = true;
643 break;
644 default:
645 return -EINVAL;
646 }
647 } else if (op == PMIC_OP_SET) {
Tom Rinie6cf0aa2016-01-17 02:44:37 +0000648 if (*enable)
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200649 on_off = OPMODE_ON;
Tom Rinie6cf0aa2016-01-17 02:44:37 +0000650 else
651 on_off = OPMODE_OFF;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200652
653 ret = max77686_buck_mode(dev, op, &on_off);
654 if (ret)
655 return ret;
656 }
657
658 return 0;
659}
660
661static int max77686_ldo_probe(struct udevice *dev)
662{
663 struct dm_regulator_uclass_platdata *uc_pdata;
664
665 uc_pdata = dev_get_uclass_platdata(dev);
666
667 uc_pdata->type = REGULATOR_TYPE_LDO;
668 uc_pdata->mode_count = max77686_ldo_modes(dev->driver_data,
669 &uc_pdata->mode, dev);
670
671 return 0;
672}
673
674static int ldo_get_value(struct udevice *dev)
675{
676 int uV;
677 int ret;
678
679 ret = max77686_ldo_val(dev, PMIC_OP_GET, &uV);
680 if (ret)
681 return ret;
682
683 return uV;
684}
685
686static int ldo_set_value(struct udevice *dev, int uV)
687{
688 return max77686_ldo_val(dev, PMIC_OP_SET, &uV);
689}
690
691static bool ldo_get_enable(struct udevice *dev)
692{
693 bool enable = false;
694 int ret;
695
696 ret = max77686_ldo_enable(dev, PMIC_OP_GET, &enable);
697 if (ret)
698 return ret;
699
700 return enable;
701}
702
703static int ldo_set_enable(struct udevice *dev, bool enable)
704{
705 return max77686_ldo_enable(dev, PMIC_OP_SET, &enable);
706}
707
708static int ldo_get_mode(struct udevice *dev)
709{
710 int mode;
711 int ret;
712
713 ret = max77686_ldo_mode(dev, PMIC_OP_GET, &mode);
714 if (ret)
715 return ret;
716
717 return mode;
718}
719
720static int ldo_set_mode(struct udevice *dev, int mode)
721{
722 return max77686_ldo_mode(dev, PMIC_OP_SET, &mode);
723}
724
725static int max77686_buck_probe(struct udevice *dev)
726{
727 struct dm_regulator_uclass_platdata *uc_pdata;
728
729 uc_pdata = dev_get_uclass_platdata(dev);
730
731 uc_pdata->type = REGULATOR_TYPE_BUCK;
732 uc_pdata->mode_count = max77686_buck_modes(dev->driver_data,
733 &uc_pdata->mode);
734
735 return 0;
736}
737
738static int buck_get_value(struct udevice *dev)
739{
740 int uV;
741 int ret;
742
743 ret = max77686_buck_val(dev, PMIC_OP_GET, &uV);
744 if (ret)
745 return ret;
746
747 return uV;
748}
749
750static int buck_set_value(struct udevice *dev, int uV)
751{
752 return max77686_buck_val(dev, PMIC_OP_SET, &uV);
753}
754
755static bool buck_get_enable(struct udevice *dev)
756{
757 bool enable = false;
758 int ret;
759
760 ret = max77686_buck_enable(dev, PMIC_OP_GET, &enable);
761 if (ret)
762 return ret;
763
764 return enable;
765}
766
767static int buck_set_enable(struct udevice *dev, bool enable)
768{
769 return max77686_buck_enable(dev, PMIC_OP_SET, &enable);
770}
771
772static int buck_get_mode(struct udevice *dev)
773{
774 int mode;
775 int ret;
776
777 ret = max77686_buck_mode(dev, PMIC_OP_GET, &mode);
778 if (ret)
779 return ret;
780
781 return mode;
782}
783
784static int buck_set_mode(struct udevice *dev, int mode)
785{
786 return max77686_buck_mode(dev, PMIC_OP_SET, &mode);
787}
788
789static const struct dm_regulator_ops max77686_ldo_ops = {
790 .get_value = ldo_get_value,
791 .set_value = ldo_set_value,
792 .get_enable = ldo_get_enable,
793 .set_enable = ldo_set_enable,
794 .get_mode = ldo_get_mode,
795 .set_mode = ldo_set_mode,
796};
797
798U_BOOT_DRIVER(max77686_ldo) = {
799 .name = MAX77686_LDO_DRIVER,
800 .id = UCLASS_REGULATOR,
801 .ops = &max77686_ldo_ops,
802 .probe = max77686_ldo_probe,
803};
804
805static const struct dm_regulator_ops max77686_buck_ops = {
806 .get_value = buck_get_value,
807 .set_value = buck_set_value,
808 .get_enable = buck_get_enable,
809 .set_enable = buck_set_enable,
810 .get_mode = buck_get_mode,
811 .set_mode = buck_set_mode,
812};
813
814U_BOOT_DRIVER(max77686_buck) = {
815 .name = MAX77686_BUCK_DRIVER,
816 .id = UCLASS_REGULATOR,
817 .ops = &max77686_buck_ops,
818 .probe = max77686_buck_probe,
819};