blob: 4e0ba12a0ef880d0477fc2d587a518f43c157537 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +02002/*
3 * Copyright (C) 2012-2015 Samsung Electronics
4 *
5 * Rajeshwari Shinde <rajeshwari.s@samsung.com>
6 * Przemyslaw Marczak <p.marczak@samsung.com>
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +02007 */
8
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +02009#include <fdtdec.h>
10#include <errno.h>
11#include <dm.h>
Simon Glassbdd5f812023-09-14 18:21:46 -060012#include <linux/printk.h>
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +020013#include <power/pmic.h>
14#include <power/regulator.h>
15#include <power/max77686_pmic.h>
16
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +020017#define MODE(_id, _val, _name) { \
18 .id = _id, \
19 .register_value = _val, \
20 .name = _name, \
21}
22
23/* LDO: 1,3,4,5,9,17,18,19,20,21,22,23,24,26,26,27 */
24static struct dm_regulator_mode max77686_ldo_mode_standby1[] = {
25 MODE(OPMODE_OFF, MAX77686_LDO_MODE_OFF, "OFF"),
26 MODE(OPMODE_LPM, MAX77686_LDO_MODE_LPM, "LPM"),
27 MODE(OPMODE_STANDBY_LPM, MAX77686_LDO_MODE_STANDBY_LPM, "ON/LPM"),
28 MODE(OPMODE_ON, MAX77686_LDO_MODE_ON, "ON"),
29};
30
31/* LDO: 2,6,7,8,10,11,12,14,15,16 */
32static struct dm_regulator_mode max77686_ldo_mode_standby2[] = {
33 MODE(OPMODE_OFF, MAX77686_LDO_MODE_OFF, "OFF"),
34 MODE(OPMODE_STANDBY, MAX77686_LDO_MODE_STANDBY, "ON/OFF"),
35 MODE(OPMODE_STANDBY_LPM, MAX77686_LDO_MODE_STANDBY_LPM, "ON/LPM"),
36 MODE(OPMODE_ON, MAX77686_LDO_MODE_ON, "ON"),
37};
38
39/* Buck: 1 */
40static struct dm_regulator_mode max77686_buck_mode_standby[] = {
41 MODE(OPMODE_OFF, MAX77686_BUCK_MODE_OFF, "OFF"),
42 MODE(OPMODE_STANDBY, MAX77686_BUCK_MODE_STANDBY, "ON/OFF"),
43 MODE(OPMODE_ON, MAX77686_BUCK_MODE_ON, "ON"),
44};
45
46/* Buck: 2,3,4 */
47static struct dm_regulator_mode max77686_buck_mode_lpm[] = {
48 MODE(OPMODE_OFF, MAX77686_BUCK_MODE_OFF, "OFF"),
49 MODE(OPMODE_STANDBY, MAX77686_BUCK_MODE_STANDBY, "ON/OFF"),
50 MODE(OPMODE_LPM, MAX77686_BUCK_MODE_LPM, "LPM"),
51 MODE(OPMODE_ON, MAX77686_BUCK_MODE_ON, "ON"),
52};
53
54/* Buck: 5,6,7,8,9 */
55static struct dm_regulator_mode max77686_buck_mode_onoff[] = {
56 MODE(OPMODE_OFF, MAX77686_BUCK_MODE_OFF, "OFF"),
57 MODE(OPMODE_ON, MAX77686_BUCK_MODE_ON, "ON"),
58};
59
Simon Glass2ede0052015-07-02 18:16:04 -060060static const char max77686_buck_ctrl[] = {
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +020061 0xff, 0x10, 0x12, 0x1c, 0x26, 0x30, 0x32, 0x34, 0x36, 0x38
62};
63
Simon Glass2ede0052015-07-02 18:16:04 -060064static const char max77686_buck_out[] = {
65 0xff, 0x11, 0x14, 0x1e, 0x28, 0x31, 0x33, 0x35, 0x37, 0x39
66};
67
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +020068static int max77686_buck_volt2hex(int buck, int uV)
69{
Tom Rini4776c642017-05-10 15:20:17 -040070 int hex = 0;
71 int hex_max = 0;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +020072
73 switch (buck) {
74 case 2:
75 case 3:
76 case 4:
77 /* hex = (uV - 600000) / 12500; */
78 hex = (uV - MAX77686_BUCK_UV_LMIN) / MAX77686_BUCK_UV_LSTEP;
79 hex_max = MAX77686_BUCK234_VOLT_MAX_HEX;
Simon Glassfdcc59b2015-08-03 08:19:25 -060080 break;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +020081 default:
Simon Glassfdcc59b2015-08-03 08:19:25 -060082 /*
83 * hex = (uV - 750000) / 50000. We assume that dynamic voltage
84 * scaling via GPIOs is not enabled and don't support that.
85 * If this is enabled then the driver will need to take that
Simon Glass7fc93c42015-08-09 09:10:57 -060086 * into account and check different registers depending on
87 * the current setting. See the datasheet for details.
Simon Glassfdcc59b2015-08-03 08:19:25 -060088 */
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +020089 hex = (uV - MAX77686_BUCK_UV_HMIN) / MAX77686_BUCK_UV_HSTEP;
90 hex_max = MAX77686_BUCK_VOLT_MAX_HEX;
91 break;
92 }
93
94 if (hex >= 0 && hex <= hex_max)
95 return hex;
96
Masahiro Yamada81e10422017-09-16 14:10:41 +090097 pr_err("Value: %d uV is wrong for BUCK%d", uV, buck);
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +020098 return -EINVAL;
99}
100
101static int max77686_buck_hex2volt(int buck, int hex)
102{
103 unsigned uV = 0;
Tom Rini4776c642017-05-10 15:20:17 -0400104 int hex_max = 0;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200105
106 if (hex < 0)
107 goto bad_hex;
108
109 switch (buck) {
110 case 2:
111 case 3:
112 case 4:
113 hex_max = MAX77686_BUCK234_VOLT_MAX_HEX;
114 if (hex > hex_max)
115 goto bad_hex;
116
117 /* uV = hex * 12500 + 600000; */
118 uV = hex * MAX77686_BUCK_UV_LSTEP + MAX77686_BUCK_UV_LMIN;
119 break;
120 default:
121 hex_max = MAX77686_BUCK_VOLT_MAX_HEX;
122 if (hex > hex_max)
123 goto bad_hex;
124
125 /* uV = hex * 50000 + 750000; */
126 uV = hex * MAX77686_BUCK_UV_HSTEP + MAX77686_BUCK_UV_HMIN;
127 break;
128 }
129
130 return uV;
131
132bad_hex:
Masahiro Yamada81e10422017-09-16 14:10:41 +0900133 pr_err("Value: %#x is wrong for BUCK%d", hex, buck);
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200134 return -EINVAL;
135}
136
137static int max77686_ldo_volt2hex(int ldo, int uV)
138{
Tom Rini4776c642017-05-10 15:20:17 -0400139 int hex = 0;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200140
141 switch (ldo) {
142 case 1:
143 case 2:
144 case 6:
145 case 7:
146 case 8:
147 case 15:
148 hex = (uV - MAX77686_LDO_UV_MIN) / MAX77686_LDO_UV_LSTEP;
149 /* hex = (uV - 800000) / 25000; */
150 break;
151 default:
152 hex = (uV - MAX77686_LDO_UV_MIN) / MAX77686_LDO_UV_HSTEP;
153 /* hex = (uV - 800000) / 50000; */
154 }
155
156 if (hex >= 0 && hex <= MAX77686_LDO_VOLT_MAX_HEX)
157 return hex;
158
Masahiro Yamada81e10422017-09-16 14:10:41 +0900159 pr_err("Value: %d uV is wrong for LDO%d", uV, ldo);
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200160 return -EINVAL;
161}
162
163static int max77686_ldo_hex2volt(int ldo, int hex)
164{
165 unsigned int uV = 0;
166
167 if (hex > MAX77686_LDO_VOLT_MAX_HEX)
168 goto bad_hex;
169
170 switch (ldo) {
171 case 1:
172 case 2:
173 case 6:
174 case 7:
175 case 8:
176 case 15:
177 /* uV = hex * 25000 + 800000; */
178 uV = hex * MAX77686_LDO_UV_LSTEP + MAX77686_LDO_UV_MIN;
179 break;
180 default:
181 /* uV = hex * 50000 + 800000; */
182 uV = hex * MAX77686_LDO_UV_HSTEP + MAX77686_LDO_UV_MIN;
183 }
184
185 return uV;
186
187bad_hex:
Masahiro Yamada81e10422017-09-16 14:10:41 +0900188 pr_err("Value: %#x is wrong for ldo%d", hex, ldo);
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200189 return -EINVAL;
190}
191
192static int max77686_ldo_hex2mode(int ldo, int hex)
193{
194 if (hex > MAX77686_LDO_MODE_MASK)
195 return -EINVAL;
196
197 switch (hex) {
198 case MAX77686_LDO_MODE_OFF:
199 return OPMODE_OFF;
200 case MAX77686_LDO_MODE_LPM: /* == MAX77686_LDO_MODE_STANDBY: */
201 /* The same mode values but different meaning for each ldo */
202 switch (ldo) {
203 case 2:
204 case 6:
205 case 7:
206 case 8:
207 case 10:
208 case 11:
209 case 12:
210 case 14:
211 case 15:
212 case 16:
213 return OPMODE_STANDBY;
214 default:
215 return OPMODE_LPM;
216 }
217 case MAX77686_LDO_MODE_STANDBY_LPM:
218 return OPMODE_STANDBY_LPM;
219 case MAX77686_LDO_MODE_ON:
220 return OPMODE_ON;
221 default:
222 return -EINVAL;
223 }
224}
225
226static int max77686_buck_hex2mode(int buck, int hex)
227{
228 if (hex > MAX77686_BUCK_MODE_MASK)
229 return -EINVAL;
230
231 switch (hex) {
232 case MAX77686_BUCK_MODE_OFF:
233 return OPMODE_OFF;
234 case MAX77686_BUCK_MODE_ON:
235 return OPMODE_ON;
236 case MAX77686_BUCK_MODE_STANDBY:
237 switch (buck) {
238 case 1:
239 case 2:
240 case 3:
241 case 4:
242 return OPMODE_STANDBY;
243 default:
244 return -EINVAL;
245 }
246 case MAX77686_BUCK_MODE_LPM:
247 switch (buck) {
248 case 2:
249 case 3:
250 case 4:
251 return OPMODE_LPM;
252 default:
253 return -EINVAL;
254 }
255 default:
256 return -EINVAL;
257 }
258}
259
260static int max77686_buck_modes(int buck, struct dm_regulator_mode **modesp)
261{
262 int ret = -EINVAL;
263
264 if (buck < 1 || buck > MAX77686_BUCK_NUM)
265 return ret;
266
267 switch (buck) {
268 case 1:
269 *modesp = max77686_buck_mode_standby;
270 ret = ARRAY_SIZE(max77686_buck_mode_standby);
271 break;
272 case 2:
273 case 3:
274 case 4:
275 *modesp = max77686_buck_mode_lpm;
276 ret = ARRAY_SIZE(max77686_buck_mode_lpm);
277 break;
278 default:
279 *modesp = max77686_buck_mode_onoff;
280 ret = ARRAY_SIZE(max77686_buck_mode_onoff);
281 }
282
283 return ret;
284}
285
286static int max77686_ldo_modes(int ldo, struct dm_regulator_mode **modesp,
287 struct udevice *dev)
288{
289 int ret = -EINVAL;
290
291 if (ldo < 1 || ldo > MAX77686_LDO_NUM)
292 return ret;
293
294 switch (ldo) {
295 case 2:
296 case 6:
297 case 7:
298 case 8:
299 case 10:
300 case 11:
301 case 12:
302 case 14:
303 case 15:
304 case 16:
305 *modesp = max77686_ldo_mode_standby2;
306 ret = ARRAY_SIZE(max77686_ldo_mode_standby2);
307 break;
308 default:
309 *modesp = max77686_ldo_mode_standby1;
310 ret = ARRAY_SIZE(max77686_ldo_mode_standby1);
311 }
312
313 return ret;
314}
315
316static int max77686_ldo_val(struct udevice *dev, int op, int *uV)
317{
Tom Rini4776c642017-05-10 15:20:17 -0400318 unsigned int adr;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200319 unsigned char val;
Tom Rini4776c642017-05-10 15:20:17 -0400320 int hex, ldo, ret;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200321
322 if (op == PMIC_OP_GET)
323 *uV = 0;
324
325 ldo = dev->driver_data;
326 if (ldo < 1 || ldo > MAX77686_LDO_NUM) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900327 pr_err("Wrong ldo number: %d", ldo);
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200328 return -EINVAL;
329 }
330
331 adr = MAX77686_REG_PMIC_LDO1CTRL1 + ldo - 1;
332
333 ret = pmic_read(dev->parent, adr, &val, 1);
334 if (ret)
335 return ret;
336
337 if (op == PMIC_OP_GET) {
338 val &= MAX77686_LDO_VOLT_MASK;
339 ret = max77686_ldo_hex2volt(ldo, val);
340 if (ret < 0)
341 return ret;
342 *uV = ret;
343 return 0;
344 }
345
346 hex = max77686_ldo_volt2hex(ldo, *uV);
347 if (hex < 0)
348 return hex;
349
350 val &= ~MAX77686_LDO_VOLT_MASK;
351 val |= hex;
352 ret = pmic_write(dev->parent, adr, &val, 1);
353
354 return ret;
355}
356
357static int max77686_buck_val(struct udevice *dev, int op, int *uV)
358{
Tom Rini4776c642017-05-10 15:20:17 -0400359 unsigned int mask, adr;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200360 unsigned char val;
Tom Rini4776c642017-05-10 15:20:17 -0400361 int hex, buck, ret;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200362
363 buck = dev->driver_data;
364 if (buck < 1 || buck > MAX77686_BUCK_NUM) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900365 pr_err("Wrong buck number: %d", buck);
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200366 return -EINVAL;
367 }
368
369 if (op == PMIC_OP_GET)
370 *uV = 0;
371
372 /* &buck_out = ctrl + 1 */
Simon Glass2ede0052015-07-02 18:16:04 -0600373 adr = max77686_buck_out[buck];
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200374
375 /* mask */
376 switch (buck) {
377 case 2:
378 case 3:
379 case 4:
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200380 mask = MAX77686_BUCK234_VOLT_MASK;
Simon Glassfdcc59b2015-08-03 08:19:25 -0600381 break;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200382 default:
383 mask = MAX77686_BUCK_VOLT_MASK;
Simon Glassfdcc59b2015-08-03 08:19:25 -0600384 break;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200385 }
386
387 ret = pmic_read(dev->parent, adr, &val, 1);
388 if (ret)
389 return ret;
390
391 if (op == PMIC_OP_GET) {
392 val &= mask;
393 ret = max77686_buck_hex2volt(buck, val);
394 if (ret < 0)
395 return ret;
396 *uV = ret;
397 return 0;
398 }
399
400 hex = max77686_buck_volt2hex(buck, *uV);
401 if (hex < 0)
402 return hex;
403
404 val &= ~mask;
405 val |= hex;
406 ret = pmic_write(dev->parent, adr, &val, 1);
407
408 return ret;
409}
410
411static int max77686_ldo_mode(struct udevice *dev, int op, int *opmode)
412{
Peng Fane4cbfa62015-07-28 22:47:08 +0800413 unsigned int adr, mode;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200414 unsigned char val;
Peng Fane4cbfa62015-07-28 22:47:08 +0800415 int ldo, ret;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200416
417 if (op == PMIC_OP_GET)
418 *opmode = -EINVAL;
419
420 ldo = dev->driver_data;
421 if (ldo < 1 || ldo > MAX77686_LDO_NUM) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900422 pr_err("Wrong ldo number: %d", ldo);
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200423 return -EINVAL;
424 }
425
426 adr = MAX77686_REG_PMIC_LDO1CTRL1 + ldo - 1;
427
428 ret = pmic_read(dev->parent, adr, &val, 1);
429 if (ret)
430 return ret;
431
432 if (op == PMIC_OP_GET) {
433 val &= MAX77686_LDO_MODE_MASK;
434 ret = max77686_ldo_hex2mode(ldo, val);
435 if (ret < 0)
436 return ret;
437 *opmode = ret;
438 return 0;
439 }
440
441 /* mode */
442 switch (*opmode) {
443 case OPMODE_OFF:
444 mode = MAX77686_LDO_MODE_OFF;
445 break;
446 case OPMODE_LPM:
447 switch (ldo) {
448 case 2:
449 case 6:
450 case 7:
451 case 8:
452 case 10:
453 case 11:
454 case 12:
455 case 14:
456 case 15:
457 case 16:
458 return -EINVAL;
459 default:
460 mode = MAX77686_LDO_MODE_LPM;
461 }
462 break;
463 case OPMODE_STANDBY:
464 switch (ldo) {
465 case 2:
466 case 6:
467 case 7:
468 case 8:
469 case 10:
470 case 11:
471 case 12:
472 case 14:
473 case 15:
474 case 16:
475 mode = MAX77686_LDO_MODE_STANDBY;
476 break;
477 default:
478 return -EINVAL;
479 }
480 break;
481 case OPMODE_STANDBY_LPM:
482 mode = MAX77686_LDO_MODE_STANDBY_LPM;
483 break;
484 case OPMODE_ON:
485 mode = MAX77686_LDO_MODE_ON;
486 break;
487 default:
488 mode = 0xff;
489 }
490
491 if (mode == 0xff) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900492 pr_err("Wrong mode: %d for ldo%d", *opmode, ldo);
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200493 return -EINVAL;
494 }
495
496 val &= ~MAX77686_LDO_MODE_MASK;
497 val |= mode;
498 ret = pmic_write(dev->parent, adr, &val, 1);
499
500 return ret;
501}
502
503static int max77686_ldo_enable(struct udevice *dev, int op, bool *enable)
504{
505 int ret, on_off;
506
507 if (op == PMIC_OP_GET) {
508 ret = max77686_ldo_mode(dev, op, &on_off);
509 if (ret)
510 return ret;
511
512 switch (on_off) {
513 case OPMODE_OFF:
Tom Rinie6cf0aa2016-01-17 02:44:37 +0000514 *enable = false;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200515 break;
516 case OPMODE_ON:
Tom Rinie6cf0aa2016-01-17 02:44:37 +0000517 *enable = true;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200518 break;
519 default:
520 return -EINVAL;
521 }
522 } else if (op == PMIC_OP_SET) {
Tom Rinie6cf0aa2016-01-17 02:44:37 +0000523 if (*enable)
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200524 on_off = OPMODE_ON;
Tom Rinie6cf0aa2016-01-17 02:44:37 +0000525 else
526 on_off = OPMODE_OFF;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200527
528 ret = max77686_ldo_mode(dev, op, &on_off);
529 if (ret)
530 return ret;
531 }
532
533 return 0;
534}
535
536static int max77686_buck_mode(struct udevice *dev, int op, int *opmode)
537{
Peng Fane4cbfa62015-07-28 22:47:08 +0800538 unsigned int mask, adr, mode, mode_shift;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200539 unsigned char val;
Peng Fane4cbfa62015-07-28 22:47:08 +0800540 int buck, ret;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200541
542 buck = dev->driver_data;
543 if (buck < 1 || buck > MAX77686_BUCK_NUM) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900544 pr_err("Wrong buck number: %d", buck);
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200545 return -EINVAL;
546 }
547
Simon Glass2ede0052015-07-02 18:16:04 -0600548 adr = max77686_buck_ctrl[buck];
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200549
550 /* mask */
551 switch (buck) {
552 case 2:
553 case 3:
554 case 4:
555 mode_shift = MAX77686_BUCK_MODE_SHIFT_2;
556 break;
557 default:
558 mode_shift = MAX77686_BUCK_MODE_SHIFT_1;
559 }
560
561 mask = MAX77686_BUCK_MODE_MASK << mode_shift;
562
563 ret = pmic_read(dev->parent, adr, &val, 1);
564 if (ret)
565 return ret;
566
567 if (op == PMIC_OP_GET) {
568 val &= mask;
569 val >>= mode_shift;
570 ret = max77686_buck_hex2mode(buck, val);
571 if (ret < 0)
572 return ret;
573 *opmode = ret;
574 return 0;
575 }
576
577 /* mode */
578 switch (*opmode) {
579 case OPMODE_OFF:
580 mode = MAX77686_BUCK_MODE_OFF;
581 break;
582 case OPMODE_STANDBY:
583 switch (buck) {
584 case 1:
585 case 2:
586 case 3:
587 case 4:
588 mode = MAX77686_BUCK_MODE_STANDBY << mode_shift;
589 break;
590 default:
591 mode = 0xff;
592 }
593 break;
594 case OPMODE_LPM:
595 switch (buck) {
596 case 2:
597 case 3:
598 case 4:
599 mode = MAX77686_BUCK_MODE_LPM << mode_shift;
600 break;
601 default:
602 mode = 0xff;
603 }
604 break;
605 case OPMODE_ON:
606 mode = MAX77686_BUCK_MODE_ON << mode_shift;
607 break;
608 default:
609 mode = 0xff;
610 }
611
612 if (mode == 0xff) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900613 pr_err("Wrong mode: %d for buck: %d\n", *opmode, buck);
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200614 return -EINVAL;
615 }
616
617 val &= ~mask;
618 val |= mode;
619 ret = pmic_write(dev->parent, adr, &val, 1);
620
621 return ret;
622}
623
624static int max77686_buck_enable(struct udevice *dev, int op, bool *enable)
625{
626 int ret, on_off;
627
628 if (op == PMIC_OP_GET) {
629 ret = max77686_buck_mode(dev, op, &on_off);
630 if (ret)
631 return ret;
632
633 switch (on_off) {
634 case OPMODE_OFF:
635 *enable = false;
636 break;
637 case OPMODE_ON:
638 *enable = true;
639 break;
640 default:
641 return -EINVAL;
642 }
643 } else if (op == PMIC_OP_SET) {
Tom Rinie6cf0aa2016-01-17 02:44:37 +0000644 if (*enable)
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200645 on_off = OPMODE_ON;
Tom Rinie6cf0aa2016-01-17 02:44:37 +0000646 else
647 on_off = OPMODE_OFF;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200648
649 ret = max77686_buck_mode(dev, op, &on_off);
650 if (ret)
651 return ret;
652 }
653
654 return 0;
655}
656
657static int max77686_ldo_probe(struct udevice *dev)
658{
Simon Glass71fa5b42020-12-03 16:55:18 -0700659 struct dm_regulator_uclass_plat *uc_pdata;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200660
Simon Glass71fa5b42020-12-03 16:55:18 -0700661 uc_pdata = dev_get_uclass_plat(dev);
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200662
663 uc_pdata->type = REGULATOR_TYPE_LDO;
664 uc_pdata->mode_count = max77686_ldo_modes(dev->driver_data,
665 &uc_pdata->mode, dev);
666
667 return 0;
668}
669
670static int ldo_get_value(struct udevice *dev)
671{
672 int uV;
673 int ret;
674
675 ret = max77686_ldo_val(dev, PMIC_OP_GET, &uV);
676 if (ret)
677 return ret;
678
679 return uV;
680}
681
682static int ldo_set_value(struct udevice *dev, int uV)
683{
684 return max77686_ldo_val(dev, PMIC_OP_SET, &uV);
685}
686
Keerthybeeac622017-06-13 09:53:48 +0530687static int ldo_get_enable(struct udevice *dev)
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200688{
689 bool enable = false;
690 int ret;
691
692 ret = max77686_ldo_enable(dev, PMIC_OP_GET, &enable);
693 if (ret)
694 return ret;
695
696 return enable;
697}
698
699static int ldo_set_enable(struct udevice *dev, bool enable)
700{
701 return max77686_ldo_enable(dev, PMIC_OP_SET, &enable);
702}
703
704static int ldo_get_mode(struct udevice *dev)
705{
706 int mode;
707 int ret;
708
709 ret = max77686_ldo_mode(dev, PMIC_OP_GET, &mode);
710 if (ret)
711 return ret;
712
713 return mode;
714}
715
716static int ldo_set_mode(struct udevice *dev, int mode)
717{
718 return max77686_ldo_mode(dev, PMIC_OP_SET, &mode);
719}
720
721static int max77686_buck_probe(struct udevice *dev)
722{
Simon Glass71fa5b42020-12-03 16:55:18 -0700723 struct dm_regulator_uclass_plat *uc_pdata;
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200724
Simon Glass71fa5b42020-12-03 16:55:18 -0700725 uc_pdata = dev_get_uclass_plat(dev);
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200726
727 uc_pdata->type = REGULATOR_TYPE_BUCK;
728 uc_pdata->mode_count = max77686_buck_modes(dev->driver_data,
729 &uc_pdata->mode);
730
731 return 0;
732}
733
734static int buck_get_value(struct udevice *dev)
735{
736 int uV;
737 int ret;
738
739 ret = max77686_buck_val(dev, PMIC_OP_GET, &uV);
740 if (ret)
741 return ret;
742
743 return uV;
744}
745
746static int buck_set_value(struct udevice *dev, int uV)
747{
748 return max77686_buck_val(dev, PMIC_OP_SET, &uV);
749}
750
Keerthybeeac622017-06-13 09:53:48 +0530751static int buck_get_enable(struct udevice *dev)
Przemyslaw Marczakafee81e2015-04-20 20:07:47 +0200752{
753 bool enable = false;
754 int ret;
755
756 ret = max77686_buck_enable(dev, PMIC_OP_GET, &enable);
757 if (ret)
758 return ret;
759
760 return enable;
761}
762
763static int buck_set_enable(struct udevice *dev, bool enable)
764{
765 return max77686_buck_enable(dev, PMIC_OP_SET, &enable);
766}
767
768static int buck_get_mode(struct udevice *dev)
769{
770 int mode;
771 int ret;
772
773 ret = max77686_buck_mode(dev, PMIC_OP_GET, &mode);
774 if (ret)
775 return ret;
776
777 return mode;
778}
779
780static int buck_set_mode(struct udevice *dev, int mode)
781{
782 return max77686_buck_mode(dev, PMIC_OP_SET, &mode);
783}
784
785static const struct dm_regulator_ops max77686_ldo_ops = {
786 .get_value = ldo_get_value,
787 .set_value = ldo_set_value,
788 .get_enable = ldo_get_enable,
789 .set_enable = ldo_set_enable,
790 .get_mode = ldo_get_mode,
791 .set_mode = ldo_set_mode,
792};
793
794U_BOOT_DRIVER(max77686_ldo) = {
795 .name = MAX77686_LDO_DRIVER,
796 .id = UCLASS_REGULATOR,
797 .ops = &max77686_ldo_ops,
798 .probe = max77686_ldo_probe,
799};
800
801static const struct dm_regulator_ops max77686_buck_ops = {
802 .get_value = buck_get_value,
803 .set_value = buck_set_value,
804 .get_enable = buck_get_enable,
805 .set_enable = buck_set_enable,
806 .get_mode = buck_get_mode,
807 .set_mode = buck_set_mode,
808};
809
810U_BOOT_DRIVER(max77686_buck) = {
811 .name = MAX77686_BUCK_DRIVER,
812 .id = UCLASS_REGULATOR,
813 .ops = &max77686_buck_ops,
814 .probe = max77686_buck_probe,
815};