blob: 8ae28672499a2e809c636f66be3c5f3bb8676dde [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) \
17 {PINGRP_##grp, PMUX_FUNC_##mux, PMUX_PULL_##pupd, PMUX_TRI_##tri}
18
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:
Simon Glassd6939692012-01-11 12:42:22 +000045 pinmux_set_func(PINGRP_IRRX, PMUX_FUNC_UARTA);
46 pinmux_set_func(PINGRP_IRTX, PMUX_FUNC_UARTA);
47 pinmux_tristate_disable(PINGRP_IRRX);
48 pinmux_tristate_disable(PINGRP_IRTX);
Stephen Warrenb9607e72012-05-14 13:13:45 +000049 break;
50 case FUNCMUX_UART1_UAA_UAB:
51 pinmux_set_func(PINGRP_UAA, PMUX_FUNC_UARTA);
52 pinmux_set_func(PINGRP_UAB, PMUX_FUNC_UARTA);
53 pinmux_tristate_disable(PINGRP_UAA);
54 pinmux_tristate_disable(PINGRP_UAB);
55 bad_config = 0;
56 break;
Stephen Warrene21649b2012-05-16 05:59:59 +000057 case FUNCMUX_UART1_GPU:
58 pinmux_set_func(PINGRP_GPU, PMUX_FUNC_UARTA);
59 pinmux_tristate_disable(PINGRP_GPU);
60 bad_config = 0;
61 break;
Lucas Stacha2cfe632012-05-16 08:21:02 +000062 case FUNCMUX_UART1_SDIO1:
63 pinmux_set_func(PINGRP_SDIO1, PMUX_FUNC_UARTA);
64 pinmux_tristate_disable(PINGRP_SDIO1);
65 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 */
80 pinmux_tristate_enable(PINGRP_SDB);
81 pinmux_set_func(PINGRP_SDB, PMUX_FUNC_SDIO3);
82 }
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) {
Allen Martind08b9e92013-01-09 10:52:23 +000087 pinmux_set_func(PINGRP_UAD, PMUX_FUNC_UARTB);
Simon Glassd6939692012-01-11 12:42:22 +000088 pinmux_tristate_disable(PINGRP_UAD);
89 }
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) {
Simon Glassd6939692012-01-11 12:42:22 +000094 pinmux_set_func(PINGRP_GMC, PMUX_FUNC_UARTD);
95 pinmux_tristate_disable(PINGRP_GMC);
96 }
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) {
102 pinmux_set_func(PINGRP_I2CP, PMUX_FUNC_I2C);
103 pinmux_tristate_disable(PINGRP_I2CP);
104 }
105 break;
106
107 case PERIPH_ID_I2C1:
108 /* support pinmux_config of 0 for now, */
109 if (config == FUNCMUX_I2C1_RM) {
110 pinmux_set_func(PINGRP_RM, PMUX_FUNC_I2C);
111 pinmux_tristate_disable(PINGRP_RM);
112 }
113 break;
114 case PERIPH_ID_I2C2: /* I2C2 */
115 switch (config) {
116 case FUNCMUX_I2C2_DDC: /* DDC pin group, select I2C2 */
117 pinmux_set_func(PINGRP_DDC, PMUX_FUNC_I2C2);
118 /* PTA to HDMI */
119 pinmux_set_func(PINGRP_PTA, PMUX_FUNC_HDMI);
120 pinmux_tristate_disable(PINGRP_DDC);
121 break;
122 case FUNCMUX_I2C2_PTA: /* PTA pin group, select I2C2 */
123 pinmux_set_func(PINGRP_PTA, PMUX_FUNC_I2C2);
124 /* set DDC_SEL to RSVDx (RSVD2 works for now) */
125 pinmux_set_func(PINGRP_DDC, PMUX_FUNC_RSVD2);
126 pinmux_tristate_disable(PINGRP_PTA);
127 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) {
134 pinmux_set_func(PINGRP_DTF, PMUX_FUNC_I2C3);
135 pinmux_tristate_disable(PINGRP_DTF);
136 }
137 break;
138
Stephen Warrend1e46072012-05-16 13:54:06 +0000139 case PERIPH_ID_SDMMC1:
140 if (config == FUNCMUX_SDMMC1_SDIO1_4BIT) {
141 pinmux_set_func(PINGRP_SDIO1, PMUX_FUNC_SDIO1);
142 pinmux_tristate_disable(PINGRP_SDIO1);
143 }
144 break;
145
Simon Glasscf06b132012-01-11 12:42:25 +0000146 case PERIPH_ID_SDMMC2:
147 if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) {
148 pinmux_set_func(PINGRP_DTA, PMUX_FUNC_SDIO2);
149 pinmux_set_func(PINGRP_DTD, PMUX_FUNC_SDIO2);
150
151 pinmux_tristate_disable(PINGRP_DTA);
152 pinmux_tristate_disable(PINGRP_DTD);
153 }
154 break;
155
156 case PERIPH_ID_SDMMC3:
157 switch (config) {
158 case FUNCMUX_SDMMC3_SDB_SLXA_8BIT:
159 pinmux_set_func(PINGRP_SLXA, PMUX_FUNC_SDIO3);
160 pinmux_set_func(PINGRP_SLXC, PMUX_FUNC_SDIO3);
161 pinmux_set_func(PINGRP_SLXD, PMUX_FUNC_SDIO3);
162 pinmux_set_func(PINGRP_SLXK, PMUX_FUNC_SDIO3);
163
164 pinmux_tristate_disable(PINGRP_SLXA);
165 pinmux_tristate_disable(PINGRP_SLXC);
166 pinmux_tristate_disable(PINGRP_SLXD);
167 pinmux_tristate_disable(PINGRP_SLXK);
168 /* fall through */
169
170 case FUNCMUX_SDMMC3_SDB_4BIT:
171 pinmux_set_func(PINGRP_SDB, PMUX_FUNC_SDIO3);
172 pinmux_set_func(PINGRP_SDC, PMUX_FUNC_SDIO3);
173 pinmux_set_func(PINGRP_SDD, PMUX_FUNC_SDIO3);
174
175 pinmux_tristate_disable(PINGRP_SDB);
176 pinmux_tristate_disable(PINGRP_SDC);
177 pinmux_tristate_disable(PINGRP_SDD);
178 bad_config = 0;
179 break;
180 }
181 break;
182
183 case PERIPH_ID_SDMMC4:
184 switch (config) {
185 case FUNCMUX_SDMMC4_ATC_ATD_8BIT:
186 pinmux_set_func(PINGRP_ATC, PMUX_FUNC_SDIO4);
187 pinmux_set_func(PINGRP_ATD, PMUX_FUNC_SDIO4);
188
189 pinmux_tristate_disable(PINGRP_ATC);
190 pinmux_tristate_disable(PINGRP_ATD);
191 break;
192
193 case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT:
194 pinmux_set_func(PINGRP_GME, PMUX_FUNC_SDIO4);
195 pinmux_tristate_disable(PINGRP_GME);
196 /* fall through */
197
198 case FUNCMUX_SDMMC4_ATB_GMA_4_BIT:
199 pinmux_set_func(PINGRP_ATB, PMUX_FUNC_SDIO4);
200 pinmux_set_func(PINGRP_GMA, PMUX_FUNC_SDIO4);
201
202 pinmux_tristate_disable(PINGRP_ATB);
203 pinmux_tristate_disable(PINGRP_GMA);
204 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) {
211 enum pmux_pingrp grp[] = {PINGRP_KBCA, PINGRP_KBCB,
212 PINGRP_KBCC, PINGRP_KBCD, PINGRP_KBCE,
213 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 }
Simon Glass7e91f402012-04-17 09:01:32 +0000221 }
Lucas Stachf97daaa2012-05-31 01:51:01 +0000222 break;
223
224 case PERIPH_ID_USB2:
225 if (config == FUNCMUX_USB2_ULPI) {
226 pinmux_set_func(PINGRP_UAA, PMUX_FUNC_ULPI);
227 pinmux_set_func(PINGRP_UAB, PMUX_FUNC_ULPI);
228 pinmux_set_func(PINGRP_UDA, PMUX_FUNC_ULPI);
229
230 pinmux_tristate_disable(PINGRP_UAA);
231 pinmux_tristate_disable(PINGRP_UAB);
232 pinmux_tristate_disable(PINGRP_UDA);
233 }
234 break;
Simon Glass7e91f402012-04-17 09:01:32 +0000235
Stephen Warrena016e142012-06-12 08:33:39 +0000236 case PERIPH_ID_SPI1:
237 if (config == FUNCMUX_SPI1_GMC_GMD) {
238 pinmux_set_func(PINGRP_GMC, PMUX_FUNC_SFLASH);
239 pinmux_set_func(PINGRP_GMD, PMUX_FUNC_SFLASH);
240
241 pinmux_tristate_disable(PINGRP_GMC);
242 pinmux_tristate_disable(PINGRP_GMD);
243 }
244 break;
245
Simon Glass35e11322012-07-29 20:53:26 +0000246 case PERIPH_ID_NDFLASH:
Lucas Stachac56d952012-09-27 13:04:27 +0000247 switch (config) {
248 case FUNCMUX_NDFLASH_ATC:
Simon Glass35e11322012-07-29 20:53:26 +0000249 pinmux_set_func(PINGRP_ATC, PMUX_FUNC_NAND);
250 pinmux_tristate_disable(PINGRP_ATC);
Lucas Stachac56d952012-09-27 13:04:27 +0000251 break;
252 case FUNCMUX_NDFLASH_KBC_8_BIT:
253 pinmux_set_func(PINGRP_KBCA, PMUX_FUNC_NAND);
254 pinmux_set_func(PINGRP_KBCC, PMUX_FUNC_NAND);
255 pinmux_set_func(PINGRP_KBCD, PMUX_FUNC_NAND);
256 pinmux_set_func(PINGRP_KBCE, PMUX_FUNC_NAND);
257 pinmux_set_func(PINGRP_KBCF, PMUX_FUNC_NAND);
258
259 pinmux_tristate_disable(PINGRP_KBCA);
260 pinmux_tristate_disable(PINGRP_KBCC);
261 pinmux_tristate_disable(PINGRP_KBCD);
262 pinmux_tristate_disable(PINGRP_KBCE);
263 pinmux_tristate_disable(PINGRP_KBCF);
264
265 bad_config = 0;
266 break;
Simon Glass35e11322012-07-29 20:53:26 +0000267 }
268 break;
Simon Glassb3444962012-10-17 13:24:46 +0000269 case PERIPH_ID_DISP1:
270 if (config == FUNCMUX_DEFAULT) {
271 int i;
272
273 for (i = PINGRP_LD0; i <= PINGRP_LD17; i++) {
274 pinmux_set_func(i, PMUX_FUNC_DISPA);
275 pinmux_tristate_disable(i);
276 pinmux_set_pullupdown(i, PMUX_PULL_NORMAL);
277 }
Stephen Warrendfb42fc2014-03-21 12:28:56 -0600278 pinmux_config_pingrp_table(disp1_default,
279 ARRAY_SIZE(disp1_default));
Simon Glassb3444962012-10-17 13:24:46 +0000280 }
281 break;
Simon Glass35e11322012-07-29 20:53:26 +0000282
Simon Glassb5a5b352011-11-28 15:04:38 +0000283 default:
284 debug("%s: invalid periph_id %d", __func__, id);
285 return -1;
286 }
287
Simon Glassd6939692012-01-11 12:42:22 +0000288 if (bad_config) {
289 debug("%s: invalid config %d for periph_id %d", __func__,
290 config, id);
291 return -1;
292 }
293
Simon Glassb5a5b352011-11-28 15:04:38 +0000294 return 0;
295}