1
2
3
4
5
6
7
8
9#include <common.h>
10#include <mpc5xxx.h>
11#include <mpc5xxx_sdma.h>
12#include <malloc.h>
13#include <net.h>
14#include <netdev.h>
15#include <miiphy.h>
16#include "mpc5xxx_fec.h"
17
18DECLARE_GLOBAL_DATA_PTR;
19
20
21
22#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
23#error "CONFIG_MII has to be defined!"
24#endif
25
26#if (DEBUG & 0x60)
27static void tfifo_print(char *devname, mpc5xxx_fec_priv *fec);
28static void rfifo_print(char *devname, mpc5xxx_fec_priv *fec);
29#endif
30
31#if (DEBUG & 0x40)
32static uint32 local_crc32(char *string, unsigned int crc_value, int len);
33#endif
34
35typedef struct {
36 uint8 data[1500];
37 int length;
38 int used;
39 uint8 head[16];
40} NBUF;
41
42int fec5xxx_miiphy_read(char *devname, uint8 phyAddr, uint8 regAddr, uint16 * retVal);
43int fec5xxx_miiphy_write(char *devname, uint8 phyAddr, uint8 regAddr, uint16 data);
44
45static int mpc5xxx_fec_init_phy(struct eth_device *dev, bd_t * bis);
46
47
48#if (DEBUG & 0x2)
49static void mpc5xxx_fec_phydump (char *devname)
50{
51 uint16 phyStatus, i;
52 uint8 phyAddr = CONFIG_PHY_ADDR;
53 uint8 reg_mask[] = {
54#if CONFIG_PHY_TYPE == 0x79c874
55
56 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
57 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
58#else
59
60 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
61 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
62#endif
63 };
64
65 for (i = 0; i < 32; i++) {
66 if (reg_mask[i]) {
67 miiphy_read(devname, phyAddr, i, &phyStatus);
68 printf("Mii reg %d: 0x%04x\n", i, phyStatus);
69 }
70 }
71}
72#endif
73
74
75static int mpc5xxx_fec_rbd_init(mpc5xxx_fec_priv *fec)
76{
77 int ix;
78 char *data;
79 static int once = 0;
80
81 for (ix = 0; ix < FEC_RBD_NUM; ix++) {
82 if (!once) {
83 data = (char *)malloc(FEC_MAX_PKT_SIZE);
84 if (data == NULL) {
85 printf ("RBD INIT FAILED\n");
86 return -1;
87 }
88 fec->rbdBase[ix].dataPointer = (uint32)data;
89 }
90 fec->rbdBase[ix].status = FEC_RBD_EMPTY;
91 fec->rbdBase[ix].dataLength = 0;
92 }
93 once ++;
94
95
96
97
98 fec->rbdBase[ix - 1].status |= FEC_RBD_WRAP;
99 fec->rbdIndex = 0;
100
101 return 0;
102}
103
104
105static void mpc5xxx_fec_tbd_init(mpc5xxx_fec_priv *fec)
106{
107 int ix;
108
109 for (ix = 0; ix < FEC_TBD_NUM; ix++) {
110 fec->tbdBase[ix].status = 0;
111 }
112
113
114
115
116 fec->tbdBase[ix - 1].status |= FEC_TBD_WRAP;
117
118
119
120
121 fec->tbdIndex = 0;
122 fec->usedTbdIndex = 0;
123 fec->cleanTbdNum = FEC_TBD_NUM;
124}
125
126
127static void mpc5xxx_fec_rbd_clean(mpc5xxx_fec_priv *fec, volatile FEC_RBD * pRbd)
128{
129
130
131
132 if ((fec->rbdIndex) == (FEC_RBD_NUM - 1))
133 pRbd->status = (FEC_RBD_WRAP | FEC_RBD_EMPTY);
134 else
135 pRbd->status = FEC_RBD_EMPTY;
136
137 pRbd->dataLength = 0;
138
139
140
141
142 SDMA_TASK_ENABLE(FEC_RECV_TASK_NO);
143
144
145
146
147 fec->rbdIndex = (fec->rbdIndex + 1) % FEC_RBD_NUM;
148}
149
150
151static void mpc5xxx_fec_tbd_scrub(mpc5xxx_fec_priv *fec)
152{
153 volatile FEC_TBD *pUsedTbd;
154
155#if (DEBUG & 0x1)
156 printf ("tbd_scrub: fec->cleanTbdNum = %d, fec->usedTbdIndex = %d\n",
157 fec->cleanTbdNum, fec->usedTbdIndex);
158#endif
159
160
161
162
163 while (fec->cleanTbdNum < FEC_TBD_NUM) {
164 pUsedTbd = &fec->tbdBase[fec->usedTbdIndex];
165 if (pUsedTbd->status & FEC_TBD_READY) {
166#if (DEBUG & 0x20)
167 printf("Cannot clean TBD %d, in use\n", fec->cleanTbdNum);
168#endif
169 return;
170 }
171
172
173
174
175 if (fec->usedTbdIndex == (FEC_TBD_NUM - 1))
176 pUsedTbd->status = FEC_TBD_WRAP;
177 else
178 pUsedTbd->status = 0;
179
180
181
182
183 fec->cleanTbdNum++;
184 fec->usedTbdIndex = (fec->usedTbdIndex + 1) % FEC_TBD_NUM;
185 }
186}
187
188
189static void mpc5xxx_fec_set_hwaddr(mpc5xxx_fec_priv *fec, char *mac)
190{
191 uint8 currByte;
192 int byte;
193 int bit;
194 uint32 crc = 0xffffffff;
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211 for (byte = 0; byte < 6; byte++) {
212 currByte = mac[byte];
213 for (bit = 0; bit < 8; bit++) {
214 if ((currByte & 0x01) ^ (crc & 0x01)) {
215 crc >>= 1;
216 crc = crc ^ 0xedb88320;
217 } else {
218 crc >>= 1;
219 }
220 currByte >>= 1;
221 }
222 }
223
224 crc = crc >> 26;
225
226
227
228
229 if (crc >= 32) {
230 fec->eth->iaddr1 = (1 << (crc - 32));
231 fec->eth->iaddr2 = 0;
232 } else {
233 fec->eth->iaddr1 = 0;
234 fec->eth->iaddr2 = (1 << crc);
235 }
236
237
238
239
240 fec->eth->paddr1 = (mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3];
241 fec->eth->paddr2 = (mac[4] << 24) + (mac[5] << 16) + 0x8808;
242}
243
244
245static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis)
246{
247 mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
248 struct mpc5xxx_sdma *sdma = (struct mpc5xxx_sdma *)MPC5XXX_SDMA;
249
250#if (DEBUG & 0x1)
251 printf ("mpc5xxx_fec_init... Begin\n");
252#endif
253
254 mpc5xxx_fec_init_phy(dev, bis);
255
256
257
258
259 mpc5xxx_fec_rbd_init(fec);
260 mpc5xxx_fec_tbd_init(fec);
261
262
263
264
265 fec->eth->ievent = 0xffffffff;
266
267
268
269
270 fec->eth->imask = 0x00000000;
271
272
273
274
275 if (fec->xcv_type == SEVENWIRE) {
276
277
278
279 fec->eth->r_cntrl = 0x05ee0020;
280 } else {
281
282
283
284 fec->eth->r_cntrl = 0x05ee0024;
285 }
286
287 fec->eth->x_cntrl = 0x00000000;
288
289
290
291
292 fec->eth->op_pause = 0x00010020;
293
294
295
296
297 fec->eth->rfifo_cntrl = 0x0c000000
298 | (fec->eth->rfifo_cntrl & ~0x0f000000);
299 fec->eth->rfifo_alarm = 0x0000030c;
300#if (DEBUG & 0x22)
301 if (fec->eth->rfifo_status & 0x00700000 ) {
302 printf("mpc5xxx_fec_init() RFIFO error\n");
303 }
304#endif
305
306
307
308
309 fec->eth->tfifo_cntrl = 0x0c000000
310 | (fec->eth->tfifo_cntrl & ~0x0f000000);
311#if (DEBUG & 0x2)
312 printf("tfifo_status: 0x%08x\n", fec->eth->tfifo_status);
313 printf("tfifo_alarm: 0x%08x\n", fec->eth->tfifo_alarm);
314#endif
315
316
317
318
319 fec->eth->tfifo_alarm = 0x00000080;
320 fec->eth->x_wmrk = 0x2;
321
322
323
324
325
326 mpc5xxx_fec_set_hwaddr(fec, (char *)dev->enetaddr);
327
328
329
330
331 fec->eth->gaddr1 = 0x00000000;
332 fec->eth->gaddr2 = 0x00000000;
333
334
335
336
337 fec->eth->xmit_fsm = 0x03000000;
338
339#if defined(CONFIG_MPC5200)
340
341
342
343
344 sdma->PtdCntrl |= 0x00000001;
345#endif
346
347
348
349
350 sdma->IPR0 = 7;
351 sdma->IPR3 = 6;
352 sdma->IPR4 = 5;
353
354
355
356
357 SDMA_CLEAR_IEVENT(FEC_RECV_TASK_NO);
358
359
360
361
362 *(volatile int *)FEC_TBD_BASE = (int)fec->tbdBase;
363 *(volatile int *)FEC_RBD_BASE = (int)fec->rbdBase;
364 *(volatile int *)FEC_TBD_NEXT = (int)fec->tbdBase;
365 *(volatile int *)FEC_RBD_NEXT = (int)fec->rbdBase;
366
367
368
369
370 fec->eth->ecntrl |= 0x00000006;
371
372#if (DEBUG & 0x2)
373 if (fec->xcv_type != SEVENWIRE)
374 mpc5xxx_fec_phydump (dev->name);
375#endif
376
377
378
379
380 SDMA_TASK_ENABLE(FEC_RECV_TASK_NO);
381
382#if (DEBUG & 0x1)
383 printf("mpc5xxx_fec_init... Done \n");
384#endif
385
386 return 1;
387}
388
389
390static int mpc5xxx_fec_init_phy(struct eth_device *dev, bd_t * bis)
391{
392 mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
393 const uint8 phyAddr = CONFIG_PHY_ADDR;
394 static int initialized = 0;
395
396 if(initialized)
397 return 0;
398 initialized = 1;
399
400#if (DEBUG & 0x1)
401 printf ("mpc5xxx_fec_init_phy... Begin\n");
402#endif
403
404
405
406
407 if (fec->xcv_type == SEVENWIRE) {
408
409#if defined(CONFIG_TOTAL5200)
410
411 *(vu_long *)MPC5XXX_GPS_PORT_CONFIG |= 0x00030000;
412#else
413
414 *(vu_long *)MPC5XXX_GPS_PORT_CONFIG |= 0x00020000;
415#endif
416 } else {
417
418 *(vu_long *)MPC5XXX_GPS_PORT_CONFIG |= 0x00050000;
419 }
420
421
422
423
424 fec->eth->ievent = 0xffffffff;
425
426
427
428
429 fec->eth->imask = 0x00000000;
430
431
432
433
434
435
436
437
438 if (fec->xcv_type != SEVENWIRE) {
439
440
441
442
443 fec->eth->mii_speed = (((gd->ipb_clk >> 20) / 5) << 1);
444 }
445
446 if (fec->xcv_type != SEVENWIRE) {
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468 int timeout = 1;
469 uint16 phyStatus;
470
471
472
473
474 miiphy_write(dev->name, phyAddr, 0x0, 0x8000);
475 udelay(1000);
476
477#if defined(CONFIG_UC101) || defined(CONFIG_MUCMC52)
478
479
480 miiphy_write(dev->name, phyAddr, 0x14, 0x4122);
481#endif
482 if (fec->xcv_type == MII10) {
483
484
485
486#if (DEBUG & 0x2)
487 printf("Forcing 10 Mbps ethernet link... ");
488#endif
489 miiphy_read(dev->name, phyAddr, 0x1, &phyStatus);
490
491
492
493 miiphy_write(dev->name, phyAddr, 0x0, 0x0180);
494
495 timeout = 20;
496 do {
497 udelay(10000);
498 if ((timeout--) == 0) {
499#if (DEBUG & 0x2)
500 printf("hmmm, should not have waited...");
501#endif
502 break;
503 }
504 miiphy_read(dev->name, phyAddr, 0x1, &phyStatus);
505#if (DEBUG & 0x2)
506 printf("=");
507#endif
508 } while ((phyStatus & 0x0004));
509
510 timeout = 1000;
511 do {
512 udelay(10000);
513 if ((timeout--) == 0) {
514 printf("failed. Link is down.\n");
515 break;
516 }
517 miiphy_read(dev->name, phyAddr, 0x1, &phyStatus);
518#if (DEBUG & 0x2)
519 printf("+");
520#endif
521 } while (!(phyStatus & 0x0004));
522
523#if (DEBUG & 0x2)
524 printf ("done.\n");
525#endif
526 } else {
527
528
529
530 miiphy_write(dev->name, phyAddr, 0x4, 0x01e1);
531
532
533
534
535 miiphy_write(dev->name, phyAddr, 0x0, 0x1200);
536
537
538
539
540 timeout = 5000;
541 do {
542 udelay(1000);
543
544 if ((timeout--) == 0) {
545#if (DEBUG & 0x2)
546 printf("PHY auto neg 0 failed...\n");
547#endif
548 return -1;
549 }
550
551 if (miiphy_read(dev->name, phyAddr, 0x1, &phyStatus) != 0) {
552#if (DEBUG & 0x2)
553 printf("PHY auto neg 1 failed 0x%04x...\n", phyStatus);
554#endif
555 return -1;
556 }
557 } while (!(phyStatus & 0x0004));
558
559#if (DEBUG & 0x2)
560 printf("PHY auto neg complete! \n");
561#endif
562 }
563
564 }
565
566#if (DEBUG & 0x2)
567 if (fec->xcv_type != SEVENWIRE)
568 mpc5xxx_fec_phydump (dev->name);
569#endif
570
571
572#if (DEBUG & 0x1)
573 printf("mpc5xxx_fec_init_phy... Done \n");
574#endif
575
576 return 1;
577}
578
579
580static void mpc5xxx_fec_halt(struct eth_device *dev)
581{
582#if defined(CONFIG_MPC5200)
583 struct mpc5xxx_sdma *sdma = (struct mpc5xxx_sdma *)MPC5XXX_SDMA;
584#endif
585 mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
586 int counter = 0xffff;
587
588#if (DEBUG & 0x2)
589 if (fec->xcv_type != SEVENWIRE)
590 mpc5xxx_fec_phydump (dev->name);
591#endif
592
593
594
595
596 fec->eth->imask = 0;
597
598
599
600
601 fec->eth->x_cntrl |= 0x00000001;
602
603
604
605
606 while ((counter--) && (!(fec->eth->ievent & 0x10000000))) ;
607
608
609
610
611 SDMA_TASK_DISABLE (FEC_XMIT_TASK_NO);
612 SDMA_TASK_DISABLE (FEC_RECV_TASK_NO);
613
614#if defined(CONFIG_MPC5200)
615
616
617
618
619 sdma->PtdCntrl &= ~0x00000001;
620#endif
621
622
623
624
625 fec->eth->ecntrl &= 0xfffffffd;
626
627
628
629
630 fec->eth->rfifo_status &= 0x00700000;
631 fec->eth->tfifo_status &= 0x00700000;
632
633 fec->eth->reset_cntrl = 0x01000000;
634
635
636
637
638 fec->eth->ecntrl |= 0x1;
639
640
641
642
643 udelay(10);
644
645
646 if (fec->xcv_type != SEVENWIRE) {
647
648
649
650
651 fec->eth->mii_speed = (((gd->ipb_clk >> 20) / 5) << 1);
652 }
653
654#if (DEBUG & 0x3)
655 printf("Ethernet task stopped\n");
656#endif
657}
658
659#if (DEBUG & 0x60)
660
661
662static void tfifo_print(char *devname, mpc5xxx_fec_priv *fec)
663{
664 uint16 phyAddr = CONFIG_PHY_ADDR;
665 uint16 phyStatus;
666
667 if ((fec->eth->tfifo_lrf_ptr != fec->eth->tfifo_lwf_ptr)
668 || (fec->eth->tfifo_rdptr != fec->eth->tfifo_wrptr)) {
669
670 miiphy_read(devname, phyAddr, 0x1, &phyStatus);
671 printf("\nphyStatus: 0x%04x\n", phyStatus);
672 printf("ecntrl: 0x%08x\n", fec->eth->ecntrl);
673 printf("ievent: 0x%08x\n", fec->eth->ievent);
674 printf("x_status: 0x%08x\n", fec->eth->x_status);
675 printf("tfifo: status 0x%08x\n", fec->eth->tfifo_status);
676
677 printf(" control 0x%08x\n", fec->eth->tfifo_cntrl);
678 printf(" lrfp 0x%08x\n", fec->eth->tfifo_lrf_ptr);
679 printf(" lwfp 0x%08x\n", fec->eth->tfifo_lwf_ptr);
680 printf(" alarm 0x%08x\n", fec->eth->tfifo_alarm);
681 printf(" readptr 0x%08x\n", fec->eth->tfifo_rdptr);
682 printf(" writptr 0x%08x\n", fec->eth->tfifo_wrptr);
683 }
684}
685
686static void rfifo_print(char *devname, mpc5xxx_fec_priv *fec)
687{
688 uint16 phyAddr = CONFIG_PHY_ADDR;
689 uint16 phyStatus;
690
691 if ((fec->eth->rfifo_lrf_ptr != fec->eth->rfifo_lwf_ptr)
692 || (fec->eth->rfifo_rdptr != fec->eth->rfifo_wrptr)) {
693
694 miiphy_read(devname, phyAddr, 0x1, &phyStatus);
695 printf("\nphyStatus: 0x%04x\n", phyStatus);
696 printf("ecntrl: 0x%08x\n", fec->eth->ecntrl);
697 printf("ievent: 0x%08x\n", fec->eth->ievent);
698 printf("x_status: 0x%08x\n", fec->eth->x_status);
699 printf("rfifo: status 0x%08x\n", fec->eth->rfifo_status);
700
701 printf(" control 0x%08x\n", fec->eth->rfifo_cntrl);
702 printf(" lrfp 0x%08x\n", fec->eth->rfifo_lrf_ptr);
703 printf(" lwfp 0x%08x\n", fec->eth->rfifo_lwf_ptr);
704 printf(" alarm 0x%08x\n", fec->eth->rfifo_alarm);
705 printf(" readptr 0x%08x\n", fec->eth->rfifo_rdptr);
706 printf(" writptr 0x%08x\n", fec->eth->rfifo_wrptr);
707 }
708}
709#endif
710
711
712
713static int mpc5xxx_fec_send(struct eth_device *dev, volatile void *eth_data,
714 int data_length)
715{
716
717
718
719
720 mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
721 volatile FEC_TBD *pTbd;
722
723#if (DEBUG & 0x20)
724 printf("tbd status: 0x%04x\n", fec->tbdBase[0].status);
725 tfifo_print(dev->name, fec);
726#endif
727
728
729
730
731 mpc5xxx_fec_tbd_scrub(fec);
732
733
734
735
736 if ((data_length > 1500) || (data_length <= 0)) {
737 return -1;
738 }
739
740
741
742
743 if (fec->cleanTbdNum < 1) {
744#if (DEBUG & 0x20)
745 printf("No available TxBDs ...\n");
746#endif
747 return -1;
748 }
749
750
751
752
753 pTbd = &fec->tbdBase[fec->tbdIndex];
754 pTbd->dataLength = data_length;
755 pTbd->dataPointer = (uint32)eth_data;
756 pTbd->status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY;
757 fec->tbdIndex = (fec->tbdIndex + 1) % FEC_TBD_NUM;
758
759#if (DEBUG & 0x100)
760 printf("SDMA_TASK_ENABLE, fec->tbdIndex = %d \n", fec->tbdIndex);
761#endif
762
763
764
765
766 if (fec->xcv_type != SEVENWIRE) {
767 uint16 phyStatus;
768 miiphy_read(dev->name, 0, 0x1, &phyStatus);
769 }
770
771
772
773
774
775#if (DEBUG & 0x20)
776 tfifo_print(dev->name, fec);
777#endif
778 SDMA_TASK_ENABLE (FEC_XMIT_TASK_NO);
779#if (DEBUG & 0x20)
780 tfifo_print(dev->name, fec);
781#endif
782#if (DEBUG & 0x8)
783 printf( "+" );
784#endif
785
786 fec->cleanTbdNum -= 1;
787
788#if (DEBUG & 0x129) && (DEBUG & 0x80000000)
789 printf ("smartDMA ethernet Tx task enabled\n");
790#endif
791
792
793
794 while (pTbd->status & FEC_TBD_READY) {
795 udelay(10);
796#if (DEBUG & 0x8)
797 printf ("TDB status = %04x\n", pTbd->status);
798#endif
799 }
800
801 return 0;
802}
803
804
805
806static int mpc5xxx_fec_recv(struct eth_device *dev)
807{
808
809
810
811 mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
812 volatile FEC_RBD *pRbd = &fec->rbdBase[fec->rbdIndex];
813 unsigned long ievent;
814 int frame_length, len = 0;
815 NBUF *frame;
816 uchar buff[FEC_MAX_PKT_SIZE];
817
818#if (DEBUG & 0x1)
819 printf ("mpc5xxx_fec_recv %d Start...\n", fec->rbdIndex);
820#endif
821#if (DEBUG & 0x8)
822 printf( "-" );
823#endif
824
825
826
827
828 ievent = fec->eth->ievent;
829 fec->eth->ievent = ievent;
830 if (ievent & 0x20060000) {
831
832 mpc5xxx_fec_halt(dev);
833 mpc5xxx_fec_init(dev, NULL);
834 return 0;
835 }
836 if (ievent & 0x80000000) {
837
838 fec->eth->x_cntrl |= 0x00000001;
839 }
840 if (ievent & 0x10000000) {
841
842 if (fec->eth->x_cntrl & 0x00000001) {
843 mpc5xxx_fec_halt(dev);
844 fec->eth->x_cntrl &= ~0x00000001;
845 mpc5xxx_fec_init(dev, NULL);
846 }
847 }
848
849 if (!(pRbd->status & FEC_RBD_EMPTY)) {
850 if ((pRbd->status & FEC_RBD_LAST) && !(pRbd->status & FEC_RBD_ERR) &&
851 ((pRbd->dataLength - 4) > 14)) {
852
853
854
855
856 frame = (NBUF *)pRbd->dataPointer;
857 frame_length = pRbd->dataLength - 4;
858
859#if (DEBUG & 0x20)
860 {
861 int i;
862 printf("recv data hdr:");
863 for (i = 0; i < 14; i++)
864 printf("%x ", *(frame->head + i));
865 printf("\n");
866 }
867#endif
868
869
870
871 memcpy(buff, frame->head, 14);
872 memcpy(buff + 14, frame->data, frame_length);
873 NetReceive(buff, frame_length);
874 len = frame_length;
875 }
876
877
878
879 mpc5xxx_fec_rbd_clean(fec, pRbd);
880 }
881 SDMA_CLEAR_IEVENT (FEC_RECV_TASK_NO);
882 return len;
883}
884
885
886
887int mpc5xxx_fec_initialize(bd_t * bis)
888{
889 mpc5xxx_fec_priv *fec;
890 struct eth_device *dev;
891 char *tmp, *end;
892 char env_enetaddr[6];
893 int i;
894
895 fec = (mpc5xxx_fec_priv *)malloc(sizeof(*fec));
896 dev = (struct eth_device *)malloc(sizeof(*dev));
897 memset(dev, 0, sizeof *dev);
898
899 fec->eth = (ethernet_regs *)MPC5XXX_FEC;
900 fec->tbdBase = (FEC_TBD *)FEC_BD_BASE;
901 fec->rbdBase = (FEC_RBD *)(FEC_BD_BASE + FEC_TBD_NUM * sizeof(FEC_TBD));
902#if defined(CONFIG_MPC5xxx_FEC_MII100)
903 fec->xcv_type = MII100;
904#elif defined(CONFIG_MPC5xxx_FEC_MII10)
905 fec->xcv_type = MII10;
906#elif defined(CONFIG_MPC5xxx_FEC_SEVENWIRE)
907 fec->xcv_type = SEVENWIRE;
908#else
909#error fec->xcv_type not initialized.
910#endif
911 if (fec->xcv_type != SEVENWIRE) {
912
913
914
915
916 fec->eth->mii_speed = (((gd->ipb_clk >> 20) / 5) << 1);
917 }
918
919 dev->priv = (void *)fec;
920 dev->iobase = MPC5XXX_FEC;
921 dev->init = mpc5xxx_fec_init;
922 dev->halt = mpc5xxx_fec_halt;
923 dev->send = mpc5xxx_fec_send;
924 dev->recv = mpc5xxx_fec_recv;
925
926 sprintf(dev->name, "FEC ETHERNET");
927 eth_register(dev);
928
929#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
930 miiphy_register (dev->name,
931 fec5xxx_miiphy_read, fec5xxx_miiphy_write);
932#endif
933
934
935
936
937
938
939 tmp = getenv("ethaddr");
940 if (tmp) {
941 for (i=0; i<6; i++) {
942 env_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;
943 if (tmp)
944 tmp = (*end) ? end+1 : end;
945 }
946 mpc5xxx_fec_set_hwaddr(fec, env_enetaddr);
947 }
948
949 return 1;
950}
951
952
953
954int fec5xxx_miiphy_read(char *devname, uint8 phyAddr, uint8 regAddr, uint16 * retVal)
955{
956 ethernet_regs *eth = (ethernet_regs *)MPC5XXX_FEC;
957 uint32 reg;
958 uint32 phy;
959 int timeout = 0xffff;
960
961
962
963
964
965 reg = regAddr << FEC_MII_DATA_RA_SHIFT;
966 phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
967
968 eth->mii_data = (FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA | phy | reg);
969
970
971
972
973 while ((timeout--) && (!(eth->ievent & 0x00800000))) ;
974
975 if (timeout == 0) {
976#if (DEBUG & 0x2)
977 printf ("Read MDIO failed...\n");
978#endif
979 return -1;
980 }
981
982
983
984
985 eth->ievent = 0x00800000;
986
987
988
989
990 *retVal = (uint16) eth->mii_data;
991
992 return 0;
993}
994
995
996int fec5xxx_miiphy_write(char *devname, uint8 phyAddr, uint8 regAddr, uint16 data)
997{
998 ethernet_regs *eth = (ethernet_regs *)MPC5XXX_FEC;
999 uint32 reg;
1000 uint32 phy;
1001 int timeout = 0xffff;
1002
1003 reg = regAddr << FEC_MII_DATA_RA_SHIFT;
1004 phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
1005
1006 eth->mii_data = (FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR |
1007 FEC_MII_DATA_TA | phy | reg | data);
1008
1009
1010
1011
1012 while ((timeout--) && (!(eth->ievent & 0x00800000))) ;
1013
1014 if (timeout == 0) {
1015#if (DEBUG & 0x2)
1016 printf ("Write MDIO failed...\n");
1017#endif
1018 return -1;
1019 }
1020
1021
1022
1023
1024 eth->ievent = 0x00800000;
1025
1026 return 0;
1027}
1028
1029#if (DEBUG & 0x40)
1030static uint32 local_crc32(char *string, unsigned int crc_value, int len)
1031{
1032 int i;
1033 char c;
1034 unsigned int crc, count;
1035
1036
1037
1038
1039
1040
1041
1042 crc = crc_value;
1043
1044 for (i = len; --i >= 0;) {
1045 c = *string++;
1046 for (count = 0; count < 8; count++) {
1047 if ((c & 0x01) ^ (crc & 0x01)) {
1048 crc >>= 1;
1049 crc = crc ^ 0xedb88320;
1050 } else {
1051 crc >>= 1;
1052 }
1053 c >>= 1;
1054 }
1055 }
1056
1057
1058
1059
1060 return crc;
1061}
1062#endif
1063