]>
Commit | Line | Data |
---|---|---|
2abbe075 WD |
1 | /* |
2 | * (C) Copyright 2003 | |
3 | * Author : Hamid Ikdoumi (Atmel) | |
4 | * | |
5 | * See file CREDITS for list of people who contributed to this | |
6 | * project. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License as | |
10 | * published by the Free Software Foundation; either version 2 of | |
11 | * the License, or (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | * MA 02111-1307 USA | |
22 | */ | |
23 | ||
24 | #include <at91rm9200_net.h> | |
25 | #include <net.h> | |
63ff004c | 26 | #include <miiphy.h> |
2abbe075 WD |
27 | |
28 | /* ----- Ethernet Buffer definitions ----- */ | |
29 | ||
30 | typedef struct { | |
31 | unsigned long addr, size; | |
32 | } rbf_t; | |
33 | ||
34 | #define RBF_ADDR 0xfffffffc | |
35 | #define RBF_OWNER (1<<0) | |
36 | #define RBF_WRAP (1<<1) | |
37 | #define RBF_BROADCAST (1<<31) | |
38 | #define RBF_MULTICAST (1<<30) | |
39 | #define RBF_UNICAST (1<<29) | |
40 | #define RBF_EXTERNAL (1<<28) | |
41 | #define RBF_UNKOWN (1<<27) | |
42 | #define RBF_SIZE 0x07ff | |
43 | #define RBF_LOCAL4 (1<<26) | |
44 | #define RBF_LOCAL3 (1<<25) | |
45 | #define RBF_LOCAL2 (1<<24) | |
46 | #define RBF_LOCAL1 (1<<23) | |
47 | ||
95f9dda2 | 48 | #define RBF_FRAMEMAX 64 |
2abbe075 WD |
49 | #define RBF_FRAMELEN 0x600 |
50 | ||
2abbe075 WD |
51 | #ifdef CONFIG_DRIVER_ETHER |
52 | ||
3a1ed1e1 | 53 | #if defined(CONFIG_CMD_NET) |
2abbe075 | 54 | |
95f9dda2 WD |
55 | /* alignment as per Errata #11 (64 bytes) is insufficient! */ |
56 | rbf_t rbfdt[RBF_FRAMEMAX] __attribute((aligned(512))); | |
57 | rbf_t *rbfp; | |
58 | ||
59 | unsigned char rbf_framebuf[RBF_FRAMEMAX][RBF_FRAMELEN] __attribute((aligned(4))); | |
60 | ||
2abbe075 | 61 | /* structure to interface the PHY */ |
429168ea | 62 | AT91S_PhyOps PhyOps; |
2abbe075 WD |
63 | |
64 | AT91PS_EMAC p_mac; | |
65 | ||
2abbe075 WD |
66 | /*********** EMAC Phy layer Management functions *************************/ |
67 | /* | |
8bde7f77 | 68 | * Name: |
2abbe075 | 69 | * at91rm9200_EmacEnableMDIO |
8bde7f77 | 70 | * Description: |
2abbe075 | 71 | * Enables the MDIO bit in MAC control register |
8bde7f77 | 72 | * Arguments: |
2abbe075 | 73 | * p_mac - pointer to struct AT91S_EMAC |
8bde7f77 | 74 | * Return value: |
2abbe075 WD |
75 | * none |
76 | */ | |
429168ea | 77 | void at91rm9200_EmacEnableMDIO (AT91PS_EMAC p_mac) |
2abbe075 WD |
78 | { |
79 | /* Mac CTRL reg set for MDIO enable */ | |
80 | p_mac->EMAC_CTL |= AT91C_EMAC_MPE; /* Management port enable */ | |
81 | } | |
82 | ||
83 | /* | |
8bde7f77 | 84 | * Name: |
2abbe075 | 85 | * at91rm9200_EmacDisableMDIO |
8bde7f77 | 86 | * Description: |
2abbe075 | 87 | * Disables the MDIO bit in MAC control register |
8bde7f77 | 88 | * Arguments: |
2abbe075 | 89 | * p_mac - pointer to struct AT91S_EMAC |
8bde7f77 | 90 | * Return value: |
2abbe075 WD |
91 | * none |
92 | */ | |
429168ea | 93 | void at91rm9200_EmacDisableMDIO (AT91PS_EMAC p_mac) |
2abbe075 WD |
94 | { |
95 | /* Mac CTRL reg set for MDIO disable */ | |
96 | p_mac->EMAC_CTL &= ~AT91C_EMAC_MPE; /* Management port disable */ | |
97 | } | |
98 | ||
99 | ||
100 | /* | |
8bde7f77 | 101 | * Name: |
2abbe075 | 102 | * at91rm9200_EmacReadPhy |
8bde7f77 | 103 | * Description: |
2abbe075 | 104 | * Reads data from the PHY register |
8bde7f77 | 105 | * Arguments: |
2abbe075 WD |
106 | * dev - pointer to struct net_device |
107 | * RegisterAddress - unsigned char | |
8bde7f77 WD |
108 | * pInput - pointer to value read from register |
109 | * Return value: | |
2abbe075 WD |
110 | * TRUE - if data read successfully |
111 | */ | |
429168ea | 112 | UCHAR at91rm9200_EmacReadPhy (AT91PS_EMAC p_mac, |
2abbe075 WD |
113 | unsigned char RegisterAddress, |
114 | unsigned short *pInput) | |
115 | { | |
116 | p_mac->EMAC_MAN = (AT91C_EMAC_HIGH & ~AT91C_EMAC_LOW) | | |
074cff0d WD |
117 | (AT91C_EMAC_RW_R) | |
118 | (RegisterAddress << 18) | | |
119 | (AT91C_EMAC_CODE_802_3); | |
2abbe075 WD |
120 | |
121 | udelay (10000); | |
122 | ||
123 | *pInput = (unsigned short) p_mac->EMAC_MAN; | |
124 | ||
125 | return TRUE; | |
126 | } | |
127 | ||
128 | ||
129 | /* | |
8bde7f77 | 130 | * Name: |
2abbe075 | 131 | * at91rm9200_EmacWritePhy |
8bde7f77 | 132 | * Description: |
2abbe075 | 133 | * Writes data to the PHY register |
8bde7f77 | 134 | * Arguments: |
2abbe075 WD |
135 | * dev - pointer to struct net_device |
136 | * RegisterAddress - unsigned char | |
8bde7f77 WD |
137 | * pOutput - pointer to value to be written in the register |
138 | * Return value: | |
2abbe075 WD |
139 | * TRUE - if data read successfully |
140 | */ | |
429168ea | 141 | UCHAR at91rm9200_EmacWritePhy (AT91PS_EMAC p_mac, |
a3ad8e26 WD |
142 | unsigned char RegisterAddress, |
143 | unsigned short *pOutput) | |
2abbe075 WD |
144 | { |
145 | p_mac->EMAC_MAN = (AT91C_EMAC_HIGH & ~AT91C_EMAC_LOW) | | |
146 | AT91C_EMAC_CODE_802_3 | AT91C_EMAC_RW_W | | |
a3ad8e26 | 147 | (RegisterAddress << 18) | *pOutput; |
2abbe075 WD |
148 | |
149 | udelay (10000); | |
150 | ||
151 | return TRUE; | |
152 | } | |
153 | ||
2abbe075 WD |
154 | int eth_init (bd_t * bd) |
155 | { | |
156 | int ret; | |
157 | int i; | |
158 | ||
159 | p_mac = AT91C_BASE_EMAC; | |
160 | ||
0b8fa03b WD |
161 | /* PIO Disable Register */ |
162 | *AT91C_PIOA_PDR = AT91C_PA16_EMDIO | AT91C_PA15_EMDC | AT91C_PA14_ERXER | | |
163 | AT91C_PA13_ERX1 | AT91C_PA12_ERX0 | AT91C_PA11_ECRS_ECRSDV | | |
164 | AT91C_PA10_ETX1 | AT91C_PA9_ETX0 | AT91C_PA8_ETXEN | | |
165 | AT91C_PA7_ETXCK_EREFCK; | |
2abbe075 | 166 | |
ea287deb WD |
167 | #ifdef CONFIG_AT91C_USE_RMII |
168 | *AT91C_PIOB_PDR = AT91C_PB19_ERXCK; | |
169 | *AT91C_PIOB_BSR = AT91C_PB19_ERXCK; | |
170 | #else | |
171 | *AT91C_PIOB_PDR = AT91C_PB19_ERXCK | AT91C_PB18_ECOL | AT91C_PB17_ERXDV | | |
0b8fa03b WD |
172 | AT91C_PB16_ERX3 | AT91C_PB15_ERX2 | AT91C_PB14_ETXER | |
173 | AT91C_PB13_ETX3 | AT91C_PB12_ETX2; | |
2abbe075 | 174 | |
0b8fa03b | 175 | /* Select B Register */ |
ea287deb | 176 | *AT91C_PIOB_BSR = AT91C_PB19_ERXCK | AT91C_PB18_ECOL | |
0b8fa03b WD |
177 | AT91C_PB17_ERXDV | AT91C_PB16_ERX3 | AT91C_PB15_ERX2 | |
178 | AT91C_PB14_ETXER | AT91C_PB13_ETX3 | AT91C_PB12_ETX2; | |
9d5028c2 | 179 | #endif |
2abbe075 WD |
180 | |
181 | *AT91C_PMC_PCER = 1 << AT91C_ID_EMAC; /* Peripheral Clock Enable Register */ | |
182 | ||
183 | p_mac->EMAC_CFG |= AT91C_EMAC_CSR; /* Clear statistics */ | |
184 | ||
185 | /* Init Ehternet buffers */ | |
2abbe075 | 186 | for (i = 0; i < RBF_FRAMEMAX; i++) { |
f57f70aa | 187 | rbfdt[i].addr = (unsigned long)rbf_framebuf[i]; |
2abbe075 WD |
188 | rbfdt[i].size = 0; |
189 | } | |
190 | rbfdt[RBF_FRAMEMAX - 1].addr |= RBF_WRAP; | |
191 | rbfp = &rbfdt[0]; | |
192 | ||
0b8fa03b WD |
193 | p_mac->EMAC_SA2L = (bd->bi_enetaddr[3] << 24) | (bd->bi_enetaddr[2] << 16) |
194 | | (bd->bi_enetaddr[1] << 8) | (bd->bi_enetaddr[0]); | |
195 | p_mac->EMAC_SA2H = (bd->bi_enetaddr[5] << 8) | (bd->bi_enetaddr[4]); | |
196 | ||
197 | p_mac->EMAC_RBQP = (long) (&rbfdt[0]); | |
198 | p_mac->EMAC_RSR &= ~(AT91C_EMAC_RSR_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA); | |
199 | ||
200 | p_mac->EMAC_CFG = (p_mac->EMAC_CFG | AT91C_EMAC_CAF | AT91C_EMAC_NBC) | |
201 | & ~AT91C_EMAC_CLK; | |
202 | ||
203 | #ifdef CONFIG_AT91C_USE_RMII | |
204 | p_mac->EMAC_CFG |= AT91C_EMAC_RMII; | |
205 | #endif | |
206 | ||
ba83a307 WD |
207 | #if (AT91C_MASTER_CLOCK > 40000000) |
208 | /* MDIO clock must not exceed 2.5 MHz, so enable MCK divider */ | |
209 | p_mac->EMAC_CFG |= AT91C_EMAC_CLK_HCLK_64; | |
210 | #endif | |
211 | ||
0b8fa03b WD |
212 | p_mac->EMAC_CTL |= AT91C_EMAC_TE | AT91C_EMAC_RE; |
213 | ||
080bdb7f | 214 | at91rm9200_GetPhyInterface (& PhyOps); |
2abbe075 | 215 | |
429168ea | 216 | if (!PhyOps.IsPhyConnected (p_mac)) |
2abbe075 WD |
217 | printf ("PHY not connected!!\n\r"); |
218 | ||
219 | /* MII management start from here */ | |
220 | if (!(p_mac->EMAC_SR & AT91C_EMAC_LINK)) { | |
429168ea | 221 | if (!(ret = PhyOps.Init (p_mac))) { |
2abbe075 WD |
222 | printf ("MAC: error during MII initialization\n"); |
223 | return 0; | |
224 | } | |
225 | } else { | |
226 | printf ("No link\n\r"); | |
227 | return 0; | |
228 | } | |
229 | ||
2abbe075 WD |
230 | return 0; |
231 | } | |
232 | ||
233 | int eth_send (volatile void *packet, int length) | |
234 | { | |
235 | while (!(p_mac->EMAC_TSR & AT91C_EMAC_BNQ)); | |
236 | p_mac->EMAC_TAR = (long) packet; | |
237 | p_mac->EMAC_TCR = length; | |
238 | while (p_mac->EMAC_TCR & 0x7ff); | |
239 | p_mac->EMAC_TSR |= AT91C_EMAC_COMP; | |
240 | return 0; | |
241 | } | |
242 | ||
243 | int eth_rx (void) | |
244 | { | |
245 | int size; | |
246 | ||
247 | if (!(rbfp->addr & RBF_OWNER)) | |
248 | return 0; | |
249 | ||
250 | size = rbfp->size & RBF_SIZE; | |
251 | NetReceive ((volatile uchar *) (rbfp->addr & RBF_ADDR), size); | |
252 | ||
253 | rbfp->addr &= ~RBF_OWNER; | |
254 | if (rbfp->addr & RBF_WRAP) | |
255 | rbfp = &rbfdt[0]; | |
256 | else | |
257 | rbfp++; | |
258 | ||
259 | p_mac->EMAC_RSR |= AT91C_EMAC_REC; | |
260 | ||
261 | return size; | |
262 | } | |
263 | ||
264 | void eth_halt (void) | |
265 | { | |
266 | }; | |
074cff0d | 267 | |
3a1ed1e1 | 268 | #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) |
63ff004c MB |
269 | int at91rm9200_miiphy_read(char *devname, unsigned char addr, |
270 | unsigned char reg, unsigned short * value) | |
074cff0d WD |
271 | { |
272 | at91rm9200_EmacEnableMDIO (p_mac); | |
273 | at91rm9200_EmacReadPhy (p_mac, reg, value); | |
274 | at91rm9200_EmacDisableMDIO (p_mac); | |
275 | return 0; | |
276 | } | |
277 | ||
63ff004c MB |
278 | int at91rm9200_miiphy_write(char *devname, unsigned char addr, |
279 | unsigned char reg, unsigned short value) | |
074cff0d WD |
280 | { |
281 | at91rm9200_EmacEnableMDIO (p_mac); | |
282 | at91rm9200_EmacWritePhy (p_mac, reg, &value); | |
283 | at91rm9200_EmacDisableMDIO (p_mac); | |
284 | return 0; | |
285 | } | |
63ff004c | 286 | |
3a1ed1e1 | 287 | #endif |
63ff004c MB |
288 | |
289 | int at91rm9200_miiphy_initialize(bd_t *bis) | |
290 | { | |
3a1ed1e1 | 291 | #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) |
63ff004c MB |
292 | miiphy_register("at91rm9200phy", at91rm9200_miiphy_read, at91rm9200_miiphy_write); |
293 | #endif | |
294 | return 0; | |
295 | } | |
074cff0d | 296 | |
3a1ed1e1 | 297 | #endif |
074cff0d | 298 | |
2abbe075 | 299 | #endif /* CONFIG_DRIVER_ETHER */ |