]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/tegra20-common/funcmux.c
Merge remote-tracking branch 'u-boot/master' into test
[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         {PMUX_PINGRP_##grp, PMUX_FUNC_##mux, PMUX_PULL_##pupd, PMUX_TRI_##tri}
18
19 static const struct pmux_pingrp_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(PMUX_PINGRP_IRRX, PMUX_FUNC_UARTA);
46                         pinmux_set_func(PMUX_PINGRP_IRTX, PMUX_FUNC_UARTA);
47                         pinmux_tristate_disable(PMUX_PINGRP_IRRX);
48                         pinmux_tristate_disable(PMUX_PINGRP_IRTX);
49                         break;
50                 case FUNCMUX_UART1_UAA_UAB:
51                         pinmux_set_func(PMUX_PINGRP_UAA, PMUX_FUNC_UARTA);
52                         pinmux_set_func(PMUX_PINGRP_UAB, PMUX_FUNC_UARTA);
53                         pinmux_tristate_disable(PMUX_PINGRP_UAA);
54                         pinmux_tristate_disable(PMUX_PINGRP_UAB);
55                         bad_config = 0;
56                         break;
57                 case FUNCMUX_UART1_GPU:
58                         pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_UARTA);
59                         pinmux_tristate_disable(PMUX_PINGRP_GPU);
60                         bad_config = 0;
61                         break;
62                 case FUNCMUX_UART1_SDIO1:
63                         pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_UARTA);
64                         pinmux_tristate_disable(PMUX_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(PMUX_PINGRP_SDB);
81                         pinmux_set_func(PMUX_PINGRP_SDB,  PMUX_FUNC_SDIO3);
82                 }
83                 break;
84
85         case PERIPH_ID_UART2:
86                 if (config == FUNCMUX_UART2_UAD) {
87                         pinmux_set_func(PMUX_PINGRP_UAD, PMUX_FUNC_UARTB);
88                         pinmux_tristate_disable(PMUX_PINGRP_UAD);
89                 }
90                 break;
91
92         case PERIPH_ID_UART4:
93                 if (config == FUNCMUX_UART4_GMC) {
94                         pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_UARTD);
95                         pinmux_tristate_disable(PMUX_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(PMUX_PINGRP_I2CP, PMUX_FUNC_I2C);
103                         pinmux_tristate_disable(PMUX_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(PMUX_PINGRP_RM, PMUX_FUNC_I2C);
111                         pinmux_tristate_disable(PMUX_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(PMUX_PINGRP_DDC, PMUX_FUNC_I2C2);
118                         /* PTA to HDMI */
119                         pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_HDMI);
120                         pinmux_tristate_disable(PMUX_PINGRP_DDC);
121                         break;
122                 case FUNCMUX_I2C2_PTA:  /* PTA pin group, select I2C2 */
123                         pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_I2C2);
124                         /* set DDC_SEL to RSVDx (RSVD2 works for now) */
125                         pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_RSVD2);
126                         pinmux_tristate_disable(PMUX_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(PMUX_PINGRP_DTF, PMUX_FUNC_I2C3);
135                         pinmux_tristate_disable(PMUX_PINGRP_DTF);
136                 }
137                 break;
138
139         case PERIPH_ID_SDMMC1:
140                 if (config == FUNCMUX_SDMMC1_SDIO1_4BIT) {
141                         pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_SDIO1);
142                         pinmux_tristate_disable(PMUX_PINGRP_SDIO1);
143                 }
144                 break;
145
146         case PERIPH_ID_SDMMC2:
147                 if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) {
148                         pinmux_set_func(PMUX_PINGRP_DTA, PMUX_FUNC_SDIO2);
149                         pinmux_set_func(PMUX_PINGRP_DTD, PMUX_FUNC_SDIO2);
150
151                         pinmux_tristate_disable(PMUX_PINGRP_DTA);
152                         pinmux_tristate_disable(PMUX_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(PMUX_PINGRP_SLXA, PMUX_FUNC_SDIO3);
160                         pinmux_set_func(PMUX_PINGRP_SLXC, PMUX_FUNC_SDIO3);
161                         pinmux_set_func(PMUX_PINGRP_SLXD, PMUX_FUNC_SDIO3);
162                         pinmux_set_func(PMUX_PINGRP_SLXK, PMUX_FUNC_SDIO3);
163
164                         pinmux_tristate_disable(PMUX_PINGRP_SLXA);
165                         pinmux_tristate_disable(PMUX_PINGRP_SLXC);
166                         pinmux_tristate_disable(PMUX_PINGRP_SLXD);
167                         pinmux_tristate_disable(PMUX_PINGRP_SLXK);
168                         /* fall through */
169
170                 case FUNCMUX_SDMMC3_SDB_4BIT:
171                         pinmux_set_func(PMUX_PINGRP_SDB, PMUX_FUNC_SDIO3);
172                         pinmux_set_func(PMUX_PINGRP_SDC, PMUX_FUNC_SDIO3);
173                         pinmux_set_func(PMUX_PINGRP_SDD, PMUX_FUNC_SDIO3);
174
175                         pinmux_tristate_disable(PMUX_PINGRP_SDB);
176                         pinmux_tristate_disable(PMUX_PINGRP_SDC);
177                         pinmux_tristate_disable(PMUX_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(PMUX_PINGRP_ATC, PMUX_FUNC_SDIO4);
187                         pinmux_set_func(PMUX_PINGRP_ATD, PMUX_FUNC_SDIO4);
188
189                         pinmux_tristate_disable(PMUX_PINGRP_ATC);
190                         pinmux_tristate_disable(PMUX_PINGRP_ATD);
191                         break;
192
193                 case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT:
194                         pinmux_set_func(PMUX_PINGRP_GME, PMUX_FUNC_SDIO4);
195                         pinmux_tristate_disable(PMUX_PINGRP_GME);
196                         /* fall through */
197
198                 case FUNCMUX_SDMMC4_ATB_GMA_4_BIT:
199                         pinmux_set_func(PMUX_PINGRP_ATB, PMUX_FUNC_SDIO4);
200                         pinmux_set_func(PMUX_PINGRP_GMA, PMUX_FUNC_SDIO4);
201
202                         pinmux_tristate_disable(PMUX_PINGRP_ATB);
203                         pinmux_tristate_disable(PMUX_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[] = {PMUX_PINGRP_KBCA,
212                                 PMUX_PINGRP_KBCB, PMUX_PINGRP_KBCC,
213                                 PMUX_PINGRP_KBCD, PMUX_PINGRP_KBCE,
214                                 PMUX_PINGRP_KBCF};
215                         int i;
216
217                         for (i = 0; i < ARRAY_SIZE(grp); i++) {
218                                 pinmux_tristate_disable(grp[i]);
219                                 pinmux_set_func(grp[i], PMUX_FUNC_KBC);
220                                 pinmux_set_pullupdown(grp[i], PMUX_PULL_UP);
221                         }
222                 }
223                 break;
224
225         case PERIPH_ID_USB2:
226                 if (config == FUNCMUX_USB2_ULPI) {
227                         pinmux_set_func(PMUX_PINGRP_UAA, PMUX_FUNC_ULPI);
228                         pinmux_set_func(PMUX_PINGRP_UAB, PMUX_FUNC_ULPI);
229                         pinmux_set_func(PMUX_PINGRP_UDA, PMUX_FUNC_ULPI);
230
231                         pinmux_tristate_disable(PMUX_PINGRP_UAA);
232                         pinmux_tristate_disable(PMUX_PINGRP_UAB);
233                         pinmux_tristate_disable(PMUX_PINGRP_UDA);
234                 }
235                 break;
236
237         case PERIPH_ID_SPI1:
238                 if (config == FUNCMUX_SPI1_GMC_GMD) {
239                         pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_SFLASH);
240                         pinmux_set_func(PMUX_PINGRP_GMD, PMUX_FUNC_SFLASH);
241
242                         pinmux_tristate_disable(PMUX_PINGRP_GMC);
243                         pinmux_tristate_disable(PMUX_PINGRP_GMD);
244                 }
245                 break;
246
247         case PERIPH_ID_NDFLASH:
248                 switch (config) {
249                 case FUNCMUX_NDFLASH_ATC:
250                         pinmux_set_func(PMUX_PINGRP_ATC, PMUX_FUNC_NAND);
251                         pinmux_tristate_disable(PMUX_PINGRP_ATC);
252                         break;
253                 case FUNCMUX_NDFLASH_KBC_8_BIT:
254                         pinmux_set_func(PMUX_PINGRP_KBCA, 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_KBCC);
262                         pinmux_tristate_disable(PMUX_PINGRP_KBCD);
263                         pinmux_tristate_disable(PMUX_PINGRP_KBCE);
264                         pinmux_tristate_disable(PMUX_PINGRP_KBCF);
265
266                         bad_config = 0;
267                         break;
268                 }
269                 break;
270         case PERIPH_ID_DISP1:
271                 if (config == FUNCMUX_DEFAULT) {
272                         int i;
273
274                         for (i = PMUX_PINGRP_LD0; i <= PMUX_PINGRP_LD17; i++) {
275                                 pinmux_set_func(i, PMUX_FUNC_DISPA);
276                                 pinmux_tristate_disable(i);
277                                 pinmux_set_pullupdown(i, PMUX_PULL_NORMAL);
278                         }
279                         pinmux_config_pingrp_table(disp1_default,
280                                                    ARRAY_SIZE(disp1_default));
281                 }
282                 break;
283
284         default:
285                 debug("%s: invalid periph_id %d", __func__, id);
286                 return -1;
287         }
288
289         if (bad_config) {
290                 debug("%s: invalid config %d for periph_id %d", __func__,
291                       config, id);
292                 return -1;
293         }
294
295         return 0;
296 }