1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright 2020 Michal Meloun <mmel@FreeBSD.org>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 /*
32 * Pin multiplexer driver for Tegra SoCs.
33 */
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/bus.h>
37 #include <sys/kernel.h>
38 #include <sys/module.h>
39 #include <sys/malloc.h>
40 #include <sys/rman.h>
41
42 #include <machine/bus.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 };
78
79 static struct ofw_compat_data compat_data[] = {
80 {"nvidia,tegra210-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,io-hv", 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_NUM(b, p) (8 * (b) + (p))
166
167 struct tegra_grp {
168 char *name;
169 bus_size_t reg;
170 int drvdn_shift;
171 int drvdn_mask;
172 int drvup_shift;
173 int drvup_mask;
174 };
175
176 #define GRP(r, nm, dn_s, dn_w, up_s, up_w) \
177 { \
178 .name = #nm, \
179 .reg = r - 0x8D4, \
180 .drvdn_shift = dn_s, \
181 .drvdn_mask = (1 << dn_w) - 1, \
182 .drvup_shift = up_s, \
183 .drvup_mask = (1 << up_w) - 1, \
184 }
185
186 /* Use register offsets from TRM */
187 static const struct tegra_grp pin_grp_tbl[] = {
188 GRP(0x9c0, pa6, 12, 5, 20, 5),
189 GRP(0x9c4, pcc7, 12, 5, 20, 5),
190 GRP(0x9c8, pe6, 12, 5, 20, 5),
191 GRP(0x9cc, pe7, 12, 5, 20, 5),
192 GRP(0x9d0, ph6, 12, 5, 20, 5),
193 GRP(0x9d4, pk0, 0, 0, 0, 0),
194 GRP(0x9d8, pk1, 0, 0, 0, 0),
195 GRP(0x9dc, pk2, 0, 0, 0, 0),
196 GRP(0x9e0, pk3, 0, 0, 0, 0),
197 GRP(0x9e4, pk4, 0, 0, 0, 0),
198 GRP(0x9e8, pk5, 0, 0, 0, 0),
199 GRP(0x9ec, pk6, 0, 0, 0, 0),
200 GRP(0x9f0, pk7, 0, 0, 0, 0),
201 GRP(0x9f4, pl0, 0, 0, 0, 0),
202 GRP(0x9f8, pl1, 0, 0, 0, 0),
203 GRP(0x9fc, pz0, 12, 7, 20, 7),
204 GRP(0xa00, pz1, 12, 7, 20, 7),
205 GRP(0xa04, pz2, 12, 7, 20, 7),
206 GRP(0xa08, pz3, 12, 7, 20, 7),
207 GRP(0xa0c, pz4, 12, 7, 20, 7),
208 GRP(0xa10, pz5, 12, 7, 20, 7),
209 GRP(0xa98, sdmmc1, 12, 7, 20, 7),
210 GRP(0xa9c, sdmmc2, 2, 6, 8, 6),
211 GRP(0xab0, sdmmc3, 12, 7, 20, 7),
212 GRP(0xab4, sdmmc4, 2, 6, 8, 6),
213 };
214
215 struct tegra_mux {
216 struct tegra_grp grp;
217 char *name;
218 bus_size_t reg;
219 char *functions[4];
220 int gpio_num;
221
222 };
223
224 #define GMUX(r, gb, gi, nm, f1, f2, f3, f4, gr, dn_s, dn_w, up_s, up_w) \
225 { \
226 .name = #nm, \
227 .reg = r, \
228 .gpio_num = GPIO_NUM(GPIO_BANK_##gb, gi), \
229 .functions = {#f1, #f2, #f3, #f4}, \
230 .grp.name = #nm, \
231 .grp.reg = gr - 0x8D4, \
232 .grp.drvdn_shift = dn_s, \
233 .grp.drvdn_mask = (1 << dn_w) - 1, \
234 .grp.drvup_shift = up_s, \
235 .grp.drvup_mask = (1 << up_w) - 1, \
236 }
237
238 #define FMUX(r, nm, f1, f2, f3, f4, gr, dn_s, dn_w, up_s, up_w) \
239 { \
240 .name = #nm, \
241 .reg = r, \
242 .gpio_num = -1, \
243 .functions = {#f1, #f2, #f3, #f4}, \
244 .grp.name = #nm, \
245 .grp.reg = gr - 0x8D4, \
246 .grp.drvdn_shift = dn_s, \
247 .grp.drvdn_mask = (1 << dn_w) - 1, \
248 .grp.drvup_shift = up_s, \
249 .grp.drvup_mask = (1 << up_w) - 1, \
250 }
251
252 static const struct tegra_mux pin_mux_tbl[] = {
253 GMUX(0x000, M, 0, sdmmc1_clk_pm0, sdmmc1, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
254 GMUX(0x004, M, 1, sdmmc1_cmd_pm1, sdmmc1, spi3, rsvd2, rsvd3, -1, 0, 0, 0, 0),
255 GMUX(0x008, M, 2, sdmmc1_dat3_pm2, sdmmc1, spi3, rsvd2, rsvd3, -1, 0, 0, 0, 0),
256 GMUX(0x00c, M, 3, sdmmc1_dat2_pm3, sdmmc1, spi3, rsvd2, rsvd3, -1, 0, 0, 0, 0),
257 GMUX(0x010, M, 4, sdmmc1_dat1_pm4, sdmmc1, spi3, rsvd2, rsvd3, -1, 0, 0, 0, 0),
258 GMUX(0x014, M, 5, sdmmc1_dat0_pm5, sdmmc1, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
259 GMUX(0x01c, P, 0, sdmmc3_clk_pp0, sdmmc3, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
260 GMUX(0x020, P, 1, sdmmc3_cmd_pp1, sdmmc3, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
261 GMUX(0x024, P, 5, sdmmc3_dat0_pp5, sdmmc3, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
262 GMUX(0x028, P, 4, sdmmc3_dat1_pp4, sdmmc3, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
263 GMUX(0x02c, P, 3, sdmmc3_dat2_pp3, sdmmc3, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
264 GMUX(0x030, P, 2, sdmmc3_dat3_pp2, sdmmc3, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
265 GMUX(0x038, A, 0, pex_l0_rst_n_pa0, pe0, rsvd1, rsvd2, rsvd3, 0xa5c, 12, 5, 20, 5),
266 GMUX(0x03c, A, 1, pex_l0_clkreq_n_pa1, pe0, rsvd1, rsvd2, rsvd3, 0xa58, 12, 5, 20, 5),
267 GMUX(0x040, A, 2, pex_wake_n_pa2, pe, rsvd1, rsvd2, rsvd3, 0xa68, 12, 5, 20, 5),
268 GMUX(0x044, A, 3, pex_l1_rst_n_pa3, pe1, rsvd1, rsvd2, rsvd3, 0xa64, 12, 5, 20, 5),
269 GMUX(0x048, A, 4, pex_l1_clkreq_n_pa4, pe1, rsvd1, rsvd2, rsvd3, 0xa60, 12, 5, 20, 5),
270 GMUX(0x04c, A, 5, sata_led_active_pa5, sata, rsvd1, rsvd2, rsvd3, 0xa94, 12, 5, 20, 5),
271 GMUX(0x050, C, 0, spi1_mosi_pc0, spi1, rsvd1, rsvd2, rsvd3, 0xae0, 0, 0, 0, 0),
272 GMUX(0x054, C, 1, spi1_miso_pc1, spi1, rsvd1, rsvd2, rsvd3, 0xadc, 0, 0, 0, 0),
273 GMUX(0x058, C, 2, spi1_sck_pc2, spi1, rsvd1, rsvd2, rsvd3, 0xae4, 0, 0, 0, 0),
274 GMUX(0x05c, C, 3, spi1_cs0_pc3, spi1, rsvd1, rsvd2, rsvd3, 0xad4, 0, 0, 0, 0),
275 GMUX(0x060, C, 4, spi1_cs1_pc4, spi1, rsvd1, rsvd2, rsvd3, 0xad8, 0, 0, 0, 0),
276 GMUX(0x064, B, 4, spi2_mosi_pb4, spi2, dtv, rsvd2, rsvd3, 0xaf4, 0, 0, 0, 0),
277 GMUX(0x068, B, 5, spi2_miso_pb5, spi2, dtv, rsvd2, rsvd3, 0xaf0, 0, 0, 0, 0),
278 GMUX(0x06c, B, 6, spi2_sck_pb6, spi2, dtv, rsvd2, rsvd3, 0xaf8, 0, 0, 0, 0),
279 GMUX(0x070, B, 7, spi2_cs0_pb7, spi2, dtv, rsvd2, rsvd3, 0xae8, 0, 0, 0, 0),
280 GMUX(0x074, DD, 0, spi2_cs1_pdd0, spi2, rsvd1, rsvd2, rsvd3, 0xaec, 0, 0, 0, 0),
281 GMUX(0x078, C, 7, spi4_mosi_pc7, spi4, rsvd1, rsvd2, rsvd3, 0xb04, 0, 0, 0, 0),
282 GMUX(0x07c, D, 0, spi4_miso_pd0, spi4, rsvd1, rsvd2, rsvd3, 0xb00, 0, 0, 0, 0),
283 GMUX(0x080, C, 5, spi4_sck_pc5, spi4, rsvd1, rsvd2, rsvd3, 0xb08, 0, 0, 0, 0),
284 GMUX(0x084, C, 6, spi4_cs0_pc6, spi4, rsvd1, rsvd2, rsvd3, 0xafc, 0, 0, 0, 0),
285 GMUX(0x088, EE, 0, qspi_sck_pee0, qspi, rsvd1, rsvd2, rsvd3, 0xa90, 0, 0, 0, 0),
286 GMUX(0x08c, EE, 1, qspi_cs_n_pee1, qspi, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
287 GMUX(0x090, EE, 2, qspi_io0_pee2, qspi, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
288 GMUX(0x094, EE, 3, qspi_io1_pee3, qspi, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
289 GMUX(0x098, EE, 4, qspi_io2_pee4, qspi, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
290 GMUX(0x09c, EE, 5, qspi_io3_pee5, qspi, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
291 GMUX(0x0a4, E, 0, dmic1_clk_pe0, dmic1, i2s3, rsvd2, rsvd3, 0x984, 12, 5, 20, 5),
292 GMUX(0x0a8, E, 1, dmic1_dat_pe1, dmic1, i2s3, rsvd2, rsvd3, 0x988, 12, 5, 20, 5),
293 GMUX(0x0ac, E, 2, dmic2_clk_pe2, dmic2, i2s3, rsvd2, rsvd3, 0x98c, 12, 5, 20, 5),
294 GMUX(0x0b0, E, 3, dmic2_dat_pe3, dmic2, i2s3, rsvd2, rsvd3, 0x990, 12, 5, 20, 5),
295 GMUX(0x0b4, E, 4, dmic3_clk_pe4, dmic3, i2s5a, rsvd2, rsvd3, 0x994, 12, 5, 20, 5),
296 GMUX(0x0b8, E, 5, dmic3_dat_pe5, dmic3, i2s5a, rsvd2, rsvd3, 0x998, 12, 5, 20, 5),
297 GMUX(0x0bc, J, 1, gen1_i2c_scl_pj1, i2c1, rsvd1, rsvd2, rsvd3, 0x9a8, 12, 5, 20, 5),
298 GMUX(0x0c0, J, 0, gen1_i2c_sda_pj0, i2c1, rsvd1, rsvd2, rsvd3, 0x9ac, 12, 5, 20, 5),
299 GMUX(0x0c4, J, 2, gen2_i2c_scl_pj2, i2c2, rsvd1, rsvd2, rsvd3, 0x9b0, 12, 5, 20, 5),
300 GMUX(0x0c8, J, 3, gen2_i2c_sda_pj3, i2c2, rsvd1, rsvd2, rsvd3, 0x9b4, 12, 5, 20, 5),
301 GMUX(0x0cc, F, 0, gen3_i2c_scl_pf0, i2c3, rsvd1, rsvd2, rsvd3, 0x9b8, 12, 5, 20, 5),
302 GMUX(0x0d0, F, 1, gen3_i2c_sda_pf1, i2c3, rsvd1, rsvd2, rsvd3, 0x9bc, 12, 5, 20, 5),
303 GMUX(0x0d4, S, 2, cam_i2c_scl_ps2, i2c3, i2cvi, rsvd2, rsvd3, 0x934, 12, 5, 20, 5),
304 GMUX(0x0d8, S, 3, cam_i2c_sda_ps3, i2c3, i2cvi, rsvd2, rsvd3, 0x938, 12, 5, 20, 5),
305 GMUX(0x0dc, Y, 3, pwr_i2c_scl_py3, i2cpmu, rsvd1, rsvd2, rsvd3, 0xa6c, 12, 5, 20, 5),
306 GMUX(0x0e0, Y, 4, pwr_i2c_sda_py4, i2cpmu, rsvd1, rsvd2, rsvd3, 0xa70, 12, 5, 20, 5),
307 GMUX(0x0e4, U, 0, uart1_tx_pu0, uarta, rsvd1, rsvd2, rsvd3, 0xb28, 12, 5, 20, 5),
308 GMUX(0x0e8, U, 1, uart1_rx_pu1, uarta, rsvd1, rsvd2, rsvd3, 0xb24, 12, 5, 20, 5),
309 GMUX(0x0ec, U, 2, uart1_rts_pu2, uarta, rsvd1, rsvd2, rsvd3, 0xb20, 12, 5, 20, 5),
310 GMUX(0x0f0, U, 3, uart1_cts_pu3, uarta, rsvd1, rsvd2, rsvd3, 0xb1c, 12, 5, 20, 5),
311 GMUX(0x0f4, G, 0, uart2_tx_pg0, uartb, i2s4a, spdif, uart, 0xb38, 12, 5, 20, 5),
312 GMUX(0x0f8, G, 1, uart2_rx_pg1, uartb, i2s4a, spdif, uart, 0xb34, 12, 5, 20, 5),
313 GMUX(0x0fc, G, 2, uart2_rts_pg2, uartb, i2s4a, rsvd2, uart, 0xb30, 12, 5, 20, 5),
314 GMUX(0x100, G, 3, uart2_cts_pg3, uartb, i2s4a, rsvd2, uart, 0xb2c, 12, 5, 20, 5),
315 GMUX(0x104, D, 1, uart3_tx_pd1, uartc, spi4, rsvd2, rsvd3, 0xb48, 12, 5, 20, 5),
316 GMUX(0x108, D, 2, uart3_rx_pd2, uartc, spi4, rsvd2, rsvd3, 0xb44, 12, 5, 20, 5),
317 GMUX(0x10c, D, 3, uart3_rts_pd3, uartc, spi4, rsvd2, rsvd3, 0xb40, 12, 5, 20, 5),
318 GMUX(0x110, D, 4, uart3_cts_pd4, uartc, spi4, rsvd2, rsvd3, 0xb3c, 12, 5, 20, 5),
319 GMUX(0x114, I, 4, uart4_tx_pi4, uartd, uart, rsvd2, rsvd3, 0xb58, 12, 5, 20, 5),
320 GMUX(0x118, I, 5, uart4_rx_pi5, uartd, uart, rsvd2, rsvd3, 0xb54, 12, 5, 20, 5),
321 GMUX(0x11c, I, 6, uart4_rts_pi6, uartd, uart, rsvd2, rsvd3, 0xb50, 12, 5, 20, 5),
322 GMUX(0x120, I, 7, uart4_cts_pi7, uartd, uart, rsvd2, rsvd3, 0xb4c, 12, 5, 20, 5),
323 GMUX(0x124, B, 0, dap1_fs_pb0, i2s1, rsvd1, rsvd2, rsvd3, 0x95c, 0, 0, 0, 0),
324 GMUX(0x128, B, 1, dap1_din_pb1, i2s1, rsvd1, rsvd2, rsvd3, 0x954, 0, 0, 0, 0),
325 GMUX(0x12c, B, 2, dap1_dout_pb2, i2s1, rsvd1, rsvd2, rsvd3, 0x958, 0, 0, 0, 0),
326 GMUX(0x130, B, 3, dap1_sclk_pb3, i2s1, rsvd1, rsvd2, rsvd3, 0x960, 0, 0, 0, 0),
327 GMUX(0x134, AA, 0, dap2_fs_paa0, i2s2, rsvd1, rsvd2, rsvd3, 0x96c, 0, 0, 0, 0),
328 GMUX(0x138, AA, 2, dap2_din_paa2, i2s2, rsvd1, rsvd2, rsvd3, 0x964, 0, 0, 0, 0),
329 GMUX(0x13c, AA, 3, dap2_dout_paa3, i2s2, rsvd1, rsvd2, rsvd3, 0x968, 0, 0, 0, 0),
330 GMUX(0x140, AA, 1, dap2_sclk_paa1, i2s2, rsvd1, rsvd2, rsvd3, 0x970, 0, 0, 0, 0),
331 GMUX(0x144, J, 4, dap4_fs_pj4, i2s4b, rsvd1, rsvd2, rsvd3, 0x97c, 12, 5, 20, 5),
332 GMUX(0x148, J, 5, dap4_din_pj5, i2s4b, rsvd1, rsvd2, rsvd3, 0x974, 12, 5, 20, 5),
333 GMUX(0x14c, J, 6, dap4_dout_pj6, i2s4b, rsvd1, rsvd2, rsvd3, 0x978, 12, 5, 20, 5),
334 GMUX(0x150, J, 7, dap4_sclk_pj7, i2s4b, rsvd1, rsvd2, rsvd3, 0x980, 12, 5, 20, 5),
335 GMUX(0x154, S, 0, cam1_mclk_ps0, extperiph3, rsvd1, rsvd2, rsvd3, 0x918, 12, 5, 20, 5),
336 GMUX(0x158, S, 1, cam2_mclk_ps1, extperiph3, rsvd1, rsvd2, rsvd3, 0x924, 12, 5, 20, 5),
337 FMUX(0x15c, jtag_rtck, jtag, rsvd1, rsvd2, rsvd3, 0xa2c, 12, 5, 20, 5),
338 FMUX(0x160, clk_32k_in, clk, rsvd1, rsvd2, rsvd3, 0x940, 12, 5, 20, 5),
339 GMUX(0x164, Y, 5, clk_32k_out_py5, soc, blink, rsvd2, rsvd3, 0x944, 12, 5, 20, 5),
340 FMUX(0x168, batt_bcl, bcl, rsvd1, rsvd2, rsvd3, 0x8f8, 12, 5, 20, 5),
341 FMUX(0x16c, clk_req, sys, rsvd1, rsvd2, rsvd3, 0x948, 12, 5, 20, 5),
342 FMUX(0x170, cpu_pwr_req, cpu, rsvd1, rsvd2, rsvd3, 0x950, 12, 5, 20, 5),
343 FMUX(0x174, pwr_int_n, pmi, rsvd1, rsvd2, rsvd3, 0xa74, 12, 5, 20, 5),
344 FMUX(0x178, shutdown, shutdown, rsvd1, rsvd2, rsvd3, 0xac8, 12, 5, 20, 5),
345 FMUX(0x17c, core_pwr_req, core, rsvd1, rsvd2, rsvd3, 0x94c, 12, 5, 20, 5),
346 GMUX(0x180, BB, 0, aud_mclk_pbb0, aud, rsvd1, rsvd2, rsvd3, 0x8f4, 12, 5, 20, 5),
347 GMUX(0x184, BB, 1, dvfs_pwm_pbb1, rsvd0, cldvfs, spi3, rsvd3, 0x9a4, 12, 5, 20, 5),
348 GMUX(0x188, BB, 2, dvfs_clk_pbb2, rsvd0, cldvfs, spi3, rsvd3, 0x9a0, 12, 5, 20, 5),
349 GMUX(0x18c, BB, 3, gpio_x1_aud_pbb3, rsvd0, rsvd1, spi3, rsvd3, 0xa14, 12, 5, 20, 5),
350 GMUX(0x190, BB, 4, gpio_x3_aud_pbb4, rsvd0, rsvd1, spi3, rsvd3, 0xa18, 12, 5, 20, 5),
351 GMUX(0x194, CC, 7, pcc7, rsvd0, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
352 GMUX(0x198, CC, 0, hdmi_cec_pcc0, cec, rsvd1, rsvd2, rsvd3, 0xa24, 12, 5, 20, 5),
353 GMUX(0x19c, CC, 1, hdmi_int_dp_hpd_pcc1, dp, rsvd1, rsvd2, rsvd3, 0xa28, 12, 5, 20, 5),
354 GMUX(0x1a0, CC, 2, spdif_out_pcc2, spdif, rsvd1, rsvd2, rsvd3, 0xad0, 12, 5, 20, 5),
355 GMUX(0x1a4, CC, 3, spdif_in_pcc3, spdif, rsvd1, rsvd2, rsvd3, 0xacc, 12, 5, 20, 5),
356 GMUX(0x1a8, CC, 4, usb_vbus_en0_pcc4, usb, rsvd1, rsvd2, rsvd3, 0xb5c, 12, 5, 20, 5),
357 GMUX(0x1ac, CC, 5, usb_vbus_en1_pcc5, usb, rsvd1, rsvd2, rsvd3, 0xb60, 12, 5, 20, 5),
358 GMUX(0x1b0, CC, 6, dp_hpd0_pcc6, dp, rsvd1, rsvd2, rsvd3, 0x99c, 12, 5, 20, 5),
359 GMUX(0x1b4, H, 0, wifi_en_ph0, rsvd0, rsvd1, rsvd2, rsvd3, 0xb64, 12, 5, 20, 5),
360 GMUX(0x1b8, H, 1, wifi_rst_ph1, rsvd0, rsvd1, rsvd2, rsvd3, 0xb68, 12, 5, 20, 5),
361 GMUX(0x1bc, H, 2, wifi_wake_ap_ph2, rsvd0, rsvd1, rsvd2, rsvd3, 0xb6c, 12, 5, 20, 5),
362 GMUX(0x1c0, H, 3, ap_wake_bt_ph3, rsvd0, uartb, spdif, rsvd3, 0x8ec, 12, 5, 20, 5),
363 GMUX(0x1c4, H, 4, bt_rst_ph4, rsvd0, uartb, spdif, rsvd3, 0x8fc, 12, 5, 20, 5),
364 GMUX(0x1c8, H, 5, bt_wake_ap_ph5, rsvd0, rsvd1, rsvd2, rsvd3, 0x900, 12, 5, 20, 5),
365 GMUX(0x1cc, H, 7, ap_wake_nfc_ph7, rsvd0, rsvd1, rsvd2, rsvd3, 0x8f0, 12, 5, 20, 5),
366 GMUX(0x1d0, I, 0, nfc_en_pi0, rsvd0, rsvd1, rsvd2, rsvd3, 0xa50, 12, 5, 20, 5),
367 GMUX(0x1d4, I, 1, nfc_int_pi1, rsvd0, rsvd1, rsvd2, rsvd3, 0xa54, 12, 5, 20, 5),
368 GMUX(0x1d8, I, 2, gps_en_pi2, rsvd0, rsvd1, rsvd2, rsvd3, 0xa1c, 12, 5, 20, 5),
369 GMUX(0x1dc, I, 3, gps_rst_pi3, rsvd0, rsvd1, rsvd2, rsvd3, 0xa20, 12, 5, 20, 5),
370 GMUX(0x1e0, S, 4, cam_rst_ps4, vgp1, rsvd1, rsvd2, rsvd3, 0x93c, 12, 5, 20, 5),
371 GMUX(0x1e4, S, 5, cam_af_en_ps5, vimclk, vgp2, rsvd2, rsvd3, 0x92c, 12, 5, 20, 5),
372 GMUX(0x1e8, S, 6, cam_flash_en_ps6, vimclk, vgp3, rsvd2, rsvd3, 0x930, 12, 5, 20, 5),
373 GMUX(0x1ec, S, 7, cam1_pwdn_ps7, vgp4, rsvd1, rsvd2, rsvd3, 0x91c, 12, 5, 20, 5),
374 GMUX(0x1f0, T, 0, cam2_pwdn_pt0, vgp5, rsvd1, rsvd2, rsvd3, 0x928, 12, 5, 20, 5),
375 GMUX(0x1f4, T, 1, cam1_strobe_pt1, vgp6, rsvd1, rsvd2, rsvd3, 0x920, 12, 5, 20, 5),
376 GMUX(0x1f8, Y, 2, lcd_te_py2, displaya, rsvd1, rsvd2, rsvd3, 0xa44, 12, 5, 20, 5),
377 GMUX(0x1fc, V, 0, lcd_bl_pwm_pv0, displaya, pwm0, sor0, rsvd3, 0xa34, 12, 5, 20, 5),
378 GMUX(0x200, V, 1, lcd_bl_en_pv1, rsvd0, rsvd1, rsvd2, rsvd3, 0xa30, 12, 5, 20, 5),
379 GMUX(0x204, V, 2, lcd_rst_pv2, rsvd0, rsvd1, rsvd2, rsvd3, 0xa40, 12, 5, 20, 5),
380 GMUX(0x208, V, 3, lcd_gpio1_pv3, displayb, rsvd1, rsvd2, rsvd3, 0xa38, 12, 5, 20, 5),
381 GMUX(0x20c, V, 4, lcd_gpio2_pv4, displayb, pwm1, rsvd2, sor1, 0xa3c, 12, 5, 20, 5),
382 GMUX(0x210, V, 5, ap_ready_pv5, rsvd0, rsvd1, rsvd2, rsvd3, 0x8e8, 12, 5, 20, 5),
383 GMUX(0x214, V, 6, touch_rst_pv6, rsvd0, rsvd1, rsvd2, rsvd3, 0xb18, 12, 5, 20, 5),
384 GMUX(0x218, V, 7, touch_clk_pv7, touch, rsvd1, rsvd2, rsvd3, 0xb10, 12, 5, 20, 5),
385 GMUX(0x21c, X, 0, modem_wake_ap_px0, rsvd0, rsvd1, rsvd2, rsvd3, 0xa48, 12, 5, 20, 5),
386 GMUX(0x220, X, 1, touch_int_px1, rsvd0, rsvd1, rsvd2, rsvd3, 0xb14, 12, 5, 20, 5),
387 GMUX(0x224, X, 2, motion_int_px2, rsvd0, rsvd1, rsvd2, rsvd3, 0xa4c, 12, 5, 20, 5),
388 GMUX(0x228, X, 3, als_prox_int_px3, rsvd0, rsvd1, rsvd2, rsvd3, 0x8e4, 12, 5, 20, 5),
389 GMUX(0x22c, X, 4, temp_alert_px4, rsvd0, rsvd1, rsvd2, rsvd3, 0xb0c, 12, 5, 20, 5),
390 GMUX(0x230, X, 5, button_power_on_px5, rsvd0, rsvd1, rsvd2, rsvd3, 0x908, 12, 5, 20, 5),
391 GMUX(0x234, X, 6, button_vol_up_px6, rsvd0, rsvd1, rsvd2, rsvd3, 0x914, 12, 5, 20, 5),
392 GMUX(0x238, X, 7, button_vol_down_px7, rsvd0, rsvd1, rsvd2, rsvd3, 0x910, 12, 5, 20, 5),
393 GMUX(0x23c, Y, 0, button_slide_sw_py0, rsvd0, rsvd1, rsvd2, rsvd3, 0x90c, 12, 5, 20, 5),
394 GMUX(0x240, Y, 1, button_home_py1, rsvd0, rsvd1, rsvd2, rsvd3, 0x904, 12, 5, 20, 5),
395 GMUX(0x244, A, 6, pa6, sata, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
396 GMUX(0x248, E, 6, pe6, rsvd0, i2s5a, pwm2, rsvd3, -1, 0, 0, 0, 0),
397 GMUX(0x24c, E, 7, pe7, rsvd0, i2s5a, pwm3, rsvd3, -1, 0, 0, 0, 0),
398 GMUX(0x250, H, 6, ph6, rsvd0, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
399 GMUX(0x254, K, 0, pk0, iqc0, i2s5b, rsvd2, rsvd3, -1, 0, 0, 0, 0),
400 GMUX(0x258, K, 1, pk1, iqc0, i2s5b, rsvd2, rsvd3, -1, 0, 0, 0, 0),
401 GMUX(0x25c, K, 2, pk2, iqc0, i2s5b, rsvd2, rsvd3, -1, 0, 0, 0, 0),
402 GMUX(0x260, K, 3, pk3, iqc0, i2s5b, rsvd2, rsvd3, -1, 0, 0, 0, 0),
403 GMUX(0x264, K, 4, pk4, iqc1, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
404 GMUX(0x268, K, 5, pk5, iqc1, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
405 GMUX(0x26c, K, 6, pk6, iqc1, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
406 GMUX(0x270, K, 7, pk7, iqc1, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
407 GMUX(0x274, L, 0, pl0, rsvd0, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
408 GMUX(0x278, L, 1, pl1, soc, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
409 GMUX(0x27c, Z, 0, pz0, vimclk2, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
410 GMUX(0x280, Z, 1, pz1, vimclk2, sdmmc1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
411 GMUX(0x284, Z, 2, pz2, sdmmc3, ccla, rsvd2, rsvd3, -1, 0, 0, 0, 0),
412 GMUX(0x288, Z, 3, pz3, sdmmc3, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
413 GMUX(0x28c, Z, 4, pz4, sdmmc1, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
414 GMUX(0x290, Z, 5, pz5, soc, rsvd1, rsvd2, rsvd3, -1, 0, 0, 0, 0),
415 };
416
417
418 static const struct tegra_grp *
419 pinmux_search_grp(char *grp_name)
420 {
421 int i;
422
423 for (i = 0; i < nitems(pin_grp_tbl); i++) {
424 if (strcmp(grp_name, pin_grp_tbl[i].name) == 0)
425 return (&pin_grp_tbl[i]);
426 }
427 return (NULL);
428 }
429
430 static const struct tegra_mux *
431 pinmux_search_mux(char *pin_name)
432 {
433 int i;
434
435 for (i = 0; i < nitems(pin_mux_tbl); i++) {
436 if (strcmp(pin_name, pin_mux_tbl[i].name) == 0)
437 return (&pin_mux_tbl[i]);
438 }
439 return (NULL);
440 }
441
442 static int
443 pinmux_mux_function(const struct tegra_mux *mux, char *fnc_name)
444 {
445 int i;
446
447 for (i = 0; i < 4; i++) {
448 if (strcmp(fnc_name, mux->functions[i]) == 0)
449 return (i);
450 }
451 return (-1);
452 }
453
454 static int
455 pinmux_config_mux(struct pinmux_softc *sc, char *pin_name,
456 const struct tegra_mux *mux, struct pincfg *cfg)
457 {
458 int tmp;
459 uint32_t reg;
460
461 reg = bus_read_4(sc->mux_mem_res, mux->reg);
462
463 if (cfg->function != NULL) {
464 tmp = pinmux_mux_function(mux, cfg->function);
465 if (tmp == -1) {
466 device_printf(sc->dev,
467 "Unknown function %s for pin %s\n", cfg->function,
468 pin_name);
469 return (ENXIO);
470 }
471 reg &= ~(TEGRA_MUX_FUNCTION_MASK << TEGRA_MUX_FUNCTION_SHIFT);
472 reg |= (tmp & TEGRA_MUX_FUNCTION_MASK) <<
473 TEGRA_MUX_FUNCTION_SHIFT;
474 }
475 if (cfg->params[PROP_ID_PULL] != -1) {
476 reg &= ~(TEGRA_MUX_PUPD_MASK << TEGRA_MUX_PUPD_SHIFT);
477 reg |= (cfg->params[PROP_ID_PULL] & TEGRA_MUX_PUPD_MASK) <<
478 TEGRA_MUX_PUPD_SHIFT;
479 }
480 if (cfg->params[PROP_ID_TRISTATE] != -1) {
481 reg &= ~(1 << TEGRA_MUX_TRISTATE_SHIFT);
482 reg |= (cfg->params[PROP_ID_TRISTATE] & 1) <<
483 TEGRA_MUX_TRISTATE_SHIFT;
484 }
485 if (cfg->params[TEGRA_MUX_ENABLE_INPUT_SHIFT] != -1) {
486 reg &= ~(1 << TEGRA_MUX_ENABLE_INPUT_SHIFT);
487 reg |= (cfg->params[TEGRA_MUX_ENABLE_INPUT_SHIFT] & 1) <<
488 TEGRA_MUX_ENABLE_INPUT_SHIFT;
489 }
490 if (cfg->params[PROP_ID_ENABLE_INPUT] != -1) {
491 reg &= ~(1 << TEGRA_MUX_ENABLE_INPUT_SHIFT);
492 reg |= (cfg->params[PROP_ID_ENABLE_INPUT] & 1) <<
493 TEGRA_MUX_ENABLE_INPUT_SHIFT;
494 }
495 if (cfg->params[PROP_ID_ENABLE_INPUT] != -1) {
496 reg &= ~(1 << TEGRA_MUX_ENABLE_INPUT_SHIFT);
497 reg |= (cfg->params[PROP_ID_OPEN_DRAIN] & 1) <<
498 TEGRA_MUX_ENABLE_INPUT_SHIFT;
499 }
500 if (cfg->params[PROP_ID_LOCK] != -1) {
501 reg &= ~(1 << TEGRA_MUX_LOCK_SHIFT);
502 reg |= (cfg->params[PROP_ID_LOCK] & 1) <<
503 TEGRA_MUX_LOCK_SHIFT;
504 }
505 if (cfg->params[PROP_ID_IORESET] != -1) {
506 reg &= ~(1 << TEGRA_MUX_IORESET_SHIFT);
507 reg |= (cfg->params[PROP_ID_IORESET] & 1) <<
508 TEGRA_MUX_IORESET_SHIFT;
509 }
510 if (cfg->params[PROP_ID_RCV_SEL] != -1) {
511 reg &= ~(1 << TEGRA_MUX_RCV_SEL_SHIFT);
512 reg |= (cfg->params[PROP_ID_RCV_SEL] & 1) <<
513 TEGRA_MUX_RCV_SEL_SHIFT;
514 }
515 bus_write_4(sc->mux_mem_res, mux->reg, reg);
516 return (0);
517 }
518
519 static int
520 pinmux_config_grp(struct pinmux_softc *sc, char *grp_name,
521 const struct tegra_grp *grp, struct pincfg *cfg)
522 {
523 uint32_t reg;
524
525 reg = bus_read_4(sc->pad_mem_res, grp->reg);
526
527 if (cfg->params[PROP_ID_HIGH_SPEED_MODE] != -1) {
528 reg &= ~(1 << TEGRA_GRP_HSM_SHIFT);
529 reg |= (cfg->params[PROP_ID_HIGH_SPEED_MODE] & 1) <<
530 TEGRA_GRP_HSM_SHIFT;
531 }
532 if (cfg->params[PROP_ID_SCHMITT] != -1) {
533 reg &= ~(1 << TEGRA_GRP_SCHMT_SHIFT);
534 reg |= (cfg->params[PROP_ID_SCHMITT] & 1) <<
535 TEGRA_GRP_SCHMT_SHIFT;
536 }
537 if (cfg->params[PROP_ID_DRIVE_TYPE] != -1) {
538 reg &= ~(TEGRA_GRP_DRV_TYPE_MASK << TEGRA_GRP_DRV_TYPE_SHIFT);
539 reg |= (cfg->params[PROP_ID_DRIVE_TYPE] &
540 TEGRA_GRP_DRV_TYPE_MASK) << TEGRA_GRP_DRV_TYPE_SHIFT;
541 }
542 if (cfg->params[PROP_ID_SLEW_RATE_RISING] != -1) {
543 reg &= ~(TEGRA_GRP_DRV_DRVDN_SLWR_MASK <<
544 TEGRA_GRP_DRV_DRVDN_SLWR_SHIFT);
545 reg |= (cfg->params[PROP_ID_SLEW_RATE_RISING] &
546 TEGRA_GRP_DRV_DRVDN_SLWR_MASK) <<
547 TEGRA_GRP_DRV_DRVDN_SLWR_SHIFT;
548 }
549 if (cfg->params[PROP_ID_SLEW_RATE_FALLING] != -1) {
550 reg &= ~(TEGRA_GRP_DRV_DRVUP_SLWF_MASK <<
551 TEGRA_GRP_DRV_DRVUP_SLWF_SHIFT);
552 reg |= (cfg->params[PROP_ID_SLEW_RATE_FALLING] &
553 TEGRA_GRP_DRV_DRVUP_SLWF_MASK) <<
554 TEGRA_GRP_DRV_DRVUP_SLWF_SHIFT;
555 }
556 if ((cfg->params[PROP_ID_DRIVE_DOWN_STRENGTH] != -1) &&
557 (grp->drvdn_mask != 0)) {
558 reg &= ~(grp->drvdn_shift << grp->drvdn_mask);
559 reg |= (cfg->params[PROP_ID_DRIVE_DOWN_STRENGTH] &
560 grp->drvdn_mask) << grp->drvdn_shift;
561 }
562 if ((cfg->params[PROP_ID_DRIVE_UP_STRENGTH] != -1) &&
563 (grp->drvup_mask != 0)) {
564 reg &= ~(grp->drvup_shift << grp->drvup_mask);
565 reg |= (cfg->params[PROP_ID_DRIVE_UP_STRENGTH] &
566 grp->drvup_mask) << grp->drvup_shift;
567 }
568 bus_write_4(sc->pad_mem_res, grp->reg, reg);
569 return (0);
570 }
571
572 static int
573 pinmux_config_node(struct pinmux_softc *sc, char *pin_name, struct pincfg *cfg)
574 {
575 const struct tegra_mux *mux;
576 const struct tegra_grp *grp;
577 bool handled;
578 int rv;
579
580 /* Handle pin muxes */
581 mux = pinmux_search_mux(pin_name);
582 handled = false;
583 if (mux != NULL) {
584 if (mux->gpio_num != -1) {
585 /* XXXX TODO: Reserve gpio here */
586 }
587 rv = pinmux_config_mux(sc, pin_name, mux, cfg);
588 if (rv != 0)
589 return (rv);
590 if (mux->grp.reg <= 0) {
591 rv = pinmux_config_grp(sc, pin_name, &mux->grp, cfg);
592 return (rv);
593 }
594 handled = true;
595 }
596
597 /* And/or handle pin groups */
598 grp = pinmux_search_grp(pin_name);
599 if (grp != NULL) {
600 rv = pinmux_config_grp(sc, pin_name, grp, cfg);
601 if (rv != 0)
602 return (rv);
603 handled = true;
604 }
605
606 if (!handled) {
607 device_printf(sc->dev, "Unknown pin: %s\n", pin_name);
608 return (ENXIO);
609 }
610 return (0);
611 }
612
613 static int
614 pinmux_read_node(struct pinmux_softc *sc, phandle_t node, struct pincfg *cfg,
615 char **pins, int *lpins)
616 {
617 int rv, i;
618
619 *lpins = OF_getprop_alloc(node, "nvidia,pins", (void **)pins);
620 if (*lpins <= 0)
621 return (ENOENT);
622
623 /* Read function (mux) settings. */
624 rv = OF_getprop_alloc(node, "nvidia,function", (void **)&cfg->function);
625 if (rv <= 0)
626 cfg->function = NULL;
627
628 /* Read numeric properties. */
629 for (i = 0; i < PROP_ID_MAX_ID; i++) {
630 rv = OF_getencprop(node, prop_names[i].name, &cfg->params[i],
631 sizeof(cfg->params[i]));
632 if (rv <= 0)
633 cfg->params[i] = -1;
634 }
635 return (0);
636 }
637
638 static int
639 pinmux_process_node(struct pinmux_softc *sc, phandle_t node)
640 {
641 struct pincfg cfg;
642 char *pins, *pname;
643 int i, len, lpins, rv;
644
645 rv = pinmux_read_node(sc, node, &cfg, &pins, &lpins);
646 if (rv != 0)
647 return (rv);
648
649 len = 0;
650 pname = pins;
651 do {
652 i = strlen(pname) + 1;
653 rv = pinmux_config_node(sc, pname, &cfg);
654 if (rv != 0)
655 device_printf(sc->dev, "Cannot configure pin: %s: %d\n",
656 pname, rv);
657 len += i;
658 pname += i;
659 } while (len < lpins);
660
661 if (pins != NULL)
662 OF_prop_free(pins);
663 if (cfg.function != NULL)
664 OF_prop_free(cfg.function);
665 return (rv);
666 }
667
668 static int pinmux_configure(device_t dev, phandle_t cfgxref)
669 {
670 struct pinmux_softc *sc;
671 phandle_t node, cfgnode;
672
673 sc = device_get_softc(dev);
674 cfgnode = OF_node_from_xref(cfgxref);
675
676
677 for (node = OF_child(cfgnode); node != 0; node = OF_peer(node)) {
678 if (!ofw_bus_node_status_okay(node))
679 continue;
680 pinmux_process_node(sc, node);
681 }
682 return (0);
683 }
684
685 static int
686 pinmux_probe(device_t dev)
687 {
688
689 if (!ofw_bus_status_okay(dev))
690 return (ENXIO);
691
692 if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
693 return (ENXIO);
694
695 device_set_desc(dev, "Tegra pin configuration");
696 return (BUS_PROBE_DEFAULT);
697 }
698
699 static int
700 pinmux_detach(device_t dev)
701 {
702
703 /* This device is always present. */
704 return (EBUSY);
705 }
706
707 static int
708 pinmux_attach(device_t dev)
709 {
710 struct pinmux_softc * sc;
711 int rid;
712
713 sc = device_get_softc(dev);
714 sc->dev = dev;
715
716 rid = 0;
717 sc->pad_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
718 RF_ACTIVE);
719 if (sc->pad_mem_res == NULL) {
720 device_printf(dev, "Cannot allocate memory resources\n");
721 return (ENXIO);
722 }
723
724 rid = 1;
725 sc->mux_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
726 RF_ACTIVE);
727 if (sc->mux_mem_res == NULL) {
728 device_printf(dev, "Cannot allocate memory resources\n");
729 return (ENXIO);
730 }
731
732
733 /* Register as a pinctrl device and process default configuration */
734 fdt_pinctrl_register(dev, NULL);
735 fdt_pinctrl_configure_by_name(dev, "boot");
736
737 return (0);
738 }
739
740
741 static device_method_t tegra210_pinmux_methods[] = {
742 /* Device interface */
743 DEVMETHOD(device_probe, pinmux_probe),
744 DEVMETHOD(device_attach, pinmux_attach),
745 DEVMETHOD(device_detach, pinmux_detach),
746
747 /* fdt_pinctrl interface */
748 DEVMETHOD(fdt_pinctrl_configure,pinmux_configure),
749
750 DEVMETHOD_END
751 };
752
753 static DEFINE_CLASS_0(pinmux, tegra210_pinmux_driver, tegra210_pinmux_methods,
754 sizeof(struct pinmux_softc));
755 EARLY_DRIVER_MODULE(tegra210_pinmux, simplebus, tegra210_pinmux_driver,
756 NULL, NULL, 71);
Cache object: 56afa9e25852b95fde985562cfaf865c
|