xref: /linux/drivers/soc/rockchip/io-domain.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Rockchip IO Voltage Domain driver
4  *
5  * Copyright 2014 MundoReader S.L.
6  * Copyright 2014 Google, Inc.
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 
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 
38 #define RK3288_SOC_CON2			0x24c
39 #define RK3288_SOC_CON2_FLASH0		BIT(7)
40 #define RK3288_SOC_FLASH_SUPPLY_NUM	2
41 
42 #define RK3308_SOC_CON0			0x300
43 #define RK3308_SOC_CON0_VCCIO3		BIT(8)
44 #define RK3308_SOC_VCCIO3_SUPPLY_NUM	3
45 
46 #define RK3328_SOC_CON4			0x410
47 #define RK3328_SOC_CON4_VCCIO2		BIT(7)
48 #define RK3328_SOC_VCCIO2_SUPPLY_NUM	1
49 
50 #define RK3368_SOC_CON15		0x43c
51 #define RK3368_SOC_CON15_FLASH0		BIT(14)
52 #define RK3368_SOC_FLASH_SUPPLY_NUM	2
53 
54 #define RK3399_PMUGRF_CON0		0x180
55 #define RK3399_PMUGRF_CON0_VSEL		BIT(8)
56 #define RK3399_PMUGRF_VSEL_SUPPLY_NUM	9
57 
58 #define RK3568_PMU_GRF_IO_VSEL0		(0x0140)
59 #define RK3568_PMU_GRF_IO_VSEL1		(0x0144)
60 #define RK3568_PMU_GRF_IO_VSEL2		(0x0148)
61 
62 struct rockchip_iodomain;
63 
64 struct rockchip_iodomain_supply {
65 	struct rockchip_iodomain *iod;
66 	struct regulator *reg;
67 	struct notifier_block nb;
68 	int idx;
69 };
70 
71 struct 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 
78 struct rockchip_iodomain {
79 	struct device *dev;
80 	struct regmap *grf;
81 	const struct rockchip_iodomain_soc_data *soc_data;
82 	struct rockchip_iodomain_supply supplies[MAX_SUPPLIES];
83 	int (*write)(struct rockchip_iodomain_supply *supply, int uV);
84 };
85 
86 static 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;
122 	}
123 
124 	return 0;
125 }
126 
127 static 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 
148 static 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 
190 	ret = supply->iod->write(supply, uV);
191 	if (ret && event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE)
192 		return NOTIFY_BAD;
193 
194 	dev_dbg(supply->iod->dev, "Setting to %d done\n", uV);
195 	return NOTIFY_OK;
196 }
197 
198 static void px30_iodomain_init(struct rockchip_iodomain *iod)
199 {
200 	int ret;
201 	u32 val;
202 
203 	/* if no VCCIO6 supply we should leave things alone */
204 	if (!iod->supplies[PX30_IO_VSEL_VCCIO6_SUPPLY_NUM].reg)
205 		return;
206 
207 	/*
208 	 * set vccio6 iodomain to also use this framework
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)
214 		dev_warn(iod->dev, "couldn't update vccio6 ctrl\n");
215 }
216 
217 static 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 
236 static 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 
255 static 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 
274 static 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 
293 static 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 
312 static 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 
327 static 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 
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  */
353 static 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 
375 static 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 
385 static 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 
402 static 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 
415 static 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 
429 static 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 
445 static 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 
457 static 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 
467 static 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 
484 static 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 
500 static 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 
523 static const struct rockchip_iodomain_soc_data soc_data_rv1108_pmu = {
524 	.grf_offset = 0x104,
525 	.supply_names = {
526 		"pmu",
527 	},
528 };
529 
530 static 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 
546 static const struct of_device_id rockchip_iodomain_match[] = {
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 	},
555 	{
556 		.compatible = "rockchip,rk3188-io-voltage-domain",
557 		.data = &soc_data_rk3188
558 	},
559 	{
560 		.compatible = "rockchip,rk3228-io-voltage-domain",
561 		.data = &soc_data_rk3228
562 	},
563 	{
564 		.compatible = "rockchip,rk3288-io-voltage-domain",
565 		.data = &soc_data_rk3288
566 	},
567 	{
568 		.compatible = "rockchip,rk3308-io-voltage-domain",
569 		.data = &soc_data_rk3308
570 	},
571 	{
572 		.compatible = "rockchip,rk3328-io-voltage-domain",
573 		.data = &soc_data_rk3328
574 	},
575 	{
576 		.compatible = "rockchip,rk3368-io-voltage-domain",
577 		.data = &soc_data_rk3368
578 	},
579 	{
580 		.compatible = "rockchip,rk3368-pmu-io-voltage-domain",
581 		.data = &soc_data_rk3368_pmu
582 	},
583 	{
584 		.compatible = "rockchip,rk3399-io-voltage-domain",
585 		.data = &soc_data_rk3399
586 	},
587 	{
588 		.compatible = "rockchip,rk3399-pmu-io-voltage-domain",
589 		.data = &soc_data_rk3399_pmu
590 	},
591 	{
592 		.compatible = "rockchip,rk3568-pmu-io-voltage-domain",
593 		.data = &soc_data_rk3568_pmu
594 	},
595 	{
596 		.compatible = "rockchip,rv1108-io-voltage-domain",
597 		.data = &soc_data_rv1108
598 	},
599 	{
600 		.compatible = "rockchip,rv1108-pmu-io-voltage-domain",
601 		.data = &soc_data_rv1108_pmu
602 	},
603 	{
604 		.compatible = "rockchip,rv1126-pmu-io-voltage-domain",
605 		.data = &soc_data_rv1126_pmu
606 	},
607 	{ /* sentinel */ },
608 };
609 MODULE_DEVICE_TABLE(of, rockchip_iodomain_match);
610 
611 static 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;
616 	struct device *parent;
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);
630 	iod->soc_data = match->data;
631 
632 	if (iod->soc_data->write)
633 		iod->write = iod->soc_data->write;
634 	else
635 		iod->write = rockchip_iodomain_write;
636 
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 
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);
679 			ret = uV;
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 
697 		ret = iod->write(supply, uV);
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 
718 unreg_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 
730 static void rockchip_iodomain_remove(struct platform_device *pdev)
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 	}
742 }
743 
744 static struct platform_driver rockchip_iodomain_driver = {
745 	.probe   = rockchip_iodomain_probe,
746 	.remove_new = rockchip_iodomain_remove,
747 	.driver  = {
748 		.name  = "rockchip-iodomain",
749 		.of_match_table = rockchip_iodomain_match,
750 	},
751 };
752 
753 module_platform_driver(rockchip_iodomain_driver);
754 
755 MODULE_DESCRIPTION("Rockchip IO-domain driver");
756 MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
757 MODULE_AUTHOR("Doug Anderson <dianders@chromium.org>");
758 MODULE_LICENSE("GPL v2");
759