blob: b8c9132378536be96178b9a54ec1d6a36e3ae27a [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
35
Simon Glass84a97c52011-11-28 15:04:38 +000036int funcmux_select(enum periph_id id, int config)
37{
Simon Glass43b1a7c2012-01-11 12:42:23 +000038 int bad_config = config != FUNCMUX_DEFAULT;
Simon Glass3ba99a32012-01-11 12:42:22 +000039
Simon Glass84a97c52011-11-28 15:04:38 +000040 switch (id) {
41 case PERIPH_ID_UART1:
Stephen Warren59f90102012-05-14 13:13:45 +000042 switch (config) {
43 case FUNCMUX_UART1_IRRX_IRTX:
Stephen Warrenf27f4e82014-03-21 12:28:58 -060044 pinmux_set_func(PMUX_PINGRP_IRRX, PMUX_FUNC_UARTA);
45 pinmux_set_func(PMUX_PINGRP_IRTX, PMUX_FUNC_UARTA);
46 pinmux_tristate_disable(PMUX_PINGRP_IRRX);
47 pinmux_tristate_disable(PMUX_PINGRP_IRTX);
Stephen Warren59f90102012-05-14 13:13:45 +000048 break;
49 case FUNCMUX_UART1_UAA_UAB:
Stephen Warrenf27f4e82014-03-21 12:28:58 -060050 pinmux_set_func(PMUX_PINGRP_UAA, PMUX_FUNC_UARTA);
51 pinmux_set_func(PMUX_PINGRP_UAB, PMUX_FUNC_UARTA);
52 pinmux_tristate_disable(PMUX_PINGRP_UAA);
53 pinmux_tristate_disable(PMUX_PINGRP_UAB);
Stephen Warren59f90102012-05-14 13:13:45 +000054 bad_config = 0;
55 break;
Stephen Warrene4c01a82012-05-16 05:59:59 +000056 case FUNCMUX_UART1_GPU:
Stephen Warrenf27f4e82014-03-21 12:28:58 -060057 pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_UARTA);
58 pinmux_tristate_disable(PMUX_PINGRP_GPU);
Stephen Warrene4c01a82012-05-16 05:59:59 +000059 bad_config = 0;
60 break;
Lucas Stach4de6eec2012-05-16 08:21:02 +000061 case FUNCMUX_UART1_SDIO1:
Stephen Warrenf27f4e82014-03-21 12:28:58 -060062 pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_UARTA);
63 pinmux_tristate_disable(PMUX_PINGRP_SDIO1);
Lucas Stach4de6eec2012-05-16 08:21:02 +000064 bad_config = 0;
65 break;
Stephen Warren59f90102012-05-14 13:13:45 +000066 }
67 if (!bad_config) {
Simon Glass3ba99a32012-01-11 12:42:22 +000068 /*
69 * Tegra appears to boot with function UARTA pre-
70 * selected on mux group SDB. If two mux groups are
71 * both set to the same function, it's unclear which
72 * group's pins drive the RX signals into the HW.
73 * For UARTA, SDB certainly overrides group IRTX in
74 * practice. To solve this, configure some alternative
75 * function on SDB to avoid the conflict. Also, tri-
76 * state the group to avoid driving any signal onto it
77 * until we know what's connected.
78 */
Stephen Warrenf27f4e82014-03-21 12:28:58 -060079 pinmux_tristate_enable(PMUX_PINGRP_SDB);
80 pinmux_set_func(PMUX_PINGRP_SDB, PMUX_FUNC_SDIO3);
Simon Glass3ba99a32012-01-11 12:42:22 +000081 }
Simon Glass84a97c52011-11-28 15:04:38 +000082 break;
83
84 case PERIPH_ID_UART2:
Stephen Warren811af732013-01-22 06:20:08 +000085 if (config == FUNCMUX_UART2_UAD) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -060086 pinmux_set_func(PMUX_PINGRP_UAD, PMUX_FUNC_UARTB);
87 pinmux_tristate_disable(PMUX_PINGRP_UAD);
Simon Glass3ba99a32012-01-11 12:42:22 +000088 }
Simon Glass84a97c52011-11-28 15:04:38 +000089 break;
90
91 case PERIPH_ID_UART4:
Simon Glass43b1a7c2012-01-11 12:42:23 +000092 if (config == FUNCMUX_UART4_GMC) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -060093 pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_UARTD);
94 pinmux_tristate_disable(PMUX_PINGRP_GMC);
Simon Glass3ba99a32012-01-11 12:42:22 +000095 }
Simon Glass84a97c52011-11-28 15:04:38 +000096 break;
97
Simon Glassd8c03b82012-01-11 12:42:24 +000098 case PERIPH_ID_DVC_I2C:
99 /* there is only one selection, pinmux_config is ignored */
100 if (config == FUNCMUX_DVC_I2CP) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600101 pinmux_set_func(PMUX_PINGRP_I2CP, PMUX_FUNC_I2C);
102 pinmux_tristate_disable(PMUX_PINGRP_I2CP);
Simon Glassd8c03b82012-01-11 12:42:24 +0000103 }
104 break;
105
106 case PERIPH_ID_I2C1:
107 /* support pinmux_config of 0 for now, */
108 if (config == FUNCMUX_I2C1_RM) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600109 pinmux_set_func(PMUX_PINGRP_RM, PMUX_FUNC_I2C);
110 pinmux_tristate_disable(PMUX_PINGRP_RM);
Simon Glassd8c03b82012-01-11 12:42:24 +0000111 }
112 break;
113 case PERIPH_ID_I2C2: /* I2C2 */
114 switch (config) {
115 case FUNCMUX_I2C2_DDC: /* DDC pin group, select I2C2 */
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600116 pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_I2C2);
Simon Glassd8c03b82012-01-11 12:42:24 +0000117 /* PTA to HDMI */
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600118 pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_HDMI);
119 pinmux_tristate_disable(PMUX_PINGRP_DDC);
Simon Glassd8c03b82012-01-11 12:42:24 +0000120 break;
121 case FUNCMUX_I2C2_PTA: /* PTA pin group, select I2C2 */
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600122 pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_I2C2);
Simon Glassd8c03b82012-01-11 12:42:24 +0000123 /* set DDC_SEL to RSVDx (RSVD2 works for now) */
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600124 pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_RSVD2);
125 pinmux_tristate_disable(PMUX_PINGRP_PTA);
Simon Glassd8c03b82012-01-11 12:42:24 +0000126 bad_config = 0;
127 break;
128 }
129 break;
130 case PERIPH_ID_I2C3: /* I2C3 */
131 /* support pinmux_config of 0 for now */
132 if (config == FUNCMUX_I2C3_DTF) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600133 pinmux_set_func(PMUX_PINGRP_DTF, PMUX_FUNC_I2C3);
134 pinmux_tristate_disable(PMUX_PINGRP_DTF);
Simon Glassd8c03b82012-01-11 12:42:24 +0000135 }
136 break;
137
Stephen Warrenb6d19012012-05-16 13:54:06 +0000138 case PERIPH_ID_SDMMC1:
139 if (config == FUNCMUX_SDMMC1_SDIO1_4BIT) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600140 pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_SDIO1);
141 pinmux_tristate_disable(PMUX_PINGRP_SDIO1);
Stephen Warrenb6d19012012-05-16 13:54:06 +0000142 }
143 break;
144
Simon Glassfb1ea632012-01-11 12:42:25 +0000145 case PERIPH_ID_SDMMC2:
146 if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600147 pinmux_set_func(PMUX_PINGRP_DTA, PMUX_FUNC_SDIO2);
148 pinmux_set_func(PMUX_PINGRP_DTD, PMUX_FUNC_SDIO2);
Simon Glassfb1ea632012-01-11 12:42:25 +0000149
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600150 pinmux_tristate_disable(PMUX_PINGRP_DTA);
151 pinmux_tristate_disable(PMUX_PINGRP_DTD);
Simon Glassfb1ea632012-01-11 12:42:25 +0000152 }
153 break;
154
155 case PERIPH_ID_SDMMC3:
156 switch (config) {
157 case FUNCMUX_SDMMC3_SDB_SLXA_8BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600158 pinmux_set_func(PMUX_PINGRP_SLXA, PMUX_FUNC_SDIO3);
159 pinmux_set_func(PMUX_PINGRP_SLXC, PMUX_FUNC_SDIO3);
160 pinmux_set_func(PMUX_PINGRP_SLXD, PMUX_FUNC_SDIO3);
161 pinmux_set_func(PMUX_PINGRP_SLXK, PMUX_FUNC_SDIO3);
Simon Glassfb1ea632012-01-11 12:42:25 +0000162
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600163 pinmux_tristate_disable(PMUX_PINGRP_SLXA);
164 pinmux_tristate_disable(PMUX_PINGRP_SLXC);
165 pinmux_tristate_disable(PMUX_PINGRP_SLXD);
166 pinmux_tristate_disable(PMUX_PINGRP_SLXK);
Simon Glassfb1ea632012-01-11 12:42:25 +0000167 /* fall through */
168
169 case FUNCMUX_SDMMC3_SDB_4BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600170 pinmux_set_func(PMUX_PINGRP_SDB, PMUX_FUNC_SDIO3);
171 pinmux_set_func(PMUX_PINGRP_SDC, PMUX_FUNC_SDIO3);
172 pinmux_set_func(PMUX_PINGRP_SDD, PMUX_FUNC_SDIO3);
Simon Glassfb1ea632012-01-11 12:42:25 +0000173
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600174 pinmux_tristate_disable(PMUX_PINGRP_SDB);
175 pinmux_tristate_disable(PMUX_PINGRP_SDC);
176 pinmux_tristate_disable(PMUX_PINGRP_SDD);
Simon Glassfb1ea632012-01-11 12:42:25 +0000177 bad_config = 0;
178 break;
179 }
180 break;
181
182 case PERIPH_ID_SDMMC4:
183 switch (config) {
184 case FUNCMUX_SDMMC4_ATC_ATD_8BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600185 pinmux_set_func(PMUX_PINGRP_ATC, PMUX_FUNC_SDIO4);
186 pinmux_set_func(PMUX_PINGRP_ATD, PMUX_FUNC_SDIO4);
Simon Glassfb1ea632012-01-11 12:42:25 +0000187
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600188 pinmux_tristate_disable(PMUX_PINGRP_ATC);
189 pinmux_tristate_disable(PMUX_PINGRP_ATD);
Simon Glassfb1ea632012-01-11 12:42:25 +0000190 break;
191
192 case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600193 pinmux_set_func(PMUX_PINGRP_GME, PMUX_FUNC_SDIO4);
194 pinmux_tristate_disable(PMUX_PINGRP_GME);
Simon Glassfb1ea632012-01-11 12:42:25 +0000195 /* fall through */
196
197 case FUNCMUX_SDMMC4_ATB_GMA_4_BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600198 pinmux_set_func(PMUX_PINGRP_ATB, PMUX_FUNC_SDIO4);
199 pinmux_set_func(PMUX_PINGRP_GMA, PMUX_FUNC_SDIO4);
Simon Glassfb1ea632012-01-11 12:42:25 +0000200
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600201 pinmux_tristate_disable(PMUX_PINGRP_ATB);
202 pinmux_tristate_disable(PMUX_PINGRP_GMA);
Simon Glassfb1ea632012-01-11 12:42:25 +0000203 bad_config = 0;
204 break;
205 }
206 break;
207
Simon Glass5dc04612012-04-17 09:01:32 +0000208 case PERIPH_ID_KBC:
209 if (config == FUNCMUX_DEFAULT) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600210 enum pmux_pingrp grp[] = {PMUX_PINGRP_KBCA,
211 PMUX_PINGRP_KBCB, PMUX_PINGRP_KBCC,
212 PMUX_PINGRP_KBCD, PMUX_PINGRP_KBCE,
213 PMUX_PINGRP_KBCF};
Simon Glass5dc04612012-04-17 09:01:32 +0000214 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 }
Lucas Stach53c79112012-05-31 01:51:01 +0000221 }
222 break;
223
224 case PERIPH_ID_USB2:
225 if (config == FUNCMUX_USB2_ULPI) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600226 pinmux_set_func(PMUX_PINGRP_UAA, PMUX_FUNC_ULPI);
227 pinmux_set_func(PMUX_PINGRP_UAB, PMUX_FUNC_ULPI);
228 pinmux_set_func(PMUX_PINGRP_UDA, PMUX_FUNC_ULPI);
Simon Glass5dc04612012-04-17 09:01:32 +0000229
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600230 pinmux_tristate_disable(PMUX_PINGRP_UAA);
231 pinmux_tristate_disable(PMUX_PINGRP_UAB);
232 pinmux_tristate_disable(PMUX_PINGRP_UDA);
Simon Glass5dc04612012-04-17 09:01:32 +0000233 }
Lucas Stach53c79112012-05-31 01:51:01 +0000234 break;
Simon Glass5dc04612012-04-17 09:01:32 +0000235
Stephen Warren1bdbc9f2012-06-12 08:33:39 +0000236 case PERIPH_ID_SPI1:
237 if (config == FUNCMUX_SPI1_GMC_GMD) {
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600238 pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_SFLASH);
239 pinmux_set_func(PMUX_PINGRP_GMD, PMUX_FUNC_SFLASH);
Stephen Warren1bdbc9f2012-06-12 08:33:39 +0000240
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600241 pinmux_tristate_disable(PMUX_PINGRP_GMC);
242 pinmux_tristate_disable(PMUX_PINGRP_GMD);
Stephen Warren1bdbc9f2012-06-12 08:33:39 +0000243 }
244 break;
245
Simon Glassfdf54732012-07-29 20:53:26 +0000246 case PERIPH_ID_NDFLASH:
Lucas Stach93748d32012-09-27 13:04:27 +0000247 switch (config) {
248 case FUNCMUX_NDFLASH_ATC:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600249 pinmux_set_func(PMUX_PINGRP_ATC, PMUX_FUNC_NAND);
250 pinmux_tristate_disable(PMUX_PINGRP_ATC);
Lucas Stach93748d32012-09-27 13:04:27 +0000251 break;
252 case FUNCMUX_NDFLASH_KBC_8_BIT:
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600253 pinmux_set_func(PMUX_PINGRP_KBCA, PMUX_FUNC_NAND);
Lucas Stachc9109a12015-03-27 01:31:44 +0100254 pinmux_set_func(PMUX_PINGRP_KBCB, PMUX_FUNC_NAND);
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600255 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 Stach93748d32012-09-27 13:04:27 +0000259
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600260 pinmux_tristate_disable(PMUX_PINGRP_KBCA);
Lucas Stachc9109a12015-03-27 01:31:44 +0100261 pinmux_tristate_disable(PMUX_PINGRP_KBCB);
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600262 pinmux_tristate_disable(PMUX_PINGRP_KBCC);
263 pinmux_tristate_disable(PMUX_PINGRP_KBCD);
264 pinmux_tristate_disable(PMUX_PINGRP_KBCE);
265 pinmux_tristate_disable(PMUX_PINGRP_KBCF);
Lucas Stach93748d32012-09-27 13:04:27 +0000266
267 bad_config = 0;
268 break;
Simon Glassfdf54732012-07-29 20:53:26 +0000269 }
270 break;
Simon Glass11ecb382012-10-17 13:24:46 +0000271 case PERIPH_ID_DISP1:
272 if (config == FUNCMUX_DEFAULT) {
273 int i;
274
Stephen Warrenf27f4e82014-03-21 12:28:58 -0600275 for (i = PMUX_PINGRP_LD0; i <= PMUX_PINGRP_LD17; i++) {
Simon Glass11ecb382012-10-17 13:24:46 +0000276 pinmux_set_func(i, PMUX_FUNC_DISPA);
277 pinmux_tristate_disable(i);
278 pinmux_set_pullupdown(i, PMUX_PULL_NORMAL);
279 }
Stephen Warrenf4df6052014-03-21 12:28:56 -0600280 pinmux_config_pingrp_table(disp1_default,
281 ARRAY_SIZE(disp1_default));
Simon Glass11ecb382012-10-17 13:24:46 +0000282 }
283 break;
Simon Glassfdf54732012-07-29 20:53:26 +0000284
Simon Glass84a97c52011-11-28 15:04:38 +0000285 default:
286 debug("%s: invalid periph_id %d", __func__, id);
287 return -1;
288 }
289
Simon Glass3ba99a32012-01-11 12:42:22 +0000290 if (bad_config) {
291 debug("%s: invalid config %d for periph_id %d", __func__,
292 config, id);
293 return -1;
294 }
295
Simon Glass84a97c52011-11-28 15:04:38 +0000296 return 0;
297}