1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include <common.h>
17
18#include <net.h>
19#include <asm/arch/netarm_registers.h>
20#include <asm/arch/netarm_dma_module.h>
21
22#include "ns7520_eth.h"
23
24
25
26
27#define ERROR(x) \
28do { \
29 char *__foo = strrchr(__FILE__, '/'); \
30 \
31 printf("%s: %d: %s(): ", (__foo == NULL ? __FILE__ : (__foo + 1)), \
32 __LINE__, __FUNCTION__); \
33 printf x; printf("\n"); \
34} while (0);
35
36
37
38#define NS7520_DRIVER_NAME "eth"
39#define KERN_WARNING "Warning:"
40#define KERN_ERR "Error:"
41#define KERN_INFO "Info:"
42
43#if 1
44# define DEBUG
45#endif
46
47#ifdef DEBUG
48# define printk printf
49
50# define DEBUG_INIT 0x0001
51# define DEBUG_MINOR 0x0002
52# define DEBUG_RX 0x0004
53# define DEBUG_TX 0x0008
54# define DEBUG_INT 0x0010
55# define DEBUG_POLL 0x0020
56# define DEBUG_LINK 0x0040
57# define DEBUG_MII 0x0100
58# define DEBUG_MII_LOW 0x0200
59# define DEBUG_MEM 0x0400
60# define DEBUG_ERROR 0x4000
61# define DEBUG_ERROR_CRIT 0x8000
62
63static int nDebugLvl = DEBUG_ERROR_CRIT;
64
65# define DEBUG_ARGS0( FLG, a0 ) if( ( nDebugLvl & (FLG) ) == (FLG) ) \
66 printf("%s: " a0, __FUNCTION__, 0, 0, 0, 0, 0, 0 )
67# define DEBUG_ARGS1( FLG, a0, a1 ) if( ( nDebugLvl & (FLG) ) == (FLG)) \
68 printf("%s: " a0, __FUNCTION__, (int)(a1), 0, 0, 0, 0, 0 )
69# define DEBUG_ARGS2( FLG, a0, a1, a2 ) if( (nDebugLvl & (FLG)) ==(FLG))\
70 printf("%s: " a0, __FUNCTION__, (int)(a1), (int)(a2), 0, 0,0,0 )
71# define DEBUG_ARGS3( FLG, a0, a1, a2, a3 ) if((nDebugLvl &(FLG))==(FLG))\
72 printf("%s: "a0,__FUNCTION__,(int)(a1),(int)(a2),(int)(a3),0,0,0)
73# define DEBUG_FN( FLG ) if( (nDebugLvl & (FLG)) == (FLG) ) \
74 printf("\r%s:line %d\n", (int)__FUNCTION__, __LINE__, 0,0,0,0);
75# define ASSERT( expr, func ) if( !( expr ) ) { \
76 printf( "Assertion failed! %s:line %d %s\n", \
77 (int)__FUNCTION__,__LINE__,(int)(#expr),0,0,0); \
78 func }
79#else
80# define printk(...)
81# define DEBUG_ARGS0( FLG, a0 )
82# define DEBUG_ARGS1( FLG, a0, a1 )
83# define DEBUG_ARGS2( FLG, a0, a1, a2 )
84# define DEBUG_ARGS3( FLG, a0, a1, a2, a3 )
85# define DEBUG_FN( n )
86# define ASSERT(expr, func)
87#endif
88
89#define NS7520_MII_NEG_DELAY (5*CONFIG_SYS_HZ)
90#define TX_TIMEOUT (5*CONFIG_SYS_HZ)
91#define RX_STALL_WORKAROUND_CNT 100
92
93static int ns7520_eth_reset(void);
94
95static void ns7520_link_auto_negotiate(void);
96static void ns7520_link_update_egcr(void);
97static void ns7520_link_print_changed(void);
98
99
100
101static char ns7520_mii_identify_phy(void);
102static unsigned short ns7520_mii_read(unsigned short uiRegister);
103static void ns7520_mii_write(unsigned short uiRegister,
104 unsigned short uiData);
105static unsigned int ns7520_mii_get_clock_divisor(unsigned int
106 unMaxMDIOClk);
107static unsigned int ns7520_mii_poll_busy(void);
108
109static unsigned int nPhyMaxMdioClock = PHY_MDIO_MAX_CLK;
110static unsigned int uiLastLinkStatus;
111static PhyType phyDetected = PHY_NONE;
112
113
114
115
116
117
118
119
120int eth_init(bd_t * pbis)
121{
122 unsigned char aucMACAddr[6];
123 char *pcTmp = getenv("ethaddr");
124 char *pcEnd;
125 int i;
126
127 DEBUG_FN(DEBUG_INIT);
128
129
130
131 if (!ns7520_eth_reset())
132 return -1;
133
134 if (NULL == pcTmp)
135 return -1;
136
137 for (i = 0; i < 6; i++) {
138 aucMACAddr[i] =
139 pcTmp ? simple_strtoul(pcTmp, &pcEnd, 16) : 0;
140 pcTmp = (*pcTmp) ? pcEnd + 1 : pcEnd;
141 }
142
143
144
145 *get_eth_reg_addr(NS7520_ETH_SA1) =
146 aucMACAddr[5] << 8 | aucMACAddr[4];
147 *get_eth_reg_addr(NS7520_ETH_SA2) =
148 aucMACAddr[3] << 8 | aucMACAddr[2];
149 *get_eth_reg_addr(NS7520_ETH_SA3) =
150 aucMACAddr[1] << 8 | aucMACAddr[0];
151
152
153
154 *get_eth_reg_addr(NS7520_ETH_MAC1) = NS7520_ETH_MAC1_RXEN;
155 *get_eth_reg_addr(NS7520_ETH_SUPP) = NS7520_ETH_SUPP_JABBER;
156 *get_eth_reg_addr(NS7520_ETH_MAC1) = NS7520_ETH_MAC1_RXEN;
157
158
159 *get_eth_reg_addr(NS7520_ETH_MAC2) = NS7520_ETH_MAC2_CRCEN |
160 NS7520_ETH_MAC2_PADEN | NS7520_ETH_MAC2_HUGE;
161
162
163
164 *get_eth_reg_addr(NS7520_ETH_SAFR) =
165 NS7520_ETH_SAFR_BROAD | NS7520_ETH_SAFR_PRM;
166
167
168 *get_eth_reg_addr(NS7520_ETH_EGCR) |=
169 NS7520_ETH_EGCR_ETXWM_75 |
170 NS7520_ETH_EGCR_ERX |
171 NS7520_ETH_EGCR_ERXREG |
172 NS7520_ETH_EGCR_ERXBR | NS7520_ETH_EGCR_ETX;
173
174 return 0;
175}
176
177
178
179
180
181
182
183int eth_send(volatile void *pPacket, int nLen)
184{
185 int i, length32, retval = 1;
186 char *pa;
187 unsigned int *pa32, lastp = 0, rest;
188 unsigned int status;
189
190 pa = (char *) pPacket;
191 pa32 = (unsigned int *) pPacket;
192 length32 = nLen / 4;
193 rest = nLen % 4;
194
195
196 switch (rest) {
197 case 0:
198 lastp = pa32[length32 - 1];
199 length32--;
200 break;
201 case 1:
202 lastp = pa32[length32] & 0x000000ff;
203 break;
204 case 2:
205 lastp = pa32[length32] & 0x0000ffff;
206 break;
207 case 3:
208 lastp = pa32[length32] & 0x00ffffff;
209 break;
210 }
211
212 while (((*get_eth_reg_addr(NS7520_ETH_EGSR)) &
213 NS7520_ETH_EGSR_TXREGE)
214 == 0) {
215 }
216
217
218 for (i = 0; i < length32; i++)
219 *get_eth_reg_addr(NS7520_ETH_FIFO) = pa32[i];
220
221
222
223 *get_eth_reg_addr(NS7520_ETH_FIFOL) = lastp;
224
225
226 while ((*get_eth_reg_addr(NS7520_ETH_EGSR) & NS7520_ETH_EGSR_TXBC)
227 == 0) {
228 }
229 status = (*get_eth_reg_addr(NS7520_ETH_ETSR));
230 *get_eth_reg_addr(NS7520_ETH_EGSR) = NS7520_ETH_EGSR_TXBC;
231
232 if (status & NS7520_ETH_ETSR_TXOK) {
233 retval = 0;
234 } else if (status & NS7520_ETH_ETSR_TXDEF) {
235 printf("Deferred, we'll see.\n");
236 retval = 0;
237 } else if (status & NS7520_ETH_ETSR_TXAL) {
238 printf("Late collision error, %d collisions.\n",
239 (*get_eth_reg_addr(NS7520_ETH_ETSR)) &
240 NS7520_ETH_ETSR_TXCOLC);
241 } else if (status & NS7520_ETH_ETSR_TXAEC) {
242 printf("Excessive collisions: %d\n",
243 (*get_eth_reg_addr(NS7520_ETH_ETSR)) &
244 NS7520_ETH_ETSR_TXCOLC);
245 } else if (status & NS7520_ETH_ETSR_TXAED) {
246 printf("Excessive deferral on xmit.\n");
247 } else if (status & NS7520_ETH_ETSR_TXAUR) {
248 printf("Packet underrun.\n");
249 } else if (status & NS7520_ETH_ETSR_TXAJ) {
250 printf("Jumbo packet error.\n");
251 } else {
252 printf("Error: Should never get here.\n");
253 }
254
255 return (retval);
256}
257
258
259
260
261
262
263
264
265int eth_rx(void)
266{
267 int i;
268 unsigned short rxlen;
269 unsigned short totrxlen = 0;
270 unsigned int *addr;
271 unsigned int rxstatus, lastrxlen;
272 char *pa;
273
274
275 while (((*get_eth_reg_addr(NS7520_ETH_EGSR)) &
276 NS7520_ETH_EGSR_RXBR) == NS7520_ETH_EGSR_RXBR) {
277
278
279 rxstatus = *get_eth_reg_addr(NS7520_ETH_ERSR);
280 rxlen = (rxstatus & NS7520_ETH_ERSR_RXSIZE) >> 16;
281
282
283 *get_eth_reg_addr(NS7520_ETH_EGSR) = NS7520_ETH_EGSR_RXBR;
284
285 if (rxstatus & NS7520_ETH_ERSR_ROVER) {
286 printf("Receive overrun, resetting FIFO.\n");
287 *get_eth_reg_addr(NS7520_ETH_EGCR) &=
288 ~NS7520_ETH_EGCR_ERX;
289 udelay(20);
290 *get_eth_reg_addr(NS7520_ETH_EGCR) |=
291 NS7520_ETH_EGCR_ERX;
292 }
293 if (rxlen == 0) {
294 printf("Nothing.\n");
295 return 0;
296 }
297
298 addr = (unsigned int *) NetRxPackets[0];
299 pa = (char *) NetRxPackets[0];
300
301
302 for (i = 0; i < rxlen / 4; i++) {
303 *addr = *get_eth_reg_addr(NS7520_ETH_FIFO);
304 addr++;
305 }
306
307 if ((*get_eth_reg_addr(NS7520_ETH_EGSR)) &
308 NS7520_ETH_EGSR_RXREGR) {
309
310 lastrxlen =
311 ((*get_eth_reg_addr(NS7520_ETH_EGSR)) &
312 NS7520_ETH_EGSR_RXFDB_MA) >> 28;
313 *addr = *get_eth_reg_addr(NS7520_ETH_FIFO);
314 switch (lastrxlen) {
315 case 1:
316 *addr &= 0xff000000;
317 break;
318 case 2:
319 *addr &= 0xffff0000;
320 break;
321 case 3:
322 *addr &= 0xffffff00;
323 break;
324 }
325 }
326
327
328 NetReceive(NetRxPackets[0], rxlen - 4);
329 totrxlen += rxlen - 4;
330 }
331
332 return totrxlen;
333}
334
335
336
337
338
339
340
341void eth_halt(void)
342{
343 DEBUG_FN(DEBUG_INIT);
344
345 *get_eth_reg_addr(NS7520_ETH_MAC1) &= ~NS7520_ETH_MAC1_RXEN;
346 *get_eth_reg_addr(NS7520_ETH_EGCR) &= ~(NS7520_ETH_EGCR_ERX |
347 NS7520_ETH_EGCR_ERXDMA |
348 NS7520_ETH_EGCR_ERXREG |
349 NS7520_ETH_EGCR_ERXBR |
350 NS7520_ETH_EGCR_ETX |
351 NS7520_ETH_EGCR_ETXDMA);
352}
353
354
355
356
357
358
359
360
361static int ns7520_eth_reset(void)
362{
363 DEBUG_FN(DEBUG_MINOR);
364
365
366 *get_eth_reg_addr(NS7520_ETH_EGCR) = 0;
367 *get_eth_reg_addr(NS7520_ETH_MAC1) &= NS7520_ETH_MAC1_SRST;
368 *get_eth_reg_addr(NS7520_ETH_MAC2) = 0;
369
370 *get_eth_reg_addr(NS7520_ETH_EGCR) |= NS7520_ETH_EGCR_MAC_RES;
371 udelay(5);
372 *get_eth_reg_addr(NS7520_ETH_EGCR) &= ~NS7520_ETH_EGCR_MAC_RES;
373
374
375
376 *get_eth_reg_addr(NS7520_ETH_MAC1) &= ~NS7520_ETH_MAC1_SRST;
377
378
379
380
381
382
383
384
385
386 *get_eth_reg_addr(NS7520_ETH_MCFG) =
387 ns7520_mii_get_clock_divisor(nPhyMaxMdioClock);
388
389
390 ns7520_mii_write(PHY_BMCR, PHY_BMCR_RESET);
391 ns7520_mii_write(PHY_BMCR, 0);
392
393 udelay(3000);
394
395
396
397
398 if (!ns7520_mii_identify_phy()) {
399 printk(KERN_ERR NS7520_DRIVER_NAME
400 ": Unsupported PHY, aborting\n");
401 return 0;
402 }
403
404
405 *get_eth_reg_addr(NS7520_ETH_MCFG) =
406 ns7520_mii_get_clock_divisor(nPhyMaxMdioClock);
407
408
409
410
411 uiLastLinkStatus = 0xff;
412
413 ns7520_link_auto_negotiate();
414
415 if (phyDetected == PHY_LXT971A)
416
417 ns7520_mii_write(PHY_LXT971_LED_CFG,
418 (PHY_LXT971_LED_CFG_LINK_ACT <<
419 PHY_LXT971_LED_CFG_SHIFT_LED2) |
420 (PHY_LXT971_LED_CFG_TRANSMIT <<
421 PHY_LXT971_LED_CFG_SHIFT_LED1));
422
423 return 1;
424}
425
426
427
428
429
430
431
432static void ns7520_link_auto_negotiate(void)
433{
434 unsigned long ulStartJiffies;
435 unsigned short uiStatus;
436
437 DEBUG_FN(DEBUG_LINK);
438
439
440
441 ns7520_mii_write(PHY_ANAR,
442 PHY_ANLPAR_TXFD |
443 PHY_ANLPAR_TX |
444 PHY_ANLPAR_10FD |
445 PHY_ANLPAR_10 |
446 PHY_ANLPAR_PSB_802_3);
447
448 ns7520_mii_write(PHY_BMCR, PHY_BMCR_AUTON | PHY_BMCR_RST_NEG);
449
450
451
452 ulStartJiffies = get_timer(0);
453 while (get_timer(0) < ulStartJiffies + NS7520_MII_NEG_DELAY) {
454 uiStatus = ns7520_mii_read(PHY_BMSR);
455 if ((uiStatus &
456 (PHY_BMSR_AUTN_COMP | PHY_BMSR_LS)) ==
457 (PHY_BMSR_AUTN_COMP | PHY_BMSR_LS)) {
458
459 ns7520_link_print_changed();
460 ns7520_link_update_egcr();
461 return;
462 }
463 }
464
465 DEBUG_ARGS0(DEBUG_LINK, "auto-negotiation timed out\n");
466
467}
468
469
470
471
472
473
474
475
476static void ns7520_link_update_egcr(void)
477{
478 unsigned int unEGCR;
479 unsigned int unMAC2;
480 unsigned int unIPGT;
481
482 DEBUG_FN(DEBUG_LINK);
483
484 unEGCR = *get_eth_reg_addr(NS7520_ETH_EGCR);
485 unMAC2 = *get_eth_reg_addr(NS7520_ETH_MAC2);
486 unIPGT =
487 *get_eth_reg_addr(NS7520_ETH_IPGT) & ~NS7520_ETH_IPGT_IPGT;
488
489 unEGCR &= ~NS7520_ETH_EGCR_EFULLD;
490 unMAC2 &= ~NS7520_ETH_MAC2_FULLD;
491 if ((uiLastLinkStatus & PHY_LXT971_STAT2_DUPLEX_MODE)
492 == PHY_LXT971_STAT2_DUPLEX_MODE) {
493 unEGCR |= NS7520_ETH_EGCR_EFULLD;
494 unMAC2 |= NS7520_ETH_MAC2_FULLD;
495 unIPGT |= 0x15;
496 } else
497 unIPGT |= 0x12;
498
499 *get_eth_reg_addr(NS7520_ETH_MAC2) = unMAC2;
500 *get_eth_reg_addr(NS7520_ETH_EGCR) = unEGCR;
501 *get_eth_reg_addr(NS7520_ETH_IPGT) = unIPGT;
502}
503
504
505
506
507
508
509
510
511static void ns7520_link_print_changed(void)
512{
513 unsigned short uiStatus;
514 unsigned short uiControl;
515
516 DEBUG_FN(DEBUG_LINK);
517
518 uiControl = ns7520_mii_read(PHY_BMCR);
519
520 if ((uiControl & PHY_BMCR_AUTON) == PHY_BMCR_AUTON) {
521
522 uiStatus = ns7520_mii_read(PHY_BMSR);
523
524 if (!(uiStatus & PHY_BMSR_LS)) {
525 printk(KERN_WARNING NS7520_DRIVER_NAME
526 ": link down\n");
527
528 } else {
529
530 if (phyDetected == PHY_LXT971A) {
531 uiStatus =
532 ns7520_mii_read(PHY_LXT971_STAT2);
533 uiStatus &=
534 (PHY_LXT971_STAT2_100BTX |
535 PHY_LXT971_STAT2_DUPLEX_MODE |
536 PHY_LXT971_STAT2_AUTO_NEG);
537
538
539 }
540
541
542 }
543 } else {
544
545
546 uiStatus = uiLastLinkStatus;
547 uiLastLinkStatus = 0xff;
548 }
549
550 if (uiStatus != uiLastLinkStatus) {
551
552 uiLastLinkStatus = uiStatus;
553
554
555
556 printk(KERN_INFO NS7520_DRIVER_NAME
557 ": link mode %i Mbps %s duplex %s\n",
558 (uiStatus & PHY_LXT971_STAT2_100BTX) ? 100 : 10,
559 (uiStatus & PHY_LXT971_STAT2_DUPLEX_MODE) ? "full" :
560 "half",
561 (uiStatus & PHY_LXT971_STAT2_AUTO_NEG) ? "(auto)" :
562 "");
563 }
564}
565
566
567
568
569
570
571
572
573
574
575
576static char ns7520_mii_identify_phy(void)
577{
578 unsigned short uiID1;
579 unsigned short uiID2;
580 unsigned char *szName;
581 char cRes = 0;
582
583 DEBUG_FN(DEBUG_MII);
584
585 phyDetected = (PhyType) uiID1 = ns7520_mii_read(PHY_PHYIDR1);
586
587 switch (phyDetected) {
588 case PHY_LXT971A:
589 szName = "LXT971A";
590 uiID2 = ns7520_mii_read(PHY_PHYIDR2);
591 nPhyMaxMdioClock = PHY_LXT971_MDIO_MAX_CLK;
592 cRes = 1;
593 break;
594 case PHY_NONE:
595 default:
596
597
598
599 uiID2 = 0;
600 szName = "unknown";
601 nPhyMaxMdioClock = PHY_MDIO_MAX_CLK;
602 phyDetected = PHY_NONE;
603 }
604
605 printk(KERN_INFO NS7520_DRIVER_NAME
606 ": PHY (0x%x, 0x%x) = %s detected\n", uiID1, uiID2, szName);
607
608 return cRes;
609}
610
611
612
613
614
615
616
617
618
619static unsigned short ns7520_mii_read(unsigned short uiRegister)
620{
621 DEBUG_FN(DEBUG_MII_LOW);
622
623
624 *get_eth_reg_addr(NS7520_ETH_MADR) =
625 CONFIG_PHY_ADDR << 8 | uiRegister;
626
627 *get_eth_reg_addr(NS7520_ETH_MCMD) = NS7520_ETH_MCMD_READ;
628
629 if (!ns7520_mii_poll_busy())
630 printk(KERN_WARNING NS7520_DRIVER_NAME
631 ": MII still busy in read\n");
632
633
634 *get_eth_reg_addr(NS7520_ETH_MCMD) = 0;
635
636 return (unsigned short) (*get_eth_reg_addr(NS7520_ETH_MRDD));
637}
638
639
640
641
642
643
644
645
646
647static void ns7520_mii_write(unsigned short uiRegister,
648 unsigned short uiData)
649{
650 DEBUG_FN(DEBUG_MII_LOW);
651
652
653 *get_eth_reg_addr(NS7520_ETH_MADR) =
654 CONFIG_PHY_ADDR << 8 | uiRegister;
655
656 *get_eth_reg_addr(NS7520_ETH_MWTD) = uiData;
657
658 if (!ns7520_mii_poll_busy()) {
659 printf(KERN_WARNING NS7520_DRIVER_NAME
660 ": MII still busy in write\n");
661 }
662}
663
664
665
666
667
668
669
670
671
672static unsigned int ns7520_mii_get_clock_divisor(unsigned int unMaxMDIOClk)
673{
674 struct {
675 unsigned int unSysClkDivisor;
676 unsigned int unClks;
677 } PHYClockDivisors[] = {
678 {
679 4, NS7520_ETH_MCFG_CLKS_4}, {
680 6, NS7520_ETH_MCFG_CLKS_6}, {
681 8, NS7520_ETH_MCFG_CLKS_8}, {
682 10, NS7520_ETH_MCFG_CLKS_10}, {
683 14, NS7520_ETH_MCFG_CLKS_14}, {
684 20, NS7520_ETH_MCFG_CLKS_20}, {
685 28, NS7520_ETH_MCFG_CLKS_28}
686 };
687
688 int nIndexSysClkDiv;
689 int nArraySize =
690 sizeof(PHYClockDivisors) / sizeof(PHYClockDivisors[0]);
691 unsigned int unClks = NS7520_ETH_MCFG_CLKS_28;
692
693
694 DEBUG_FN(DEBUG_INIT);
695
696 for (nIndexSysClkDiv = 0; nIndexSysClkDiv < nArraySize;
697 nIndexSysClkDiv++) {
698
699
700 if (NETARM_XTAL_FREQ /
701 PHYClockDivisors[nIndexSysClkDiv].unSysClkDivisor <=
702 unMaxMDIOClk) {
703 unClks = PHYClockDivisors[nIndexSysClkDiv].unClks;
704 break;
705 }
706 }
707
708 DEBUG_ARGS2(DEBUG_INIT,
709 "Taking MDIO Clock bit mask 0x%0x for max clock %i\n",
710 unClks, unMaxMDIOClk);
711
712
713 return unClks;
714}
715
716
717
718
719
720
721
722
723
724
725static unsigned int ns7520_mii_poll_busy(void)
726{
727 unsigned int unTimeout = 1000;
728
729 DEBUG_FN(DEBUG_MII_LOW);
730
731 while (((*get_eth_reg_addr(NS7520_ETH_MIND) & NS7520_ETH_MIND_BUSY)
732 == NS7520_ETH_MIND_BUSY) && unTimeout)
733 unTimeout--;
734
735 return unTimeout;
736}
737
738
739
740
741#if defined(CONFIG_MII)
742
743
744
745
746#define MII_ADDRESS_MAX (31)
747
748
749
750
751#define MII_REGISTER_MAX (31)
752
753
754
755
756enum mii_status {
757 MII_STATUS_SUCCESS = 0,
758 MII_STATUS_FAILURE = 1,
759};
760
761
762
763
764extern int ns7520_miiphy_read(char *devname, unsigned char const addr,
765 unsigned char const reg, unsigned short *const value)
766{
767 int ret = MII_STATUS_FAILURE;
768
769
770 if (addr > MII_ADDRESS_MAX) {
771 ERROR(("invalid addr, 0x%02X", addr));
772 goto miiphy_read_failed_0;
773 }
774
775 if (reg > MII_REGISTER_MAX) {
776 ERROR(("invalid reg, 0x%02X", reg));
777 goto miiphy_read_failed_0;
778 }
779
780 if (value == NULL) {
781 ERROR(("NULL value"));
782 goto miiphy_read_failed_0;
783 }
784
785 DEBUG_FN(DEBUG_MII_LOW);
786
787
788 *get_eth_reg_addr(NS7520_ETH_MADR) = (addr << 8) | reg;
789
790 *get_eth_reg_addr(NS7520_ETH_MCMD) = NS7520_ETH_MCMD_READ;
791
792 if (!ns7520_mii_poll_busy())
793 printk(KERN_WARNING NS7520_DRIVER_NAME
794 ": MII still busy in read\n");
795
796
797 *get_eth_reg_addr(NS7520_ETH_MCMD) = 0;
798
799 *value = (*get_eth_reg_addr(NS7520_ETH_MRDD));
800 ret = MII_STATUS_SUCCESS;
801
802
803 miiphy_read_failed_0:
804 return (ret);
805}
806
807
808
809
810extern int ns7520_miiphy_write(char *devname, unsigned char const addr,
811 unsigned char const reg, unsigned short const value)
812{
813 int ret = MII_STATUS_FAILURE;
814
815
816 if (addr > MII_ADDRESS_MAX) {
817 ERROR(("invalid addr, 0x%02X", addr));
818 goto miiphy_write_failed_0;
819 }
820
821 if (reg > MII_REGISTER_MAX) {
822 ERROR(("invalid reg, 0x%02X", reg));
823 goto miiphy_write_failed_0;
824 }
825
826
827 *get_eth_reg_addr(NS7520_ETH_MADR) = (addr << 8) | reg;
828
829 *get_eth_reg_addr(NS7520_ETH_MWTD) = value;
830
831 if (!ns7520_mii_poll_busy()) {
832 printf(KERN_WARNING NS7520_DRIVER_NAME
833 ": MII still busy in write\n");
834 }
835
836 ret = MII_STATUS_SUCCESS;
837
838
839 miiphy_write_failed_0:
840 return (ret);
841}
842#endif
843
844int ns7520_miiphy_initialize(bd_t *bis)
845{
846#if defined(CONFIG_MII)
847 miiphy_register("ns7520phy", ns7520_miiphy_read, ns7520_miiphy_write);
848#endif
849 return 0;
850}
851