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