xref: /freebsd/sys/arm/nvidia/tegra_pinmux.c (revision aa1a8ff2d6dbc51ef058f46f3db5a8bb77967145)
1 /*-
2  * Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 /*
29  * Pin multiplexer driver for Tegra SoCs.
30  */
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/bus.h>
34 #include <sys/kernel.h>
35 #include <sys/module.h>
36 #include <sys/malloc.h>
37 #include <sys/rman.h>
38 
39 #include <machine/bus.h>
40 #include <machine/fdt.h>
41 
42 #include <dev/fdt/fdt_common.h>
43 #include <dev/fdt/fdt_pinctrl.h>
44 #include <dev/ofw/openfirm.h>
45 #include <dev/ofw/ofw_bus.h>
46 #include <dev/ofw/ofw_bus_subr.h>
47 
48 /* Pin multipexor register. */
49 #define	TEGRA_MUX_FUNCTION_MASK  0x03
50 #define	TEGRA_MUX_FUNCTION_SHIFT 0
51 #define	TEGRA_MUX_PUPD_MASK  0x03
52 #define	TEGRA_MUX_PUPD_SHIFT 2
53 #define	TEGRA_MUX_TRISTATE_SHIFT 4
54 #define	TEGRA_MUX_ENABLE_INPUT_SHIFT 5
55 #define	TEGRA_MUX_OPEN_DRAIN_SHIFT 6
56 #define	TEGRA_MUX_LOCK_SHIFT 7
57 #define	TEGRA_MUX_IORESET_SHIFT 8
58 #define	TEGRA_MUX_RCV_SEL_SHIFT 9
59 
60 /* Pin goup register. */
61 #define	TEGRA_GRP_HSM_SHIFT 2
62 #define	TEGRA_GRP_SCHMT_SHIFT 3
63 #define	TEGRA_GRP_DRV_TYPE_SHIFT 6
64 #define	TEGRA_GRP_DRV_TYPE_MASK 0x03
65 #define	TEGRA_GRP_DRV_DRVDN_SLWR_SHIFT 28
66 #define	TEGRA_GRP_DRV_DRVDN_SLWR_MASK 0x03
67 #define	TEGRA_GRP_DRV_DRVUP_SLWF_SHIFT 30
68 #define	TEGRA_GRP_DRV_DRVUP_SLWF_MASK 0x03
69 
70 struct pinmux_softc {
71 	device_t	dev;
72 	struct resource	*pad_mem_res;
73 	struct resource	*mux_mem_res;
74 	struct resource	*mipi_mem_res;
75 };
76 
77 static struct ofw_compat_data compat_data[] = {
78 	{"nvidia,tegra124-pinmux",	1},
79 	{NULL,				0},
80 };
81 
82 enum prop_id {
83 	PROP_ID_PULL,
84 	PROP_ID_TRISTATE,
85 	PROP_ID_ENABLE_INPUT,
86 	PROP_ID_OPEN_DRAIN,
87 	PROP_ID_LOCK,
88 	PROP_ID_IORESET,
89 	PROP_ID_RCV_SEL,
90 	PROP_ID_HIGH_SPEED_MODE,
91 	PROP_ID_SCHMITT,
92 	PROP_ID_LOW_POWER_MODE,
93 	PROP_ID_DRIVE_DOWN_STRENGTH,
94 	PROP_ID_DRIVE_UP_STRENGTH,
95 	PROP_ID_SLEW_RATE_FALLING,
96 	PROP_ID_SLEW_RATE_RISING,
97 	PROP_ID_DRIVE_TYPE,
98 
99 	PROP_ID_MAX_ID
100 };
101 
102 /* Numeric based parameters. */
103 static const struct prop_name {
104 	const char *name;
105 	enum prop_id id;
106 } prop_names[] = {
107 	{"nvidia,pull",			PROP_ID_PULL},
108 	{"nvidia,tristate",		PROP_ID_TRISTATE},
109 	{"nvidia,enable-input",		PROP_ID_ENABLE_INPUT},
110 	{"nvidia,open-drain",		PROP_ID_OPEN_DRAIN},
111 	{"nvidia,lock",			PROP_ID_LOCK},
112 	{"nvidia,io-reset",		PROP_ID_IORESET},
113 	{"nvidia,rcv-sel",		PROP_ID_RCV_SEL},
114 	{"nvidia,high-speed-mode",	PROP_ID_HIGH_SPEED_MODE},
115 	{"nvidia,schmitt",		PROP_ID_SCHMITT},
116 	{"nvidia,low-power-mode",	PROP_ID_LOW_POWER_MODE},
117 	{"nvidia,pull-down-strength",	PROP_ID_DRIVE_DOWN_STRENGTH},
118 	{"nvidia,pull-up-strength",	PROP_ID_DRIVE_UP_STRENGTH},
119 	{"nvidia,slew-rate-falling",	PROP_ID_SLEW_RATE_FALLING},
120 	{"nvidia,slew-rate-rising",	PROP_ID_SLEW_RATE_RISING},
121 	{"nvidia,drive-type",		PROP_ID_DRIVE_TYPE},
122 };
123 
124 /*
125  * configuration for one pin group.
126  */
127 struct pincfg {
128 	char	*function;
129 	int	params[PROP_ID_MAX_ID];
130 };
131 #define	GPIO_BANK_A	 0
132 #define	GPIO_BANK_B	 1
133 #define	GPIO_BANK_C	 2
134 #define	GPIO_BANK_D	 3
135 #define	GPIO_BANK_E	 4
136 #define	GPIO_BANK_F	 5
137 #define	GPIO_BANK_G	 6
138 #define	GPIO_BANK_H	 7
139 #define	GPIO_BANK_I	 8
140 #define	GPIO_BANK_J	 9
141 #define	GPIO_BANK_K	10
142 #define	GPIO_BANK_L	11
143 #define	GPIO_BANK_M	12
144 #define	GPIO_BANK_N	13
145 #define	GPIO_BANK_O	14
146 #define	GPIO_BANK_P	15
147 #define	GPIO_BANK_Q	16
148 #define	GPIO_BANK_R	17
149 #define	GPIO_BANK_S	18
150 #define	GPIO_BANK_T	19
151 #define	GPIO_BANK_U	20
152 #define	GPIO_BANK_V	21
153 #define	GPIO_BANK_W	22
154 #define	GPIO_BANK_X	23
155 #define	GPIO_BANK_Y	24
156 #define	GPIO_BANK_Z	25
157 #define	GPIO_BANK_AA	26
158 #define	GPIO_BANK_BB	27
159 #define	GPIO_BANK_CC	28
160 #define	GPIO_BANK_DD	29
161 #define	GPIO_BANK_EE	30
162 #define	GPIO_BANK_FF	31
163 #define	GPIO_NUM(b, p) (8 * (b) + (p))
164 
165 struct tegra_mux {
166 	char *name;
167 	bus_size_t reg;
168 	char *functions[4];
169 	int gpio_num;
170 };
171 
172 #define	GMUX(r, gb, gi, nm, f1, f2, f3, f4)				\
173 {									\
174 	.name = #nm,							\
175 	.reg = r,							\
176 	.gpio_num = GPIO_NUM(GPIO_BANK_##gb, gi),			\
177 	.functions = {#f1, #f2, #f3, #f4},				\
178 }
179 
180 #define	FMUX(r, nm, f1, f2, f3, f4)					\
181 {									\
182 	.name = #nm,							\
183 	.reg = r,							\
184 	.gpio_num = -1,							\
185 	.functions = {#f1, #f2, #f3, #f4},				\
186 }
187 
188 static const struct tegra_mux pin_mux_tbl[] = {
189 	GMUX(0x000,  O, 1, ulpi_data0_po1,         spi3,       hsi,        uarta,        ulpi),
190 	GMUX(0x004,  O, 2, ulpi_data1_po2,         spi3,       hsi,        uarta,        ulpi),
191 	GMUX(0x008,  O, 3, ulpi_data2_po3,         spi3,       hsi,        uarta,        ulpi),
192 	GMUX(0x00C,  O, 4, ulpi_data3_po4,         spi3,       hsi,        uarta,        ulpi),
193 	GMUX(0x010,  O, 5, ulpi_data4_po5,         spi2,       hsi,        uarta,        ulpi),
194 	GMUX(0x014,  O, 6, ulpi_data5_po6,         spi2,       hsi,        uarta,        ulpi),
195 	GMUX(0x018,  O, 7, ulpi_data6_po7,         spi2,       hsi,        uarta,        ulpi),
196 	GMUX(0x01C,  O, 0, ulpi_data7_po0,         spi2,       hsi,        uarta,        ulpi),
197 	GMUX(0x020,  P, 9, ulpi_clk_py0,           spi1,       spi5,       uartd,        ulpi),
198 	GMUX(0x024,  P, 1, ulpi_dir_py1,           spi1,       spi5,       uartd,        ulpi),
199 	GMUX(0x028,  P, 2, ulpi_nxt_py2,           spi1,       spi5,       uartd,        ulpi),
200 	GMUX(0x02C,  P, 3, ulpi_stp_py3,           spi1,       spi5,       uartd,        ulpi),
201 	GMUX(0x030,  P, 0, dap3_fs_pp0,            i2s2,       spi5,       displaya,     displayb),
202 	GMUX(0x034,  P, 1, dap3_din_pp1,           i2s2,       spi5,       displaya,     displayb),
203 	GMUX(0x038,  P, 2, dap3_dout_pp2,          i2s2,       spi5,       displaya,     rsvd4),
204 	GMUX(0x03C,  P, 3, dap3_sclk_pp3,          i2s2,       spi5,       rsvd3,        displayb),
205 	GMUX(0x040,  V, 0, pv0,                    rsvd1,      rsvd2,      rsvd3,        rsvd4),
206 	GMUX(0x044,  V, 1, pv1,                    rsvd1,      rsvd2,      rsvd3,        rsvd4),
207 	GMUX(0x048,  Z, 0, sdmmc1_clk_pz0,         sdmmc1,     clk12,      rsvd3,        rsvd4),
208 	GMUX(0x04C,  Z, 1, sdmmc1_cmd_pz1,         sdmmc1,     spdif,      spi4,         uarta),
209 	GMUX(0x050,  Y, 4, sdmmc1_dat3_py4,        sdmmc1,     spdif,      spi4,         uarta),
210 	GMUX(0x054,  Y, 5, sdmmc1_dat2_py5,        sdmmc1,     pwm0,       spi4,         uarta),
211 	GMUX(0x058,  Y, 6, sdmmc1_dat1_py6,        sdmmc1,     pwm1,       spi4,         uarta),
212 	GMUX(0x05C,  Y, 7, sdmmc1_dat0_py7,        sdmmc1,     rsvd2,      spi4,         uarta),
213 	GMUX(0x068,  W, 5, clk2_out_pw5,           extperiph2, rsvd2,      rsvd3,        rsvd4),
214 	GMUX(0x06C, CC, 5, clk2_req_pcc5,          dap,        rsvd2,      rsvd3,        rsvd4),
215 	GMUX(0x110,  N, 7, hdmi_int_pn7,           rsvd1,      rsvd2,      rsvd3,        rsvd4),
216 	GMUX(0x114,  V, 4, ddc_scl_pv4,            i2c4,       rsvd2,      rsvd3,        rsvd4),
217 	GMUX(0x118,  V, 5, ddc_sda_pv5,            i2c4,       rsvd2,      rsvd3,        rsvd4),
218 	GMUX(0x164,  V, 3, uart2_rxd_pc3,          irda,       spdif,      uarta,        spi4),
219 	GMUX(0x168,  C, 2, uart2_txd_pc2,          irda,       spdif,      uarta,        spi4),
220 	GMUX(0x16C,  J, 6, uart2_rts_n_pj6,        uarta,      uartb,      gmi,          spi4),
221 	GMUX(0x170,  J, 5, uart2_cts_n_pj5,        uarta,      uartb,      gmi,          spi4),
222 	GMUX(0x174,  W, 6, uart3_txd_pw6,          uartc,      rsvd2,      gmi,          spi4),
223 	GMUX(0x178,  W, 7, uart3_rxd_pw7,          uartc,      rsvd2,      gmi,          spi4),
224 	GMUX(0x17C,  S, 1, uart3_cts_n_pa1,        uartc,      sdmmc1,     dtv,          gmi),
225 	GMUX(0x180,  C, 0, uart3_rts_n_pc0,        uartc,      pwm0,       dtv,          gmi),
226 	GMUX(0x184,  U, 0, pu0,                    owr,        uarta,      gmi,          rsvd4),
227 	GMUX(0x188,  U, 1, pu1,                    rsvd1,      uarta,      gmi,          rsvd4),
228 	GMUX(0x18C,  U, 2, pu2,                    rsvd1,      uarta,      gmi,          rsvd4),
229 	GMUX(0x190,  U, 3, pu3,                    pwm0,       uarta,      gmi,          displayb),
230 	GMUX(0x194,  U, 4, pu4,                    pwm1,       uarta,      gmi,          displayb),
231 	GMUX(0x198,  U, 5, pu5,                    pwm2,       uarta,      gmi,          displayb),
232 	GMUX(0x19C,  U, 6, pu6,                    pwm3,       uarta,      rsvd3,        gmi),
233 	GMUX(0x1A0,  C, 5, gen1_i2c_sda_pc5,       i2c1,       rsvd2,      rsvd3,        rsvd4),
234 	GMUX(0x1A4,  C, 4, gen1_i2c_scl_pc4,       i2c1,       rsvd2,      rsvd3,        rsvd4),
235 	GMUX(0x1A8,  P, 3, dap4_fs_pp4,            i2s3,       gmi,        dtv,          rsvd4),
236 	GMUX(0x1AC,  P, 4, dap4_din_pp5,           i2s3,       gmi,        rsvd3,        rsvd4),
237 	GMUX(0x1B0,  P, 5, dap4_dout_pp6,          i2s3,       gmi,        dtv,          rsvd4),
238 	GMUX(0x1B4,  P, 7, dap4_sclk_pp7,          i2s3,       gmi,        rsvd3,        rsvd4),
239 	GMUX(0x1B8,  P, 0, clk3_out_pee0,          extperiph3, rsvd2,      rsvd3,        rsvd4),
240 	GMUX(0x1BC, EE, 1, clk3_req_pee1,          dev3,       rsvd2,      rsvd3,        rsvd4),
241 	GMUX(0x1C0,  C, 7, pc7,                    rsvd1,      rsvd2,      gmi,          gmi_alt),
242 	GMUX(0x1C4,  I, 5, pi5,                    sdmmc2,     rsvd2,      gmi,          rsvd4),
243 	GMUX(0x1C8,  I, 7, pi7,                    rsvd1,      trace,      gmi,          dtv),
244 	GMUX(0x1CC,  K, 0, pk0,                    rsvd1,      sdmmc3,     gmi,          soc),
245 	GMUX(0x1D0,  K, 1, pk1,                    sdmmc2,     trace,      gmi,          rsvd4),
246 	GMUX(0x1D4,  J, 0, pj0,                    rsvd1,      rsvd2,      gmi,          usb),
247 	GMUX(0x1D8,  J, 2, pj2,                    rsvd1,      rsvd2,      gmi,          soc),
248 	GMUX(0x1DC,  K, 3, pk3,                    sdmmc2,     trace,      gmi,          ccla),
249 	GMUX(0x1E0,  K, 4, pk4,                    sdmmc2,     rsvd2,      gmi,          gmi_alt),
250 	GMUX(0x1E4,  K, 2, pk2,                    rsvd1,      rsvd2,      gmi,          rsvd4),
251 	GMUX(0x1E8,  I, 3, pi3,                    rsvd1,      rsvd2,      gmi,          spi4),
252 	GMUX(0x1EC,  I, 6, pi6,                    rsvd1,      rsvd2,      gmi,          sdmmc2),
253 	GMUX(0x1F0,  G, 0, pg0,                    rsvd1,      rsvd2,      gmi,          rsvd4),
254 	GMUX(0x1F4,  G, 1, pg1,                    rsvd1,      rsvd2,      gmi,          rsvd4),
255 	GMUX(0x1F8,  G, 2, pg2,                    rsvd1,      trace,      gmi,          rsvd4),
256 	GMUX(0x1FC,  G, 3, pg3,                    rsvd1,      trace,      gmi,          rsvd4),
257 	GMUX(0x200,  G, 4, pg4,                    rsvd1,      tmds,       gmi,          spi4),
258 	GMUX(0x204,  G, 5, pg5,                    rsvd1,      rsvd2,      gmi,          spi4),
259 	GMUX(0x208,  G, 6, pg6,                    rsvd1,      rsvd2,      gmi,          spi4),
260 	GMUX(0x20C,  G, 7, pg7,                    rsvd1,      rsvd2,      gmi,          spi4),
261 	GMUX(0x210,  H, 0, ph0,                    pwm0,       trace,      gmi,          dtv),
262 	GMUX(0x214,  H, 1, ph1,                    pwm1,       tmds,       gmi,          displaya),
263 	GMUX(0x218,  H, 2, ph2,                    pwm2,       tmds,       gmi,          cldvfs),
264 	GMUX(0x21C,  H, 3, ph3,                    pwm3,       spi4,       gmi,          cldvfs),
265 	GMUX(0x220,  H, 4, ph4,                    sdmmc2,     rsvd2,      gmi,          rsvd4),
266 	GMUX(0x224,  H, 5, ph5,                    sdmmc2,     rsvd2,      gmi,          rsvd4),
267 	GMUX(0x228,  H, 6, ph6,                    sdmmc2,     trace,      gmi,          dtv),
268 	GMUX(0x22C,  H, 7, ph7,                    sdmmc2,     trace,      gmi,          dtv),
269 	GMUX(0x230,  J, 7, pj7,                    uartd,      rsvd2,      gmi,          gmi_alt),
270 	GMUX(0x234,  B, 0, pb0,                    uartd,      rsvd2,      gmi,          rsvd4),
271 	GMUX(0x238,  B, 1, pb1,                    uartd,      rsvd2,      gmi,          rsvd4),
272 	GMUX(0x23C,  K, 7, pk7,                    uartd,      rsvd2,      gmi,          rsvd4),
273 	GMUX(0x240,  I, 0, pi0,                    rsvd1,      rsvd2,      gmi,          rsvd4),
274 	GMUX(0x244,  I, 1, pi1,                    rsvd1,      rsvd2,      gmi,          rsvd4),
275 	GMUX(0x248,  I, 2, pi2,                    sdmmc2,     trace,      gmi,          rsvd4),
276 	GMUX(0x24C,  I, 4, pi4,                    spi4,       trace,      gmi,          displaya),
277 	GMUX(0x250,  T, 5, gen2_i2c_scl_pt5,       i2c2,       rsvd2,      gmi,          rsvd4),
278 	GMUX(0x254,  T, 6, gen2_i2c_sda_pt6,       i2c2,       rsvd2,      gmi,          rsvd4),
279 	GMUX(0x258, CC, 4, sdmmc4_clk_pcc4,        sdmmc4,     rsvd2,      gmi,          rsvd4),
280 	GMUX(0x25C,  T, 7, sdmmc4_cmd_pt7,         sdmmc4,     rsvd2,      gmi,          rsvd4),
281 	GMUX(0x260, AA, 0, sdmmc4_dat0_paa0,       sdmmc4,     spi3,       gmi,          rsvd4),
282 	GMUX(0x264, AA, 1, sdmmc4_dat1_paa1,       sdmmc4,     spi3,       gmi,          rsvd4),
283 	GMUX(0x268, AA, 2, sdmmc4_dat2_paa2,       sdmmc4,     spi3,       gmi,          rsvd4),
284 	GMUX(0x26C, AA, 3, sdmmc4_dat3_paa3,       sdmmc4,     spi3,       gmi,          rsvd4),
285 	GMUX(0x270, AA, 4, sdmmc4_dat4_paa4,       sdmmc4,     spi3,       gmi,          rsvd4),
286 	GMUX(0x274, AA, 5, sdmmc4_dat5_paa5,       sdmmc4,     spi3,       rsvd3,        rsvd4),
287 	GMUX(0x278, AA, 6, sdmmc4_dat6_paa6,       sdmmc4,     spi3,       gmi,          rsvd4),
288 	GMUX(0x27C, AA, 7, sdmmc4_dat7_paa7,       sdmmc4,     rsvd2,      gmi,          rsvd4),
289 	GMUX(0x284, CC, 0, cam_mclk_pcc0,          vi,         vi_alt1,    vi_alt3,      sdmmc2),
290 	GMUX(0x288, CC, 1, pcc1,                   i2s4,       rsvd2,      rsvd3,        sdmmc2),
291 	GMUX(0x28C, BB, 0, pbb0,                   vgp6,       vimclk2,    sdmmc2,       vimclk2_alt),
292 	GMUX(0x290, BB, 1, cam_i2c_scl_pbb1,       vgp1,       i2c3,       rsvd3,        sdmmc2),
293 	GMUX(0x294, BB, 2, cam_i2c_sda_pbb2,       vgp2,       i2c3,       rsvd3,        sdmmc2),
294 	GMUX(0x298, BB, 3, pbb3,                   vgp3,       displaya,   displayb,     sdmmc2),
295 	GMUX(0x29C, BB, 4, pbb4,                   vgp4,       displaya,   displayb,     sdmmc2),
296 	GMUX(0x2A0, BB, 5, pbb5,                   vgp5,       displaya,   rsvd3,        sdmmc2),
297 	GMUX(0x2A4, BB, 6, pbb6,                   i2s4,       rsvd2,      displayb,     sdmmc2),
298 	GMUX(0x2A8, BB, 7, pbb7,                   i2s4,       rsvd2,      rsvd3,        sdmmc2),
299 	GMUX(0x2AC, CC, 2, pcc2,                   i2s4,       rsvd2,      sdmmc3,       sdmmc2),
300 	FMUX(0x2B0,        jtag_rtck,              rtck,       rsvd2,      rsvd3,        rsvd4),
301 	GMUX(0x2B4,  Z, 6, pwr_i2c_scl_pz6,        i2cpwr,     rsvd2,      rsvd3,        rsvd4),
302 	GMUX(0x2B8,  Z, 7, pwr_i2c_sda_pz7,        i2cpwr,     rsvd2,      rsvd3,        rsvd4),
303 	GMUX(0x2BC,  R, 0, kb_row0_pr0,            kbc,        rsvd2,      rsvd3,        rsvd4),
304 	GMUX(0x2C0,  R, 1, kb_row1_pr1,            kbc,        rsvd2,      rsvd3,        rsvd4),
305 	GMUX(0x2C4,  R, 2, kb_row2_pr2,            kbc,        rsvd2,      rsvd3,        rsvd4),
306 	GMUX(0x2C8,  R, 3, kb_row3_pr3,            kbc,        displaya,   sys,          displayb),
307 	GMUX(0x2CC,  R, 4, kb_row4_pr4,            kbc,        displaya,   rsvd3,        displayb),
308 	GMUX(0x2D0,  R, 5, kb_row5_pr5,            kbc,        displaya,   rsvd3,        displayb),
309 	GMUX(0x2D4,  R, 6, kb_row6_pr6,            kbc,        displaya,   displaya_alt, displayb),
310 	GMUX(0x2D8,  R, 7, kb_row7_pr7,            kbc,        rsvd2,      cldvfs,       uarta),
311 	GMUX(0x2DC,  S, 0, kb_row8_ps0,            kbc,        rsvd2,      cldvfs,       uarta),
312 	GMUX(0x2E0,  S, 1, kb_row9_ps1,            kbc,        rsvd2,      rsvd3,        uarta),
313 	GMUX(0x2E4,  S, 2, kb_row10_ps2,           kbc,        rsvd2,      rsvd3,        uarta),
314 	GMUX(0x2E8,  S, 3, kb_row11_ps3,           kbc,        rsvd2,      rsvd3,        irda),
315 	GMUX(0x2EC,  S, 4, kb_row12_ps4,           kbc,        rsvd2,      rsvd3,        irda),
316 	GMUX(0x2F0,  S, 5, kb_row13_ps5,           kbc,        rsvd2,      spi2,         rsvd4),
317 	GMUX(0x2F4,  S, 6, kb_row14_ps6,           kbc,        rsvd2,      spi2,         rsvd4),
318 	GMUX(0x2F8,  S, 7, kb_row15_ps7,           kbc,        soc,        rsvd3,        rsvd4),
319 	GMUX(0x2FC,  Q, 0, kb_col0_pq0,            kbc,        rsvd2,      spi2,         rsvd4),
320 	GMUX(0x300,  Q, 1, kb_col1_pq1,            kbc,        rsvd2,      spi2,         rsvd4),
321 	GMUX(0x304,  Q, 2, kb_col2_pq2,            kbc,        rsvd2,      spi2,         rsvd4),
322 	GMUX(0x308,  Q, 3, kb_col3_pq3,            kbc,        displaya,   pwm2,         uarta),
323 	GMUX(0x30C,  Q, 4, kb_col4_pq4,            kbc,        owr,        sdmmc3,       uarta),
324 	GMUX(0x310,  Q, 5, kb_col5_pq5,            kbc,        rsvd2,      sdmmc3,       rsvd4),
325 	GMUX(0x314,  Q, 6, kb_col6_pq6,            kbc,        rsvd2,      spi2,         uartd),
326 	GMUX(0x318,  Q, 7, kb_col7_pq7,            kbc,        rsvd2,      spi2,         uartd),
327 	GMUX(0x31C,  A, 0, clk_32k_out_pa0,        blink,      soc,        rsvd3,        rsvd4),
328 	FMUX(0x324,        core_pwr_req,           pwron,      rsvd2,      rsvd3,        rsvd4),
329 	FMUX(0x328,        cpu_pwr_req,            cpu,        rsvd2,      rsvd3,        rsvd4),
330 	FMUX(0x32C,        pwr_int_n,              pmi,        rsvd2,      rsvd3,        rsvd4),
331 	FMUX(0x330,        clk_32k_in,             clk,        rsvd2,      rsvd3,        rsvd4),
332 	FMUX(0x334,        owr,                    owr,        rsvd2,      rsvd3,        rsvd4),
333 	GMUX(0x338,  N, 0, dap1_fs_pn0,            i2s0,       hda,        gmi,          rsvd4),
334 	GMUX(0x33C,  N, 1, dap1_din_pn1,           i2s0,       hda,        gmi,          rsvd4),
335 	GMUX(0x340,  N, 2, dap1_dout_pn2,          i2s0,       hda,        gmi,          sata),
336 	GMUX(0x344,  N, 3, dap1_sclk_pn3,          i2s0,       hda,        gmi,          rsvd4),
337 	GMUX(0x348, EE, 2, dap_mclk1_req_pee2,     dap,        dap1,       sata,         rsvd4),
338 	GMUX(0x34C,  W, 4, dap_mclk1_pw4,          extperiph1, dap2,       rsvd3,        rsvd4),
339 	GMUX(0x350,  K, 6, spdif_in_pk6,           spdif,      rsvd2,      rsvd3,        i2c3),
340 	GMUX(0x354,  K, 5, spdif_out_pk5,          spdif,      rsvd2,      rsvd3,        i2c3),
341 	GMUX(0x358,  A, 2, dap2_fs_pa2,            i2s1,       hda,        gmi,          rsvd4),
342 	GMUX(0x35C,  A, 4, dap2_din_pa4,           i2s1,       hda,        gmi,          rsvd4),
343 	GMUX(0x360,  A, 5, dap2_dout_pa5,          i2s1,       hda,        gmi,          rsvd4),
344 	GMUX(0x364,  A, 3, dap2_sclk_pa3,          i2s1,       hda,        gmi,          rsvd4),
345 	GMUX(0x368,  X, 0, dvfs_pwm_px0,           spi6,       cldvfs,     gmi,          rsvd4),
346 	GMUX(0x36C,  X, 1, gpio_x1_aud_px1,        spi6,       rsvd2,      gmi,          rsvd4),
347 	GMUX(0x370,  X, 3, gpio_x3_aud_px3,        spi6,       spi1,       gmi,          rsvd4),
348 	GMUX(0x374,  X, 2, dvfs_clk_px2,           spi6,       cldvfs,     gmi,          rsvd4),
349 	GMUX(0x378,  X, 4, gpio_x4_aud_px4,        gmi,        spi1,       spi2,         dap2),
350 	GMUX(0x37C,  X, 5, gpio_x5_aud_px5,        gmi,        spi1,       spi2,         rsvd4),
351 	GMUX(0x380,  X, 6, gpio_x6_aud_px6,        spi6,       spi1,       spi2,         gmi),
352 	GMUX(0x384,  X, 7, gpio_x7_aud_px7,        rsvd1,      spi1,       spi2,         rsvd4),
353 	GMUX(0x390,  A, 6, sdmmc3_clk_pa6,         sdmmc3,     rsvd2,      rsvd3,        spi3),
354 	GMUX(0x394,  A, 7, sdmmc3_cmd_pa7,         sdmmc3,     pwm3,       uarta,        spi3),
355 	GMUX(0x398,  B, 7, sdmmc3_dat0_pb7,        sdmmc3,     rsvd2,      rsvd3,        spi3),
356 	GMUX(0x39C,  B, 6, sdmmc3_dat1_pb6,        sdmmc3,     pwm2,       uarta,        spi3),
357 	GMUX(0x3A0,  B, 5, sdmmc3_dat2_pb5,        sdmmc3,     pwm1,       displaya,     spi3),
358 	GMUX(0x3A4,  B, 4, sdmmc3_dat3_pb4,        sdmmc3,     pwm0,       displayb,     spi3),
359 	GMUX(0x3BC, DD, 1, pex_l0_rst_n_pdd1,      pe0,        rsvd2,      rsvd3,        rsvd4),
360 	GMUX(0x3C0, DD, 2, pex_l0_clkreq_n_pdd2,   pe0,        rsvd2,      rsvd3,        rsvd4),
361 	GMUX(0x3C4, DD, 3, pex_wake_n_pdd3,        pe,         rsvd2,      rsvd3,        rsvd4),
362 	GMUX(0x3CC, DD, 5, pex_l1_rst_n_pdd5,      pe1,        rsvd2,      rsvd3,        rsvd4),
363 	GMUX(0x3D0, DD, 6, pex_l1_clkreq_n_pdd6,   pe1,        rsvd2,      rsvd3,        rsvd4),
364 	GMUX(0x3E0, EE, 3, hdmi_cec_pee3,          cec,        rsvd2,      rsvd3,        rsvd4),
365 	GMUX(0x3E4,  V, 3, sdmmc1_wp_n_pv3,        sdmmc1,     clk12,      spi4,         uarta),
366 	GMUX(0x3E8,  V, 2, sdmmc3_cd_n_pv2,        sdmmc3,     owr,        rsvd3,        rsvd4),
367 	GMUX(0x3EC,  W, 2, gpio_w2_aud_pw2,        spi6,       rsvd2,      spi2,         i2c1),
368 	GMUX(0x3F0,  W, 3, gpio_w3_aud_pw3,        spi6,       spi1,       spi2,         i2c1),
369 	GMUX(0x3F4,  N, 4, usb_vbus_en0_pn4,       usb,        rsvd2,      rsvd3,        rsvd4),
370 	GMUX(0x3F8,  N, 5, usb_vbus_en1_pn5,       usb,        rsvd2,      rsvd3,        rsvd4),
371 	GMUX(0x3FC, EE, 5, sdmmc3_clk_lb_in_pee5,  sdmmc3,     rsvd2,      rsvd3,        rsvd4),
372 	GMUX(0x400, EE, 4, sdmmc3_clk_lb_out_pee4, sdmmc3,     rsvd2,      rsvd3,        rsvd4),
373 	FMUX(0x404,        gmi_clk_lb,             sdmmc2,     rsvd2,      gmi,          rsvd4),
374 	FMUX(0x408,        reset_out_n,            rsvd1,      rsvd2,      rsvd3,        reset_out_n),
375 	GMUX(0x40C,  T, 0, kb_row16_pt0,           kbc,        rsvd2,      rsvd3,        uartc),
376 	GMUX(0x410,  T, 1, kb_row17_pt1,           kbc,        rsvd2,      rsvd3,        uartc),
377 	GMUX(0x414, FF, 1, usb_vbus_en2_pff1,      usb,        rsvd2,      rsvd3,        rsvd4),
378 	GMUX(0x418, FF, 2, pff2,                   sata,       rsvd2,      rsvd3,        rsvd4),
379 	GMUX(0x430, FF, 0, dp_hpd_pff0,            dp,         rsvd2,      rsvd3,        rsvd4),
380 };
381 
382 struct tegra_grp {
383 	char *name;
384 	bus_size_t reg;
385 	int drvdn_shift;
386 	int drvdn_mask;
387 	int drvup_shift;
388 	int drvup_mask;
389 };
390 
391 #define	GRP(r, nm, dn_s, dn_w, up_s, up_w)				\
392 {									\
393 	.name = #nm,							\
394 	.reg = r - 0x868,						\
395 	.drvdn_shift = dn_s,						\
396 	.drvdn_mask = (1 << dn_w) - 1,					\
397 	.drvup_shift = up_s,						\
398 	.drvup_mask = (1 << dn_w) - 1,					\
399 }
400 
401 /* Use register offsets from TRM */
402 static const struct tegra_grp pin_grp_tbl[] = {
403 	GRP(0x868, ao1,          12,  5,  20,  5),
404 	GRP(0x86C, ao2,          12,  5,  20,  5),
405 	GRP(0x870, at1,          12,  7,  20,  7),
406 	GRP(0x874, at2,          12,  7,  20,  7),
407 	GRP(0x878, at3,          12,  7,  20,  7),
408 	GRP(0x87C, at4,          12,  7,  20,  7),
409 	GRP(0x880, at5,          14,  5,  19,  5),
410 	GRP(0x884, cdev1,        12,  5,  20,  5),
411 	GRP(0x888, cdev2,        12,  5,  20,  5),
412 	GRP(0x890, dap1,         12,  5,  20,  5),
413 	GRP(0x894, dap2,         12,  5,  20,  5),
414 	GRP(0x898, dap3,         12,  5,  20,  5),
415 	GRP(0x89C, dap4,         12,  5,  20,  5),
416 	GRP(0x8A0, dbg,          12,  5,  20,  5),
417 	GRP(0x8B0, sdio3,        12,  7,  20,  7),
418 	GRP(0x8B4, spi,          12,  5,  20,  5),
419 	GRP(0x8B8, uaa,          12,  5,  20,  5),
420 	GRP(0x8BC, uab,          12,  5,  20,  5),
421 	GRP(0x8C0, uart2,        12,  5,  20,  5),
422 	GRP(0x8C4, uart3,        12,  5,  20,  5),
423 	GRP(0x8EC, sdio1,        12,  7,  20,  7),
424 	GRP(0x8FC, ddc,          12,  5,  20,  5),
425 	GRP(0x900, gma,          14,  5,  20,  5),
426 	GRP(0x910, gme,          14,  5,  19,  5),
427 	GRP(0x914, gmf,          14,  5,  19,  5),
428 	GRP(0x918, gmg,          14,  5,  19,  5),
429 	GRP(0x91C, gmh,          14,  5,  19,  5),
430 	GRP(0x920, owr,          12,  5,  20,  5),
431 	GRP(0x924, uda,          12,  5,  20,  5),
432 	GRP(0x928, gpv,          12,  5,  20,  5),
433 	GRP(0x92C, dev3,         12,  5,  20,  5),
434 	GRP(0x938, cec,          12,  5,  20,  5),
435 	GRP(0x994, at6,          12,  7,  20,  7),
436 	GRP(0x998, dap5,         12,  5,  20,  5),
437 	GRP(0x99C, usb_vbus_en,  12,  5,  20,  5),
438 	GRP(0x9A8, ao3,          12,  5,  -1,  0),
439 	GRP(0x9B0, ao0,          12,  5,  20,  5),
440 	GRP(0x9B4, hv0,          12,  5,  -1,  0),
441 	GRP(0x9C4, sdio4,        12,  5,  20,  5),
442 	GRP(0x9C8, ao4,          12,  7,  20,  7),
443 };
444 
445 static const struct tegra_grp *
446 pinmux_search_grp(char *grp_name)
447 {
448 	int i;
449 
450 	for (i = 0; i < nitems(pin_grp_tbl); i++) {
451 		if (strcmp(grp_name, pin_grp_tbl[i].name) == 0)
452 			return 	(&pin_grp_tbl[i]);
453 	}
454 	return (NULL);
455 }
456 
457 static const struct tegra_mux *
458 pinmux_search_mux(char *pin_name)
459 {
460 	int i;
461 
462 	for (i = 0; i < nitems(pin_mux_tbl); i++) {
463 		if (strcmp(pin_name, pin_mux_tbl[i].name) == 0)
464 			return 	(&pin_mux_tbl[i]);
465 	}
466 	return (NULL);
467 }
468 
469 static int
470 pinmux_mux_function(const struct tegra_mux *mux, char *fnc_name)
471 {
472 	int i;
473 
474 	for (i = 0; i < 4; i++) {
475 		if (strcmp(fnc_name, mux->functions[i]) == 0)
476 			return 	(i);
477 	}
478 	return (-1);
479 }
480 
481 static int
482 pinmux_config_mux(struct pinmux_softc *sc, char *pin_name,
483     const struct tegra_mux *mux, struct pincfg *cfg)
484 {
485 	int tmp;
486 	uint32_t reg;
487 
488 	reg = bus_read_4(sc->mux_mem_res, mux->reg);
489 
490 	if (cfg->function != NULL) {
491 		tmp = pinmux_mux_function(mux, cfg->function);
492 		if (tmp == -1) {
493 			device_printf(sc->dev,
494 			    "Unknown function %s for pin %s\n", cfg->function,
495 			    pin_name);
496 			return (ENXIO);
497 		}
498 		reg &= ~(TEGRA_MUX_FUNCTION_MASK << TEGRA_MUX_FUNCTION_SHIFT);
499 		reg |=  (tmp & TEGRA_MUX_FUNCTION_MASK) <<
500 		    TEGRA_MUX_FUNCTION_SHIFT;
501 	}
502 	if (cfg->params[PROP_ID_PULL] != -1) {
503 		reg &= ~(TEGRA_MUX_PUPD_MASK << TEGRA_MUX_PUPD_SHIFT);
504 		reg |=  (cfg->params[PROP_ID_PULL] & TEGRA_MUX_PUPD_MASK) <<
505 		    TEGRA_MUX_PUPD_SHIFT;
506 	}
507 	if (cfg->params[PROP_ID_TRISTATE] != -1) {
508 		reg &= ~(1 << TEGRA_MUX_TRISTATE_SHIFT);
509 		reg |=  (cfg->params[PROP_ID_TRISTATE] & 1) <<
510 		    TEGRA_MUX_TRISTATE_SHIFT;
511 	}
512 	if (cfg->params[TEGRA_MUX_ENABLE_INPUT_SHIFT] != -1) {
513 		reg &= ~(1 << TEGRA_MUX_ENABLE_INPUT_SHIFT);
514 		reg |=  (cfg->params[TEGRA_MUX_ENABLE_INPUT_SHIFT] & 1) <<
515 		    TEGRA_MUX_ENABLE_INPUT_SHIFT;
516 	}
517 	if (cfg->params[PROP_ID_ENABLE_INPUT] != -1) {
518 		reg &= ~(1 << TEGRA_MUX_ENABLE_INPUT_SHIFT);
519 		reg |=  (cfg->params[PROP_ID_ENABLE_INPUT] & 1) <<
520 		    TEGRA_MUX_ENABLE_INPUT_SHIFT;
521 	}
522 	if (cfg->params[PROP_ID_ENABLE_INPUT] != -1) {
523 		reg &= ~(1 << TEGRA_MUX_ENABLE_INPUT_SHIFT);
524 		reg |=  (cfg->params[PROP_ID_OPEN_DRAIN] & 1) <<
525 		    TEGRA_MUX_ENABLE_INPUT_SHIFT;
526 	}
527 	if (cfg->params[PROP_ID_LOCK] != -1) {
528 		reg &= ~(1 << TEGRA_MUX_LOCK_SHIFT);
529 		reg |=  (cfg->params[PROP_ID_LOCK] & 1) <<
530 		    TEGRA_MUX_LOCK_SHIFT;
531 	}
532 	if (cfg->params[PROP_ID_IORESET] != -1) {
533 		reg &= ~(1 << TEGRA_MUX_IORESET_SHIFT);
534 		reg |=  (cfg->params[PROP_ID_IORESET] & 1) <<
535 		    TEGRA_MUX_IORESET_SHIFT;
536 	}
537 	if (cfg->params[PROP_ID_RCV_SEL] != -1) {
538 		reg &= ~(1 << TEGRA_MUX_RCV_SEL_SHIFT);
539 		reg |=  (cfg->params[PROP_ID_RCV_SEL] & 1) <<
540 		    TEGRA_MUX_RCV_SEL_SHIFT;
541 	}
542 	bus_write_4(sc->mux_mem_res, mux->reg, reg);
543 	return (0);
544 }
545 
546 static int
547 pinmux_config_grp(struct pinmux_softc *sc, char *grp_name,
548     const struct tegra_grp *grp, struct pincfg *cfg)
549 {
550 	uint32_t reg;
551 
552 	reg = bus_read_4(sc->pad_mem_res, grp->reg);
553 
554 	if (cfg->params[PROP_ID_HIGH_SPEED_MODE] != -1) {
555 		reg &= ~(1 << TEGRA_GRP_HSM_SHIFT);
556 		reg |=  (cfg->params[PROP_ID_HIGH_SPEED_MODE] & 1) <<
557 		    TEGRA_GRP_HSM_SHIFT;
558 	}
559 	if (cfg->params[PROP_ID_SCHMITT] != -1) {
560 		reg &= ~(1 << TEGRA_GRP_SCHMT_SHIFT);
561 		reg |=  (cfg->params[PROP_ID_SCHMITT] & 1) <<
562 		    TEGRA_GRP_SCHMT_SHIFT;
563 	}
564 	if (cfg->params[PROP_ID_DRIVE_TYPE] != -1) {
565 		reg &= ~(TEGRA_GRP_DRV_TYPE_MASK << TEGRA_GRP_DRV_TYPE_SHIFT);
566 		reg |=  (cfg->params[PROP_ID_DRIVE_TYPE] &
567 		    TEGRA_GRP_DRV_TYPE_MASK) << TEGRA_GRP_DRV_TYPE_SHIFT;
568 	}
569 	if (cfg->params[PROP_ID_SLEW_RATE_RISING] != -1) {
570 		reg &= ~(TEGRA_GRP_DRV_DRVDN_SLWR_MASK <<
571 		    TEGRA_GRP_DRV_DRVDN_SLWR_SHIFT);
572 		reg |=  (cfg->params[PROP_ID_SLEW_RATE_RISING] &
573 		    TEGRA_GRP_DRV_DRVDN_SLWR_MASK) <<
574 		    TEGRA_GRP_DRV_DRVDN_SLWR_SHIFT;
575 	}
576 	if (cfg->params[PROP_ID_SLEW_RATE_FALLING] != -1) {
577 		reg &= ~(TEGRA_GRP_DRV_DRVUP_SLWF_MASK <<
578 		    TEGRA_GRP_DRV_DRVUP_SLWF_SHIFT);
579 		reg |=  (cfg->params[PROP_ID_SLEW_RATE_FALLING] &
580 		    TEGRA_GRP_DRV_DRVUP_SLWF_MASK) <<
581 		    TEGRA_GRP_DRV_DRVUP_SLWF_SHIFT;
582 	}
583 	if ((cfg->params[PROP_ID_DRIVE_DOWN_STRENGTH] != -1) &&
584 		 (grp->drvdn_mask != -1)) {
585 		reg &= ~(grp->drvdn_shift << grp->drvdn_mask);
586 		reg |=  (cfg->params[PROP_ID_DRIVE_DOWN_STRENGTH] &
587 		    grp->drvdn_mask) << grp->drvdn_shift;
588 	}
589 	if ((cfg->params[PROP_ID_DRIVE_UP_STRENGTH] != -1) &&
590 		 (grp->drvup_mask != -1)) {
591 		reg &= ~(grp->drvup_shift << grp->drvup_mask);
592 		reg |=  (cfg->params[PROP_ID_DRIVE_UP_STRENGTH] &
593 		    grp->drvup_mask) << grp->drvup_shift;
594 	}
595 	bus_write_4(sc->pad_mem_res, grp->reg, reg);
596 	return (0);
597 }
598 
599 static int
600 pinmux_config_node(struct pinmux_softc *sc, char *pin_name, struct pincfg *cfg)
601 {
602 	const struct tegra_mux *mux;
603 	const struct tegra_grp *grp;
604 	uint32_t reg;
605 	int rv;
606 
607 	/* Handle MIPI special case first */
608 	if (strcmp(pin_name, "dsi_b") == 0) {
609 		if (cfg->function == NULL) {
610 			/* nothing to set */
611 			return (0);
612 		}
613 		reg = bus_read_4(sc->mipi_mem_res, 0); /* register 0x820 */
614 		if (strcmp(cfg->function, "csi") == 0)
615 			reg &= ~(1 << 1);
616 		else if (strcmp(cfg->function, "dsi_b") == 0)
617 			reg |= (1 << 1);
618 		bus_write_4(sc->mipi_mem_res, 0, reg); /* register 0x820 */
619 	}
620 
621 	/* Handle pin muxes */
622 	mux = pinmux_search_mux(pin_name);
623 	if (mux != NULL) {
624 		if (mux->gpio_num != -1) {
625 			/* XXXX TODO: Reserve gpio here */
626 		}
627 		rv = pinmux_config_mux(sc, pin_name, mux, cfg);
628 		return (rv);
629 	}
630 
631 	/* Handle pin groups */
632 	grp = pinmux_search_grp(pin_name);
633 	if (grp != NULL) {
634 		rv = pinmux_config_grp(sc, pin_name, grp, cfg);
635 		return (rv);
636 	}
637 
638 	device_printf(sc->dev, "Unknown pin: %s\n", pin_name);
639 	return (ENXIO);
640 }
641 
642 static int
643 pinmux_read_node(struct pinmux_softc *sc, phandle_t node, struct pincfg *cfg,
644     char **pins, int *lpins)
645 {
646 	int rv, i;
647 
648 	*lpins = OF_getprop_alloc(node, "nvidia,pins", (void **)pins);
649 	if (*lpins <= 0)
650 		return (ENOENT);
651 
652 	/* Read function (mux) settings. */
653 	rv = OF_getprop_alloc(node, "nvidia,function",
654 	    (void **)&cfg->function);
655 	if (rv <= 0)
656 		cfg->function = NULL;
657 
658 	/* Read numeric properties. */
659 	for (i = 0; i < PROP_ID_MAX_ID; i++) {
660 		rv = OF_getencprop(node, prop_names[i].name, &cfg->params[i],
661 		    sizeof(cfg->params[i]));
662 		if (rv <= 0)
663 			cfg->params[i] = -1;
664 	}
665 	return (0);
666 }
667 
668 static int
669 pinmux_process_node(struct pinmux_softc *sc, phandle_t node)
670 {
671 	struct pincfg cfg;
672 	char *pins, *pname;
673 	int i, len, lpins, rv;
674 
675 	rv = pinmux_read_node(sc, node, &cfg, &pins, &lpins);
676 	if (rv != 0)
677 		return (rv);
678 
679 	len = 0;
680 	pname = pins;
681 	do {
682 		i = strlen(pname) + 1;
683 		rv = pinmux_config_node(sc, pname, &cfg);
684 		if (rv != 0)
685 			device_printf(sc->dev,
686 			    "Cannot configure pin: %s: %d\n", pname, rv);
687 
688 		len += i;
689 		pname += i;
690 	} while (len < lpins);
691 
692 	if (pins != NULL)
693 		OF_prop_free(pins);
694 	if (cfg.function != NULL)
695 		OF_prop_free(cfg.function);
696 	return (rv);
697 }
698 
699 static int pinmux_configure(device_t dev, phandle_t cfgxref)
700 {
701 	struct pinmux_softc *sc;
702 	phandle_t node, cfgnode;
703 
704 	sc = device_get_softc(dev);
705 	cfgnode = OF_node_from_xref(cfgxref);
706 
707 	for (node = OF_child(cfgnode); node != 0; node = OF_peer(node)) {
708 		if (!ofw_bus_node_status_okay(node))
709 			continue;
710 		pinmux_process_node(sc, node);
711 	}
712 	return (0);
713 }
714 
715 static int
716 pinmux_probe(device_t dev)
717 {
718 
719 	if (!ofw_bus_status_okay(dev))
720 		return (ENXIO);
721 
722 	if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
723 		return (ENXIO);
724 
725 	device_set_desc(dev, "Tegra pin configuration");
726 	return (BUS_PROBE_DEFAULT);
727 }
728 
729 static int
730 pinmux_detach(device_t dev)
731 {
732 
733 	/* This device is always present. */
734 	return (EBUSY);
735 }
736 
737 static int
738 pinmux_attach(device_t dev)
739 {
740 	struct pinmux_softc * sc;
741 	int rid;
742 
743 	sc = device_get_softc(dev);
744 	sc->dev = dev;
745 
746 	rid = 0;
747 	sc->pad_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
748 	    RF_ACTIVE);
749 	if (sc->pad_mem_res == NULL) {
750 		device_printf(dev, "Cannot allocate memory resources\n");
751 		return (ENXIO);
752 	}
753 
754 	rid = 1;
755 	sc->mux_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
756 	    RF_ACTIVE);
757 	if (sc->mux_mem_res == NULL) {
758 		device_printf(dev, "Cannot allocate memory resources\n");
759 		return (ENXIO);
760 	}
761 
762 	rid = 2;
763 	sc->mipi_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
764 	    RF_ACTIVE);
765 	if (sc->mipi_mem_res == NULL) {
766 		device_printf(dev, "Cannot allocate memory resources\n");
767 		return (ENXIO);
768 	}
769 
770 	/* Register as a pinctrl device and process default configuration */
771 	fdt_pinctrl_register(dev, NULL);
772 	fdt_pinctrl_configure_by_name(dev, "boot");
773 
774 	return (0);
775 }
776 
777 static device_method_t tegra_pinmux_methods[] = {
778 	/* Device interface */
779 	DEVMETHOD(device_probe,         pinmux_probe),
780 	DEVMETHOD(device_attach,        pinmux_attach),
781 	DEVMETHOD(device_detach,        pinmux_detach),
782 
783 	/* fdt_pinctrl interface */
784 	DEVMETHOD(fdt_pinctrl_configure,pinmux_configure),
785 
786 	DEVMETHOD_END
787 };
788 
789 static DEFINE_CLASS_0(pinmux, tegra_pinmux_driver, tegra_pinmux_methods,
790     sizeof(struct pinmux_softc));
791 EARLY_DRIVER_MODULE(tegra_pinmux, simplebus, tegra_pinmux_driver, NULL, NULL,
792     71);
793