blob: 951ae196161d5ee748e5a25f824cdbd5a23106f6 [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;
Stephen Warren59f90102012-05-14 13:13:45 +000065 }
66 if (!bad_config) {
Simon Glass3ba99a32012-01-11 12:42:22 +000067 /*
68 * Tegra appears to boot with function UARTA pre-
69 * selected on mux group SDB. If two mux groups are
70 * both set to the same function, it's unclear which
71 * group's pins drive the RX signals into the HW.
72 * For UARTA, SDB certainly overrides group IRTX in
73 * practice. To solve this, configure some alternative
74 * function on SDB to avoid the conflict. Also, tri-
75 * state the group to avoid driving any signal onto it
76 * until we know what's connected.
77 */
Stephen Warrenf27f4e82014-03-21 12:28:58 -060078 pinmux_tristate_enable(PMUX_PINGRP_SDB);
79 pinmux_set_func(PMUX_PINGRP_SDB, PMUX_FUNC_SDIO3);
Simon Glass3ba99a32012-01-11 12:42:22 +000080 }
Simon Glass84a97c52011-11-28 15:04:38 +000081 break;
82
83 case PERIPH_ID_UART2:
Stephen Warren811af732013-01-22 06:20:08 +000084 if (config == FUNCMUX_UART2_UAD) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -060085 pinmux_set_func(PMUX_PINGRP_UAD, PMUX_FUNC_UARTB);
86 pinmux_tristate_disable(PMUX_PINGRP_UAD);
Simon Glass3ba99a32012-01-11 12:42:22 +000087 }
Simon Glass84a97c52011-11-28 15:04:38 +000088 break;
89
90 case PERIPH_ID_UART4:
Simon Glass43b1a7c2012-01-11 12:42:23 +000091 if (config == FUNCMUX_UART4_GMC) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -060092 pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_UARTD);
93 pinmux_tristate_disable(PMUX_PINGRP_GMC);
Simon Glass3ba99a32012-01-11 12:42:22 +000094 }
Simon Glass84a97c52011-11-28 15:04:38 +000095 break;
96
Simon Glassd8c03b82012-01-11 12:42:24 +000097 case PERIPH_ID_DVC_I2C:
98 /* there is only one selection, pinmux_config is ignored */
99 if (config == FUNCMUX_DVC_I2CP) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600100 pinmux_set_func(PMUX_PINGRP_I2CP, PMUX_FUNC_I2C);
101 pinmux_tristate_disable(PMUX_PINGRP_I2CP);
Simon Glassd8c03b82012-01-11 12:42:24 +0000102 }
103 break;
104
105 case PERIPH_ID_I2C1:
106 /* support pinmux_config of 0 for now, */
107 if (config == FUNCMUX_I2C1_RM) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600108 pinmux_set_func(PMUX_PINGRP_RM, PMUX_FUNC_I2C);
109 pinmux_tristate_disable(PMUX_PINGRP_RM);
Simon Glassd8c03b82012-01-11 12:42:24 +0000110 }
111 break;
112 case PERIPH_ID_I2C2: /* I2C2 */
113 switch (config) {
114 case FUNCMUX_I2C2_DDC: /* DDC pin group, select I2C2 */
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600115 pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_I2C2);
Simon Glassd8c03b82012-01-11 12:42:24 +0000116 /* PTA to HDMI */
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600117 pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_HDMI);
118 pinmux_tristate_disable(PMUX_PINGRP_DDC);
Simon Glassd8c03b82012-01-11 12:42:24 +0000119 break;
120 case FUNCMUX_I2C2_PTA: /* PTA pin group, select I2C2 */
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600121 pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_I2C2);
Simon Glassd8c03b82012-01-11 12:42:24 +0000122 /* set DDC_SEL to RSVDx (RSVD2 works for now) */
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600123 pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_RSVD2);
124 pinmux_tristate_disable(PMUX_PINGRP_PTA);
Simon Glassd8c03b82012-01-11 12:42:24 +0000125 bad_config = 0;
126 break;
127 }
128 break;
129 case PERIPH_ID_I2C3: /* I2C3 */
130 /* support pinmux_config of 0 for now */
131 if (config == FUNCMUX_I2C3_DTF) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600132 pinmux_set_func(PMUX_PINGRP_DTF, PMUX_FUNC_I2C3);
133 pinmux_tristate_disable(PMUX_PINGRP_DTF);
Simon Glassd8c03b82012-01-11 12:42:24 +0000134 }
135 break;
136
Stephen Warrenb6d19012012-05-16 13:54:06 +0000137 case PERIPH_ID_SDMMC1:
138 if (config == FUNCMUX_SDMMC1_SDIO1_4BIT) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600139 pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_SDIO1);
140 pinmux_tristate_disable(PMUX_PINGRP_SDIO1);
Stephen Warrenb6d19012012-05-16 13:54:06 +0000141 }
142 break;
143
Simon Glassfb1ea632012-01-11 12:42:25 +0000144 case PERIPH_ID_SDMMC2:
145 if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600146 pinmux_set_func(PMUX_PINGRP_DTA, PMUX_FUNC_SDIO2);
147 pinmux_set_func(PMUX_PINGRP_DTD, PMUX_FUNC_SDIO2);
Simon Glassfb1ea632012-01-11 12:42:25 +0000148
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600149 pinmux_tristate_disable(PMUX_PINGRP_DTA);
150 pinmux_tristate_disable(PMUX_PINGRP_DTD);
Simon Glassfb1ea632012-01-11 12:42:25 +0000151 }
152 break;
153
154 case PERIPH_ID_SDMMC3:
155 switch (config) {
156 case FUNCMUX_SDMMC3_SDB_SLXA_8BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600157 pinmux_set_func(PMUX_PINGRP_SLXA, PMUX_FUNC_SDIO3);
158 pinmux_set_func(PMUX_PINGRP_SLXC, PMUX_FUNC_SDIO3);
159 pinmux_set_func(PMUX_PINGRP_SLXD, PMUX_FUNC_SDIO3);
160 pinmux_set_func(PMUX_PINGRP_SLXK, PMUX_FUNC_SDIO3);
Simon Glassfb1ea632012-01-11 12:42:25 +0000161
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600162 pinmux_tristate_disable(PMUX_PINGRP_SLXA);
163 pinmux_tristate_disable(PMUX_PINGRP_SLXC);
164 pinmux_tristate_disable(PMUX_PINGRP_SLXD);
165 pinmux_tristate_disable(PMUX_PINGRP_SLXK);
Simon Glassfb1ea632012-01-11 12:42:25 +0000166 /* fall through */
167
168 case FUNCMUX_SDMMC3_SDB_4BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600169 pinmux_set_func(PMUX_PINGRP_SDB, PMUX_FUNC_SDIO3);
170 pinmux_set_func(PMUX_PINGRP_SDC, PMUX_FUNC_SDIO3);
171 pinmux_set_func(PMUX_PINGRP_SDD, PMUX_FUNC_SDIO3);
Simon Glassfb1ea632012-01-11 12:42:25 +0000172
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600173 pinmux_tristate_disable(PMUX_PINGRP_SDB);
174 pinmux_tristate_disable(PMUX_PINGRP_SDC);
175 pinmux_tristate_disable(PMUX_PINGRP_SDD);
Simon Glassfb1ea632012-01-11 12:42:25 +0000176 bad_config = 0;
177 break;
178 }
179 break;
180
181 case PERIPH_ID_SDMMC4:
182 switch (config) {
183 case FUNCMUX_SDMMC4_ATC_ATD_8BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600184 pinmux_set_func(PMUX_PINGRP_ATC, PMUX_FUNC_SDIO4);
185 pinmux_set_func(PMUX_PINGRP_ATD, PMUX_FUNC_SDIO4);
Simon Glassfb1ea632012-01-11 12:42:25 +0000186
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600187 pinmux_tristate_disable(PMUX_PINGRP_ATC);
188 pinmux_tristate_disable(PMUX_PINGRP_ATD);
Simon Glassfb1ea632012-01-11 12:42:25 +0000189 break;
190
191 case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600192 pinmux_set_func(PMUX_PINGRP_GME, PMUX_FUNC_SDIO4);
193 pinmux_tristate_disable(PMUX_PINGRP_GME);
Simon Glassfb1ea632012-01-11 12:42:25 +0000194 /* fall through */
195
196 case FUNCMUX_SDMMC4_ATB_GMA_4_BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600197 pinmux_set_func(PMUX_PINGRP_ATB, PMUX_FUNC_SDIO4);
198 pinmux_set_func(PMUX_PINGRP_GMA, PMUX_FUNC_SDIO4);
Simon Glassfb1ea632012-01-11 12:42:25 +0000199
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600200 pinmux_tristate_disable(PMUX_PINGRP_ATB);
201 pinmux_tristate_disable(PMUX_PINGRP_GMA);
Simon Glassfb1ea632012-01-11 12:42:25 +0000202 bad_config = 0;
203 break;
204 }
205 break;
206
Simon Glass5dc04612012-04-17 09:01:32 +0000207 case PERIPH_ID_KBC:
208 if (config == FUNCMUX_DEFAULT) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600209 enum pmux_pingrp grp[] = {PMUX_PINGRP_KBCA,
210 PMUX_PINGRP_KBCB, PMUX_PINGRP_KBCC,
211 PMUX_PINGRP_KBCD, PMUX_PINGRP_KBCE,
212 PMUX_PINGRP_KBCF};
Simon Glass5dc04612012-04-17 09:01:32 +0000213 int i;
214
215 for (i = 0; i < ARRAY_SIZE(grp); i++) {
216 pinmux_tristate_disable(grp[i]);
217 pinmux_set_func(grp[i], PMUX_FUNC_KBC);
218 pinmux_set_pullupdown(grp[i], PMUX_PULL_UP);
219 }
Lucas Stach53c79112012-05-31 01:51:01 +0000220 }
221 break;
222
223 case PERIPH_ID_USB2:
224 if (config == FUNCMUX_USB2_ULPI) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600225 pinmux_set_func(PMUX_PINGRP_UAA, PMUX_FUNC_ULPI);
226 pinmux_set_func(PMUX_PINGRP_UAB, PMUX_FUNC_ULPI);
227 pinmux_set_func(PMUX_PINGRP_UDA, PMUX_FUNC_ULPI);
Simon Glass5dc04612012-04-17 09:01:32 +0000228
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600229 pinmux_tristate_disable(PMUX_PINGRP_UAA);
230 pinmux_tristate_disable(PMUX_PINGRP_UAB);
231 pinmux_tristate_disable(PMUX_PINGRP_UDA);
Simon Glass5dc04612012-04-17 09:01:32 +0000232 }
Lucas Stach53c79112012-05-31 01:51:01 +0000233 break;
Simon Glass5dc04612012-04-17 09:01:32 +0000234
Stephen Warren1bdbc9f2012-06-12 08:33:39 +0000235 case PERIPH_ID_SPI1:
236 if (config == FUNCMUX_SPI1_GMC_GMD) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600237 pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_SFLASH);
238 pinmux_set_func(PMUX_PINGRP_GMD, PMUX_FUNC_SFLASH);
Stephen Warren1bdbc9f2012-06-12 08:33:39 +0000239
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600240 pinmux_tristate_disable(PMUX_PINGRP_GMC);
241 pinmux_tristate_disable(PMUX_PINGRP_GMD);
Stephen Warren1bdbc9f2012-06-12 08:33:39 +0000242 }
243 break;
244
Simon Glassfdf54732012-07-29 20:53:26 +0000245 case PERIPH_ID_NDFLASH:
Lucas Stach93748d32012-09-27 13:04:27 +0000246 switch (config) {
247 case FUNCMUX_NDFLASH_ATC:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600248 pinmux_set_func(PMUX_PINGRP_ATC, PMUX_FUNC_NAND);
249 pinmux_tristate_disable(PMUX_PINGRP_ATC);
Lucas Stach93748d32012-09-27 13:04:27 +0000250 break;
251 case FUNCMUX_NDFLASH_KBC_8_BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600252 pinmux_set_func(PMUX_PINGRP_KBCA, PMUX_FUNC_NAND);
Lucas Stachc9109a12015-03-27 01:31:44 +0100253 pinmux_set_func(PMUX_PINGRP_KBCB, PMUX_FUNC_NAND);
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600254 pinmux_set_func(PMUX_PINGRP_KBCC, PMUX_FUNC_NAND);
255 pinmux_set_func(PMUX_PINGRP_KBCD, PMUX_FUNC_NAND);
256 pinmux_set_func(PMUX_PINGRP_KBCE, PMUX_FUNC_NAND);
257 pinmux_set_func(PMUX_PINGRP_KBCF, PMUX_FUNC_NAND);
Lucas Stach93748d32012-09-27 13:04:27 +0000258
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600259 pinmux_tristate_disable(PMUX_PINGRP_KBCA);
Lucas Stachc9109a12015-03-27 01:31:44 +0100260 pinmux_tristate_disable(PMUX_PINGRP_KBCB);
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600261 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);
Lucas Stach93748d32012-09-27 13:04:27 +0000265
266 bad_config = 0;
267 break;
Simon Glassfdf54732012-07-29 20:53:26 +0000268 }
269 break;
Simon Glass11ecb382012-10-17 13:24:46 +0000270 case PERIPH_ID_DISP1:
271 if (config == FUNCMUX_DEFAULT) {
272 int i;
273
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600274 for (i = PMUX_PINGRP_LD0; i <= PMUX_PINGRP_LD17; i++) {
Simon Glass11ecb382012-10-17 13:24:46 +0000275 pinmux_set_func(i, PMUX_FUNC_DISPA);
276 pinmux_tristate_disable(i);
277 pinmux_set_pullupdown(i, PMUX_PULL_NORMAL);
278 }
Stephen Warrenf4df6052014-03-21 12:28:56 -0600279 pinmux_config_pingrp_table(disp1_default,
280 ARRAY_SIZE(disp1_default));
Simon Glass11ecb382012-10-17 13:24:46 +0000281 }
282 break;
Simon Glassfdf54732012-07-29 20:53:26 +0000283
Simon Glass84a97c52011-11-28 15:04:38 +0000284 default:
285 debug("%s: invalid periph_id %d", __func__, id);
286 return -1;
287 }
288
Simon Glass3ba99a32012-01-11 12:42:22 +0000289 if (bad_config) {
290 debug("%s: invalid config %d for periph_id %d", __func__,
291 config, id);
292 return -1;
293 }
294
Simon Glass84a97c52011-11-28 15:04:38 +0000295 return 0;
296}