1
2
3
4
5
6
7
8#include <common.h>
9#include <malloc.h>
10#include <commproc.h>
11#include <net.h>
12#include <command.h>
13
14DECLARE_GLOBAL_DATA_PTR;
15
16#undef ET_DEBUG
17
18#if defined(CONFIG_CMD_NET) && \
19 (defined(FEC_ENET) || defined(CONFIG_ETHER_ON_FEC1) || defined(CONFIG_ETHER_ON_FEC2))
20
21
22#if defined(FEC_ENET) && !defined(CONFIG_ETHER_ON_FEC1) && !defined(CONFIG_ETHER_ON_FEC2)
23#define CONFIG_ETHER_ON_FEC1 1
24#endif
25
26
27#if defined(CONFIG_SYS_DISCOVER_PHY) || defined(CONFIG_FEC1_PHY) || defined(CONFIG_FEC2_PHY)
28#define WANT_MII
29#else
30#undef WANT_MII
31#endif
32
33#if defined(WANT_MII)
34#include <miiphy.h>
35
36#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
37#error "CONFIG_MII has to be defined!"
38#endif
39
40#endif
41
42#if defined(CONFIG_RMII) && !defined(WANT_MII)
43#error RMII support is unusable without a working PHY.
44#endif
45
46#ifdef CONFIG_SYS_DISCOVER_PHY
47static int mii_discover_phy(struct eth_device *dev);
48#endif
49
50int fec8xx_miiphy_read(const char *devname, unsigned char addr,
51 unsigned char reg, unsigned short *value);
52int fec8xx_miiphy_write(const char *devname, unsigned char addr,
53 unsigned char reg, unsigned short value);
54
55static struct ether_fcc_info_s
56{
57 int ether_index;
58 int fecp_offset;
59 int phy_addr;
60 int actual_phy_addr;
61 int initialized;
62}
63 ether_fcc_info[] = {
64#if defined(CONFIG_ETHER_ON_FEC1)
65 {
66 0,
67 offsetof(immap_t, im_cpm.cp_fec1),
68#if defined(CONFIG_FEC1_PHY)
69 CONFIG_FEC1_PHY,
70#else
71 -1,
72#endif
73 -1,
74 0,
75
76 },
77#endif
78#if defined(CONFIG_ETHER_ON_FEC2)
79 {
80 1,
81 offsetof(immap_t, im_cpm.cp_fec2),
82#if defined(CONFIG_FEC2_PHY)
83 CONFIG_FEC2_PHY,
84#else
85 -1,
86#endif
87 -1,
88 0,
89 },
90#endif
91};
92
93
94#define DBUF_LENGTH 1520
95
96#define TX_BUF_CNT 2
97
98#define TOUT_LOOP 100
99
100#define PKT_MAXBUF_SIZE 1518
101#define PKT_MINBUF_SIZE 64
102#define PKT_MAXBLR_SIZE 1520
103
104#ifdef __GNUC__
105static char txbuf[DBUF_LENGTH] __attribute__ ((aligned(8)));
106#else
107#error txbuf must be aligned.
108#endif
109
110static uint rxIdx;
111static uint txIdx;
112
113
114
115
116
117
118
119typedef volatile struct CommonBufferDescriptor {
120 cbd_t rxbd[PKTBUFSRX];
121 cbd_t txbd[TX_BUF_CNT];
122} RTXBD;
123
124static RTXBD *rtx = NULL;
125
126static int fec_send(struct eth_device *dev, void *packet, int length);
127static int fec_recv(struct eth_device* dev);
128static int fec_init(struct eth_device* dev, bd_t * bd);
129static void fec_halt(struct eth_device* dev);
130#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
131static void __mii_init(void);
132#endif
133
134int fec_initialize(bd_t *bis)
135{
136 struct eth_device* dev;
137 struct ether_fcc_info_s *efis;
138 int i;
139
140 for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++) {
141
142 dev = malloc(sizeof(*dev));
143 if (dev == NULL)
144 hang();
145
146 memset(dev, 0, sizeof(*dev));
147
148
149
150 if (i == 0) {
151 sprintf (dev->name, "FEC");
152 } else {
153 sprintf (dev->name, "FEC%d",
154 ether_fcc_info[i].ether_index + 1);
155 }
156
157 efis = ðer_fcc_info[i];
158
159
160
161
162 efis->actual_phy_addr = -1;
163
164 dev->priv = efis;
165 dev->init = fec_init;
166 dev->halt = fec_halt;
167 dev->send = fec_send;
168 dev->recv = fec_recv;
169
170 eth_register(dev);
171
172#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
173 miiphy_register(dev->name,
174 fec8xx_miiphy_read, fec8xx_miiphy_write);
175#endif
176 }
177 return 1;
178}
179
180static int fec_send(struct eth_device *dev, void *packet, int length)
181{
182 int j, rc;
183 struct ether_fcc_info_s *efis = dev->priv;
184 volatile fec_t *fecp = (volatile fec_t *)(CONFIG_SYS_IMMR + efis->fecp_offset);
185
186
187
188
189 j = 0;
190 while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j<TOUT_LOOP)) {
191 udelay(1);
192 j++;
193 }
194 if (j>=TOUT_LOOP) {
195 printf("TX not ready\n");
196 }
197
198 rtx->txbd[txIdx].cbd_bufaddr = (uint)packet;
199 rtx->txbd[txIdx].cbd_datlen = length;
200 rtx->txbd[txIdx].cbd_sc |= BD_ENET_TX_READY | BD_ENET_TX_LAST;
201 __asm__ ("eieio");
202
203
204 fecp->fec_x_des_active = 0x01000000;
205
206 j = 0;
207 while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j<TOUT_LOOP)) {
208#if defined(CONFIG_ICU862)
209 udelay(10);
210#else
211 udelay(1);
212#endif
213 j++;
214 }
215 if (j>=TOUT_LOOP) {
216 printf("TX timeout\n");
217 }
218#ifdef ET_DEBUG
219 printf("%s[%d] %s: cycles: %d status: %x retry cnt: %d\n",
220 __FILE__,__LINE__,__FUNCTION__,j,rtx->txbd[txIdx].cbd_sc,
221 (rtx->txbd[txIdx].cbd_sc & 0x003C)>>2);
222#endif
223 ;
224 rc = (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_STATS);
225
226 txIdx = (txIdx + 1) % TX_BUF_CNT;
227
228 return rc;
229}
230
231static int fec_recv (struct eth_device *dev)
232{
233 struct ether_fcc_info_s *efis = dev->priv;
234 volatile fec_t *fecp =
235 (volatile fec_t *) (CONFIG_SYS_IMMR + efis->fecp_offset);
236 int length;
237
238 for (;;) {
239
240 if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
241 length = -1;
242 break;
243 }
244
245 length = rtx->rxbd[rxIdx].cbd_datlen;
246
247 if (rtx->rxbd[rxIdx].cbd_sc & 0x003f) {
248#ifdef ET_DEBUG
249 printf ("%s[%d] err: %x\n",
250 __FUNCTION__, __LINE__,
251 rtx->rxbd[rxIdx].cbd_sc);
252#endif
253 } else {
254 uchar *rx = NetRxPackets[rxIdx];
255
256 length -= 4;
257
258#if defined(CONFIG_CMD_CDP)
259 if ((rx[0] & 1) != 0
260 && memcmp ((uchar *) rx, NetBcastAddr, 6) != 0
261 && !is_cdp_packet((uchar *)rx))
262 rx = NULL;
263#endif
264
265
266
267 if (rx != NULL)
268 NetReceive (rx, length);
269 }
270
271
272 rtx->rxbd[rxIdx].cbd_datlen = 0;
273
274
275 if ((rxIdx + 1) >= PKTBUFSRX) {
276 rtx->rxbd[PKTBUFSRX - 1].cbd_sc =
277 (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
278 rxIdx = 0;
279 } else {
280 rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
281 rxIdx++;
282 }
283
284 __asm__ ("eieio");
285
286
287 fecp->fec_r_des_active = 0x01000000;
288 }
289
290 return length;
291}
292
293
294
295
296
297
298
299#define FEC_ECNTRL_PINMUX 0x00000004
300#define FEC_ECNTRL_ETHER_EN 0x00000002
301#define FEC_ECNTRL_RESET 0x00000001
302
303#define FEC_RCNTRL_BC_REJ 0x00000010
304#define FEC_RCNTRL_PROM 0x00000008
305#define FEC_RCNTRL_MII_MODE 0x00000004
306#define FEC_RCNTRL_DRT 0x00000002
307#define FEC_RCNTRL_LOOP 0x00000001
308
309#define FEC_TCNTRL_FDEN 0x00000004
310#define FEC_TCNTRL_HBC 0x00000002
311#define FEC_TCNTRL_GTS 0x00000001
312
313#define FEC_RESET_DELAY 50
314
315#if defined(CONFIG_RMII)
316
317static inline void fec_10Mbps(struct eth_device *dev)
318{
319 struct ether_fcc_info_s *efis = dev->priv;
320 int fecidx = efis->ether_index;
321 uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008;
322
323 if ((unsigned int)fecidx >= 2)
324 hang();
325
326 ((volatile immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_cptr |= mask;
327}
328
329static inline void fec_100Mbps(struct eth_device *dev)
330{
331 struct ether_fcc_info_s *efis = dev->priv;
332 int fecidx = efis->ether_index;
333 uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008;
334
335 if ((unsigned int)fecidx >= 2)
336 hang();
337
338 ((volatile immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_cptr &= ~mask;
339}
340
341#endif
342
343static inline void fec_full_duplex(struct eth_device *dev)
344{
345 struct ether_fcc_info_s *efis = dev->priv;
346 volatile fec_t *fecp = (volatile fec_t *)(CONFIG_SYS_IMMR + efis->fecp_offset);
347
348 fecp->fec_r_cntrl &= ~FEC_RCNTRL_DRT;
349 fecp->fec_x_cntrl |= FEC_TCNTRL_FDEN;
350}
351
352static inline void fec_half_duplex(struct eth_device *dev)
353{
354 struct ether_fcc_info_s *efis = dev->priv;
355 volatile fec_t *fecp = (volatile fec_t *)(CONFIG_SYS_IMMR + efis->fecp_offset);
356
357 fecp->fec_r_cntrl |= FEC_RCNTRL_DRT;
358 fecp->fec_x_cntrl &= ~FEC_TCNTRL_FDEN;
359}
360
361static void fec_pin_init(int fecidx)
362{
363 bd_t *bd = gd->bd;
364 volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
365
366
367
368
369
370
371
372
373
374
375
376
377
378 immr->im_cpm.cp_fec1.fec_mii_speed = ((bd->bi_intfreq + 4999999) / 5000000) << 1;
379
380#if defined(CONFIG_MPC885_FAMILY) && defined(WANT_MII)
381
382 immr->im_ioport.iop_pdpar |= 0x0080;
383 immr->im_ioport.iop_pddir &= ~0x0080;
384#endif
385
386 if (fecidx == 0) {
387#if defined(CONFIG_ETHER_ON_FEC1)
388
389#if defined(CONFIG_MPC885_FAMILY)
390
391#if !defined(CONFIG_RMII)
392
393 immr->im_ioport.iop_papar |= 0xf830;
394 immr->im_ioport.iop_padir |= 0x0830;
395 immr->im_ioport.iop_padir &= ~0xf000;
396
397 immr->im_cpm.cp_pbpar |= 0x00001001;
398 immr->im_cpm.cp_pbdir &= ~0x00001001;
399
400 immr->im_ioport.iop_pcpar |= 0x000c;
401 immr->im_ioport.iop_pcdir &= ~0x000c;
402
403 immr->im_cpm.cp_pepar |= 0x00000003;
404 immr->im_cpm.cp_pedir |= 0x00000003;
405 immr->im_cpm.cp_peso &= ~0x00000003;
406
407 immr->im_cpm.cp_cptr &= ~0x00000100;
408
409#else
410
411#if !defined(CONFIG_FEC1_PHY_NORXERR)
412 immr->im_ioport.iop_papar |= 0x1000;
413 immr->im_ioport.iop_padir &= ~0x1000;
414#endif
415 immr->im_ioport.iop_papar |= 0xe810;
416 immr->im_ioport.iop_padir |= 0x0810;
417 immr->im_ioport.iop_padir &= ~0xe000;
418
419 immr->im_cpm.cp_pbpar |= 0x00000001;
420 immr->im_cpm.cp_pbdir &= ~0x00000001;
421
422 immr->im_cpm.cp_cptr |= 0x00000100;
423 immr->im_cpm.cp_cptr &= ~0x00000050;
424
425#endif
426
427#elif !defined(CONFIG_ICU862)
428
429
430
431 immr->im_ioport.iop_pdpar = 0x1fff;
432
433
434
435
436 if ((get_immr(0) & 0xffff) < 0x0501)
437 immr->im_ioport.iop_pddir = 0x1c58;
438 else
439 immr->im_ioport.iop_pddir = 0x1fff;
440#else
441
442
443
444
445#if defined(CONFIG_ICU862) && defined(CONFIG_SYS_DISCOVER_PHY)
446
447
448
449
450
451
452 immr->im_ioport.iop_pdpar |= 0x4080;
453#endif
454
455
456
457
458 if (immr->im_ioport.iop_pdpar & (0x8000 >> 1)) {
459
460
461
462
463 immr->im_ioport.utmode &= ~0x80;
464 } else {
465
466
467
468
469
470
471
472 immr->im_ioport.utmode |= 0x80;
473 }
474#endif
475
476#endif
477 } else if (fecidx == 1) {
478
479#if defined(CONFIG_ETHER_ON_FEC2)
480
481#if defined(CONFIG_MPC885_FAMILY)
482
483#if !defined(CONFIG_RMII)
484 immr->im_cpm.cp_pepar |= 0x0003fffc;
485 immr->im_cpm.cp_pedir |= 0x0003fffc;
486 immr->im_cpm.cp_peso &= ~0x000087fc;
487 immr->im_cpm.cp_peso |= 0x00037800;
488
489 immr->im_cpm.cp_cptr &= ~0x00000080;
490#else
491
492#if !defined(CONFIG_FEC2_PHY_NORXERR)
493 immr->im_cpm.cp_pepar |= 0x00000010;
494 immr->im_cpm.cp_pedir |= 0x00000010;
495 immr->im_cpm.cp_peso &= ~0x00000010;
496#endif
497 immr->im_cpm.cp_pepar |= 0x00039620;
498 immr->im_cpm.cp_pedir |= 0x00039620;
499 immr->im_cpm.cp_peso |= 0x00031000;
500 immr->im_cpm.cp_peso &= ~0x00008620;
501
502 immr->im_cpm.cp_cptr |= 0x00000080;
503 immr->im_cpm.cp_cptr &= ~0x00000028;
504#endif
505
506#endif
507
508#endif
509
510 }
511}
512
513static int fec_reset(volatile fec_t *fecp)
514{
515 int i;
516
517
518
519
520
521
522
523
524
525 fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET;
526 for (i = 0;
527 (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY);
528 ++i) {
529 udelay (1);
530 }
531 if (i == FEC_RESET_DELAY)
532 return -1;
533
534 return 0;
535}
536
537static int fec_init (struct eth_device *dev, bd_t * bd)
538{
539 struct ether_fcc_info_s *efis = dev->priv;
540 volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
541 volatile fec_t *fecp =
542 (volatile fec_t *) (CONFIG_SYS_IMMR + efis->fecp_offset);
543 int i;
544
545#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
546
547
548
549
550 if (efis->ether_index != 0)
551 __mii_init();
552#endif
553
554 if (fec_reset(fecp) < 0)
555 printf ("FEC_RESET_DELAY timeout\n");
556
557
558
559 fecp->fec_imask = 0;
560
561
562
563 fecp->fec_ievent = 0xffc0;
564
565
566
567
568
569#define ea dev->enetaddr
570 fecp->fec_addr_low = (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]);
571 fecp->fec_addr_high = (ea[4] << 8) | (ea[5]);
572#undef ea
573
574#if defined(CONFIG_CMD_CDP)
575
576
577
578 fecp->fec_hash_table_high = 0xffffffff;
579 fecp->fec_hash_table_low = 0xffffffff;
580#else
581
582
583 fecp->fec_hash_table_high = 0;
584 fecp->fec_hash_table_low = 0;
585#endif
586
587
588
589 fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
590
591
592
593 fecp->fec_r_hash = PKT_MAXBUF_SIZE;
594
595
596
597
598 rxIdx = 0;
599 txIdx = 0;
600
601 if (!rtx) {
602#ifdef CONFIG_SYS_ALLOC_DPRAM
603 rtx = (RTXBD *) (immr->im_cpm.cp_dpmem +
604 dpram_alloc_align (sizeof (RTXBD), 8));
605#else
606 rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + CPM_FEC_BASE);
607#endif
608 }
609
610
611
612
613
614 for (i = 0; i < PKTBUFSRX; i++) {
615 rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
616 rtx->rxbd[i].cbd_datlen = 0;
617 rtx->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i];
618 }
619 rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
620
621
622
623
624
625
626 for (i = 0; i < TX_BUF_CNT; i++) {
627 rtx->txbd[i].cbd_sc = BD_ENET_TX_LAST | BD_ENET_TX_TC;
628 rtx->txbd[i].cbd_datlen = 0;
629 rtx->txbd[i].cbd_bufaddr = (uint) (&txbuf[0]);
630 }
631 rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
632
633
634
635 fecp->fec_r_des_start = (unsigned int) (&rtx->rxbd[0]);
636 fecp->fec_x_des_start = (unsigned int) (&rtx->txbd[0]);
637
638
639
640#if 0
641 fecp->fec_r_cntrl = FEC_RCNTRL_MII_MODE;
642 fecp->fec_x_cntrl = FEC_TCNTRL_FDEN;
643#else
644 fecp->fec_r_cntrl = FEC_RCNTRL_MII_MODE | FEC_RCNTRL_DRT;
645 fecp->fec_x_cntrl = 0;
646#endif
647
648
649
650 fecp->fec_fun_code = 0x78000000;
651
652
653
654
655 fec_pin_init (efis->ether_index);
656
657 rxIdx = 0;
658 txIdx = 0;
659
660
661
662
663 fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN;
664
665 if (efis->phy_addr == -1) {
666#ifdef CONFIG_SYS_DISCOVER_PHY
667
668
669
670 efis->actual_phy_addr = mii_discover_phy (dev);
671
672 if (efis->actual_phy_addr == -1) {
673 printf ("Unable to discover phy!\n");
674 return -1;
675 }
676#else
677 efis->actual_phy_addr = -1;
678#endif
679 } else {
680 efis->actual_phy_addr = efis->phy_addr;
681 }
682
683#if defined(CONFIG_MII) && defined(CONFIG_RMII)
684
685
686
687 if (miiphy_speed (dev->name, efis->actual_phy_addr) == _100BASET) {
688 fec_100Mbps (dev);
689 } else {
690 fec_10Mbps (dev);
691 }
692#endif
693
694#if defined(CONFIG_MII)
695
696
697
698 if (miiphy_duplex (dev->name, efis->actual_phy_addr) == FULL) {
699 fec_full_duplex (dev);
700 } else {
701 fec_half_duplex (dev);
702 }
703#endif
704
705
706 fecp->fec_r_des_active = 0x01000000;
707
708 efis->initialized = 1;
709
710 return 0;
711}
712
713
714static void fec_halt(struct eth_device* dev)
715{
716 struct ether_fcc_info_s *efis = dev->priv;
717 volatile fec_t *fecp = (volatile fec_t *)(CONFIG_SYS_IMMR + efis->fecp_offset);
718 int i;
719
720
721 if (!efis->initialized)
722 return;
723
724
725
726
727
728
729
730
731
732 fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET;
733 for (i = 0;
734 (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY);
735 ++i) {
736 udelay (1);
737 }
738 if (i == FEC_RESET_DELAY) {
739 printf ("FEC_RESET_DELAY timeout\n");
740 return;
741 }
742
743 efis->initialized = 0;
744}
745
746#if defined(CONFIG_SYS_DISCOVER_PHY) || defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
747
748
749
750
751#define mk_mii_read(ADDR, REG) (0x60020000 | ((ADDR << 23) | \
752 (REG & 0x1f) << 18))
753
754#define mk_mii_write(ADDR, REG, VAL) (0x50020000 | ((ADDR << 23) | \
755 (REG & 0x1f) << 18) | \
756 (VAL & 0xffff))
757
758
759
760#define FEC_ENET_HBERR ((uint)0x80000000)
761#define FEC_ENET_BABR ((uint)0x40000000)
762#define FEC_ENET_BABT ((uint)0x20000000)
763#define FEC_ENET_GRA ((uint)0x10000000)
764#define FEC_ENET_TXF ((uint)0x08000000)
765#define FEC_ENET_TXB ((uint)0x04000000)
766#define FEC_ENET_RXF ((uint)0x02000000)
767#define FEC_ENET_RXB ((uint)0x01000000)
768#define FEC_ENET_MII ((uint)0x00800000)
769#define FEC_ENET_EBERR ((uint)0x00400000)
770
771
772
773#define PHY_ID_LXT970 0x78100000
774#define PHY_ID_LXT971 0x001378e0
775#define PHY_ID_82555 0x02a80150
776#define PHY_ID_QS6612 0x01814400
777#define PHY_ID_AMD79C784 0x00225610
778#define PHY_ID_LSI80225 0x0016f870
779#define PHY_ID_LSI80225B 0x0016f880
780#define PHY_ID_DM9161 0x0181B880
781#define PHY_ID_KSM8995M 0x00221450
782
783
784static uint
785mii_send(uint mii_cmd)
786{
787 uint mii_reply;
788 volatile fec_t *ep;
789 int cnt;
790
791 ep = &(((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_fec);
792
793 ep->fec_mii_data = mii_cmd;
794
795
796 cnt = 0;
797 while (!(ep->fec_ievent & FEC_ENET_MII)) {
798 if (++cnt > 1000) {
799 printf("mii_send STUCK!\n");
800 break;
801 }
802 }
803 mii_reply = ep->fec_mii_data;
804 ep->fec_ievent = FEC_ENET_MII;
805#if 0
806 printf("%s[%d] %s: sent=0x%8.8x, reply=0x%8.8x\n",
807 __FILE__,__LINE__,__FUNCTION__,mii_cmd,mii_reply);
808#endif
809 return (mii_reply & 0xffff);
810}
811#endif
812
813#if defined(CONFIG_SYS_DISCOVER_PHY)
814static int mii_discover_phy(struct eth_device *dev)
815{
816#define MAX_PHY_PASSES 11
817 uint phyno;
818 int pass;
819 uint phytype;
820 int phyaddr;
821
822 phyaddr = -1;
823 for (pass = 1; pass <= MAX_PHY_PASSES && phyaddr < 0; ++pass) {
824 if (pass > 1) {
825
826
827
828
829
830 udelay(10000);
831 }
832 for (phyno = 0; phyno < 32 && phyaddr < 0; ++phyno) {
833 phytype = mii_send(mk_mii_read(phyno, MII_PHYSID2));
834#ifdef ET_DEBUG
835 printf("PHY type 0x%x pass %d type ", phytype, pass);
836#endif
837 if (phytype != 0xffff) {
838 phyaddr = phyno;
839 phytype |= mii_send(mk_mii_read(phyno,
840 MII_PHYSID1)) << 16;
841
842#ifdef ET_DEBUG
843 printf("PHY @ 0x%x pass %d type ",phyno,pass);
844 switch (phytype & 0xfffffff0) {
845 case PHY_ID_LXT970:
846 printf("LXT970\n");
847 break;
848 case PHY_ID_LXT971:
849 printf("LXT971\n");
850 break;
851 case PHY_ID_82555:
852 printf("82555\n");
853 break;
854 case PHY_ID_QS6612:
855 printf("QS6612\n");
856 break;
857 case PHY_ID_AMD79C784:
858 printf("AMD79C784\n");
859 break;
860 case PHY_ID_LSI80225B:
861 printf("LSI L80225/B\n");
862 break;
863 case PHY_ID_DM9161:
864 printf("Davicom DM9161\n");
865 break;
866 case PHY_ID_KSM8995M:
867 printf("MICREL KS8995M\n");
868 break;
869 default:
870 printf("0x%08x\n", phytype);
871 break;
872 }
873#endif
874 }
875 }
876 }
877 if (phyaddr < 0) {
878 printf("No PHY device found.\n");
879 }
880 return phyaddr;
881}
882#endif
883
884#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && !defined(CONFIG_BITBANGMII)
885
886
887
888
889
890
891static void __mii_init(void)
892{
893 volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
894 volatile fec_t *fecp = &(immr->im_cpm.cp_fec);
895
896 if (fec_reset(fecp) < 0)
897 printf ("FEC_RESET_DELAY timeout\n");
898
899
900
901 fecp->fec_imask = 0;
902
903
904
905 fecp->fec_ievent = 0xffc0;
906
907
908
909 fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN;
910}
911
912void mii_init (void)
913{
914 int i;
915
916 __mii_init();
917
918
919
920 for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++)
921 fec_pin_init(ether_fcc_info[i].ether_index);
922}
923
924
925
926
927
928
929
930
931
932
933
934
935int fec8xx_miiphy_read(const char *devname, unsigned char addr,
936 unsigned char reg, unsigned short *value)
937{
938 short rdreg;
939
940#ifdef MII_DEBUG
941 printf ("miiphy_read(0x%x) @ 0x%x = ", reg, addr);
942#endif
943 rdreg = mii_send(mk_mii_read(addr, reg));
944
945 *value = rdreg;
946#ifdef MII_DEBUG
947 printf ("0x%04x\n", *value);
948#endif
949 return 0;
950}
951
952int fec8xx_miiphy_write(const char *devname, unsigned char addr,
953 unsigned char reg, unsigned short value)
954{
955#ifdef MII_DEBUG
956 printf ("miiphy_write(0x%x) @ 0x%x = ", reg, addr);
957#endif
958 (void)mii_send(mk_mii_write(addr, reg, value));
959
960#ifdef MII_DEBUG
961 printf ("0x%04x\n", value);
962#endif
963 return 0;
964}
965#endif
966
967#endif
968