1 /*
2  * Copyright (C) 2006, 2008 Atmel Corporation
3  *
4  * See file CREDITS for list of people who contributed to this
5  * project.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of
10  * the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20  * MA 02111-1307 USA
21  */
22 #include <common.h>
23 
24 #include <asm/io.h>
25 
26 #include <asm/arch/chip-features.h>
27 #include <asm/arch/memory-map.h>
28 #include <asm/arch/portmux.h>
29 
30 /*
31  * Lots of small functions here. We depend on --gc-sections getting
32  * rid of the ones we don't need.
33  */
portmux_enable_ebi(unsigned int bus_width,unsigned int addr_width,unsigned long flags,unsigned long drive_strength)34 void portmux_enable_ebi(unsigned int bus_width, unsigned int addr_width,
35 		unsigned long flags, unsigned long drive_strength)
36 {
37 	unsigned long porte_mask = 0;
38 
39 	if (bus_width > 16)
40 		portmux_select_peripheral(PORTMUX_PORT_E, 0xffff,
41 				PORTMUX_FUNC_A, PORTMUX_BUSKEEPER);
42 	if (addr_width > 23)
43 		porte_mask |= (((1 << (addr_width - 23)) - 1) & 7) << 16;
44 	if (flags & PORTMUX_EBI_CS(2))
45 		porte_mask |= 1 << 25;
46 	if (flags & PORTMUX_EBI_CS(4))
47 		porte_mask |= 1 << 21;
48 	if (flags & PORTMUX_EBI_CS(5))
49 		porte_mask |= 1 << 22;
50 	if (flags & (PORTMUX_EBI_CF(0) | PORTMUX_EBI_CF(1)))
51 		porte_mask |= (1 << 19) | (1 << 20) | (1 << 23);
52 
53 	portmux_select_peripheral(PORTMUX_PORT_E, porte_mask,
54 			PORTMUX_FUNC_A, 0);
55 
56 	if (flags & PORTMUX_EBI_NWAIT)
57 		portmux_select_peripheral(PORTMUX_PORT_E, 1 << 24,
58 				PORTMUX_FUNC_A, PORTMUX_PULL_UP);
59 }
60 
61 #ifdef AT32AP700x_CHIP_HAS_MACB
portmux_enable_macb0(unsigned long flags,unsigned long drive_strength)62 void portmux_enable_macb0(unsigned long flags, unsigned long drive_strength)
63 {
64 	unsigned long portc_mask;
65 
66 	portc_mask = (1 << 3)	/* TXD0	*/
67 		| (1 << 4)	/* TXD1	*/
68 		| (1 << 7)	/* TXEN	*/
69 		| (1 << 8)	/* TXCK */
70 		| (1 << 9)	/* RXD0	*/
71 		| (1 << 10)	/* RXD1	*/
72 		| (1 << 13)	/* RXER	*/
73 		| (1 << 15)	/* RXDV	*/
74 		| (1 << 16)	/* MDC	*/
75 		| (1 << 17);	/* MDIO	*/
76 
77 	if (flags & PORTMUX_MACB_MII)
78 		portc_mask |= (1 << 0)	/* COL	*/
79 			| (1 << 1)	/* CRS	*/
80 			| (1 << 2)	/* TXER	*/
81 			| (1 << 5)	/* TXD2	*/
82 			| (1 << 6)	/* TXD3 */
83 			| (1 << 11)	/* RXD2	*/
84 			| (1 << 12)	/* RXD3	*/
85 			| (1 << 14);	/* RXCK	*/
86 
87 	if (flags & PORTMUX_MACB_SPEED)
88 		portc_mask |= (1 << 18);/* SPD	*/
89 
90 	/* REVISIT: Some pins are probably pure outputs */
91 	portmux_select_peripheral(PORTMUX_PORT_C, portc_mask,
92 			PORTMUX_FUNC_A, PORTMUX_BUSKEEPER);
93 }
94 
portmux_enable_macb1(unsigned long flags,unsigned long drive_strength)95 void portmux_enable_macb1(unsigned long flags, unsigned long drive_strength)
96 {
97 	unsigned long portc_mask = 0;
98 	unsigned long portd_mask;
99 
100 	portd_mask = (1 << 13)	/* TXD0	*/
101 		| (1 << 14)	/* TXD1	*/
102 		| (1 << 11)	/* TXEN	*/
103 		| (1 << 12)	/* TXCK */
104 		| (1 << 10)	/* RXD0	*/
105 		| (1 << 6)	/* RXD1	*/
106 		| (1 << 5)	/* RXER	*/
107 		| (1 << 4)	/* RXDV	*/
108 		| (1 << 3)	/* MDC	*/
109 		| (1 << 2);	/* MDIO	*/
110 
111 	if (flags & PORTMUX_MACB_MII)
112 		portc_mask = (1 << 19)	/* COL	*/
113 			| (1 << 23)	/* CRS	*/
114 			| (1 << 26)	/* TXER	*/
115 			| (1 << 27)	/* TXD2	*/
116 			| (1 << 28)	/* TXD3 */
117 			| (1 << 29)	/* RXD2	*/
118 			| (1 << 30)	/* RXD3	*/
119 			| (1 << 24);	/* RXCK	*/
120 
121 	if (flags & PORTMUX_MACB_SPEED)
122 		portd_mask |= (1 << 15);/* SPD	*/
123 
124 	/* REVISIT: Some pins are probably pure outputs */
125 	portmux_select_peripheral(PORTMUX_PORT_D, portc_mask,
126 			PORTMUX_FUNC_B, PORTMUX_BUSKEEPER);
127 	portmux_select_peripheral(PORTMUX_PORT_C, portc_mask,
128 			PORTMUX_FUNC_B, PORTMUX_BUSKEEPER);
129 }
130 #endif
131 
132 #ifdef AT32AP700x_CHIP_HAS_MMCI
portmux_enable_mmci(unsigned int slot,unsigned long flags,unsigned long drive_strength)133 void portmux_enable_mmci(unsigned int slot, unsigned long flags,
134 		unsigned long drive_strength)
135 {
136 	unsigned long mask;
137 	unsigned long portmux_flags = PORTMUX_PULL_UP;
138 
139 	/* First, the common CLK signal. It doesn't need a pull-up */
140 	portmux_select_peripheral(PORTMUX_PORT_A, 1 << 10,
141 			PORTMUX_FUNC_A, 0);
142 
143 	if (flags & PORTMUX_MMCI_EXT_PULLUP)
144 		portmux_flags = 0;
145 
146 	/* Then, the per-slot signals */
147 	switch (slot) {
148 	case 0:
149 		mask = (1 << 11) | (1 << 12);	/* CMD and DATA0 */
150 		if (flags & PORTMUX_MMCI_4BIT)
151 			/* DATA1..DATA3 */
152 			mask |= (1 << 13) | (1 << 14) | (1 << 15);
153 		portmux_select_peripheral(PORTMUX_PORT_A, mask,
154 				PORTMUX_FUNC_A, portmux_flags);
155 		break;
156 	case 1:
157 		mask = (1 << 6) | (1 << 7);	/* CMD and DATA0 */
158 		if (flags & PORTMUX_MMCI_4BIT)
159 			/* DATA1..DATA3 */
160 			mask |= (1 << 8) | (1 << 9) | (1 << 10);
161 		portmux_select_peripheral(PORTMUX_PORT_B, mask,
162 				PORTMUX_FUNC_B, portmux_flags);
163 		break;
164 	}
165 }
166 #endif
167 
168 #ifdef AT32AP700x_CHIP_HAS_SPI
portmux_enable_spi0(unsigned long cs_mask,unsigned long drive_strength)169 void portmux_enable_spi0(unsigned long cs_mask, unsigned long drive_strength)
170 {
171 	unsigned long pin_mask;
172 
173 	/* MOSI and SCK */
174 	portmux_select_peripheral(PORTMUX_PORT_A, (1 << 1) | (1 << 2),
175 			PORTMUX_FUNC_A, 0);
176 	/* MISO may float */
177 	portmux_select_peripheral(PORTMUX_PORT_A, 1 << 0,
178 			PORTMUX_FUNC_A, PORTMUX_BUSKEEPER);
179 
180 	/* Set up NPCSx as GPIO outputs, initially high */
181 	pin_mask = (cs_mask & 7) << 3;
182 	if (cs_mask & (1 << 3))
183 		pin_mask |= 1 << 20;
184 
185 	portmux_select_gpio(PORTMUX_PORT_A, pin_mask,
186 			PORTMUX_DIR_OUTPUT | PORTMUX_INIT_HIGH);
187 }
188 
portmux_enable_spi1(unsigned long cs_mask,unsigned long drive_strength)189 void portmux_enable_spi1(unsigned long cs_mask, unsigned long drive_strength)
190 {
191 	/* MOSI and SCK */
192 	portmux_select_peripheral(PORTMUX_PORT_B, (1 << 1) | (1 << 5),
193 			PORTMUX_FUNC_B, 0);
194 	/* MISO may float */
195 	portmux_select_peripheral(PORTMUX_PORT_B, 1 << 0,
196 			PORTMUX_FUNC_B, PORTMUX_BUSKEEPER);
197 
198 	/* Set up NPCSx as GPIO outputs, initially high */
199 	portmux_select_gpio(PORTMUX_PORT_B, (cs_mask & 7) << 2,
200 			PORTMUX_DIR_OUTPUT | PORTMUX_INIT_HIGH);
201 	portmux_select_gpio(PORTMUX_PORT_A, (cs_mask & 8) << (27 - 3),
202 			PORTMUX_DIR_OUTPUT | PORTMUX_INIT_HIGH);
203 }
204 #endif
205 
206 #ifdef AT32AP700x_CHIP_HAS_LCDC
portmux_enable_lcdc(int pin_config)207 void portmux_enable_lcdc(int pin_config)
208 {
209 	unsigned long portc_mask = 0;
210 	unsigned long portd_mask = 0;
211 	unsigned long porte_mask = 0;
212 
213 	switch (pin_config) {
214 	case 0:
215 		portc_mask = (1 << 19)	/* CC     */
216 			| (1 << 20)	/* HSYNC  */
217 			| (1 << 21)	/* PCLK   */
218 			| (1 << 22)	/* VSYNC  */
219 			| (1 << 23)	/* DVAL   */
220 			| (1 << 24)	/* MODE   */
221 			| (1 << 25)	/* PWR    */
222 			| (1 << 26)	/* DATA0  */
223 			| (1 << 27)	/* DATA1  */
224 			| (1 << 28)	/* DATA2  */
225 			| (1 << 29)	/* DATA3  */
226 			| (1 << 30)	/* DATA4  */
227 			| (1 << 31);	/* DATA5  */
228 
229 		portd_mask = (1 << 0)	/* DATA6  */
230 			| (1 << 1)	/* DATA7  */
231 			| (1 << 2)	/* DATA8  */
232 			| (1 << 3)	/* DATA9  */
233 			| (1 << 4)	/* DATA10 */
234 			| (1 << 5)	/* DATA11 */
235 			| (1 << 6)	/* DATA12 */
236 			| (1 << 7)	/* DATA13 */
237 			| (1 << 8)	/* DATA14 */
238 			| (1 << 9)	/* DATA15 */
239 			| (1 << 10)	/* DATA16 */
240 			| (1 << 11)	/* DATA17 */
241 			| (1 << 12)	/* DATA18 */
242 			| (1 << 13)	/* DATA19 */
243 			| (1 << 14)	/* DATA20 */
244 			| (1 << 15)	/* DATA21 */
245 			| (1 << 16)	/* DATA22 */
246 			| (1 << 17);	/* DATA23 */
247 		break;
248 
249 	case 1:
250 		portc_mask = (1 << 20)	/* HSYNC  */
251 			| (1 << 21)	/* PCLK   */
252 			| (1 << 22)	/* VSYNC  */
253 			| (1 << 25)	/* PWR    */
254 			| (1 << 31);	/* DATA5  */
255 
256 		portd_mask = (1 << 0)	/* DATA6  */
257 			| (1 << 1)	/* DATA7  */
258 			| (1 << 7)	/* DATA13 */
259 			| (1 << 8)	/* DATA14 */
260 			| (1 << 9)	/* DATA15 */
261 			| (1 << 16)	/* DATA22 */
262 			| (1 << 17);	/* DATA23 */
263 
264 		porte_mask = (1 << 0)	/* CC     */
265 			| (1 << 1)	/* DVAL   */
266 			| (1 << 2)	/* MODE   */
267 			| (1 << 3)	/* DATA0  */
268 			| (1 << 4)	/* DATA1  */
269 			| (1 << 5)	/* DATA2  */
270 			| (1 << 6)	/* DATA3  */
271 			| (1 << 7)	/* DATA4  */
272 			| (1 << 8)	/* DATA8  */
273 			| (1 << 9)	/* DATA9  */
274 			| (1 << 10)	/* DATA10 */
275 			| (1 << 11)	/* DATA11 */
276 			| (1 << 12)	/* DATA12 */
277 			| (1 << 13)	/* DATA16 */
278 			| (1 << 14)	/* DATA17 */
279 			| (1 << 15)	/* DATA18 */
280 			| (1 << 16)	/* DATA19 */
281 			| (1 << 17)	/* DATA20 */
282 			| (1 << 18);	/* DATA21 */
283 		break;
284 	}
285 
286 	/* REVISIT: Some pins are probably pure outputs */
287 	portmux_select_peripheral(PORTMUX_PORT_C, portc_mask,
288 			PORTMUX_FUNC_A, PORTMUX_BUSKEEPER);
289 	portmux_select_peripheral(PORTMUX_PORT_D, portd_mask,
290 			PORTMUX_FUNC_A, PORTMUX_BUSKEEPER);
291 	portmux_select_peripheral(PORTMUX_PORT_E, porte_mask,
292 			PORTMUX_FUNC_B, PORTMUX_BUSKEEPER);
293 }
294 #endif
295