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