1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35#include <common.h>
36#include <net.h>
37
38#include "ns9750_eth.h"
39
40
41
42#define NS9750_DRIVER_NAME "eth"
43#define KERN_WARNING "Warning:"
44#define KERN_ERR "Error:"
45#define KERN_INFO "Info:"
46
47#if 0
48# define DEBUG
49#endif
50
51#ifdef DEBUG
52# define printk printf
53
54# define DEBUG_INIT 0x0001
55# define DEBUG_MINOR 0x0002
56# define DEBUG_RX 0x0004
57# define DEBUG_TX 0x0008
58# define DEBUG_INT 0x0010
59# define DEBUG_POLL 0x0020
60# define DEBUG_LINK 0x0040
61# define DEBUG_MII 0x0100
62# define DEBUG_MII_LOW 0x0200
63# define DEBUG_MEM 0x0400
64# define DEBUG_ERROR 0x4000
65# define DEBUG_ERROR_CRIT 0x8000
66
67static int nDebugLvl = DEBUG_ERROR_CRIT;
68
69# define DEBUG_ARGS0( FLG, a0 ) if( ( nDebugLvl & (FLG) ) == (FLG) ) \
70 printf("%s: " a0, __FUNCTION__, 0, 0, 0, 0, 0, 0 )
71# define DEBUG_ARGS1( FLG, a0, a1 ) if( ( nDebugLvl & (FLG) ) == (FLG)) \
72 printf("%s: " a0, __FUNCTION__, (int)(a1), 0, 0, 0, 0, 0 )
73# define DEBUG_ARGS2( FLG, a0, a1, a2 ) if( (nDebugLvl & (FLG)) ==(FLG))\
74 printf("%s: " a0, __FUNCTION__, (int)(a1), (int)(a2), 0, 0,0,0 )
75# define DEBUG_ARGS3( FLG, a0, a1, a2, a3 ) if((nDebugLvl &(FLG))==(FLG))\
76 printf("%s: "a0,__FUNCTION__,(int)(a1),(int)(a2),(int)(a3),0,0,0)
77# define DEBUG_FN( FLG ) if( (nDebugLvl & (FLG)) == (FLG) ) \
78 printf("\r%s:line %d\n", (int)__FUNCTION__, __LINE__, 0,0,0,0);
79# define ASSERT( expr, func ) if( !( expr ) ) { \
80 printf( "Assertion failed! %s:line %d %s\n", \
81 (int)__FUNCTION__,__LINE__,(int)(#expr),0,0,0); \
82 func }
83#else
84# define printk(...)
85# define DEBUG_ARGS0( FLG, a0 )
86# define DEBUG_ARGS1( FLG, a0, a1 )
87# define DEBUG_ARGS2( FLG, a0, a1, a2 )
88# define DEBUG_ARGS3( FLG, a0, a1, a2, a3 )
89# define DEBUG_FN( n )
90# define ASSERT(expr, func)
91#endif
92
93#define NS9750_MII_NEG_DELAY (5*CONFIG_SYS_HZ)
94#define TX_TIMEOUT (5*CONFIG_SYS_HZ)
95
96
97#define FS_EEPROM_AUTONEG_MASK 0x7
98#define FS_EEPROM_AUTONEG_SPEED_MASK 0x1
99#define FS_EEPROM_AUTONEG_SPEED_10 0x0
100#define FS_EEPROM_AUTONEG_SPEED_100 0x1
101#define FS_EEPROM_AUTONEG_DUPLEX_MASK 0x2
102#define FS_EEPROM_AUTONEG_DUPLEX_HALF 0x0
103#define FS_EEPROM_AUTONEG_DUPLEX_FULL 0x2
104#define FS_EEPROM_AUTONEG_ENABLE_MASK 0x4
105#define FS_EEPROM_AUTONEG_DISABLE 0x0
106#define FS_EEPROM_AUTONEG_ENABLE 0x4
107
108
109typedef struct
110{
111 unsigned int* punSrc;
112 unsigned int unLen;
113 unsigned int* punDest;
114 union {
115 unsigned int unReg;
116 struct {
117 unsigned uStatus : 16;
118 unsigned uRes : 12;
119 unsigned uFull : 1;
120 unsigned uEnable : 1;
121 unsigned uInt : 1;
122 unsigned uWrap : 1;
123 } bits;
124 } s;
125} rx_buffer_desc_t;
126
127typedef struct
128{
129 unsigned int* punSrc;
130 unsigned int unLen;
131 unsigned int* punDest;
132 union {
133 unsigned int unReg;
134
135 struct {
136 unsigned uStatus : 16;
137 unsigned uRes : 12;
138 unsigned uFull : 1;
139 unsigned uLast : 1;
140 unsigned uInt : 1;
141 unsigned uWrap : 1;
142 } bits;
143 } s;
144} tx_buffer_desc_t;
145
146static int ns9750_eth_reset( void );
147
148static void ns9750_link_force( void );
149static void ns9750_link_auto_negotiate( void );
150static void ns9750_link_update_egcr( void );
151static void ns9750_link_print_changed( void );
152
153
154
155static char ns9750_mii_identify_phy( void );
156static unsigned short ns9750_mii_read( unsigned short uiRegister );
157static void ns9750_mii_write( unsigned short uiRegister, unsigned short uiData );
158static unsigned int ns9750_mii_get_clock_divisor( unsigned int unMaxMDIOClk );
159static unsigned int ns9750_mii_poll_busy( void );
160
161static unsigned int nPhyMaxMdioClock = PHY_MDIO_MAX_CLK;
162static unsigned char ucLinkMode = FS_EEPROM_AUTONEG_ENABLE;
163static unsigned int uiLastLinkStatus;
164static PhyType phyDetected = PHY_NONE;
165
166
167static tx_buffer_desc_t* pTxBufferDesc =
168 (tx_buffer_desc_t*) get_eth_reg_addr( NS9750_ETH_TXBD );
169
170
171static rx_buffer_desc_t aRxBufferDesc[ 4 ];
172
173
174
175
176
177
178
179
180int eth_init (bd_t * pbis)
181{
182
183
184 unsigned char aucMACAddr[6] = { 0x00, 0x04, 0xf3, 0x00, 0x06, 0x35 };
185 char *pcTmp = getenv ("ethaddr");
186 char *pcEnd;
187 int i;
188
189 DEBUG_FN (DEBUG_INIT);
190
191
192
193 if (!ns9750_eth_reset ())
194 return -1;
195
196 if (pcTmp != NULL)
197 for (i = 0; i < 6; i++) {
198 aucMACAddr[i] =
199 pcTmp ? simple_strtoul (pcTmp, &pcEnd,
200 16) : 0;
201 pcTmp = (*pcTmp) ? pcEnd + 1 : pcEnd;
202 }
203
204
205
206 *get_eth_reg_addr (NS9750_ETH_SA1) =
207 aucMACAddr[5] << 8 | aucMACAddr[4];
208 *get_eth_reg_addr (NS9750_ETH_SA2) =
209 aucMACAddr[3] << 8 | aucMACAddr[2];
210 *get_eth_reg_addr (NS9750_ETH_SA3) =
211 aucMACAddr[1] << 8 | aucMACAddr[0];
212
213
214
215 *get_eth_reg_addr (NS9750_ETH_MAC1) = NS9750_ETH_MAC1_RXEN;
216
217
218 *get_eth_reg_addr (NS9750_ETH_MAC2) = NS9750_ETH_MAC2_CRCEN |
219 NS9750_ETH_MAC2_PADEN | NS9750_ETH_MAC2_HUGE;
220
221
222 *get_eth_reg_addr (NS9750_ETH_EGCR1) =
223 NS9750_ETH_EGCR1_ETXWM |
224 NS9750_ETH_EGCR1_ERX |
225 NS9750_ETH_EGCR1_ERXDMA |
226 NS9750_ETH_EGCR1_ETX |
227 NS9750_ETH_EGCR1_ETXDMA | NS9750_ETH_EGCR1_ITXA;
228
229
230 for (i = 0; i < 4; i++) {
231 aRxBufferDesc[i].punSrc = 0;
232 aRxBufferDesc[i].unLen = 0;
233 aRxBufferDesc[i].s.bits.uWrap = 1;
234 aRxBufferDesc[i].s.bits.uInt = 1;
235 aRxBufferDesc[i].s.bits.uEnable = 0;
236 aRxBufferDesc[i].s.bits.uFull = 0;
237 }
238
239
240
241 aRxBufferDesc[0].punSrc = (unsigned int *) NetRxPackets[0];
242 aRxBufferDesc[0].s.bits.uEnable = 1;
243 aRxBufferDesc[0].unLen = 1522;
244
245 *get_eth_reg_addr (NS9750_ETH_RXAPTR) =
246 (unsigned int) &aRxBufferDesc[0];
247
248
249 *get_eth_reg_addr (NS9750_ETH_EGCR1) |= NS9750_ETH_EGCR1_ERXINIT;
250 while (!
251 (*get_eth_reg_addr (NS9750_ETH_EGSR) & NS9750_ETH_EGSR_RXINIT))
252
253 udelay (1);
254
255
256 *get_eth_reg_addr (NS9750_ETH_EGCR1) &= ~NS9750_ETH_EGCR1_ERXINIT;
257
258 *get_eth_reg_addr (NS9750_ETH_RXFREE) = 0x1;
259
260 return 0;
261}
262
263
264
265
266
267
268
269int eth_send (volatile void *pPacket, int nLen)
270{
271 ulong ulTimeout;
272
273 DEBUG_FN (DEBUG_TX);
274
275
276 *get_eth_reg_addr (NS9750_ETH_EINTR) &=
277 *get_eth_reg_addr (NS9750_ETH_EINTR) & NS9750_ETH_EINTR_TX_MA;
278
279
280
281 pTxBufferDesc->punSrc = (unsigned int *) pPacket;
282
283 pTxBufferDesc->unLen = nLen;
284
285 pTxBufferDesc->s.unReg = 0xf0000000;
286
287 *get_eth_reg_addr (NS9750_ETH_TXPTR) = 0x0;
288
289
290
291 *get_eth_reg_addr (NS9750_ETH_EGCR2) &= ~NS9750_ETH_EGCR2_TCLER;
292 *get_eth_reg_addr (NS9750_ETH_EGCR2) |= NS9750_ETH_EGCR2_TCLER;
293
294 ulTimeout = get_timer (0);
295
296 DEBUG_ARGS0 (DEBUG_TX | DEBUG_MINOR,
297 "Waiting for transmission to finish\n");
298 while (!
299 (*get_eth_reg_addr (NS9750_ETH_EINTR) &
300 (NS9750_ETH_EINTR_TXDONE | NS9750_ETH_EINTR_TXERR))) {
301
302 if (get_timer (0) - ulTimeout > TX_TIMEOUT) {
303 DEBUG_ARGS0 (DEBUG_TX, "Transmit Timed out\n");
304 return -1;
305 }
306 }
307 DEBUG_ARGS0 (DEBUG_TX | DEBUG_MINOR, "transmitted...\n");
308
309 return 0;
310}
311
312
313
314
315
316
317
318
319int eth_rx (void)
320{
321 int nLen = 0;
322 unsigned int unStatus;
323
324 unStatus =
325 *get_eth_reg_addr (NS9750_ETH_EINTR) & NS9750_ETH_EINTR_RX_MA;
326
327 if (!unStatus)
328
329 return 0;
330
331 DEBUG_FN (DEBUG_RX);
332
333
334 nLen = (int) aRxBufferDesc[0].unLen - 4;
335
336
337 *get_eth_reg_addr (NS9750_ETH_EINTR) = unStatus;
338
339 aRxBufferDesc[0].unLen = 1522;
340 aRxBufferDesc[0].s.bits.uFull = 0;
341
342
343 *get_eth_reg_addr (NS9750_ETH_RXFREE) |= 0x1;
344
345
346
347 if (unStatus & NS9750_ETH_EINTR_RXDONEA)
348 NetReceive (NetRxPackets[0], nLen);
349
350 return nLen;
351}
352
353
354
355
356
357
358
359void eth_halt (void)
360{
361 DEBUG_FN (DEBUG_INIT);
362
363 *get_eth_reg_addr (NS9750_ETH_MAC1) &= ~NS9750_ETH_MAC1_RXEN;
364 *get_eth_reg_addr (NS9750_ETH_EGCR1) &= ~(NS9750_ETH_EGCR1_ERX |
365 NS9750_ETH_EGCR1_ERXDMA |
366 NS9750_ETH_EGCR1_ETX |
367 NS9750_ETH_EGCR1_ETXDMA);
368}
369
370
371
372
373
374
375
376
377static int ns9750_eth_reset (void)
378{
379 DEBUG_FN (DEBUG_MINOR);
380
381
382 *get_eth_reg_addr (NS9750_ETH_EGCR1) |= NS9750_ETH_EGCR1_MAC_HRST;
383 udelay (5);
384 *get_eth_reg_addr (NS9750_ETH_EGCR1) &= ~NS9750_ETH_EGCR1_MAC_HRST;
385
386
387
388 *get_eth_reg_addr (NS9750_ETH_MAC1) &= ~NS9750_ETH_MAC1_SRST;
389
390
391
392
393
394
395
396
397
398 *get_eth_reg_addr (NS9750_ETH_MCFG) =
399 ns9750_mii_get_clock_divisor (nPhyMaxMdioClock);
400
401
402 ns9750_mii_write(MII_BMCR, BMCR_RESET);
403 ns9750_mii_write(MII_BMCR, 0);
404
405
406 udelay (3000);
407
408
409
410
411
412
413 if (!ns9750_mii_identify_phy ()) {
414 printk (KERN_ERR NS9750_DRIVER_NAME
415 ": Unsupported PHY, aborting\n");
416 return 0;
417 }
418
419
420 *get_eth_reg_addr (NS9750_ETH_MCFG) =
421 ns9750_mii_get_clock_divisor (nPhyMaxMdioClock);
422
423
424
425
426
427 uiLastLinkStatus = 0xff;
428
429 if ((ucLinkMode & FS_EEPROM_AUTONEG_ENABLE_MASK) ==
430 FS_EEPROM_AUTONEG_DISABLE)
431
432 ns9750_link_force ();
433 else
434 ns9750_link_auto_negotiate ();
435
436 if (phyDetected == PHY_LXT971A)
437
438 ns9750_mii_write (PHY_LXT971_LED_CFG,
439 PHY_LXT971_LED_CFG_LINK_ACT <<
440 PHY_LXT971_LED_CFG_SHIFT_LED2);
441
442 return 1;
443}
444
445
446
447
448
449
450
451
452static void ns9750_link_force (void)
453{
454 unsigned short uiControl;
455
456 DEBUG_FN (DEBUG_LINK);
457
458 uiControl = ns9750_mii_read(MII_BMCR);
459 uiControl &= ~(BMCR_SPEED1000 | BMCR_SPEED100 |
460 BMCR_ANENABLE | BMCR_FULLDPLX);
461
462 uiLastLinkStatus = 0;
463
464 if ((ucLinkMode & FS_EEPROM_AUTONEG_SPEED_MASK) ==
465 FS_EEPROM_AUTONEG_SPEED_100) {
466 uiControl |= BMCR_SPEED100;
467 uiLastLinkStatus |= PHY_LXT971_STAT2_100BTX;
468 }
469
470 if ((ucLinkMode & FS_EEPROM_AUTONEG_DUPLEX_MASK) ==
471 FS_EEPROM_AUTONEG_DUPLEX_FULL) {
472 uiControl |= BMCR_FULLDPLX;
473 uiLastLinkStatus |= PHY_LXT971_STAT2_DUPLEX_MODE;
474 }
475
476 ns9750_mii_write(MII_BMCR, uiControl);
477
478 ns9750_link_print_changed ();
479 ns9750_link_update_egcr ();
480}
481
482
483
484
485
486
487
488static void ns9750_link_auto_negotiate (void)
489{
490 unsigned long ulStartJiffies;
491 unsigned short uiStatus;
492
493 DEBUG_FN (DEBUG_LINK);
494
495
496
497 ns9750_mii_write(MII_ADVERTISE,
498 LPA_100FULL |
499 LPA_100HALF |
500 LPA_10FULL |
501 LPA_10HALF |
502 PHY_ANLPAR_PSB_802_3);
503
504 ns9750_mii_write(MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);
505
506
507
508 ulStartJiffies = get_ticks ();
509 while (get_ticks () < ulStartJiffies + NS9750_MII_NEG_DELAY) {
510 uiStatus = ns9750_mii_read(MII_BMSR);
511 if ((uiStatus &
512 (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) ==
513 (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) {
514
515 ns9750_link_print_changed ();
516 ns9750_link_update_egcr ();
517 return;
518 }
519 }
520
521 DEBUG_ARGS0 (DEBUG_LINK, "auto-negotiation timed out\n");
522
523}
524
525
526
527
528
529
530
531
532static void ns9750_link_update_egcr (void)
533{
534 unsigned int unEGCR;
535 unsigned int unMAC2;
536 unsigned int unIPGT;
537
538 DEBUG_FN (DEBUG_LINK);
539
540 unEGCR = *get_eth_reg_addr (NS9750_ETH_EGCR1);
541 unMAC2 = *get_eth_reg_addr (NS9750_ETH_MAC2);
542 unIPGT = *get_eth_reg_addr (NS9750_ETH_IPGT) & ~NS9750_ETH_IPGT_MA;
543
544 unMAC2 &= ~NS9750_ETH_MAC2_FULLD;
545 if ((uiLastLinkStatus & PHY_LXT971_STAT2_DUPLEX_MODE)
546 == PHY_LXT971_STAT2_DUPLEX_MODE) {
547 unMAC2 |= NS9750_ETH_MAC2_FULLD;
548 unIPGT |= 0x15;
549 } else
550 unIPGT |= 0x12;
551
552 *get_eth_reg_addr (NS9750_ETH_MAC2) = unMAC2;
553 *get_eth_reg_addr (NS9750_ETH_EGCR1) = unEGCR;
554 *get_eth_reg_addr (NS9750_ETH_IPGT) = unIPGT;
555}
556
557
558
559
560
561
562
563
564static void ns9750_link_print_changed (void)
565{
566 unsigned short uiStatus;
567 unsigned short uiControl;
568
569 DEBUG_FN (DEBUG_LINK);
570
571 uiControl = ns9750_mii_read(MII_BMCR);
572
573 if ((uiControl & BMCR_ANENABLE) == BMCR_ANENABLE) {
574
575 uiStatus = ns9750_mii_read(MII_BMSR);
576
577 if (!(uiStatus & BMSR_LSTATUS)) {
578 printk (KERN_WARNING NS9750_DRIVER_NAME
579 ": link down\n");
580
581 } else {
582
583 if (phyDetected == PHY_LXT971A) {
584 uiStatus = ns9750_mii_read (PHY_LXT971_STAT2);
585 uiStatus &= (PHY_LXT971_STAT2_100BTX |
586 PHY_LXT971_STAT2_DUPLEX_MODE |
587 PHY_LXT971_STAT2_AUTO_NEG);
588
589
590 }
591
592
593 }
594 } else {
595
596
597 uiStatus = uiLastLinkStatus;
598 uiLastLinkStatus = 0xff;
599 }
600
601 if (uiStatus != uiLastLinkStatus) {
602
603 uiLastLinkStatus = uiStatus;
604
605
606
607 printk (KERN_INFO NS9750_DRIVER_NAME
608 ": link mode %i Mbps %s duplex %s\n",
609 (uiStatus & PHY_LXT971_STAT2_100BTX) ? 100 : 10,
610 (uiStatus & PHY_LXT971_STAT2_DUPLEX_MODE) ? "full" :
611 "half",
612 (uiStatus & PHY_LXT971_STAT2_AUTO_NEG) ? "(auto)" :
613 "");
614 }
615}
616
617
618
619
620
621
622
623
624
625
626
627static char ns9750_mii_identify_phy (void)
628{
629 unsigned short uiID1;
630 unsigned short uiID2;
631 unsigned char *szName;
632 char cRes = 0;
633
634 DEBUG_FN (DEBUG_MII);
635
636 phyDetected = (PhyType) uiID1 = ns9750_mii_read(MII_PHYSID1);
637
638 switch (phyDetected) {
639 case PHY_LXT971A:
640 szName = "LXT971A";
641 uiID2 = ns9750_mii_read(MII_PHYSID2);
642 nPhyMaxMdioClock = PHY_LXT971_MDIO_MAX_CLK;
643 cRes = 1;
644 break;
645 case PHY_NONE:
646 default:
647
648
649
650 uiID2 = 0;
651 szName = "unknown";
652 nPhyMaxMdioClock = PHY_MDIO_MAX_CLK;
653 phyDetected = PHY_NONE;
654 }
655
656 printk (KERN_INFO NS9750_DRIVER_NAME
657 ": PHY (0x%x, 0x%x) = %s detected\n", uiID1, uiID2, szName);
658
659 return cRes;
660}
661
662
663
664
665
666
667
668
669
670static unsigned short ns9750_mii_read (unsigned short uiRegister)
671{
672 DEBUG_FN (DEBUG_MII_LOW);
673
674
675 *get_eth_reg_addr (NS9750_ETH_MADR) =
676 NS9750_ETH_PHY_ADDRESS << 8 | uiRegister;
677
678 *get_eth_reg_addr (NS9750_ETH_MCMD) = NS9750_ETH_MCMD_READ;
679
680 if (!ns9750_mii_poll_busy ())
681 printk (KERN_WARNING NS9750_DRIVER_NAME
682 ": MII still busy in read\n");
683
684
685 *get_eth_reg_addr (NS9750_ETH_MCMD) = 0;
686
687 return (unsigned short) (*get_eth_reg_addr (NS9750_ETH_MRDD));
688}
689
690
691
692
693
694
695
696
697
698
699static void ns9750_mii_write (unsigned short uiRegister,
700 unsigned short uiData)
701{
702 DEBUG_FN (DEBUG_MII_LOW);
703
704
705 *get_eth_reg_addr (NS9750_ETH_MADR) =
706 NS9750_ETH_PHY_ADDRESS << 8 | uiRegister;
707
708 *get_eth_reg_addr (NS9750_ETH_MWTD) = uiData;
709
710 if (!ns9750_mii_poll_busy ()) {
711 printf (KERN_WARNING NS9750_DRIVER_NAME
712 ": MII still busy in write\n");
713 }
714}
715
716
717
718
719
720
721
722
723
724
725static unsigned int ns9750_mii_get_clock_divisor (unsigned int unMaxMDIOClk)
726{
727 struct {
728 unsigned int unSysClkDivisor;
729 unsigned int unClks;
730 } PHYClockDivisors[] = {
731 {
732 4, NS9750_ETH_MCFG_CLKS_4}, {
733 6, NS9750_ETH_MCFG_CLKS_6}, {
734 8, NS9750_ETH_MCFG_CLKS_8}, {
735 10, NS9750_ETH_MCFG_CLKS_10}, {
736 20, NS9750_ETH_MCFG_CLKS_20}, {
737 30, NS9750_ETH_MCFG_CLKS_30}, {
738 40, NS9750_ETH_MCFG_CLKS_40}
739 };
740
741 int nIndexSysClkDiv;
742 int nArraySize =
743 sizeof (PHYClockDivisors) / sizeof (PHYClockDivisors[0]);
744 unsigned int unClks = NS9750_ETH_MCFG_CLKS_40;
745
746
747 DEBUG_FN (DEBUG_INIT);
748
749 for (nIndexSysClkDiv = 0; nIndexSysClkDiv < nArraySize;
750 nIndexSysClkDiv++) {
751
752
753 if (AHB_CLK_FREQ /
754 PHYClockDivisors[nIndexSysClkDiv].unSysClkDivisor <=
755 unMaxMDIOClk) {
756 unClks = PHYClockDivisors[nIndexSysClkDiv].unClks;
757 break;
758 }
759 }
760
761 DEBUG_ARGS2 (DEBUG_INIT,
762 "Taking MDIO Clock bit mask 0x%0x for max clock %i\n",
763 unClks, unMaxMDIOClk);
764
765
766 return unClks;
767}
768
769
770
771
772
773
774
775
776
777
778static unsigned int ns9750_mii_poll_busy (void)
779{
780 unsigned int unTimeout = 10000;
781
782 DEBUG_FN (DEBUG_MII_LOW);
783
784 while (((*get_eth_reg_addr (NS9750_ETH_MIND) & NS9750_ETH_MIND_BUSY)
785 == NS9750_ETH_MIND_BUSY) && unTimeout)
786 unTimeout--;
787
788 return unTimeout;
789}
790