1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (c) 2011 The Chromium OS Authors.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun /* Tegra20 high-level function multiplexing */
8*4882a593Smuzhiyun #include <common.h>
9*4882a593Smuzhiyun #include <asm/arch/clock.h>
10*4882a593Smuzhiyun #include <asm/arch/funcmux.h>
11*4882a593Smuzhiyun #include <asm/arch/pinmux.h>
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun /*
14*4882a593Smuzhiyun * The PINMUX macro is used to set up pinmux tables.
15*4882a593Smuzhiyun */
16*4882a593Smuzhiyun #define PINMUX(grp, mux, pupd, tri) \
17*4882a593Smuzhiyun {PMUX_PINGRP_##grp, PMUX_FUNC_##mux, PMUX_PULL_##pupd, PMUX_TRI_##tri}
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun static const struct pmux_pingrp_config disp1_default[] = {
20*4882a593Smuzhiyun PINMUX(LDI, DISPA, NORMAL, NORMAL),
21*4882a593Smuzhiyun PINMUX(LHP0, DISPA, NORMAL, NORMAL),
22*4882a593Smuzhiyun PINMUX(LHP1, DISPA, NORMAL, NORMAL),
23*4882a593Smuzhiyun PINMUX(LHP2, DISPA, NORMAL, NORMAL),
24*4882a593Smuzhiyun PINMUX(LHS, DISPA, NORMAL, NORMAL),
25*4882a593Smuzhiyun PINMUX(LM0, RSVD4, NORMAL, NORMAL),
26*4882a593Smuzhiyun PINMUX(LPP, DISPA, NORMAL, NORMAL),
27*4882a593Smuzhiyun PINMUX(LPW0, DISPA, NORMAL, NORMAL),
28*4882a593Smuzhiyun PINMUX(LPW2, DISPA, NORMAL, NORMAL),
29*4882a593Smuzhiyun PINMUX(LSC0, DISPA, NORMAL, NORMAL),
30*4882a593Smuzhiyun PINMUX(LSPI, DISPA, NORMAL, NORMAL),
31*4882a593Smuzhiyun PINMUX(LVP1, DISPA, NORMAL, NORMAL),
32*4882a593Smuzhiyun PINMUX(LVS, DISPA, NORMAL, NORMAL),
33*4882a593Smuzhiyun PINMUX(SLXD, SPDIF, NORMAL, NORMAL),
34*4882a593Smuzhiyun };
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun
funcmux_select(enum periph_id id,int config)37*4882a593Smuzhiyun int funcmux_select(enum periph_id id, int config)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun int bad_config = config != FUNCMUX_DEFAULT;
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun switch (id) {
42*4882a593Smuzhiyun case PERIPH_ID_UART1:
43*4882a593Smuzhiyun switch (config) {
44*4882a593Smuzhiyun case FUNCMUX_UART1_IRRX_IRTX:
45*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_IRRX, PMUX_FUNC_UARTA);
46*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_IRTX, PMUX_FUNC_UARTA);
47*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_IRRX);
48*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_IRTX);
49*4882a593Smuzhiyun break;
50*4882a593Smuzhiyun case FUNCMUX_UART1_UAA_UAB:
51*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_UAA, PMUX_FUNC_UARTA);
52*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_UAB, PMUX_FUNC_UARTA);
53*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_UAA);
54*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_UAB);
55*4882a593Smuzhiyun bad_config = 0;
56*4882a593Smuzhiyun break;
57*4882a593Smuzhiyun case FUNCMUX_UART1_GPU:
58*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_UARTA);
59*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_GPU);
60*4882a593Smuzhiyun bad_config = 0;
61*4882a593Smuzhiyun break;
62*4882a593Smuzhiyun case FUNCMUX_UART1_SDIO1:
63*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_UARTA);
64*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_SDIO1);
65*4882a593Smuzhiyun bad_config = 0;
66*4882a593Smuzhiyun break;
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun if (!bad_config) {
69*4882a593Smuzhiyun /*
70*4882a593Smuzhiyun * Tegra appears to boot with function UARTA pre-
71*4882a593Smuzhiyun * selected on mux group SDB. If two mux groups are
72*4882a593Smuzhiyun * both set to the same function, it's unclear which
73*4882a593Smuzhiyun * group's pins drive the RX signals into the HW.
74*4882a593Smuzhiyun * For UARTA, SDB certainly overrides group IRTX in
75*4882a593Smuzhiyun * practice. To solve this, configure some alternative
76*4882a593Smuzhiyun * function on SDB to avoid the conflict. Also, tri-
77*4882a593Smuzhiyun * state the group to avoid driving any signal onto it
78*4882a593Smuzhiyun * until we know what's connected.
79*4882a593Smuzhiyun */
80*4882a593Smuzhiyun pinmux_tristate_enable(PMUX_PINGRP_SDB);
81*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_SDB, PMUX_FUNC_SDIO3);
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun break;
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun case PERIPH_ID_UART2:
86*4882a593Smuzhiyun if (config == FUNCMUX_UART2_UAD) {
87*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_UAD, PMUX_FUNC_UARTB);
88*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_UAD);
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun break;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun case PERIPH_ID_UART4:
93*4882a593Smuzhiyun if (config == FUNCMUX_UART4_GMC) {
94*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_UARTD);
95*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_GMC);
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun break;
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun case PERIPH_ID_DVC_I2C:
100*4882a593Smuzhiyun /* there is only one selection, pinmux_config is ignored */
101*4882a593Smuzhiyun if (config == FUNCMUX_DVC_I2CP) {
102*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_I2CP, PMUX_FUNC_I2C);
103*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_I2CP);
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun break;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun case PERIPH_ID_I2C1:
108*4882a593Smuzhiyun /* support pinmux_config of 0 for now, */
109*4882a593Smuzhiyun if (config == FUNCMUX_I2C1_RM) {
110*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_RM, PMUX_FUNC_I2C);
111*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_RM);
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun break;
114*4882a593Smuzhiyun case PERIPH_ID_I2C2: /* I2C2 */
115*4882a593Smuzhiyun switch (config) {
116*4882a593Smuzhiyun case FUNCMUX_I2C2_DDC: /* DDC pin group, select I2C2 */
117*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_I2C2);
118*4882a593Smuzhiyun /* PTA to HDMI */
119*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_HDMI);
120*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_DDC);
121*4882a593Smuzhiyun break;
122*4882a593Smuzhiyun case FUNCMUX_I2C2_PTA: /* PTA pin group, select I2C2 */
123*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_I2C2);
124*4882a593Smuzhiyun /* set DDC_SEL to RSVDx (RSVD2 works for now) */
125*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_RSVD2);
126*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_PTA);
127*4882a593Smuzhiyun bad_config = 0;
128*4882a593Smuzhiyun break;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun break;
131*4882a593Smuzhiyun case PERIPH_ID_I2C3: /* I2C3 */
132*4882a593Smuzhiyun /* support pinmux_config of 0 for now */
133*4882a593Smuzhiyun if (config == FUNCMUX_I2C3_DTF) {
134*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_DTF, PMUX_FUNC_I2C3);
135*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_DTF);
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun break;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun case PERIPH_ID_SDMMC1:
140*4882a593Smuzhiyun if (config == FUNCMUX_SDMMC1_SDIO1_4BIT) {
141*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_SDIO1);
142*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_SDIO1);
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun break;
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun case PERIPH_ID_SDMMC2:
147*4882a593Smuzhiyun if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) {
148*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_DTA, PMUX_FUNC_SDIO2);
149*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_DTD, PMUX_FUNC_SDIO2);
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_DTA);
152*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_DTD);
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun break;
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun case PERIPH_ID_SDMMC3:
157*4882a593Smuzhiyun switch (config) {
158*4882a593Smuzhiyun case FUNCMUX_SDMMC3_SDB_SLXA_8BIT:
159*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_SLXA, PMUX_FUNC_SDIO3);
160*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_SLXC, PMUX_FUNC_SDIO3);
161*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_SLXD, PMUX_FUNC_SDIO3);
162*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_SLXK, PMUX_FUNC_SDIO3);
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_SLXA);
165*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_SLXC);
166*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_SLXD);
167*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_SLXK);
168*4882a593Smuzhiyun /* fall through */
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun case FUNCMUX_SDMMC3_SDB_4BIT:
171*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_SDB, PMUX_FUNC_SDIO3);
172*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_SDC, PMUX_FUNC_SDIO3);
173*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_SDD, PMUX_FUNC_SDIO3);
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_SDB);
176*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_SDC);
177*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_SDD);
178*4882a593Smuzhiyun bad_config = 0;
179*4882a593Smuzhiyun break;
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun break;
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun case PERIPH_ID_SDMMC4:
184*4882a593Smuzhiyun switch (config) {
185*4882a593Smuzhiyun case FUNCMUX_SDMMC4_ATC_ATD_8BIT:
186*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_ATC, PMUX_FUNC_SDIO4);
187*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_ATD, PMUX_FUNC_SDIO4);
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_ATC);
190*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_ATD);
191*4882a593Smuzhiyun break;
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT:
194*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_GME, PMUX_FUNC_SDIO4);
195*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_GME);
196*4882a593Smuzhiyun /* fall through */
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun case FUNCMUX_SDMMC4_ATB_GMA_4_BIT:
199*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_ATB, PMUX_FUNC_SDIO4);
200*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_GMA, PMUX_FUNC_SDIO4);
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_ATB);
203*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_GMA);
204*4882a593Smuzhiyun bad_config = 0;
205*4882a593Smuzhiyun break;
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun break;
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun case PERIPH_ID_KBC:
210*4882a593Smuzhiyun if (config == FUNCMUX_DEFAULT) {
211*4882a593Smuzhiyun enum pmux_pingrp grp[] = {PMUX_PINGRP_KBCA,
212*4882a593Smuzhiyun PMUX_PINGRP_KBCB, PMUX_PINGRP_KBCC,
213*4882a593Smuzhiyun PMUX_PINGRP_KBCD, PMUX_PINGRP_KBCE,
214*4882a593Smuzhiyun PMUX_PINGRP_KBCF};
215*4882a593Smuzhiyun int i;
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(grp); i++) {
218*4882a593Smuzhiyun pinmux_tristate_disable(grp[i]);
219*4882a593Smuzhiyun pinmux_set_func(grp[i], PMUX_FUNC_KBC);
220*4882a593Smuzhiyun pinmux_set_pullupdown(grp[i], PMUX_PULL_UP);
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun break;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun case PERIPH_ID_USB2:
226*4882a593Smuzhiyun if (config == FUNCMUX_USB2_ULPI) {
227*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_UAA, PMUX_FUNC_ULPI);
228*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_UAB, PMUX_FUNC_ULPI);
229*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_UDA, PMUX_FUNC_ULPI);
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_UAA);
232*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_UAB);
233*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_UDA);
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun break;
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun case PERIPH_ID_SPI1:
238*4882a593Smuzhiyun if (config == FUNCMUX_SPI1_GMC_GMD) {
239*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_SFLASH);
240*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_GMD, PMUX_FUNC_SFLASH);
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_GMC);
243*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_GMD);
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun break;
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun case PERIPH_ID_NDFLASH:
248*4882a593Smuzhiyun switch (config) {
249*4882a593Smuzhiyun case FUNCMUX_NDFLASH_ATC:
250*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_ATC, PMUX_FUNC_NAND);
251*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_ATC);
252*4882a593Smuzhiyun break;
253*4882a593Smuzhiyun case FUNCMUX_NDFLASH_KBC_8_BIT:
254*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_KBCA, PMUX_FUNC_NAND);
255*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_KBCB, PMUX_FUNC_NAND);
256*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_KBCC, PMUX_FUNC_NAND);
257*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_KBCD, PMUX_FUNC_NAND);
258*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_KBCE, PMUX_FUNC_NAND);
259*4882a593Smuzhiyun pinmux_set_func(PMUX_PINGRP_KBCF, PMUX_FUNC_NAND);
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_KBCA);
262*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_KBCB);
263*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_KBCC);
264*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_KBCD);
265*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_KBCE);
266*4882a593Smuzhiyun pinmux_tristate_disable(PMUX_PINGRP_KBCF);
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun bad_config = 0;
269*4882a593Smuzhiyun break;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun break;
272*4882a593Smuzhiyun case PERIPH_ID_DISP1:
273*4882a593Smuzhiyun if (config == FUNCMUX_DEFAULT) {
274*4882a593Smuzhiyun int i;
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun for (i = PMUX_PINGRP_LD0; i <= PMUX_PINGRP_LD17; i++) {
277*4882a593Smuzhiyun pinmux_set_func(i, PMUX_FUNC_DISPA);
278*4882a593Smuzhiyun pinmux_tristate_disable(i);
279*4882a593Smuzhiyun pinmux_set_pullupdown(i, PMUX_PULL_NORMAL);
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun pinmux_config_pingrp_table(disp1_default,
282*4882a593Smuzhiyun ARRAY_SIZE(disp1_default));
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun break;
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun default:
287*4882a593Smuzhiyun debug("%s: invalid periph_id %d", __func__, id);
288*4882a593Smuzhiyun return -1;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun if (bad_config) {
292*4882a593Smuzhiyun debug("%s: invalid config %d for periph_id %d", __func__,
293*4882a593Smuzhiyun config, id);
294*4882a593Smuzhiyun return -1;
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun return 0;
298*4882a593Smuzhiyun }
299