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