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