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