blob: 3a20803993403b2e4601f32db78b7d19dd5ba7b0 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Przemyslaw Marczak1757df42015-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 Marczak1757df42015-04-20 20:07:47 +02007 */
8
9#include <common.h>
10#include <fdtdec.h>
11#include <errno.h>
12#include <dm.h>
Simon Glass1e94b462023-09-14 18:21:46 -060013#include <linux/printk.h>
Przemyslaw Marczak1757df42015-04-20 20:07:47 +020014#include <power/pmic.h>
15#include <power/regulator.h>
16#include <power/max77686_pmic.h>
17
Przemyslaw Marczak1757df42015-04-20 20:07:47 +020018#define MODE(_id, _val, _name) { \
19 .id = _id, \
20 .register_value = _val, \
21 .name = _name, \
22}
23
24/* LDO: 1,3,4,5,9,17,18,19,20,21,22,23,24,26,26,27 */
25static struct dm_regulator_mode max77686_ldo_mode_standby1[] = {
26 MODE(OPMODE_OFF, MAX77686_LDO_MODE_OFF, "OFF"),
27 MODE(OPMODE_LPM, MAX77686_LDO_MODE_LPM, "LPM"),
28 MODE(OPMODE_STANDBY_LPM, MAX77686_LDO_MODE_STANDBY_LPM, "ON/LPM"),
29 MODE(OPMODE_ON, MAX77686_LDO_MODE_ON, "ON"),
30};
31
32/* LDO: 2,6,7,8,10,11,12,14,15,16 */
33static struct dm_regulator_mode max77686_ldo_mode_standby2[] = {
34 MODE(OPMODE_OFF, MAX77686_LDO_MODE_OFF, "OFF"),
35 MODE(OPMODE_STANDBY, MAX77686_LDO_MODE_STANDBY, "ON/OFF"),
36 MODE(OPMODE_STANDBY_LPM, MAX77686_LDO_MODE_STANDBY_LPM, "ON/LPM"),
37 MODE(OPMODE_ON, MAX77686_LDO_MODE_ON, "ON"),
38};
39
40/* Buck: 1 */
41static struct dm_regulator_mode max77686_buck_mode_standby[] = {
42 MODE(OPMODE_OFF, MAX77686_BUCK_MODE_OFF, "OFF"),
43 MODE(OPMODE_STANDBY, MAX77686_BUCK_MODE_STANDBY, "ON/OFF"),
44 MODE(OPMODE_ON, MAX77686_BUCK_MODE_ON, "ON"),
45};
46
47/* Buck: 2,3,4 */
48static struct dm_regulator_mode max77686_buck_mode_lpm[] = {
49 MODE(OPMODE_OFF, MAX77686_BUCK_MODE_OFF, "OFF"),
50 MODE(OPMODE_STANDBY, MAX77686_BUCK_MODE_STANDBY, "ON/OFF"),
51 MODE(OPMODE_LPM, MAX77686_BUCK_MODE_LPM, "LPM"),
52 MODE(OPMODE_ON, MAX77686_BUCK_MODE_ON, "ON"),
53};
54
55/* Buck: 5,6,7,8,9 */
56static struct dm_regulator_mode max77686_buck_mode_onoff[] = {
57 MODE(OPMODE_OFF, MAX77686_BUCK_MODE_OFF, "OFF"),
58 MODE(OPMODE_ON, MAX77686_BUCK_MODE_ON, "ON"),
59};
60
Simon Glass8c428702015-07-02 18:16:04 -060061static const char max77686_buck_ctrl[] = {
Przemyslaw Marczak1757df42015-04-20 20:07:47 +020062 0xff, 0x10, 0x12, 0x1c, 0x26, 0x30, 0x32, 0x34, 0x36, 0x38
63};
64
Simon Glass8c428702015-07-02 18:16:04 -060065static const char max77686_buck_out[] = {
66 0xff, 0x11, 0x14, 0x1e, 0x28, 0x31, 0x33, 0x35, 0x37, 0x39
67};
68
Przemyslaw Marczak1757df42015-04-20 20:07:47 +020069static int max77686_buck_volt2hex(int buck, int uV)
70{
Tom Riniaae78fa2017-05-10 15:20:17 -040071 int hex = 0;
72 int hex_max = 0;
Przemyslaw Marczak1757df42015-04-20 20:07:47 +020073
74 switch (buck) {
75 case 2:
76 case 3:
77 case 4:
78 /* hex = (uV - 600000) / 12500; */
79 hex = (uV - MAX77686_BUCK_UV_LMIN) / MAX77686_BUCK_UV_LSTEP;
80 hex_max = MAX77686_BUCK234_VOLT_MAX_HEX;
Simon Glass75a429f2015-08-03 08:19:25 -060081 break;
Przemyslaw Marczak1757df42015-04-20 20:07:47 +020082 default:
Simon Glass75a429f2015-08-03 08:19:25 -060083 /*
84 * hex = (uV - 750000) / 50000. We assume that dynamic voltage
85 * scaling via GPIOs is not enabled and don't support that.
86 * If this is enabled then the driver will need to take that
Simon Glasse6b606d2015-08-09 09:10:57 -060087 * into account and check different registers depending on
88 * the current setting. See the datasheet for details.
Simon Glass75a429f2015-08-03 08:19:25 -060089 */
Przemyslaw Marczak1757df42015-04-20 20:07:47 +020090 hex = (uV - MAX77686_BUCK_UV_HMIN) / MAX77686_BUCK_UV_HSTEP;
91 hex_max = MAX77686_BUCK_VOLT_MAX_HEX;
92 break;
93 }
94
95 if (hex >= 0 && hex <= hex_max)
96 return hex;
97
Masahiro Yamada9b643e32017-09-16 14:10:41 +090098 pr_err("Value: %d uV is wrong for BUCK%d", uV, buck);
Przemyslaw Marczak1757df42015-04-20 20:07:47 +020099 return -EINVAL;
100}
101
102static int max77686_buck_hex2volt(int buck, int hex)
103{
104 unsigned uV = 0;
Tom Riniaae78fa2017-05-10 15:20:17 -0400105 int hex_max = 0;
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200106
107 if (hex < 0)
108 goto bad_hex;
109
110 switch (buck) {
111 case 2:
112 case 3:
113 case 4:
114 hex_max = MAX77686_BUCK234_VOLT_MAX_HEX;
115 if (hex > hex_max)
116 goto bad_hex;
117
118 /* uV = hex * 12500 + 600000; */
119 uV = hex * MAX77686_BUCK_UV_LSTEP + MAX77686_BUCK_UV_LMIN;
120 break;
121 default:
122 hex_max = MAX77686_BUCK_VOLT_MAX_HEX;
123 if (hex > hex_max)
124 goto bad_hex;
125
126 /* uV = hex * 50000 + 750000; */
127 uV = hex * MAX77686_BUCK_UV_HSTEP + MAX77686_BUCK_UV_HMIN;
128 break;
129 }
130
131 return uV;
132
133bad_hex:
Masahiro Yamada9b643e32017-09-16 14:10:41 +0900134 pr_err("Value: %#x is wrong for BUCK%d", hex, buck);
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200135 return -EINVAL;
136}
137
138static int max77686_ldo_volt2hex(int ldo, int uV)
139{
Tom Riniaae78fa2017-05-10 15:20:17 -0400140 int hex = 0;
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200141
142 switch (ldo) {
143 case 1:
144 case 2:
145 case 6:
146 case 7:
147 case 8:
148 case 15:
149 hex = (uV - MAX77686_LDO_UV_MIN) / MAX77686_LDO_UV_LSTEP;
150 /* hex = (uV - 800000) / 25000; */
151 break;
152 default:
153 hex = (uV - MAX77686_LDO_UV_MIN) / MAX77686_LDO_UV_HSTEP;
154 /* hex = (uV - 800000) / 50000; */
155 }
156
157 if (hex >= 0 && hex <= MAX77686_LDO_VOLT_MAX_HEX)
158 return hex;
159
Masahiro Yamada9b643e32017-09-16 14:10:41 +0900160 pr_err("Value: %d uV is wrong for LDO%d", uV, ldo);
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200161 return -EINVAL;
162}
163
164static int max77686_ldo_hex2volt(int ldo, int hex)
165{
166 unsigned int uV = 0;
167
168 if (hex > MAX77686_LDO_VOLT_MAX_HEX)
169 goto bad_hex;
170
171 switch (ldo) {
172 case 1:
173 case 2:
174 case 6:
175 case 7:
176 case 8:
177 case 15:
178 /* uV = hex * 25000 + 800000; */
179 uV = hex * MAX77686_LDO_UV_LSTEP + MAX77686_LDO_UV_MIN;
180 break;
181 default:
182 /* uV = hex * 50000 + 800000; */
183 uV = hex * MAX77686_LDO_UV_HSTEP + MAX77686_LDO_UV_MIN;
184 }
185
186 return uV;
187
188bad_hex:
Masahiro Yamada9b643e32017-09-16 14:10:41 +0900189 pr_err("Value: %#x is wrong for ldo%d", hex, ldo);
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200190 return -EINVAL;
191}
192
193static int max77686_ldo_hex2mode(int ldo, int hex)
194{
195 if (hex > MAX77686_LDO_MODE_MASK)
196 return -EINVAL;
197
198 switch (hex) {
199 case MAX77686_LDO_MODE_OFF:
200 return OPMODE_OFF;
201 case MAX77686_LDO_MODE_LPM: /* == MAX77686_LDO_MODE_STANDBY: */
202 /* The same mode values but different meaning for each ldo */
203 switch (ldo) {
204 case 2:
205 case 6:
206 case 7:
207 case 8:
208 case 10:
209 case 11:
210 case 12:
211 case 14:
212 case 15:
213 case 16:
214 return OPMODE_STANDBY;
215 default:
216 return OPMODE_LPM;
217 }
218 case MAX77686_LDO_MODE_STANDBY_LPM:
219 return OPMODE_STANDBY_LPM;
220 case MAX77686_LDO_MODE_ON:
221 return OPMODE_ON;
222 default:
223 return -EINVAL;
224 }
225}
226
227static int max77686_buck_hex2mode(int buck, int hex)
228{
229 if (hex > MAX77686_BUCK_MODE_MASK)
230 return -EINVAL;
231
232 switch (hex) {
233 case MAX77686_BUCK_MODE_OFF:
234 return OPMODE_OFF;
235 case MAX77686_BUCK_MODE_ON:
236 return OPMODE_ON;
237 case MAX77686_BUCK_MODE_STANDBY:
238 switch (buck) {
239 case 1:
240 case 2:
241 case 3:
242 case 4:
243 return OPMODE_STANDBY;
244 default:
245 return -EINVAL;
246 }
247 case MAX77686_BUCK_MODE_LPM:
248 switch (buck) {
249 case 2:
250 case 3:
251 case 4:
252 return OPMODE_LPM;
253 default:
254 return -EINVAL;
255 }
256 default:
257 return -EINVAL;
258 }
259}
260
261static int max77686_buck_modes(int buck, struct dm_regulator_mode **modesp)
262{
263 int ret = -EINVAL;
264
265 if (buck < 1 || buck > MAX77686_BUCK_NUM)
266 return ret;
267
268 switch (buck) {
269 case 1:
270 *modesp = max77686_buck_mode_standby;
271 ret = ARRAY_SIZE(max77686_buck_mode_standby);
272 break;
273 case 2:
274 case 3:
275 case 4:
276 *modesp = max77686_buck_mode_lpm;
277 ret = ARRAY_SIZE(max77686_buck_mode_lpm);
278 break;
279 default:
280 *modesp = max77686_buck_mode_onoff;
281 ret = ARRAY_SIZE(max77686_buck_mode_onoff);
282 }
283
284 return ret;
285}
286
287static int max77686_ldo_modes(int ldo, struct dm_regulator_mode **modesp,
288 struct udevice *dev)
289{
290 int ret = -EINVAL;
291
292 if (ldo < 1 || ldo > MAX77686_LDO_NUM)
293 return ret;
294
295 switch (ldo) {
296 case 2:
297 case 6:
298 case 7:
299 case 8:
300 case 10:
301 case 11:
302 case 12:
303 case 14:
304 case 15:
305 case 16:
306 *modesp = max77686_ldo_mode_standby2;
307 ret = ARRAY_SIZE(max77686_ldo_mode_standby2);
308 break;
309 default:
310 *modesp = max77686_ldo_mode_standby1;
311 ret = ARRAY_SIZE(max77686_ldo_mode_standby1);
312 }
313
314 return ret;
315}
316
317static int max77686_ldo_val(struct udevice *dev, int op, int *uV)
318{
Tom Riniaae78fa2017-05-10 15:20:17 -0400319 unsigned int adr;
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200320 unsigned char val;
Tom Riniaae78fa2017-05-10 15:20:17 -0400321 int hex, ldo, ret;
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200322
323 if (op == PMIC_OP_GET)
324 *uV = 0;
325
326 ldo = dev->driver_data;
327 if (ldo < 1 || ldo > MAX77686_LDO_NUM) {
Masahiro Yamada9b643e32017-09-16 14:10:41 +0900328 pr_err("Wrong ldo number: %d", ldo);
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200329 return -EINVAL;
330 }
331
332 adr = MAX77686_REG_PMIC_LDO1CTRL1 + ldo - 1;
333
334 ret = pmic_read(dev->parent, adr, &val, 1);
335 if (ret)
336 return ret;
337
338 if (op == PMIC_OP_GET) {
339 val &= MAX77686_LDO_VOLT_MASK;
340 ret = max77686_ldo_hex2volt(ldo, val);
341 if (ret < 0)
342 return ret;
343 *uV = ret;
344 return 0;
345 }
346
347 hex = max77686_ldo_volt2hex(ldo, *uV);
348 if (hex < 0)
349 return hex;
350
351 val &= ~MAX77686_LDO_VOLT_MASK;
352 val |= hex;
353 ret = pmic_write(dev->parent, adr, &val, 1);
354
355 return ret;
356}
357
358static int max77686_buck_val(struct udevice *dev, int op, int *uV)
359{
Tom Riniaae78fa2017-05-10 15:20:17 -0400360 unsigned int mask, adr;
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200361 unsigned char val;
Tom Riniaae78fa2017-05-10 15:20:17 -0400362 int hex, buck, ret;
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200363
364 buck = dev->driver_data;
365 if (buck < 1 || buck > MAX77686_BUCK_NUM) {
Masahiro Yamada9b643e32017-09-16 14:10:41 +0900366 pr_err("Wrong buck number: %d", buck);
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200367 return -EINVAL;
368 }
369
370 if (op == PMIC_OP_GET)
371 *uV = 0;
372
373 /* &buck_out = ctrl + 1 */
Simon Glass8c428702015-07-02 18:16:04 -0600374 adr = max77686_buck_out[buck];
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200375
376 /* mask */
377 switch (buck) {
378 case 2:
379 case 3:
380 case 4:
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200381 mask = MAX77686_BUCK234_VOLT_MASK;
Simon Glass75a429f2015-08-03 08:19:25 -0600382 break;
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200383 default:
384 mask = MAX77686_BUCK_VOLT_MASK;
Simon Glass75a429f2015-08-03 08:19:25 -0600385 break;
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200386 }
387
388 ret = pmic_read(dev->parent, adr, &val, 1);
389 if (ret)
390 return ret;
391
392 if (op == PMIC_OP_GET) {
393 val &= mask;
394 ret = max77686_buck_hex2volt(buck, val);
395 if (ret < 0)
396 return ret;
397 *uV = ret;
398 return 0;
399 }
400
401 hex = max77686_buck_volt2hex(buck, *uV);
402 if (hex < 0)
403 return hex;
404
405 val &= ~mask;
406 val |= hex;
407 ret = pmic_write(dev->parent, adr, &val, 1);
408
409 return ret;
410}
411
412static int max77686_ldo_mode(struct udevice *dev, int op, int *opmode)
413{
Peng Fan86405222015-07-28 22:47:08 +0800414 unsigned int adr, mode;
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200415 unsigned char val;
Peng Fan86405222015-07-28 22:47:08 +0800416 int ldo, ret;
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200417
418 if (op == PMIC_OP_GET)
419 *opmode = -EINVAL;
420
421 ldo = dev->driver_data;
422 if (ldo < 1 || ldo > MAX77686_LDO_NUM) {
Masahiro Yamada9b643e32017-09-16 14:10:41 +0900423 pr_err("Wrong ldo number: %d", ldo);
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200424 return -EINVAL;
425 }
426
427 adr = MAX77686_REG_PMIC_LDO1CTRL1 + ldo - 1;
428
429 ret = pmic_read(dev->parent, adr, &val, 1);
430 if (ret)
431 return ret;
432
433 if (op == PMIC_OP_GET) {
434 val &= MAX77686_LDO_MODE_MASK;
435 ret = max77686_ldo_hex2mode(ldo, val);
436 if (ret < 0)
437 return ret;
438 *opmode = ret;
439 return 0;
440 }
441
442 /* mode */
443 switch (*opmode) {
444 case OPMODE_OFF:
445 mode = MAX77686_LDO_MODE_OFF;
446 break;
447 case OPMODE_LPM:
448 switch (ldo) {
449 case 2:
450 case 6:
451 case 7:
452 case 8:
453 case 10:
454 case 11:
455 case 12:
456 case 14:
457 case 15:
458 case 16:
459 return -EINVAL;
460 default:
461 mode = MAX77686_LDO_MODE_LPM;
462 }
463 break;
464 case OPMODE_STANDBY:
465 switch (ldo) {
466 case 2:
467 case 6:
468 case 7:
469 case 8:
470 case 10:
471 case 11:
472 case 12:
473 case 14:
474 case 15:
475 case 16:
476 mode = MAX77686_LDO_MODE_STANDBY;
477 break;
478 default:
479 return -EINVAL;
480 }
481 break;
482 case OPMODE_STANDBY_LPM:
483 mode = MAX77686_LDO_MODE_STANDBY_LPM;
484 break;
485 case OPMODE_ON:
486 mode = MAX77686_LDO_MODE_ON;
487 break;
488 default:
489 mode = 0xff;
490 }
491
492 if (mode == 0xff) {
Masahiro Yamada9b643e32017-09-16 14:10:41 +0900493 pr_err("Wrong mode: %d for ldo%d", *opmode, ldo);
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200494 return -EINVAL;
495 }
496
497 val &= ~MAX77686_LDO_MODE_MASK;
498 val |= mode;
499 ret = pmic_write(dev->parent, adr, &val, 1);
500
501 return ret;
502}
503
504static int max77686_ldo_enable(struct udevice *dev, int op, bool *enable)
505{
506 int ret, on_off;
507
508 if (op == PMIC_OP_GET) {
509 ret = max77686_ldo_mode(dev, op, &on_off);
510 if (ret)
511 return ret;
512
513 switch (on_off) {
514 case OPMODE_OFF:
Tom Rini6d6aece2016-01-17 02:44:37 +0000515 *enable = false;
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200516 break;
517 case OPMODE_ON:
Tom Rini6d6aece2016-01-17 02:44:37 +0000518 *enable = true;
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200519 break;
520 default:
521 return -EINVAL;
522 }
523 } else if (op == PMIC_OP_SET) {
Tom Rini6d6aece2016-01-17 02:44:37 +0000524 if (*enable)
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200525 on_off = OPMODE_ON;
Tom Rini6d6aece2016-01-17 02:44:37 +0000526 else
527 on_off = OPMODE_OFF;
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200528
529 ret = max77686_ldo_mode(dev, op, &on_off);
530 if (ret)
531 return ret;
532 }
533
534 return 0;
535}
536
537static int max77686_buck_mode(struct udevice *dev, int op, int *opmode)
538{
Peng Fan86405222015-07-28 22:47:08 +0800539 unsigned int mask, adr, mode, mode_shift;
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200540 unsigned char val;
Peng Fan86405222015-07-28 22:47:08 +0800541 int buck, ret;
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200542
543 buck = dev->driver_data;
544 if (buck < 1 || buck > MAX77686_BUCK_NUM) {
Masahiro Yamada9b643e32017-09-16 14:10:41 +0900545 pr_err("Wrong buck number: %d", buck);
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200546 return -EINVAL;
547 }
548
Simon Glass8c428702015-07-02 18:16:04 -0600549 adr = max77686_buck_ctrl[buck];
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200550
551 /* mask */
552 switch (buck) {
553 case 2:
554 case 3:
555 case 4:
556 mode_shift = MAX77686_BUCK_MODE_SHIFT_2;
557 break;
558 default:
559 mode_shift = MAX77686_BUCK_MODE_SHIFT_1;
560 }
561
562 mask = MAX77686_BUCK_MODE_MASK << mode_shift;
563
564 ret = pmic_read(dev->parent, adr, &val, 1);
565 if (ret)
566 return ret;
567
568 if (op == PMIC_OP_GET) {
569 val &= mask;
570 val >>= mode_shift;
571 ret = max77686_buck_hex2mode(buck, val);
572 if (ret < 0)
573 return ret;
574 *opmode = ret;
575 return 0;
576 }
577
578 /* mode */
579 switch (*opmode) {
580 case OPMODE_OFF:
581 mode = MAX77686_BUCK_MODE_OFF;
582 break;
583 case OPMODE_STANDBY:
584 switch (buck) {
585 case 1:
586 case 2:
587 case 3:
588 case 4:
589 mode = MAX77686_BUCK_MODE_STANDBY << mode_shift;
590 break;
591 default:
592 mode = 0xff;
593 }
594 break;
595 case OPMODE_LPM:
596 switch (buck) {
597 case 2:
598 case 3:
599 case 4:
600 mode = MAX77686_BUCK_MODE_LPM << mode_shift;
601 break;
602 default:
603 mode = 0xff;
604 }
605 break;
606 case OPMODE_ON:
607 mode = MAX77686_BUCK_MODE_ON << mode_shift;
608 break;
609 default:
610 mode = 0xff;
611 }
612
613 if (mode == 0xff) {
Masahiro Yamada9b643e32017-09-16 14:10:41 +0900614 pr_err("Wrong mode: %d for buck: %d\n", *opmode, buck);
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200615 return -EINVAL;
616 }
617
618 val &= ~mask;
619 val |= mode;
620 ret = pmic_write(dev->parent, adr, &val, 1);
621
622 return ret;
623}
624
625static int max77686_buck_enable(struct udevice *dev, int op, bool *enable)
626{
627 int ret, on_off;
628
629 if (op == PMIC_OP_GET) {
630 ret = max77686_buck_mode(dev, op, &on_off);
631 if (ret)
632 return ret;
633
634 switch (on_off) {
635 case OPMODE_OFF:
636 *enable = false;
637 break;
638 case OPMODE_ON:
639 *enable = true;
640 break;
641 default:
642 return -EINVAL;
643 }
644 } else if (op == PMIC_OP_SET) {
Tom Rini6d6aece2016-01-17 02:44:37 +0000645 if (*enable)
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200646 on_off = OPMODE_ON;
Tom Rini6d6aece2016-01-17 02:44:37 +0000647 else
648 on_off = OPMODE_OFF;
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200649
650 ret = max77686_buck_mode(dev, op, &on_off);
651 if (ret)
652 return ret;
653 }
654
655 return 0;
656}
657
658static int max77686_ldo_probe(struct udevice *dev)
659{
Simon Glasscaa4daa2020-12-03 16:55:18 -0700660 struct dm_regulator_uclass_plat *uc_pdata;
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200661
Simon Glasscaa4daa2020-12-03 16:55:18 -0700662 uc_pdata = dev_get_uclass_plat(dev);
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200663
664 uc_pdata->type = REGULATOR_TYPE_LDO;
665 uc_pdata->mode_count = max77686_ldo_modes(dev->driver_data,
666 &uc_pdata->mode, dev);
667
668 return 0;
669}
670
671static int ldo_get_value(struct udevice *dev)
672{
673 int uV;
674 int ret;
675
676 ret = max77686_ldo_val(dev, PMIC_OP_GET, &uV);
677 if (ret)
678 return ret;
679
680 return uV;
681}
682
683static int ldo_set_value(struct udevice *dev, int uV)
684{
685 return max77686_ldo_val(dev, PMIC_OP_SET, &uV);
686}
687
Keerthyb6168352017-06-13 09:53:48 +0530688static int ldo_get_enable(struct udevice *dev)
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200689{
690 bool enable = false;
691 int ret;
692
693 ret = max77686_ldo_enable(dev, PMIC_OP_GET, &enable);
694 if (ret)
695 return ret;
696
697 return enable;
698}
699
700static int ldo_set_enable(struct udevice *dev, bool enable)
701{
702 return max77686_ldo_enable(dev, PMIC_OP_SET, &enable);
703}
704
705static int ldo_get_mode(struct udevice *dev)
706{
707 int mode;
708 int ret;
709
710 ret = max77686_ldo_mode(dev, PMIC_OP_GET, &mode);
711 if (ret)
712 return ret;
713
714 return mode;
715}
716
717static int ldo_set_mode(struct udevice *dev, int mode)
718{
719 return max77686_ldo_mode(dev, PMIC_OP_SET, &mode);
720}
721
722static int max77686_buck_probe(struct udevice *dev)
723{
Simon Glasscaa4daa2020-12-03 16:55:18 -0700724 struct dm_regulator_uclass_plat *uc_pdata;
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200725
Simon Glasscaa4daa2020-12-03 16:55:18 -0700726 uc_pdata = dev_get_uclass_plat(dev);
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200727
728 uc_pdata->type = REGULATOR_TYPE_BUCK;
729 uc_pdata->mode_count = max77686_buck_modes(dev->driver_data,
730 &uc_pdata->mode);
731
732 return 0;
733}
734
735static int buck_get_value(struct udevice *dev)
736{
737 int uV;
738 int ret;
739
740 ret = max77686_buck_val(dev, PMIC_OP_GET, &uV);
741 if (ret)
742 return ret;
743
744 return uV;
745}
746
747static int buck_set_value(struct udevice *dev, int uV)
748{
749 return max77686_buck_val(dev, PMIC_OP_SET, &uV);
750}
751
Keerthyb6168352017-06-13 09:53:48 +0530752static int buck_get_enable(struct udevice *dev)
Przemyslaw Marczak1757df42015-04-20 20:07:47 +0200753{
754 bool enable = false;
755 int ret;
756
757 ret = max77686_buck_enable(dev, PMIC_OP_GET, &enable);
758 if (ret)
759 return ret;
760
761 return enable;
762}
763
764static int buck_set_enable(struct udevice *dev, bool enable)
765{
766 return max77686_buck_enable(dev, PMIC_OP_SET, &enable);
767}
768
769static int buck_get_mode(struct udevice *dev)
770{
771 int mode;
772 int ret;
773
774 ret = max77686_buck_mode(dev, PMIC_OP_GET, &mode);
775 if (ret)
776 return ret;
777
778 return mode;
779}
780
781static int buck_set_mode(struct udevice *dev, int mode)
782{
783 return max77686_buck_mode(dev, PMIC_OP_SET, &mode);
784}
785
786static const struct dm_regulator_ops max77686_ldo_ops = {
787 .get_value = ldo_get_value,
788 .set_value = ldo_set_value,
789 .get_enable = ldo_get_enable,
790 .set_enable = ldo_set_enable,
791 .get_mode = ldo_get_mode,
792 .set_mode = ldo_set_mode,
793};
794
795U_BOOT_DRIVER(max77686_ldo) = {
796 .name = MAX77686_LDO_DRIVER,
797 .id = UCLASS_REGULATOR,
798 .ops = &max77686_ldo_ops,
799 .probe = max77686_ldo_probe,
800};
801
802static const struct dm_regulator_ops max77686_buck_ops = {
803 .get_value = buck_get_value,
804 .set_value = buck_set_value,
805 .get_enable = buck_get_enable,
806 .set_enable = buck_set_enable,
807 .get_mode = buck_get_mode,
808 .set_mode = buck_set_mode,
809};
810
811U_BOOT_DRIVER(max77686_buck) = {
812 .name = MAX77686_BUCK_DRIVER,
813 .id = UCLASS_REGULATOR,
814 .ops = &max77686_buck_ops,
815 .probe = max77686_buck_probe,
816};