]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/tegra20-common/funcmux.c
Merge branch 'master' of git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / arch / arm / cpu / tegra20-common / funcmux.c
1 /*
2  * Copyright (c) 2011 The Chromium OS Authors.
3  * See file CREDITS for list of people who contributed to this
4  * project.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
19  * MA 02111-1307 USA
20  */
21
22 /* Tegra20 high-level function multiplexing */
23 #include <common.h>
24 #include <asm/arch/clock.h>
25 #include <asm/arch/funcmux.h>
26 #include <asm/arch/pinmux.h>
27
28 /*
29  * The PINMUX macro is used to set up pinmux tables.
30  */
31 #define PINMUX(grp, mux, pupd, tri)                   \
32         {PINGRP_##grp, PMUX_FUNC_##mux, PMUX_PULL_##pupd, PMUX_TRI_##tri}
33
34 static const struct pingroup_config disp1_default[] = {
35         PINMUX(LDI,   DISPA,      NORMAL,    NORMAL),
36         PINMUX(LHP0,  DISPA,      NORMAL,    NORMAL),
37         PINMUX(LHP1,  DISPA,      NORMAL,    NORMAL),
38         PINMUX(LHP2,  DISPA,      NORMAL,    NORMAL),
39         PINMUX(LHS,   DISPA,      NORMAL,    NORMAL),
40         PINMUX(LM0,   RSVD4,      NORMAL,    NORMAL),
41         PINMUX(LPP,   DISPA,      NORMAL,    NORMAL),
42         PINMUX(LPW0,  DISPA,      NORMAL,    NORMAL),
43         PINMUX(LPW2,  DISPA,      NORMAL,    NORMAL),
44         PINMUX(LSC0,  DISPA,      NORMAL,    NORMAL),
45         PINMUX(LSPI,  DISPA,      NORMAL,    NORMAL),
46         PINMUX(LVP1,  DISPA,      NORMAL,    NORMAL),
47         PINMUX(LVS,   DISPA,      NORMAL,    NORMAL),
48         PINMUX(SLXD,  SPDIF,      NORMAL,    NORMAL),
49 };
50
51
52 int funcmux_select(enum periph_id id, int config)
53 {
54         int bad_config = config != FUNCMUX_DEFAULT;
55
56         switch (id) {
57         case PERIPH_ID_UART1:
58                 switch (config) {
59                 case FUNCMUX_UART1_IRRX_IRTX:
60                         pinmux_set_func(PINGRP_IRRX, PMUX_FUNC_UARTA);
61                         pinmux_set_func(PINGRP_IRTX, PMUX_FUNC_UARTA);
62                         pinmux_tristate_disable(PINGRP_IRRX);
63                         pinmux_tristate_disable(PINGRP_IRTX);
64                         break;
65                 case FUNCMUX_UART1_UAA_UAB:
66                         pinmux_set_func(PINGRP_UAA, PMUX_FUNC_UARTA);
67                         pinmux_set_func(PINGRP_UAB, PMUX_FUNC_UARTA);
68                         pinmux_tristate_disable(PINGRP_UAA);
69                         pinmux_tristate_disable(PINGRP_UAB);
70                         bad_config = 0;
71                         break;
72                 case FUNCMUX_UART1_GPU:
73                         pinmux_set_func(PINGRP_GPU, PMUX_FUNC_UARTA);
74                         pinmux_tristate_disable(PINGRP_GPU);
75                         bad_config = 0;
76                         break;
77                 case FUNCMUX_UART1_SDIO1:
78                         pinmux_set_func(PINGRP_SDIO1, PMUX_FUNC_UARTA);
79                         pinmux_tristate_disable(PINGRP_SDIO1);
80                         bad_config = 0;
81                         break;
82                 }
83                 if (!bad_config) {
84                         /*
85                          * Tegra appears to boot with function UARTA pre-
86                          * selected on mux group SDB. If two mux groups are
87                          * both set to the same function, it's unclear which
88                          * group's pins drive the RX signals into the HW.
89                          * For UARTA, SDB certainly overrides group IRTX in
90                          * practice. To solve this, configure some alternative
91                          * function on SDB to avoid the conflict. Also, tri-
92                          * state the group to avoid driving any signal onto it
93                          * until we know what's connected.
94                          */
95                         pinmux_tristate_enable(PINGRP_SDB);
96                         pinmux_set_func(PINGRP_SDB,  PMUX_FUNC_SDIO3);
97                 }
98                 break;
99
100         case PERIPH_ID_UART2:
101                 if (config == FUNCMUX_UART2_IRDA) {
102                         pinmux_set_func(PINGRP_UAD, PMUX_FUNC_IRDA);
103                         pinmux_tristate_disable(PINGRP_UAD);
104                 }
105                 break;
106
107         case PERIPH_ID_UART4:
108                 if (config == FUNCMUX_UART4_GMC) {
109                         pinmux_set_func(PINGRP_GMC, PMUX_FUNC_UARTD);
110                         pinmux_tristate_disable(PINGRP_GMC);
111                 }
112                 break;
113
114         case PERIPH_ID_DVC_I2C:
115                 /* there is only one selection, pinmux_config is ignored */
116                 if (config == FUNCMUX_DVC_I2CP) {
117                         pinmux_set_func(PINGRP_I2CP, PMUX_FUNC_I2C);
118                         pinmux_tristate_disable(PINGRP_I2CP);
119                 }
120                 break;
121
122         case PERIPH_ID_I2C1:
123                 /* support pinmux_config of 0 for now, */
124                 if (config == FUNCMUX_I2C1_RM) {
125                         pinmux_set_func(PINGRP_RM, PMUX_FUNC_I2C);
126                         pinmux_tristate_disable(PINGRP_RM);
127                 }
128                 break;
129         case PERIPH_ID_I2C2: /* I2C2 */
130                 switch (config) {
131                 case FUNCMUX_I2C2_DDC:  /* DDC pin group, select I2C2 */
132                         pinmux_set_func(PINGRP_DDC, PMUX_FUNC_I2C2);
133                         /* PTA to HDMI */
134                         pinmux_set_func(PINGRP_PTA, PMUX_FUNC_HDMI);
135                         pinmux_tristate_disable(PINGRP_DDC);
136                         break;
137                 case FUNCMUX_I2C2_PTA:  /* PTA pin group, select I2C2 */
138                         pinmux_set_func(PINGRP_PTA, PMUX_FUNC_I2C2);
139                         /* set DDC_SEL to RSVDx (RSVD2 works for now) */
140                         pinmux_set_func(PINGRP_DDC, PMUX_FUNC_RSVD2);
141                         pinmux_tristate_disable(PINGRP_PTA);
142                         bad_config = 0;
143                         break;
144                 }
145                 break;
146         case PERIPH_ID_I2C3: /* I2C3 */
147                 /* support pinmux_config of 0 for now */
148                 if (config == FUNCMUX_I2C3_DTF) {
149                         pinmux_set_func(PINGRP_DTF, PMUX_FUNC_I2C3);
150                         pinmux_tristate_disable(PINGRP_DTF);
151                 }
152                 break;
153
154         case PERIPH_ID_SDMMC1:
155                 if (config == FUNCMUX_SDMMC1_SDIO1_4BIT) {
156                         pinmux_set_func(PINGRP_SDIO1, PMUX_FUNC_SDIO1);
157                         pinmux_tristate_disable(PINGRP_SDIO1);
158                 }
159                 break;
160
161         case PERIPH_ID_SDMMC2:
162                 if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) {
163                         pinmux_set_func(PINGRP_DTA, PMUX_FUNC_SDIO2);
164                         pinmux_set_func(PINGRP_DTD, PMUX_FUNC_SDIO2);
165
166                         pinmux_tristate_disable(PINGRP_DTA);
167                         pinmux_tristate_disable(PINGRP_DTD);
168                 }
169                 break;
170
171         case PERIPH_ID_SDMMC3:
172                 switch (config) {
173                 case FUNCMUX_SDMMC3_SDB_SLXA_8BIT:
174                         pinmux_set_func(PINGRP_SLXA, PMUX_FUNC_SDIO3);
175                         pinmux_set_func(PINGRP_SLXC, PMUX_FUNC_SDIO3);
176                         pinmux_set_func(PINGRP_SLXD, PMUX_FUNC_SDIO3);
177                         pinmux_set_func(PINGRP_SLXK, PMUX_FUNC_SDIO3);
178
179                         pinmux_tristate_disable(PINGRP_SLXA);
180                         pinmux_tristate_disable(PINGRP_SLXC);
181                         pinmux_tristate_disable(PINGRP_SLXD);
182                         pinmux_tristate_disable(PINGRP_SLXK);
183                         /* fall through */
184
185                 case FUNCMUX_SDMMC3_SDB_4BIT:
186                         pinmux_set_func(PINGRP_SDB, PMUX_FUNC_SDIO3);
187                         pinmux_set_func(PINGRP_SDC, PMUX_FUNC_SDIO3);
188                         pinmux_set_func(PINGRP_SDD, PMUX_FUNC_SDIO3);
189
190                         pinmux_tristate_disable(PINGRP_SDB);
191                         pinmux_tristate_disable(PINGRP_SDC);
192                         pinmux_tristate_disable(PINGRP_SDD);
193                         bad_config = 0;
194                         break;
195                 }
196                 break;
197
198         case PERIPH_ID_SDMMC4:
199                 switch (config) {
200                 case FUNCMUX_SDMMC4_ATC_ATD_8BIT:
201                         pinmux_set_func(PINGRP_ATC, PMUX_FUNC_SDIO4);
202                         pinmux_set_func(PINGRP_ATD, PMUX_FUNC_SDIO4);
203
204                         pinmux_tristate_disable(PINGRP_ATC);
205                         pinmux_tristate_disable(PINGRP_ATD);
206                         break;
207
208                 case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT:
209                         pinmux_set_func(PINGRP_GME, PMUX_FUNC_SDIO4);
210                         pinmux_tristate_disable(PINGRP_GME);
211                         /* fall through */
212
213                 case FUNCMUX_SDMMC4_ATB_GMA_4_BIT:
214                         pinmux_set_func(PINGRP_ATB, PMUX_FUNC_SDIO4);
215                         pinmux_set_func(PINGRP_GMA, PMUX_FUNC_SDIO4);
216
217                         pinmux_tristate_disable(PINGRP_ATB);
218                         pinmux_tristate_disable(PINGRP_GMA);
219                         bad_config = 0;
220                         break;
221                 }
222                 break;
223
224         case PERIPH_ID_KBC:
225                 if (config == FUNCMUX_DEFAULT) {
226                         enum pmux_pingrp grp[] = {PINGRP_KBCA, PINGRP_KBCB,
227                                 PINGRP_KBCC, PINGRP_KBCD, PINGRP_KBCE,
228                                 PINGRP_KBCF};
229                         int i;
230
231                         for (i = 0; i < ARRAY_SIZE(grp); i++) {
232                                 pinmux_tristate_disable(grp[i]);
233                                 pinmux_set_func(grp[i], PMUX_FUNC_KBC);
234                                 pinmux_set_pullupdown(grp[i], PMUX_PULL_UP);
235                         }
236                 }
237                 break;
238
239         case PERIPH_ID_USB2:
240                 if (config == FUNCMUX_USB2_ULPI) {
241                         pinmux_set_func(PINGRP_UAA, PMUX_FUNC_ULPI);
242                         pinmux_set_func(PINGRP_UAB, PMUX_FUNC_ULPI);
243                         pinmux_set_func(PINGRP_UDA, PMUX_FUNC_ULPI);
244
245                         pinmux_tristate_disable(PINGRP_UAA);
246                         pinmux_tristate_disable(PINGRP_UAB);
247                         pinmux_tristate_disable(PINGRP_UDA);
248                 }
249                 break;
250
251         case PERIPH_ID_SPI1:
252                 if (config == FUNCMUX_SPI1_GMC_GMD) {
253                         pinmux_set_func(PINGRP_GMC, PMUX_FUNC_SFLASH);
254                         pinmux_set_func(PINGRP_GMD, PMUX_FUNC_SFLASH);
255
256                         pinmux_tristate_disable(PINGRP_GMC);
257                         pinmux_tristate_disable(PINGRP_GMD);
258                 }
259                 break;
260
261         case PERIPH_ID_NDFLASH:
262                 switch (config) {
263                 case FUNCMUX_NDFLASH_ATC:
264                         pinmux_set_func(PINGRP_ATC, PMUX_FUNC_NAND);
265                         pinmux_tristate_disable(PINGRP_ATC);
266                         break;
267                 case FUNCMUX_NDFLASH_KBC_8_BIT:
268                         pinmux_set_func(PINGRP_KBCA, PMUX_FUNC_NAND);
269                         pinmux_set_func(PINGRP_KBCC, PMUX_FUNC_NAND);
270                         pinmux_set_func(PINGRP_KBCD, PMUX_FUNC_NAND);
271                         pinmux_set_func(PINGRP_KBCE, PMUX_FUNC_NAND);
272                         pinmux_set_func(PINGRP_KBCF, PMUX_FUNC_NAND);
273
274                         pinmux_tristate_disable(PINGRP_KBCA);
275                         pinmux_tristate_disable(PINGRP_KBCC);
276                         pinmux_tristate_disable(PINGRP_KBCD);
277                         pinmux_tristate_disable(PINGRP_KBCE);
278                         pinmux_tristate_disable(PINGRP_KBCF);
279
280                         bad_config = 0;
281                         break;
282                 }
283                 break;
284         case PERIPH_ID_DISP1:
285                 if (config == FUNCMUX_DEFAULT) {
286                         int i;
287
288                         for (i = PINGRP_LD0; i <= PINGRP_LD17; i++) {
289                                 pinmux_set_func(i, PMUX_FUNC_DISPA);
290                                 pinmux_tristate_disable(i);
291                                 pinmux_set_pullupdown(i, PMUX_PULL_NORMAL);
292                         }
293                         pinmux_config_table(disp1_default,
294                                             ARRAY_SIZE(disp1_default));
295                 }
296                 break;
297
298         default:
299                 debug("%s: invalid periph_id %d", __func__, id);
300                 return -1;
301         }
302
303         if (bad_config) {
304                 debug("%s: invalid config %d for periph_id %d", __func__,
305                       config, id);
306                 return -1;
307         }
308
309         return 0;
310 }