]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/powerpc/cpu/mpc8220/fec.c
Merge branch 'master' of git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / arch / powerpc / cpu / mpc8220 / fec.c
1 /*
2  * (C) Copyright 2003
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * This file is based on mpc4200fec.c,
6  * (C) Copyright Motorola, Inc., 2000
7  */
8
9 #include <common.h>
10 #include <mpc8220.h>
11 #include <malloc.h>
12 #include <net.h>
13 #include <miiphy.h>
14 #include "dma.h"
15 #include "fec.h"
16
17 #undef  DEBUG
18 #if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
19     defined(CONFIG_MPC8220_FEC)
20
21 #if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
22 #error "CONFIG_MII has to be defined!"
23 #endif
24
25 #ifdef DEBUG
26 static void tfifo_print (char *devname, mpc8220_fec_priv * fec);
27 static void rfifo_print (char *devname, mpc8220_fec_priv * fec);
28 #endif /* DEBUG */
29
30 #ifdef DEBUG
31 static u32 local_crc32 (char *string, unsigned int crc_value, int len);
32 #endif
33
34 typedef struct {
35         u8 data[1500];          /* actual data */
36         int length;             /* actual length */
37         int used;               /* buffer in use or not */
38         u8 head[16];            /* MAC header(6 + 6 + 2) + 2(aligned) */
39 } NBUF;
40
41 int fec8220_miiphy_read (char *devname, u8 phyAddr, u8 regAddr, u16 * retVal);
42 int fec8220_miiphy_write (char *devname, u8 phyAddr, u8 regAddr, u16 data);
43
44 /********************************************************************/
45 #ifdef DEBUG
46 static void mpc8220_fec_phydump (char *devname)
47 {
48         u16 phyStatus, i;
49         u8 phyAddr = CONFIG_PHY_ADDR;
50         u8 reg_mask[] = {
51 #if CONFIG_PHY_TYPE == 0x79c874 /* AMD Am79C874 */
52                 /* regs to print: 0...7, 16...19, 21, 23, 24 */
53                 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
54                 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
55 #else
56                 /* regs to print: 0...8, 16...20 */
57                 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
58                 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
59 #endif
60         };
61
62         for (i = 0; i < 32; i++) {
63                 if (reg_mask[i]) {
64                         miiphy_read (devname, phyAddr, i, &phyStatus);
65                         printf ("Mii reg %d: 0x%04x\n", i, phyStatus);
66                 }
67         }
68 }
69 #endif
70
71 /********************************************************************/
72 static int mpc8220_fec_rbd_init (mpc8220_fec_priv * fec)
73 {
74         int ix;
75         char *data;
76         static int once = 0;
77
78         for (ix = 0; ix < FEC_RBD_NUM; ix++) {
79                 if (!once) {
80                         data = (char *) malloc (FEC_MAX_PKT_SIZE);
81                         if (data == NULL) {
82                                 printf ("RBD INIT FAILED\n");
83                                 return -1;
84                         }
85                         fec->rbdBase[ix].dataPointer = (u32) data;
86                 }
87                 fec->rbdBase[ix].status = FEC_RBD_EMPTY;
88                 fec->rbdBase[ix].dataLength = 0;
89         }
90         once++;
91
92         /*
93          * have the last RBD to close the ring
94          */
95         fec->rbdBase[ix - 1].status |= FEC_RBD_WRAP;
96         fec->rbdIndex = 0;
97
98         return 0;
99 }
100
101 /********************************************************************/
102 static void mpc8220_fec_tbd_init (mpc8220_fec_priv * fec)
103 {
104         int ix;
105
106         for (ix = 0; ix < FEC_TBD_NUM; ix++) {
107                 fec->tbdBase[ix].status = 0;
108         }
109
110         /*
111          * Have the last TBD to close the ring
112          */
113         fec->tbdBase[ix - 1].status |= FEC_TBD_WRAP;
114
115         /*
116          * Initialize some indices
117          */
118         fec->tbdIndex = 0;
119         fec->usedTbdIndex = 0;
120         fec->cleanTbdNum = FEC_TBD_NUM;
121 }
122
123 /********************************************************************/
124 static void mpc8220_fec_rbd_clean (mpc8220_fec_priv * fec, FEC_RBD * pRbd)
125 {
126         /*
127          * Reset buffer descriptor as empty
128          */
129         if ((fec->rbdIndex) == (FEC_RBD_NUM - 1))
130                 pRbd->status = (FEC_RBD_WRAP | FEC_RBD_EMPTY);
131         else
132                 pRbd->status = FEC_RBD_EMPTY;
133
134         pRbd->dataLength = 0;
135
136         /*
137          * Now, we have an empty RxBD, restart the SmartDMA receive task
138          */
139         DMA_TASK_ENABLE (FEC_RECV_TASK_NO);
140
141         /*
142          * Increment BD count
143          */
144         fec->rbdIndex = (fec->rbdIndex + 1) % FEC_RBD_NUM;
145 }
146
147 /********************************************************************/
148 static void mpc8220_fec_tbd_scrub (mpc8220_fec_priv * fec)
149 {
150         FEC_TBD *pUsedTbd;
151
152 #ifdef DEBUG
153         printf ("tbd_scrub: fec->cleanTbdNum = %d, fec->usedTbdIndex = %d\n",
154                 fec->cleanTbdNum, fec->usedTbdIndex);
155 #endif
156
157         /*
158          * process all the consumed TBDs
159          */
160         while (fec->cleanTbdNum < FEC_TBD_NUM) {
161                 pUsedTbd = &fec->tbdBase[fec->usedTbdIndex];
162                 if (pUsedTbd->status & FEC_TBD_READY) {
163 #ifdef DEBUG
164                         printf ("Cannot clean TBD %d, in use\n",
165                                 fec->cleanTbdNum);
166 #endif
167                         return;
168                 }
169
170                 /*
171                  * clean this buffer descriptor
172                  */
173                 if (fec->usedTbdIndex == (FEC_TBD_NUM - 1))
174                         pUsedTbd->status = FEC_TBD_WRAP;
175                 else
176                         pUsedTbd->status = 0;
177
178                 /*
179                  * update some indeces for a correct handling of the TBD ring
180                  */
181                 fec->cleanTbdNum++;
182                 fec->usedTbdIndex = (fec->usedTbdIndex + 1) % FEC_TBD_NUM;
183         }
184 }
185
186 /********************************************************************/
187 static void mpc8220_fec_set_hwaddr (mpc8220_fec_priv * fec, char *mac)
188 {
189         u8 currByte;            /* byte for which to compute the CRC */
190         int byte;               /* loop - counter */
191         int bit;                /* loop - counter */
192         u32 crc = 0xffffffff;   /* initial value */
193
194         /*
195          * The algorithm used is the following:
196          * we loop on each of the six bytes of the provided address,
197          * and we compute the CRC by left-shifting the previous
198          * value by one position, so that each bit in the current
199          * byte of the address may contribute the calculation. If
200          * the latter and the MSB in the CRC are different, then
201          * the CRC value so computed is also ex-ored with the
202          * "polynomium generator". The current byte of the address
203          * is also shifted right by one bit at each iteration.
204          * This is because the CRC generatore in hardware is implemented
205          * as a shift-register with as many ex-ores as the radixes
206          * in the polynomium. This suggests that we represent the
207          * polynomiumm itself as a 32-bit constant.
208          */
209         for (byte = 0; byte < 6; byte++) {
210                 currByte = mac[byte];
211                 for (bit = 0; bit < 8; bit++) {
212                         if ((currByte & 0x01) ^ (crc & 0x01)) {
213                                 crc >>= 1;
214                                 crc = crc ^ 0xedb88320;
215                         } else {
216                                 crc >>= 1;
217                         }
218                         currByte >>= 1;
219                 }
220         }
221
222         crc = crc >> 26;
223
224         /*
225          * Set individual hash table register
226          */
227         if (crc >= 32) {
228                 fec->eth->iaddr1 = (1 << (crc - 32));
229                 fec->eth->iaddr2 = 0;
230         } else {
231                 fec->eth->iaddr1 = 0;
232                 fec->eth->iaddr2 = (1 << crc);
233         }
234
235         /*
236          * Set physical address
237          */
238         fec->eth->paddr1 =
239                 (mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3];
240         fec->eth->paddr2 = (mac[4] << 24) + (mac[5] << 16) + 0x8808;
241 }
242
243 /********************************************************************/
244 static int mpc8220_fec_init (struct eth_device *dev, bd_t * bis)
245 {
246         mpc8220_fec_priv *fec = (mpc8220_fec_priv *) dev->priv;
247         struct mpc8220_dma *dma = (struct mpc8220_dma *) MMAP_DMA;
248         const u8 phyAddr = CONFIG_PHY_ADDR;     /* Only one PHY */
249
250 #ifdef DEBUG
251         printf ("mpc8220_fec_init... Begin\n");
252 #endif
253
254         /*
255          * Initialize RxBD/TxBD rings
256          */
257         mpc8220_fec_rbd_init (fec);
258         mpc8220_fec_tbd_init (fec);
259
260         /*
261          * Set up Pin Muxing for FEC 1
262          */
263         *(vu_long *) MMAP_PCFG = 0;
264         *(vu_long *) (MMAP_PCFG + 4) = 0;
265         /*
266          * Clear FEC-Lite interrupt event register(IEVENT)
267          */
268         fec->eth->ievent = 0xffffffff;
269
270         /*
271          * Set interrupt mask register
272          */
273         fec->eth->imask = 0x00000000;
274
275         /*
276          * Set FEC-Lite receive control register(R_CNTRL):
277          */
278         if (fec->xcv_type == SEVENWIRE) {
279                 /*
280                  * Frame length=1518; 7-wire mode
281                  */
282                 fec->eth->r_cntrl = 0x05ee0020; /*0x05ee0000;FIXME */
283         } else {
284                 /*
285                  * Frame length=1518; MII mode;
286                  */
287                 fec->eth->r_cntrl = 0x05ee0024; /*0x05ee0004;FIXME */
288         }
289
290         fec->eth->x_cntrl = 0x00000000; /* half-duplex, heartbeat disabled */
291         if (fec->xcv_type != SEVENWIRE) {
292                 /*
293                  * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
294                  * and do not drop the Preamble.
295                  */
296                 /* tbd - rtm */
297                 /*fec->eth->mii_speed = (((gd->ipb_clk >> 20) / 5) << 1); */
298                 /* No MII for 7-wire mode */
299                 fec->eth->mii_speed = 0x00000030;
300         }
301
302         /*
303          * Set Opcode/Pause Duration Register
304          */
305         fec->eth->op_pause = 0x00010020;        /*FIXME0xffff0020; */
306
307         /*
308          * Set Rx FIFO alarm and granularity value
309          */
310         fec->eth->rfifo_cntrl = 0x0c000000;
311         fec->eth->rfifo_alarm = 0x0000030c;
312 #ifdef DEBUG
313         if (fec->eth->rfifo_status & 0x00700000) {
314                 printf ("mpc8220_fec_init() RFIFO error\n");
315         }
316 #endif
317
318         /*
319          * Set Tx FIFO granularity value
320          */
321         /*fec->eth->tfifo_cntrl = 0x0c000000; */ /*tbd - rtm */
322         fec->eth->tfifo_cntrl = 0x0e000000;
323 #ifdef DEBUG
324         printf ("tfifo_status: 0x%08x\n", fec->eth->tfifo_status);
325         printf ("tfifo_alarm: 0x%08x\n", fec->eth->tfifo_alarm);
326 #endif
327
328         /*
329          * Set transmit fifo watermark register(X_WMRK), default = 64
330          */
331         fec->eth->tfifo_alarm = 0x00000080;
332         fec->eth->x_wmrk = 0x2;
333
334         /*
335          * Set individual address filter for unicast address
336          * and set physical address registers.
337          */
338         mpc8220_fec_set_hwaddr (fec, (char *)(dev->enetaddr));
339
340         /*
341          * Set multicast address filter
342          */
343         fec->eth->gaddr1 = 0x00000000;
344         fec->eth->gaddr2 = 0x00000000;
345
346         /*
347          * Turn ON cheater FSM: ????
348          */
349         fec->eth->xmit_fsm = 0x03000000;
350
351 #if 1
352 /*#if defined(CONFIG_MPC5200)*/
353         /*
354          * Turn off COMM bus prefetch in the MGT5200 BestComm. It doesn't
355          * work w/ the current receive task.
356          */
357         dma->PtdCntrl |= 0x00000001;
358 #endif
359
360         /*
361          * Set priority of different initiators
362          */
363         dma->IPR0 = 7;          /* always */
364         dma->IPR3 = 6;          /* Eth RX */
365         dma->IPR4 = 5;          /* Eth Tx */
366
367         /*
368          * Clear SmartDMA task interrupt pending bits
369          */
370         DMA_CLEAR_IEVENT (FEC_RECV_TASK_NO);
371
372         /*
373          * Initialize SmartDMA parameters stored in SRAM
374          */
375         *(int *) FEC_TBD_BASE = (int) fec->tbdBase;
376         *(int *) FEC_RBD_BASE = (int) fec->rbdBase;
377         *(int *) FEC_TBD_NEXT = (int) fec->tbdBase;
378         *(int *) FEC_RBD_NEXT = (int) fec->rbdBase;
379
380         if (fec->xcv_type != SEVENWIRE) {
381                 /*
382                  * Initialize PHY(LXT971A):
383                  *
384                  *   Generally, on power up, the LXT971A reads its configuration
385                  *   pins to check for forced operation, If not cofigured for
386                  *   forced operation, it uses auto-negotiation/parallel detection
387                  *   to automatically determine line operating conditions.
388                  *   If the PHY device on the other side of the link supports
389                  *   auto-negotiation, the LXT971A auto-negotiates with it
390                  *   using Fast Link Pulse(FLP) Bursts. If the PHY partner does not
391                  *   support auto-negotiation, the LXT971A automatically detects
392                  *   the presence of either link pulses(10Mbps PHY) or Idle
393                  *   symbols(100Mbps) and sets its operating conditions accordingly.
394                  *
395                  *   When auto-negotiation is controlled by software, the following
396                  *   steps are recommended.
397                  *
398                  * Note:
399                  *   The physical address is dependent on hardware configuration.
400                  *
401                  */
402                 int timeout = 1;
403                 u16 phyStatus;
404
405                 /*
406                  * Reset PHY, then delay 300ns
407                  */
408                 miiphy_write (dev->name, phyAddr, 0x0, 0x8000);
409                 udelay (1000);
410
411                 if (fec->xcv_type == MII10) {
412                         /*
413                          * Force 10Base-T, FDX operation
414                          */
415 #ifdef DEBUG
416                         printf ("Forcing 10 Mbps ethernet link... ");
417 #endif
418                         miiphy_read (dev->name, phyAddr, 0x1, &phyStatus);
419                         /*
420                            miiphy_write(fec, phyAddr, 0x0, 0x0100);
421                          */
422                         miiphy_write (dev->name, phyAddr, 0x0, 0x0180);
423
424                         timeout = 20;
425                         do {    /* wait for link status to go down */
426                                 udelay (10000);
427                                 if ((timeout--) == 0) {
428 #ifdef DEBUG
429                                         printf ("hmmm, should not have waited...");
430 #endif
431                                         break;
432                                 }
433                                 miiphy_read (dev->name, phyAddr, 0x1, &phyStatus);
434 #ifdef DEBUG
435                                 printf ("=");
436 #endif
437                         } while ((phyStatus & 0x0004)); /* !link up */
438
439                         timeout = 1000;
440                         do {    /* wait for link status to come back up */
441                                 udelay (10000);
442                                 if ((timeout--) == 0) {
443                                         printf ("failed. Link is down.\n");
444                                         break;
445                                 }
446                                 miiphy_read (dev->name, phyAddr, 0x1, &phyStatus);
447 #ifdef DEBUG
448                                 printf ("+");
449 #endif
450                         } while (!(phyStatus & 0x0004));        /* !link up */
451
452 #ifdef DEBUG
453                         printf ("done.\n");
454 #endif
455                 } else {        /* MII100 */
456                         /*
457                          * Set the auto-negotiation advertisement register bits
458                          */
459                         miiphy_write (dev->name, phyAddr, 0x4, 0x01e1);
460
461                         /*
462                          * Set MDIO bit 0.12 = 1(&& bit 0.9=1?) to enable auto-negotiation
463                          */
464                         miiphy_write (dev->name, phyAddr, 0x0, 0x1200);
465
466                         /*
467                          * Wait for AN completion
468                          */
469                         timeout = 5000;
470                         do {
471                                 udelay (1000);
472
473                                 if ((timeout--) == 0) {
474 #ifdef DEBUG
475                                         printf ("PHY auto neg 0 failed...\n");
476 #endif
477                                         return -1;
478                                 }
479
480                                 if (miiphy_read (dev->name, phyAddr, 0x1, &phyStatus) !=
481                                     0) {
482 #ifdef DEBUG
483                                         printf ("PHY auto neg 1 failed 0x%04x...\n", phyStatus);
484 #endif
485                                         return -1;
486                                 }
487                         } while (!(phyStatus & 0x0004));
488
489 #ifdef DEBUG
490                         printf ("PHY auto neg complete! \n");
491 #endif
492                 }
493
494         }
495
496         /*
497          * Enable FEC-Lite controller
498          */
499         fec->eth->ecntrl |= 0x00000006;
500
501 #ifdef DEBUG
502         if (fec->xcv_type != SEVENWIRE)
503                 mpc8220_fec_phydump (dev->name);
504 #endif
505
506         /*
507          * Enable SmartDMA receive task
508          */
509         DMA_TASK_ENABLE (FEC_RECV_TASK_NO);
510
511 #ifdef DEBUG
512         printf ("mpc8220_fec_init... Done \n");
513 #endif
514
515         return 1;
516 }
517
518 /********************************************************************/
519 static void mpc8220_fec_halt (struct eth_device *dev)
520 {
521         mpc8220_fec_priv *fec = (mpc8220_fec_priv *) dev->priv;
522         int counter = 0xffff;
523
524 #ifdef DEBUG
525         if (fec->xcv_type != SEVENWIRE)
526                 mpc8220_fec_phydump (dev->name);
527 #endif
528
529         /*
530          * mask FEC chip interrupts
531          */
532         fec->eth->imask = 0;
533
534         /*
535          * issue graceful stop command to the FEC transmitter if necessary
536          */
537         fec->eth->x_cntrl |= 0x00000001;
538
539         /*
540          * wait for graceful stop to register
541          */
542         while ((counter--) && (!(fec->eth->ievent & 0x10000000)));
543
544         /*
545          * Disable SmartDMA tasks
546          */
547         DMA_TASK_DISABLE (FEC_XMIT_TASK_NO);
548         DMA_TASK_DISABLE (FEC_RECV_TASK_NO);
549
550         /*
551          * Disable the Ethernet Controller
552          */
553         fec->eth->ecntrl &= 0xfffffffd;
554
555         /*
556          * Clear FIFO status registers
557          */
558         fec->eth->rfifo_status &= 0x00700000;
559         fec->eth->tfifo_status &= 0x00700000;
560
561         fec->eth->reset_cntrl = 0x01000000;
562
563         /*
564          * Issue a reset command to the FEC chip
565          */
566         fec->eth->ecntrl |= 0x1;
567
568         /*
569          * wait at least 16 clock cycles
570          */
571         udelay (10);
572
573 #ifdef DEBUG
574         printf ("Ethernet task stopped\n");
575 #endif
576 }
577
578 #ifdef DEBUG
579 /********************************************************************/
580
581 static void tfifo_print (char *devname, mpc8220_fec_priv * fec)
582 {
583         u16 phyAddr = CONFIG_PHY_ADDR;
584         u16 phyStatus;
585
586         if ((fec->eth->tfifo_lrf_ptr != fec->eth->tfifo_lwf_ptr)
587             || (fec->eth->tfifo_rdptr != fec->eth->tfifo_wrptr)) {
588
589                 miiphy_read (devname, phyAddr, 0x1, &phyStatus);
590                 printf ("\nphyStatus: 0x%04x\n", phyStatus);
591                 printf ("ecntrl:   0x%08x\n", fec->eth->ecntrl);
592                 printf ("ievent:   0x%08x\n", fec->eth->ievent);
593                 printf ("x_status: 0x%08x\n", fec->eth->x_status);
594                 printf ("tfifo: status  0x%08x\n", fec->eth->tfifo_status);
595
596                 printf ("       control 0x%08x\n", fec->eth->tfifo_cntrl);
597                 printf ("       lrfp    0x%08x\n", fec->eth->tfifo_lrf_ptr);
598                 printf ("       lwfp    0x%08x\n", fec->eth->tfifo_lwf_ptr);
599                 printf ("       alarm   0x%08x\n", fec->eth->tfifo_alarm);
600                 printf ("       readptr 0x%08x\n", fec->eth->tfifo_rdptr);
601                 printf ("       writptr 0x%08x\n", fec->eth->tfifo_wrptr);
602         }
603 }
604
605 static void rfifo_print (char *devname, mpc8220_fec_priv * fec)
606 {
607         u16 phyAddr = CONFIG_PHY_ADDR;
608         u16 phyStatus;
609
610         if ((fec->eth->rfifo_lrf_ptr != fec->eth->rfifo_lwf_ptr)
611             || (fec->eth->rfifo_rdptr != fec->eth->rfifo_wrptr)) {
612
613                 miiphy_read (devname, phyAddr, 0x1, &phyStatus);
614                 printf ("\nphyStatus: 0x%04x\n", phyStatus);
615                 printf ("ecntrl:   0x%08x\n", fec->eth->ecntrl);
616                 printf ("ievent:   0x%08x\n", fec->eth->ievent);
617                 printf ("x_status: 0x%08x\n", fec->eth->x_status);
618                 printf ("rfifo: status  0x%08x\n", fec->eth->rfifo_status);
619
620                 printf ("       control 0x%08x\n", fec->eth->rfifo_cntrl);
621                 printf ("       lrfp    0x%08x\n", fec->eth->rfifo_lrf_ptr);
622                 printf ("       lwfp    0x%08x\n", fec->eth->rfifo_lwf_ptr);
623                 printf ("       alarm   0x%08x\n", fec->eth->rfifo_alarm);
624                 printf ("       readptr 0x%08x\n", fec->eth->rfifo_rdptr);
625                 printf ("       writptr 0x%08x\n", fec->eth->rfifo_wrptr);
626         }
627 }
628 #endif /* DEBUG */
629
630 /********************************************************************/
631
632 static int mpc8220_fec_send (struct eth_device *dev, volatile void *eth_data,
633                              int data_length)
634 {
635         /*
636          * This routine transmits one frame.  This routine only accepts
637          * 6-byte Ethernet addresses.
638          */
639         mpc8220_fec_priv *fec = (mpc8220_fec_priv *) dev->priv;
640         FEC_TBD *pTbd;
641
642 #ifdef DEBUG
643         printf ("tbd status: 0x%04x\n", fec->tbdBase[0].status);
644         tfifo_print (dev->name, fec);
645 #endif
646
647         /*
648          * Clear Tx BD ring at first
649          */
650         mpc8220_fec_tbd_scrub (fec);
651
652         /*
653          * Check for valid length of data.
654          */
655         if ((data_length > 1500) || (data_length <= 0)) {
656                 return -1;
657         }
658
659         /*
660          * Check the number of vacant TxBDs.
661          */
662         if (fec->cleanTbdNum < 1) {
663 #ifdef DEBUG
664                 printf ("No available TxBDs ...\n");
665 #endif
666                 return -1;
667         }
668
669         /*
670          * Get the first TxBD to send the mac header
671          */
672         pTbd = &fec->tbdBase[fec->tbdIndex];
673         pTbd->dataLength = data_length;
674         pTbd->dataPointer = (u32) eth_data;
675         pTbd->status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY;
676         fec->tbdIndex = (fec->tbdIndex + 1) % FEC_TBD_NUM;
677
678 #ifdef DEBUG
679         printf ("DMA_TASK_ENABLE, fec->tbdIndex = %d \n", fec->tbdIndex);
680 #endif
681
682         /*
683          * Kick the MII i/f
684          */
685         if (fec->xcv_type != SEVENWIRE) {
686                 u16 phyStatus;
687
688                 miiphy_read (dev->name, 0, 0x1, &phyStatus);
689         }
690
691         /*
692          * Enable SmartDMA transmit task
693          */
694
695 #ifdef DEBUG
696         tfifo_print (dev->name, fec);
697 #endif
698
699         DMA_TASK_ENABLE (FEC_XMIT_TASK_NO);
700
701 #ifdef DEBUG
702         tfifo_print (dev->name, fec);
703 #endif
704
705 #ifdef DEBUG
706         printf ("+");
707 #endif
708
709         fec->cleanTbdNum -= 1;
710
711 #ifdef DEBUG
712         printf ("smartDMA ethernet Tx task enabled\n");
713 #endif
714         /*
715          * wait until frame is sent .
716          */
717         while (pTbd->status & FEC_TBD_READY) {
718                 udelay (10);
719 #ifdef DEBUG
720                 printf ("TDB status = %04x\n", pTbd->status);
721 #endif
722         }
723
724         return 0;
725 }
726
727
728 /********************************************************************/
729 static int mpc8220_fec_recv (struct eth_device *dev)
730 {
731         /*
732          * This command pulls one frame from the card
733          */
734         mpc8220_fec_priv *fec = (mpc8220_fec_priv *) dev->priv;
735         FEC_RBD *pRbd = &fec->rbdBase[fec->rbdIndex];
736         unsigned long ievent;
737         int frame_length, len = 0;
738         NBUF *frame;
739
740 #ifdef DEBUG
741         printf ("mpc8220_fec_recv %d Start...\n", fec->rbdIndex);
742         printf ("-");
743 #endif
744
745         /*
746          * Check if any critical events have happened
747          */
748         ievent = fec->eth->ievent;
749         fec->eth->ievent = ievent;
750         if (ievent & 0x20060000) {
751                 /* BABT, Rx/Tx FIFO errors */
752                 mpc8220_fec_halt (dev);
753                 mpc8220_fec_init (dev, NULL);
754                 return 0;
755         }
756         if (ievent & 0x80000000) {
757                 /* Heartbeat error */
758                 fec->eth->x_cntrl |= 0x00000001;
759         }
760         if (ievent & 0x10000000) {
761                 /* Graceful stop complete */
762                 if (fec->eth->x_cntrl & 0x00000001) {
763                         mpc8220_fec_halt (dev);
764                         fec->eth->x_cntrl &= ~0x00000001;
765                         mpc8220_fec_init (dev, NULL);
766                 }
767         }
768
769         if (!(pRbd->status & FEC_RBD_EMPTY)) {
770                 if ((pRbd->status & FEC_RBD_LAST)
771                     && !(pRbd->status & FEC_RBD_ERR)
772                     && ((pRbd->dataLength - 4) > 14)) {
773
774                         /*
775                          * Get buffer address and size
776                          */
777                         frame = (NBUF *) pRbd->dataPointer;
778                         frame_length = pRbd->dataLength - 4;
779
780 #if (0)
781                         {
782                                 int i;
783
784                                 printf ("recv data hdr:");
785                                 for (i = 0; i < 14; i++)
786                                         printf ("%x ", *(frame->head + i));
787                                 printf ("\n");
788                         }
789 #endif
790                         /*
791                          *  Fill the buffer and pass it to upper layers
792                          */
793 /*                      memcpy(buff, frame->head, 14);
794                         memcpy(buff + 14, frame->data, frame_length);*/
795                         NetReceive ((volatile uchar *) pRbd->dataPointer,
796                                     frame_length);
797                         len = frame_length;
798                 }
799                 /*
800                  * Reset buffer descriptor as empty
801                  */
802                 mpc8220_fec_rbd_clean (fec, pRbd);
803         }
804         DMA_CLEAR_IEVENT (FEC_RECV_TASK_NO);
805         return len;
806 }
807
808
809 /********************************************************************/
810 int mpc8220_fec_initialize (bd_t * bis)
811 {
812         mpc8220_fec_priv *fec;
813
814 #ifdef CONFIG_HAS_ETH1
815         mpc8220_fec_priv *fec2;
816 #endif
817         struct eth_device *dev;
818         char *tmp, *end;
819         char env_enetaddr[6];
820
821 #ifdef CONFIG_HAS_ETH1
822         char env_enet1addr[6];
823 #endif
824         int i;
825
826         fec = (mpc8220_fec_priv *) malloc (sizeof (*fec));
827         dev = (struct eth_device *) malloc (sizeof (*dev));
828         memset (dev, 0, sizeof *dev);
829
830         fec->eth = (ethernet_regs *) MMAP_FEC1;
831 #ifdef CONFIG_HAS_ETH1
832         fec2 = (mpc8220_fec_priv *) malloc (sizeof (*fec));
833         fec2->eth = (ethernet_regs *) MMAP_FEC2;
834 #endif
835         fec->tbdBase = (FEC_TBD *) FEC_BD_BASE;
836         fec->rbdBase =
837                 (FEC_RBD *) (FEC_BD_BASE + FEC_TBD_NUM * sizeof (FEC_TBD));
838         fec->xcv_type = MII100;
839
840         dev->priv = (void *) fec;
841         dev->iobase = MMAP_FEC1;
842         dev->init = mpc8220_fec_init;
843         dev->halt = mpc8220_fec_halt;
844         dev->send = mpc8220_fec_send;
845         dev->recv = mpc8220_fec_recv;
846
847         sprintf (dev->name, "FEC ETHERNET");
848         eth_register (dev);
849
850 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
851         miiphy_register (dev->name,
852                         fec8220_miiphy_read, fec8220_miiphy_write);
853 #endif
854
855         /*
856          * Try to set the mac address now. The fec mac address is
857          * a garbage after reset. When not using fec for booting
858          * the Linux fec driver will try to work with this garbage.
859          */
860         tmp = getenv ("ethaddr");
861         if (tmp) {
862                 for (i = 0; i < 6; i++) {
863                         env_enetaddr[i] =
864                                 tmp ? simple_strtoul (tmp, &end, 16) : 0;
865                         if (tmp)
866                                 tmp = (*end) ? end + 1 : end;
867                 }
868                 mpc8220_fec_set_hwaddr (fec, env_enetaddr);
869         }
870 #ifdef CONFIG_HAS_ETH1
871         tmp = getenv ("eth1addr");
872         if (tmp) {
873                 for (i = 0; i < 6; i++) {
874                         env_enet1addr[i] =
875                                 tmp ? simple_strtoul (tmp, &end, 16) : 0;
876                         if (tmp)
877                                 tmp = (*end) ? end + 1 : end;
878                 }
879                 mpc8220_fec_set_hwaddr (fec2, env_enet1addr);
880         }
881 #endif
882
883         return 1;
884 }
885
886 /* MII-interface related functions */
887 /********************************************************************/
888 int fec8220_miiphy_read (char *devname, u8 phyAddr, u8 regAddr, u16 * retVal)
889 {
890         ethernet_regs *eth = (ethernet_regs *) MMAP_FEC1;
891         u32 reg;                /* convenient holder for the PHY register */
892         u32 phy;                /* convenient holder for the PHY */
893         int timeout = 0xffff;
894
895         /*
896          * reading from any PHY's register is done by properly
897          * programming the FEC's MII data register.
898          */
899         reg = regAddr << FEC_MII_DATA_RA_SHIFT;
900         phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
901
902         eth->mii_data =
903                 (FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA | phy
904                  | reg);
905
906         /*
907          * wait for the related interrupt
908          */
909         while ((timeout--) && (!(eth->ievent & 0x00800000)));
910
911         if (timeout == 0) {
912 #ifdef DEBUG
913                 printf ("Read MDIO failed...\n");
914 #endif
915                 return -1;
916         }
917
918         /*
919          * clear mii interrupt bit
920          */
921         eth->ievent = 0x00800000;
922
923         /*
924          * it's now safe to read the PHY's register
925          */
926         *retVal = (u16) eth->mii_data;
927
928         return 0;
929 }
930
931 /********************************************************************/
932 int fec8220_miiphy_write (char *devname, u8 phyAddr, u8 regAddr, u16 data)
933 {
934         ethernet_regs *eth = (ethernet_regs *) MMAP_FEC1;
935         u32 reg;                /* convenient holder for the PHY register */
936         u32 phy;                /* convenient holder for the PHY */
937         int timeout = 0xffff;
938
939         reg = regAddr << FEC_MII_DATA_RA_SHIFT;
940         phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
941
942         eth->mii_data = (FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR |
943                          FEC_MII_DATA_TA | phy | reg | data);
944
945         /*
946          * wait for the MII interrupt
947          */
948         while ((timeout--) && (!(eth->ievent & 0x00800000)));
949
950         if (timeout == 0) {
951 #ifdef DEBUG
952                 printf ("Write MDIO failed...\n");
953 #endif
954                 return -1;
955         }
956
957         /*
958          * clear MII interrupt bit
959          */
960         eth->ievent = 0x00800000;
961
962         return 0;
963 }
964
965 #ifdef DEBUG
966 static u32 local_crc32 (char *string, unsigned int crc_value, int len)
967 {
968         int i;
969         char c;
970         unsigned int crc, count;
971
972         /*
973          * crc32 algorithm
974          */
975         /*
976          * crc = 0xffffffff; * The initialized value should be 0xffffffff
977          */
978         crc = crc_value;
979
980         for (i = len; --i >= 0;) {
981                 c = *string++;
982                 for (count = 0; count < 8; count++) {
983                         if ((c & 0x01) ^ (crc & 0x01)) {
984                                 crc >>= 1;
985                                 crc = crc ^ 0xedb88320;
986                         } else {
987                                 crc >>= 1;
988                         }
989                         c >>= 1;
990                 }
991         }
992
993         /*
994          * In big endian system, do byte swaping for crc value
995          */
996         return crc;
997 }
998 #endif /* DEBUG */
999
1000 #endif /* CONFIG_MPC8220_FEC */