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