xref: /openbsd-src/sys/dev/fdt/rkpinctrl.c (revision 1a8dbaac879b9f3335ad7fb25429ce63ac1d6bac)
1 /*	$OpenBSD: rkpinctrl.c,v 1.6 2020/09/04 01:11:16 jmatthew 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 struct rkpinctrl_softc {
53 	struct simplebus_softc	sc_sbus;
54 
55 	struct regmap		*sc_grf;
56 	struct regmap		*sc_pmu;
57 };
58 
59 int	rkpinctrl_match(struct device *, void *, void *);
60 void	rkpinctrl_attach(struct device *, struct device *, void *);
61 
62 struct cfattach	rkpinctrl_ca = {
63 	sizeof (struct rkpinctrl_softc), rkpinctrl_match, rkpinctrl_attach
64 };
65 
66 struct cfdriver rkpinctrl_cd = {
67 	NULL, "rkpinctrl", DV_DULL
68 };
69 
70 int	rk3288_pinctrl(uint32_t, void *);
71 int	rk3308_pinctrl(uint32_t, void *);
72 int	rk3328_pinctrl(uint32_t, void *);
73 int	rk3399_pinctrl(uint32_t, void *);
74 
75 int
76 rkpinctrl_match(struct device *parent, void *match, void *aux)
77 {
78 	struct fdt_attach_args *faa = aux;
79 
80 	return (OF_is_compatible(faa->fa_node, "rockchip,rk3288-pinctrl") ||
81 	    OF_is_compatible(faa->fa_node, "rockchip,rk3308-pinctrl") ||
82 	    OF_is_compatible(faa->fa_node, "rockchip,rk3328-pinctrl") ||
83 	    OF_is_compatible(faa->fa_node, "rockchip,rk3399-pinctrl"));
84 }
85 
86 void
87 rkpinctrl_attach(struct device *parent, struct device *self, void *aux)
88 {
89 	struct rkpinctrl_softc *sc = (struct rkpinctrl_softc *)self;
90 	struct fdt_attach_args *faa = aux;
91 	uint32_t grf, pmu;
92 
93 	grf = OF_getpropint(faa->fa_node, "rockchip,grf", 0);
94 	pmu = OF_getpropint(faa->fa_node, "rockchip,pmu", 0);
95 	sc->sc_grf = regmap_byphandle(grf);
96 	sc->sc_pmu = regmap_byphandle(pmu);
97 
98 	if (sc->sc_grf == NULL && sc->sc_pmu == NULL) {
99 		printf(": no registers\n");
100 		return;
101 	}
102 
103 	if (OF_is_compatible(faa->fa_node, "rockchip,rk3288-pinctrl"))
104 		pinctrl_register(faa->fa_node, rk3288_pinctrl, sc);
105 	else if (OF_is_compatible(faa->fa_node, "rockchip,rk3308-pinctrl"))
106 		pinctrl_register(faa->fa_node, rk3308_pinctrl, sc);
107 	else if (OF_is_compatible(faa->fa_node, "rockchip,rk3328-pinctrl"))
108 		pinctrl_register(faa->fa_node, rk3328_pinctrl, sc);
109 	else
110 		pinctrl_register(faa->fa_node, rk3399_pinctrl, sc);
111 
112 	/* Attach GPIO banks. */
113 	simplebus_attach(parent, &sc->sc_sbus.sc_dev, faa);
114 }
115 
116 /*
117  * Rockchip RK3288
118  */
119 
120 int
121 rk3288_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
122 {
123 	int node;
124 
125 	node = OF_getnodebyphandle(phandle);
126 	if (node == 0)
127 		return -1;
128 
129 	/* XXX */
130 	if (bank == 0)
131 		return -1;
132 
133 	if (OF_getproplen(node, "bias-disable") == 0)
134 		return 0;
135 	if (OF_getproplen(node, "bias-pull-up") == 0)
136 		return 1;
137 	if (OF_getproplen(node, "bias-pull-down") == 0)
138 		return 2;
139 
140 	return -1;
141 }
142 
143 int
144 rk3288_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
145 {
146 	int strength, level;
147 	int levels[4] = { 2, 4, 8, 12 };
148 	int node;
149 
150 	node = OF_getnodebyphandle(phandle);
151 	if (node == 0)
152 		return -1;
153 
154 	/* XXX */
155 	if (bank == 0)
156 		return -1;
157 
158 	strength = OF_getpropint(node, "drive-strength", -1);
159 	if (strength == -1)
160 		return -1;
161 
162 	/* Convert drive strength to level. */
163 	for (level = 3; level >= 0; level--) {
164 		if (strength >= levels[level])
165 			break;
166 	}
167 	return level;
168 }
169 
170 int
171 rk3288_pinctrl(uint32_t phandle, void *cookie)
172 {
173 	struct rkpinctrl_softc *sc = cookie;
174 	uint32_t *pins;
175 	int node, len, i;
176 
177 	KASSERT(sc->sc_grf);
178 	KASSERT(sc->sc_pmu);
179 
180 	node = OF_getnodebyphandle(phandle);
181 	if (node == 0)
182 		return -1;
183 
184 	len = OF_getproplen(node, "rockchip,pins");
185 	if (len <= 0)
186 		return -1;
187 
188 	pins = malloc(len, M_TEMP, M_WAITOK);
189 	if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
190 		goto fail;
191 
192 	for (i = 0; i < len / sizeof(uint32_t); i += 4) {
193 		struct regmap *rm;
194 		bus_size_t base, off;
195 		uint32_t bank, idx, mux;
196 		int pull, strength;
197 		uint32_t mask, bits;
198 		int s;
199 
200 		bank = pins[i];
201 		idx = pins[i + 1];
202 		mux = pins[i + 2];
203 		pull = rk3288_pull(bank, idx, pins[i + 3]);
204 		strength = rk3288_strength(bank, idx, pins[i + 3]);
205 
206 		if (bank > 8 || idx > 32 || mux > 7)
207 			continue;
208 
209 		/* Bank 0 lives in the PMU. */
210 		if (bank < 1) {
211 			rm = sc->sc_pmu;
212 			base = RK3288_PMUGRF_GPIO0A_IOMUX;
213 		} else {
214 			rm = sc->sc_grf;
215 			base = RK3288_GRF_GPIO1A_IOMUX - 0x10;
216 		}
217 
218 		s = splhigh();
219 
220 		/* IOMUX control */
221 		off = bank * 0x10 + (idx / 8) * 0x04;
222 
223 		/* GPIO3D, GPIO4A and GPIO4B are special. */
224 		if ((bank == 3 && idx >= 24) || (bank == 4 && idx < 16)) {
225 			mask = (0x7 << ((idx % 4) * 4));
226 			bits = (mux << ((idx % 4) * 4));
227 		} else {
228 			mask = (0x3 << ((idx % 8) * 2));
229 			bits = (mux << ((idx % 8) * 2));
230 		}
231 		if (bank > 3 || (bank == 3 && idx >= 28))
232 			off += 0x04;
233 		if (bank > 4 || (bank == 4 && idx >= 4))
234 			off += 0x04;
235 		if (bank > 4 || (bank == 4 && idx >= 12))
236 			off += 0x04;
237 		regmap_write_4(rm, base + off, mask << 16 | bits);
238 
239 		/* GPIO pad pull down and pull up control */
240 		if (pull >= 0) {
241 			off = 0x140 + bank * 0x10 + (idx / 8) * 0x04;
242 			mask = (0x3 << ((idx % 8) * 2));
243 			bits = (pull << ((idx % 8) * 2));
244 			regmap_write_4(rm, base + off, mask << 16 | bits);
245 		}
246 
247 		/* GPIO drive strength control */
248 		if (strength >= 0) {
249 			off = 0x1c0 + bank * 0x10 + (idx / 8) * 0x04;
250 			mask = (0x3 << ((idx % 8) * 2));
251 			bits = (strength << ((idx % 8) * 2));
252 			regmap_write_4(rm, base + off, mask << 16 | bits);
253 		}
254 
255 		splx(s);
256 	}
257 
258 	free(pins, M_TEMP, len);
259 	return 0;
260 
261 fail:
262 	free(pins, M_TEMP, len);
263 	return -1;
264 }
265 
266 /*
267  * Rockchip RK3308
268  */
269 
270 int
271 rk3308_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
272 {
273 	int node;
274 
275 	node = OF_getnodebyphandle(phandle);
276 	if (node == 0)
277 		return -1;
278 
279 	if (OF_getproplen(node, "bias-disable") == 0)
280 		return 0;
281 	if (OF_getproplen(node, "bias-pull-up") == 0)
282 		return 1;
283 	if (OF_getproplen(node, "bias-pull-down") == 0)
284 		return 2;
285 
286 	return -1;
287 }
288 
289 int
290 rk3308_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
291 {
292 	int strength, level;
293 	int levels[4] = { 2, 4, 8, 12 };
294 	int node;
295 
296 	node = OF_getnodebyphandle(phandle);
297 	if (node == 0)
298 		return -1;
299 
300 	strength = OF_getpropint(node, "drive-strength", -1);
301 	if (strength == -1)
302 		return -1;
303 
304 	/* Convert drive strength to level. */
305 	for (level = 3; level >= 0; level--) {
306 		if (strength >= levels[level])
307 			break;
308 	}
309 	return level;
310 }
311 
312 int
313 rk3308_pinctrl(uint32_t phandle, void *cookie)
314 {
315 	struct rkpinctrl_softc *sc = cookie;
316 	uint32_t *pins;
317 	int node, len, i;
318 
319 	KASSERT(sc->sc_grf);
320 
321 	node = OF_getnodebyphandle(phandle);
322 	if (node == 0)
323 		return -1;
324 
325 	len = OF_getproplen(node, "rockchip,pins");
326 	if (len <= 0)
327 		return -1;
328 
329 	pins = malloc(len, M_TEMP, M_WAITOK);
330 	if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
331 		goto fail;
332 
333 	for (i = 0; i < len / sizeof(uint32_t); i += 4) {
334 		struct regmap *rm = sc->sc_grf;
335 		bus_size_t base, off;
336 		uint32_t bank, idx, mux;
337 		int pull, strength;
338 		uint32_t mask, bits;
339 		int s;
340 
341 		bank = pins[i];
342 		idx = pins[i + 1];
343 		mux = pins[i + 2];
344 		pull = rk3308_pull(bank, idx, pins[i + 3]);
345 		strength = rk3308_strength(bank, idx, pins[i + 3]);
346 
347 		if (bank > 4 || idx > 32 || mux > 7)
348 			continue;
349 
350 		base = RK3308_GRF_GPIO0A_IOMUX;
351 
352 		s = splhigh();
353 
354 		/* IOMUX control */
355 		off = bank * 0x20 + (idx / 8) * 0x08;
356 
357 		/* GPIO1B, GPIO1C and GPIO3B are special. */
358 		if ((bank == 1) && (idx == 14)) {
359 			mask = (0xf << 12);
360 			bits = (mux << 12);
361 		} else if ((bank == 1) && (idx == 15)) {
362 			off += 4;
363 			mask = 0x3;
364 			bits = mux;
365 		} else if ((bank == 1) && (idx >= 16 && idx <= 17)) {
366 			mask = (0x3 << ((idx - 16) * 2));
367 			bits = (mux << ((idx - 16) * 2));
368 		} else if ((bank == 1) && (idx >= 18 && idx <= 20)) {
369 			mask = (0xf << (((idx - 18) * 4) + 4));
370 			bits = (mux << (((idx - 18) * 4) + 4));
371 		} else if ((bank == 1) && (idx >= 21 && idx <= 23)) {
372 			off += 4;
373 			mask = (0xf << ((idx - 21) * 4));
374 			bits = (mux << ((idx - 21) * 4));
375 		} else if ((bank == 3) && (idx >= 12 && idx <= 13)) {
376 			mask = (0xf << (((idx - 12) * 4) + 8));
377 			bits = (mux << (((idx - 12) * 4) + 8));
378 		} else {
379 			mask = (0x3 << ((idx % 8) * 2));
380 			bits = (mux << ((idx % 8) * 2));
381 		}
382 		regmap_write_4(rm, base + off, mask << 16 | bits);
383 
384 		/* GPIO pad pull down and pull up control */
385 		if (pull >= 0) {
386 			off = 0xa0 + bank * 0x10 + (idx / 8) * 0x04;
387 			mask = (0x3 << ((idx % 8) * 2));
388 			bits = (pull << ((idx % 8) * 2));
389 			regmap_write_4(rm, base + off, mask << 16 | bits);
390 		}
391 
392 		/* GPIO drive strength control */
393 		if (strength >= 0) {
394 			off = 0x100 + bank * 0x10 + (idx / 8) * 0x04;
395 			mask = (0x3 << ((idx % 8) * 2));
396 			bits = (strength << ((idx % 8) * 2));
397 			regmap_write_4(rm, base + off, mask << 16 | bits);
398 		}
399 
400 		splx(s);
401 	}
402 
403 	free(pins, M_TEMP, len);
404 	return 0;
405 
406 fail:
407 	free(pins, M_TEMP, len);
408 	return -1;
409 }
410 
411 /*
412  * Rockchip RK3328
413  */
414 
415 int
416 rk3328_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
417 {
418 	int node;
419 
420 	node = OF_getnodebyphandle(phandle);
421 	if (node == 0)
422 		return -1;
423 
424 	if (OF_getproplen(node, "bias-disable") == 0)
425 		return 0;
426 	if (OF_getproplen(node, "bias-pull-up") == 0)
427 		return 1;
428 	if (OF_getproplen(node, "bias-pull-down") == 0)
429 		return 2;
430 
431 	return -1;
432 }
433 
434 int
435 rk3328_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
436 {
437 	int strength, level;
438 	int levels[4] = { 2, 4, 8, 12 };
439 	int node;
440 
441 	node = OF_getnodebyphandle(phandle);
442 	if (node == 0)
443 		return -1;
444 
445 	strength = OF_getpropint(node, "drive-strength", -1);
446 	if (strength == -1)
447 		return -1;
448 
449 	/* Convert drive strength to level. */
450 	for (level = 3; level >= 0; level--) {
451 		if (strength >= levels[level])
452 			break;
453 	}
454 	return level;
455 }
456 
457 int
458 rk3328_pinctrl(uint32_t phandle, void *cookie)
459 {
460 	struct rkpinctrl_softc *sc = cookie;
461 	uint32_t *pins;
462 	int node, len, i;
463 
464 	KASSERT(sc->sc_grf);
465 
466 	node = OF_getnodebyphandle(phandle);
467 	if (node == 0)
468 		return -1;
469 
470 	len = OF_getproplen(node, "rockchip,pins");
471 	if (len <= 0)
472 		return -1;
473 
474 	pins = malloc(len, M_TEMP, M_WAITOK);
475 	if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
476 		goto fail;
477 
478 	for (i = 0; i < len / sizeof(uint32_t); i += 4) {
479 		struct regmap *rm = sc->sc_grf;
480 		bus_size_t base, off;
481 		uint32_t bank, idx, mux;
482 		int pull, strength;
483 		uint32_t mask, bits;
484 		int s;
485 
486 		bank = pins[i];
487 		idx = pins[i + 1];
488 		mux = pins[i + 2];
489 		pull = rk3288_pull(bank, idx, pins[i + 3]);
490 		strength = rk3288_strength(bank, idx, pins[i + 3]);
491 
492 		if (bank > 3 || idx > 32 || mux > 3)
493 			continue;
494 
495 		base = RK3328_GRF_GPIO0A_IOMUX;
496 
497 		s = splhigh();
498 
499 		/* IOMUX control */
500 		off = bank * 0x10 + (idx / 8) * 0x04;
501 
502 		/* GPIO2B, GPIO2C, GPIO3A and GPIO3B are special. */
503 		if (bank == 2 && idx == 15) {
504 			mask = 0x7;
505 			bits = mux;
506 		} else if (bank == 2 && idx >= 16 && idx <= 20) {
507 			mask = (0x7 << ((idx - 16) * 3));
508 			bits = (mux << ((idx - 16) * 3));
509 		} else if (bank == 2 && idx >= 21 && idx <= 23) {
510 			mask = (0x7 << ((idx - 21) * 3));
511 			bits = (mux << ((idx - 21) * 3));
512 		} else if (bank == 3 && idx <= 4) {
513 			mask = (0x7 << (idx * 3));
514 			bits = (mux << (idx * 3));
515 		} else if (bank == 3 && idx >= 5 && idx <= 7) {
516 			mask = (0x7 << ((idx - 5) * 3));
517 			bits = (mux << ((idx - 5) * 3));
518 		} else if (bank == 3 && idx >= 8 && idx <= 12) {
519 			mask = (0x7 << ((idx - 8) * 3));
520 			bits = (mux << ((idx - 8) * 3));
521 		} else if (bank == 3 && idx >= 13 && idx <= 15) {
522 			mask = (0x7 << ((idx - 13) * 3));
523 			bits = (mux << ((idx - 13) * 3));
524 		} else {
525 			mask = (0x3 << ((idx % 8) * 2));
526 			bits = (mux << ((idx % 8) * 2));
527 		}
528 		if (bank > 2 || (bank == 2 && idx >= 15))
529 			off += 0x04;
530 		if (bank > 2 || (bank == 2 && idx >= 21))
531 			off += 0x04;
532 		if (bank > 3 || (bank == 3 && idx >= 5))
533 			off += 0x04;
534 		if (bank > 3 || (bank == 3 && idx >= 13))
535 			off += 0x04;
536 		regmap_write_4(rm, base + off, mask << 16 | bits);
537 
538 		/* GPIO pad pull down and pull up control */
539 		if (pull >= 0) {
540 			off = 0x100 + bank * 0x10 + (idx / 8) * 0x04;
541 			mask = (0x3 << ((idx % 8) * 2));
542 			bits = (pull << ((idx % 8) * 2));
543 			regmap_write_4(rm, base + off, mask << 16 | bits);
544 		}
545 
546 		/* GPIO drive strength control */
547 		if (strength >= 0) {
548 			off = 0x200 + bank * 0x10 + (idx / 8) * 0x04;
549 			mask = (0x3 << ((idx % 8) * 2));
550 			bits = (strength << ((idx % 8) * 2));
551 			regmap_write_4(rm, base + off, mask << 16 | bits);
552 		}
553 
554 		splx(s);
555 	}
556 
557 	free(pins, M_TEMP, len);
558 	return 0;
559 
560 fail:
561 	free(pins, M_TEMP, len);
562 	return -1;
563 }
564 
565 /*
566  * Rockchip RK3399
567  */
568 
569 int
570 rk3399_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
571 {
572 	int pull_up, pull_down;
573 	int node;
574 
575 	node = OF_getnodebyphandle(phandle);
576 	if (node == 0)
577 		return -1;
578 
579 	if (bank == 2 && idx >= 16) {
580 		pull_up = 3;
581 		pull_down = 1;
582 	} else {
583 		pull_up = 1;
584 		pull_down = 2;
585 	}
586 
587 	if (OF_getproplen(node, "bias-disable") == 0)
588 		return 0;
589 	if (OF_getproplen(node, "bias-pull-up") == 0)
590 		return pull_up;
591 	if (OF_getproplen(node, "bias-pull-down") == 0)
592 		return pull_down;
593 
594 	return -1;
595 }
596 
597 /* Magic because the drive strength configurations vary wildly. */
598 
599 int rk3399_strength_levels[][8] = {
600 	{ 2, 4, 8, 12 },			/* default */
601 	{ 3, 6, 9, 12 },			/* 1.8V or 3.0V */
602 	{ 5, 10, 15, 20 },			/* 1.8V only */
603 	{ 4, 6, 8, 10, 12, 14, 16, 18 },	/* 1.8V or 3.0V auto */
604 	{ 4, 7, 10, 13, 16, 19, 22, 26 },	/* 3.3V */
605 };
606 
607 int rk3399_strength_types[][4] = {
608 	{ 2, 2, 0, 0 },
609 	{ 1, 1, 1, 1 },
610 	{ 1, 1, 2, 2 },
611 	{ 4, 4, 4, 1 },
612 	{ 1, 3, 1, 1 },
613 };
614 
615 int rk3399_strength_regs[][4] = {
616 	{ 0x0080, 0x0088, 0x0090, 0x0098 },
617 	{ 0x00a0, 0x00a8, 0x00b0, 0x00b8 },
618 	{ 0x0100, 0x0104, 0x0108, 0x010c },
619 	{ 0x0110, 0x0118, 0x0120, 0x0128 },
620 	{ 0x012c, 0x0130, 0x0138, 0x013c },
621 };
622 
623 int
624 rk3399_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
625 {
626 	int strength, type, level;
627 	int *levels;
628 	int node;
629 
630 	node = OF_getnodebyphandle(phandle);
631 	if (node == 0)
632 		return -1;
633 
634 	strength = OF_getpropint(node, "drive-strength", -1);
635 	if (strength == -1)
636 		return -1;
637 
638 	/* Convert drive strength to level. */
639 	type = rk3399_strength_types[bank][idx / 8];
640 	levels = rk3399_strength_levels[type];
641 	for (level = 7; level >= 0; level--) {
642 		if (strength >= levels[level] && levels[level] > 0)
643 			break;
644 	}
645 	return level;
646 }
647 
648 int
649 rk3399_pinctrl(uint32_t phandle, void *cookie)
650 {
651 	struct rkpinctrl_softc *sc = cookie;
652 	uint32_t *pins;
653 	int node, len, i;
654 
655 	KASSERT(sc->sc_grf);
656 	KASSERT(sc->sc_pmu);
657 
658 	node = OF_getnodebyphandle(phandle);
659 	if (node == 0)
660 		return -1;
661 
662 	len = OF_getproplen(node, "rockchip,pins");
663 	if (len <= 0)
664 		return -1;
665 
666 	pins = malloc(len, M_TEMP, M_WAITOK);
667 	if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
668 		goto fail;
669 
670 	for (i = 0; i < len / sizeof(uint32_t); i += 4) {
671 		struct regmap *rm;
672 		bus_size_t base, off;
673 		uint32_t bank, idx, mux;
674 		int pull, strength, type, shift;
675 		uint32_t mask, bits;
676 		int s;
677 
678 		bank = pins[i];
679 		idx = pins[i + 1];
680 		mux = pins[i + 2];
681 		pull = rk3399_pull(bank, idx, pins[i + 3]);
682 		strength = rk3399_strength(bank, idx, pins[i + 3]);
683 
684 		if (bank > 5 || idx > 32 || mux > 3)
685 			continue;
686 
687 		/* Bank 0 and 1 live in the PMU. */
688 		if (bank < 2) {
689 			rm = sc->sc_pmu;
690 			base = RK3399_PMUGRF_GPIO0A_IOMUX;
691 		} else {
692 			rm = sc->sc_grf;
693 			base = RK3399_GRF_GPIO2A_IOMUX - 0x20;
694 		}
695 
696 		s = splhigh();
697 
698 		/* IOMUX control */
699 		off = bank * 0x10 + (idx / 8) * 0x04;
700 		mask = (0x3 << ((idx % 8) * 2));
701 		bits = (mux << ((idx % 8) * 2));
702 		regmap_write_4(rm, base + off, mask << 16 | bits);
703 
704 		/* GPIO pad pull down and pull up control */
705 		if (pull >= 0) {
706 			off = 0x40 + bank * 0x10 + (idx / 8) * 0x04;
707 			mask = (0x3 << ((idx % 8) * 2));
708 			bits = (pull << ((idx % 8) * 2));
709 			regmap_write_4(rm, base + off, mask << 16 | bits);
710 		}
711 
712 		/* GPIO drive strength control */
713 		if (strength >= 0) {
714 			off = rk3399_strength_regs[bank][idx / 8];
715 			type = rk3399_strength_types[bank][idx / 8];
716 			shift = (type > 2) ? 3 : 2;
717 			mask = (((1 << shift) - 1) << ((idx % 8) * shift));
718 			bits = (strength << ((idx % 8) * shift));
719 			if (mask & 0x0000ffff) {
720 				regmap_write_4(rm, base + off,
721 				    mask << 16 | (bits & 0x0000ffff));
722 			}
723 			if (mask & 0xffff0000) {
724 				regmap_write_4(rm, base + off + 0x04,
725 				    (mask & 0xffff0000) | bits >> 16);
726 			}
727 		}
728 
729 		splx(s);
730 	}
731 
732 	free(pins, M_TEMP, len);
733 	return 0;
734 
735 fail:
736 	free(pins, M_TEMP, len);
737 	return -1;
738 }
739