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
411 *(vu_long *)MPC5XXX_GPS_PORT_CONFIG |= 0x00020000;
412 } else {
413
414 *(vu_long *)MPC5XXX_GPS_PORT_CONFIG |= 0x00050000;
415 }
416
417
418
419
420 fec->eth->ievent = 0xffffffff;
421
422
423
424
425 fec->eth->imask = 0x00000000;
426
427
428
429
430
431
432
433
434 if (fec->xcv_type != SEVENWIRE) {
435
436
437
438
439
440 fec->eth->mii_speed = (((gd->arch.ipb_clk >> 20) / 5) << 1);
441 }
442
443 if (fec->xcv_type != SEVENWIRE) {
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465 int timeout = 1;
466 uint16 phyStatus;
467
468
469
470
471 miiphy_write(dev->name, phyAddr, 0x0, 0x8000);
472 udelay(1000);
473
474 if (fec->xcv_type == MII10) {
475
476
477
478#if (DEBUG & 0x2)
479 printf("Forcing 10 Mbps ethernet link... ");
480#endif
481 miiphy_read(dev->name, phyAddr, 0x1, &phyStatus);
482
483
484
485 miiphy_write(dev->name, phyAddr, 0x0, 0x0180);
486
487 timeout = 20;
488 do {
489 udelay(10000);
490 if ((timeout--) == 0) {
491#if (DEBUG & 0x2)
492 printf("hmmm, should not have waited...");
493#endif
494 break;
495 }
496 miiphy_read(dev->name, phyAddr, 0x1, &phyStatus);
497#if (DEBUG & 0x2)
498 printf("=");
499#endif
500 } while ((phyStatus & 0x0004));
501
502 timeout = 1000;
503 do {
504 udelay(10000);
505 if ((timeout--) == 0) {
506 printf("failed. Link is down.\n");
507 break;
508 }
509 miiphy_read(dev->name, phyAddr, 0x1, &phyStatus);
510#if (DEBUG & 0x2)
511 printf("+");
512#endif
513 } while (!(phyStatus & 0x0004));
514
515#if (DEBUG & 0x2)
516 printf ("done.\n");
517#endif
518 } else {
519
520
521
522 miiphy_write(dev->name, phyAddr, 0x4, 0x01e1);
523
524
525
526
527 miiphy_write(dev->name, phyAddr, 0x0, 0x1200);
528
529
530
531
532 timeout = 5000;
533 do {
534 udelay(1000);
535
536 if ((timeout--) == 0) {
537#if (DEBUG & 0x2)
538 printf("PHY auto neg 0 failed...\n");
539#endif
540 return -1;
541 }
542
543 if (miiphy_read(dev->name, phyAddr, 0x1, &phyStatus) != 0) {
544#if (DEBUG & 0x2)
545 printf("PHY auto neg 1 failed 0x%04x...\n", phyStatus);
546#endif
547 return -1;
548 }
549 } while (!(phyStatus & 0x0004));
550
551#if (DEBUG & 0x2)
552 printf("PHY auto neg complete! \n");
553#endif
554 }
555
556 }
557
558#if (DEBUG & 0x2)
559 if (fec->xcv_type != SEVENWIRE)
560 mpc5xxx_fec_phydump (dev->name);
561#endif
562
563
564#if (DEBUG & 0x1)
565 printf("mpc5xxx_fec_init_phy... Done \n");
566#endif
567
568 return 1;
569}
570
571
572static void mpc5xxx_fec_halt(struct eth_device *dev)
573{
574 struct mpc5xxx_sdma *sdma = (struct mpc5xxx_sdma *)MPC5XXX_SDMA;
575 mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
576 int counter = 0xffff;
577
578#if (DEBUG & 0x2)
579 if (fec->xcv_type != SEVENWIRE)
580 mpc5xxx_fec_phydump (dev->name);
581#endif
582
583
584
585
586 fec->eth->imask = 0;
587
588
589
590
591 fec->eth->x_cntrl |= 0x00000001;
592
593
594
595
596 while ((counter--) && (!(fec->eth->ievent & 0x10000000))) ;
597
598
599
600
601 SDMA_TASK_DISABLE (FEC_XMIT_TASK_NO);
602 SDMA_TASK_DISABLE (FEC_RECV_TASK_NO);
603
604
605
606
607
608 sdma->PtdCntrl &= ~0x00000001;
609
610
611
612
613 fec->eth->ecntrl &= 0xfffffffd;
614
615
616
617
618 fec->eth->rfifo_status &= 0x00700000;
619 fec->eth->tfifo_status &= 0x00700000;
620
621 fec->eth->reset_cntrl = 0x01000000;
622
623
624
625
626 fec->eth->ecntrl |= 0x1;
627
628
629
630
631 udelay(10);
632
633
634 if (fec->xcv_type != SEVENWIRE) {
635
636
637
638
639
640 fec->eth->mii_speed = (((gd->arch.ipb_clk >> 20) / 5) << 1);
641 }
642
643#if (DEBUG & 0x3)
644 printf("Ethernet task stopped\n");
645#endif
646}
647
648#if (DEBUG & 0x60)
649
650
651static void tfifo_print(char *devname, mpc5xxx_fec_priv *fec)
652{
653 uint16 phyAddr = CONFIG_PHY_ADDR;
654 uint16 phyStatus;
655
656 if ((fec->eth->tfifo_lrf_ptr != fec->eth->tfifo_lwf_ptr)
657 || (fec->eth->tfifo_rdptr != fec->eth->tfifo_wrptr)) {
658
659 miiphy_read(devname, phyAddr, 0x1, &phyStatus);
660 printf("\nphyStatus: 0x%04x\n", phyStatus);
661 printf("ecntrl: 0x%08x\n", fec->eth->ecntrl);
662 printf("ievent: 0x%08x\n", fec->eth->ievent);
663 printf("x_status: 0x%08x\n", fec->eth->x_status);
664 printf("tfifo: status 0x%08x\n", fec->eth->tfifo_status);
665
666 printf(" control 0x%08x\n", fec->eth->tfifo_cntrl);
667 printf(" lrfp 0x%08x\n", fec->eth->tfifo_lrf_ptr);
668 printf(" lwfp 0x%08x\n", fec->eth->tfifo_lwf_ptr);
669 printf(" alarm 0x%08x\n", fec->eth->tfifo_alarm);
670 printf(" readptr 0x%08x\n", fec->eth->tfifo_rdptr);
671 printf(" writptr 0x%08x\n", fec->eth->tfifo_wrptr);
672 }
673}
674
675static void rfifo_print(char *devname, mpc5xxx_fec_priv *fec)
676{
677 uint16 phyAddr = CONFIG_PHY_ADDR;
678 uint16 phyStatus;
679
680 if ((fec->eth->rfifo_lrf_ptr != fec->eth->rfifo_lwf_ptr)
681 || (fec->eth->rfifo_rdptr != fec->eth->rfifo_wrptr)) {
682
683 miiphy_read(devname, phyAddr, 0x1, &phyStatus);
684 printf("\nphyStatus: 0x%04x\n", phyStatus);
685 printf("ecntrl: 0x%08x\n", fec->eth->ecntrl);
686 printf("ievent: 0x%08x\n", fec->eth->ievent);
687 printf("x_status: 0x%08x\n", fec->eth->x_status);
688 printf("rfifo: status 0x%08x\n", fec->eth->rfifo_status);
689
690 printf(" control 0x%08x\n", fec->eth->rfifo_cntrl);
691 printf(" lrfp 0x%08x\n", fec->eth->rfifo_lrf_ptr);
692 printf(" lwfp 0x%08x\n", fec->eth->rfifo_lwf_ptr);
693 printf(" alarm 0x%08x\n", fec->eth->rfifo_alarm);
694 printf(" readptr 0x%08x\n", fec->eth->rfifo_rdptr);
695 printf(" writptr 0x%08x\n", fec->eth->rfifo_wrptr);
696 }
697}
698#endif
699
700
701
702static int mpc5xxx_fec_send(struct eth_device *dev, void *eth_data,
703 int data_length)
704{
705
706
707
708
709 mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
710 volatile FEC_TBD *pTbd;
711
712#if (DEBUG & 0x20)
713 printf("tbd status: 0x%04x\n", fec->tbdBase[0].status);
714 tfifo_print(dev->name, fec);
715#endif
716
717
718
719
720 mpc5xxx_fec_tbd_scrub(fec);
721
722
723
724
725 if ((data_length > 1500) || (data_length <= 0)) {
726 return -1;
727 }
728
729
730
731
732 if (fec->cleanTbdNum < 1) {
733#if (DEBUG & 0x20)
734 printf("No available TxBDs ...\n");
735#endif
736 return -1;
737 }
738
739
740
741
742 pTbd = &fec->tbdBase[fec->tbdIndex];
743 pTbd->dataLength = data_length;
744 pTbd->dataPointer = (uint32)eth_data;
745 pTbd->status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY;
746 fec->tbdIndex = (fec->tbdIndex + 1) % FEC_TBD_NUM;
747
748#if (DEBUG & 0x100)
749 printf("SDMA_TASK_ENABLE, fec->tbdIndex = %d \n", fec->tbdIndex);
750#endif
751
752
753
754
755 if (fec->xcv_type != SEVENWIRE) {
756 uint16 phyStatus;
757 miiphy_read(dev->name, 0, 0x1, &phyStatus);
758 }
759
760
761
762
763
764#if (DEBUG & 0x20)
765 tfifo_print(dev->name, fec);
766#endif
767 SDMA_TASK_ENABLE (FEC_XMIT_TASK_NO);
768#if (DEBUG & 0x20)
769 tfifo_print(dev->name, fec);
770#endif
771#if (DEBUG & 0x8)
772 printf( "+" );
773#endif
774
775 fec->cleanTbdNum -= 1;
776
777#if (DEBUG & 0x129) && (DEBUG & 0x80000000)
778 printf ("smartDMA ethernet Tx task enabled\n");
779#endif
780
781
782
783 while (pTbd->status & FEC_TBD_READY) {
784 udelay(10);
785#if (DEBUG & 0x8)
786 printf ("TDB status = %04x\n", pTbd->status);
787#endif
788 }
789
790 return 0;
791}
792
793
794
795static int mpc5xxx_fec_recv(struct eth_device *dev)
796{
797
798
799
800 mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
801 volatile FEC_RBD *pRbd = &fec->rbdBase[fec->rbdIndex];
802 unsigned long ievent;
803 int frame_length, len = 0;
804 NBUF *frame;
805 uchar buff[FEC_MAX_PKT_SIZE];
806
807#if (DEBUG & 0x1)
808 printf ("mpc5xxx_fec_recv %d Start...\n", fec->rbdIndex);
809#endif
810#if (DEBUG & 0x8)
811 printf( "-" );
812#endif
813
814
815
816
817 ievent = fec->eth->ievent;
818 fec->eth->ievent = ievent;
819 if (ievent & 0x20060000) {
820
821 mpc5xxx_fec_halt(dev);
822 mpc5xxx_fec_init(dev, NULL);
823 return 0;
824 }
825 if (ievent & 0x80000000) {
826
827 fec->eth->x_cntrl |= 0x00000001;
828 }
829 if (ievent & 0x10000000) {
830
831 if (fec->eth->x_cntrl & 0x00000001) {
832 mpc5xxx_fec_halt(dev);
833 fec->eth->x_cntrl &= ~0x00000001;
834 mpc5xxx_fec_init(dev, NULL);
835 }
836 }
837
838 if (!(pRbd->status & FEC_RBD_EMPTY)) {
839 if ((pRbd->status & FEC_RBD_LAST) && !(pRbd->status & FEC_RBD_ERR) &&
840 ((pRbd->dataLength - 4) > 14)) {
841
842
843
844
845 frame = (NBUF *)pRbd->dataPointer;
846 frame_length = pRbd->dataLength - 4;
847
848#if (DEBUG & 0x20)
849 {
850 int i;
851 printf("recv data hdr:");
852 for (i = 0; i < 14; i++)
853 printf("%x ", *(frame->head + i));
854 printf("\n");
855 }
856#endif
857
858
859
860 memcpy(buff, frame->head, 14);
861 memcpy(buff + 14, frame->data, frame_length);
862 net_process_received_packet(buff, frame_length);
863 len = frame_length;
864 }
865
866
867
868 mpc5xxx_fec_rbd_clean(fec, pRbd);
869 }
870 SDMA_CLEAR_IEVENT (FEC_RECV_TASK_NO);
871 return len;
872}
873
874
875
876int mpc5xxx_fec_initialize(bd_t * bis)
877{
878 mpc5xxx_fec_priv *fec;
879 struct eth_device *dev;
880 char *tmp, *end;
881 char env_enetaddr[6];
882 int i;
883
884 fec = (mpc5xxx_fec_priv *)malloc(sizeof(*fec));
885 dev = (struct eth_device *)malloc(sizeof(*dev));
886 memset(dev, 0, sizeof *dev);
887
888 fec->eth = (ethernet_regs *)MPC5XXX_FEC;
889 fec->tbdBase = (FEC_TBD *)FEC_BD_BASE;
890 fec->rbdBase = (FEC_RBD *)(FEC_BD_BASE + FEC_TBD_NUM * sizeof(FEC_TBD));
891#if defined(CONFIG_MPC5xxx_FEC_MII100)
892 fec->xcv_type = MII100;
893#elif defined(CONFIG_MPC5xxx_FEC_MII10)
894 fec->xcv_type = MII10;
895#elif defined(CONFIG_MPC5xxx_FEC_SEVENWIRE)
896 fec->xcv_type = SEVENWIRE;
897#else
898#error fec->xcv_type not initialized.
899#endif
900 if (fec->xcv_type != SEVENWIRE) {
901
902
903
904
905
906 fec->eth->mii_speed = (((gd->arch.ipb_clk >> 20) / 5) << 1);
907 }
908
909 dev->priv = (void *)fec;
910 dev->iobase = MPC5XXX_FEC;
911 dev->init = mpc5xxx_fec_init;
912 dev->halt = mpc5xxx_fec_halt;
913 dev->send = mpc5xxx_fec_send;
914 dev->recv = mpc5xxx_fec_recv;
915
916 strcpy(dev->name, "FEC");
917 eth_register(dev);
918
919#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
920 miiphy_register (dev->name,
921 fec5xxx_miiphy_read, fec5xxx_miiphy_write);
922#endif
923
924
925
926
927
928
929 tmp = getenv("ethaddr");
930 if (tmp) {
931 for (i=0; i<6; i++) {
932 env_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;
933 if (tmp)
934 tmp = (*end) ? end+1 : end;
935 }
936 mpc5xxx_fec_set_hwaddr(fec, env_enetaddr);
937 }
938
939 return 1;
940}
941
942
943
944int fec5xxx_miiphy_read(const char *devname, uint8 phyAddr, uint8 regAddr, uint16 * retVal)
945{
946 ethernet_regs *eth = (ethernet_regs *)MPC5XXX_FEC;
947 uint32 reg;
948 uint32 phy;
949 int timeout = 0xffff;
950
951
952
953
954
955 reg = regAddr << FEC_MII_DATA_RA_SHIFT;
956 phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
957
958 eth->mii_data = (FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA | phy | reg);
959
960
961
962
963 while ((timeout--) && (!(eth->ievent & 0x00800000))) ;
964
965 if (timeout == 0) {
966#if (DEBUG & 0x2)
967 printf ("Read MDIO failed...\n");
968#endif
969 return -1;
970 }
971
972
973
974
975 eth->ievent = 0x00800000;
976
977
978
979
980 *retVal = (uint16) eth->mii_data;
981
982 return 0;
983}
984
985
986int fec5xxx_miiphy_write(const char *devname, uint8 phyAddr, uint8 regAddr, uint16 data)
987{
988 ethernet_regs *eth = (ethernet_regs *)MPC5XXX_FEC;
989 uint32 reg;
990 uint32 phy;
991 int timeout = 0xffff;
992
993 reg = regAddr << FEC_MII_DATA_RA_SHIFT;
994 phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
995
996 eth->mii_data = (FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR |
997 FEC_MII_DATA_TA | phy | reg | data);
998
999
1000
1001
1002 while ((timeout--) && (!(eth->ievent & 0x00800000))) ;
1003
1004 if (timeout == 0) {
1005#if (DEBUG & 0x2)
1006 printf ("Write MDIO failed...\n");
1007#endif
1008 return -1;
1009 }
1010
1011
1012
1013
1014 eth->ievent = 0x00800000;
1015
1016 return 0;
1017}
1018