Merge tag 'signed-efi-next' of git://github.com/agraf/u-boot
[oweals/u-boot.git] / drivers / net / mcffec.c
1 /*
2  * (C) Copyright 2000-2004
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * (C) Copyright 2007 Freescale Semiconductor, Inc.
6  * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
7  *
8  * SPDX-License-Identifier:     GPL-2.0+
9  */
10
11 #include <common.h>
12 #include <environment.h>
13 #include <malloc.h>
14
15 #include <command.h>
16 #include <net.h>
17 #include <netdev.h>
18 #include <miiphy.h>
19
20 #include <asm/fec.h>
21 #include <asm/immap.h>
22
23 #undef  ET_DEBUG
24 #undef  MII_DEBUG
25
26 /* Ethernet Transmit and Receive Buffers */
27 #define DBUF_LENGTH             1520
28 #define TX_BUF_CNT              2
29 #define PKT_MAXBUF_SIZE         1518
30 #define PKT_MINBUF_SIZE         64
31 #define PKT_MAXBLR_SIZE         1520
32 #define LAST_PKTBUFSRX          PKTBUFSRX - 1
33 #define BD_ENET_RX_W_E          (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY)
34 #define BD_ENET_TX_RDY_LST      (BD_ENET_TX_READY | BD_ENET_TX_LAST)
35
36 DECLARE_GLOBAL_DATA_PTR;
37
38 struct fec_info_s fec_info[] = {
39 #ifdef CONFIG_SYS_FEC0_IOBASE
40         {
41          0,                     /* index */
42          CONFIG_SYS_FEC0_IOBASE,        /* io base */
43          CONFIG_SYS_FEC0_PINMUX,        /* gpio pin muxing */
44          CONFIG_SYS_FEC0_MIIBASE,       /* mii base */
45          -1,                    /* phy_addr */
46          0,                     /* duplex and speed */
47          0,                     /* phy name */
48          0,                     /* phyname init */
49          0,                     /* RX BD */
50          0,                     /* TX BD */
51          0,                     /* rx Index */
52          0,                     /* tx Index */
53          0,                     /* tx buffer */
54          0,                     /* initialized flag */
55          (struct fec_info_s *)-1,
56          },
57 #endif
58 #ifdef CONFIG_SYS_FEC1_IOBASE
59         {
60          1,                     /* index */
61          CONFIG_SYS_FEC1_IOBASE,        /* io base */
62          CONFIG_SYS_FEC1_PINMUX,        /* gpio pin muxing */
63          CONFIG_SYS_FEC1_MIIBASE,       /* mii base */
64          -1,                    /* phy_addr */
65          0,                     /* duplex and speed */
66          0,                     /* phy name */
67          0,                     /* phy name init */
68 #ifdef CONFIG_SYS_FEC_BUF_USE_SRAM
69          (cbd_t *)DBUF_LENGTH,  /* RX BD */
70 #else
71          0,                     /* RX BD */
72 #endif
73          0,                     /* TX BD */
74          0,                     /* rx Index */
75          0,                     /* tx Index */
76          0,                     /* tx buffer */
77          0,                     /* initialized flag */
78          (struct fec_info_s *)-1,
79          }
80 #endif
81 };
82
83 int fec_recv(struct eth_device *dev);
84 int fec_init(struct eth_device *dev, bd_t * bd);
85 void fec_halt(struct eth_device *dev);
86 void fec_reset(struct eth_device *dev);
87
88 void setFecDuplexSpeed(volatile fec_t * fecp, bd_t * bd, int dup_spd)
89 {
90         if ((dup_spd >> 16) == FULL) {
91                 /* Set maximum frame length */
92                 fecp->rcr = FEC_RCR_MAX_FL(PKT_MAXBUF_SIZE) | FEC_RCR_MII_MODE |
93                     FEC_RCR_PROM | 0x100;
94                 fecp->tcr = FEC_TCR_FDEN;
95         } else {
96                 /* Half duplex mode */
97                 fecp->rcr = FEC_RCR_MAX_FL(PKT_MAXBUF_SIZE) |
98                     FEC_RCR_MII_MODE | FEC_RCR_DRT;
99                 fecp->tcr &= ~FEC_TCR_FDEN;
100         }
101
102         if ((dup_spd & 0xFFFF) == _100BASET) {
103 #ifdef CONFIG_MCF5445x
104                 fecp->rcr &= ~0x200;    /* disabled 10T base */
105 #endif
106 #ifdef MII_DEBUG
107                 printf("100Mbps\n");
108 #endif
109                 bd->bi_ethspeed = 100;
110         } else {
111 #ifdef CONFIG_MCF5445x
112                 fecp->rcr |= 0x200;     /* enabled 10T base */
113 #endif
114 #ifdef MII_DEBUG
115                 printf("10Mbps\n");
116 #endif
117                 bd->bi_ethspeed = 10;
118         }
119 }
120
121 static int fec_send(struct eth_device *dev, void *packet, int length)
122 {
123         struct fec_info_s *info = dev->priv;
124         volatile fec_t *fecp = (fec_t *) (info->iobase);
125         int j, rc;
126         u16 phyStatus;
127
128         miiphy_read(dev->name, info->phy_addr, MII_BMSR, &phyStatus);
129
130         /* section 16.9.23.3
131          * Wait for ready
132          */
133         j = 0;
134         while ((info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_READY) &&
135                (j < MCFFEC_TOUT_LOOP)) {
136                 udelay(1);
137                 j++;
138         }
139         if (j >= MCFFEC_TOUT_LOOP) {
140                 printf("TX not ready\n");
141         }
142
143         info->txbd[info->txIdx].cbd_bufaddr = (uint) packet;
144         info->txbd[info->txIdx].cbd_datlen = length;
145         info->txbd[info->txIdx].cbd_sc |= BD_ENET_TX_RDY_LST;
146
147         /* Activate transmit Buffer Descriptor polling */
148         fecp->tdar = 0x01000000;        /* Descriptor polling active    */
149
150 #ifndef CONFIG_SYS_FEC_BUF_USE_SRAM
151         /*
152          * FEC unable to initial transmit data packet.
153          * A nop will ensure the descriptor polling active completed.
154          * CF Internal RAM has shorter cycle access than DRAM. If use
155          * DRAM as Buffer descriptor and data, a nop is a must.
156          * Affect only V2 and V3.
157          */
158         __asm__ ("nop");
159
160 #endif
161
162 #ifdef CONFIG_SYS_UNIFY_CACHE
163         icache_invalid();
164 #endif
165
166         j = 0;
167         while ((info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_READY) &&
168                (j < MCFFEC_TOUT_LOOP)) {
169                 udelay(1);
170                 j++;
171         }
172         if (j >= MCFFEC_TOUT_LOOP) {
173                 printf("TX timeout\n");
174         }
175
176 #ifdef ET_DEBUG
177         printf("%s[%d] %s: cycles: %d    status: %x  retry cnt: %d\n",
178                __FILE__, __LINE__, __FUNCTION__, j,
179                info->txbd[info->txIdx].cbd_sc,
180                (info->txbd[info->txIdx].cbd_sc & 0x003C) >> 2);
181 #endif
182
183         /* return only status bits */
184         rc = (info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_STATS);
185         info->txIdx = (info->txIdx + 1) % TX_BUF_CNT;
186
187         return rc;
188 }
189
190 int fec_recv(struct eth_device *dev)
191 {
192         struct fec_info_s *info = dev->priv;
193         volatile fec_t *fecp = (fec_t *) (info->iobase);
194         int length;
195
196         for (;;) {
197 #ifndef CONFIG_SYS_FEC_BUF_USE_SRAM
198 #endif
199 #ifdef CONFIG_SYS_UNIFY_CACHE
200                 icache_invalid();
201 #endif
202                 /* section 16.9.23.2 */
203                 if (info->rxbd[info->rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
204                         length = -1;
205                         break;  /* nothing received - leave for() loop */
206                 }
207
208                 length = info->rxbd[info->rxIdx].cbd_datlen;
209
210                 if (info->rxbd[info->rxIdx].cbd_sc & 0x003f) {
211                         printf("%s[%d] err: %x\n",
212                                __FUNCTION__, __LINE__,
213                                info->rxbd[info->rxIdx].cbd_sc);
214 #ifdef ET_DEBUG
215                         printf("%s[%d] err: %x\n",
216                                __FUNCTION__, __LINE__,
217                                info->rxbd[info->rxIdx].cbd_sc);
218 #endif
219                 } else {
220
221                         length -= 4;
222                         /* Pass the packet up to the protocol layers. */
223                         net_process_received_packet(net_rx_packets[info->rxIdx],
224                                                     length);
225
226                         fecp->eir |= FEC_EIR_RXF;
227                 }
228
229                 /* Give the buffer back to the FEC. */
230                 info->rxbd[info->rxIdx].cbd_datlen = 0;
231
232                 /* wrap around buffer index when necessary */
233                 if (info->rxIdx == LAST_PKTBUFSRX) {
234                         info->rxbd[PKTBUFSRX - 1].cbd_sc = BD_ENET_RX_W_E;
235                         info->rxIdx = 0;
236                 } else {
237                         info->rxbd[info->rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
238                         info->rxIdx++;
239                 }
240
241                 /* Try to fill Buffer Descriptors */
242                 fecp->rdar = 0x01000000;        /* Descriptor polling active    */
243         }
244
245         return length;
246 }
247
248 #ifdef ET_DEBUG
249 void dbgFecRegs(struct eth_device *dev)
250 {
251         struct fec_info_s *info = dev->priv;
252         volatile fec_t *fecp = (fec_t *) (info->iobase);
253
254         printf("=====\n");
255         printf("ievent       %x - %x\n", (int)&fecp->eir, fecp->eir);
256         printf("imask        %x - %x\n", (int)&fecp->eimr, fecp->eimr);
257         printf("r_des_active %x - %x\n", (int)&fecp->rdar, fecp->rdar);
258         printf("x_des_active %x - %x\n", (int)&fecp->tdar, fecp->tdar);
259         printf("ecntrl       %x - %x\n", (int)&fecp->ecr, fecp->ecr);
260         printf("mii_mframe   %x - %x\n", (int)&fecp->mmfr, fecp->mmfr);
261         printf("mii_speed    %x - %x\n", (int)&fecp->mscr, fecp->mscr);
262         printf("mii_ctrlstat %x - %x\n", (int)&fecp->mibc, fecp->mibc);
263         printf("r_cntrl      %x - %x\n", (int)&fecp->rcr, fecp->rcr);
264         printf("x_cntrl      %x - %x\n", (int)&fecp->tcr, fecp->tcr);
265         printf("padr_l       %x - %x\n", (int)&fecp->palr, fecp->palr);
266         printf("padr_u       %x - %x\n", (int)&fecp->paur, fecp->paur);
267         printf("op_pause     %x - %x\n", (int)&fecp->opd, fecp->opd);
268         printf("iadr_u       %x - %x\n", (int)&fecp->iaur, fecp->iaur);
269         printf("iadr_l       %x - %x\n", (int)&fecp->ialr, fecp->ialr);
270         printf("gadr_u       %x - %x\n", (int)&fecp->gaur, fecp->gaur);
271         printf("gadr_l       %x - %x\n", (int)&fecp->galr, fecp->galr);
272         printf("x_wmrk       %x - %x\n", (int)&fecp->tfwr, fecp->tfwr);
273         printf("r_bound      %x - %x\n", (int)&fecp->frbr, fecp->frbr);
274         printf("r_fstart     %x - %x\n", (int)&fecp->frsr, fecp->frsr);
275         printf("r_drng       %x - %x\n", (int)&fecp->erdsr, fecp->erdsr);
276         printf("x_drng       %x - %x\n", (int)&fecp->etdsr, fecp->etdsr);
277         printf("r_bufsz      %x - %x\n", (int)&fecp->emrbr, fecp->emrbr);
278
279         printf("\n");
280         printf("rmon_t_drop        %x - %x\n", (int)&fecp->rmon_t_drop,
281                fecp->rmon_t_drop);
282         printf("rmon_t_packets     %x - %x\n", (int)&fecp->rmon_t_packets,
283                fecp->rmon_t_packets);
284         printf("rmon_t_bc_pkt      %x - %x\n", (int)&fecp->rmon_t_bc_pkt,
285                fecp->rmon_t_bc_pkt);
286         printf("rmon_t_mc_pkt      %x - %x\n", (int)&fecp->rmon_t_mc_pkt,
287                fecp->rmon_t_mc_pkt);
288         printf("rmon_t_crc_align   %x - %x\n", (int)&fecp->rmon_t_crc_align,
289                fecp->rmon_t_crc_align);
290         printf("rmon_t_undersize   %x - %x\n", (int)&fecp->rmon_t_undersize,
291                fecp->rmon_t_undersize);
292         printf("rmon_t_oversize    %x - %x\n", (int)&fecp->rmon_t_oversize,
293                fecp->rmon_t_oversize);
294         printf("rmon_t_frag        %x - %x\n", (int)&fecp->rmon_t_frag,
295                fecp->rmon_t_frag);
296         printf("rmon_t_jab         %x - %x\n", (int)&fecp->rmon_t_jab,
297                fecp->rmon_t_jab);
298         printf("rmon_t_col         %x - %x\n", (int)&fecp->rmon_t_col,
299                fecp->rmon_t_col);
300         printf("rmon_t_p64         %x - %x\n", (int)&fecp->rmon_t_p64,
301                fecp->rmon_t_p64);
302         printf("rmon_t_p65to127    %x - %x\n", (int)&fecp->rmon_t_p65to127,
303                fecp->rmon_t_p65to127);
304         printf("rmon_t_p128to255   %x - %x\n", (int)&fecp->rmon_t_p128to255,
305                fecp->rmon_t_p128to255);
306         printf("rmon_t_p256to511   %x - %x\n", (int)&fecp->rmon_t_p256to511,
307                fecp->rmon_t_p256to511);
308         printf("rmon_t_p512to1023  %x - %x\n", (int)&fecp->rmon_t_p512to1023,
309                fecp->rmon_t_p512to1023);
310         printf("rmon_t_p1024to2047 %x - %x\n", (int)&fecp->rmon_t_p1024to2047,
311                fecp->rmon_t_p1024to2047);
312         printf("rmon_t_p_gte2048   %x - %x\n", (int)&fecp->rmon_t_p_gte2048,
313                fecp->rmon_t_p_gte2048);
314         printf("rmon_t_octets      %x - %x\n", (int)&fecp->rmon_t_octets,
315                fecp->rmon_t_octets);
316
317         printf("\n");
318         printf("ieee_t_drop      %x - %x\n", (int)&fecp->ieee_t_drop,
319                fecp->ieee_t_drop);
320         printf("ieee_t_frame_ok  %x - %x\n", (int)&fecp->ieee_t_frame_ok,
321                fecp->ieee_t_frame_ok);
322         printf("ieee_t_1col      %x - %x\n", (int)&fecp->ieee_t_1col,
323                fecp->ieee_t_1col);
324         printf("ieee_t_mcol      %x - %x\n", (int)&fecp->ieee_t_mcol,
325                fecp->ieee_t_mcol);
326         printf("ieee_t_def       %x - %x\n", (int)&fecp->ieee_t_def,
327                fecp->ieee_t_def);
328         printf("ieee_t_lcol      %x - %x\n", (int)&fecp->ieee_t_lcol,
329                fecp->ieee_t_lcol);
330         printf("ieee_t_excol     %x - %x\n", (int)&fecp->ieee_t_excol,
331                fecp->ieee_t_excol);
332         printf("ieee_t_macerr    %x - %x\n", (int)&fecp->ieee_t_macerr,
333                fecp->ieee_t_macerr);
334         printf("ieee_t_cserr     %x - %x\n", (int)&fecp->ieee_t_cserr,
335                fecp->ieee_t_cserr);
336         printf("ieee_t_sqe       %x - %x\n", (int)&fecp->ieee_t_sqe,
337                fecp->ieee_t_sqe);
338         printf("ieee_t_fdxfc     %x - %x\n", (int)&fecp->ieee_t_fdxfc,
339                fecp->ieee_t_fdxfc);
340         printf("ieee_t_octets_ok %x - %x\n", (int)&fecp->ieee_t_octets_ok,
341                fecp->ieee_t_octets_ok);
342
343         printf("\n");
344         printf("rmon_r_drop        %x - %x\n", (int)&fecp->rmon_r_drop,
345                fecp->rmon_r_drop);
346         printf("rmon_r_packets     %x - %x\n", (int)&fecp->rmon_r_packets,
347                fecp->rmon_r_packets);
348         printf("rmon_r_bc_pkt      %x - %x\n", (int)&fecp->rmon_r_bc_pkt,
349                fecp->rmon_r_bc_pkt);
350         printf("rmon_r_mc_pkt      %x - %x\n", (int)&fecp->rmon_r_mc_pkt,
351                fecp->rmon_r_mc_pkt);
352         printf("rmon_r_crc_align   %x - %x\n", (int)&fecp->rmon_r_crc_align,
353                fecp->rmon_r_crc_align);
354         printf("rmon_r_undersize   %x - %x\n", (int)&fecp->rmon_r_undersize,
355                fecp->rmon_r_undersize);
356         printf("rmon_r_oversize    %x - %x\n", (int)&fecp->rmon_r_oversize,
357                fecp->rmon_r_oversize);
358         printf("rmon_r_frag        %x - %x\n", (int)&fecp->rmon_r_frag,
359                fecp->rmon_r_frag);
360         printf("rmon_r_jab         %x - %x\n", (int)&fecp->rmon_r_jab,
361                fecp->rmon_r_jab);
362         printf("rmon_r_p64         %x - %x\n", (int)&fecp->rmon_r_p64,
363                fecp->rmon_r_p64);
364         printf("rmon_r_p65to127    %x - %x\n", (int)&fecp->rmon_r_p65to127,
365                fecp->rmon_r_p65to127);
366         printf("rmon_r_p128to255   %x - %x\n", (int)&fecp->rmon_r_p128to255,
367                fecp->rmon_r_p128to255);
368         printf("rmon_r_p256to511   %x - %x\n", (int)&fecp->rmon_r_p256to511,
369                fecp->rmon_r_p256to511);
370         printf("rmon_r_p512to1023  %x - %x\n", (int)&fecp->rmon_r_p512to1023,
371                fecp->rmon_r_p512to1023);
372         printf("rmon_r_p1024to2047 %x - %x\n", (int)&fecp->rmon_r_p1024to2047,
373                fecp->rmon_r_p1024to2047);
374         printf("rmon_r_p_gte2048   %x - %x\n", (int)&fecp->rmon_r_p_gte2048,
375                fecp->rmon_r_p_gte2048);
376         printf("rmon_r_octets      %x - %x\n", (int)&fecp->rmon_r_octets,
377                fecp->rmon_r_octets);
378
379         printf("\n");
380         printf("ieee_r_drop      %x - %x\n", (int)&fecp->ieee_r_drop,
381                fecp->ieee_r_drop);
382         printf("ieee_r_frame_ok  %x - %x\n", (int)&fecp->ieee_r_frame_ok,
383                fecp->ieee_r_frame_ok);
384         printf("ieee_r_crc       %x - %x\n", (int)&fecp->ieee_r_crc,
385                fecp->ieee_r_crc);
386         printf("ieee_r_align     %x - %x\n", (int)&fecp->ieee_r_align,
387                fecp->ieee_r_align);
388         printf("ieee_r_macerr    %x - %x\n", (int)&fecp->ieee_r_macerr,
389                fecp->ieee_r_macerr);
390         printf("ieee_r_fdxfc     %x - %x\n", (int)&fecp->ieee_r_fdxfc,
391                fecp->ieee_r_fdxfc);
392         printf("ieee_r_octets_ok %x - %x\n", (int)&fecp->ieee_r_octets_ok,
393                fecp->ieee_r_octets_ok);
394
395         printf("\n\n\n");
396 }
397 #endif
398
399 int fec_init(struct eth_device *dev, bd_t * bd)
400 {
401         struct fec_info_s *info = dev->priv;
402         volatile fec_t *fecp = (fec_t *) (info->iobase);
403         int i;
404         uchar ea[6];
405
406         fecpin_setclear(dev, 1);
407
408         fec_reset(dev);
409
410 #if defined(CONFIG_CMD_MII) || defined (CONFIG_MII) || \
411         defined (CONFIG_SYS_DISCOVER_PHY)
412
413         mii_init();
414
415         setFecDuplexSpeed(fecp, bd, info->dup_spd);
416 #else
417 #ifndef CONFIG_SYS_DISCOVER_PHY
418         setFecDuplexSpeed(fecp, bd, (FECDUPLEX << 16) | FECSPEED);
419 #endif                          /* ifndef CONFIG_SYS_DISCOVER_PHY */
420 #endif                          /* CONFIG_CMD_MII || CONFIG_MII */
421
422         /* We use strictly polling mode only */
423         fecp->eimr = 0;
424
425         /* Clear any pending interrupt */
426         fecp->eir = 0xffffffff;
427
428         /* Set station address   */
429         if ((u32) fecp == CONFIG_SYS_FEC0_IOBASE) {
430 #ifdef CONFIG_SYS_FEC1_IOBASE
431                 volatile fec_t *fecp1 = (fec_t *) (CONFIG_SYS_FEC1_IOBASE);
432                 eth_env_get_enetaddr("eth1addr", ea);
433                 fecp1->palr =
434                     (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]);
435                 fecp1->paur = (ea[4] << 24) | (ea[5] << 16);
436 #endif
437                 eth_env_get_enetaddr("ethaddr", ea);
438                 fecp->palr =
439                     (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]);
440                 fecp->paur = (ea[4] << 24) | (ea[5] << 16);
441         } else {
442 #ifdef CONFIG_SYS_FEC0_IOBASE
443                 volatile fec_t *fecp0 = (fec_t *) (CONFIG_SYS_FEC0_IOBASE);
444                 eth_env_get_enetaddr("ethaddr", ea);
445                 fecp0->palr =
446                     (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]);
447                 fecp0->paur = (ea[4] << 24) | (ea[5] << 16);
448 #endif
449 #ifdef CONFIG_SYS_FEC1_IOBASE
450                 eth_env_get_enetaddr("eth1addr", ea);
451                 fecp->palr =
452                     (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]);
453                 fecp->paur = (ea[4] << 24) | (ea[5] << 16);
454 #endif
455         }
456
457         /* Clear unicast address hash table */
458         fecp->iaur = 0;
459         fecp->ialr = 0;
460
461         /* Clear multicast address hash table */
462         fecp->gaur = 0;
463         fecp->galr = 0;
464
465         /* Set maximum receive buffer size. */
466         fecp->emrbr = PKT_MAXBLR_SIZE;
467
468         /*
469          * Setup Buffers and Buffer Descriptors
470          */
471         info->rxIdx = 0;
472         info->txIdx = 0;
473
474         /*
475          * Setup Receiver Buffer Descriptors (13.14.24.18)
476          * Settings:
477          *     Empty, Wrap
478          */
479         for (i = 0; i < PKTBUFSRX; i++) {
480                 info->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
481                 info->rxbd[i].cbd_datlen = 0;   /* Reset */
482                 info->rxbd[i].cbd_bufaddr = (uint) net_rx_packets[i];
483         }
484         info->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
485
486         /*
487          * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)
488          * Settings:
489          *    Last, Tx CRC
490          */
491         for (i = 0; i < TX_BUF_CNT; i++) {
492                 info->txbd[i].cbd_sc = BD_ENET_TX_LAST | BD_ENET_TX_TC;
493                 info->txbd[i].cbd_datlen = 0;   /* Reset */
494                 info->txbd[i].cbd_bufaddr = (uint) (&info->txbuf[0]);
495         }
496         info->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
497
498         /* Set receive and transmit descriptor base */
499         fecp->erdsr = (unsigned int)(&info->rxbd[0]);
500         fecp->etdsr = (unsigned int)(&info->txbd[0]);
501
502         /* Now enable the transmit and receive processing */
503         fecp->ecr |= FEC_ECR_ETHER_EN;
504
505         /* And last, try to fill Rx Buffer Descriptors */
506         fecp->rdar = 0x01000000;        /* Descriptor polling active    */
507
508         return 1;
509 }
510
511 void fec_reset(struct eth_device *dev)
512 {
513         struct fec_info_s *info = dev->priv;
514         volatile fec_t *fecp = (fec_t *) (info->iobase);
515         int i;
516
517         fecp->ecr = FEC_ECR_RESET;
518         for (i = 0; (fecp->ecr & FEC_ECR_RESET) && (i < FEC_RESET_DELAY); ++i) {
519                 udelay(1);
520         }
521         if (i == FEC_RESET_DELAY) {
522                 printf("FEC_RESET_DELAY timeout\n");
523         }
524 }
525
526 void fec_halt(struct eth_device *dev)
527 {
528         struct fec_info_s *info = dev->priv;
529
530         fec_reset(dev);
531
532         fecpin_setclear(dev, 0);
533
534         info->rxIdx = info->txIdx = 0;
535         memset(info->rxbd, 0, PKTBUFSRX * sizeof(cbd_t));
536         memset(info->txbd, 0, TX_BUF_CNT * sizeof(cbd_t));
537         memset(info->txbuf, 0, DBUF_LENGTH);
538 }
539
540 int mcffec_initialize(bd_t * bis)
541 {
542         struct eth_device *dev;
543         int i;
544 #ifdef CONFIG_SYS_FEC_BUF_USE_SRAM
545         u32 tmp = CONFIG_SYS_INIT_RAM_ADDR + 0x1000;
546 #endif
547
548         for (i = 0; i < ARRAY_SIZE(fec_info); i++) {
549
550                 dev =
551                     (struct eth_device *)memalign(CONFIG_SYS_CACHELINE_SIZE,
552                                                   sizeof *dev);
553                 if (dev == NULL)
554                         hang();
555
556                 memset(dev, 0, sizeof(*dev));
557
558                 sprintf(dev->name, "FEC%d", fec_info[i].index);
559
560                 dev->priv = &fec_info[i];
561                 dev->init = fec_init;
562                 dev->halt = fec_halt;
563                 dev->send = fec_send;
564                 dev->recv = fec_recv;
565
566                 /* setup Receive and Transmit buffer descriptor */
567 #ifdef CONFIG_SYS_FEC_BUF_USE_SRAM
568                 fec_info[i].rxbd = (cbd_t *)((u32)fec_info[i].rxbd + tmp);
569                 tmp = (u32)fec_info[i].rxbd;
570                 fec_info[i].txbd =
571                     (cbd_t *)((u32)fec_info[i].txbd + tmp +
572                     (PKTBUFSRX * sizeof(cbd_t)));
573                 tmp = (u32)fec_info[i].txbd;
574                 fec_info[i].txbuf =
575                     (char *)((u32)fec_info[i].txbuf + tmp +
576                     (CONFIG_SYS_TX_ETH_BUFFER * sizeof(cbd_t)));
577                 tmp = (u32)fec_info[i].txbuf;
578 #else
579                 fec_info[i].rxbd =
580                     (cbd_t *) memalign(CONFIG_SYS_CACHELINE_SIZE,
581                                        (PKTBUFSRX * sizeof(cbd_t)));
582                 fec_info[i].txbd =
583                     (cbd_t *) memalign(CONFIG_SYS_CACHELINE_SIZE,
584                                        (TX_BUF_CNT * sizeof(cbd_t)));
585                 fec_info[i].txbuf =
586                     (char *)memalign(CONFIG_SYS_CACHELINE_SIZE, DBUF_LENGTH);
587 #endif
588
589 #ifdef ET_DEBUG
590                 printf("rxbd %x txbd %x\n",
591                        (int)fec_info[i].rxbd, (int)fec_info[i].txbd);
592 #endif
593
594                 fec_info[i].phy_name = (char *)memalign(CONFIG_SYS_CACHELINE_SIZE, 32);
595
596                 eth_register(dev);
597
598 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
599                 int retval;
600                 struct mii_dev *mdiodev = mdio_alloc();
601                 if (!mdiodev)
602                         return -ENOMEM;
603                 strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
604                 mdiodev->read = mcffec_miiphy_read;
605                 mdiodev->write = mcffec_miiphy_write;
606
607                 retval = mdio_register(mdiodev);
608                 if (retval < 0)
609                         return retval;
610 #endif
611                 if (i > 0)
612                         fec_info[i - 1].next = &fec_info[i];
613         }
614         fec_info[i - 1].next = &fec_info[0];
615
616         /* default speed */
617         bis->bi_ethspeed = 10;
618
619         return 0;
620 }