1 /* $OpenBSD: rkpinctrl.c,v 1.15 2024/02/11 16:01:09 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 #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
rkpinctrl_match(struct device * parent,void * match,void * aux)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
rkpinctrl_attach(struct device * parent,struct device * self,void * aux)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
rk3288_pull(uint32_t bank,uint32_t idx,uint32_t phandle)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
rk3288_strength(uint32_t bank,uint32_t idx,uint32_t phandle)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
rk3288_pinctrl(uint32_t phandle,void * cookie)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
264 if (bank > 8 || idx >= 32 || mux > 7)
265 continue;
266
267 pull = rk3288_pull(bank, idx, pins[i + 3]);
268 strength = rk3288_strength(bank, idx, pins[i + 3]);
269
270 /* Bank 0 lives in the PMU. */
271 if (bank < 1) {
272 rm = sc->sc_pmu;
273 base = RK3288_PMUGRF_GPIO0A_IOMUX;
274 } else {
275 rm = sc->sc_grf;
276 base = RK3288_GRF_GPIO1A_IOMUX - 0x10;
277 }
278
279 s = splhigh();
280
281 /* IOMUX control */
282 off = bank * 0x10 + (idx / 8) * 0x04;
283
284 /* GPIO3D, GPIO4A and GPIO4B are special. */
285 if ((bank == 3 && idx >= 24) || (bank == 4 && idx < 16)) {
286 mask = (0x7 << ((idx % 4) * 4));
287 bits = (mux << ((idx % 4) * 4));
288 } else {
289 mask = (0x3 << ((idx % 8) * 2));
290 bits = (mux << ((idx % 8) * 2));
291 }
292 if (bank > 3 || (bank == 3 && idx >= 28))
293 off += 0x04;
294 if (bank > 4 || (bank == 4 && idx >= 4))
295 off += 0x04;
296 if (bank > 4 || (bank == 4 && idx >= 12))
297 off += 0x04;
298 regmap_write_4(rm, base + off, mask << 16 | bits);
299
300 /* GPIO pad pull down and pull up control */
301 if (pull >= 0) {
302 off = 0x140 + bank * 0x10 + (idx / 8) * 0x04;
303 mask = (0x3 << ((idx % 8) * 2));
304 bits = (pull << ((idx % 8) * 2));
305 regmap_write_4(rm, base + off, mask << 16 | bits);
306 }
307
308 /* GPIO drive strength control */
309 if (strength >= 0) {
310 off = 0x1c0 + bank * 0x10 + (idx / 8) * 0x04;
311 mask = (0x3 << ((idx % 8) * 2));
312 bits = (strength << ((idx % 8) * 2));
313 regmap_write_4(rm, base + off, mask << 16 | bits);
314 }
315
316 splx(s);
317 }
318
319 free(pins, M_TEMP, len);
320 return 0;
321
322 fail:
323 free(pins, M_TEMP, len);
324 return -1;
325 }
326
327 /*
328 * Rockchip RK3308
329 */
330
331 int
rk3308_pull(uint32_t bank,uint32_t idx,uint32_t phandle)332 rk3308_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
333 {
334 int node;
335
336 node = OF_getnodebyphandle(phandle);
337 if (node == 0)
338 return -1;
339
340 if (OF_getproplen(node, "bias-disable") == 0)
341 return 0;
342 if (OF_getproplen(node, "bias-pull-up") == 0)
343 return 1;
344 if (OF_getproplen(node, "bias-pull-down") == 0)
345 return 2;
346
347 return -1;
348 }
349
350 int
rk3308_strength(uint32_t bank,uint32_t idx,uint32_t phandle)351 rk3308_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
352 {
353 int strength, level;
354 int levels[4] = { 2, 4, 8, 12 };
355 int node;
356
357 node = OF_getnodebyphandle(phandle);
358 if (node == 0)
359 return -1;
360
361 strength = OF_getpropint(node, "drive-strength", -1);
362 if (strength == -1)
363 return -1;
364
365 /* Convert drive strength to level. */
366 for (level = 3; level >= 0; level--) {
367 if (strength >= levels[level])
368 break;
369 }
370 return level;
371 }
372
373 int
rk3308_pinctrl(uint32_t phandle,void * cookie)374 rk3308_pinctrl(uint32_t phandle, void *cookie)
375 {
376 struct rkpinctrl_softc *sc = cookie;
377 uint32_t *pins;
378 int node, len, i;
379
380 KASSERT(sc->sc_grf);
381
382 node = OF_getnodebyphandle(phandle);
383 if (node == 0)
384 return -1;
385
386 len = OF_getproplen(node, "rockchip,pins");
387 if (len <= 0)
388 return -1;
389
390 pins = malloc(len, M_TEMP, M_WAITOK);
391 if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
392 goto fail;
393
394 for (i = 0; i < len / sizeof(uint32_t); i += 4) {
395 struct regmap *rm = sc->sc_grf;
396 bus_size_t base, off;
397 uint32_t bank, idx, mux;
398 int pull, strength;
399 uint32_t mask, bits;
400 int s;
401
402 bank = pins[i];
403 idx = pins[i + 1];
404 mux = pins[i + 2];
405
406 if (bank > 4 || idx >= 32 || mux > 7)
407 continue;
408
409 pull = rk3308_pull(bank, idx, pins[i + 3]);
410 strength = rk3308_strength(bank, idx, pins[i + 3]);
411
412 base = RK3308_GRF_GPIO0A_IOMUX;
413
414 s = splhigh();
415
416 /* IOMUX control */
417 off = bank * 0x20 + (idx / 8) * 0x08;
418
419 /* GPIO1B, GPIO1C and GPIO3B are special. */
420 if ((bank == 1) && (idx == 14)) {
421 mask = (0xf << 12);
422 bits = (mux << 12);
423 } else if ((bank == 1) && (idx == 15)) {
424 off += 4;
425 mask = 0x3;
426 bits = mux;
427 } else if ((bank == 1) && (idx >= 16 && idx <= 17)) {
428 mask = (0x3 << ((idx - 16) * 2));
429 bits = (mux << ((idx - 16) * 2));
430 } else if ((bank == 1) && (idx >= 18 && idx <= 20)) {
431 mask = (0xf << (((idx - 18) * 4) + 4));
432 bits = (mux << (((idx - 18) * 4) + 4));
433 } else if ((bank == 1) && (idx >= 21 && idx <= 23)) {
434 off += 4;
435 mask = (0xf << ((idx - 21) * 4));
436 bits = (mux << ((idx - 21) * 4));
437 } else if ((bank == 3) && (idx >= 12 && idx <= 13)) {
438 mask = (0xf << (((idx - 12) * 4) + 8));
439 bits = (mux << (((idx - 12) * 4) + 8));
440 } else {
441 mask = (0x3 << ((idx % 8) * 2));
442 bits = (mux << ((idx % 8) * 2));
443 }
444 regmap_write_4(rm, base + off, mask << 16 | bits);
445
446 /* GPIO pad pull down and pull up control */
447 if (pull >= 0) {
448 off = 0xa0 + bank * 0x10 + (idx / 8) * 0x04;
449 mask = (0x3 << ((idx % 8) * 2));
450 bits = (pull << ((idx % 8) * 2));
451 regmap_write_4(rm, base + off, mask << 16 | bits);
452 }
453
454 /* GPIO drive strength control */
455 if (strength >= 0) {
456 off = 0x100 + bank * 0x10 + (idx / 8) * 0x04;
457 mask = (0x3 << ((idx % 8) * 2));
458 bits = (strength << ((idx % 8) * 2));
459 regmap_write_4(rm, base + off, mask << 16 | bits);
460 }
461
462 splx(s);
463 }
464
465 free(pins, M_TEMP, len);
466 return 0;
467
468 fail:
469 free(pins, M_TEMP, len);
470 return -1;
471 }
472
473 /*
474 * Rockchip RK3328
475 */
476
477 int
rk3328_pull(uint32_t bank,uint32_t idx,uint32_t phandle)478 rk3328_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
479 {
480 int node;
481
482 node = OF_getnodebyphandle(phandle);
483 if (node == 0)
484 return -1;
485
486 if (OF_getproplen(node, "bias-disable") == 0)
487 return 0;
488 if (OF_getproplen(node, "bias-pull-up") == 0)
489 return 1;
490 if (OF_getproplen(node, "bias-pull-down") == 0)
491 return 2;
492
493 return -1;
494 }
495
496 int
rk3328_strength(uint32_t bank,uint32_t idx,uint32_t phandle)497 rk3328_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
498 {
499 int strength, level;
500 int levels[4] = { 2, 4, 8, 12 };
501 int node;
502
503 node = OF_getnodebyphandle(phandle);
504 if (node == 0)
505 return -1;
506
507 strength = OF_getpropint(node, "drive-strength", -1);
508 if (strength == -1)
509 return -1;
510
511 /* Convert drive strength to level. */
512 for (level = 3; level >= 0; level--) {
513 if (strength >= levels[level])
514 break;
515 }
516 return level;
517 }
518
519 int
rk3328_pinctrl(uint32_t phandle,void * cookie)520 rk3328_pinctrl(uint32_t phandle, void *cookie)
521 {
522 struct rkpinctrl_softc *sc = cookie;
523 uint32_t *pins;
524 int node, len, i;
525
526 KASSERT(sc->sc_grf);
527
528 node = OF_getnodebyphandle(phandle);
529 if (node == 0)
530 return -1;
531
532 len = OF_getproplen(node, "rockchip,pins");
533 if (len <= 0)
534 return -1;
535
536 pins = malloc(len, M_TEMP, M_WAITOK);
537 if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
538 goto fail;
539
540 for (i = 0; i < len / sizeof(uint32_t); i += 4) {
541 struct regmap *rm = sc->sc_grf;
542 bus_size_t base, off;
543 uint32_t bank, idx, mux;
544 int pull, strength;
545 uint32_t mask, bits;
546 int s;
547
548 bank = pins[i];
549 idx = pins[i + 1];
550 mux = pins[i + 2];
551
552 if (bank > 3 || idx >= 32 || mux > 3)
553 continue;
554
555 pull = rk3328_pull(bank, idx, pins[i + 3]);
556 strength = rk3328_strength(bank, idx, pins[i + 3]);
557
558 base = RK3328_GRF_GPIO0A_IOMUX;
559
560 s = splhigh();
561
562 /* IOMUX control */
563 off = bank * 0x10 + (idx / 8) * 0x04;
564
565 /* GPIO2B, GPIO2C, GPIO3A and GPIO3B are special. */
566 if (bank == 2 && idx == 15) {
567 mask = 0x7;
568 bits = mux;
569 } else if (bank == 2 && idx >= 16 && idx <= 20) {
570 mask = (0x7 << ((idx - 16) * 3));
571 bits = (mux << ((idx - 16) * 3));
572 } else if (bank == 2 && idx >= 21 && idx <= 23) {
573 mask = (0x7 << ((idx - 21) * 3));
574 bits = (mux << ((idx - 21) * 3));
575 } else if (bank == 3 && idx <= 4) {
576 mask = (0x7 << (idx * 3));
577 bits = (mux << (idx * 3));
578 } else if (bank == 3 && idx >= 5 && idx <= 7) {
579 mask = (0x7 << ((idx - 5) * 3));
580 bits = (mux << ((idx - 5) * 3));
581 } else if (bank == 3 && idx >= 8 && idx <= 12) {
582 mask = (0x7 << ((idx - 8) * 3));
583 bits = (mux << ((idx - 8) * 3));
584 } else if (bank == 3 && idx >= 13 && idx <= 15) {
585 mask = (0x7 << ((idx - 13) * 3));
586 bits = (mux << ((idx - 13) * 3));
587 } else {
588 mask = (0x3 << ((idx % 8) * 2));
589 bits = (mux << ((idx % 8) * 2));
590 }
591 if (bank > 2 || (bank == 2 && idx >= 15))
592 off += 0x04;
593 if (bank > 2 || (bank == 2 && idx >= 21))
594 off += 0x04;
595 if (bank > 3 || (bank == 3 && idx >= 5))
596 off += 0x04;
597 if (bank > 3 || (bank == 3 && idx >= 13))
598 off += 0x04;
599 regmap_write_4(rm, base + off, mask << 16 | bits);
600
601 /* GPIO pad pull down and pull up control */
602 if (pull >= 0) {
603 off = 0x100 + bank * 0x10 + (idx / 8) * 0x04;
604 mask = (0x3 << ((idx % 8) * 2));
605 bits = (pull << ((idx % 8) * 2));
606 regmap_write_4(rm, base + off, mask << 16 | bits);
607 }
608
609 /* GPIO drive strength control */
610 if (strength >= 0) {
611 off = 0x200 + bank * 0x10 + (idx / 8) * 0x04;
612 mask = (0x3 << ((idx % 8) * 2));
613 bits = (strength << ((idx % 8) * 2));
614 regmap_write_4(rm, base + off, mask << 16 | bits);
615 }
616
617 splx(s);
618 }
619
620 free(pins, M_TEMP, len);
621 return 0;
622
623 fail:
624 free(pins, M_TEMP, len);
625 return -1;
626 }
627
628 /*
629 * Rockchip RK3399
630 */
631
632 int
rk3399_pull(uint32_t bank,uint32_t idx,uint32_t phandle)633 rk3399_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
634 {
635 int pull_up, pull_down;
636 int node;
637
638 node = OF_getnodebyphandle(phandle);
639 if (node == 0)
640 return -1;
641
642 if (bank == 2 && idx >= 16) {
643 pull_up = 3;
644 pull_down = 1;
645 } else {
646 pull_up = 1;
647 pull_down = 2;
648 }
649
650 if (OF_getproplen(node, "bias-disable") == 0)
651 return 0;
652 if (OF_getproplen(node, "bias-pull-up") == 0)
653 return pull_up;
654 if (OF_getproplen(node, "bias-pull-down") == 0)
655 return pull_down;
656
657 return -1;
658 }
659
660 /* Magic because the drive strength configurations vary wildly. */
661
662 const int rk3399_strength_levels[][8] = {
663 { 2, 4, 8, 12 }, /* default */
664 { 3, 6, 9, 12 }, /* 1.8V or 3.0V */
665 { 5, 10, 15, 20 }, /* 1.8V only */
666 { 4, 6, 8, 10, 12, 14, 16, 18 }, /* 1.8V or 3.0V auto */
667 { 4, 7, 10, 13, 16, 19, 22, 26 }, /* 3.3V */
668 };
669
670 const int rk3399_strength_types[][4] = {
671 { 2, 2, 0, 0 },
672 { 1, 1, 1, 1 },
673 { 1, 1, 2, 2 },
674 { 4, 4, 4, 1 },
675 { 1, 3, 1, 1 },
676 };
677
678 const int rk3399_strength_regs[][4] = {
679 { 0x0080, 0x0088, 0x0090, 0x0098 },
680 { 0x00a0, 0x00a8, 0x00b0, 0x00b8 },
681 { 0x0100, 0x0104, 0x0108, 0x010c },
682 { 0x0110, 0x0118, 0x0120, 0x0128 },
683 { 0x012c, 0x0130, 0x0138, 0x013c },
684 };
685
686 int
rk3399_strength(uint32_t bank,uint32_t idx,uint32_t phandle)687 rk3399_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
688 {
689 int strength, type, level;
690 const int *levels;
691 int node;
692
693 node = OF_getnodebyphandle(phandle);
694 if (node == 0)
695 return -1;
696
697 strength = OF_getpropint(node, "drive-strength", -1);
698 if (strength == -1)
699 return -1;
700
701 /* Convert drive strength to level. */
702 type = rk3399_strength_types[bank][idx / 8];
703 levels = rk3399_strength_levels[type];
704 for (level = 7; level >= 0; level--) {
705 if (strength >= levels[level] && levels[level] > 0)
706 break;
707 }
708 return level;
709 }
710
711 int
rk3399_pinctrl(uint32_t phandle,void * cookie)712 rk3399_pinctrl(uint32_t phandle, void *cookie)
713 {
714 struct rkpinctrl_softc *sc = cookie;
715 uint32_t *pins;
716 int node, len, i;
717
718 KASSERT(sc->sc_grf);
719 KASSERT(sc->sc_pmu);
720
721 node = OF_getnodebyphandle(phandle);
722 if (node == 0)
723 return -1;
724
725 len = OF_getproplen(node, "rockchip,pins");
726 if (len <= 0)
727 return -1;
728
729 pins = malloc(len, M_TEMP, M_WAITOK);
730 if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
731 goto fail;
732
733 for (i = 0; i < len / sizeof(uint32_t); i += 4) {
734 struct regmap *rm;
735 bus_size_t base, off;
736 uint32_t bank, idx, mux;
737 int pull, strength, type, shift;
738 uint32_t mask, bits;
739 int s;
740
741 bank = pins[i];
742 idx = pins[i + 1];
743 mux = pins[i + 2];
744
745 if (bank > 4 || idx >= 32 || mux > 3)
746 continue;
747
748 pull = rk3399_pull(bank, idx, pins[i + 3]);
749 strength = rk3399_strength(bank, idx, pins[i + 3]);
750
751 /* Bank 0 and 1 live in the PMU. */
752 if (bank < 2) {
753 rm = sc->sc_pmu;
754 base = RK3399_PMUGRF_GPIO0A_IOMUX;
755 } else {
756 rm = sc->sc_grf;
757 base = RK3399_GRF_GPIO2A_IOMUX - 0x20;
758 }
759
760 s = splhigh();
761
762 /* IOMUX control */
763 off = bank * 0x10 + (idx / 8) * 0x04;
764 mask = (0x3 << ((idx % 8) * 2));
765 bits = (mux << ((idx % 8) * 2));
766 regmap_write_4(rm, base + off, mask << 16 | bits);
767
768 /* GPIO pad pull down and pull up control */
769 if (pull >= 0) {
770 off = 0x40 + bank * 0x10 + (idx / 8) * 0x04;
771 mask = (0x3 << ((idx % 8) * 2));
772 bits = (pull << ((idx % 8) * 2));
773 regmap_write_4(rm, base + off, mask << 16 | bits);
774 }
775
776 /* GPIO drive strength control */
777 if (strength >= 0) {
778 off = rk3399_strength_regs[bank][idx / 8];
779 type = rk3399_strength_types[bank][idx / 8];
780 shift = (type > 2) ? 3 : 2;
781 mask = (((1 << shift) - 1) << ((idx % 8) * shift));
782 bits = (strength << ((idx % 8) * shift));
783 if (mask & 0x0000ffff) {
784 regmap_write_4(rm, base + off,
785 mask << 16 | (bits & 0x0000ffff));
786 }
787 if (mask & 0xffff0000) {
788 regmap_write_4(rm, base + off + 0x04,
789 (mask & 0xffff0000) | bits >> 16);
790 }
791 }
792
793 splx(s);
794 }
795
796 free(pins, M_TEMP, len);
797 return 0;
798
799 fail:
800 free(pins, M_TEMP, len);
801 return -1;
802 }
803
804 /*
805 * Rockchip RK3568
806 */
807
808 int
rk3568_pull(uint32_t bank,uint32_t idx,uint32_t phandle)809 rk3568_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
810 {
811 int node;
812
813 node = OF_getnodebyphandle(phandle);
814 if (node == 0)
815 return -1;
816
817 if (OF_getproplen(node, "bias-disable") == 0)
818 return 0;
819 if (OF_getproplen(node, "bias-pull-up") == 0)
820 return 1;
821 if (OF_getproplen(node, "bias-pull-down") == 0)
822 return 2;
823
824 return -1;
825 }
826
827 int
rk3568_strength(uint32_t bank,uint32_t idx,uint32_t phandle)828 rk3568_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
829 {
830 int node;
831
832 node = OF_getnodebyphandle(phandle);
833 if (node == 0)
834 return -1;
835
836 return OF_getpropint(node, "drive-strength", -1);
837 }
838
839 int
rk3568_schmitt(uint32_t bank,uint32_t idx,uint32_t phandle)840 rk3568_schmitt(uint32_t bank, uint32_t idx, uint32_t phandle)
841 {
842 int node;
843
844 node = OF_getnodebyphandle(phandle);
845 if (node == 0)
846 return -1;
847
848 if (OF_getproplen(node, "input-schmitt-disable") == 0)
849 return 1;
850 if (OF_getproplen(node, "input-schmitt-enable") == 0)
851 return 2;
852
853 return -1;
854 }
855
856 struct rockchip_route_table rk3568_route_table[] = {
857 { 0, RK_PB7, 1, ROUTE_PMU, 0x0110, ROUTE_VAL(0, 0) }, /* PWM0 M0 */
858 { 0, RK_PC7, 2, ROUTE_PMU, 0x0110, ROUTE_VAL(0, 1) }, /* PWM0 M1 */
859 { 0, RK_PC0, 1, ROUTE_PMU, 0x0110, ROUTE_VAL(2, 0) }, /* PWM1 M0 */
860 { 0, RK_PB5, 4, ROUTE_PMU, 0x0110, ROUTE_VAL(2, 1) }, /* PWM1 M1 */
861 { 0, RK_PC1, 1, ROUTE_PMU, 0x0110, ROUTE_VAL(4, 0) }, /* PWM2 M0 */
862 { 0, RK_PB6, 4, ROUTE_PMU, 0x0110, ROUTE_VAL(4, 1) }, /* PWM2 M1 */
863
864 { 3, RK_PB1, 3, ROUTE_GRF, 0x0300, ROUTE_VAL(8, 0) }, /* GMAC1 M0 */
865 { 4, RK_PA7, 3, ROUTE_GRF, 0x0300, ROUTE_VAL(8, 1) }, /* GMAC1 M1 */
866 { 0, RK_PB6, 1, ROUTE_GRF, 0x0300, ROUTE_VAL(14, 0) }, /* I2C2 M0 */
867 { 4, RK_PB4, 1, ROUTE_GRF, 0x0300, ROUTE_VAL(14, 1) }, /* I2C2 M1 */
868
869 { 1, RK_PA0, 1, ROUTE_GRF, 0x0304, ROUTE_VAL(0, 0) }, /* I2C3 M0 */
870 { 3, RK_PB6, 4, ROUTE_GRF, 0x0304, ROUTE_VAL(0, 1) }, /* I2C3 M1 */
871 { 4, RK_PB2, 1, ROUTE_GRF, 0x0304, ROUTE_VAL(2, 0) }, /* I2C4 M0 */
872 { 2, RK_PB1, 2, ROUTE_GRF, 0x0304, ROUTE_VAL(2, 1) }, /* I2C4 M1 */
873 { 3, RK_PB4, 4, ROUTE_GRF, 0x0304, ROUTE_VAL(4, 0) }, /* I2C5 M0 */
874 { 4, RK_PD0, 2, ROUTE_GRF, 0x0304, ROUTE_VAL(4, 1) }, /* I2C5 M1 */
875 { 3, RK_PB1, 5, ROUTE_GRF, 0x0304, ROUTE_VAL(14, 0) }, /* PWM8 M0 */
876 { 1, RK_PD5, 4, ROUTE_GRF, 0x0304, ROUTE_VAL(14, 1) }, /* PWM8 M1 */
877
878 { 3, RK_PB2, 5, ROUTE_GRF, 0x0308, ROUTE_VAL(0, 0) }, /* PWM9 M0 */
879 { 1, RK_PD6, 4, ROUTE_GRF, 0x0308, ROUTE_VAL(0, 1) }, /* PWM9 M1 */
880 { 3, RK_PB5, 5, ROUTE_GRF, 0x0308, ROUTE_VAL(2, 0) }, /* PWM10 M0 */
881 { 2, RK_PA1, 2, ROUTE_GRF, 0x0308, ROUTE_VAL(2, 1) }, /* PWM10 M1 */
882 { 3, RK_PB6, 5, ROUTE_GRF, 0x0308, ROUTE_VAL(4, 0) }, /* PWM11 M0 */
883 { 4, RK_PC0, 3, ROUTE_GRF, 0x0308, ROUTE_VAL(4, 1) }, /* PWM11 M1 */
884 { 3, RK_PB7, 2, ROUTE_GRF, 0x0308, ROUTE_VAL(6, 0) }, /* PWM12 M0 */
885 { 4, RK_PC5, 1, ROUTE_GRF, 0x0308, ROUTE_VAL(6, 1) }, /* PWM12 M1 */
886 { 3, RK_PC0, 2, ROUTE_GRF, 0x0308, ROUTE_VAL(8, 0) }, /* PWM13 M0 */
887 { 4, RK_PC6, 1, ROUTE_GRF, 0x0308, ROUTE_VAL(8, 1) }, /* PWM13 M1 */
888 { 3, RK_PC4, 1, ROUTE_GRF, 0x0308, ROUTE_VAL(10, 0) }, /* PWM14 M0 */
889 { 4, RK_PC2, 1, ROUTE_GRF, 0x0308, ROUTE_VAL(10, 1) }, /* PWM14 M1 */
890 { 3, RK_PC5, 1, ROUTE_GRF, 0x0308, ROUTE_VAL(12, 0) }, /* PWM15 M0 */
891 { 4, RK_PC3, 1, ROUTE_GRF, 0x0308, ROUTE_VAL(12, 1) }, /* PWM15 M1 */
892 { 3, RK_PD2, 3, ROUTE_GRF, 0x0308, ROUTE_VAL(14, 0) }, /* SDMMC2 M0 */
893 { 3, RK_PA5, 5, ROUTE_GRF, 0x0308, ROUTE_VAL(14, 1) }, /* SDMMC2 M1 */
894
895 { 2, RK_PB4, 2, ROUTE_GRF, 0x030c, ROUTE_VAL(8, 0) }, /* UART1 M0 */
896 { 3, RK_PD6, 4, ROUTE_GRF, 0x030c, ROUTE_VAL(8, 1) }, /* UART1 M1 */
897 { 0, RK_PD1, 1, ROUTE_GRF, 0x030c, ROUTE_VAL(10, 0) }, /* UART2 M0 */
898 { 1, RK_PD5, 2, ROUTE_GRF, 0x030c, ROUTE_VAL(10, 1) }, /* UART2 M1 */
899 { 1, RK_PA1, 2, ROUTE_GRF, 0x030c, ROUTE_VAL(12, 0) }, /* UART3 M0 */
900 { 3, RK_PB7, 4, ROUTE_GRF, 0x030c, ROUTE_VAL(12, 1) }, /* UART3 M1 */
901 { 1, RK_PA6, 2, ROUTE_GRF, 0x030c, ROUTE_VAL(14, 0) }, /* UART4 M0 */
902 { 3, RK_PB2, 4, ROUTE_GRF, 0x030c, ROUTE_VAL(14, 1) }, /* UART4 M1 */
903
904 { 2, RK_PA2, 3, ROUTE_GRF, 0x0310, ROUTE_VAL(0, 0) }, /* UART5 M0 */
905 { 3, RK_PC2, 4, ROUTE_GRF, 0x0310, ROUTE_VAL(0, 1) }, /* UART5 M1 */
906 { 2, RK_PA4, 3, ROUTE_GRF, 0x0310, ROUTE_VAL(2, 0) }, /* UART6 M0 */
907 { 1, RK_PD5, 3, ROUTE_GRF, 0x0310, ROUTE_VAL(2, 1) }, /* UART6 M1 */
908 { 2, RK_PA6, 3, ROUTE_GRF, 0x0310, ROUTE_VAL(4, 0) }, /* UART7 M0 */
909 { 3, RK_PC4, 4, ROUTE_GRF, 0x0310, ROUTE_VAL(4, 1) }, /* UART7 M1 */
910 { 4, RK_PA2, 4, ROUTE_GRF, 0x0310, ROUTE_VAL(4, 2) }, /* UART7 M2 */
911 { 2, RK_PC5, 3, ROUTE_GRF, 0x0310, ROUTE_VAL(6, 0) }, /* UART8 M0 */
912 { 2, RK_PD7, 4, ROUTE_GRF, 0x0310, ROUTE_VAL(6, 1) }, /* UART8 M1 */
913 { 2, RK_PB0, 3, ROUTE_GRF, 0x0310, ROUTE_VAL(8, 0) }, /* UART9 M0 */
914 { 4, RK_PC5, 4, ROUTE_GRF, 0x0310, ROUTE_VAL(8, 1) }, /* UART9 M1 */
915 { 4, RK_PA4, 4, ROUTE_GRF, 0x0310, ROUTE_VAL(8, 2) }, /* UART9 M2 */
916 { 1, RK_PA2, 1, ROUTE_GRF, 0x0310, ROUTE_VAL(10, 0) }, /* I2S1 M0 */
917 { 3, RK_PC6, 4, ROUTE_GRF, 0x0310, ROUTE_VAL(10, 1) }, /* I2S1 M1 */
918 { 2, RK_PD0, 5, ROUTE_GRF, 0x0310, ROUTE_VAL(10, 2) }, /* I2S1 M2 */
919 { 2, RK_PC1, 1, ROUTE_GRF, 0x0310, ROUTE_VAL(12, 0) }, /* I2S2 M0 */
920 { 4, RK_PB6, 5, ROUTE_GRF, 0x0310, ROUTE_VAL(12, 1) }, /* I2S2 M1 */
921 { 3, RK_PA2, 4, ROUTE_GRF, 0x0310, ROUTE_VAL(14, 0) }, /* I2S3 M0 */
922 { 4, RK_PC2, 5, ROUTE_GRF, 0x0310, ROUTE_VAL(14, 1) }, /* I2S3 M1 */
923
924 { 0, RK_PA5, 3, ROUTE_GRF, 0x0314, ROUTE_VAL(2, 0) }, /* PCIE20 M0 */
925 { 2, RK_PD0, 4, ROUTE_GRF, 0x0314, ROUTE_VAL(2, 1) }, /* PCIE20 M1 */
926 { 1, RK_PB0, 4, ROUTE_GRF, 0x0314, ROUTE_VAL(2, 2) }, /* PCIE20 M2 */
927 { 0, RK_PA4, 3, ROUTE_GRF, 0x0314, ROUTE_VAL(4, 0) }, /* PCIE30X1 M0 */
928 { 2, RK_PD2, 4, ROUTE_GRF, 0x0314, ROUTE_VAL(4, 1) }, /* PCIE30X1 M1 */
929 { 1, RK_PA5, 4, ROUTE_GRF, 0x0314, ROUTE_VAL(4, 2) }, /* PCIE30X1 M2 */
930 { 0, RK_PA6, 2, ROUTE_GRF, 0x0314, ROUTE_VAL(6, 0) }, /* PCIE30X2 M0 */
931 { 2, RK_PD4, 4, ROUTE_GRF, 0x0314, ROUTE_VAL(6, 1) }, /* PCIE30X2 M1 */
932 { 4, RK_PC2, 4, ROUTE_GRF, 0x0314, ROUTE_VAL(6, 2) }, /* PCIE30X2 M2 */
933 };
934
935 void
rk3568_route(struct rkpinctrl_softc * sc,uint32_t * pins)936 rk3568_route(struct rkpinctrl_softc *sc, uint32_t *pins)
937 {
938 struct rockchip_route_table *route = NULL;
939 struct regmap *rm;
940 int bank = pins[0];
941 int idx = pins[1];
942 int mux = pins[2];
943 int i;
944
945 for (i = 0; i < nitems(rk3568_route_table); i++) {
946 if (bank == rk3568_route_table[i].bank &&
947 idx == rk3568_route_table[i].idx &&
948 mux == rk3568_route_table[i].mux) {
949 route = &rk3568_route_table[i];
950 break;
951 }
952 }
953 if (route == NULL)
954 return;
955
956 rm = route->grf ? sc->sc_pmu : sc->sc_grf;
957 regmap_write_4(rm, route->reg, route->val);
958 }
959
960 int
rk3568_pinctrl(uint32_t phandle,void * cookie)961 rk3568_pinctrl(uint32_t phandle, void *cookie)
962 {
963 struct rkpinctrl_softc *sc = cookie;
964 uint32_t *pins;
965 int node, len, i;
966
967 KASSERT(sc->sc_grf);
968 KASSERT(sc->sc_pmu);
969
970 node = OF_getnodebyphandle(phandle);
971 if (node == 0)
972 return -1;
973
974 len = OF_getproplen(node, "rockchip,pins");
975 if (len <= 0)
976 return -1;
977
978 pins = malloc(len, M_TEMP, M_WAITOK);
979 if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
980 goto fail;
981
982 for (i = 0; i < len / sizeof(uint32_t); i += 4) {
983 struct regmap *rm;
984 bus_size_t iomux_base, p_base, ds_base, ie_base, off;
985 uint32_t bank, idx, mux;
986 int pull, strength, schmitt;
987 uint32_t mask, bits;
988 int s;
989
990 bank = pins[i];
991 idx = pins[i + 1];
992 mux = pins[i + 2];
993
994 if (bank > 5 || idx >= 32 || mux > 7)
995 continue;
996
997 pull = rk3568_pull(bank, idx, pins[i + 3]);
998 strength = rk3568_strength(bank, idx, pins[i + 3]);
999 schmitt = rk3568_schmitt(bank, idx, pins[i + 3]);
1000
1001 /* Bank 0 lives in the PMU. */
1002 if (bank < 1) {
1003 rm = sc->sc_pmu;
1004 iomux_base = RK3568_PMUGRF_GPIO0A_IOMUX_L;
1005 p_base = RK3568_PMUGRF_GPIO0A_P;
1006 ds_base = RK3568_PMUGRF_GPIO0A_DS_0;
1007 ie_base = RK3568_PMUGRF_GPIO0A_IE;
1008 } else {
1009 rm = sc->sc_grf;
1010 iomux_base = RK3568_GRF_GPIO1A_IOMUX_L;
1011 p_base = RK3568_GRF_GPIO1A_P;
1012 ds_base = RK3568_GRF_GPIO1A_DS_0;
1013 ie_base = RK3568_GRF_GPIO1A_IE;
1014 bank = bank - 1;
1015 }
1016
1017 s = splhigh();
1018
1019 /* IOMUX control */
1020 rk3568_route(sc, &pins[i]);
1021 off = bank * 0x20 + (idx / 4) * 0x04;
1022 mask = (0x7 << ((idx % 4) * 4));
1023 bits = (mux << ((idx % 4) * 4));
1024 regmap_write_4(rm, iomux_base + off, mask << 16 | bits);
1025
1026 /* GPIO pad pull down and pull up control */
1027 if (pull >= 0) {
1028 off = bank * 0x10 + (idx / 8) * 0x04;
1029 mask = (0x3 << ((idx % 8) * 2));
1030 bits = (pull << ((idx % 8) * 2));
1031 regmap_write_4(rm, p_base + off, mask << 16 | bits);
1032 }
1033
1034 /* GPIO drive strength control */
1035 if (strength >= 0) {
1036 off = bank * 0x40 + (idx / 2) * 0x04;
1037 mask = (0x3f << ((idx % 2) * 8));
1038 bits = ((1 << (strength + 1)) - 1) << ((idx % 2) * 8);
1039 regmap_write_4(rm, ds_base + off, mask << 16 | bits);
1040 }
1041
1042 /* GPIO Schmitt trigger. */
1043 if (schmitt >= 0) {
1044 off = bank * 0x10 + (idx / 8) * 0x04;
1045 mask = (0x3 << ((idx % 8) * 2));
1046 bits = schmitt << ((idx % 8) * 2);
1047 regmap_write_4(rm, ie_base + off, mask << 16 | bits);
1048 }
1049
1050 splx(s);
1051 }
1052
1053 free(pins, M_TEMP, len);
1054 return 0;
1055
1056 fail:
1057 free(pins, M_TEMP, len);
1058 return -1;
1059 }
1060
1061
1062 /*
1063 * Rockchip RK3588
1064 */
1065
1066 int
rk3588_pull(uint32_t bank,uint32_t idx,uint32_t phandle)1067 rk3588_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
1068 {
1069 int node;
1070
1071 node = OF_getnodebyphandle(phandle);
1072 if (node == 0)
1073 return -1;
1074
1075 if (OF_getproplen(node, "bias-disable") == 0)
1076 return 0;
1077 if (OF_getproplen(node, "bias-pull-up") == 0)
1078 return 3;
1079 if (OF_getproplen(node, "bias-pull-down") == 0)
1080 return 1;
1081
1082 return -1;
1083 }
1084
1085 int
rk3588_strength(uint32_t bank,uint32_t idx,uint32_t phandle)1086 rk3588_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
1087 {
1088 int node;
1089
1090 node = OF_getnodebyphandle(phandle);
1091 if (node == 0)
1092 return -1;
1093
1094 return OF_getpropint(node, "drive-strength", -1);
1095 }
1096
1097 int
rk3588_schmitt(uint32_t bank,uint32_t idx,uint32_t phandle)1098 rk3588_schmitt(uint32_t bank, uint32_t idx, uint32_t phandle)
1099 {
1100 int node;
1101
1102 node = OF_getnodebyphandle(phandle);
1103 if (node == 0)
1104 return -1;
1105
1106 if (OF_getproplen(node, "input-schmitt-disable") == 0)
1107 return 0;
1108 if (OF_getproplen(node, "input-schmitt-enable") == 0)
1109 return 1;
1110
1111 return -1;
1112 }
1113
1114 #define RK3588_PMU1_IOC 0x0000
1115 #define RK3588_PMU2_IOC 0x4000
1116 #define RK3588_BUS_IOC 0x8000
1117 #define RK3588_VCCIO1_4_IOC 0x9000
1118 #define RK3588_VCCIO3_5_IOC 0xa000
1119 #define RK3588_VCCIO2_IOC 0xb000
1120 #define RK3588_VCCIO6_IOC 0xc000
1121 #define RK3588_EMMC_IOC 0xd000
1122
1123 bus_size_t
rk3588_base(uint32_t bank,uint32_t idx)1124 rk3588_base(uint32_t bank, uint32_t idx)
1125 {
1126 if (bank == 1 && idx < 32)
1127 return RK3588_VCCIO1_4_IOC;
1128 if (bank == 2 && idx < 6)
1129 return RK3588_EMMC_IOC;
1130 if (bank == 2 && idx < 24)
1131 return RK3588_VCCIO3_5_IOC;
1132 if (bank == 2 && idx < 32)
1133 return RK3588_EMMC_IOC;
1134 if (bank == 3 && idx < 32)
1135 return RK3588_VCCIO3_5_IOC;
1136 if (bank == 4 && idx < 18)
1137 return RK3588_VCCIO6_IOC;
1138 if (bank == 4 && idx < 24)
1139 return RK3588_VCCIO3_5_IOC;
1140 if (bank == 4 && idx < 32)
1141 return RK3588_VCCIO2_IOC;
1142
1143 return (bus_size_t)-1;
1144 }
1145
1146 int
rk3588_pinctrl(uint32_t phandle,void * cookie)1147 rk3588_pinctrl(uint32_t phandle, void *cookie)
1148 {
1149 struct rkpinctrl_softc *sc = cookie;
1150 struct regmap *rm = sc->sc_grf;
1151 uint32_t *pins;
1152 int node, len, i;
1153
1154 KASSERT(sc->sc_grf);
1155
1156 node = OF_getnodebyphandle(phandle);
1157 if (node == 0)
1158 return -1;
1159
1160 len = OF_getproplen(node, "rockchip,pins");
1161 if (len <= 0)
1162 return -1;
1163
1164 pins = malloc(len, M_TEMP, M_WAITOK);
1165 if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
1166 goto fail;
1167
1168 for (i = 0; i < len / sizeof(uint32_t); i += 4) {
1169 bus_size_t iomux_base, p_base, ds_base, smt_base, off;
1170 uint32_t bank, idx, mux;
1171 int pull, strength, schmitt;
1172 uint32_t mask, bits;
1173 int s;
1174
1175 bank = pins[i];
1176 idx = pins[i + 1];
1177 mux = pins[i + 2];
1178
1179 if (bank > 5 || idx >= 32 || mux > 15)
1180 continue;
1181
1182 pull = rk3588_pull(bank, idx, pins[i + 3]);
1183 strength = rk3588_strength(bank, idx, pins[i + 3]);
1184 schmitt = rk3588_schmitt(bank, idx, pins[i + 3]);
1185
1186 if (bank == 0 && idx < 12) {
1187 /* PMU1 */
1188 iomux_base = RK3588_PMU1_IOC;
1189 } else {
1190 /* BUS */
1191 iomux_base = RK3588_BUS_IOC;
1192 }
1193
1194 if (bank == 0) {
1195 if (idx < 12) {
1196 /* PMU1 */
1197 p_base = RK3588_PMU1_IOC + 0x0020;
1198 ds_base = RK3588_PMU1_IOC + 0x0010;
1199 smt_base = RK3588_PMU1_IOC + 0x0030;
1200 } else {
1201 /* PMU2 */
1202 p_base = RK3588_PMU2_IOC + 0x0024;
1203 ds_base = RK3588_PMU2_IOC + 0x0008;
1204 smt_base = RK3588_PMU2_IOC + 0x003c;
1205 }
1206 } else {
1207 bus_size_t base = rk3588_base(bank, idx);
1208 KASSERT(base != (bus_size_t)-1);
1209
1210 p_base = base + 0x0100;
1211 ds_base = base + 0x0000;
1212 smt_base = base + 0x0200;
1213 }
1214
1215 s = splhigh();
1216
1217 /* IOMUX control */
1218 off = bank * 0x20 + (idx / 4) * 0x04;
1219 mask = (0xf << ((idx % 4) * 4));
1220 bits = (mux << ((idx % 4) * 4));
1221 regmap_write_4(rm, iomux_base + off, mask << 16 | bits);
1222 if (bank == 0 && idx > 12) {
1223 iomux_base = RK3588_PMU2_IOC;
1224 off = (idx - 12) / 4 * 0x04;
1225 mux = (mux < 8) ? mux : 8;
1226 bits = (mux << ((idx % 4) * 4));
1227 regmap_write_4(rm, iomux_base + off, mask << 16 | bits);
1228 }
1229
1230 /* GPIO pad pull down and pull up control */
1231 if (pull >= 0) {
1232 off = bank * 0x10 + (idx / 8) * 0x04;
1233 mask = (0x3 << ((idx % 8) * 2));
1234 bits = (pull << ((idx % 8) * 2));
1235 regmap_write_4(rm, p_base + off, mask << 16 | bits);
1236 }
1237
1238 /* GPIO drive strength control */
1239 if (strength >= 0) {
1240 off = bank * 0x20 + (idx / 4) * 0x04;
1241 mask = (0xf << ((idx % 4) * 4));
1242 bits = (strength << ((idx % 4) * 4));
1243 regmap_write_4(rm, ds_base + off, mask << 16 | bits);
1244 }
1245
1246 /* GPIO Schmitt trigger. */
1247 if (schmitt >= 0) {
1248 off = bank * 0x10 + (idx / 8) * 0x04;
1249 mask = (0x1 << (idx % 8));
1250 bits = (schmitt << (idx % 8));
1251 regmap_write_4(rm, smt_base + off, mask << 16 | bits);
1252 }
1253
1254 splx(s);
1255 }
1256
1257 free(pins, M_TEMP, len);
1258 return 0;
1259
1260 fail:
1261 free(pins, M_TEMP, len);
1262 return -1;
1263 }
1264