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