xref: /openbsd-src/sys/dev/fdt/rkpinctrl.c (revision 3374c67d44f9b75b98444cbf63020f777792342e)
1 /*	$OpenBSD: rkpinctrl.c,v 1.9 2022/10/09 20:30:59 kettenis 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 #ifdef __armv7__
33 #include <arm/simplebus/simplebusvar.h>
34 #else
35 #include <arm64/dev/simplebusvar.h>
36 #endif
37 
38 /* RK3288 registers */
39 #define RK3288_GRF_GPIO1A_IOMUX		0x0000
40 #define RK3288_PMUGRF_GPIO0A_IOMUX	0x0084
41 
42 /* RK3308 registers */
43 #define RK3308_GRF_GPIO0A_IOMUX		0x0000
44 
45 /* RK3328 registers */
46 #define RK3328_GRF_GPIO0A_IOMUX		0x0000
47 
48 /* RK3399 registers */
49 #define RK3399_GRF_GPIO2A_IOMUX		0xe000
50 #define RK3399_PMUGRF_GPIO0A_IOMUX	0x0000
51 
52 /* RK3568 registers */
53 #define RK3568_GRF_GPIO1A_IOMUX_L	0x0000
54 #define RK3568_GRF_GPIO1A_P		0x0080
55 #define RK3568_GRF_GPIO1A_IE		0x00c0
56 #define RK3568_GRF_GPIO1A_DS_0		0x0200
57 #define RK3568_PMUGRF_GPIO0A_IOMUX_L	0x0000
58 #define RK3568_PMUGRF_GPIO0A_P		0x0020
59 #define RK3568_PMUGRF_GPIO0A_IE		0x0030
60 #define RK3568_PMUGRF_GPIO0A_DS_0	0x0070
61 
62 struct rkpinctrl_softc {
63 	struct simplebus_softc	sc_sbus;
64 
65 	struct regmap		*sc_grf;
66 	struct regmap		*sc_pmu;
67 };
68 
69 int	rkpinctrl_match(struct device *, void *, void *);
70 void	rkpinctrl_attach(struct device *, struct device *, void *);
71 
72 const struct cfattach	rkpinctrl_ca = {
73 	sizeof (struct rkpinctrl_softc), rkpinctrl_match, rkpinctrl_attach
74 };
75 
76 struct cfdriver rkpinctrl_cd = {
77 	NULL, "rkpinctrl", DV_DULL
78 };
79 
80 int	rk3288_pinctrl(uint32_t, void *);
81 int	rk3308_pinctrl(uint32_t, void *);
82 int	rk3328_pinctrl(uint32_t, void *);
83 int	rk3399_pinctrl(uint32_t, void *);
84 int	rk3568_pinctrl(uint32_t, void *);
85 
86 int
87 rkpinctrl_match(struct device *parent, void *match, void *aux)
88 {
89 	struct fdt_attach_args *faa = aux;
90 
91 	return (OF_is_compatible(faa->fa_node, "rockchip,rk3288-pinctrl") ||
92 	    OF_is_compatible(faa->fa_node, "rockchip,rk3308-pinctrl") ||
93 	    OF_is_compatible(faa->fa_node, "rockchip,rk3328-pinctrl") ||
94 	    OF_is_compatible(faa->fa_node, "rockchip,rk3399-pinctrl") ||
95 	    OF_is_compatible(faa->fa_node, "rockchip,rk3568-pinctrl"));
96 }
97 
98 void
99 rkpinctrl_attach(struct device *parent, struct device *self, void *aux)
100 {
101 	struct rkpinctrl_softc *sc = (struct rkpinctrl_softc *)self;
102 	struct fdt_attach_args *faa = aux;
103 	uint32_t grf, pmu;
104 
105 	grf = OF_getpropint(faa->fa_node, "rockchip,grf", 0);
106 	pmu = OF_getpropint(faa->fa_node, "rockchip,pmu", 0);
107 	sc->sc_grf = regmap_byphandle(grf);
108 	sc->sc_pmu = regmap_byphandle(pmu);
109 
110 	if (sc->sc_grf == NULL && sc->sc_pmu == NULL) {
111 		printf(": no registers\n");
112 		return;
113 	}
114 
115 	if (OF_is_compatible(faa->fa_node, "rockchip,rk3288-pinctrl"))
116 		pinctrl_register(faa->fa_node, rk3288_pinctrl, sc);
117 	else if (OF_is_compatible(faa->fa_node, "rockchip,rk3308-pinctrl"))
118 		pinctrl_register(faa->fa_node, rk3308_pinctrl, sc);
119 	else if (OF_is_compatible(faa->fa_node, "rockchip,rk3328-pinctrl"))
120 		pinctrl_register(faa->fa_node, rk3328_pinctrl, sc);
121 	else if (OF_is_compatible(faa->fa_node, "rockchip,rk3399-pinctrl"))
122 		pinctrl_register(faa->fa_node, rk3399_pinctrl, sc);
123 	else
124 		pinctrl_register(faa->fa_node, rk3568_pinctrl, sc);
125 
126 	/* Attach GPIO banks. */
127 	simplebus_attach(parent, &sc->sc_sbus.sc_dev, faa);
128 }
129 
130 /*
131  * Rockchip RK3288
132  */
133 
134 int
135 rk3288_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
136 {
137 	int node;
138 
139 	node = OF_getnodebyphandle(phandle);
140 	if (node == 0)
141 		return -1;
142 
143 	/* XXX */
144 	if (bank == 0)
145 		return -1;
146 
147 	if (OF_getproplen(node, "bias-disable") == 0)
148 		return 0;
149 	if (OF_getproplen(node, "bias-pull-up") == 0)
150 		return 1;
151 	if (OF_getproplen(node, "bias-pull-down") == 0)
152 		return 2;
153 
154 	return -1;
155 }
156 
157 int
158 rk3288_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
159 {
160 	int strength, level;
161 	int levels[4] = { 2, 4, 8, 12 };
162 	int node;
163 
164 	node = OF_getnodebyphandle(phandle);
165 	if (node == 0)
166 		return -1;
167 
168 	/* XXX */
169 	if (bank == 0)
170 		return -1;
171 
172 	strength = OF_getpropint(node, "drive-strength", -1);
173 	if (strength == -1)
174 		return -1;
175 
176 	/* Convert drive strength to level. */
177 	for (level = 3; level >= 0; level--) {
178 		if (strength >= levels[level])
179 			break;
180 	}
181 	return level;
182 }
183 
184 int
185 rk3288_pinctrl(uint32_t phandle, void *cookie)
186 {
187 	struct rkpinctrl_softc *sc = cookie;
188 	uint32_t *pins;
189 	int node, len, i;
190 
191 	KASSERT(sc->sc_grf);
192 	KASSERT(sc->sc_pmu);
193 
194 	node = OF_getnodebyphandle(phandle);
195 	if (node == 0)
196 		return -1;
197 
198 	len = OF_getproplen(node, "rockchip,pins");
199 	if (len <= 0)
200 		return -1;
201 
202 	pins = malloc(len, M_TEMP, M_WAITOK);
203 	if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
204 		goto fail;
205 
206 	for (i = 0; i < len / sizeof(uint32_t); i += 4) {
207 		struct regmap *rm;
208 		bus_size_t base, off;
209 		uint32_t bank, idx, mux;
210 		int pull, strength;
211 		uint32_t mask, bits;
212 		int s;
213 
214 		bank = pins[i];
215 		idx = pins[i + 1];
216 		mux = pins[i + 2];
217 		pull = rk3288_pull(bank, idx, pins[i + 3]);
218 		strength = rk3288_strength(bank, idx, pins[i + 3]);
219 
220 		if (bank > 8 || idx > 32 || mux > 7)
221 			continue;
222 
223 		/* Bank 0 lives in the PMU. */
224 		if (bank < 1) {
225 			rm = sc->sc_pmu;
226 			base = RK3288_PMUGRF_GPIO0A_IOMUX;
227 		} else {
228 			rm = sc->sc_grf;
229 			base = RK3288_GRF_GPIO1A_IOMUX - 0x10;
230 		}
231 
232 		s = splhigh();
233 
234 		/* IOMUX control */
235 		off = bank * 0x10 + (idx / 8) * 0x04;
236 
237 		/* GPIO3D, GPIO4A and GPIO4B are special. */
238 		if ((bank == 3 && idx >= 24) || (bank == 4 && idx < 16)) {
239 			mask = (0x7 << ((idx % 4) * 4));
240 			bits = (mux << ((idx % 4) * 4));
241 		} else {
242 			mask = (0x3 << ((idx % 8) * 2));
243 			bits = (mux << ((idx % 8) * 2));
244 		}
245 		if (bank > 3 || (bank == 3 && idx >= 28))
246 			off += 0x04;
247 		if (bank > 4 || (bank == 4 && idx >= 4))
248 			off += 0x04;
249 		if (bank > 4 || (bank == 4 && idx >= 12))
250 			off += 0x04;
251 		regmap_write_4(rm, base + off, mask << 16 | bits);
252 
253 		/* GPIO pad pull down and pull up control */
254 		if (pull >= 0) {
255 			off = 0x140 + bank * 0x10 + (idx / 8) * 0x04;
256 			mask = (0x3 << ((idx % 8) * 2));
257 			bits = (pull << ((idx % 8) * 2));
258 			regmap_write_4(rm, base + off, mask << 16 | bits);
259 		}
260 
261 		/* GPIO drive strength control */
262 		if (strength >= 0) {
263 			off = 0x1c0 + bank * 0x10 + (idx / 8) * 0x04;
264 			mask = (0x3 << ((idx % 8) * 2));
265 			bits = (strength << ((idx % 8) * 2));
266 			regmap_write_4(rm, base + off, mask << 16 | bits);
267 		}
268 
269 		splx(s);
270 	}
271 
272 	free(pins, M_TEMP, len);
273 	return 0;
274 
275 fail:
276 	free(pins, M_TEMP, len);
277 	return -1;
278 }
279 
280 /*
281  * Rockchip RK3308
282  */
283 
284 int
285 rk3308_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
286 {
287 	int node;
288 
289 	node = OF_getnodebyphandle(phandle);
290 	if (node == 0)
291 		return -1;
292 
293 	if (OF_getproplen(node, "bias-disable") == 0)
294 		return 0;
295 	if (OF_getproplen(node, "bias-pull-up") == 0)
296 		return 1;
297 	if (OF_getproplen(node, "bias-pull-down") == 0)
298 		return 2;
299 
300 	return -1;
301 }
302 
303 int
304 rk3308_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
305 {
306 	int strength, level;
307 	int levels[4] = { 2, 4, 8, 12 };
308 	int node;
309 
310 	node = OF_getnodebyphandle(phandle);
311 	if (node == 0)
312 		return -1;
313 
314 	strength = OF_getpropint(node, "drive-strength", -1);
315 	if (strength == -1)
316 		return -1;
317 
318 	/* Convert drive strength to level. */
319 	for (level = 3; level >= 0; level--) {
320 		if (strength >= levels[level])
321 			break;
322 	}
323 	return level;
324 }
325 
326 int
327 rk3308_pinctrl(uint32_t phandle, void *cookie)
328 {
329 	struct rkpinctrl_softc *sc = cookie;
330 	uint32_t *pins;
331 	int node, len, i;
332 
333 	KASSERT(sc->sc_grf);
334 
335 	node = OF_getnodebyphandle(phandle);
336 	if (node == 0)
337 		return -1;
338 
339 	len = OF_getproplen(node, "rockchip,pins");
340 	if (len <= 0)
341 		return -1;
342 
343 	pins = malloc(len, M_TEMP, M_WAITOK);
344 	if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
345 		goto fail;
346 
347 	for (i = 0; i < len / sizeof(uint32_t); i += 4) {
348 		struct regmap *rm = sc->sc_grf;
349 		bus_size_t base, off;
350 		uint32_t bank, idx, mux;
351 		int pull, strength;
352 		uint32_t mask, bits;
353 		int s;
354 
355 		bank = pins[i];
356 		idx = pins[i + 1];
357 		mux = pins[i + 2];
358 		pull = rk3308_pull(bank, idx, pins[i + 3]);
359 		strength = rk3308_strength(bank, idx, pins[i + 3]);
360 
361 		if (bank > 4 || idx > 32 || mux > 7)
362 			continue;
363 
364 		base = RK3308_GRF_GPIO0A_IOMUX;
365 
366 		s = splhigh();
367 
368 		/* IOMUX control */
369 		off = bank * 0x20 + (idx / 8) * 0x08;
370 
371 		/* GPIO1B, GPIO1C and GPIO3B are special. */
372 		if ((bank == 1) && (idx == 14)) {
373 			mask = (0xf << 12);
374 			bits = (mux << 12);
375 		} else if ((bank == 1) && (idx == 15)) {
376 			off += 4;
377 			mask = 0x3;
378 			bits = mux;
379 		} else if ((bank == 1) && (idx >= 16 && idx <= 17)) {
380 			mask = (0x3 << ((idx - 16) * 2));
381 			bits = (mux << ((idx - 16) * 2));
382 		} else if ((bank == 1) && (idx >= 18 && idx <= 20)) {
383 			mask = (0xf << (((idx - 18) * 4) + 4));
384 			bits = (mux << (((idx - 18) * 4) + 4));
385 		} else if ((bank == 1) && (idx >= 21 && idx <= 23)) {
386 			off += 4;
387 			mask = (0xf << ((idx - 21) * 4));
388 			bits = (mux << ((idx - 21) * 4));
389 		} else if ((bank == 3) && (idx >= 12 && idx <= 13)) {
390 			mask = (0xf << (((idx - 12) * 4) + 8));
391 			bits = (mux << (((idx - 12) * 4) + 8));
392 		} else {
393 			mask = (0x3 << ((idx % 8) * 2));
394 			bits = (mux << ((idx % 8) * 2));
395 		}
396 		regmap_write_4(rm, base + off, mask << 16 | bits);
397 
398 		/* GPIO pad pull down and pull up control */
399 		if (pull >= 0) {
400 			off = 0xa0 + bank * 0x10 + (idx / 8) * 0x04;
401 			mask = (0x3 << ((idx % 8) * 2));
402 			bits = (pull << ((idx % 8) * 2));
403 			regmap_write_4(rm, base + off, mask << 16 | bits);
404 		}
405 
406 		/* GPIO drive strength control */
407 		if (strength >= 0) {
408 			off = 0x100 + bank * 0x10 + (idx / 8) * 0x04;
409 			mask = (0x3 << ((idx % 8) * 2));
410 			bits = (strength << ((idx % 8) * 2));
411 			regmap_write_4(rm, base + off, mask << 16 | bits);
412 		}
413 
414 		splx(s);
415 	}
416 
417 	free(pins, M_TEMP, len);
418 	return 0;
419 
420 fail:
421 	free(pins, M_TEMP, len);
422 	return -1;
423 }
424 
425 /*
426  * Rockchip RK3328
427  */
428 
429 int
430 rk3328_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
431 {
432 	int node;
433 
434 	node = OF_getnodebyphandle(phandle);
435 	if (node == 0)
436 		return -1;
437 
438 	if (OF_getproplen(node, "bias-disable") == 0)
439 		return 0;
440 	if (OF_getproplen(node, "bias-pull-up") == 0)
441 		return 1;
442 	if (OF_getproplen(node, "bias-pull-down") == 0)
443 		return 2;
444 
445 	return -1;
446 }
447 
448 int
449 rk3328_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
450 {
451 	int strength, level;
452 	int levels[4] = { 2, 4, 8, 12 };
453 	int node;
454 
455 	node = OF_getnodebyphandle(phandle);
456 	if (node == 0)
457 		return -1;
458 
459 	strength = OF_getpropint(node, "drive-strength", -1);
460 	if (strength == -1)
461 		return -1;
462 
463 	/* Convert drive strength to level. */
464 	for (level = 3; level >= 0; level--) {
465 		if (strength >= levels[level])
466 			break;
467 	}
468 	return level;
469 }
470 
471 int
472 rk3328_pinctrl(uint32_t phandle, void *cookie)
473 {
474 	struct rkpinctrl_softc *sc = cookie;
475 	uint32_t *pins;
476 	int node, len, i;
477 
478 	KASSERT(sc->sc_grf);
479 
480 	node = OF_getnodebyphandle(phandle);
481 	if (node == 0)
482 		return -1;
483 
484 	len = OF_getproplen(node, "rockchip,pins");
485 	if (len <= 0)
486 		return -1;
487 
488 	pins = malloc(len, M_TEMP, M_WAITOK);
489 	if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
490 		goto fail;
491 
492 	for (i = 0; i < len / sizeof(uint32_t); i += 4) {
493 		struct regmap *rm = sc->sc_grf;
494 		bus_size_t base, off;
495 		uint32_t bank, idx, mux;
496 		int pull, strength;
497 		uint32_t mask, bits;
498 		int s;
499 
500 		bank = pins[i];
501 		idx = pins[i + 1];
502 		mux = pins[i + 2];
503 		pull = rk3288_pull(bank, idx, pins[i + 3]);
504 		strength = rk3288_strength(bank, idx, pins[i + 3]);
505 
506 		if (bank > 3 || idx > 32 || mux > 3)
507 			continue;
508 
509 		base = RK3328_GRF_GPIO0A_IOMUX;
510 
511 		s = splhigh();
512 
513 		/* IOMUX control */
514 		off = bank * 0x10 + (idx / 8) * 0x04;
515 
516 		/* GPIO2B, GPIO2C, GPIO3A and GPIO3B are special. */
517 		if (bank == 2 && idx == 15) {
518 			mask = 0x7;
519 			bits = mux;
520 		} else if (bank == 2 && idx >= 16 && idx <= 20) {
521 			mask = (0x7 << ((idx - 16) * 3));
522 			bits = (mux << ((idx - 16) * 3));
523 		} else if (bank == 2 && idx >= 21 && idx <= 23) {
524 			mask = (0x7 << ((idx - 21) * 3));
525 			bits = (mux << ((idx - 21) * 3));
526 		} else if (bank == 3 && idx <= 4) {
527 			mask = (0x7 << (idx * 3));
528 			bits = (mux << (idx * 3));
529 		} else if (bank == 3 && idx >= 5 && idx <= 7) {
530 			mask = (0x7 << ((idx - 5) * 3));
531 			bits = (mux << ((idx - 5) * 3));
532 		} else if (bank == 3 && idx >= 8 && idx <= 12) {
533 			mask = (0x7 << ((idx - 8) * 3));
534 			bits = (mux << ((idx - 8) * 3));
535 		} else if (bank == 3 && idx >= 13 && idx <= 15) {
536 			mask = (0x7 << ((idx - 13) * 3));
537 			bits = (mux << ((idx - 13) * 3));
538 		} else {
539 			mask = (0x3 << ((idx % 8) * 2));
540 			bits = (mux << ((idx % 8) * 2));
541 		}
542 		if (bank > 2 || (bank == 2 && idx >= 15))
543 			off += 0x04;
544 		if (bank > 2 || (bank == 2 && idx >= 21))
545 			off += 0x04;
546 		if (bank > 3 || (bank == 3 && idx >= 5))
547 			off += 0x04;
548 		if (bank > 3 || (bank == 3 && idx >= 13))
549 			off += 0x04;
550 		regmap_write_4(rm, base + off, mask << 16 | bits);
551 
552 		/* GPIO pad pull down and pull up control */
553 		if (pull >= 0) {
554 			off = 0x100 + bank * 0x10 + (idx / 8) * 0x04;
555 			mask = (0x3 << ((idx % 8) * 2));
556 			bits = (pull << ((idx % 8) * 2));
557 			regmap_write_4(rm, base + off, mask << 16 | bits);
558 		}
559 
560 		/* GPIO drive strength control */
561 		if (strength >= 0) {
562 			off = 0x200 + bank * 0x10 + (idx / 8) * 0x04;
563 			mask = (0x3 << ((idx % 8) * 2));
564 			bits = (strength << ((idx % 8) * 2));
565 			regmap_write_4(rm, base + off, mask << 16 | bits);
566 		}
567 
568 		splx(s);
569 	}
570 
571 	free(pins, M_TEMP, len);
572 	return 0;
573 
574 fail:
575 	free(pins, M_TEMP, len);
576 	return -1;
577 }
578 
579 /*
580  * Rockchip RK3399
581  */
582 
583 int
584 rk3399_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
585 {
586 	int pull_up, pull_down;
587 	int node;
588 
589 	node = OF_getnodebyphandle(phandle);
590 	if (node == 0)
591 		return -1;
592 
593 	if (bank == 2 && idx >= 16) {
594 		pull_up = 3;
595 		pull_down = 1;
596 	} else {
597 		pull_up = 1;
598 		pull_down = 2;
599 	}
600 
601 	if (OF_getproplen(node, "bias-disable") == 0)
602 		return 0;
603 	if (OF_getproplen(node, "bias-pull-up") == 0)
604 		return pull_up;
605 	if (OF_getproplen(node, "bias-pull-down") == 0)
606 		return pull_down;
607 
608 	return -1;
609 }
610 
611 /* Magic because the drive strength configurations vary wildly. */
612 
613 const int rk3399_strength_levels[][8] = {
614 	{ 2, 4, 8, 12 },			/* default */
615 	{ 3, 6, 9, 12 },			/* 1.8V or 3.0V */
616 	{ 5, 10, 15, 20 },			/* 1.8V only */
617 	{ 4, 6, 8, 10, 12, 14, 16, 18 },	/* 1.8V or 3.0V auto */
618 	{ 4, 7, 10, 13, 16, 19, 22, 26 },	/* 3.3V */
619 };
620 
621 const int rk3399_strength_types[][4] = {
622 	{ 2, 2, 0, 0 },
623 	{ 1, 1, 1, 1 },
624 	{ 1, 1, 2, 2 },
625 	{ 4, 4, 4, 1 },
626 	{ 1, 3, 1, 1 },
627 };
628 
629 const int rk3399_strength_regs[][4] = {
630 	{ 0x0080, 0x0088, 0x0090, 0x0098 },
631 	{ 0x00a0, 0x00a8, 0x00b0, 0x00b8 },
632 	{ 0x0100, 0x0104, 0x0108, 0x010c },
633 	{ 0x0110, 0x0118, 0x0120, 0x0128 },
634 	{ 0x012c, 0x0130, 0x0138, 0x013c },
635 };
636 
637 int
638 rk3399_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
639 {
640 	int strength, type, level;
641 	const int *levels;
642 	int node;
643 
644 	node = OF_getnodebyphandle(phandle);
645 	if (node == 0)
646 		return -1;
647 
648 	strength = OF_getpropint(node, "drive-strength", -1);
649 	if (strength == -1)
650 		return -1;
651 
652 	/* Convert drive strength to level. */
653 	type = rk3399_strength_types[bank][idx / 8];
654 	levels = rk3399_strength_levels[type];
655 	for (level = 7; level >= 0; level--) {
656 		if (strength >= levels[level] && levels[level] > 0)
657 			break;
658 	}
659 	return level;
660 }
661 
662 int
663 rk3399_pinctrl(uint32_t phandle, void *cookie)
664 {
665 	struct rkpinctrl_softc *sc = cookie;
666 	uint32_t *pins;
667 	int node, len, i;
668 
669 	KASSERT(sc->sc_grf);
670 	KASSERT(sc->sc_pmu);
671 
672 	node = OF_getnodebyphandle(phandle);
673 	if (node == 0)
674 		return -1;
675 
676 	len = OF_getproplen(node, "rockchip,pins");
677 	if (len <= 0)
678 		return -1;
679 
680 	pins = malloc(len, M_TEMP, M_WAITOK);
681 	if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
682 		goto fail;
683 
684 	for (i = 0; i < len / sizeof(uint32_t); i += 4) {
685 		struct regmap *rm;
686 		bus_size_t base, off;
687 		uint32_t bank, idx, mux;
688 		int pull, strength, type, shift;
689 		uint32_t mask, bits;
690 		int s;
691 
692 		bank = pins[i];
693 		idx = pins[i + 1];
694 		mux = pins[i + 2];
695 		pull = rk3399_pull(bank, idx, pins[i + 3]);
696 		strength = rk3399_strength(bank, idx, pins[i + 3]);
697 
698 		if (bank > 5 || idx > 32 || mux > 3)
699 			continue;
700 
701 		/* Bank 0 and 1 live in the PMU. */
702 		if (bank < 2) {
703 			rm = sc->sc_pmu;
704 			base = RK3399_PMUGRF_GPIO0A_IOMUX;
705 		} else {
706 			rm = sc->sc_grf;
707 			base = RK3399_GRF_GPIO2A_IOMUX - 0x20;
708 		}
709 
710 		s = splhigh();
711 
712 		/* IOMUX control */
713 		off = bank * 0x10 + (idx / 8) * 0x04;
714 		mask = (0x3 << ((idx % 8) * 2));
715 		bits = (mux << ((idx % 8) * 2));
716 		regmap_write_4(rm, base + off, mask << 16 | bits);
717 
718 		/* GPIO pad pull down and pull up control */
719 		if (pull >= 0) {
720 			off = 0x40 + bank * 0x10 + (idx / 8) * 0x04;
721 			mask = (0x3 << ((idx % 8) * 2));
722 			bits = (pull << ((idx % 8) * 2));
723 			regmap_write_4(rm, base + off, mask << 16 | bits);
724 		}
725 
726 		/* GPIO drive strength control */
727 		if (strength >= 0) {
728 			off = rk3399_strength_regs[bank][idx / 8];
729 			type = rk3399_strength_types[bank][idx / 8];
730 			shift = (type > 2) ? 3 : 2;
731 			mask = (((1 << shift) - 1) << ((idx % 8) * shift));
732 			bits = (strength << ((idx % 8) * shift));
733 			if (mask & 0x0000ffff) {
734 				regmap_write_4(rm, base + off,
735 				    mask << 16 | (bits & 0x0000ffff));
736 			}
737 			if (mask & 0xffff0000) {
738 				regmap_write_4(rm, base + off + 0x04,
739 				    (mask & 0xffff0000) | bits >> 16);
740 			}
741 		}
742 
743 		splx(s);
744 	}
745 
746 	free(pins, M_TEMP, len);
747 	return 0;
748 
749 fail:
750 	free(pins, M_TEMP, len);
751 	return -1;
752 }
753 
754 /*
755  * Rockchip RK3568
756  */
757 
758 int
759 rk3568_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
760 {
761 	int node;
762 
763 	node = OF_getnodebyphandle(phandle);
764 	if (node == 0)
765 		return -1;
766 
767 	if (OF_getproplen(node, "bias-disable") == 0)
768 		return 0;
769 	if (OF_getproplen(node, "bias-pull-up") == 0)
770 		return 1;
771 	if (OF_getproplen(node, "bias-pull-down") == 0)
772 		return 2;
773 
774 	return -1;
775 }
776 
777 int
778 rk3568_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
779 {
780 	int node;
781 
782 	node = OF_getnodebyphandle(phandle);
783 	if (node == 0)
784 		return -1;
785 
786 	return OF_getpropint(node, "drive-strength", -1);
787 }
788 
789 int
790 rk3568_schmitt(uint32_t bank, uint32_t idx, uint32_t phandle)
791 {
792 	int node;
793 
794 	node = OF_getnodebyphandle(phandle);
795 	if (node == 0)
796 		return -1;
797 
798 	if (OF_getproplen(node, "input-schmitt-disable") == 0)
799 		return 1;
800 	if (OF_getproplen(node, "input-schmitt-enable") == 0)
801 		return 2;
802 
803 	return -1;
804 }
805 
806 int
807 rk3568_pinctrl(uint32_t phandle, void *cookie)
808 {
809 	struct rkpinctrl_softc *sc = cookie;
810 	uint32_t *pins;
811 	int node, len, i;
812 
813 	KASSERT(sc->sc_grf);
814 	KASSERT(sc->sc_pmu);
815 
816 	node = OF_getnodebyphandle(phandle);
817 	if (node == 0)
818 		return -1;
819 
820 	len = OF_getproplen(node, "rockchip,pins");
821 	if (len <= 0)
822 		return -1;
823 
824 	pins = malloc(len, M_TEMP, M_WAITOK);
825 	if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
826 		goto fail;
827 
828 	for (i = 0; i < len / sizeof(uint32_t); i += 4) {
829 		struct regmap *rm;
830 		bus_size_t iomux_base, p_base, ds_base, ie_base, off;
831 		uint32_t bank, idx, mux;
832 		int pull, strength, schmitt;
833 		uint32_t mask, bits;
834 		int s;
835 
836 		bank = pins[i];
837 		idx = pins[i + 1];
838 		mux = pins[i + 2];
839 		pull = rk3568_pull(bank, idx, pins[i + 3]);
840 		strength = rk3568_strength(bank, idx, pins[i + 3]);
841 		schmitt = rk3568_schmitt(bank, idx, pins[i + 3]);
842 
843 		if (bank > 5 || idx > 32 || mux > 7)
844 			continue;
845 
846 		/* Bank 0 lives in the PMU. */
847 		if (bank < 1) {
848 			rm = sc->sc_pmu;
849 			iomux_base = RK3568_PMUGRF_GPIO0A_IOMUX_L;
850 			p_base = RK3568_PMUGRF_GPIO0A_P;
851 			ds_base = RK3568_PMUGRF_GPIO0A_DS_0;
852 			ie_base = RK3568_PMUGRF_GPIO0A_IE;
853 		} else {
854 			rm = sc->sc_grf;
855 			iomux_base = RK3568_GRF_GPIO1A_IOMUX_L;
856 			p_base = RK3568_GRF_GPIO1A_P;
857 			ds_base = RK3568_GRF_GPIO1A_DS_0;
858 			ie_base = RK3568_GRF_GPIO1A_IE;
859 			bank = bank - 1;
860 		}
861 
862 		s = splhigh();
863 
864 		/* IOMUX control */
865 		off = bank * 0x20 + (idx / 4) * 0x04;
866 		mask = (0x7 << ((idx % 4) * 4));
867 		bits = (mux << ((idx % 4) * 4));
868 		regmap_write_4(rm, iomux_base + off, mask << 16 | bits);
869 
870 		/* GPIO pad pull down and pull up control */
871 		if (pull >= 0) {
872 			off = bank * 0x10 + (idx / 8) * 0x04;
873 			mask = (0x3 << ((idx % 8) * 2));
874 			bits = (pull << ((idx % 8) * 2));
875 			regmap_write_4(rm, p_base + off, mask << 16 | bits);
876 		}
877 
878 		/* GPIO drive strength control */
879 		if (strength >= 0) {
880 			off = bank * 0x40 + (idx / 2) * 0x04;
881 			mask = (0x3f << ((idx % 2) * 8));
882 			bits = ((1 << (strength + 1)) - 1) << ((idx % 2) * 8);
883 			regmap_write_4(rm, ds_base + off, mask << 16 | bits);
884 		}
885 
886 		/* GPIO Schmitt trigger. */
887 		if (schmitt >= 0) {
888 			off = bank * 0x10 + (idx / 8) * 0x04;
889 			mask = (0x3 << ((idx % 8) * 2));
890 			bits = schmitt << ((idx % 8) * 2);
891 			regmap_write_4(rm, ie_base + off, mask << 16 | bits);
892 		}
893 
894 		splx(s);
895 	}
896 
897 	free(pins, M_TEMP, len);
898 	return 0;
899 
900 fail:
901 	free(pins, M_TEMP, len);
902 	return -1;
903 }
904