]> git.sur5r.net Git - u-boot/blob - arch/arm/mach-tegra/tegra20/funcmux.c
SPDX: Convert all of our single license tags to Linux Kernel style
[u-boot] / arch / arm / mach-tegra / tegra20 / funcmux.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2011 The Chromium OS Authors.
4  */
5
6 /* Tegra20 high-level function multiplexing */
7 #include <common.h>
8 #include <asm/arch/clock.h>
9 #include <asm/arch/funcmux.h>
10 #include <asm/arch/pinmux.h>
11
12 /*
13  * The PINMUX macro is used to set up pinmux tables.
14  */
15 #define PINMUX(grp, mux, pupd, tri)                   \
16         {PMUX_PINGRP_##grp, PMUX_FUNC_##mux, PMUX_PULL_##pupd, PMUX_TRI_##tri}
17
18 static const struct pmux_pingrp_config disp1_default[] = {
19         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
36 int funcmux_select(enum periph_id id, int config)
37 {
38         int bad_config = config != FUNCMUX_DEFAULT;
39
40         switch (id) {
41         case PERIPH_ID_UART1:
42                 switch (config) {
43                 case FUNCMUX_UART1_IRRX_IRTX:
44                         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);
48                         break;
49                 case FUNCMUX_UART1_UAA_UAB:
50                         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);
54                         bad_config = 0;
55                         break;
56                 case FUNCMUX_UART1_GPU:
57                         pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_UARTA);
58                         pinmux_tristate_disable(PMUX_PINGRP_GPU);
59                         bad_config = 0;
60                         break;
61                 case FUNCMUX_UART1_SDIO1:
62                         pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_UARTA);
63                         pinmux_tristate_disable(PMUX_PINGRP_SDIO1);
64                         bad_config = 0;
65                         break;
66                 }
67                 if (!bad_config) {
68                         /*
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                          */
79                         pinmux_tristate_enable(PMUX_PINGRP_SDB);
80                         pinmux_set_func(PMUX_PINGRP_SDB,  PMUX_FUNC_SDIO3);
81                 }
82                 break;
83
84         case PERIPH_ID_UART2:
85                 if (config == FUNCMUX_UART2_UAD) {
86                         pinmux_set_func(PMUX_PINGRP_UAD, PMUX_FUNC_UARTB);
87                         pinmux_tristate_disable(PMUX_PINGRP_UAD);
88                 }
89                 break;
90
91         case PERIPH_ID_UART4:
92                 if (config == FUNCMUX_UART4_GMC) {
93                         pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_UARTD);
94                         pinmux_tristate_disable(PMUX_PINGRP_GMC);
95                 }
96                 break;
97
98         case PERIPH_ID_DVC_I2C:
99                 /* there is only one selection, pinmux_config is ignored */
100                 if (config == FUNCMUX_DVC_I2CP) {
101                         pinmux_set_func(PMUX_PINGRP_I2CP, PMUX_FUNC_I2C);
102                         pinmux_tristate_disable(PMUX_PINGRP_I2CP);
103                 }
104                 break;
105
106         case PERIPH_ID_I2C1:
107                 /* support pinmux_config of 0 for now, */
108                 if (config == FUNCMUX_I2C1_RM) {
109                         pinmux_set_func(PMUX_PINGRP_RM, PMUX_FUNC_I2C);
110                         pinmux_tristate_disable(PMUX_PINGRP_RM);
111                 }
112                 break;
113         case PERIPH_ID_I2C2: /* I2C2 */
114                 switch (config) {
115                 case FUNCMUX_I2C2_DDC:  /* DDC pin group, select I2C2 */
116                         pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_I2C2);
117                         /* PTA to HDMI */
118                         pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_HDMI);
119                         pinmux_tristate_disable(PMUX_PINGRP_DDC);
120                         break;
121                 case FUNCMUX_I2C2_PTA:  /* PTA pin group, select I2C2 */
122                         pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_I2C2);
123                         /* set DDC_SEL to RSVDx (RSVD2 works for now) */
124                         pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_RSVD2);
125                         pinmux_tristate_disable(PMUX_PINGRP_PTA);
126                         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) {
133                         pinmux_set_func(PMUX_PINGRP_DTF, PMUX_FUNC_I2C3);
134                         pinmux_tristate_disable(PMUX_PINGRP_DTF);
135                 }
136                 break;
137
138         case PERIPH_ID_SDMMC1:
139                 if (config == FUNCMUX_SDMMC1_SDIO1_4BIT) {
140                         pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_SDIO1);
141                         pinmux_tristate_disable(PMUX_PINGRP_SDIO1);
142                 }
143                 break;
144
145         case PERIPH_ID_SDMMC2:
146                 if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) {
147                         pinmux_set_func(PMUX_PINGRP_DTA, PMUX_FUNC_SDIO2);
148                         pinmux_set_func(PMUX_PINGRP_DTD, PMUX_FUNC_SDIO2);
149
150                         pinmux_tristate_disable(PMUX_PINGRP_DTA);
151                         pinmux_tristate_disable(PMUX_PINGRP_DTD);
152                 }
153                 break;
154
155         case PERIPH_ID_SDMMC3:
156                 switch (config) {
157                 case FUNCMUX_SDMMC3_SDB_SLXA_8BIT:
158                         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);
162
163                         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);
167                         /* fall through */
168
169                 case FUNCMUX_SDMMC3_SDB_4BIT:
170                         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);
173
174                         pinmux_tristate_disable(PMUX_PINGRP_SDB);
175                         pinmux_tristate_disable(PMUX_PINGRP_SDC);
176                         pinmux_tristate_disable(PMUX_PINGRP_SDD);
177                         bad_config = 0;
178                         break;
179                 }
180                 break;
181
182         case PERIPH_ID_SDMMC4:
183                 switch (config) {
184                 case FUNCMUX_SDMMC4_ATC_ATD_8BIT:
185                         pinmux_set_func(PMUX_PINGRP_ATC, PMUX_FUNC_SDIO4);
186                         pinmux_set_func(PMUX_PINGRP_ATD, PMUX_FUNC_SDIO4);
187
188                         pinmux_tristate_disable(PMUX_PINGRP_ATC);
189                         pinmux_tristate_disable(PMUX_PINGRP_ATD);
190                         break;
191
192                 case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT:
193                         pinmux_set_func(PMUX_PINGRP_GME, PMUX_FUNC_SDIO4);
194                         pinmux_tristate_disable(PMUX_PINGRP_GME);
195                         /* fall through */
196
197                 case FUNCMUX_SDMMC4_ATB_GMA_4_BIT:
198                         pinmux_set_func(PMUX_PINGRP_ATB, PMUX_FUNC_SDIO4);
199                         pinmux_set_func(PMUX_PINGRP_GMA, PMUX_FUNC_SDIO4);
200
201                         pinmux_tristate_disable(PMUX_PINGRP_ATB);
202                         pinmux_tristate_disable(PMUX_PINGRP_GMA);
203                         bad_config = 0;
204                         break;
205                 }
206                 break;
207
208         case PERIPH_ID_KBC:
209                 if (config == FUNCMUX_DEFAULT) {
210                         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};
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                         }
221                 }
222                 break;
223
224         case PERIPH_ID_USB2:
225                 if (config == FUNCMUX_USB2_ULPI) {
226                         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);
229
230                         pinmux_tristate_disable(PMUX_PINGRP_UAA);
231                         pinmux_tristate_disable(PMUX_PINGRP_UAB);
232                         pinmux_tristate_disable(PMUX_PINGRP_UDA);
233                 }
234                 break;
235
236         case PERIPH_ID_SPI1:
237                 if (config == FUNCMUX_SPI1_GMC_GMD) {
238                         pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_SFLASH);
239                         pinmux_set_func(PMUX_PINGRP_GMD, PMUX_FUNC_SFLASH);
240
241                         pinmux_tristate_disable(PMUX_PINGRP_GMC);
242                         pinmux_tristate_disable(PMUX_PINGRP_GMD);
243                 }
244                 break;
245
246         case PERIPH_ID_NDFLASH:
247                 switch (config) {
248                 case FUNCMUX_NDFLASH_ATC:
249                         pinmux_set_func(PMUX_PINGRP_ATC, PMUX_FUNC_NAND);
250                         pinmux_tristate_disable(PMUX_PINGRP_ATC);
251                         break;
252                 case FUNCMUX_NDFLASH_KBC_8_BIT:
253                         pinmux_set_func(PMUX_PINGRP_KBCA, PMUX_FUNC_NAND);
254                         pinmux_set_func(PMUX_PINGRP_KBCB, 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);
259
260                         pinmux_tristate_disable(PMUX_PINGRP_KBCA);
261                         pinmux_tristate_disable(PMUX_PINGRP_KBCB);
262                         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);
266
267                         bad_config = 0;
268                         break;
269                 }
270                 break;
271         case PERIPH_ID_DISP1:
272                 if (config == FUNCMUX_DEFAULT) {
273                         int i;
274
275                         for (i = PMUX_PINGRP_LD0; i <= PMUX_PINGRP_LD17; i++) {
276                                 pinmux_set_func(i, PMUX_FUNC_DISPA);
277                                 pinmux_tristate_disable(i);
278                                 pinmux_set_pullupdown(i, PMUX_PULL_NORMAL);
279                         }
280                         pinmux_config_pingrp_table(disp1_default,
281                                                    ARRAY_SIZE(disp1_default));
282                 }
283                 break;
284
285         default:
286                 debug("%s: invalid periph_id %d", __func__, id);
287                 return -1;
288         }
289
290         if (bad_config) {
291                 debug("%s: invalid config %d for periph_id %d", __func__,
292                       config, id);
293                 return -1;
294         }
295
296         return 0;
297 }