xref: /openbsd-src/sys/dev/fdt/rkpinctrl.c (revision 1ad61ae0a79a724d2d3ec69e69c8e1d1ff6b53a0)
1 /*	$OpenBSD: rkpinctrl.c,v 1.14 2023/09/22 01:10:44 jsg Exp $	*/
2 /*
3  * Copyright (c) 2017, 2018 Mark Kettenis <kettenis@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/device.h>
21 #include <sys/malloc.h>
22 
23 #include <machine/intr.h>
24 #include <machine/bus.h>
25 #include <machine/fdt.h>
26 
27 #include <dev/ofw/openfirm.h>
28 #include <dev/ofw/ofw_misc.h>
29 #include <dev/ofw/ofw_pinctrl.h>
30 #include <dev/ofw/fdt.h>
31 
32 #include <machine/simplebusvar.h>
33 
34 /* Pin numbers (from devicetree bindings) */
35 #define RK_PA0		0
36 #define RK_PA1		1
37 #define RK_PA2		2
38 #define RK_PA3		3
39 #define RK_PA4		4
40 #define RK_PA5		5
41 #define RK_PA6		6
42 #define RK_PA7		7
43 #define RK_PB0		8
44 #define RK_PB1		9
45 #define RK_PB2		10
46 #define RK_PB3		11
47 #define RK_PB4		12
48 #define RK_PB5		13
49 #define RK_PB6		14
50 #define RK_PB7		15
51 #define RK_PC0		16
52 #define RK_PC1		17
53 #define RK_PC2		18
54 #define RK_PC3		19
55 #define RK_PC4		20
56 #define RK_PC5		21
57 #define RK_PC6		22
58 #define RK_PC7		23
59 #define RK_PD0		24
60 #define RK_PD1		25
61 #define RK_PD2		26
62 #define RK_PD3		27
63 #define RK_PD4		28
64 #define RK_PD5		29
65 #define RK_PD6		30
66 #define RK_PD7		31
67 
68 /* RK3288 registers */
69 #define RK3288_GRF_GPIO1A_IOMUX		0x0000
70 #define RK3288_PMUGRF_GPIO0A_IOMUX	0x0084
71 
72 /* RK3308 registers */
73 #define RK3308_GRF_GPIO0A_IOMUX		0x0000
74 
75 /* RK3328 registers */
76 #define RK3328_GRF_GPIO0A_IOMUX		0x0000
77 
78 /* RK3399 registers */
79 #define RK3399_GRF_GPIO2A_IOMUX		0xe000
80 #define RK3399_PMUGRF_GPIO0A_IOMUX	0x0000
81 
82 /* RK3568 registers */
83 #define RK3568_GRF_GPIO1A_IOMUX_L	0x0000
84 #define RK3568_GRF_GPIO1A_P		0x0080
85 #define RK3568_GRF_GPIO1A_IE		0x00c0
86 #define RK3568_GRF_GPIO1A_DS_0		0x0200
87 #define RK3568_PMUGRF_GPIO0A_IOMUX_L	0x0000
88 #define RK3568_PMUGRF_GPIO0A_P		0x0020
89 #define RK3568_PMUGRF_GPIO0A_IE		0x0030
90 #define RK3568_PMUGRF_GPIO0A_DS_0	0x0070
91 
92 struct rockchip_route_table {
93 	u_int bank : 3;
94 	u_int idx : 5;
95 	u_int mux : 3;
96 	u_int grf : 1;
97 #define ROUTE_GRF	0
98 #define ROUTE_PMU	1
99 	uint16_t reg;
100 	uint32_t val;
101 #define ROUTE_VAL(bit, val)	((0x3 << (bit)) << 16 | ((val) << (bit)))
102 };
103 
104 struct rkpinctrl_softc {
105 	struct simplebus_softc	sc_sbus;
106 
107 	struct regmap		*sc_grf;
108 	struct regmap		*sc_pmu;
109 };
110 
111 int	rkpinctrl_match(struct device *, void *, void *);
112 void	rkpinctrl_attach(struct device *, struct device *, void *);
113 
114 const struct cfattach	rkpinctrl_ca = {
115 	sizeof (struct rkpinctrl_softc), rkpinctrl_match, rkpinctrl_attach
116 };
117 
118 struct cfdriver rkpinctrl_cd = {
119 	NULL, "rkpinctrl", DV_DULL
120 };
121 
122 int	rk3288_pinctrl(uint32_t, void *);
123 int	rk3308_pinctrl(uint32_t, void *);
124 int	rk3328_pinctrl(uint32_t, void *);
125 int	rk3399_pinctrl(uint32_t, void *);
126 int	rk3568_pinctrl(uint32_t, void *);
127 int	rk3588_pinctrl(uint32_t, void *);
128 
129 int
130 rkpinctrl_match(struct device *parent, void *match, void *aux)
131 {
132 	struct fdt_attach_args *faa = aux;
133 
134 	return (OF_is_compatible(faa->fa_node, "rockchip,rk3288-pinctrl") ||
135 	    OF_is_compatible(faa->fa_node, "rockchip,rk3308-pinctrl") ||
136 	    OF_is_compatible(faa->fa_node, "rockchip,rk3328-pinctrl") ||
137 	    OF_is_compatible(faa->fa_node, "rockchip,rk3399-pinctrl") ||
138 	    OF_is_compatible(faa->fa_node, "rockchip,rk3568-pinctrl") ||
139 	    OF_is_compatible(faa->fa_node, "rockchip,rk3588-pinctrl"));
140 }
141 
142 void
143 rkpinctrl_attach(struct device *parent, struct device *self, void *aux)
144 {
145 	struct rkpinctrl_softc *sc = (struct rkpinctrl_softc *)self;
146 	struct fdt_attach_args *faa = aux;
147 	uint32_t grf, pmu;
148 
149 	grf = OF_getpropint(faa->fa_node, "rockchip,grf", 0);
150 	pmu = OF_getpropint(faa->fa_node, "rockchip,pmu", 0);
151 	sc->sc_grf = regmap_byphandle(grf);
152 	sc->sc_pmu = regmap_byphandle(pmu);
153 
154 	if (sc->sc_grf == NULL && sc->sc_pmu == NULL) {
155 		printf(": no registers\n");
156 		return;
157 	}
158 
159 	if (OF_is_compatible(faa->fa_node, "rockchip,rk3288-pinctrl"))
160 		pinctrl_register(faa->fa_node, rk3288_pinctrl, sc);
161 	else if (OF_is_compatible(faa->fa_node, "rockchip,rk3308-pinctrl"))
162 		pinctrl_register(faa->fa_node, rk3308_pinctrl, sc);
163 	else if (OF_is_compatible(faa->fa_node, "rockchip,rk3328-pinctrl"))
164 		pinctrl_register(faa->fa_node, rk3328_pinctrl, sc);
165 	else if (OF_is_compatible(faa->fa_node, "rockchip,rk3399-pinctrl"))
166 		pinctrl_register(faa->fa_node, rk3399_pinctrl, sc);
167 	else if (OF_is_compatible(faa->fa_node, "rockchip,rk3568-pinctrl"))
168 		pinctrl_register(faa->fa_node, rk3568_pinctrl, sc);
169 	else
170 		pinctrl_register(faa->fa_node, rk3588_pinctrl, sc);
171 
172 	/* Attach GPIO banks. */
173 	simplebus_attach(parent, &sc->sc_sbus.sc_dev, faa);
174 }
175 
176 /*
177  * Rockchip RK3288
178  */
179 
180 int
181 rk3288_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
182 {
183 	int node;
184 
185 	node = OF_getnodebyphandle(phandle);
186 	if (node == 0)
187 		return -1;
188 
189 	/* XXX */
190 	if (bank == 0)
191 		return -1;
192 
193 	if (OF_getproplen(node, "bias-disable") == 0)
194 		return 0;
195 	if (OF_getproplen(node, "bias-pull-up") == 0)
196 		return 1;
197 	if (OF_getproplen(node, "bias-pull-down") == 0)
198 		return 2;
199 
200 	return -1;
201 }
202 
203 int
204 rk3288_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
205 {
206 	int strength, level;
207 	int levels[4] = { 2, 4, 8, 12 };
208 	int node;
209 
210 	node = OF_getnodebyphandle(phandle);
211 	if (node == 0)
212 		return -1;
213 
214 	/* XXX */
215 	if (bank == 0)
216 		return -1;
217 
218 	strength = OF_getpropint(node, "drive-strength", -1);
219 	if (strength == -1)
220 		return -1;
221 
222 	/* Convert drive strength to level. */
223 	for (level = 3; level >= 0; level--) {
224 		if (strength >= levels[level])
225 			break;
226 	}
227 	return level;
228 }
229 
230 int
231 rk3288_pinctrl(uint32_t phandle, void *cookie)
232 {
233 	struct rkpinctrl_softc *sc = cookie;
234 	uint32_t *pins;
235 	int node, len, i;
236 
237 	KASSERT(sc->sc_grf);
238 	KASSERT(sc->sc_pmu);
239 
240 	node = OF_getnodebyphandle(phandle);
241 	if (node == 0)
242 		return -1;
243 
244 	len = OF_getproplen(node, "rockchip,pins");
245 	if (len <= 0)
246 		return -1;
247 
248 	pins = malloc(len, M_TEMP, M_WAITOK);
249 	if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
250 		goto fail;
251 
252 	for (i = 0; i < len / sizeof(uint32_t); i += 4) {
253 		struct regmap *rm;
254 		bus_size_t base, off;
255 		uint32_t bank, idx, mux;
256 		int pull, strength;
257 		uint32_t mask, bits;
258 		int s;
259 
260 		bank = pins[i];
261 		idx = pins[i + 1];
262 		mux = pins[i + 2];
263 		pull = rk3288_pull(bank, idx, pins[i + 3]);
264 		strength = rk3288_strength(bank, idx, pins[i + 3]);
265 
266 		if (bank > 8 || idx > 32 || mux > 7)
267 			continue;
268 
269 		/* Bank 0 lives in the PMU. */
270 		if (bank < 1) {
271 			rm = sc->sc_pmu;
272 			base = RK3288_PMUGRF_GPIO0A_IOMUX;
273 		} else {
274 			rm = sc->sc_grf;
275 			base = RK3288_GRF_GPIO1A_IOMUX - 0x10;
276 		}
277 
278 		s = splhigh();
279 
280 		/* IOMUX control */
281 		off = bank * 0x10 + (idx / 8) * 0x04;
282 
283 		/* GPIO3D, GPIO4A and GPIO4B are special. */
284 		if ((bank == 3 && idx >= 24) || (bank == 4 && idx < 16)) {
285 			mask = (0x7 << ((idx % 4) * 4));
286 			bits = (mux << ((idx % 4) * 4));
287 		} else {
288 			mask = (0x3 << ((idx % 8) * 2));
289 			bits = (mux << ((idx % 8) * 2));
290 		}
291 		if (bank > 3 || (bank == 3 && idx >= 28))
292 			off += 0x04;
293 		if (bank > 4 || (bank == 4 && idx >= 4))
294 			off += 0x04;
295 		if (bank > 4 || (bank == 4 && idx >= 12))
296 			off += 0x04;
297 		regmap_write_4(rm, base + off, mask << 16 | bits);
298 
299 		/* GPIO pad pull down and pull up control */
300 		if (pull >= 0) {
301 			off = 0x140 + bank * 0x10 + (idx / 8) * 0x04;
302 			mask = (0x3 << ((idx % 8) * 2));
303 			bits = (pull << ((idx % 8) * 2));
304 			regmap_write_4(rm, base + off, mask << 16 | bits);
305 		}
306 
307 		/* GPIO drive strength control */
308 		if (strength >= 0) {
309 			off = 0x1c0 + bank * 0x10 + (idx / 8) * 0x04;
310 			mask = (0x3 << ((idx % 8) * 2));
311 			bits = (strength << ((idx % 8) * 2));
312 			regmap_write_4(rm, base + off, mask << 16 | bits);
313 		}
314 
315 		splx(s);
316 	}
317 
318 	free(pins, M_TEMP, len);
319 	return 0;
320 
321 fail:
322 	free(pins, M_TEMP, len);
323 	return -1;
324 }
325 
326 /*
327  * Rockchip RK3308
328  */
329 
330 int
331 rk3308_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
332 {
333 	int node;
334 
335 	node = OF_getnodebyphandle(phandle);
336 	if (node == 0)
337 		return -1;
338 
339 	if (OF_getproplen(node, "bias-disable") == 0)
340 		return 0;
341 	if (OF_getproplen(node, "bias-pull-up") == 0)
342 		return 1;
343 	if (OF_getproplen(node, "bias-pull-down") == 0)
344 		return 2;
345 
346 	return -1;
347 }
348 
349 int
350 rk3308_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
351 {
352 	int strength, level;
353 	int levels[4] = { 2, 4, 8, 12 };
354 	int node;
355 
356 	node = OF_getnodebyphandle(phandle);
357 	if (node == 0)
358 		return -1;
359 
360 	strength = OF_getpropint(node, "drive-strength", -1);
361 	if (strength == -1)
362 		return -1;
363 
364 	/* Convert drive strength to level. */
365 	for (level = 3; level >= 0; level--) {
366 		if (strength >= levels[level])
367 			break;
368 	}
369 	return level;
370 }
371 
372 int
373 rk3308_pinctrl(uint32_t phandle, void *cookie)
374 {
375 	struct rkpinctrl_softc *sc = cookie;
376 	uint32_t *pins;
377 	int node, len, i;
378 
379 	KASSERT(sc->sc_grf);
380 
381 	node = OF_getnodebyphandle(phandle);
382 	if (node == 0)
383 		return -1;
384 
385 	len = OF_getproplen(node, "rockchip,pins");
386 	if (len <= 0)
387 		return -1;
388 
389 	pins = malloc(len, M_TEMP, M_WAITOK);
390 	if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
391 		goto fail;
392 
393 	for (i = 0; i < len / sizeof(uint32_t); i += 4) {
394 		struct regmap *rm = sc->sc_grf;
395 		bus_size_t base, off;
396 		uint32_t bank, idx, mux;
397 		int pull, strength;
398 		uint32_t mask, bits;
399 		int s;
400 
401 		bank = pins[i];
402 		idx = pins[i + 1];
403 		mux = pins[i + 2];
404 		pull = rk3308_pull(bank, idx, pins[i + 3]);
405 		strength = rk3308_strength(bank, idx, pins[i + 3]);
406 
407 		if (bank > 4 || idx > 32 || mux > 7)
408 			continue;
409 
410 		base = RK3308_GRF_GPIO0A_IOMUX;
411 
412 		s = splhigh();
413 
414 		/* IOMUX control */
415 		off = bank * 0x20 + (idx / 8) * 0x08;
416 
417 		/* GPIO1B, GPIO1C and GPIO3B are special. */
418 		if ((bank == 1) && (idx == 14)) {
419 			mask = (0xf << 12);
420 			bits = (mux << 12);
421 		} else if ((bank == 1) && (idx == 15)) {
422 			off += 4;
423 			mask = 0x3;
424 			bits = mux;
425 		} else if ((bank == 1) && (idx >= 16 && idx <= 17)) {
426 			mask = (0x3 << ((idx - 16) * 2));
427 			bits = (mux << ((idx - 16) * 2));
428 		} else if ((bank == 1) && (idx >= 18 && idx <= 20)) {
429 			mask = (0xf << (((idx - 18) * 4) + 4));
430 			bits = (mux << (((idx - 18) * 4) + 4));
431 		} else if ((bank == 1) && (idx >= 21 && idx <= 23)) {
432 			off += 4;
433 			mask = (0xf << ((idx - 21) * 4));
434 			bits = (mux << ((idx - 21) * 4));
435 		} else if ((bank == 3) && (idx >= 12 && idx <= 13)) {
436 			mask = (0xf << (((idx - 12) * 4) + 8));
437 			bits = (mux << (((idx - 12) * 4) + 8));
438 		} else {
439 			mask = (0x3 << ((idx % 8) * 2));
440 			bits = (mux << ((idx % 8) * 2));
441 		}
442 		regmap_write_4(rm, base + off, mask << 16 | bits);
443 
444 		/* GPIO pad pull down and pull up control */
445 		if (pull >= 0) {
446 			off = 0xa0 + bank * 0x10 + (idx / 8) * 0x04;
447 			mask = (0x3 << ((idx % 8) * 2));
448 			bits = (pull << ((idx % 8) * 2));
449 			regmap_write_4(rm, base + off, mask << 16 | bits);
450 		}
451 
452 		/* GPIO drive strength control */
453 		if (strength >= 0) {
454 			off = 0x100 + bank * 0x10 + (idx / 8) * 0x04;
455 			mask = (0x3 << ((idx % 8) * 2));
456 			bits = (strength << ((idx % 8) * 2));
457 			regmap_write_4(rm, base + off, mask << 16 | bits);
458 		}
459 
460 		splx(s);
461 	}
462 
463 	free(pins, M_TEMP, len);
464 	return 0;
465 
466 fail:
467 	free(pins, M_TEMP, len);
468 	return -1;
469 }
470 
471 /*
472  * Rockchip RK3328
473  */
474 
475 int
476 rk3328_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
477 {
478 	int node;
479 
480 	node = OF_getnodebyphandle(phandle);
481 	if (node == 0)
482 		return -1;
483 
484 	if (OF_getproplen(node, "bias-disable") == 0)
485 		return 0;
486 	if (OF_getproplen(node, "bias-pull-up") == 0)
487 		return 1;
488 	if (OF_getproplen(node, "bias-pull-down") == 0)
489 		return 2;
490 
491 	return -1;
492 }
493 
494 int
495 rk3328_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
496 {
497 	int strength, level;
498 	int levels[4] = { 2, 4, 8, 12 };
499 	int node;
500 
501 	node = OF_getnodebyphandle(phandle);
502 	if (node == 0)
503 		return -1;
504 
505 	strength = OF_getpropint(node, "drive-strength", -1);
506 	if (strength == -1)
507 		return -1;
508 
509 	/* Convert drive strength to level. */
510 	for (level = 3; level >= 0; level--) {
511 		if (strength >= levels[level])
512 			break;
513 	}
514 	return level;
515 }
516 
517 int
518 rk3328_pinctrl(uint32_t phandle, void *cookie)
519 {
520 	struct rkpinctrl_softc *sc = cookie;
521 	uint32_t *pins;
522 	int node, len, i;
523 
524 	KASSERT(sc->sc_grf);
525 
526 	node = OF_getnodebyphandle(phandle);
527 	if (node == 0)
528 		return -1;
529 
530 	len = OF_getproplen(node, "rockchip,pins");
531 	if (len <= 0)
532 		return -1;
533 
534 	pins = malloc(len, M_TEMP, M_WAITOK);
535 	if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
536 		goto fail;
537 
538 	for (i = 0; i < len / sizeof(uint32_t); i += 4) {
539 		struct regmap *rm = sc->sc_grf;
540 		bus_size_t base, off;
541 		uint32_t bank, idx, mux;
542 		int pull, strength;
543 		uint32_t mask, bits;
544 		int s;
545 
546 		bank = pins[i];
547 		idx = pins[i + 1];
548 		mux = pins[i + 2];
549 		pull = rk3328_pull(bank, idx, pins[i + 3]);
550 		strength = rk3328_strength(bank, idx, pins[i + 3]);
551 
552 		if (bank > 3 || idx > 32 || mux > 3)
553 			continue;
554 
555 		base = RK3328_GRF_GPIO0A_IOMUX;
556 
557 		s = splhigh();
558 
559 		/* IOMUX control */
560 		off = bank * 0x10 + (idx / 8) * 0x04;
561 
562 		/* GPIO2B, GPIO2C, GPIO3A and GPIO3B are special. */
563 		if (bank == 2 && idx == 15) {
564 			mask = 0x7;
565 			bits = mux;
566 		} else if (bank == 2 && idx >= 16 && idx <= 20) {
567 			mask = (0x7 << ((idx - 16) * 3));
568 			bits = (mux << ((idx - 16) * 3));
569 		} else if (bank == 2 && idx >= 21 && idx <= 23) {
570 			mask = (0x7 << ((idx - 21) * 3));
571 			bits = (mux << ((idx - 21) * 3));
572 		} else if (bank == 3 && idx <= 4) {
573 			mask = (0x7 << (idx * 3));
574 			bits = (mux << (idx * 3));
575 		} else if (bank == 3 && idx >= 5 && idx <= 7) {
576 			mask = (0x7 << ((idx - 5) * 3));
577 			bits = (mux << ((idx - 5) * 3));
578 		} else if (bank == 3 && idx >= 8 && idx <= 12) {
579 			mask = (0x7 << ((idx - 8) * 3));
580 			bits = (mux << ((idx - 8) * 3));
581 		} else if (bank == 3 && idx >= 13 && idx <= 15) {
582 			mask = (0x7 << ((idx - 13) * 3));
583 			bits = (mux << ((idx - 13) * 3));
584 		} else {
585 			mask = (0x3 << ((idx % 8) * 2));
586 			bits = (mux << ((idx % 8) * 2));
587 		}
588 		if (bank > 2 || (bank == 2 && idx >= 15))
589 			off += 0x04;
590 		if (bank > 2 || (bank == 2 && idx >= 21))
591 			off += 0x04;
592 		if (bank > 3 || (bank == 3 && idx >= 5))
593 			off += 0x04;
594 		if (bank > 3 || (bank == 3 && idx >= 13))
595 			off += 0x04;
596 		regmap_write_4(rm, base + off, mask << 16 | bits);
597 
598 		/* GPIO pad pull down and pull up control */
599 		if (pull >= 0) {
600 			off = 0x100 + bank * 0x10 + (idx / 8) * 0x04;
601 			mask = (0x3 << ((idx % 8) * 2));
602 			bits = (pull << ((idx % 8) * 2));
603 			regmap_write_4(rm, base + off, mask << 16 | bits);
604 		}
605 
606 		/* GPIO drive strength control */
607 		if (strength >= 0) {
608 			off = 0x200 + bank * 0x10 + (idx / 8) * 0x04;
609 			mask = (0x3 << ((idx % 8) * 2));
610 			bits = (strength << ((idx % 8) * 2));
611 			regmap_write_4(rm, base + off, mask << 16 | bits);
612 		}
613 
614 		splx(s);
615 	}
616 
617 	free(pins, M_TEMP, len);
618 	return 0;
619 
620 fail:
621 	free(pins, M_TEMP, len);
622 	return -1;
623 }
624 
625 /*
626  * Rockchip RK3399
627  */
628 
629 int
630 rk3399_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
631 {
632 	int pull_up, pull_down;
633 	int node;
634 
635 	node = OF_getnodebyphandle(phandle);
636 	if (node == 0)
637 		return -1;
638 
639 	if (bank == 2 && idx >= 16) {
640 		pull_up = 3;
641 		pull_down = 1;
642 	} else {
643 		pull_up = 1;
644 		pull_down = 2;
645 	}
646 
647 	if (OF_getproplen(node, "bias-disable") == 0)
648 		return 0;
649 	if (OF_getproplen(node, "bias-pull-up") == 0)
650 		return pull_up;
651 	if (OF_getproplen(node, "bias-pull-down") == 0)
652 		return pull_down;
653 
654 	return -1;
655 }
656 
657 /* Magic because the drive strength configurations vary wildly. */
658 
659 const int rk3399_strength_levels[][8] = {
660 	{ 2, 4, 8, 12 },			/* default */
661 	{ 3, 6, 9, 12 },			/* 1.8V or 3.0V */
662 	{ 5, 10, 15, 20 },			/* 1.8V only */
663 	{ 4, 6, 8, 10, 12, 14, 16, 18 },	/* 1.8V or 3.0V auto */
664 	{ 4, 7, 10, 13, 16, 19, 22, 26 },	/* 3.3V */
665 };
666 
667 const int rk3399_strength_types[][4] = {
668 	{ 2, 2, 0, 0 },
669 	{ 1, 1, 1, 1 },
670 	{ 1, 1, 2, 2 },
671 	{ 4, 4, 4, 1 },
672 	{ 1, 3, 1, 1 },
673 };
674 
675 const int rk3399_strength_regs[][4] = {
676 	{ 0x0080, 0x0088, 0x0090, 0x0098 },
677 	{ 0x00a0, 0x00a8, 0x00b0, 0x00b8 },
678 	{ 0x0100, 0x0104, 0x0108, 0x010c },
679 	{ 0x0110, 0x0118, 0x0120, 0x0128 },
680 	{ 0x012c, 0x0130, 0x0138, 0x013c },
681 };
682 
683 int
684 rk3399_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
685 {
686 	int strength, type, level;
687 	const int *levels;
688 	int node;
689 
690 	node = OF_getnodebyphandle(phandle);
691 	if (node == 0)
692 		return -1;
693 
694 	strength = OF_getpropint(node, "drive-strength", -1);
695 	if (strength == -1)
696 		return -1;
697 
698 	/* Convert drive strength to level. */
699 	type = rk3399_strength_types[bank][idx / 8];
700 	levels = rk3399_strength_levels[type];
701 	for (level = 7; level >= 0; level--) {
702 		if (strength >= levels[level] && levels[level] > 0)
703 			break;
704 	}
705 	return level;
706 }
707 
708 int
709 rk3399_pinctrl(uint32_t phandle, void *cookie)
710 {
711 	struct rkpinctrl_softc *sc = cookie;
712 	uint32_t *pins;
713 	int node, len, i;
714 
715 	KASSERT(sc->sc_grf);
716 	KASSERT(sc->sc_pmu);
717 
718 	node = OF_getnodebyphandle(phandle);
719 	if (node == 0)
720 		return -1;
721 
722 	len = OF_getproplen(node, "rockchip,pins");
723 	if (len <= 0)
724 		return -1;
725 
726 	pins = malloc(len, M_TEMP, M_WAITOK);
727 	if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
728 		goto fail;
729 
730 	for (i = 0; i < len / sizeof(uint32_t); i += 4) {
731 		struct regmap *rm;
732 		bus_size_t base, off;
733 		uint32_t bank, idx, mux;
734 		int pull, strength, type, shift;
735 		uint32_t mask, bits;
736 		int s;
737 
738 		bank = pins[i];
739 		idx = pins[i + 1];
740 		mux = pins[i + 2];
741 		pull = rk3399_pull(bank, idx, pins[i + 3]);
742 		strength = rk3399_strength(bank, idx, pins[i + 3]);
743 
744 		if (bank > 5 || idx > 32 || mux > 3)
745 			continue;
746 
747 		/* Bank 0 and 1 live in the PMU. */
748 		if (bank < 2) {
749 			rm = sc->sc_pmu;
750 			base = RK3399_PMUGRF_GPIO0A_IOMUX;
751 		} else {
752 			rm = sc->sc_grf;
753 			base = RK3399_GRF_GPIO2A_IOMUX - 0x20;
754 		}
755 
756 		s = splhigh();
757 
758 		/* IOMUX control */
759 		off = bank * 0x10 + (idx / 8) * 0x04;
760 		mask = (0x3 << ((idx % 8) * 2));
761 		bits = (mux << ((idx % 8) * 2));
762 		regmap_write_4(rm, base + off, mask << 16 | bits);
763 
764 		/* GPIO pad pull down and pull up control */
765 		if (pull >= 0) {
766 			off = 0x40 + bank * 0x10 + (idx / 8) * 0x04;
767 			mask = (0x3 << ((idx % 8) * 2));
768 			bits = (pull << ((idx % 8) * 2));
769 			regmap_write_4(rm, base + off, mask << 16 | bits);
770 		}
771 
772 		/* GPIO drive strength control */
773 		if (strength >= 0) {
774 			off = rk3399_strength_regs[bank][idx / 8];
775 			type = rk3399_strength_types[bank][idx / 8];
776 			shift = (type > 2) ? 3 : 2;
777 			mask = (((1 << shift) - 1) << ((idx % 8) * shift));
778 			bits = (strength << ((idx % 8) * shift));
779 			if (mask & 0x0000ffff) {
780 				regmap_write_4(rm, base + off,
781 				    mask << 16 | (bits & 0x0000ffff));
782 			}
783 			if (mask & 0xffff0000) {
784 				regmap_write_4(rm, base + off + 0x04,
785 				    (mask & 0xffff0000) | bits >> 16);
786 			}
787 		}
788 
789 		splx(s);
790 	}
791 
792 	free(pins, M_TEMP, len);
793 	return 0;
794 
795 fail:
796 	free(pins, M_TEMP, len);
797 	return -1;
798 }
799 
800 /*
801  * Rockchip RK3568
802  */
803 
804 int
805 rk3568_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
806 {
807 	int node;
808 
809 	node = OF_getnodebyphandle(phandle);
810 	if (node == 0)
811 		return -1;
812 
813 	if (OF_getproplen(node, "bias-disable") == 0)
814 		return 0;
815 	if (OF_getproplen(node, "bias-pull-up") == 0)
816 		return 1;
817 	if (OF_getproplen(node, "bias-pull-down") == 0)
818 		return 2;
819 
820 	return -1;
821 }
822 
823 int
824 rk3568_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
825 {
826 	int node;
827 
828 	node = OF_getnodebyphandle(phandle);
829 	if (node == 0)
830 		return -1;
831 
832 	return OF_getpropint(node, "drive-strength", -1);
833 }
834 
835 int
836 rk3568_schmitt(uint32_t bank, uint32_t idx, uint32_t phandle)
837 {
838 	int node;
839 
840 	node = OF_getnodebyphandle(phandle);
841 	if (node == 0)
842 		return -1;
843 
844 	if (OF_getproplen(node, "input-schmitt-disable") == 0)
845 		return 1;
846 	if (OF_getproplen(node, "input-schmitt-enable") == 0)
847 		return 2;
848 
849 	return -1;
850 }
851 
852 struct rockchip_route_table rk3568_route_table[] = {
853 	{ 0, RK_PB7, 1, ROUTE_PMU, 0x0110, ROUTE_VAL(0, 0) }, /* PWM0 M0 */
854 	{ 0, RK_PC7, 2, ROUTE_PMU, 0x0110, ROUTE_VAL(0, 1) }, /* PWM0 M1 */
855 	{ 0, RK_PC0, 1, ROUTE_PMU, 0x0110, ROUTE_VAL(2, 0) }, /* PWM1 M0 */
856 	{ 0, RK_PB5, 4, ROUTE_PMU, 0x0110, ROUTE_VAL(2, 1) }, /* PWM1 M1 */
857 	{ 0, RK_PC1, 1, ROUTE_PMU, 0x0110, ROUTE_VAL(4, 0) }, /* PWM2 M0 */
858 	{ 0, RK_PB6, 4, ROUTE_PMU, 0x0110, ROUTE_VAL(4, 1) }, /* PWM2 M1 */
859 
860 	{ 3, RK_PB1, 3, ROUTE_GRF, 0x0300, ROUTE_VAL(8, 0) }, /* GMAC1 M0 */
861 	{ 4, RK_PA7, 3, ROUTE_GRF, 0x0300, ROUTE_VAL(8, 1) }, /* GMAC1 M1 */
862 	{ 0, RK_PB6, 1, ROUTE_GRF, 0x0300, ROUTE_VAL(14, 0) }, /* I2C2 M0 */
863 	{ 4, RK_PB4, 1, ROUTE_GRF, 0x0300, ROUTE_VAL(14, 1) }, /* I2C2 M1 */
864 
865 	{ 1, RK_PA0, 1, ROUTE_GRF, 0x0304, ROUTE_VAL(0, 0) }, /* I2C3 M0 */
866 	{ 3, RK_PB6, 4, ROUTE_GRF, 0x0304, ROUTE_VAL(0, 1) }, /* I2C3 M1 */
867 	{ 4, RK_PB2, 1, ROUTE_GRF, 0x0304, ROUTE_VAL(2, 0) }, /* I2C4 M0 */
868 	{ 2, RK_PB1, 2, ROUTE_GRF, 0x0304, ROUTE_VAL(2, 1) }, /* I2C4 M1 */
869 	{ 3, RK_PB4, 4, ROUTE_GRF, 0x0304, ROUTE_VAL(4, 0) }, /* I2C5 M0 */
870 	{ 4, RK_PD0, 2, ROUTE_GRF, 0x0304, ROUTE_VAL(4, 1) }, /* I2C5 M1 */
871 	{ 3, RK_PB1, 5, ROUTE_GRF, 0x0304, ROUTE_VAL(14, 0) }, /* PWM8 M0 */
872 	{ 1, RK_PD5, 4, ROUTE_GRF, 0x0304, ROUTE_VAL(14, 1) }, /* PWM8 M1 */
873 
874 	{ 3, RK_PB2, 5, ROUTE_GRF, 0x0308, ROUTE_VAL(0, 0) }, /* PWM9 M0 */
875 	{ 1, RK_PD6, 4, ROUTE_GRF, 0x0308, ROUTE_VAL(0, 1) }, /* PWM9 M1 */
876 	{ 3, RK_PB5, 5, ROUTE_GRF, 0x0308, ROUTE_VAL(2, 0) }, /* PWM10 M0 */
877 	{ 2, RK_PA1, 2, ROUTE_GRF, 0x0308, ROUTE_VAL(2, 1) }, /* PWM10 M1 */
878 	{ 3, RK_PB6, 5, ROUTE_GRF, 0x0308, ROUTE_VAL(4, 0) }, /* PWM11 M0 */
879 	{ 4, RK_PC0, 3, ROUTE_GRF, 0x0308, ROUTE_VAL(4, 1) }, /* PWM11 M1 */
880 	{ 3, RK_PB7, 2, ROUTE_GRF, 0x0308, ROUTE_VAL(6, 0) }, /* PWM12 M0 */
881 	{ 4, RK_PC5, 1, ROUTE_GRF, 0x0308, ROUTE_VAL(6, 1) }, /* PWM12 M1 */
882 	{ 3, RK_PC0, 2, ROUTE_GRF, 0x0308, ROUTE_VAL(8, 0) }, /* PWM13 M0 */
883 	{ 4, RK_PC6, 1, ROUTE_GRF, 0x0308, ROUTE_VAL(8, 1) }, /* PWM13 M1 */
884 	{ 3, RK_PC4, 1, ROUTE_GRF, 0x0308, ROUTE_VAL(10, 0) }, /* PWM14 M0 */
885 	{ 4, RK_PC2, 1, ROUTE_GRF, 0x0308, ROUTE_VAL(10, 1) }, /* PWM14 M1 */
886 	{ 3, RK_PC5, 1, ROUTE_GRF, 0x0308, ROUTE_VAL(12, 0) }, /* PWM15 M0 */
887 	{ 4, RK_PC3, 1, ROUTE_GRF, 0x0308, ROUTE_VAL(12, 1) }, /* PWM15 M1 */
888 	{ 3, RK_PD2, 3, ROUTE_GRF, 0x0308, ROUTE_VAL(14, 0) }, /* SDMMC2 M0 */
889 	{ 3, RK_PA5, 5, ROUTE_GRF, 0x0308, ROUTE_VAL(14, 1) }, /* SDMMC2 M1 */
890 
891 	{ 2, RK_PB4, 2, ROUTE_GRF, 0x030c, ROUTE_VAL(8, 0) }, /* UART1 M0 */
892 	{ 3, RK_PD6, 4, ROUTE_GRF, 0x030c, ROUTE_VAL(8, 1) }, /* UART1 M1 */
893 	{ 0, RK_PD1, 1, ROUTE_GRF, 0x030c, ROUTE_VAL(10, 0) }, /* UART2 M0 */
894 	{ 1, RK_PD5, 2, ROUTE_GRF, 0x030c, ROUTE_VAL(10, 1) }, /* UART2 M1 */
895 	{ 1, RK_PA1, 2, ROUTE_GRF, 0x030c, ROUTE_VAL(12, 0) }, /* UART3 M0 */
896 	{ 3, RK_PB7, 4, ROUTE_GRF, 0x030c, ROUTE_VAL(12, 1) }, /* UART3 M1 */
897 	{ 1, RK_PA6, 2, ROUTE_GRF, 0x030c, ROUTE_VAL(14, 0) }, /* UART4 M0 */
898 	{ 3, RK_PB2, 4, ROUTE_GRF, 0x030c, ROUTE_VAL(14, 1) }, /* UART4 M1 */
899 
900 	{ 2, RK_PA2, 3, ROUTE_GRF, 0x0310, ROUTE_VAL(0, 0) }, /* UART5 M0 */
901 	{ 3, RK_PC2, 4, ROUTE_GRF, 0x0310, ROUTE_VAL(0, 1) }, /* UART5 M1 */
902 	{ 2, RK_PA4, 3, ROUTE_GRF, 0x0310, ROUTE_VAL(2, 0) }, /* UART6 M0 */
903 	{ 1, RK_PD5, 3, ROUTE_GRF, 0x0310, ROUTE_VAL(2, 1) }, /* UART6 M1 */
904 	{ 2, RK_PA6, 3, ROUTE_GRF, 0x0310, ROUTE_VAL(4, 0) }, /* UART7 M0 */
905 	{ 3, RK_PC4, 4, ROUTE_GRF, 0x0310, ROUTE_VAL(4, 1) }, /* UART7 M1 */
906 	{ 4, RK_PA2, 4, ROUTE_GRF, 0x0310, ROUTE_VAL(4, 2) }, /* UART7 M2 */
907 	{ 2, RK_PC5, 3, ROUTE_GRF, 0x0310, ROUTE_VAL(6, 0) }, /* UART8 M0 */
908 	{ 2, RK_PD7, 4, ROUTE_GRF, 0x0310, ROUTE_VAL(6, 1) }, /* UART8 M1 */
909 	{ 2, RK_PB0, 3, ROUTE_GRF, 0x0310, ROUTE_VAL(8, 0) }, /* UART9 M0 */
910 	{ 4, RK_PC5, 4, ROUTE_GRF, 0x0310, ROUTE_VAL(8, 1) }, /* UART9 M1 */
911 	{ 4, RK_PA4, 4, ROUTE_GRF, 0x0310, ROUTE_VAL(8, 2) }, /* UART9 M2 */
912 	{ 1, RK_PA2, 1, ROUTE_GRF, 0x0310, ROUTE_VAL(10, 0) }, /* I2S1 M0 */
913 	{ 3, RK_PC6, 4, ROUTE_GRF, 0x0310, ROUTE_VAL(10, 1) }, /* I2S1 M1 */
914 	{ 2, RK_PD0, 5, ROUTE_GRF, 0x0310, ROUTE_VAL(10, 2) }, /* I2S1 M2 */
915 	{ 2, RK_PC1, 1, ROUTE_GRF, 0x0310, ROUTE_VAL(12, 0) }, /* I2S2 M0 */
916 	{ 4, RK_PB6, 5, ROUTE_GRF, 0x0310, ROUTE_VAL(12, 1) }, /* I2S2 M1 */
917 	{ 3, RK_PA2, 4, ROUTE_GRF, 0x0310, ROUTE_VAL(14, 0) }, /* I2S3 M0 */
918 	{ 4, RK_PC2, 5, ROUTE_GRF, 0x0310, ROUTE_VAL(14, 1) }, /* I2S3 M1 */
919 
920 	{ 0, RK_PA5, 3, ROUTE_GRF, 0x0314, ROUTE_VAL(2, 0) }, /* PCIE20 M0 */
921 	{ 2, RK_PD0, 4, ROUTE_GRF, 0x0314, ROUTE_VAL(2, 1) }, /* PCIE20 M1 */
922 	{ 1, RK_PB0, 4, ROUTE_GRF, 0x0314, ROUTE_VAL(2, 2) }, /* PCIE20 M2 */
923 	{ 0, RK_PA4, 3, ROUTE_GRF, 0x0314, ROUTE_VAL(4, 0) }, /* PCIE30X1 M0 */
924 	{ 2, RK_PD2, 4, ROUTE_GRF, 0x0314, ROUTE_VAL(4, 1) }, /* PCIE30X1 M1 */
925 	{ 1, RK_PA5, 4, ROUTE_GRF, 0x0314, ROUTE_VAL(4, 2) }, /* PCIE30X1 M2 */
926 	{ 0, RK_PA6, 2, ROUTE_GRF, 0x0314, ROUTE_VAL(6, 0) }, /* PCIE30X2 M0 */
927 	{ 2, RK_PD4, 4, ROUTE_GRF, 0x0314, ROUTE_VAL(6, 1) }, /* PCIE30X2 M1 */
928 	{ 4, RK_PC2, 4, ROUTE_GRF, 0x0314, ROUTE_VAL(6, 2) }, /* PCIE30X2 M2 */
929 };
930 
931 void
932 rk3568_route(struct rkpinctrl_softc *sc, uint32_t *pins)
933 {
934 	struct rockchip_route_table *route = NULL;
935 	struct regmap *rm;
936 	int bank = pins[0];
937 	int idx = pins[1];
938 	int mux = pins[2];
939 	int i;
940 
941 	for (i = 0; i < nitems(rk3568_route_table); i++) {
942 		if (bank == rk3568_route_table[i].bank &&
943 		    idx == rk3568_route_table[i].idx &&
944 		    mux == rk3568_route_table[i].mux) {
945 			route = &rk3568_route_table[i];
946 			break;
947 		}
948 	}
949 	if (route == NULL)
950 		return;
951 
952 	rm = route->grf ? sc->sc_pmu : sc->sc_grf;
953 	regmap_write_4(rm, route->reg, route->val);
954 }
955 
956 int
957 rk3568_pinctrl(uint32_t phandle, void *cookie)
958 {
959 	struct rkpinctrl_softc *sc = cookie;
960 	uint32_t *pins;
961 	int node, len, i;
962 
963 	KASSERT(sc->sc_grf);
964 	KASSERT(sc->sc_pmu);
965 
966 	node = OF_getnodebyphandle(phandle);
967 	if (node == 0)
968 		return -1;
969 
970 	len = OF_getproplen(node, "rockchip,pins");
971 	if (len <= 0)
972 		return -1;
973 
974 	pins = malloc(len, M_TEMP, M_WAITOK);
975 	if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
976 		goto fail;
977 
978 	for (i = 0; i < len / sizeof(uint32_t); i += 4) {
979 		struct regmap *rm;
980 		bus_size_t iomux_base, p_base, ds_base, ie_base, off;
981 		uint32_t bank, idx, mux;
982 		int pull, strength, schmitt;
983 		uint32_t mask, bits;
984 		int s;
985 
986 		bank = pins[i];
987 		idx = pins[i + 1];
988 		mux = pins[i + 2];
989 		pull = rk3568_pull(bank, idx, pins[i + 3]);
990 		strength = rk3568_strength(bank, idx, pins[i + 3]);
991 		schmitt = rk3568_schmitt(bank, idx, pins[i + 3]);
992 
993 		if (bank > 5 || idx > 32 || mux > 7)
994 			continue;
995 
996 		/* Bank 0 lives in the PMU. */
997 		if (bank < 1) {
998 			rm = sc->sc_pmu;
999 			iomux_base = RK3568_PMUGRF_GPIO0A_IOMUX_L;
1000 			p_base = RK3568_PMUGRF_GPIO0A_P;
1001 			ds_base = RK3568_PMUGRF_GPIO0A_DS_0;
1002 			ie_base = RK3568_PMUGRF_GPIO0A_IE;
1003 		} else {
1004 			rm = sc->sc_grf;
1005 			iomux_base = RK3568_GRF_GPIO1A_IOMUX_L;
1006 			p_base = RK3568_GRF_GPIO1A_P;
1007 			ds_base = RK3568_GRF_GPIO1A_DS_0;
1008 			ie_base = RK3568_GRF_GPIO1A_IE;
1009 			bank = bank - 1;
1010 		}
1011 
1012 		s = splhigh();
1013 
1014 		/* IOMUX control */
1015 		rk3568_route(sc, &pins[i]);
1016 		off = bank * 0x20 + (idx / 4) * 0x04;
1017 		mask = (0x7 << ((idx % 4) * 4));
1018 		bits = (mux << ((idx % 4) * 4));
1019 		regmap_write_4(rm, iomux_base + off, mask << 16 | bits);
1020 
1021 		/* GPIO pad pull down and pull up control */
1022 		if (pull >= 0) {
1023 			off = bank * 0x10 + (idx / 8) * 0x04;
1024 			mask = (0x3 << ((idx % 8) * 2));
1025 			bits = (pull << ((idx % 8) * 2));
1026 			regmap_write_4(rm, p_base + off, mask << 16 | bits);
1027 		}
1028 
1029 		/* GPIO drive strength control */
1030 		if (strength >= 0) {
1031 			off = bank * 0x40 + (idx / 2) * 0x04;
1032 			mask = (0x3f << ((idx % 2) * 8));
1033 			bits = ((1 << (strength + 1)) - 1) << ((idx % 2) * 8);
1034 			regmap_write_4(rm, ds_base + off, mask << 16 | bits);
1035 		}
1036 
1037 		/* GPIO Schmitt trigger. */
1038 		if (schmitt >= 0) {
1039 			off = bank * 0x10 + (idx / 8) * 0x04;
1040 			mask = (0x3 << ((idx % 8) * 2));
1041 			bits = schmitt << ((idx % 8) * 2);
1042 			regmap_write_4(rm, ie_base + off, mask << 16 | bits);
1043 		}
1044 
1045 		splx(s);
1046 	}
1047 
1048 	free(pins, M_TEMP, len);
1049 	return 0;
1050 
1051 fail:
1052 	free(pins, M_TEMP, len);
1053 	return -1;
1054 }
1055 
1056 
1057 /*
1058  * Rockchip RK3588
1059  */
1060 
1061 int
1062 rk3588_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
1063 {
1064 	int node;
1065 
1066 	node = OF_getnodebyphandle(phandle);
1067 	if (node == 0)
1068 		return -1;
1069 
1070 	if (OF_getproplen(node, "bias-disable") == 0)
1071 		return 0;
1072 	if (OF_getproplen(node, "bias-pull-up") == 0)
1073 		return 3;
1074 	if (OF_getproplen(node, "bias-pull-down") == 0)
1075 		return 1;
1076 
1077 	return -1;
1078 }
1079 
1080 int
1081 rk3588_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
1082 {
1083 	int node;
1084 
1085 	node = OF_getnodebyphandle(phandle);
1086 	if (node == 0)
1087 		return -1;
1088 
1089 	return OF_getpropint(node, "drive-strength", -1);
1090 }
1091 
1092 int
1093 rk3588_schmitt(uint32_t bank, uint32_t idx, uint32_t phandle)
1094 {
1095 	int node;
1096 
1097 	node = OF_getnodebyphandle(phandle);
1098 	if (node == 0)
1099 		return -1;
1100 
1101 	if (OF_getproplen(node, "input-schmitt-disable") == 0)
1102 		return 0;
1103 	if (OF_getproplen(node, "input-schmitt-enable") == 0)
1104 		return 1;
1105 
1106 	return -1;
1107 }
1108 
1109 #define RK3588_PMU1_IOC		0x0000
1110 #define RK3588_PMU2_IOC		0x4000
1111 #define RK3588_BUS_IOC		0x8000
1112 #define RK3588_VCCIO1_4_IOC	0x9000
1113 #define RK3588_VCCIO3_5_IOC	0xa000
1114 #define RK3588_VCCIO2_IOC	0xb000
1115 #define RK3588_VCCIO6_IOC	0xc000
1116 #define RK3588_EMMC_IOC		0xd000
1117 
1118 bus_size_t
1119 rk3588_base(uint32_t bank, uint32_t idx)
1120 {
1121 	if (bank == 1 && idx < 32)
1122 		return RK3588_VCCIO1_4_IOC;
1123 	if (bank == 2 && idx < 6)
1124 		return RK3588_EMMC_IOC;
1125 	if (bank == 2 && idx < 24)
1126 		return RK3588_VCCIO3_5_IOC;
1127 	if (bank == 2 && idx < 32)
1128 		return RK3588_EMMC_IOC;
1129 	if (bank == 3 && idx < 32)
1130 		return RK3588_VCCIO3_5_IOC;
1131 	if (bank == 4 && idx < 18)
1132 		return RK3588_VCCIO6_IOC;
1133 	if (bank == 4 && idx < 24)
1134 		return RK3588_VCCIO3_5_IOC;
1135 	if (bank == 4 && idx < 32)
1136 		return RK3588_VCCIO2_IOC;
1137 
1138 	return (bus_size_t)-1;
1139 }
1140 
1141 int
1142 rk3588_pinctrl(uint32_t phandle, void *cookie)
1143 {
1144 	struct rkpinctrl_softc *sc = cookie;
1145 	struct regmap *rm = sc->sc_grf;
1146 	uint32_t *pins;
1147 	int node, len, i;
1148 
1149 	KASSERT(sc->sc_grf);
1150 
1151 	node = OF_getnodebyphandle(phandle);
1152 	if (node == 0)
1153 		return -1;
1154 
1155 	len = OF_getproplen(node, "rockchip,pins");
1156 	if (len <= 0)
1157 		return -1;
1158 
1159 	pins = malloc(len, M_TEMP, M_WAITOK);
1160 	if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
1161 		goto fail;
1162 
1163 	for (i = 0; i < len / sizeof(uint32_t); i += 4) {
1164 		bus_size_t iomux_base, p_base, ds_base, smt_base, off;
1165 		uint32_t bank, idx, mux;
1166 		int pull, strength, schmitt;
1167 		uint32_t mask, bits;
1168 		int s;
1169 
1170 		bank = pins[i];
1171 		idx = pins[i + 1];
1172 		mux = pins[i + 2];
1173 		pull = rk3588_pull(bank, idx, pins[i + 3]);
1174 		strength = rk3588_strength(bank, idx, pins[i + 3]);
1175 		schmitt = rk3588_schmitt(bank, idx, pins[i + 3]);
1176 
1177 		if (bank > 5 || idx > 32 || mux > 15)
1178 			continue;
1179 
1180 		if (bank == 0 && idx < 12) {
1181 			/* PMU1 */
1182 			iomux_base = RK3588_PMU1_IOC;
1183 		} else {
1184 			/* BUS */
1185 			iomux_base = RK3588_BUS_IOC;
1186 		}
1187 
1188 		if (bank == 0) {
1189 			if (idx < 12) {
1190 				/* PMU1 */
1191 				p_base = RK3588_PMU1_IOC + 0x0020;
1192 				ds_base = RK3588_PMU1_IOC + 0x0010;
1193 				smt_base = RK3588_PMU1_IOC + 0x0030;
1194 			} else {
1195 				/* PMU2 */
1196 				p_base = RK3588_PMU2_IOC + 0x0024;
1197 				ds_base = RK3588_PMU2_IOC + 0x0008;
1198 				smt_base = RK3588_PMU2_IOC + 0x003c;
1199 			}
1200 		} else {
1201 			bus_size_t base = rk3588_base(bank, idx);
1202 			KASSERT(base != (bus_size_t)-1);
1203 
1204 			p_base = base + 0x0100;
1205 			ds_base = base + 0x0000;
1206 			smt_base = base + 0x0200;
1207 		}
1208 
1209 		s = splhigh();
1210 
1211 		/* IOMUX control */
1212 		off = bank * 0x20 + (idx / 4) * 0x04;
1213 		mask = (0xf << ((idx % 4) * 4));
1214 		bits = (mux << ((idx % 4) * 4));
1215 		regmap_write_4(rm, iomux_base + off, mask << 16 | bits);
1216 		if (bank == 0 && idx > 12) {
1217 			iomux_base = RK3588_PMU2_IOC;
1218 			off = (idx - 12) / 4 * 0x04;
1219 			mux = (mux < 8) ? mux : 8;
1220 			bits = (mux << ((idx % 4) * 4));
1221 			regmap_write_4(rm, iomux_base + off, mask << 16 | bits);
1222 		}
1223 
1224 		/* GPIO pad pull down and pull up control */
1225 		if (pull >= 0) {
1226 			off = bank * 0x10 + (idx / 8) * 0x04;
1227 			mask = (0x3 << ((idx % 8) * 2));
1228 			bits = (pull << ((idx % 8) * 2));
1229 			regmap_write_4(rm, p_base + off, mask << 16 | bits);
1230 		}
1231 
1232 		/* GPIO drive strength control */
1233 		if (strength >= 0) {
1234 			off = bank * 0x20 + (idx / 4) * 0x04;
1235 			mask = (0xf << ((idx % 4) * 4));
1236 			bits = (strength << ((idx % 4) * 4));
1237 			regmap_write_4(rm, ds_base + off, mask << 16 | bits);
1238 		}
1239 
1240 		/* GPIO Schmitt trigger. */
1241 		if (schmitt >= 0) {
1242 			off = bank * 0x10 + (idx / 8) * 0x04;
1243 			mask = (0x1 << (idx % 8));
1244 			bits = (schmitt << (idx % 8));
1245 			regmap_write_4(rm, smt_base + off, mask << 16 | bits);
1246 		}
1247 
1248 		splx(s);
1249 	}
1250 
1251 	free(pins, M_TEMP, len);
1252 	return 0;
1253 
1254 fail:
1255 	free(pins, M_TEMP, len);
1256 	return -1;
1257 }
1258