]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/rockchip/rk_pinctrl.c
Remove spurious newline
[FreeBSD/FreeBSD.git] / sys / arm64 / rockchip / rk_pinctrl.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2018 Emmanuel Vadot <manu@FreeBSD.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/bus.h>
36
37 #include <sys/kernel.h>
38 #include <sys/module.h>
39 #include <sys/rman.h>
40 #include <sys/lock.h>
41 #include <sys/mutex.h>
42
43 #include <machine/bus.h>
44 #include <machine/resource.h>
45 #include <machine/intr.h>
46
47 #include <dev/fdt/simplebus.h>
48
49 #include <dev/ofw/ofw_bus.h>
50 #include <dev/ofw/ofw_bus_subr.h>
51
52 #include <dev/fdt/fdt_pinctrl.h>
53
54 #include <dev/extres/syscon/syscon.h>
55
56 #include "syscon_if.h"
57
58 #include "opt_soc.h"
59
60 struct rk_pinctrl_pin_drive {
61         uint32_t        bank;
62         uint32_t        subbank;
63         uint32_t        offset;
64         uint32_t        value;
65         uint32_t        ma;
66 };
67
68 struct rk_pinctrl_bank {
69         uint32_t        bank_num;
70         uint32_t        subbank_num;
71         uint32_t        offset;
72         uint32_t        nbits;
73 };
74
75 struct rk_pinctrl_pin_fixup {
76         uint32_t        bank;
77         uint32_t        subbank;
78         uint32_t        pin;
79         uint32_t        reg;
80         uint32_t        bit;
81         uint32_t        mask;
82 };
83
84 struct rk_pinctrl_softc;
85
86 struct rk_pinctrl_conf {
87         struct rk_pinctrl_bank          *iomux_conf;
88         uint32_t                        iomux_nbanks;
89         struct rk_pinctrl_pin_fixup     *pin_fixup;
90         uint32_t                        npin_fixup;
91         struct rk_pinctrl_pin_drive     *pin_drive;
92         uint32_t                        npin_drive;
93         uint32_t                        (*get_pd_offset)(struct rk_pinctrl_softc *, uint32_t);
94         struct syscon                   *(*get_syscon)(struct rk_pinctrl_softc *, uint32_t);
95 };
96
97 struct rk_pinctrl_softc {
98         struct simplebus_softc  simplebus_sc;
99         device_t                dev;
100         struct syscon           *grf;
101         struct syscon           *pmu;
102         struct rk_pinctrl_conf  *conf;
103 };
104
105 static struct rk_pinctrl_bank rk3328_iomux_bank[] = {
106         {
107                 .bank_num = 0,
108                 .subbank_num = 0,
109                 .offset = 0x00,
110                 .nbits = 2,
111         },
112         {
113                 .bank_num = 0,
114                 .subbank_num = 1,
115                 .offset = 0x04,
116                 .nbits = 2,
117         },
118         {
119                 .bank_num = 0,
120                 .subbank_num = 2,
121                 .offset = 0x08,
122                 .nbits = 2,
123         },
124         {
125                 .bank_num = 0,
126                 .subbank_num = 3,
127                 .offset = 0xc,
128                 .nbits = 2,
129         },
130         {
131                 .bank_num = 1,
132                 .subbank_num = 0,
133                 .offset = 0x10,
134                 .nbits = 2,
135         },
136         {
137                 .bank_num = 1,
138                 .subbank_num = 1,
139                 .offset = 0x14,
140                 .nbits = 2,
141         },
142         {
143                 .bank_num = 1,
144                 .subbank_num = 2,
145                 .offset = 0x18,
146                 .nbits = 2,
147         },
148         {
149                 .bank_num = 1,
150                 .subbank_num = 3,
151                 .offset = 0x1C,
152                 .nbits = 2,
153         },
154         {
155                 .bank_num = 2,
156                 .subbank_num = 0,
157                 .offset = 0x20,
158                 .nbits = 2,
159         },
160         {
161                 .bank_num = 2,
162                 .subbank_num = 1,
163                 .offset = 0x24,
164                 .nbits = 3,
165         },
166         {
167                 .bank_num = 2,
168                 .subbank_num = 2,
169                 .offset = 0x2c,
170                 .nbits = 3,
171         },
172         {
173                 .bank_num = 2,
174                 .subbank_num = 3,
175                 .offset = 0x34,
176                 .nbits = 2,
177         },
178         {
179                 .bank_num = 3,
180                 .subbank_num = 0,
181                 .offset = 0x38,
182                 .nbits = 3,
183         },
184         {
185                 .bank_num = 3,
186                 .subbank_num = 1,
187                 .offset = 0x40,
188                 .nbits = 3,
189         },
190         {
191                 .bank_num = 3,
192                 .subbank_num = 2,
193                 .offset = 0x48,
194                 .nbits = 2,
195         },
196         {
197                 .bank_num = 3,
198                 .subbank_num = 3,
199                 .offset = 0x4c,
200                 .nbits = 2,
201         },
202 };
203
204 static struct rk_pinctrl_pin_fixup rk3328_pin_fixup[] = {
205         {
206                 .bank = 2,
207                 .pin = 12,
208                 .reg = 0x24,
209                 .bit = 8,
210                 .mask = 0x300,
211         },
212         {
213                 .bank = 2,
214                 .pin = 15,
215                 .reg = 0x28,
216                 .bit = 0,
217                 .mask = 0x7,
218         },
219         {
220                 .bank = 2,
221                 .pin = 23,
222                 .reg = 0x30,
223                 .bit = 14,
224                 .mask = 0x6000,
225         },
226 };
227
228 #define RK_PINDRIVE(_bank, _subbank, _offset, _value, _ma)      \
229         {       \
230                 .bank = _bank,          \
231                 .subbank = _subbank,    \
232                 .offset = _offset,      \
233                 .value = _value,        \
234                 .ma = _ma,              \
235         },
236
237 static struct rk_pinctrl_pin_drive rk3328_pin_drive[] = {
238         RK_PINDRIVE(0, 0, 0x200, 0, 2)
239         RK_PINDRIVE(0, 0, 0x200, 1, 4)
240         RK_PINDRIVE(0, 0, 0x200, 2, 8)
241         RK_PINDRIVE(0, 0, 0x200, 3, 12)
242
243         RK_PINDRIVE(0, 1, 0x204, 0, 2)
244         RK_PINDRIVE(0, 1, 0x204, 1, 4)
245         RK_PINDRIVE(0, 1, 0x204, 2, 8)
246         RK_PINDRIVE(0, 1, 0x204, 3, 12)
247
248         RK_PINDRIVE(0, 2, 0x208, 0, 2)
249         RK_PINDRIVE(0, 2, 0x208, 1, 4)
250         RK_PINDRIVE(0, 2, 0x208, 2, 8)
251         RK_PINDRIVE(0, 2, 0x208, 3, 12)
252
253         RK_PINDRIVE(0, 3, 0x20C, 0, 2)
254         RK_PINDRIVE(0, 3, 0x20C, 1, 4)
255         RK_PINDRIVE(0, 3, 0x20C, 2, 8)
256         RK_PINDRIVE(0, 3, 0x20C, 3, 12)
257
258         RK_PINDRIVE(1, 0, 0x210, 0, 2)
259         RK_PINDRIVE(1, 0, 0x210, 1, 4)
260         RK_PINDRIVE(1, 0, 0x210, 2, 8)
261         RK_PINDRIVE(1, 0, 0x210, 3, 12)
262
263         RK_PINDRIVE(1, 1, 0x214, 0, 2)
264         RK_PINDRIVE(1, 1, 0x214, 1, 4)
265         RK_PINDRIVE(1, 1, 0x214, 2, 8)
266         RK_PINDRIVE(1, 1, 0x214, 3, 12)
267
268         RK_PINDRIVE(1, 2, 0x218, 0, 2)
269         RK_PINDRIVE(1, 2, 0x218, 1, 4)
270         RK_PINDRIVE(1, 2, 0x218, 2, 8)
271         RK_PINDRIVE(1, 2, 0x218, 3, 12)
272
273         RK_PINDRIVE(1, 3, 0x21C, 0, 2)
274         RK_PINDRIVE(1, 3, 0x21C, 1, 4)
275         RK_PINDRIVE(1, 3, 0x21C, 2, 8)
276         RK_PINDRIVE(1, 3, 0x21C, 3, 12)
277
278         RK_PINDRIVE(2, 0, 0x220, 0, 2)
279         RK_PINDRIVE(2, 0, 0x220, 1, 4)
280         RK_PINDRIVE(2, 0, 0x220, 2, 8)
281         RK_PINDRIVE(2, 0, 0x220, 3, 12)
282
283         RK_PINDRIVE(2, 1, 0x224, 0, 2)
284         RK_PINDRIVE(2, 1, 0x224, 1, 4)
285         RK_PINDRIVE(2, 1, 0x224, 2, 8)
286         RK_PINDRIVE(2, 1, 0x224, 3, 12)
287
288         RK_PINDRIVE(2, 2, 0x228, 0, 2)
289         RK_PINDRIVE(2, 2, 0x228, 1, 4)
290         RK_PINDRIVE(2, 2, 0x228, 2, 8)
291         RK_PINDRIVE(2, 2, 0x228, 3, 12)
292
293         RK_PINDRIVE(2, 3, 0x22C, 0, 2)
294         RK_PINDRIVE(2, 3, 0x22C, 1, 4)
295         RK_PINDRIVE(2, 3, 0x22C, 2, 8)
296         RK_PINDRIVE(2, 3, 0x22C, 3, 12)
297
298         RK_PINDRIVE(3, 0, 0x230, 0, 2)
299         RK_PINDRIVE(3, 0, 0x230, 1, 4)
300         RK_PINDRIVE(3, 0, 0x230, 2, 8)
301         RK_PINDRIVE(3, 0, 0x230, 3, 12)
302
303         RK_PINDRIVE(3, 1, 0x234, 0, 2)
304         RK_PINDRIVE(3, 1, 0x234, 1, 4)
305         RK_PINDRIVE(3, 1, 0x234, 2, 8)
306         RK_PINDRIVE(3, 1, 0x234, 3, 12)
307
308         RK_PINDRIVE(3, 2, 0x238, 0, 2)
309         RK_PINDRIVE(3, 2, 0x238, 1, 4)
310         RK_PINDRIVE(3, 2, 0x238, 2, 8)
311         RK_PINDRIVE(3, 2, 0x238, 3, 12)
312
313         RK_PINDRIVE(3, 3, 0x23C, 0, 2)
314         RK_PINDRIVE(3, 3, 0x23C, 1, 4)
315         RK_PINDRIVE(3, 3, 0x23C, 2, 8)
316         RK_PINDRIVE(3, 3, 0x23C, 3, 12)
317 };
318
319 static uint32_t
320 rk3328_get_pd_offset(struct rk_pinctrl_softc *sc, uint32_t bank)
321 {
322         return (0x100);
323 }
324
325 static struct syscon *
326 rk3328_get_syscon(struct rk_pinctrl_softc *sc, uint32_t bank)
327 {
328         return (sc->grf);
329 }
330
331 struct rk_pinctrl_conf rk3328_conf = {
332         .iomux_conf = rk3328_iomux_bank,
333         .iomux_nbanks = nitems(rk3328_iomux_bank),
334         .pin_fixup = rk3328_pin_fixup,
335         .npin_fixup = nitems(rk3328_pin_fixup),
336         .pin_drive = rk3328_pin_drive,
337         .npin_drive = nitems(rk3328_pin_drive),
338         .get_pd_offset = rk3328_get_pd_offset,
339         .get_syscon = rk3328_get_syscon,
340 };
341
342 static struct rk_pinctrl_bank rk3399_iomux_bank[] = {
343         {
344                 .bank_num = 0,
345                 .subbank_num = 0,
346                 .offset = 0x00,
347                 .nbits = 2,
348         },
349         {
350                 .bank_num = 0,
351                 .subbank_num = 1,
352                 .offset = 0x04,
353                 .nbits = 2,
354         },
355         {
356                 .bank_num = 0,
357                 .subbank_num = 2,
358                 .offset = 0x08,
359                 .nbits = 2,
360         },
361         {
362                 .bank_num = 0,
363                 .subbank_num = 3,
364                 .offset = 0x0c,
365                 .nbits = 2,
366         },
367         {
368                 .bank_num = 1,
369                 .subbank_num = 0,
370                 .offset = 0x10,
371                 .nbits = 2,
372         },
373         {
374                 .bank_num = 1,
375                 .subbank_num = 1,
376                 .offset = 0x14,
377                 .nbits = 2,
378         },
379         {
380                 .bank_num = 1,
381                 .subbank_num = 2,
382                 .offset = 0x18,
383                 .nbits = 2,
384         },
385         {
386                 .bank_num = 1,
387                 .subbank_num = 3,
388                 .offset = 0x1c,
389                 .nbits = 2,
390         },
391         {
392                 .bank_num = 2,
393                 .subbank_num = 0,
394                 .offset = 0xe000,
395                 .nbits = 2,
396         },
397         {
398                 .bank_num = 2,
399                 .subbank_num = 1,
400                 .offset = 0xe004,
401                 .nbits = 2,
402         },
403         {
404                 .bank_num = 2,
405                 .subbank_num = 2,
406                 .offset = 0xe008,
407                 .nbits = 2,
408         },
409         {
410                 .bank_num = 2,
411                 .subbank_num = 3,
412                 .offset = 0xe00c,
413                 .nbits = 2,
414         },
415         {
416                 .bank_num = 3,
417                 .subbank_num = 0,
418                 .offset = 0xe010,
419                 .nbits = 2,
420         },
421         {
422                 .bank_num = 3,
423                 .subbank_num = 1,
424                 .offset = 0xe014,
425                 .nbits = 2,
426         },
427         {
428                 .bank_num = 3,
429                 .subbank_num = 2,
430                 .offset = 0xe018,
431                 .nbits = 2,
432         },
433         {
434                 .bank_num = 3,
435                 .subbank_num = 3,
436                 .offset = 0xe01c,
437                 .nbits = 2,
438         },
439         {
440                 .bank_num = 4,
441                 .subbank_num = 0,
442                 .offset = 0xe020,
443                 .nbits = 2,
444         },
445         {
446                 .bank_num = 4,
447                 .subbank_num = 1,
448                 .offset = 0xe024,
449                 .nbits = 2,
450         },
451         {
452                 .bank_num = 4,
453                 .subbank_num = 2,
454                 .offset = 0xe028,
455                 .nbits = 2,
456         },
457         {
458                 .bank_num = 4,
459                 .subbank_num = 3,
460                 .offset = 0xe02c,
461                 .nbits = 2,
462         },
463 };
464
465 static struct rk_pinctrl_pin_fixup rk3399_pin_fixup[] = {};
466
467 static struct rk_pinctrl_pin_drive rk3399_pin_drive[] = {
468         /* GPIO0A */
469         RK_PINDRIVE(0, 0, 0x80, 0, 5)
470         RK_PINDRIVE(0, 0, 0x80, 1, 10)
471         RK_PINDRIVE(0, 0, 0x80, 2, 15)
472         RK_PINDRIVE(0, 0, 0x80, 3, 20)
473
474         /* GPIOB */
475         RK_PINDRIVE(0, 1, 0x88, 0, 5)
476         RK_PINDRIVE(0, 1, 0x88, 1, 10)
477         RK_PINDRIVE(0, 1, 0x88, 2, 15)
478         RK_PINDRIVE(0, 1, 0x88, 3, 20)
479
480         /* GPIO1A */
481         RK_PINDRIVE(1, 0, 0xA0, 0, 3)
482         RK_PINDRIVE(1, 0, 0xA0, 1, 6)
483         RK_PINDRIVE(1, 0, 0xA0, 2, 9)
484         RK_PINDRIVE(1, 0, 0xA0, 3, 12)
485
486         /* GPIO1B */
487         RK_PINDRIVE(1, 1, 0xA8, 0, 3)
488         RK_PINDRIVE(1, 1, 0xA8, 1, 6)
489         RK_PINDRIVE(1, 1, 0xA8, 2, 9)
490         RK_PINDRIVE(1, 1, 0xA8, 3, 12)
491
492         /* GPIO1C */
493         RK_PINDRIVE(1, 2, 0xB0, 0, 3)
494         RK_PINDRIVE(1, 2, 0xB0, 1, 6)
495         RK_PINDRIVE(1, 2, 0xB0, 2, 9)
496         RK_PINDRIVE(1, 2, 0xB0, 3, 12)
497
498         /* GPIO1D */
499         RK_PINDRIVE(1, 3, 0xB8, 0, 3)
500         RK_PINDRIVE(1, 3, 0xB8, 1, 6)
501         RK_PINDRIVE(1, 3, 0xB8, 2, 9)
502         RK_PINDRIVE(1, 3, 0xB8, 3, 12)
503 };
504
505 static uint32_t
506 rk3399_get_pd_offset(struct rk_pinctrl_softc *sc, uint32_t bank)
507 {
508         if (bank < 2)
509                 return (0x40);
510
511         return (0xe040);
512 }
513
514 static struct syscon *
515 rk3399_get_syscon(struct rk_pinctrl_softc *sc, uint32_t bank)
516 {
517         if (bank < 2)
518                 return (sc->pmu);
519
520         return (sc->grf);
521 }
522
523 struct rk_pinctrl_conf rk3399_conf = {
524         .iomux_conf = rk3399_iomux_bank,
525         .iomux_nbanks = nitems(rk3399_iomux_bank),
526         .pin_fixup = rk3399_pin_fixup,
527         .npin_fixup = nitems(rk3399_pin_fixup),
528         .pin_drive = rk3399_pin_drive,
529         .npin_drive = nitems(rk3399_pin_drive),
530         .get_pd_offset = rk3399_get_pd_offset,
531         .get_syscon = rk3399_get_syscon,
532 };
533
534 static struct ofw_compat_data compat_data[] = {
535 #ifdef SOC_ROCKCHIP_RK3328
536         {"rockchip,rk3328-pinctrl", (uintptr_t)&rk3328_conf},
537 #endif
538 #ifdef SOC_ROCKCHIP_RK3399
539         {"rockchip,rk3399-pinctrl", (uintptr_t)&rk3399_conf},
540 #endif
541         {NULL,             0}
542 };
543
544 static int
545 rk_pinctrl_parse_bias(phandle_t node)
546 {
547         if (OF_hasprop(node, "bias-disable"))
548                 return (0);
549         if (OF_hasprop(node, "bias-pull-up"))
550                 return (1);
551         if (OF_hasprop(node, "bias-pull-down"))
552                 return (2);
553
554         return (-1);
555 }
556
557 static int rk_pinctrl_parse_drive(struct rk_pinctrl_softc *sc, phandle_t node,
558   uint32_t bank, uint32_t subbank, uint32_t *drive, uint32_t *offset)
559 {
560         uint32_t value;
561         int i;
562
563         if (OF_getencprop(node, "drive-strength", &value,
564             sizeof(value)) != 0)
565                 return (-1);
566
567         /* Map to the correct drive value */
568         for (i = 0; i < sc->conf->npin_drive; i++) {
569                 if (sc->conf->pin_drive[i].bank != bank &&
570                     sc->conf->pin_drive[i].subbank != subbank)
571                         continue;
572                 if (sc->conf->pin_drive[i].ma == value) {
573                         *drive = sc->conf->pin_drive[i].value;
574                         return (0);
575                 }
576         }
577
578         return (-1);
579 }
580
581 static void
582 rk_pinctrl_get_fixup(struct rk_pinctrl_softc *sc, uint32_t bank, uint32_t pin,
583     uint32_t *reg, uint32_t *mask, uint32_t *bit)
584 {
585         int i;
586
587         for (i = 0; i < sc->conf->npin_fixup; i++)
588                 if (sc->conf->pin_fixup[i].bank == bank &&
589                     sc->conf->pin_fixup[i].pin == pin) {
590                         *reg = sc->conf->pin_fixup[i].reg;
591                         *mask = sc->conf->pin_fixup[i].mask;
592                         *bit = sc->conf->pin_fixup[i].bit;
593
594                         return;
595                 }
596 }
597
598 static void
599 rk_pinctrl_configure_pin(struct rk_pinctrl_softc *sc, uint32_t *pindata)
600 {
601         phandle_t pin_conf;
602         struct syscon *syscon;
603         uint32_t bank, subbank, pin, function, bias;
604         uint32_t bit, mask, reg, drive;
605         int i;
606
607         bank = pindata[0];
608         pin = pindata[1];
609         function = pindata[2];
610         pin_conf = OF_node_from_xref(pindata[3]);
611         subbank = pin / 8;
612
613         for (i = 0; i < sc->conf->iomux_nbanks; i++)
614                 if (sc->conf->iomux_conf[i].bank_num == bank &&
615                     sc->conf->iomux_conf[i].subbank_num == subbank)
616                         break;
617
618         if (i == sc->conf->iomux_nbanks) {
619                 device_printf(sc->dev, "Unknown pin %d in bank %d\n", pin,
620                     bank);
621                 return;
622         }
623
624         /* Find syscon */
625         syscon = sc->conf->get_syscon(sc, bank);
626
627         /* Parse pin function */
628         reg = sc->conf->iomux_conf[i].offset;
629         switch (sc->conf->iomux_conf[i].nbits) {
630         case 3:
631                 if ((pin % 8) >= 5)
632                         reg += 4;
633                 bit = (pin % 8 % 5) * 3;
634                 mask = (0x7 << bit) << 16;
635                 break;
636         case 2:
637         default:
638                 bit = (pin % 8) * 2;
639                 mask = (0x3 << bit) << 16;
640                 break;
641         }
642         rk_pinctrl_get_fixup(sc, bank, pin, &reg, &mask, &bit);
643         SYSCON_WRITE_4(syscon, reg, function << bit | mask);
644
645         /* Pull-Up/Down */
646         bias = rk_pinctrl_parse_bias(pin_conf);
647         if (bias >= 0) {
648                 reg = sc->conf->get_pd_offset(sc, bank);
649
650                 reg += bank * 0x10 + ((pin / 8) * 0x4);
651                 bit = (pin % 8) * 2;
652                 mask = (0x3 << bit) << 16;
653                 SYSCON_WRITE_4(syscon, reg, bias << bit | mask);
654         }
655
656         /* Drive Strength */
657         if (rk_pinctrl_parse_drive(sc, pin_conf, bank, subbank, &drive, &reg) == 0) {
658                 bit = (pin % 8) * 2;
659                 mask = (0x3 << bit) << 16;
660                 SYSCON_WRITE_4(syscon, reg, bias << bit | mask);
661         }
662 }
663
664 static int
665 rk_pinctrl_configure_pins(device_t dev, phandle_t cfgxref)
666 {
667         struct rk_pinctrl_softc *sc;
668         phandle_t node;
669         uint32_t *pins;
670         int i, npins;
671
672         sc = device_get_softc(dev);
673         node = OF_node_from_xref(cfgxref);
674
675         npins = OF_getencprop_alloc_multi(node, "rockchip,pins",  sizeof(*pins),
676             (void **)&pins);
677         if (npins <= 0)
678                 return (ENOENT);
679
680         for (i = 0; i != npins; i += 4)
681                 rk_pinctrl_configure_pin(sc, pins + i);
682
683         return (0);
684 }
685
686 static int
687 rk_pinctrl_probe(device_t dev)
688 {
689
690         if (!ofw_bus_status_okay(dev))
691                 return (ENXIO);
692
693         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
694                 return (ENXIO);
695
696         device_set_desc(dev, "RockChip Pinctrl controller");
697         return (BUS_PROBE_DEFAULT);
698 }
699
700 static int
701 rk_pinctrl_attach(device_t dev)
702 {
703         struct rk_pinctrl_softc *sc;
704         phandle_t node;
705         device_t cdev;
706
707         sc = device_get_softc(dev);
708         sc->dev = dev;
709
710         node = ofw_bus_get_node(dev);
711
712         if (OF_hasprop(node, "rockchip,grf") &&
713             syscon_get_by_ofw_property(dev, node,
714             "rockchip,grf", &sc->grf) != 0) {
715                 device_printf(dev, "cannot get grf driver handle\n");
716                 return (ENXIO);
717         }
718
719         // RK3399 has banks in PMU. RK3328 does not have a PMU.
720         if (ofw_bus_node_is_compatible(node, "rockchip,rk3399-pinctrl")) {
721                 if (OF_hasprop(node, "rockchip,pmu") &&
722                     syscon_get_by_ofw_property(dev, node,
723                     "rockchip,pmu", &sc->pmu) != 0) {
724                         device_printf(dev, "cannot get pmu driver handle\n");
725                         return (ENXIO);
726                 }
727         }
728
729         sc->conf = (struct rk_pinctrl_conf *)ofw_bus_search_compatible(dev,
730             compat_data)->ocd_data;
731
732         fdt_pinctrl_register(dev, "rockchip,pins");
733         fdt_pinctrl_configure_tree(dev);
734
735         simplebus_init(dev, node);
736
737         bus_generic_probe(dev);
738
739         /* Attach child devices */
740         for (node = OF_child(node); node > 0; node = OF_peer(node)) {
741                 if (!ofw_bus_node_is_compatible(node, "rockchip,gpio-bank"))
742                         continue;
743                 cdev = simplebus_add_device(dev, node, 0, NULL, -1, NULL);
744                 if (cdev != NULL)
745                         device_probe_and_attach(cdev);
746         }
747
748         return (bus_generic_attach(dev));
749 }
750
751 static int
752 rk_pinctrl_detach(device_t dev)
753 {
754
755         return (EBUSY);
756 }
757
758 static device_method_t rk_pinctrl_methods[] = {
759         /* Device interface */
760         DEVMETHOD(device_probe,         rk_pinctrl_probe),
761         DEVMETHOD(device_attach,        rk_pinctrl_attach),
762         DEVMETHOD(device_detach,        rk_pinctrl_detach),
763
764         /* fdt_pinctrl interface */
765         DEVMETHOD(fdt_pinctrl_configure,rk_pinctrl_configure_pins),
766
767         DEVMETHOD_END
768 };
769
770 static devclass_t rk_pinctrl_devclass;
771
772 DEFINE_CLASS_1(rk_pinctrl, rk_pinctrl_driver, rk_pinctrl_methods,
773     sizeof(struct rk_pinctrl_softc), simplebus_driver);
774
775 EARLY_DRIVER_MODULE(rk_pinctrl, simplebus, rk_pinctrl_driver,
776     rk_pinctrl_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
777 MODULE_VERSION(rk_pinctrl, 1);