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