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