blob: 0df4a0738de49d1bfc671bc3c312bde7cc06a68d [file] [log] [blame]
Simon Glassb5a5b352011-11-28 15:04:38 +00001/*
2 * Copyright (c) 2011 The Chromium OS Authors.
Simon Glassb5a5b352011-11-28 15:04:38 +00003 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02004 * SPDX-License-Identifier: GPL-2.0+
Simon Glassb5a5b352011-11-28 15:04:38 +00005 */
6
Allen Martin00a27492012-08-31 08:30:00 +00007/* Tegra20 high-level function multiplexing */
Simon Glassb5a5b352011-11-28 15:04:38 +00008#include <common.h>
9#include <asm/arch/clock.h>
Simon Glass2faf1862012-01-11 12:42:23 +000010#include <asm/arch/funcmux.h>
Simon Glassb5a5b352011-11-28 15:04:38 +000011#include <asm/arch/pinmux.h>
12
Simon Glassb3444962012-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 Warren70ad3752014-03-21 12:28:58 -060017 {PMUX_PINGRP_##grp, PMUX_FUNC_##mux, PMUX_PULL_##pupd, PMUX_TRI_##tri}
Simon Glassb3444962012-10-17 13:24:46 +000018
Stephen Warrendfb42fc2014-03-21 12:28:56 -060019static const struct pmux_pingrp_config disp1_default[] = {
Simon Glassb3444962012-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 Glassb5a5b352011-11-28 15:04:38 +000037int funcmux_select(enum periph_id id, int config)
38{
Simon Glass2faf1862012-01-11 12:42:23 +000039 int bad_config = config != FUNCMUX_DEFAULT;
Simon Glassd6939692012-01-11 12:42:22 +000040
Simon Glassb5a5b352011-11-28 15:04:38 +000041 switch (id) {
42 case PERIPH_ID_UART1:
Stephen Warrenb9607e72012-05-14 13:13:45 +000043 switch (config) {
44 case FUNCMUX_UART1_IRRX_IRTX:
Stephen Warren70ad3752014-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 Warrenb9607e72012-05-14 13:13:45 +000049 break;
50 case FUNCMUX_UART1_UAA_UAB:
Stephen Warren70ad3752014-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 Warrenb9607e72012-05-14 13:13:45 +000055 bad_config = 0;
56 break;
Stephen Warrene21649b2012-05-16 05:59:59 +000057 case FUNCMUX_UART1_GPU:
Stephen Warren70ad3752014-03-21 12:28:58 -060058 pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_UARTA);
59 pinmux_tristate_disable(PMUX_PINGRP_GPU);
Stephen Warrene21649b2012-05-16 05:59:59 +000060 bad_config = 0;
61 break;
Lucas Stacha2cfe632012-05-16 08:21:02 +000062 case FUNCMUX_UART1_SDIO1:
Stephen Warren70ad3752014-03-21 12:28:58 -060063 pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_UARTA);
64 pinmux_tristate_disable(PMUX_PINGRP_SDIO1);
Lucas Stacha2cfe632012-05-16 08:21:02 +000065 bad_config = 0;
66 break;
Stephen Warrenb9607e72012-05-14 13:13:45 +000067 }
68 if (!bad_config) {
Simon Glassd6939692012-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 Warren70ad3752014-03-21 12:28:58 -060080 pinmux_tristate_enable(PMUX_PINGRP_SDB);
81 pinmux_set_func(PMUX_PINGRP_SDB, PMUX_FUNC_SDIO3);
Simon Glassd6939692012-01-11 12:42:22 +000082 }
Simon Glassb5a5b352011-11-28 15:04:38 +000083 break;
84
85 case PERIPH_ID_UART2:
Stephen Warren4727a132013-01-22 06:20:08 +000086 if (config == FUNCMUX_UART2_UAD) {
Stephen Warren70ad3752014-03-21 12:28:58 -060087 pinmux_set_func(PMUX_PINGRP_UAD, PMUX_FUNC_UARTB);
88 pinmux_tristate_disable(PMUX_PINGRP_UAD);
Simon Glassd6939692012-01-11 12:42:22 +000089 }
Simon Glassb5a5b352011-11-28 15:04:38 +000090 break;
91
92 case PERIPH_ID_UART4:
Simon Glass2faf1862012-01-11 12:42:23 +000093 if (config == FUNCMUX_UART4_GMC) {
Stephen Warren70ad3752014-03-21 12:28:58 -060094 pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_UARTD);
95 pinmux_tristate_disable(PMUX_PINGRP_GMC);
Simon Glassd6939692012-01-11 12:42:22 +000096 }
Simon Glassb5a5b352011-11-28 15:04:38 +000097 break;
98
Simon Glass8a1133c2012-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 Warren70ad3752014-03-21 12:28:58 -0600102 pinmux_set_func(PMUX_PINGRP_I2CP, PMUX_FUNC_I2C);
103 pinmux_tristate_disable(PMUX_PINGRP_I2CP);
Simon Glass8a1133c2012-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 Warren70ad3752014-03-21 12:28:58 -0600110 pinmux_set_func(PMUX_PINGRP_RM, PMUX_FUNC_I2C);
111 pinmux_tristate_disable(PMUX_PINGRP_RM);
Simon Glass8a1133c2012-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 Warren70ad3752014-03-21 12:28:58 -0600117 pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_I2C2);
Simon Glass8a1133c2012-01-11 12:42:24 +0000118 /* PTA to HDMI */
Stephen Warren70ad3752014-03-21 12:28:58 -0600119 pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_HDMI);
120 pinmux_tristate_disable(PMUX_PINGRP_DDC);
Simon Glass8a1133c2012-01-11 12:42:24 +0000121 break;
122 case FUNCMUX_I2C2_PTA: /* PTA pin group, select I2C2 */
Stephen Warren70ad3752014-03-21 12:28:58 -0600123 pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_I2C2);
Simon Glass8a1133c2012-01-11 12:42:24 +0000124 /* set DDC_SEL to RSVDx (RSVD2 works for now) */
Stephen Warren70ad3752014-03-21 12:28:58 -0600125 pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_RSVD2);
126 pinmux_tristate_disable(PMUX_PINGRP_PTA);
Simon Glass8a1133c2012-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 Warren70ad3752014-03-21 12:28:58 -0600134 pinmux_set_func(PMUX_PINGRP_DTF, PMUX_FUNC_I2C3);
135 pinmux_tristate_disable(PMUX_PINGRP_DTF);
Simon Glass8a1133c2012-01-11 12:42:24 +0000136 }
137 break;
138
Stephen Warrend1e46072012-05-16 13:54:06 +0000139 case PERIPH_ID_SDMMC1:
140 if (config == FUNCMUX_SDMMC1_SDIO1_4BIT) {
Stephen Warren70ad3752014-03-21 12:28:58 -0600141 pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_SDIO1);
142 pinmux_tristate_disable(PMUX_PINGRP_SDIO1);
Stephen Warrend1e46072012-05-16 13:54:06 +0000143 }
144 break;
145
Simon Glasscf06b132012-01-11 12:42:25 +0000146 case PERIPH_ID_SDMMC2:
147 if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) {
Stephen Warren70ad3752014-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 Glasscf06b132012-01-11 12:42:25 +0000150
Stephen Warren70ad3752014-03-21 12:28:58 -0600151 pinmux_tristate_disable(PMUX_PINGRP_DTA);
152 pinmux_tristate_disable(PMUX_PINGRP_DTD);
Simon Glasscf06b132012-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 Warren70ad3752014-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 Glasscf06b132012-01-11 12:42:25 +0000163
Stephen Warren70ad3752014-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 Glasscf06b132012-01-11 12:42:25 +0000168 /* fall through */
169
170 case FUNCMUX_SDMMC3_SDB_4BIT:
Stephen Warren70ad3752014-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 Glasscf06b132012-01-11 12:42:25 +0000174
Stephen Warren70ad3752014-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 Glasscf06b132012-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 Warren70ad3752014-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 Glasscf06b132012-01-11 12:42:25 +0000188
Stephen Warren70ad3752014-03-21 12:28:58 -0600189 pinmux_tristate_disable(PMUX_PINGRP_ATC);
190 pinmux_tristate_disable(PMUX_PINGRP_ATD);
Simon Glasscf06b132012-01-11 12:42:25 +0000191 break;
192
193 case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT:
Stephen Warren70ad3752014-03-21 12:28:58 -0600194 pinmux_set_func(PMUX_PINGRP_GME, PMUX_FUNC_SDIO4);
195 pinmux_tristate_disable(PMUX_PINGRP_GME);
Simon Glasscf06b132012-01-11 12:42:25 +0000196 /* fall through */
197
198 case FUNCMUX_SDMMC4_ATB_GMA_4_BIT:
Stephen Warren70ad3752014-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 Glasscf06b132012-01-11 12:42:25 +0000201
Stephen Warren70ad3752014-03-21 12:28:58 -0600202 pinmux_tristate_disable(PMUX_PINGRP_ATB);
203 pinmux_tristate_disable(PMUX_PINGRP_GMA);
Simon Glasscf06b132012-01-11 12:42:25 +0000204 bad_config = 0;
205 break;
206 }
207 break;
208
Simon Glass7e91f402012-04-17 09:01:32 +0000209 case PERIPH_ID_KBC:
210 if (config == FUNCMUX_DEFAULT) {
Stephen Warren70ad3752014-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 Glass7e91f402012-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 }
Simon Glass7e91f402012-04-17 09:01:32 +0000222 }
Lucas Stachf97daaa2012-05-31 01:51:01 +0000223 break;
224
225 case PERIPH_ID_USB2:
226 if (config == FUNCMUX_USB2_ULPI) {
Stephen Warren70ad3752014-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);
Lucas Stachf97daaa2012-05-31 01:51:01 +0000230
Stephen Warren70ad3752014-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);
Lucas Stachf97daaa2012-05-31 01:51:01 +0000234 }
235 break;
Simon Glass7e91f402012-04-17 09:01:32 +0000236
Stephen Warrena016e142012-06-12 08:33:39 +0000237 case PERIPH_ID_SPI1:
238 if (config == FUNCMUX_SPI1_GMC_GMD) {
Stephen Warren70ad3752014-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 Warrena016e142012-06-12 08:33:39 +0000241
Stephen Warren70ad3752014-03-21 12:28:58 -0600242 pinmux_tristate_disable(PMUX_PINGRP_GMC);
243 pinmux_tristate_disable(PMUX_PINGRP_GMD);
Stephen Warrena016e142012-06-12 08:33:39 +0000244 }
245 break;
246
Simon Glass35e11322012-07-29 20:53:26 +0000247 case PERIPH_ID_NDFLASH:
Lucas Stachac56d952012-09-27 13:04:27 +0000248 switch (config) {
249 case FUNCMUX_NDFLASH_ATC:
Stephen Warren70ad3752014-03-21 12:28:58 -0600250 pinmux_set_func(PMUX_PINGRP_ATC, PMUX_FUNC_NAND);
251 pinmux_tristate_disable(PMUX_PINGRP_ATC);
Lucas Stachac56d952012-09-27 13:04:27 +0000252 break;
253 case FUNCMUX_NDFLASH_KBC_8_BIT:
Stephen Warren70ad3752014-03-21 12:28:58 -0600254 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);
Lucas Stachac56d952012-09-27 13:04:27 +0000259
Stephen Warren70ad3752014-03-21 12:28:58 -0600260 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);
Lucas Stachac56d952012-09-27 13:04:27 +0000265
266 bad_config = 0;
267 break;
Simon Glass35e11322012-07-29 20:53:26 +0000268 }
269 break;
Simon Glassb3444962012-10-17 13:24:46 +0000270 case PERIPH_ID_DISP1:
271 if (config == FUNCMUX_DEFAULT) {
272 int i;
273
Stephen Warren70ad3752014-03-21 12:28:58 -0600274 for (i = PMUX_PINGRP_LD0; i <= PMUX_PINGRP_LD17; i++) {
Simon Glassb3444962012-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 Warrendfb42fc2014-03-21 12:28:56 -0600279 pinmux_config_pingrp_table(disp1_default,
280 ARRAY_SIZE(disp1_default));
Simon Glassb3444962012-10-17 13:24:46 +0000281 }
282 break;
Simon Glass35e11322012-07-29 20:53:26 +0000283
Simon Glassb5a5b352011-11-28 15:04:38 +0000284 default:
285 debug("%s: invalid periph_id %d", __func__, id);
286 return -1;
287 }
288
Simon Glassd6939692012-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 Glassb5a5b352011-11-28 15:04:38 +0000295 return 0;
296}