blob: 90fe0cba8ea44cd752cd4719470ff62e79e0465f [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass84a97c52011-11-28 15:04:38 +00002/*
3 * Copyright (c) 2011 The Chromium OS Authors.
Simon Glass84a97c52011-11-28 15:04:38 +00004 */
5
Allen Martin55d98a12012-08-31 08:30:00 +00006/* Tegra20 high-level function multiplexing */
Simon Glass84a97c52011-11-28 15:04:38 +00007#include <common.h>
Simon Glass0f2af882020-05-10 11:40:05 -06008#include <log.h>
Simon Glass84a97c52011-11-28 15:04:38 +00009#include <asm/arch/clock.h>
Simon Glass43b1a7c2012-01-11 12:42:23 +000010#include <asm/arch/funcmux.h>
Simon Glass84a97c52011-11-28 15:04:38 +000011#include <asm/arch/pinmux.h>
12
Simon Glass11ecb382012-10-17 13:24:46 +000013/*
14 * The PINMUX macro is used to set up pinmux tables.
15 */
16#define PINMUX(grp, mux, pupd, tri) \
Stephen Warrenf27f4e82014-03-21 12:28:58 -060017 {PMUX_PINGRP_##grp, PMUX_FUNC_##mux, PMUX_PULL_##pupd, PMUX_TRI_##tri}
Simon Glass11ecb382012-10-17 13:24:46 +000018
Stephen Warrenf4df6052014-03-21 12:28:56 -060019static const struct pmux_pingrp_config disp1_default[] = {
Simon Glass11ecb382012-10-17 13:24:46 +000020 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
Simon Glass84a97c52011-11-28 15:04:38 +000037int funcmux_select(enum periph_id id, int config)
38{
Simon Glass43b1a7c2012-01-11 12:42:23 +000039 int bad_config = config != FUNCMUX_DEFAULT;
Simon Glass3ba99a32012-01-11 12:42:22 +000040
Simon Glass84a97c52011-11-28 15:04:38 +000041 switch (id) {
42 case PERIPH_ID_UART1:
Stephen Warren59f90102012-05-14 13:13:45 +000043 switch (config) {
44 case FUNCMUX_UART1_IRRX_IRTX:
Stephen Warrenf27f4e82014-03-21 12:28:58 -060045 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);
Stephen Warren59f90102012-05-14 13:13:45 +000049 break;
50 case FUNCMUX_UART1_UAA_UAB:
Stephen Warrenf27f4e82014-03-21 12:28:58 -060051 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);
Stephen Warren59f90102012-05-14 13:13:45 +000055 bad_config = 0;
56 break;
Stephen Warrene4c01a82012-05-16 05:59:59 +000057 case FUNCMUX_UART1_GPU:
Stephen Warrenf27f4e82014-03-21 12:28:58 -060058 pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_UARTA);
59 pinmux_tristate_disable(PMUX_PINGRP_GPU);
Stephen Warrene4c01a82012-05-16 05:59:59 +000060 bad_config = 0;
61 break;
Lucas Stach4de6eec2012-05-16 08:21:02 +000062 case FUNCMUX_UART1_SDIO1:
Stephen Warrenf27f4e82014-03-21 12:28:58 -060063 pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_UARTA);
64 pinmux_tristate_disable(PMUX_PINGRP_SDIO1);
Lucas Stach4de6eec2012-05-16 08:21:02 +000065 bad_config = 0;
66 break;
Stephen Warren59f90102012-05-14 13:13:45 +000067 }
68 if (!bad_config) {
Simon Glass3ba99a32012-01-11 12:42:22 +000069 /*
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 */
Stephen Warrenf27f4e82014-03-21 12:28:58 -060080 pinmux_tristate_enable(PMUX_PINGRP_SDB);
81 pinmux_set_func(PMUX_PINGRP_SDB, PMUX_FUNC_SDIO3);
Simon Glass3ba99a32012-01-11 12:42:22 +000082 }
Simon Glass84a97c52011-11-28 15:04:38 +000083 break;
84
85 case PERIPH_ID_UART2:
Stephen Warren811af732013-01-22 06:20:08 +000086 if (config == FUNCMUX_UART2_UAD) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -060087 pinmux_set_func(PMUX_PINGRP_UAD, PMUX_FUNC_UARTB);
88 pinmux_tristate_disable(PMUX_PINGRP_UAD);
Simon Glass3ba99a32012-01-11 12:42:22 +000089 }
Simon Glass84a97c52011-11-28 15:04:38 +000090 break;
91
92 case PERIPH_ID_UART4:
Simon Glass43b1a7c2012-01-11 12:42:23 +000093 if (config == FUNCMUX_UART4_GMC) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -060094 pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_UARTD);
95 pinmux_tristate_disable(PMUX_PINGRP_GMC);
Simon Glass3ba99a32012-01-11 12:42:22 +000096 }
Simon Glass84a97c52011-11-28 15:04:38 +000097 break;
98
Simon Glassd8c03b82012-01-11 12:42:24 +000099 case PERIPH_ID_DVC_I2C:
100 /* there is only one selection, pinmux_config is ignored */
101 if (config == FUNCMUX_DVC_I2CP) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600102 pinmux_set_func(PMUX_PINGRP_I2CP, PMUX_FUNC_I2C);
103 pinmux_tristate_disable(PMUX_PINGRP_I2CP);
Simon Glassd8c03b82012-01-11 12:42:24 +0000104 }
105 break;
106
107 case PERIPH_ID_I2C1:
108 /* support pinmux_config of 0 for now, */
109 if (config == FUNCMUX_I2C1_RM) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600110 pinmux_set_func(PMUX_PINGRP_RM, PMUX_FUNC_I2C);
111 pinmux_tristate_disable(PMUX_PINGRP_RM);
Simon Glassd8c03b82012-01-11 12:42:24 +0000112 }
113 break;
114 case PERIPH_ID_I2C2: /* I2C2 */
115 switch (config) {
116 case FUNCMUX_I2C2_DDC: /* DDC pin group, select I2C2 */
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600117 pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_I2C2);
Simon Glassd8c03b82012-01-11 12:42:24 +0000118 /* PTA to HDMI */
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600119 pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_HDMI);
120 pinmux_tristate_disable(PMUX_PINGRP_DDC);
Simon Glassd8c03b82012-01-11 12:42:24 +0000121 break;
122 case FUNCMUX_I2C2_PTA: /* PTA pin group, select I2C2 */
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600123 pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_I2C2);
Simon Glassd8c03b82012-01-11 12:42:24 +0000124 /* set DDC_SEL to RSVDx (RSVD2 works for now) */
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600125 pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_RSVD2);
126 pinmux_tristate_disable(PMUX_PINGRP_PTA);
Simon Glassd8c03b82012-01-11 12:42:24 +0000127 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) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600134 pinmux_set_func(PMUX_PINGRP_DTF, PMUX_FUNC_I2C3);
135 pinmux_tristate_disable(PMUX_PINGRP_DTF);
Simon Glassd8c03b82012-01-11 12:42:24 +0000136 }
137 break;
138
Stephen Warrenb6d19012012-05-16 13:54:06 +0000139 case PERIPH_ID_SDMMC1:
140 if (config == FUNCMUX_SDMMC1_SDIO1_4BIT) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600141 pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_SDIO1);
142 pinmux_tristate_disable(PMUX_PINGRP_SDIO1);
Stephen Warrenb6d19012012-05-16 13:54:06 +0000143 }
144 break;
145
Simon Glassfb1ea632012-01-11 12:42:25 +0000146 case PERIPH_ID_SDMMC2:
147 if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600148 pinmux_set_func(PMUX_PINGRP_DTA, PMUX_FUNC_SDIO2);
149 pinmux_set_func(PMUX_PINGRP_DTD, PMUX_FUNC_SDIO2);
Simon Glassfb1ea632012-01-11 12:42:25 +0000150
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600151 pinmux_tristate_disable(PMUX_PINGRP_DTA);
152 pinmux_tristate_disable(PMUX_PINGRP_DTD);
Simon Glassfb1ea632012-01-11 12:42:25 +0000153 }
154 break;
155
156 case PERIPH_ID_SDMMC3:
157 switch (config) {
158 case FUNCMUX_SDMMC3_SDB_SLXA_8BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600159 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);
Simon Glassfb1ea632012-01-11 12:42:25 +0000163
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600164 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);
Simon Glassfb1ea632012-01-11 12:42:25 +0000168 /* fall through */
169
170 case FUNCMUX_SDMMC3_SDB_4BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600171 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);
Simon Glassfb1ea632012-01-11 12:42:25 +0000174
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600175 pinmux_tristate_disable(PMUX_PINGRP_SDB);
176 pinmux_tristate_disable(PMUX_PINGRP_SDC);
177 pinmux_tristate_disable(PMUX_PINGRP_SDD);
Simon Glassfb1ea632012-01-11 12:42:25 +0000178 bad_config = 0;
179 break;
180 }
181 break;
182
183 case PERIPH_ID_SDMMC4:
184 switch (config) {
185 case FUNCMUX_SDMMC4_ATC_ATD_8BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600186 pinmux_set_func(PMUX_PINGRP_ATC, PMUX_FUNC_SDIO4);
187 pinmux_set_func(PMUX_PINGRP_ATD, PMUX_FUNC_SDIO4);
Simon Glassfb1ea632012-01-11 12:42:25 +0000188
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600189 pinmux_tristate_disable(PMUX_PINGRP_ATC);
190 pinmux_tristate_disable(PMUX_PINGRP_ATD);
Simon Glassfb1ea632012-01-11 12:42:25 +0000191 break;
192
193 case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600194 pinmux_set_func(PMUX_PINGRP_GME, PMUX_FUNC_SDIO4);
195 pinmux_tristate_disable(PMUX_PINGRP_GME);
Simon Glassfb1ea632012-01-11 12:42:25 +0000196 /* fall through */
197
198 case FUNCMUX_SDMMC4_ATB_GMA_4_BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600199 pinmux_set_func(PMUX_PINGRP_ATB, PMUX_FUNC_SDIO4);
200 pinmux_set_func(PMUX_PINGRP_GMA, PMUX_FUNC_SDIO4);
Simon Glassfb1ea632012-01-11 12:42:25 +0000201
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600202 pinmux_tristate_disable(PMUX_PINGRP_ATB);
203 pinmux_tristate_disable(PMUX_PINGRP_GMA);
Simon Glassfb1ea632012-01-11 12:42:25 +0000204 bad_config = 0;
205 break;
206 }
207 break;
208
Simon Glass5dc04612012-04-17 09:01:32 +0000209 case PERIPH_ID_KBC:
210 if (config == FUNCMUX_DEFAULT) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600211 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};
Simon Glass5dc04612012-04-17 09:01:32 +0000215 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 }
Lucas Stach53c79112012-05-31 01:51:01 +0000222 }
223 break;
224
225 case PERIPH_ID_USB2:
226 if (config == FUNCMUX_USB2_ULPI) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600227 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);
Simon Glass5dc04612012-04-17 09:01:32 +0000230
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600231 pinmux_tristate_disable(PMUX_PINGRP_UAA);
232 pinmux_tristate_disable(PMUX_PINGRP_UAB);
233 pinmux_tristate_disable(PMUX_PINGRP_UDA);
Simon Glass5dc04612012-04-17 09:01:32 +0000234 }
Lucas Stach53c79112012-05-31 01:51:01 +0000235 break;
Simon Glass5dc04612012-04-17 09:01:32 +0000236
Stephen Warren1bdbc9f2012-06-12 08:33:39 +0000237 case PERIPH_ID_SPI1:
238 if (config == FUNCMUX_SPI1_GMC_GMD) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600239 pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_SFLASH);
240 pinmux_set_func(PMUX_PINGRP_GMD, PMUX_FUNC_SFLASH);
Stephen Warren1bdbc9f2012-06-12 08:33:39 +0000241
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600242 pinmux_tristate_disable(PMUX_PINGRP_GMC);
243 pinmux_tristate_disable(PMUX_PINGRP_GMD);
Stephen Warren1bdbc9f2012-06-12 08:33:39 +0000244 }
245 break;
246
Simon Glassfdf54732012-07-29 20:53:26 +0000247 case PERIPH_ID_NDFLASH:
Lucas Stach93748d32012-09-27 13:04:27 +0000248 switch (config) {
249 case FUNCMUX_NDFLASH_ATC:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600250 pinmux_set_func(PMUX_PINGRP_ATC, PMUX_FUNC_NAND);
251 pinmux_tristate_disable(PMUX_PINGRP_ATC);
Lucas Stach93748d32012-09-27 13:04:27 +0000252 break;
253 case FUNCMUX_NDFLASH_KBC_8_BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600254 pinmux_set_func(PMUX_PINGRP_KBCA, PMUX_FUNC_NAND);
Lucas Stachc9109a12015-03-27 01:31:44 +0100255 pinmux_set_func(PMUX_PINGRP_KBCB, PMUX_FUNC_NAND);
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600256 pinmux_set_func(PMUX_PINGRP_KBCC, PMUX_FUNC_NAND);
257 pinmux_set_func(PMUX_PINGRP_KBCD, PMUX_FUNC_NAND);
258 pinmux_set_func(PMUX_PINGRP_KBCE, PMUX_FUNC_NAND);
259 pinmux_set_func(PMUX_PINGRP_KBCF, PMUX_FUNC_NAND);
Lucas Stach93748d32012-09-27 13:04:27 +0000260
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600261 pinmux_tristate_disable(PMUX_PINGRP_KBCA);
Lucas Stachc9109a12015-03-27 01:31:44 +0100262 pinmux_tristate_disable(PMUX_PINGRP_KBCB);
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600263 pinmux_tristate_disable(PMUX_PINGRP_KBCC);
264 pinmux_tristate_disable(PMUX_PINGRP_KBCD);
265 pinmux_tristate_disable(PMUX_PINGRP_KBCE);
266 pinmux_tristate_disable(PMUX_PINGRP_KBCF);
Lucas Stach93748d32012-09-27 13:04:27 +0000267
268 bad_config = 0;
269 break;
Simon Glassfdf54732012-07-29 20:53:26 +0000270 }
271 break;
Simon Glass11ecb382012-10-17 13:24:46 +0000272 case PERIPH_ID_DISP1:
273 if (config == FUNCMUX_DEFAULT) {
274 int i;
275
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600276 for (i = PMUX_PINGRP_LD0; i <= PMUX_PINGRP_LD17; i++) {
Simon Glass11ecb382012-10-17 13:24:46 +0000277 pinmux_set_func(i, PMUX_FUNC_DISPA);
278 pinmux_tristate_disable(i);
279 pinmux_set_pullupdown(i, PMUX_PULL_NORMAL);
280 }
Stephen Warrenf4df6052014-03-21 12:28:56 -0600281 pinmux_config_pingrp_table(disp1_default,
282 ARRAY_SIZE(disp1_default));
Simon Glass11ecb382012-10-17 13:24:46 +0000283 }
284 break;
Simon Glassfdf54732012-07-29 20:53:26 +0000285
Simon Glass84a97c52011-11-28 15:04:38 +0000286 default:
287 debug("%s: invalid periph_id %d", __func__, id);
288 return -1;
289 }
290
Simon Glass3ba99a32012-01-11 12:42:22 +0000291 if (bad_config) {
292 debug("%s: invalid config %d for periph_id %d", __func__,
293 config, id);
294 return -1;
295 }
296
Simon Glass84a97c52011-11-28 15:04:38 +0000297 return 0;
298}