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