xref: /rk3399_rockchip-uboot/drivers/power/io-domain/rockchip-io-domain.c (revision 2a3fb7bb049d69d96f3bc7dae8caa756fdc8a613)
1 /* SPDX-License-Identifier:     GPL-2.0+ */
2 /*
3  * (C) Copyright 2018 Rockchip Electronics Co., Ltd
4  */
5 
6 #include <common.h>
7 #include <dm.h>
8 #include <dm/of_access.h>
9 #include <regmap.h>
10 #include <syscon.h>
11 #include <asm/arch/clock.h>
12 #include <fdtdec.h>
13 #include <linux/compat.h>
14 #include <linux/err.h>
15 #include <power/regulator.h>
16 
17 #define MAX_SUPPLIES		16
18 
19 /*
20  * The max voltage for 1.8V and 3.3V come from the Rockchip datasheet under
21  * "Recommended Operating Conditions" for "Digital GPIO".   When the typical
22  * is 3.3V the max is 3.6V.  When the typical is 1.8V the max is 1.98V.
23  *
24  * They are used like this:
25  * - If the voltage on a rail is above the "1.8" voltage (1.98V) we'll tell the
26  *   SoC we're at 3.3.
27  * - If the voltage on a rail is above the "3.3" voltage (3.6V) we'll consider
28  *   that to be an error.
29  */
30 #define MAX_VOLTAGE_1_8	1980000
31 #define MAX_VOLTAGE_3_3	3600000
32 
33 #define PX30_IO_VSEL			0x180
34 #define PX30_IO_VSEL_VCCIO6_SRC		BIT(0)
35 #define PX30_IO_VSEL_VCCIO6_SUPPLY_NUM	1
36 
37 #define RK3288_SOC_CON2			0x24c
38 #define RK3288_SOC_CON2_FLASH0		BIT(7)
39 #define RK3288_SOC_FLASH_SUPPLY_NUM	2
40 
41 #define RK3308_SOC_CON0			0x300
42 #define RK3308_SOC_CON0_VCCIO3		BIT(8)
43 #define RK3308_SOC_VCCIO3_SUPPLY_NUM	3
44 
45 #define RK3328_SOC_CON4			0x410
46 #define RK3328_SOC_CON4_VCCIO2		BIT(7)
47 #define RK3328_SOC_VCCIO2_SUPPLY_NUM	1
48 
49 #define RK3366_SOC_CON6			0x418
50 #define RK3366_SOC_CON6_FLASH0		BIT(14)
51 #define RK3366_SOC_FLASH_SUPPLY_NUM	2
52 
53 #define RK3368_SOC_CON15		0x43c
54 #define RK3368_SOC_CON15_FLASH0		BIT(14)
55 #define RK3368_SOC_FLASH_SUPPLY_NUM	2
56 
57 #define RK3399_PMUGRF_CON0		0x180
58 #define RK3399_PMUGRF_CON0_VSEL		BIT(8)
59 #define RK3399_PMUGRF_VSEL_SUPPLY_NUM	9
60 
61 struct rockchip_iodomain_priv;
62 
63 /**
64  * @supplies: voltage settings matching the register bits.
65  */
66 struct rockchip_iodomain_soc_data {
67 	int grf_offset;
68 	const char *supply_names[MAX_SUPPLIES];
69 	void (*init)(struct rockchip_iodomain_priv *iod);
70 };
71 
72 struct rockchip_iodomain_supply {
73 	struct rockchip_iodomain_priv *iod;
74 	struct udevice *reg;
75 	int idx;
76 };
77 
78 struct rockchip_iodomain_priv {
79 	struct regmap *regmap_base;
80 	struct rockchip_iodomain_soc_data *sdata;
81 	struct rockchip_iodomain_supply supplies[MAX_SUPPLIES];
82 };
83 
84 static int rockchip_ofdata_to_platdata(struct udevice *dev)
85 {
86 	struct rockchip_iodomain_priv *priv = dev_get_priv(dev);
87 	struct syscon_uc_info *syscon_priv;
88 	struct regmap *regmap;
89 
90 	syscon_priv = dev_get_uclass_priv(dev_get_parent(dev));
91 	regmap = syscon_priv->regmap;
92 	if (IS_ERR(regmap))
93 		return PTR_ERR(regmap);
94 
95 	priv->regmap_base = regmap;
96 
97 	return 0;
98 }
99 
100 static int rockchip_iodomain_write(struct rockchip_iodomain_supply *supply,
101 				   int uV)
102 {
103 	struct rockchip_iodomain_priv *priv = supply->iod;
104 	struct regmap *regmap = priv->regmap_base;
105 	u32 val;
106 	int ret;
107 
108 	/* set value bit */
109 	val = (uV > MAX_VOLTAGE_1_8) ? 0 : 1;
110 	val <<= supply->idx;
111 
112 	/* apply hiword-mask */
113 	val |= (BIT(supply->idx) << 16);
114 
115 	ret = regmap_write(regmap, priv->sdata->grf_offset, val);
116 	if (ret) {
117 		dev_err(priv->dev, "Couldn't write to GRF\n");
118 		return ret;
119 	}
120 
121 	return 0;
122 }
123 
124 static void px30_iodomain_init(struct rockchip_iodomain_priv *iod)
125 {
126 	int ret;
127 	u32 val;
128 
129 	/* if no VCCIO0 supply we should leave things alone */
130 	if (!iod->supplies[PX30_IO_VSEL_VCCIO6_SUPPLY_NUM].reg)
131 		return;
132 
133 	/*
134 	 * set vccio0 iodomain to also use this framework
135 	 * instead of a special gpio.
136 	 */
137 	val = PX30_IO_VSEL_VCCIO6_SRC | (PX30_IO_VSEL_VCCIO6_SRC << 16);
138 	ret = regmap_write(iod->regmap_base, PX30_IO_VSEL, val);
139 	if (ret < 0)
140 		dev_warn(iod->dev, "couldn't update vccio0 ctrl\n");
141 }
142 
143 static void rk3288_iodomain_init(struct rockchip_iodomain_priv *iod)
144 {
145 	int ret;
146 	u32 val;
147 
148 	/* if no flash supply we should leave things alone */
149 	if (!iod->supplies[RK3288_SOC_FLASH_SUPPLY_NUM].reg)
150 		return;
151 
152 	/*
153 	 * set flash0 iodomain to also use this framework
154 	 * instead of a special gpio.
155 	 */
156 	val = RK3288_SOC_CON2_FLASH0 | (RK3288_SOC_CON2_FLASH0 << 16);
157 	ret = regmap_write(iod->regmap_base, RK3288_SOC_CON2, val);
158 	if (ret < 0)
159 		dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
160 }
161 
162 static void rk3308_iodomain_init(struct rockchip_iodomain_priv *iod)
163 {
164 	int ret;
165 	u32 val;
166 
167 	/* if no vccio3 supply we should leave things alone */
168 	if (!iod->supplies[RK3308_SOC_VCCIO3_SUPPLY_NUM].reg)
169 		return;
170 
171 	/*
172 	 * set vccio3 iodomain to also use this framework
173 	 * instead of a special gpio.
174 	 */
175 	val = RK3308_SOC_CON0_VCCIO3 | (RK3308_SOC_CON0_VCCIO3 << 16);
176 	ret = regmap_write(iod->regmap_base, RK3308_SOC_CON0, val);
177 	if (ret < 0)
178 		dev_warn(iod->dev, "couldn't update vccio3 vsel ctrl\n");
179 }
180 
181 static void rk3328_iodomain_init(struct rockchip_iodomain_priv *iod)
182 {
183 	int ret;
184 	u32 val;
185 
186 	/* if no vccio2 supply we should leave things alone */
187 	if (!iod->supplies[RK3328_SOC_VCCIO2_SUPPLY_NUM].reg)
188 		return;
189 
190 	/*
191 	 * set vccio2 iodomain to also use this framework
192 	 * instead of a special gpio.
193 	 */
194 	val = RK3328_SOC_CON4_VCCIO2 | (RK3328_SOC_CON4_VCCIO2 << 16);
195 	ret = regmap_write(iod->regmap_base, RK3328_SOC_CON4, val);
196 	if (ret < 0)
197 		dev_warn(iod->dev, "couldn't update vccio2 vsel ctrl\n");
198 }
199 
200 static void rk3366_iodomain_init(struct rockchip_iodomain_priv *iod)
201 {
202 	int ret;
203 	u32 val;
204 
205 	/* if no flash supply we should leave things alone */
206 	if (!iod->supplies[RK3366_SOC_FLASH_SUPPLY_NUM].reg)
207 		return;
208 
209 	/*
210 	 * set flash0 iodomain to also use this framework
211 	 * instead of a special gpio.
212 	 */
213 	val = RK3366_SOC_CON6_FLASH0 | (RK3366_SOC_CON6_FLASH0 << 16);
214 	ret = regmap_write(iod->regmap_base, RK3368_SOC_CON15, val);
215 	if (ret < 0)
216 		dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
217 }
218 
219 static void rk3368_iodomain_init(struct rockchip_iodomain_priv *iod)
220 {
221 	int ret;
222 	u32 val;
223 
224 	/* if no flash supply we should leave things alone */
225 	if (!iod->supplies[RK3368_SOC_FLASH_SUPPLY_NUM].reg)
226 		return;
227 
228 	/*
229 	 * set flash0 iodomain to also use this framework
230 	 * instead of a special gpio.
231 	 */
232 	val = RK3368_SOC_CON15_FLASH0 | (RK3368_SOC_CON15_FLASH0 << 16);
233 	ret = regmap_write(iod->regmap_base, RK3368_SOC_CON15, val);
234 	if (ret < 0)
235 		dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
236 }
237 
238 static void rk3399_pmu_iodomain_init(struct rockchip_iodomain_priv *iod)
239 {
240 	int ret;
241 	u32 val;
242 
243 	/* if no pmu io supply we should leave things alone */
244 	if (!iod->supplies[RK3399_PMUGRF_VSEL_SUPPLY_NUM].reg)
245 		return;
246 
247 	/*
248 	 * set pmu io iodomain to also use this framework
249 	 * instead of a special gpio.
250 	 */
251 	val = RK3399_PMUGRF_CON0_VSEL | (RK3399_PMUGRF_CON0_VSEL << 16);
252 	ret = regmap_write(iod->regmap_base, RK3399_PMUGRF_CON0, val);
253 	if (ret < 0)
254 		dev_warn(iod->dev, "couldn't update pmu io iodomain ctrl\n");
255 }
256 
257 static const struct rockchip_iodomain_soc_data soc_data_px30 = {
258 	.grf_offset = 0x180,
259 	.supply_names = {
260 		NULL,
261 		"vccio6",
262 		"vccio1",
263 		"vccio2",
264 		"vccio3",
265 		"vccio4",
266 		"vccio5",
267 		"vccio-oscgpi",
268 	},
269 	.init = px30_iodomain_init,
270 };
271 
272 static const struct rockchip_iodomain_soc_data soc_data_px30_pmu = {
273 	.grf_offset = 0x100,
274 	.supply_names = {
275 		NULL,
276 		NULL,
277 		NULL,
278 		NULL,
279 		NULL,
280 		NULL,
281 		NULL,
282 		NULL,
283 		NULL,
284 		NULL,
285 		NULL,
286 		NULL,
287 		NULL,
288 		NULL,
289 		"pmuio1",
290 		"pmuio2",
291 	},
292 };
293 
294 /*
295  * On the rk3188 the io-domains are handled by a shared register with the
296  * lower 8 bits being still being continuing drive-strength settings.
297  */
298 static const struct rockchip_iodomain_soc_data soc_data_rk3188 = {
299 	.grf_offset = 0x104,
300 	.supply_names = {
301 		NULL,
302 		NULL,
303 		NULL,
304 		NULL,
305 		NULL,
306 		NULL,
307 		NULL,
308 		NULL,
309 		"ap0",
310 		"ap1",
311 		"cif",
312 		"flash",
313 		"vccio0",
314 		"vccio1",
315 		"lcdc0",
316 		"lcdc1",
317 	},
318 };
319 
320 static const struct rockchip_iodomain_soc_data soc_data_rk322x = {
321 	.grf_offset = 0x418,
322 	.supply_names = {
323 		"vccio1",
324 		"vccio2",
325 		"vccio3",
326 		"vccio4",
327 	},
328 };
329 
330 static const struct rockchip_iodomain_soc_data soc_data_rk3288 = {
331 	.grf_offset = 0x380,
332 	.supply_names = {
333 		"lcdc",		/* LCDC_VDD */
334 		"dvp",		/* DVPIO_VDD */
335 		"flash0",	/* FLASH0_VDD (emmc) */
336 		"flash1",	/* FLASH1_VDD (sdio1) */
337 		"wifi",		/* APIO3_VDD  (sdio0) */
338 		"bb",		/* APIO5_VDD */
339 		"audio",	/* APIO4_VDD */
340 		"sdcard",	/* SDMMC0_VDD (sdmmc) */
341 		"gpio30",	/* APIO1_VDD */
342 		"gpio1830",	/* APIO2_VDD */
343 	},
344 	.init = rk3288_iodomain_init,
345 };
346 
347 static const struct rockchip_iodomain_soc_data soc_data_rk3308 = {
348 	.grf_offset = 0x300,
349 	.supply_names = {
350 		"vccio0",
351 		"vccio1",
352 		"vccio2",
353 		"vccio3",
354 		"vccio4",
355 		"vccio5",
356 	},
357 	.init = rk3308_iodomain_init,
358 };
359 
360 static const struct rockchip_iodomain_soc_data soc_data_rk3328 = {
361 	.grf_offset = 0x410,
362 	.supply_names = {
363 		"vccio1",
364 		"vccio2",
365 		"vccio3",
366 		"vccio4",
367 		"vccio5",
368 		"vccio6",
369 		"pmuio",
370 	},
371 	.init = rk3328_iodomain_init,
372 };
373 
374 static const struct rockchip_iodomain_soc_data soc_data_rk3366 = {
375 	.grf_offset = 0x900,
376 	.supply_names = {
377 		"lcdc",         /* LCDC_IOVDD */
378 		"dvpts",        /* DVP_IOVDD */
379 		"flash",        /* FLASH_IOVDD (emmc) */
380 		"wifibt",       /* APIO1_IOVDD */
381 		NULL,
382 		"audio",        /* AUDIO_IODVDD */
383 		"sdcard",       /* SDMMC_IOVDD (sdmmc) */
384 		"tphdsor",      /* APIO2_IOVDD */
385 	},
386 	.init = rk3366_iodomain_init,
387 };
388 
389 static const struct rockchip_iodomain_soc_data soc_data_rk3368 = {
390 	.grf_offset = 0x900,
391 	.supply_names = {
392 		NULL,		/* reserved */
393 		"dvp",		/* DVPIO_VDD */
394 		"flash0",	/* FLASH0_VDD (emmc) */
395 		"wifi",		/* APIO2_VDD (sdio0) */
396 		NULL,
397 		"audio",	/* APIO3_VDD */
398 		"sdcard",	/* SDMMC0_VDD (sdmmc) */
399 		"gpio30",	/* APIO1_VDD */
400 		"gpio1830",	/* APIO4_VDD (gpujtag) */
401 	},
402 	.init = rk3368_iodomain_init,
403 };
404 
405 static const struct rockchip_iodomain_soc_data soc_data_rk3368_pmu = {
406 	.grf_offset = 0x100,
407 	.supply_names = {
408 		NULL,
409 		NULL,
410 		NULL,
411 		NULL,
412 		"pmu",	        /*PMU IO domain*/
413 		"vop",	        /*LCDC IO domain*/
414 	},
415 };
416 
417 static const struct rockchip_iodomain_soc_data soc_data_rk3399 = {
418 	.grf_offset = 0xe640,
419 	.supply_names = {
420 		"bt656",		/* APIO2_VDD */
421 		"audio",		/* APIO5_VDD */
422 		"sdmmc",		/* SDMMC0_VDD */
423 		"gpio1830",		/* APIO4_VDD */
424 	},
425 };
426 
427 static const struct rockchip_iodomain_soc_data soc_data_rk3399_pmu = {
428 	.grf_offset = 0x180,
429 	.supply_names = {
430 		NULL,
431 		NULL,
432 		NULL,
433 		NULL,
434 		NULL,
435 		NULL,
436 		NULL,
437 		NULL,
438 		NULL,
439 		"pmu1830",		/* PMUIO2_VDD */
440 	},
441 	.init = rk3399_pmu_iodomain_init,
442 };
443 
444 static const struct rockchip_iodomain_soc_data soc_data_rv1108 = {
445 	.grf_offset = 0x404,
446 	.supply_names = {
447 		NULL,
448 		NULL,
449 		NULL,
450 		NULL,
451 		NULL,
452 		NULL,
453 		NULL,
454 		NULL,
455 		NULL,
456 		NULL,
457 		NULL,
458 		"vccio1",
459 		"vccio2",
460 		"vccio3",
461 		"vccio5",
462 		"vccio6",
463 	},
464 
465 };
466 
467 static const struct rockchip_iodomain_soc_data soc_data_rv1108_pmu = {
468 	.grf_offset = 0x104,
469 	.supply_names = {
470 		"pmu",
471 	},
472 };
473 
474 static const struct rockchip_iodomain_soc_data soc_data_rv1126_pmu = {
475 	.grf_offset = 0x140,
476 	.supply_names = {
477 		NULL,
478 		"vccio1",
479 		"vccio2",
480 		"vccio3",
481 		"vccio4",
482 		"vccio5",
483 		"vccio6",
484 		"vccio7",
485 		"pmuio0",
486 		"pmuio1",
487 	},
488 };
489 
490 static struct udevice *of_get_regulator(ofnode node, const char *supply)
491 {
492 	char sname[32]; /* 32 is max size of property name */
493 	struct udevice *sudev = NULL;
494 	ofnode snode;
495 	u32 phandle;
496 	int ret;
497 
498 	snprintf(sname, 32, "%s-supply", supply);
499 
500 	/* Get regulator and clk */
501 	if (!ofnode_read_u32(node, sname, &phandle)) {
502 		snode = ofnode_get_by_phandle(phandle);
503 		ret = regulator_get_by_devname(snode.np->name, &sudev);
504 		if (ret) {
505 			printf("%s: Get (%s) regulator: %s failed, ret=%d\n",
506 			       __func__,
507 			       sname, snode.np->full_name, ret);
508 			return NULL;
509 		}
510 		debug("IO-DOMAIN: supply: %s\n", snode.np->full_name);
511 	}
512 
513 	return sudev;
514 }
515 
516 static int rockchip_iodomain_probe(struct udevice *dev)
517 {
518 	struct rockchip_iodomain_priv *priv = dev_get_priv(dev);
519 	struct rockchip_iodomain_soc_data *sdata;
520 	int i, ret;
521 
522 	sdata = (struct rockchip_iodomain_soc_data *)dev_get_driver_data(dev);
523 	priv->sdata = sdata;
524 
525 	if (!priv->regmap_base)
526 		return -1;
527 
528 	for (i = 0; i < MAX_SUPPLIES; i++) {
529 		const char *supply_name = priv->sdata->supply_names[i];
530 		struct rockchip_iodomain_supply *supply = &priv->supplies[i];
531 		struct udevice *reg;
532 		u32 uV;
533 
534 		if (!supply_name)
535 			continue;
536 
537 		reg = of_get_regulator(dev_ofnode(dev), supply_name);
538 		if (!reg)
539 			continue;
540 
541 		uV = regulator_get_value(reg);
542 		if (uV <= 0) {
543 			printf("voltage(%d uV) is invalid from %s\n", uV, reg->name);
544 			continue;
545 		}
546 
547 		if (uV > MAX_VOLTAGE_3_3) {
548 			printf("%d uV is too high from %s\n", uV, reg->name);
549 			continue;
550 		}
551 
552 		/* setup our supply */
553 		supply->idx = i;
554 		supply->iod = priv;
555 		supply->reg = reg;
556 
557 		ret = rockchip_iodomain_write(supply, uV);
558 		if (ret)
559 			supply->reg = NULL;
560 	}
561 
562 	if (priv->sdata->init)
563 		priv->sdata->init(priv);
564 
565 	return 0;
566 }
567 
568 static const struct udevice_id rockchip_iodomain_match[] = {
569 	{
570 		.compatible = "rockchip,px30-io-voltage-domain",
571 		.data = (ulong)&soc_data_px30
572 	},
573 	{
574 		.compatible = "rockchip,px30-pmu-io-voltage-domain",
575 		.data = (ulong)&soc_data_px30_pmu
576 	},
577 	{
578 		.compatible = "rockchip,rk3188-io-voltage-domain",
579 		.data = (ulong)&soc_data_rk3188
580 	},
581 	{
582 		.compatible = "rockchip,rk322x-io-voltage-domain",
583 		.data = (ulong)&soc_data_rk322x
584 	},
585 	{
586 		.compatible = "rockchip,rk3288-io-voltage-domain",
587 		.data = (ulong)&soc_data_rk3288
588 	},
589 	{
590 		.compatible = "rockchip,rk3308-io-voltage-domain",
591 		.data = (ulong)&soc_data_rk3308
592 	},
593 	{
594 		.compatible = "rockchip,rk3328-io-voltage-domain",
595 		.data = (ulong)&soc_data_rk3328
596 	},
597 	{
598 		.compatible = "rockchip,rk3366-io-voltage-domain",
599 		.data = (ulong)&soc_data_rk3366
600 	},
601 	{
602 		.compatible = "rockchip,rk3368-io-voltage-domain",
603 		.data = (ulong)&soc_data_rk3368
604 	},
605 	{
606 		.compatible = "rockchip,rk3368-pmu-io-voltage-domain",
607 		.data = (ulong)&soc_data_rk3368_pmu
608 	},
609 	{
610 		.compatible = "rockchip,rk3399-io-voltage-domain",
611 		.data = (ulong)&soc_data_rk3399
612 	},
613 	{
614 		.compatible = "rockchip,rk3399-pmu-io-voltage-domain",
615 		.data = (ulong)&soc_data_rk3399_pmu
616 	},
617 	{
618 		.compatible = "rockchip,rv1108-io-voltage-domain",
619 		.data = (ulong)&soc_data_rv1108
620 	},
621 	{
622 		.compatible = "rockchip,rv1108-pmu-io-voltage-domain",
623 		.data = (ulong)&soc_data_rv1108_pmu
624 	},
625 	{
626 		.compatible = "rockchip,rv1126-pmu-io-voltage-domain",
627 		.data = (ulong)&soc_data_rv1126_pmu
628 	},
629 	{ /* sentinel */ },
630 };
631 
632 U_BOOT_DRIVER(io_domain) = {
633 	.name		= "io_domain",
634 	.id		= UCLASS_IO_DOMAIN,
635 	.of_match	= rockchip_iodomain_match,
636 	.priv_auto_alloc_size = sizeof(struct rockchip_iodomain_priv),
637 	.ofdata_to_platdata	= rockchip_ofdata_to_platdata,
638 	.probe		= rockchip_iodomain_probe,
639 };
640