blob: 2ee0f6ea76f109590d9b02e412e1187af808b0c9 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glassb5a5b352011-11-28 15:04:38 +00002/*
3 * Copyright (c) 2011 The Chromium OS Authors.
Simon Glassb5a5b352011-11-28 15:04:38 +00004 */
5
Allen Martin00a27492012-08-31 08:30:00 +00006/* Tegra20 high-level function multiplexing */
Simon Glassb5a5b352011-11-28 15:04:38 +00007#include <common.h>
8#include <asm/arch/clock.h>
Simon Glass2faf1862012-01-11 12:42:23 +00009#include <asm/arch/funcmux.h>
Simon Glassb5a5b352011-11-28 15:04:38 +000010#include <asm/arch/pinmux.h>
11
Simon Glassb3444962012-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 Warren70ad3752014-03-21 12:28:58 -060016 {PMUX_PINGRP_##grp, PMUX_FUNC_##mux, PMUX_PULL_##pupd, PMUX_TRI_##tri}
Simon Glassb3444962012-10-17 13:24:46 +000017
Stephen Warrendfb42fc2014-03-21 12:28:56 -060018static const struct pmux_pingrp_config disp1_default[] = {
Simon Glassb3444962012-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 Glassb5a5b352011-11-28 15:04:38 +000036int funcmux_select(enum periph_id id, int config)
37{
Simon Glass2faf1862012-01-11 12:42:23 +000038 int bad_config = config != FUNCMUX_DEFAULT;
Simon Glassd6939692012-01-11 12:42:22 +000039
Simon Glassb5a5b352011-11-28 15:04:38 +000040 switch (id) {
41 case PERIPH_ID_UART1:
Stephen Warrenb9607e72012-05-14 13:13:45 +000042 switch (config) {
43 case FUNCMUX_UART1_IRRX_IRTX:
Stephen Warren70ad3752014-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 Warrenb9607e72012-05-14 13:13:45 +000048 break;
49 case FUNCMUX_UART1_UAA_UAB:
Stephen Warren70ad3752014-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 Warrenb9607e72012-05-14 13:13:45 +000054 bad_config = 0;
55 break;
Stephen Warrene21649b2012-05-16 05:59:59 +000056 case FUNCMUX_UART1_GPU:
Stephen Warren70ad3752014-03-21 12:28:58 -060057 pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_UARTA);
58 pinmux_tristate_disable(PMUX_PINGRP_GPU);
Stephen Warrene21649b2012-05-16 05:59:59 +000059 bad_config = 0;
60 break;
Lucas Stacha2cfe632012-05-16 08:21:02 +000061 case FUNCMUX_UART1_SDIO1:
Stephen Warren70ad3752014-03-21 12:28:58 -060062 pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_UARTA);
63 pinmux_tristate_disable(PMUX_PINGRP_SDIO1);
Lucas Stacha2cfe632012-05-16 08:21:02 +000064 bad_config = 0;
65 break;
Stephen Warrenb9607e72012-05-14 13:13:45 +000066 }
67 if (!bad_config) {
Simon Glassd6939692012-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 Warren70ad3752014-03-21 12:28:58 -060079 pinmux_tristate_enable(PMUX_PINGRP_SDB);
80 pinmux_set_func(PMUX_PINGRP_SDB, PMUX_FUNC_SDIO3);
Simon Glassd6939692012-01-11 12:42:22 +000081 }
Simon Glassb5a5b352011-11-28 15:04:38 +000082 break;
83
84 case PERIPH_ID_UART2:
Stephen Warren4727a132013-01-22 06:20:08 +000085 if (config == FUNCMUX_UART2_UAD) {
Stephen Warren70ad3752014-03-21 12:28:58 -060086 pinmux_set_func(PMUX_PINGRP_UAD, PMUX_FUNC_UARTB);
87 pinmux_tristate_disable(PMUX_PINGRP_UAD);
Simon Glassd6939692012-01-11 12:42:22 +000088 }
Simon Glassb5a5b352011-11-28 15:04:38 +000089 break;
90
91 case PERIPH_ID_UART4:
Simon Glass2faf1862012-01-11 12:42:23 +000092 if (config == FUNCMUX_UART4_GMC) {
Stephen Warren70ad3752014-03-21 12:28:58 -060093 pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_UARTD);
94 pinmux_tristate_disable(PMUX_PINGRP_GMC);
Simon Glassd6939692012-01-11 12:42:22 +000095 }
Simon Glassb5a5b352011-11-28 15:04:38 +000096 break;
97
Simon Glass8a1133c2012-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 Warren70ad3752014-03-21 12:28:58 -0600101 pinmux_set_func(PMUX_PINGRP_I2CP, PMUX_FUNC_I2C);
102 pinmux_tristate_disable(PMUX_PINGRP_I2CP);
Simon Glass8a1133c2012-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 Warren70ad3752014-03-21 12:28:58 -0600109 pinmux_set_func(PMUX_PINGRP_RM, PMUX_FUNC_I2C);
110 pinmux_tristate_disable(PMUX_PINGRP_RM);
Simon Glass8a1133c2012-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 Warren70ad3752014-03-21 12:28:58 -0600116 pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_I2C2);
Simon Glass8a1133c2012-01-11 12:42:24 +0000117 /* PTA to HDMI */
Stephen Warren70ad3752014-03-21 12:28:58 -0600118 pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_HDMI);
119 pinmux_tristate_disable(PMUX_PINGRP_DDC);
Simon Glass8a1133c2012-01-11 12:42:24 +0000120 break;
121 case FUNCMUX_I2C2_PTA: /* PTA pin group, select I2C2 */
Stephen Warren70ad3752014-03-21 12:28:58 -0600122 pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_I2C2);
Simon Glass8a1133c2012-01-11 12:42:24 +0000123 /* set DDC_SEL to RSVDx (RSVD2 works for now) */
Stephen Warren70ad3752014-03-21 12:28:58 -0600124 pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_RSVD2);
125 pinmux_tristate_disable(PMUX_PINGRP_PTA);
Simon Glass8a1133c2012-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 Warren70ad3752014-03-21 12:28:58 -0600133 pinmux_set_func(PMUX_PINGRP_DTF, PMUX_FUNC_I2C3);
134 pinmux_tristate_disable(PMUX_PINGRP_DTF);
Simon Glass8a1133c2012-01-11 12:42:24 +0000135 }
136 break;
137
Stephen Warrend1e46072012-05-16 13:54:06 +0000138 case PERIPH_ID_SDMMC1:
139 if (config == FUNCMUX_SDMMC1_SDIO1_4BIT) {
Stephen Warren70ad3752014-03-21 12:28:58 -0600140 pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_SDIO1);
141 pinmux_tristate_disable(PMUX_PINGRP_SDIO1);
Stephen Warrend1e46072012-05-16 13:54:06 +0000142 }
143 break;
144
Simon Glasscf06b132012-01-11 12:42:25 +0000145 case PERIPH_ID_SDMMC2:
146 if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) {
Stephen Warren70ad3752014-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 Glasscf06b132012-01-11 12:42:25 +0000149
Stephen Warren70ad3752014-03-21 12:28:58 -0600150 pinmux_tristate_disable(PMUX_PINGRP_DTA);
151 pinmux_tristate_disable(PMUX_PINGRP_DTD);
Simon Glasscf06b132012-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 Warren70ad3752014-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 Glasscf06b132012-01-11 12:42:25 +0000162
Stephen Warren70ad3752014-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 Glasscf06b132012-01-11 12:42:25 +0000167 /* fall through */
168
169 case FUNCMUX_SDMMC3_SDB_4BIT:
Stephen Warren70ad3752014-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 Glasscf06b132012-01-11 12:42:25 +0000173
Stephen Warren70ad3752014-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 Glasscf06b132012-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 Warren70ad3752014-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 Glasscf06b132012-01-11 12:42:25 +0000187
Stephen Warren70ad3752014-03-21 12:28:58 -0600188 pinmux_tristate_disable(PMUX_PINGRP_ATC);
189 pinmux_tristate_disable(PMUX_PINGRP_ATD);
Simon Glasscf06b132012-01-11 12:42:25 +0000190 break;
191
192 case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT:
Stephen Warren70ad3752014-03-21 12:28:58 -0600193 pinmux_set_func(PMUX_PINGRP_GME, PMUX_FUNC_SDIO4);
194 pinmux_tristate_disable(PMUX_PINGRP_GME);
Simon Glasscf06b132012-01-11 12:42:25 +0000195 /* fall through */
196
197 case FUNCMUX_SDMMC4_ATB_GMA_4_BIT:
Stephen Warren70ad3752014-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 Glasscf06b132012-01-11 12:42:25 +0000200
Stephen Warren70ad3752014-03-21 12:28:58 -0600201 pinmux_tristate_disable(PMUX_PINGRP_ATB);
202 pinmux_tristate_disable(PMUX_PINGRP_GMA);
Simon Glasscf06b132012-01-11 12:42:25 +0000203 bad_config = 0;
204 break;
205 }
206 break;
207
Simon Glass7e91f402012-04-17 09:01:32 +0000208 case PERIPH_ID_KBC:
209 if (config == FUNCMUX_DEFAULT) {
Stephen Warren70ad3752014-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 Glass7e91f402012-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 }
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) {
Stephen Warren70ad3752014-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);
Lucas Stachf97daaa2012-05-31 01:51:01 +0000229
Stephen Warren70ad3752014-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);
Lucas Stachf97daaa2012-05-31 01:51:01 +0000233 }
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) {
Stephen Warren70ad3752014-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 Warrena016e142012-06-12 08:33:39 +0000240
Stephen Warren70ad3752014-03-21 12:28:58 -0600241 pinmux_tristate_disable(PMUX_PINGRP_GMC);
242 pinmux_tristate_disable(PMUX_PINGRP_GMD);
Stephen Warrena016e142012-06-12 08:33:39 +0000243 }
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:
Stephen Warren70ad3752014-03-21 12:28:58 -0600249 pinmux_set_func(PMUX_PINGRP_ATC, PMUX_FUNC_NAND);
250 pinmux_tristate_disable(PMUX_PINGRP_ATC);
Lucas Stachac56d952012-09-27 13:04:27 +0000251 break;
252 case FUNCMUX_NDFLASH_KBC_8_BIT:
Stephen Warren70ad3752014-03-21 12:28:58 -0600253 pinmux_set_func(PMUX_PINGRP_KBCA, PMUX_FUNC_NAND);
Lucas Stach9b219d42015-03-27 01:31:44 +0100254 pinmux_set_func(PMUX_PINGRP_KBCB, PMUX_FUNC_NAND);
Stephen Warren70ad3752014-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 Stachac56d952012-09-27 13:04:27 +0000259
Stephen Warren70ad3752014-03-21 12:28:58 -0600260 pinmux_tristate_disable(PMUX_PINGRP_KBCA);
Lucas Stach9b219d42015-03-27 01:31:44 +0100261 pinmux_tristate_disable(PMUX_PINGRP_KBCB);
Stephen Warren70ad3752014-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 Stachac56d952012-09-27 13:04:27 +0000266
267 bad_config = 0;
268 break;
Simon Glass35e11322012-07-29 20:53:26 +0000269 }
270 break;
Simon Glassb3444962012-10-17 13:24:46 +0000271 case PERIPH_ID_DISP1:
272 if (config == FUNCMUX_DEFAULT) {
273 int i;
274
Stephen Warren70ad3752014-03-21 12:28:58 -0600275 for (i = PMUX_PINGRP_LD0; i <= PMUX_PINGRP_LD17; i++) {
Simon Glassb3444962012-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 Warrendfb42fc2014-03-21 12:28:56 -0600280 pinmux_config_pingrp_table(disp1_default,
281 ARRAY_SIZE(disp1_default));
Simon Glassb3444962012-10-17 13:24:46 +0000282 }
283 break;
Simon Glass35e11322012-07-29 20:53:26 +0000284
Simon Glassb5a5b352011-11-28 15:04:38 +0000285 default:
286 debug("%s: invalid periph_id %d", __func__, id);
287 return -1;
288 }
289
Simon Glassd6939692012-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 Glassb5a5b352011-11-28 15:04:38 +0000296 return 0;
297}