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