avr32:portmux: fix setup for macb1
[karo-tx-uboot.git] / arch / avr32 / cpu / at32ap700x / portmux.c
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/hardware.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  */
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
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
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, portd_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
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
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
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
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