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