Merge tag 'bcachefs-2024-10-05' of git://evilpiepirate.org/bcachefs
[linux-2.6-block.git] / drivers / soc / rockchip / io-domain.c
CommitLineData
9c92ab61 1// SPDX-License-Identifier: GPL-2.0-only
662a9586
HS
2/*
3 * Rockchip IO Voltage Domain driver
4 *
5 * Copyright 2014 MundoReader S.L.
6 * Copyright 2014 Google, Inc.
662a9586
HS
7 */
8
9#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/err.h>
12#include <linux/mfd/syscon.h>
13#include <linux/of.h>
14#include <linux/platform_device.h>
15#include <linux/regmap.h>
16#include <linux/regulator/consumer.h>
17
18#define MAX_SUPPLIES 16
19
20/*
21 * The max voltage for 1.8V and 3.3V come from the Rockchip datasheet under
22 * "Recommended Operating Conditions" for "Digital GPIO". When the typical
23 * is 3.3V the max is 3.6V. When the typical is 1.8V the max is 1.98V.
24 *
25 * They are used like this:
26 * - If the voltage on a rail is above the "1.8" voltage (1.98V) we'll tell the
27 * SoC we're at 3.3.
28 * - If the voltage on a rail is above the "3.3" voltage (3.6V) we'll consider
29 * that to be an error.
30 */
31#define MAX_VOLTAGE_1_8 1980000
32#define MAX_VOLTAGE_3_3 3600000
33
b8281fa7
DW
34#define PX30_IO_VSEL 0x180
35#define PX30_IO_VSEL_VCCIO6_SRC BIT(0)
36#define PX30_IO_VSEL_VCCIO6_SUPPLY_NUM 1
37
662a9586
HS
38#define RK3288_SOC_CON2 0x24c
39#define RK3288_SOC_CON2_FLASH0 BIT(7)
40#define RK3288_SOC_FLASH_SUPPLY_NUM 2
41
f0d70478
DW
42#define RK3308_SOC_CON0 0x300
43#define RK3308_SOC_CON0_VCCIO3 BIT(8)
44#define RK3308_SOC_VCCIO3_SUPPLY_NUM 3
45
7db36b1c
DW
46#define RK3328_SOC_CON4 0x410
47#define RK3328_SOC_CON4_VCCIO2 BIT(7)
48#define RK3328_SOC_VCCIO2_SUPPLY_NUM 1
49
3fc147e9
HS
50#define RK3368_SOC_CON15 0x43c
51#define RK3368_SOC_CON15_FLASH0 BIT(14)
52#define RK3368_SOC_FLASH_SUPPLY_NUM 2
53
f447671b
DW
54#define RK3399_PMUGRF_CON0 0x180
55#define RK3399_PMUGRF_CON0_VSEL BIT(8)
56#define RK3399_PMUGRF_VSEL_SUPPLY_NUM 9
57
28b05a64
JX
58#define RK3568_PMU_GRF_IO_VSEL0 (0x0140)
59#define RK3568_PMU_GRF_IO_VSEL1 (0x0144)
60#define RK3568_PMU_GRF_IO_VSEL2 (0x0148)
662a9586 61
28b05a64 62struct rockchip_iodomain;
662a9586
HS
63
64struct rockchip_iodomain_supply {
65 struct rockchip_iodomain *iod;
66 struct regulator *reg;
67 struct notifier_block nb;
68 int idx;
69};
70
28b05a64
JX
71struct rockchip_iodomain_soc_data {
72 int grf_offset;
73 const char *supply_names[MAX_SUPPLIES];
74 void (*init)(struct rockchip_iodomain *iod);
75 int (*write)(struct rockchip_iodomain_supply *supply, int uV);
76};
77
662a9586
HS
78struct rockchip_iodomain {
79 struct device *dev;
80 struct regmap *grf;
5a2772a8 81 const struct rockchip_iodomain_soc_data *soc_data;
662a9586 82 struct rockchip_iodomain_supply supplies[MAX_SUPPLIES];
28b05a64 83 int (*write)(struct rockchip_iodomain_supply *supply, int uV);
662a9586
HS
84};
85
28b05a64
JX
86static int rk3568_iodomain_write(struct rockchip_iodomain_supply *supply, int uV)
87{
88 struct rockchip_iodomain *iod = supply->iod;
89 u32 is_3v3 = uV > MAX_VOLTAGE_1_8;
90 u32 val0, val1;
91 int b;
92
93 switch (supply->idx) {
94 case 0: /* pmuio1 */
95 break;
96 case 1: /* pmuio2 */
97 b = supply->idx;
98 val0 = BIT(16 + b) | (is_3v3 ? 0 : BIT(b));
99 b = supply->idx + 4;
100 val1 = BIT(16 + b) | (is_3v3 ? BIT(b) : 0);
101
102 regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL2, val0);
103 regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL2, val1);
104 break;
105 case 3: /* vccio2 */
106 break;
107 case 2: /* vccio1 */
108 case 4: /* vccio3 */
109 case 5: /* vccio4 */
110 case 6: /* vccio5 */
111 case 7: /* vccio6 */
112 case 8: /* vccio7 */
113 b = supply->idx - 1;
114 val0 = BIT(16 + b) | (is_3v3 ? 0 : BIT(b));
115 val1 = BIT(16 + b) | (is_3v3 ? BIT(b) : 0);
116
117 regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL0, val0);
118 regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL1, val1);
119 break;
120 default:
121 return -EINVAL;
9e5747c5 122 }
28b05a64
JX
123
124 return 0;
125}
126
662a9586
HS
127static int rockchip_iodomain_write(struct rockchip_iodomain_supply *supply,
128 int uV)
129{
130 struct rockchip_iodomain *iod = supply->iod;
131 u32 val;
132 int ret;
133
134 /* set value bit */
135 val = (uV > MAX_VOLTAGE_1_8) ? 0 : 1;
136 val <<= supply->idx;
137
138 /* apply hiword-mask */
139 val |= (BIT(supply->idx) << 16);
140
141 ret = regmap_write(iod->grf, iod->soc_data->grf_offset, val);
142 if (ret)
143 dev_err(iod->dev, "Couldn't write to GRF\n");
144
145 return ret;
146}
147
148static int rockchip_iodomain_notify(struct notifier_block *nb,
149 unsigned long event,
150 void *data)
151{
152 struct rockchip_iodomain_supply *supply =
153 container_of(nb, struct rockchip_iodomain_supply, nb);
154 int uV;
155 int ret;
156
157 /*
158 * According to Rockchip it's important to keep the SoC IO domain
159 * higher than (or equal to) the external voltage. That means we need
160 * to change it before external voltage changes happen in the case
161 * of an increase.
162 *
163 * Note that in the "pre" change we pick the max possible voltage that
164 * the regulator might end up at (the client requests a range and we
165 * don't know for certain the exact voltage). Right now we rely on the
166 * slop in MAX_VOLTAGE_1_8 and MAX_VOLTAGE_3_3 to save us if clients
167 * request something like a max of 3.6V when they really want 3.3V.
168 * We could attempt to come up with better rules if this fails.
169 */
170 if (event & REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) {
171 struct pre_voltage_change_data *pvc_data = data;
172
173 uV = max_t(unsigned long, pvc_data->old_uV, pvc_data->max_uV);
174 } else if (event & (REGULATOR_EVENT_VOLTAGE_CHANGE |
175 REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE)) {
176 uV = (unsigned long)data;
177 } else {
178 return NOTIFY_OK;
179 }
180
181 dev_dbg(supply->iod->dev, "Setting to %d\n", uV);
182
183 if (uV > MAX_VOLTAGE_3_3) {
184 dev_err(supply->iod->dev, "Voltage too high: %d\n", uV);
185
186 if (event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE)
187 return NOTIFY_BAD;
188 }
189
28b05a64 190 ret = supply->iod->write(supply, uV);
662a9586
HS
191 if (ret && event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE)
192 return NOTIFY_BAD;
193
f5261402 194 dev_dbg(supply->iod->dev, "Setting to %d done\n", uV);
662a9586
HS
195 return NOTIFY_OK;
196}
197
b8281fa7
DW
198static void px30_iodomain_init(struct rockchip_iodomain *iod)
199{
200 int ret;
201 u32 val;
202
adef0ced 203 /* if no VCCIO6 supply we should leave things alone */
b8281fa7
DW
204 if (!iod->supplies[PX30_IO_VSEL_VCCIO6_SUPPLY_NUM].reg)
205 return;
206
207 /*
adef0ced 208 * set vccio6 iodomain to also use this framework
b8281fa7
DW
209 * instead of a special gpio.
210 */
211 val = PX30_IO_VSEL_VCCIO6_SRC | (PX30_IO_VSEL_VCCIO6_SRC << 16);
212 ret = regmap_write(iod->grf, PX30_IO_VSEL, val);
213 if (ret < 0)
adef0ced 214 dev_warn(iod->dev, "couldn't update vccio6 ctrl\n");
b8281fa7
DW
215}
216
662a9586
HS
217static void rk3288_iodomain_init(struct rockchip_iodomain *iod)
218{
219 int ret;
220 u32 val;
221
222 /* if no flash supply we should leave things alone */
223 if (!iod->supplies[RK3288_SOC_FLASH_SUPPLY_NUM].reg)
224 return;
225
226 /*
227 * set flash0 iodomain to also use this framework
228 * instead of a special gpio.
229 */
230 val = RK3288_SOC_CON2_FLASH0 | (RK3288_SOC_CON2_FLASH0 << 16);
231 ret = regmap_write(iod->grf, RK3288_SOC_CON2, val);
232 if (ret < 0)
233 dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
234}
235
f0d70478
DW
236static void rk3308_iodomain_init(struct rockchip_iodomain *iod)
237{
238 int ret;
239 u32 val;
240
241 /* if no vccio3 supply we should leave things alone */
242 if (!iod->supplies[RK3308_SOC_VCCIO3_SUPPLY_NUM].reg)
243 return;
244
245 /*
246 * set vccio3 iodomain to also use this framework
247 * instead of a special gpio.
248 */
249 val = RK3308_SOC_CON0_VCCIO3 | (RK3308_SOC_CON0_VCCIO3 << 16);
250 ret = regmap_write(iod->grf, RK3308_SOC_CON0, val);
251 if (ret < 0)
252 dev_warn(iod->dev, "couldn't update vccio3 vsel ctrl\n");
253}
254
7db36b1c
DW
255static void rk3328_iodomain_init(struct rockchip_iodomain *iod)
256{
257 int ret;
258 u32 val;
259
260 /* if no vccio2 supply we should leave things alone */
261 if (!iod->supplies[RK3328_SOC_VCCIO2_SUPPLY_NUM].reg)
262 return;
263
264 /*
265 * set vccio2 iodomain to also use this framework
266 * instead of a special gpio.
267 */
268 val = RK3328_SOC_CON4_VCCIO2 | (RK3328_SOC_CON4_VCCIO2 << 16);
269 ret = regmap_write(iod->grf, RK3328_SOC_CON4, val);
270 if (ret < 0)
271 dev_warn(iod->dev, "couldn't update vccio2 vsel ctrl\n");
272}
273
3fc147e9
HS
274static void rk3368_iodomain_init(struct rockchip_iodomain *iod)
275{
276 int ret;
277 u32 val;
278
279 /* if no flash supply we should leave things alone */
280 if (!iod->supplies[RK3368_SOC_FLASH_SUPPLY_NUM].reg)
281 return;
282
283 /*
284 * set flash0 iodomain to also use this framework
285 * instead of a special gpio.
286 */
287 val = RK3368_SOC_CON15_FLASH0 | (RK3368_SOC_CON15_FLASH0 << 16);
288 ret = regmap_write(iod->grf, RK3368_SOC_CON15, val);
289 if (ret < 0)
290 dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
291}
292
f447671b
DW
293static void rk3399_pmu_iodomain_init(struct rockchip_iodomain *iod)
294{
295 int ret;
296 u32 val;
297
298 /* if no pmu io supply we should leave things alone */
299 if (!iod->supplies[RK3399_PMUGRF_VSEL_SUPPLY_NUM].reg)
300 return;
301
302 /*
303 * set pmu io iodomain to also use this framework
304 * instead of a special gpio.
305 */
306 val = RK3399_PMUGRF_CON0_VSEL | (RK3399_PMUGRF_CON0_VSEL << 16);
307 ret = regmap_write(iod->grf, RK3399_PMUGRF_CON0, val);
308 if (ret < 0)
309 dev_warn(iod->dev, "couldn't update pmu io iodomain ctrl\n");
310}
311
b8281fa7
DW
312static const struct rockchip_iodomain_soc_data soc_data_px30 = {
313 .grf_offset = 0x180,
314 .supply_names = {
315 NULL,
316 "vccio6",
317 "vccio1",
318 "vccio2",
319 "vccio3",
320 "vccio4",
321 "vccio5",
322 "vccio-oscgpi",
323 },
324 .init = px30_iodomain_init,
325};
326
327static const struct rockchip_iodomain_soc_data soc_data_px30_pmu = {
328 .grf_offset = 0x100,
329 .supply_names = {
330 NULL,
331 NULL,
332 NULL,
333 NULL,
334 NULL,
335 NULL,
336 NULL,
337 NULL,
338 NULL,
339 NULL,
340 NULL,
341 NULL,
342 NULL,
343 NULL,
344 "pmuio1",
345 "pmuio2",
346 },
347};
348
662a9586
HS
349/*
350 * On the rk3188 the io-domains are handled by a shared register with the
351 * lower 8 bits being still being continuing drive-strength settings.
352 */
353static const struct rockchip_iodomain_soc_data soc_data_rk3188 = {
354 .grf_offset = 0x104,
355 .supply_names = {
356 NULL,
357 NULL,
358 NULL,
359 NULL,
360 NULL,
361 NULL,
362 NULL,
363 NULL,
364 "ap0",
365 "ap1",
366 "cif",
367 "flash",
368 "vccio0",
369 "vccio1",
370 "lcdc0",
371 "lcdc1",
372 },
373};
374
1a99d0c7
DW
375static const struct rockchip_iodomain_soc_data soc_data_rk3228 = {
376 .grf_offset = 0x418,
377 .supply_names = {
378 "vccio1",
379 "vccio2",
380 "vccio3",
381 "vccio4",
382 },
383};
384
662a9586
HS
385static const struct rockchip_iodomain_soc_data soc_data_rk3288 = {
386 .grf_offset = 0x380,
387 .supply_names = {
388 "lcdc", /* LCDC_VDD */
389 "dvp", /* DVPIO_VDD */
390 "flash0", /* FLASH0_VDD (emmc) */
391 "flash1", /* FLASH1_VDD (sdio1) */
392 "wifi", /* APIO3_VDD (sdio0) */
393 "bb", /* APIO5_VDD */
394 "audio", /* APIO4_VDD */
395 "sdcard", /* SDMMC0_VDD (sdmmc) */
396 "gpio30", /* APIO1_VDD */
397 "gpio1830", /* APIO2_VDD */
398 },
399 .init = rk3288_iodomain_init,
400};
401
f0d70478
DW
402static const struct rockchip_iodomain_soc_data soc_data_rk3308 = {
403 .grf_offset = 0x300,
404 .supply_names = {
405 "vccio0",
406 "vccio1",
407 "vccio2",
408 "vccio3",
409 "vccio4",
410 "vccio5",
411 },
412 .init = rk3308_iodomain_init,
413};
414
7db36b1c
DW
415static const struct rockchip_iodomain_soc_data soc_data_rk3328 = {
416 .grf_offset = 0x410,
417 .supply_names = {
418 "vccio1",
419 "vccio2",
420 "vccio3",
421 "vccio4",
422 "vccio5",
423 "vccio6",
424 "pmuio",
425 },
426 .init = rk3328_iodomain_init,
427};
428
3fc147e9
HS
429static const struct rockchip_iodomain_soc_data soc_data_rk3368 = {
430 .grf_offset = 0x900,
431 .supply_names = {
432 NULL, /* reserved */
433 "dvp", /* DVPIO_VDD */
434 "flash0", /* FLASH0_VDD (emmc) */
435 "wifi", /* APIO2_VDD (sdio0) */
436 NULL,
437 "audio", /* APIO3_VDD */
438 "sdcard", /* SDMMC0_VDD (sdmmc) */
439 "gpio30", /* APIO1_VDD */
440 "gpio1830", /* APIO4_VDD (gpujtag) */
441 },
442 .init = rk3368_iodomain_init,
443};
444
445static const struct rockchip_iodomain_soc_data soc_data_rk3368_pmu = {
446 .grf_offset = 0x100,
447 .supply_names = {
448 NULL,
449 NULL,
450 NULL,
451 NULL,
452 "pmu", /*PMU IO domain*/
453 "vop", /*LCDC IO domain*/
454 },
455};
456
f447671b
DW
457static const struct rockchip_iodomain_soc_data soc_data_rk3399 = {
458 .grf_offset = 0xe640,
459 .supply_names = {
460 "bt656", /* APIO2_VDD */
461 "audio", /* APIO5_VDD */
462 "sdmmc", /* SDMMC0_VDD */
463 "gpio1830", /* APIO4_VDD */
464 },
465};
466
467static const struct rockchip_iodomain_soc_data soc_data_rk3399_pmu = {
468 .grf_offset = 0x180,
469 .supply_names = {
470 NULL,
471 NULL,
472 NULL,
473 NULL,
474 NULL,
475 NULL,
476 NULL,
477 NULL,
478 NULL,
479 "pmu1830", /* PMUIO2_VDD */
480 },
481 .init = rk3399_pmu_iodomain_init,
482};
483
28b05a64
JX
484static const struct rockchip_iodomain_soc_data soc_data_rk3568_pmu = {
485 .grf_offset = 0x140,
486 .supply_names = {
487 "pmuio1",
488 "pmuio2",
489 "vccio1",
490 "vccio2",
491 "vccio3",
492 "vccio4",
493 "vccio5",
494 "vccio6",
495 "vccio7",
496 },
497 .write = rk3568_iodomain_write,
498};
499
9d913e43
DW
500static const struct rockchip_iodomain_soc_data soc_data_rv1108 = {
501 .grf_offset = 0x404,
502 .supply_names = {
503 NULL,
504 NULL,
505 NULL,
506 NULL,
507 NULL,
508 NULL,
509 NULL,
510 NULL,
511 NULL,
512 NULL,
513 NULL,
514 "vccio1",
515 "vccio2",
516 "vccio3",
517 "vccio5",
518 "vccio6",
519 },
520
521};
522
523static const struct rockchip_iodomain_soc_data soc_data_rv1108_pmu = {
524 .grf_offset = 0x104,
525 .supply_names = {
526 "pmu",
527 },
528};
529
570ed4e5
JX
530static const struct rockchip_iodomain_soc_data soc_data_rv1126_pmu = {
531 .grf_offset = 0x140,
532 .supply_names = {
533 NULL,
534 "vccio1",
535 "vccio2",
536 "vccio3",
537 "vccio4",
538 "vccio5",
539 "vccio6",
540 "vccio7",
541 "pmuio0",
542 "pmuio1",
543 },
544};
545
662a9586 546static const struct of_device_id rockchip_iodomain_match[] = {
b8281fa7
DW
547 {
548 .compatible = "rockchip,px30-io-voltage-domain",
549 .data = (void *)&soc_data_px30
550 },
551 {
552 .compatible = "rockchip,px30-pmu-io-voltage-domain",
553 .data = (void *)&soc_data_px30_pmu
554 },
662a9586
HS
555 {
556 .compatible = "rockchip,rk3188-io-voltage-domain",
5a2772a8 557 .data = &soc_data_rk3188
662a9586 558 },
1a99d0c7
DW
559 {
560 .compatible = "rockchip,rk3228-io-voltage-domain",
5a2772a8 561 .data = &soc_data_rk3228
1a99d0c7 562 },
662a9586
HS
563 {
564 .compatible = "rockchip,rk3288-io-voltage-domain",
5a2772a8 565 .data = &soc_data_rk3288
662a9586 566 },
f0d70478
DW
567 {
568 .compatible = "rockchip,rk3308-io-voltage-domain",
569 .data = &soc_data_rk3308
570 },
7db36b1c
DW
571 {
572 .compatible = "rockchip,rk3328-io-voltage-domain",
5a2772a8 573 .data = &soc_data_rk3328
7db36b1c 574 },
3fc147e9
HS
575 {
576 .compatible = "rockchip,rk3368-io-voltage-domain",
5a2772a8 577 .data = &soc_data_rk3368
3fc147e9
HS
578 },
579 {
580 .compatible = "rockchip,rk3368-pmu-io-voltage-domain",
5a2772a8 581 .data = &soc_data_rk3368_pmu
3fc147e9 582 },
f447671b
DW
583 {
584 .compatible = "rockchip,rk3399-io-voltage-domain",
5a2772a8 585 .data = &soc_data_rk3399
f447671b
DW
586 },
587 {
588 .compatible = "rockchip,rk3399-pmu-io-voltage-domain",
5a2772a8 589 .data = &soc_data_rk3399_pmu
f447671b 590 },
28b05a64
JX
591 {
592 .compatible = "rockchip,rk3568-pmu-io-voltage-domain",
593 .data = &soc_data_rk3568_pmu
594 },
9d913e43
DW
595 {
596 .compatible = "rockchip,rv1108-io-voltage-domain",
5a2772a8 597 .data = &soc_data_rv1108
9d913e43
DW
598 },
599 {
600 .compatible = "rockchip,rv1108-pmu-io-voltage-domain",
5a2772a8 601 .data = &soc_data_rv1108_pmu
9d913e43 602 },
570ed4e5
JX
603 {
604 .compatible = "rockchip,rv1126-pmu-io-voltage-domain",
605 .data = &soc_data_rv1126_pmu
606 },
662a9586
HS
607 { /* sentinel */ },
608};
fa743d96 609MODULE_DEVICE_TABLE(of, rockchip_iodomain_match);
662a9586
HS
610
611static int rockchip_iodomain_probe(struct platform_device *pdev)
612{
613 struct device_node *np = pdev->dev.of_node;
614 const struct of_device_id *match;
615 struct rockchip_iodomain *iod;
bc19b9a8 616 struct device *parent;
662a9586
HS
617 int i, ret = 0;
618
619 if (!np)
620 return -ENODEV;
621
622 iod = devm_kzalloc(&pdev->dev, sizeof(*iod), GFP_KERNEL);
623 if (!iod)
624 return -ENOMEM;
625
626 iod->dev = &pdev->dev;
627 platform_set_drvdata(pdev, iod);
628
629 match = of_match_node(rockchip_iodomain_match, np);
5a2772a8 630 iod->soc_data = match->data;
662a9586 631
28b05a64
JX
632 if (iod->soc_data->write)
633 iod->write = iod->soc_data->write;
634 else
635 iod->write = rockchip_iodomain_write;
636
bc19b9a8
HS
637 parent = pdev->dev.parent;
638 if (parent && parent->of_node) {
639 iod->grf = syscon_node_to_regmap(parent->of_node);
640 } else {
641 dev_dbg(&pdev->dev, "falling back to old binding\n");
642 iod->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
643 }
644
662a9586
HS
645 if (IS_ERR(iod->grf)) {
646 dev_err(&pdev->dev, "couldn't find grf regmap\n");
647 return PTR_ERR(iod->grf);
648 }
649
650 for (i = 0; i < MAX_SUPPLIES; i++) {
651 const char *supply_name = iod->soc_data->supply_names[i];
652 struct rockchip_iodomain_supply *supply = &iod->supplies[i];
653 struct regulator *reg;
654 int uV;
655
656 if (!supply_name)
657 continue;
658
659 reg = devm_regulator_get_optional(iod->dev, supply_name);
660 if (IS_ERR(reg)) {
661 ret = PTR_ERR(reg);
662
663 /* If a supply wasn't specified, that's OK */
664 if (ret == -ENODEV)
665 continue;
666 else if (ret != -EPROBE_DEFER)
667 dev_err(iod->dev, "couldn't get regulator %s\n",
668 supply_name);
669 goto unreg_notify;
670 }
671
672 /* set initial correct value */
673 uV = regulator_get_voltage(reg);
674
675 /* must be a regulator we can get the voltage of */
676 if (uV < 0) {
677 dev_err(iod->dev, "Can't determine voltage: %s\n",
678 supply_name);
c2867b2e 679 ret = uV;
662a9586
HS
680 goto unreg_notify;
681 }
682
683 if (uV > MAX_VOLTAGE_3_3) {
684 dev_crit(iod->dev,
685 "%d uV is too high. May damage SoC!\n",
686 uV);
687 ret = -EINVAL;
688 goto unreg_notify;
689 }
690
691 /* setup our supply */
692 supply->idx = i;
693 supply->iod = iod;
694 supply->reg = reg;
695 supply->nb.notifier_call = rockchip_iodomain_notify;
696
28b05a64 697 ret = iod->write(supply, uV);
662a9586
HS
698 if (ret) {
699 supply->reg = NULL;
700 goto unreg_notify;
701 }
702
703 /* register regulator notifier */
704 ret = regulator_register_notifier(reg, &supply->nb);
705 if (ret) {
706 dev_err(&pdev->dev,
707 "regulator notifier request failed\n");
708 supply->reg = NULL;
709 goto unreg_notify;
710 }
711 }
712
713 if (iod->soc_data->init)
714 iod->soc_data->init(iod);
715
716 return 0;
717
718unreg_notify:
719 for (i = MAX_SUPPLIES - 1; i >= 0; i--) {
720 struct rockchip_iodomain_supply *io_supply = &iod->supplies[i];
721
722 if (io_supply->reg)
723 regulator_unregister_notifier(io_supply->reg,
724 &io_supply->nb);
725 }
726
727 return ret;
728}
729
20bd1191 730static void rockchip_iodomain_remove(struct platform_device *pdev)
662a9586
HS
731{
732 struct rockchip_iodomain *iod = platform_get_drvdata(pdev);
733 int i;
734
735 for (i = MAX_SUPPLIES - 1; i >= 0; i--) {
736 struct rockchip_iodomain_supply *io_supply = &iod->supplies[i];
737
738 if (io_supply->reg)
739 regulator_unregister_notifier(io_supply->reg,
740 &io_supply->nb);
741 }
662a9586
HS
742}
743
744static struct platform_driver rockchip_iodomain_driver = {
745 .probe = rockchip_iodomain_probe,
20bd1191 746 .remove_new = rockchip_iodomain_remove,
662a9586
HS
747 .driver = {
748 .name = "rockchip-iodomain",
749 .of_match_table = rockchip_iodomain_match,
750 },
751};
752
753module_platform_driver(rockchip_iodomain_driver);
754
755MODULE_DESCRIPTION("Rockchip IO-domain driver");
756MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
757MODULE_AUTHOR("Doug Anderson <dianders@chromium.org>");
758MODULE_LICENSE("GPL v2");