]>
Commit | Line | Data |
---|---|---|
b5a5b351 SG |
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 | ||
00a2749d | 22 | /* Tegra20 high-level function multiplexing */ |
b5a5b351 SG |
23 | #include <common.h> |
24 | #include <asm/arch/clock.h> | |
2faf1863 | 25 | #include <asm/arch/funcmux.h> |
b5a5b351 SG |
26 | #include <asm/arch/pinmux.h> |
27 | ||
28 | int funcmux_select(enum periph_id id, int config) | |
29 | { | |
2faf1863 | 30 | int bad_config = config != FUNCMUX_DEFAULT; |
d693969d | 31 | |
b5a5b351 SG |
32 | switch (id) { |
33 | case PERIPH_ID_UART1: | |
b9607e70 SW |
34 | switch (config) { |
35 | case FUNCMUX_UART1_IRRX_IRTX: | |
d693969d SG |
36 | pinmux_set_func(PINGRP_IRRX, PMUX_FUNC_UARTA); |
37 | pinmux_set_func(PINGRP_IRTX, PMUX_FUNC_UARTA); | |
38 | pinmux_tristate_disable(PINGRP_IRRX); | |
39 | pinmux_tristate_disable(PINGRP_IRTX); | |
b9607e70 SW |
40 | break; |
41 | case FUNCMUX_UART1_UAA_UAB: | |
42 | pinmux_set_func(PINGRP_UAA, PMUX_FUNC_UARTA); | |
43 | pinmux_set_func(PINGRP_UAB, PMUX_FUNC_UARTA); | |
44 | pinmux_tristate_disable(PINGRP_UAA); | |
45 | pinmux_tristate_disable(PINGRP_UAB); | |
46 | bad_config = 0; | |
47 | break; | |
e21649be SW |
48 | case FUNCMUX_UART1_GPU: |
49 | pinmux_set_func(PINGRP_GPU, PMUX_FUNC_UARTA); | |
50 | pinmux_tristate_disable(PINGRP_GPU); | |
51 | bad_config = 0; | |
52 | break; | |
a2cfe63e LS |
53 | case FUNCMUX_UART1_SDIO1: |
54 | pinmux_set_func(PINGRP_SDIO1, PMUX_FUNC_UARTA); | |
55 | pinmux_tristate_disable(PINGRP_SDIO1); | |
56 | bad_config = 0; | |
57 | break; | |
b9607e70 SW |
58 | } |
59 | if (!bad_config) { | |
d693969d SG |
60 | /* |
61 | * Tegra appears to boot with function UARTA pre- | |
62 | * selected on mux group SDB. If two mux groups are | |
63 | * both set to the same function, it's unclear which | |
64 | * group's pins drive the RX signals into the HW. | |
65 | * For UARTA, SDB certainly overrides group IRTX in | |
66 | * practice. To solve this, configure some alternative | |
67 | * function on SDB to avoid the conflict. Also, tri- | |
68 | * state the group to avoid driving any signal onto it | |
69 | * until we know what's connected. | |
70 | */ | |
71 | pinmux_tristate_enable(PINGRP_SDB); | |
72 | pinmux_set_func(PINGRP_SDB, PMUX_FUNC_SDIO3); | |
73 | } | |
b5a5b351 SG |
74 | break; |
75 | ||
76 | case PERIPH_ID_UART2: | |
2faf1863 | 77 | if (config == FUNCMUX_UART2_IRDA) { |
d693969d SG |
78 | pinmux_set_func(PINGRP_UAD, PMUX_FUNC_IRDA); |
79 | pinmux_tristate_disable(PINGRP_UAD); | |
80 | } | |
b5a5b351 SG |
81 | break; |
82 | ||
83 | case PERIPH_ID_UART4: | |
2faf1863 | 84 | if (config == FUNCMUX_UART4_GMC) { |
d693969d SG |
85 | pinmux_set_func(PINGRP_GMC, PMUX_FUNC_UARTD); |
86 | pinmux_tristate_disable(PINGRP_GMC); | |
87 | } | |
b5a5b351 SG |
88 | break; |
89 | ||
8a1133c6 SG |
90 | case PERIPH_ID_DVC_I2C: |
91 | /* there is only one selection, pinmux_config is ignored */ | |
92 | if (config == FUNCMUX_DVC_I2CP) { | |
93 | pinmux_set_func(PINGRP_I2CP, PMUX_FUNC_I2C); | |
94 | pinmux_tristate_disable(PINGRP_I2CP); | |
95 | } | |
96 | break; | |
97 | ||
98 | case PERIPH_ID_I2C1: | |
99 | /* support pinmux_config of 0 for now, */ | |
100 | if (config == FUNCMUX_I2C1_RM) { | |
101 | pinmux_set_func(PINGRP_RM, PMUX_FUNC_I2C); | |
102 | pinmux_tristate_disable(PINGRP_RM); | |
103 | } | |
104 | break; | |
105 | case PERIPH_ID_I2C2: /* I2C2 */ | |
106 | switch (config) { | |
107 | case FUNCMUX_I2C2_DDC: /* DDC pin group, select I2C2 */ | |
108 | pinmux_set_func(PINGRP_DDC, PMUX_FUNC_I2C2); | |
109 | /* PTA to HDMI */ | |
110 | pinmux_set_func(PINGRP_PTA, PMUX_FUNC_HDMI); | |
111 | pinmux_tristate_disable(PINGRP_DDC); | |
112 | break; | |
113 | case FUNCMUX_I2C2_PTA: /* PTA pin group, select I2C2 */ | |
114 | pinmux_set_func(PINGRP_PTA, PMUX_FUNC_I2C2); | |
115 | /* set DDC_SEL to RSVDx (RSVD2 works for now) */ | |
116 | pinmux_set_func(PINGRP_DDC, PMUX_FUNC_RSVD2); | |
117 | pinmux_tristate_disable(PINGRP_PTA); | |
118 | bad_config = 0; | |
119 | break; | |
120 | } | |
121 | break; | |
122 | case PERIPH_ID_I2C3: /* I2C3 */ | |
123 | /* support pinmux_config of 0 for now */ | |
124 | if (config == FUNCMUX_I2C3_DTF) { | |
125 | pinmux_set_func(PINGRP_DTF, PMUX_FUNC_I2C3); | |
126 | pinmux_tristate_disable(PINGRP_DTF); | |
127 | } | |
128 | break; | |
129 | ||
d1e46079 SW |
130 | case PERIPH_ID_SDMMC1: |
131 | if (config == FUNCMUX_SDMMC1_SDIO1_4BIT) { | |
132 | pinmux_set_func(PINGRP_SDIO1, PMUX_FUNC_SDIO1); | |
133 | pinmux_tristate_disable(PINGRP_SDIO1); | |
134 | } | |
135 | break; | |
136 | ||
cf06b139 SG |
137 | case PERIPH_ID_SDMMC2: |
138 | if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) { | |
139 | pinmux_set_func(PINGRP_DTA, PMUX_FUNC_SDIO2); | |
140 | pinmux_set_func(PINGRP_DTD, PMUX_FUNC_SDIO2); | |
141 | ||
142 | pinmux_tristate_disable(PINGRP_DTA); | |
143 | pinmux_tristate_disable(PINGRP_DTD); | |
144 | } | |
145 | break; | |
146 | ||
147 | case PERIPH_ID_SDMMC3: | |
148 | switch (config) { | |
149 | case FUNCMUX_SDMMC3_SDB_SLXA_8BIT: | |
150 | pinmux_set_func(PINGRP_SLXA, PMUX_FUNC_SDIO3); | |
151 | pinmux_set_func(PINGRP_SLXC, PMUX_FUNC_SDIO3); | |
152 | pinmux_set_func(PINGRP_SLXD, PMUX_FUNC_SDIO3); | |
153 | pinmux_set_func(PINGRP_SLXK, PMUX_FUNC_SDIO3); | |
154 | ||
155 | pinmux_tristate_disable(PINGRP_SLXA); | |
156 | pinmux_tristate_disable(PINGRP_SLXC); | |
157 | pinmux_tristate_disable(PINGRP_SLXD); | |
158 | pinmux_tristate_disable(PINGRP_SLXK); | |
159 | /* fall through */ | |
160 | ||
161 | case FUNCMUX_SDMMC3_SDB_4BIT: | |
162 | pinmux_set_func(PINGRP_SDB, PMUX_FUNC_SDIO3); | |
163 | pinmux_set_func(PINGRP_SDC, PMUX_FUNC_SDIO3); | |
164 | pinmux_set_func(PINGRP_SDD, PMUX_FUNC_SDIO3); | |
165 | ||
166 | pinmux_tristate_disable(PINGRP_SDB); | |
167 | pinmux_tristate_disable(PINGRP_SDC); | |
168 | pinmux_tristate_disable(PINGRP_SDD); | |
169 | bad_config = 0; | |
170 | break; | |
171 | } | |
172 | break; | |
173 | ||
174 | case PERIPH_ID_SDMMC4: | |
175 | switch (config) { | |
176 | case FUNCMUX_SDMMC4_ATC_ATD_8BIT: | |
177 | pinmux_set_func(PINGRP_ATC, PMUX_FUNC_SDIO4); | |
178 | pinmux_set_func(PINGRP_ATD, PMUX_FUNC_SDIO4); | |
179 | ||
180 | pinmux_tristate_disable(PINGRP_ATC); | |
181 | pinmux_tristate_disable(PINGRP_ATD); | |
182 | break; | |
183 | ||
184 | case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT: | |
185 | pinmux_set_func(PINGRP_GME, PMUX_FUNC_SDIO4); | |
186 | pinmux_tristate_disable(PINGRP_GME); | |
187 | /* fall through */ | |
188 | ||
189 | case FUNCMUX_SDMMC4_ATB_GMA_4_BIT: | |
190 | pinmux_set_func(PINGRP_ATB, PMUX_FUNC_SDIO4); | |
191 | pinmux_set_func(PINGRP_GMA, PMUX_FUNC_SDIO4); | |
192 | ||
193 | pinmux_tristate_disable(PINGRP_ATB); | |
194 | pinmux_tristate_disable(PINGRP_GMA); | |
195 | bad_config = 0; | |
196 | break; | |
197 | } | |
198 | break; | |
199 | ||
7e91f40d SG |
200 | case PERIPH_ID_KBC: |
201 | if (config == FUNCMUX_DEFAULT) { | |
202 | enum pmux_pingrp grp[] = {PINGRP_KBCA, PINGRP_KBCB, | |
203 | PINGRP_KBCC, PINGRP_KBCD, PINGRP_KBCE, | |
204 | PINGRP_KBCF}; | |
205 | int i; | |
206 | ||
207 | for (i = 0; i < ARRAY_SIZE(grp); i++) { | |
208 | pinmux_tristate_disable(grp[i]); | |
209 | pinmux_set_func(grp[i], PMUX_FUNC_KBC); | |
210 | pinmux_set_pullupdown(grp[i], PMUX_PULL_UP); | |
211 | } | |
f97daaa2 LS |
212 | } |
213 | break; | |
7e91f40d | 214 | |
f97daaa2 LS |
215 | case PERIPH_ID_USB2: |
216 | if (config == FUNCMUX_USB2_ULPI) { | |
217 | pinmux_set_func(PINGRP_UAA, PMUX_FUNC_ULPI); | |
218 | pinmux_set_func(PINGRP_UAB, PMUX_FUNC_ULPI); | |
219 | pinmux_set_func(PINGRP_UDA, PMUX_FUNC_ULPI); | |
220 | ||
221 | pinmux_tristate_disable(PINGRP_UAA); | |
222 | pinmux_tristate_disable(PINGRP_UAB); | |
223 | pinmux_tristate_disable(PINGRP_UDA); | |
7e91f40d | 224 | } |
f97daaa2 | 225 | break; |
7e91f40d | 226 | |
a016e144 SW |
227 | case PERIPH_ID_SPI1: |
228 | if (config == FUNCMUX_SPI1_GMC_GMD) { | |
229 | pinmux_set_func(PINGRP_GMC, PMUX_FUNC_SFLASH); | |
230 | pinmux_set_func(PINGRP_GMD, PMUX_FUNC_SFLASH); | |
231 | ||
232 | pinmux_tristate_disable(PINGRP_GMC); | |
233 | pinmux_tristate_disable(PINGRP_GMD); | |
234 | } | |
235 | break; | |
236 | ||
b5a5b351 SG |
237 | default: |
238 | debug("%s: invalid periph_id %d", __func__, id); | |
239 | return -1; | |
240 | } | |
241 | ||
d693969d SG |
242 | if (bad_config) { |
243 | debug("%s: invalid config %d for periph_id %d", __func__, | |
244 | config, id); | |
245 | return -1; | |
246 | } | |
247 | ||
b5a5b351 SG |
248 | return 0; |
249 | } |