blob: 2a3b004b049fd16bf1ebc6b5002e21c505e65e99 [file] [log] [blame]
Haavard Skinnemoenab0df362008-08-29 21:09:49 +02001/*
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 */
34void 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
62void 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
95void 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
133void 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
169void 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
189void 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