]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/tegra20-common/funcmux.c
sandbox: ignore sandbox.dtb
[karo-tx-uboot.git] / arch / arm / cpu / tegra20-common / funcmux.c
1 /*
2  * Copyright (c) 2011 The Chromium OS Authors.
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6
7 /* Tegra20 high-level function multiplexing */
8 #include <common.h>
9 #include <asm/arch/clock.h>
10 #include <asm/arch/funcmux.h>
11 #include <asm/arch/pinmux.h>
12
13 /*
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
19 static const struct pingroup_config disp1_default[] = {
20         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
37 int funcmux_select(enum periph_id id, int config)
38 {
39         int bad_config = config != FUNCMUX_DEFAULT;
40
41         switch (id) {
42         case PERIPH_ID_UART1:
43                 switch (config) {
44                 case FUNCMUX_UART1_IRRX_IRTX:
45                         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);
49                         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;
57                 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;
62                 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;
67                 }
68                 if (!bad_config) {
69                         /*
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                 }
83                 break;
84
85         case PERIPH_ID_UART2:
86                 if (config == FUNCMUX_UART2_UAD) {
87                         pinmux_set_func(PINGRP_UAD, PMUX_FUNC_UARTB);
88                         pinmux_tristate_disable(PINGRP_UAD);
89                 }
90                 break;
91
92         case PERIPH_ID_UART4:
93                 if (config == FUNCMUX_UART4_GMC) {
94                         pinmux_set_func(PINGRP_GMC, PMUX_FUNC_UARTD);
95                         pinmux_tristate_disable(PINGRP_GMC);
96                 }
97                 break;
98
99         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
139         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
146         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
209         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                         }
221                 }
222                 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;
235
236         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
246         case PERIPH_ID_NDFLASH:
247                 switch (config) {
248                 case FUNCMUX_NDFLASH_ATC:
249                         pinmux_set_func(PINGRP_ATC, PMUX_FUNC_NAND);
250                         pinmux_tristate_disable(PINGRP_ATC);
251                         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;
267                 }
268                 break;
269         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                         }
278                         pinmux_config_table(disp1_default,
279                                             ARRAY_SIZE(disp1_default));
280                 }
281                 break;
282
283         default:
284                 debug("%s: invalid periph_id %d", __func__, id);
285                 return -1;
286         }
287
288         if (bad_config) {
289                 debug("%s: invalid config %d for periph_id %d", __func__,
290                       config, id);
291                 return -1;
292         }
293
294         return 0;
295 }