blob: f60d5aad3a443e286939bd369d29348714e4c107 [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 Glass0f2af882020-05-10 11:40:05 -06007#include <log.h>
Simon Glass84a97c52011-11-28 15:04:38 +00008#include <asm/arch/clock.h>
Simon Glass43b1a7c2012-01-11 12:42:23 +00009#include <asm/arch/funcmux.h>
Simon Glass84a97c52011-11-28 15:04:38 +000010#include <asm/arch/pinmux.h>
11
Simon Glass11ecb382012-10-17 13:24:46 +000012/*
13 * The PINMUX macro is used to set up pinmux tables.
14 */
15#define PINMUX(grp, mux, pupd, tri) \
Stephen Warrenf27f4e82014-03-21 12:28:58 -060016 {PMUX_PINGRP_##grp, PMUX_FUNC_##mux, PMUX_PULL_##pupd, PMUX_TRI_##tri}
Simon Glass11ecb382012-10-17 13:24:46 +000017
Stephen Warrenf4df6052014-03-21 12:28:56 -060018static const struct pmux_pingrp_config disp1_default[] = {
Simon Glass11ecb382012-10-17 13:24:46 +000019 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
Simon Glass84a97c52011-11-28 15:04:38 +000035int funcmux_select(enum periph_id id, int config)
36{
Simon Glass43b1a7c2012-01-11 12:42:23 +000037 int bad_config = config != FUNCMUX_DEFAULT;
Simon Glass3ba99a32012-01-11 12:42:22 +000038
Simon Glass84a97c52011-11-28 15:04:38 +000039 switch (id) {
40 case PERIPH_ID_UART1:
Stephen Warren59f90102012-05-14 13:13:45 +000041 switch (config) {
42 case FUNCMUX_UART1_IRRX_IRTX:
Stephen Warrenf27f4e82014-03-21 12:28:58 -060043 pinmux_set_func(PMUX_PINGRP_IRRX, PMUX_FUNC_UARTA);
44 pinmux_set_func(PMUX_PINGRP_IRTX, PMUX_FUNC_UARTA);
45 pinmux_tristate_disable(PMUX_PINGRP_IRRX);
46 pinmux_tristate_disable(PMUX_PINGRP_IRTX);
Stephen Warren59f90102012-05-14 13:13:45 +000047 break;
48 case FUNCMUX_UART1_UAA_UAB:
Stephen Warrenf27f4e82014-03-21 12:28:58 -060049 pinmux_set_func(PMUX_PINGRP_UAA, PMUX_FUNC_UARTA);
50 pinmux_set_func(PMUX_PINGRP_UAB, PMUX_FUNC_UARTA);
51 pinmux_tristate_disable(PMUX_PINGRP_UAA);
52 pinmux_tristate_disable(PMUX_PINGRP_UAB);
Stephen Warren59f90102012-05-14 13:13:45 +000053 bad_config = 0;
54 break;
Stephen Warrene4c01a82012-05-16 05:59:59 +000055 case FUNCMUX_UART1_GPU:
Stephen Warrenf27f4e82014-03-21 12:28:58 -060056 pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_UARTA);
57 pinmux_tristate_disable(PMUX_PINGRP_GPU);
Stephen Warrene4c01a82012-05-16 05:59:59 +000058 bad_config = 0;
59 break;
Lucas Stach4de6eec2012-05-16 08:21:02 +000060 case FUNCMUX_UART1_SDIO1:
Stephen Warrenf27f4e82014-03-21 12:28:58 -060061 pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_UARTA);
62 pinmux_tristate_disable(PMUX_PINGRP_SDIO1);
Lucas Stach4de6eec2012-05-16 08:21:02 +000063 bad_config = 0;
64 break;
Artur Kowalski420e9d82025-03-30 21:26:39 +020065 case FUNCMUX_UART1_SDB_SDD:
66 pinmux_set_func(PMUX_PINGRP_SDB, PMUX_FUNC_UARTA);
67 pinmux_set_func(PMUX_PINGRP_SDD, PMUX_FUNC_UARTA);
68 pinmux_tristate_disable(PMUX_PINGRP_SDB);
69 pinmux_tristate_disable(PMUX_PINGRP_SDD);
70 bad_config = 0;
71 break;
Stephen Warren59f90102012-05-14 13:13:45 +000072 }
Artur Kowalski420e9d82025-03-30 21:26:39 +020073 if (!bad_config && config != FUNCMUX_UART1_SDB_SDD) {
Simon Glass3ba99a32012-01-11 12:42:22 +000074 /*
75 * Tegra appears to boot with function UARTA pre-
76 * selected on mux group SDB. If two mux groups are
77 * both set to the same function, it's unclear which
78 * group's pins drive the RX signals into the HW.
79 * For UARTA, SDB certainly overrides group IRTX in
80 * practice. To solve this, configure some alternative
81 * function on SDB to avoid the conflict. Also, tri-
82 * state the group to avoid driving any signal onto it
83 * until we know what's connected.
84 */
Stephen Warrenf27f4e82014-03-21 12:28:58 -060085 pinmux_tristate_enable(PMUX_PINGRP_SDB);
86 pinmux_set_func(PMUX_PINGRP_SDB, PMUX_FUNC_SDIO3);
Simon Glass3ba99a32012-01-11 12:42:22 +000087 }
Simon Glass84a97c52011-11-28 15:04:38 +000088 break;
89
90 case PERIPH_ID_UART2:
Stephen Warren811af732013-01-22 06:20:08 +000091 if (config == FUNCMUX_UART2_UAD) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -060092 pinmux_set_func(PMUX_PINGRP_UAD, PMUX_FUNC_UARTB);
93 pinmux_tristate_disable(PMUX_PINGRP_UAD);
Simon Glass3ba99a32012-01-11 12:42:22 +000094 }
Simon Glass84a97c52011-11-28 15:04:38 +000095 break;
96
97 case PERIPH_ID_UART4:
Simon Glass43b1a7c2012-01-11 12:42:23 +000098 if (config == FUNCMUX_UART4_GMC) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -060099 pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_UARTD);
100 pinmux_tristate_disable(PMUX_PINGRP_GMC);
Simon Glass3ba99a32012-01-11 12:42:22 +0000101 }
Simon Glass84a97c52011-11-28 15:04:38 +0000102 break;
103
Simon Glassd8c03b82012-01-11 12:42:24 +0000104 case PERIPH_ID_DVC_I2C:
105 /* there is only one selection, pinmux_config is ignored */
106 if (config == FUNCMUX_DVC_I2CP) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600107 pinmux_set_func(PMUX_PINGRP_I2CP, PMUX_FUNC_I2C);
108 pinmux_tristate_disable(PMUX_PINGRP_I2CP);
Simon Glassd8c03b82012-01-11 12:42:24 +0000109 }
110 break;
111
112 case PERIPH_ID_I2C1:
113 /* support pinmux_config of 0 for now, */
114 if (config == FUNCMUX_I2C1_RM) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600115 pinmux_set_func(PMUX_PINGRP_RM, PMUX_FUNC_I2C);
116 pinmux_tristate_disable(PMUX_PINGRP_RM);
Simon Glassd8c03b82012-01-11 12:42:24 +0000117 }
118 break;
119 case PERIPH_ID_I2C2: /* I2C2 */
120 switch (config) {
121 case FUNCMUX_I2C2_DDC: /* DDC pin group, select I2C2 */
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600122 pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_I2C2);
Simon Glassd8c03b82012-01-11 12:42:24 +0000123 /* PTA to HDMI */
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600124 pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_HDMI);
125 pinmux_tristate_disable(PMUX_PINGRP_DDC);
Simon Glassd8c03b82012-01-11 12:42:24 +0000126 break;
127 case FUNCMUX_I2C2_PTA: /* PTA pin group, select I2C2 */
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600128 pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_I2C2);
Simon Glassd8c03b82012-01-11 12:42:24 +0000129 /* set DDC_SEL to RSVDx (RSVD2 works for now) */
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600130 pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_RSVD2);
131 pinmux_tristate_disable(PMUX_PINGRP_PTA);
Simon Glassd8c03b82012-01-11 12:42:24 +0000132 bad_config = 0;
133 break;
134 }
135 break;
136 case PERIPH_ID_I2C3: /* I2C3 */
137 /* support pinmux_config of 0 for now */
138 if (config == FUNCMUX_I2C3_DTF) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600139 pinmux_set_func(PMUX_PINGRP_DTF, PMUX_FUNC_I2C3);
140 pinmux_tristate_disable(PMUX_PINGRP_DTF);
Simon Glassd8c03b82012-01-11 12:42:24 +0000141 }
142 break;
143
Stephen Warrenb6d19012012-05-16 13:54:06 +0000144 case PERIPH_ID_SDMMC1:
145 if (config == FUNCMUX_SDMMC1_SDIO1_4BIT) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600146 pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_SDIO1);
147 pinmux_tristate_disable(PMUX_PINGRP_SDIO1);
Stephen Warrenb6d19012012-05-16 13:54:06 +0000148 }
149 break;
150
Simon Glassfb1ea632012-01-11 12:42:25 +0000151 case PERIPH_ID_SDMMC2:
152 if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600153 pinmux_set_func(PMUX_PINGRP_DTA, PMUX_FUNC_SDIO2);
154 pinmux_set_func(PMUX_PINGRP_DTD, PMUX_FUNC_SDIO2);
Simon Glassfb1ea632012-01-11 12:42:25 +0000155
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600156 pinmux_tristate_disable(PMUX_PINGRP_DTA);
157 pinmux_tristate_disable(PMUX_PINGRP_DTD);
Simon Glassfb1ea632012-01-11 12:42:25 +0000158 }
159 break;
160
161 case PERIPH_ID_SDMMC3:
162 switch (config) {
163 case FUNCMUX_SDMMC3_SDB_SLXA_8BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600164 pinmux_set_func(PMUX_PINGRP_SLXA, PMUX_FUNC_SDIO3);
165 pinmux_set_func(PMUX_PINGRP_SLXC, PMUX_FUNC_SDIO3);
166 pinmux_set_func(PMUX_PINGRP_SLXD, PMUX_FUNC_SDIO3);
167 pinmux_set_func(PMUX_PINGRP_SLXK, PMUX_FUNC_SDIO3);
Simon Glassfb1ea632012-01-11 12:42:25 +0000168
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600169 pinmux_tristate_disable(PMUX_PINGRP_SLXA);
170 pinmux_tristate_disable(PMUX_PINGRP_SLXC);
171 pinmux_tristate_disable(PMUX_PINGRP_SLXD);
172 pinmux_tristate_disable(PMUX_PINGRP_SLXK);
Simon Glassfb1ea632012-01-11 12:42:25 +0000173 /* fall through */
174
175 case FUNCMUX_SDMMC3_SDB_4BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600176 pinmux_set_func(PMUX_PINGRP_SDB, PMUX_FUNC_SDIO3);
177 pinmux_set_func(PMUX_PINGRP_SDC, PMUX_FUNC_SDIO3);
178 pinmux_set_func(PMUX_PINGRP_SDD, PMUX_FUNC_SDIO3);
Simon Glassfb1ea632012-01-11 12:42:25 +0000179
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600180 pinmux_tristate_disable(PMUX_PINGRP_SDB);
181 pinmux_tristate_disable(PMUX_PINGRP_SDC);
182 pinmux_tristate_disable(PMUX_PINGRP_SDD);
Simon Glassfb1ea632012-01-11 12:42:25 +0000183 bad_config = 0;
184 break;
185 }
186 break;
187
188 case PERIPH_ID_SDMMC4:
189 switch (config) {
190 case FUNCMUX_SDMMC4_ATC_ATD_8BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600191 pinmux_set_func(PMUX_PINGRP_ATC, PMUX_FUNC_SDIO4);
192 pinmux_set_func(PMUX_PINGRP_ATD, PMUX_FUNC_SDIO4);
Simon Glassfb1ea632012-01-11 12:42:25 +0000193
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600194 pinmux_tristate_disable(PMUX_PINGRP_ATC);
195 pinmux_tristate_disable(PMUX_PINGRP_ATD);
Simon Glassfb1ea632012-01-11 12:42:25 +0000196 break;
197
198 case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600199 pinmux_set_func(PMUX_PINGRP_GME, PMUX_FUNC_SDIO4);
200 pinmux_tristate_disable(PMUX_PINGRP_GME);
Simon Glassfb1ea632012-01-11 12:42:25 +0000201 /* fall through */
202
203 case FUNCMUX_SDMMC4_ATB_GMA_4_BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600204 pinmux_set_func(PMUX_PINGRP_ATB, PMUX_FUNC_SDIO4);
205 pinmux_set_func(PMUX_PINGRP_GMA, PMUX_FUNC_SDIO4);
Simon Glassfb1ea632012-01-11 12:42:25 +0000206
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600207 pinmux_tristate_disable(PMUX_PINGRP_ATB);
208 pinmux_tristate_disable(PMUX_PINGRP_GMA);
Simon Glassfb1ea632012-01-11 12:42:25 +0000209 bad_config = 0;
210 break;
211 }
212 break;
213
Simon Glass5dc04612012-04-17 09:01:32 +0000214 case PERIPH_ID_KBC:
215 if (config == FUNCMUX_DEFAULT) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600216 enum pmux_pingrp grp[] = {PMUX_PINGRP_KBCA,
217 PMUX_PINGRP_KBCB, PMUX_PINGRP_KBCC,
218 PMUX_PINGRP_KBCD, PMUX_PINGRP_KBCE,
219 PMUX_PINGRP_KBCF};
Simon Glass5dc04612012-04-17 09:01:32 +0000220 int i;
221
222 for (i = 0; i < ARRAY_SIZE(grp); i++) {
223 pinmux_tristate_disable(grp[i]);
224 pinmux_set_func(grp[i], PMUX_FUNC_KBC);
225 pinmux_set_pullupdown(grp[i], PMUX_PULL_UP);
226 }
Lucas Stach53c79112012-05-31 01:51:01 +0000227 }
228 break;
229
230 case PERIPH_ID_USB2:
231 if (config == FUNCMUX_USB2_ULPI) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600232 pinmux_set_func(PMUX_PINGRP_UAA, PMUX_FUNC_ULPI);
233 pinmux_set_func(PMUX_PINGRP_UAB, PMUX_FUNC_ULPI);
234 pinmux_set_func(PMUX_PINGRP_UDA, PMUX_FUNC_ULPI);
Simon Glass5dc04612012-04-17 09:01:32 +0000235
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600236 pinmux_tristate_disable(PMUX_PINGRP_UAA);
237 pinmux_tristate_disable(PMUX_PINGRP_UAB);
238 pinmux_tristate_disable(PMUX_PINGRP_UDA);
Simon Glass5dc04612012-04-17 09:01:32 +0000239 }
Lucas Stach53c79112012-05-31 01:51:01 +0000240 break;
Simon Glass5dc04612012-04-17 09:01:32 +0000241
Stephen Warren1bdbc9f2012-06-12 08:33:39 +0000242 case PERIPH_ID_SPI1:
243 if (config == FUNCMUX_SPI1_GMC_GMD) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600244 pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_SFLASH);
245 pinmux_set_func(PMUX_PINGRP_GMD, PMUX_FUNC_SFLASH);
Stephen Warren1bdbc9f2012-06-12 08:33:39 +0000246
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600247 pinmux_tristate_disable(PMUX_PINGRP_GMC);
248 pinmux_tristate_disable(PMUX_PINGRP_GMD);
Stephen Warren1bdbc9f2012-06-12 08:33:39 +0000249 }
250 break;
251
Simon Glassfdf54732012-07-29 20:53:26 +0000252 case PERIPH_ID_NDFLASH:
Lucas Stach93748d32012-09-27 13:04:27 +0000253 switch (config) {
254 case FUNCMUX_NDFLASH_ATC:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600255 pinmux_set_func(PMUX_PINGRP_ATC, PMUX_FUNC_NAND);
256 pinmux_tristate_disable(PMUX_PINGRP_ATC);
Lucas Stach93748d32012-09-27 13:04:27 +0000257 break;
258 case FUNCMUX_NDFLASH_KBC_8_BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600259 pinmux_set_func(PMUX_PINGRP_KBCA, PMUX_FUNC_NAND);
Lucas Stachc9109a12015-03-27 01:31:44 +0100260 pinmux_set_func(PMUX_PINGRP_KBCB, PMUX_FUNC_NAND);
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600261 pinmux_set_func(PMUX_PINGRP_KBCC, PMUX_FUNC_NAND);
262 pinmux_set_func(PMUX_PINGRP_KBCD, PMUX_FUNC_NAND);
263 pinmux_set_func(PMUX_PINGRP_KBCE, PMUX_FUNC_NAND);
264 pinmux_set_func(PMUX_PINGRP_KBCF, PMUX_FUNC_NAND);
Lucas Stach93748d32012-09-27 13:04:27 +0000265
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600266 pinmux_tristate_disable(PMUX_PINGRP_KBCA);
Lucas Stachc9109a12015-03-27 01:31:44 +0100267 pinmux_tristate_disable(PMUX_PINGRP_KBCB);
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600268 pinmux_tristate_disable(PMUX_PINGRP_KBCC);
269 pinmux_tristate_disable(PMUX_PINGRP_KBCD);
270 pinmux_tristate_disable(PMUX_PINGRP_KBCE);
271 pinmux_tristate_disable(PMUX_PINGRP_KBCF);
Lucas Stach93748d32012-09-27 13:04:27 +0000272
273 bad_config = 0;
274 break;
Simon Glassfdf54732012-07-29 20:53:26 +0000275 }
276 break;
Simon Glass11ecb382012-10-17 13:24:46 +0000277 case PERIPH_ID_DISP1:
278 if (config == FUNCMUX_DEFAULT) {
279 int i;
280
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600281 for (i = PMUX_PINGRP_LD0; i <= PMUX_PINGRP_LD17; i++) {
Simon Glass11ecb382012-10-17 13:24:46 +0000282 pinmux_set_func(i, PMUX_FUNC_DISPA);
283 pinmux_tristate_disable(i);
284 pinmux_set_pullupdown(i, PMUX_PULL_NORMAL);
285 }
Stephen Warrenf4df6052014-03-21 12:28:56 -0600286 pinmux_config_pingrp_table(disp1_default,
287 ARRAY_SIZE(disp1_default));
Simon Glass11ecb382012-10-17 13:24:46 +0000288 }
289 break;
Simon Glassfdf54732012-07-29 20:53:26 +0000290
Simon Glass84a97c52011-11-28 15:04:38 +0000291 default:
292 debug("%s: invalid periph_id %d", __func__, id);
293 return -1;
294 }
295
Simon Glass3ba99a32012-01-11 12:42:22 +0000296 if (bad_config) {
297 debug("%s: invalid config %d for periph_id %d", __func__,
298 config, id);
299 return -1;
300 }
301
Simon Glass84a97c52011-11-28 15:04:38 +0000302 return 0;
303}