]> git.sur5r.net Git - u-boot/blob - cpu/coldfire/fec.c
* Cleanup lowboot code for MPC5200
[u-boot] / cpu / coldfire / fec.c
1 /*
2  * (C) Copyright 2000
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
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 <common.h>
25 #include <commproc.h>
26 #include <net.h>
27 #include <command.h>
28
29
30 /**************************************************************
31  *
32  * FEC Ethernet Initialization Routine
33  *
34  *************************************************************/
35
36 #define FEC_ECNTRL_ETHER_EN     0x00000002
37 #define FEC_ECNTRL_RESET        0x00000001
38
39 #define FEC_RCNTRL_BC_REJ       0x00000010
40 #define FEC_RCNTRL_PROM         0x00000008
41 #define FEC_RCNTRL_MII_MODE     0x00000004
42 #define FEC_RCNTRL_DRT          0x00000002
43 #define FEC_RCNTRL_LOOP         0x00000001
44
45 #define FEC_TCNTRL_FDEN         0x00000004
46 #define FEC_TCNTRL_HBC          0x00000002
47 #define FEC_TCNTRL_GTS          0x00000001
48
49 #define FEC_RESET_DELAY         50000
50
51
52 /* Ethernet Transmit and Receive Buffers */
53 #define DBUF_LENGTH  1520
54 #define TX_BUF_CNT 2
55 #define TOUT_LOOP 100
56
57 #define PKT_MAXBUF_SIZE         1518
58 #define PKT_MINBUF_SIZE         64
59 #define PKT_MAXBLR_SIZE         1520
60
61
62 #ifdef CONFIG_M5272
63 #define FEC_ADDR 0x10000840
64 #endif
65 #ifdef CONFIG_M5282
66 #define FEC_ADDR 0x40001000
67 #endif
68
69 #undef  ET_DEBUG
70
71 #if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(FEC_ENET)
72
73
74 static char txbuf[DBUF_LENGTH];
75
76 static uint rxIdx;              /* index of the current RX buffer */
77 static uint txIdx;              /* index of the current TX buffer */
78
79 /*
80   * FEC Ethernet Tx and Rx buffer descriptors allocated at the
81   *  immr->udata_bd address on Dual-Port RAM
82   * Provide for Double Buffering
83   */
84
85 typedef volatile struct CommonBufferDescriptor {
86         cbd_t rxbd[PKTBUFSRX];  /* Rx BD */
87         cbd_t txbd[TX_BUF_CNT]; /* Tx BD */
88 } RTXBD;
89
90 static RTXBD *rtx = 0x380000;
91
92
93 int eth_send (volatile void *packet, int length)
94 {
95         int j, rc;
96         volatile fec_t *fecp = FEC_ADDR;
97
98         /* section 16.9.23.3
99          * Wait for ready
100          */
101         j = 0;
102         while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY)
103                && (j < TOUT_LOOP)) {
104                 udelay (1);
105                 j++;
106         }
107         if (j >= TOUT_LOOP) {
108                 printf ("TX not ready\n");
109         }
110
111         rtx->txbd[txIdx].cbd_bufaddr = (uint) packet;
112         rtx->txbd[txIdx].cbd_datlen = length;
113         rtx->txbd[txIdx].cbd_sc |= BD_ENET_TX_READY | BD_ENET_TX_LAST;
114
115         /* Activate transmit Buffer Descriptor polling */
116         fecp->fec_x_des_active = 0x01000000;    /* Descriptor polling active    */
117
118         j = 0;
119         while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY)
120                && (j < TOUT_LOOP)) {
121                 udelay (1);
122                 j++;
123         }
124         if (j >= TOUT_LOOP) {
125                 printf ("TX timeout\n");
126         }
127 #ifdef ET_DEBUG
128         printf ("%s[%d] %s: cycles: %d    status: %x  retry cnt: %d\n",
129                 __FILE__, __LINE__, __FUNCTION__, j, rtx->txbd[txIdx].cbd_sc,
130                 (rtx->txbd[txIdx].cbd_sc & 0x003C) >> 2);
131 #endif
132         /* return only status bits */ ;
133         rc = (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_STATS);
134
135         txIdx = (txIdx + 1) % TX_BUF_CNT;
136
137         return rc;
138 }
139
140 int eth_rx (void)
141 {
142         int length;
143         volatile fec_t *fecp = FEC_ADDR;
144
145         for (;;) {
146                 /* section 16.9.23.2 */
147                 if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
148                         length = -1;
149                         break;  /* nothing received - leave for() loop */
150                 }
151
152                 length = rtx->rxbd[rxIdx].cbd_datlen;
153
154                 if (rtx->rxbd[rxIdx].cbd_sc & 0x003f) {
155 #ifdef ET_DEBUG
156                         printf ("%s[%d] err: %x\n",
157                                 __FUNCTION__, __LINE__,
158                                 rtx->rxbd[rxIdx].cbd_sc);
159 #endif
160                 } else {
161                         /* Pass the packet up to the protocol layers. */
162                         NetReceive (NetRxPackets[rxIdx], length - 4);
163                 }
164
165                 /* Give the buffer back to the FEC. */
166                 rtx->rxbd[rxIdx].cbd_datlen = 0;
167
168                 /* wrap around buffer index when necessary */
169                 if ((rxIdx + 1) >= PKTBUFSRX) {
170                         rtx->rxbd[PKTBUFSRX - 1].cbd_sc =
171                                 (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
172                         rxIdx = 0;
173                 } else {
174                         rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
175                         rxIdx++;
176                 }
177
178                 /* Try to fill Buffer Descriptors */
179                 fecp->fec_r_des_active = 0x01000000;    /* Descriptor polling active    */
180         }
181
182         return length;
183 }
184
185
186 int eth_init (bd_t * bd)
187 {
188
189         int i;
190         volatile fec_t *fecp = FEC_ADDR;
191
192         /* Whack a reset.
193          * A delay is required between a reset of the FEC block and
194          * initialization of other FEC registers because the reset takes
195          * some time to complete. If you don't delay, subsequent writes
196          * to FEC registers might get killed by the reset routine which is
197          * still in progress.
198          */
199
200         fecp->fec_ecntrl = FEC_ECNTRL_RESET;
201         for (i = 0;
202              (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY);
203              ++i) {
204                 udelay (1);
205         }
206         if (i == FEC_RESET_DELAY) {
207                 printf ("FEC_RESET_DELAY timeout\n");
208                 return 0;
209         }
210
211         /* We use strictly polling mode only
212          */
213         fecp->fec_imask = 0;
214
215         /* Clear any pending interrupt */
216         fecp->fec_ievent = 0xffffffff;
217
218         /* Set station address   */
219 #define ea bd->bi_enetaddr
220         fecp->fec_addr_low = (ea[0] << 24) | (ea[1] << 16) |
221                 (ea[2] << 8) | (ea[3]);
222         fecp->fec_addr_high = (ea[4] << 24) | (ea[5] << 16);
223 #undef ea
224
225         /* Clear multicast address hash table
226          */
227         fecp->fec_hash_table_high = 0;
228         fecp->fec_hash_table_low = 0;
229
230         /* Set maximum receive buffer size.
231          */
232         fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
233
234         /*
235          * Setup Buffers and Buffer Desriptors
236          */
237         rxIdx = 0;
238         txIdx = 0;
239
240         /*
241          * Setup Receiver Buffer Descriptors (13.14.24.18)
242          * Settings:
243          *     Empty, Wrap
244          */
245         for (i = 0; i < PKTBUFSRX; i++) {
246                 rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
247                 rtx->rxbd[i].cbd_datlen = 0;    /* Reset */
248                 rtx->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i];
249         }
250         rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
251
252         /*
253          * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)
254          * Settings:
255          *    Last, Tx CRC
256          */
257         for (i = 0; i < TX_BUF_CNT; i++) {
258                 rtx->txbd[i].cbd_sc = BD_ENET_TX_LAST | BD_ENET_TX_TC;
259                 rtx->txbd[i].cbd_datlen = 0;    /* Reset */
260                 rtx->txbd[i].cbd_bufaddr = (uint) (&txbuf[0]);
261         }
262         rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
263
264         /* Set receive and transmit descriptor base
265          */
266         fecp->fec_r_des_start = (unsigned int) (&rtx->rxbd[0]);
267         fecp->fec_x_des_start = (unsigned int) (&rtx->txbd[0]);
268
269         /* Enable MII mode
270          */
271
272         /* Half duplex mode */
273         fecp->fec_r_cntrl = (PKT_MAXBUF_SIZE << 16) | FEC_RCNTRL_MII_MODE;
274         fecp->fec_r_cntrl = (PKT_MAXBUF_SIZE << 16) | FEC_RCNTRL_MII_MODE;
275         fecp->fec_x_cntrl = 0;
276
277         fecp->fec_mii_speed = 0;
278
279         /* Now enable the transmit and receive processing
280          */
281         fecp->fec_ecntrl = FEC_ECNTRL_ETHER_EN;
282
283         /* And last, try to fill Rx Buffer Descriptors */
284         fecp->fec_r_des_active = 0x01000000;    /* Descriptor polling active    */
285
286         return 1;
287 }
288
289
290 void eth_halt (void)
291 {
292         volatile fec_t *fecp = FEC_ADDR;
293
294         fecp->fec_ecntrl = 0;
295 }
296 #endif