summaryrefslogtreecommitdiffstats
path: root/drivers/net/aspeednic.c
blob: 8b85893a4f7460126e41d3627e4e681bdfbb902a (plain)
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
/*
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <common.h>
#include <net.h>
#include <asm/io.h>

//#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && defined(CONFIG_ASPEEDNIC)

/* From the board config file */
#define CONFIG_MAC1_PHY_SETTING         2
#define CONFIG_MAC2_PHY_SETTING         0
#define CONFIG_ASPEED_MAC_NUMBER  1
#define CONFIG_ASPEED_MAC_CONFIG  1 // config MAC1
#define _PHY_SETTING_CONCAT(mac) CONFIG_MAC##mac##_PHY_SETTING
#define _GET_MAC_PHY_SETTING(mac) _PHY_SETTING_CONCAT(mac)
#define CONFIG_ASPEED_MAC_PHY_SETTING \
	  _GET_MAC_PHY_SETTING(CONFIG_ASPEED_MAC_CONFIG)
#define CONFIG_MAC_INTERFACE_CLOCK_DELAY        0x2255
#define CONFIG_RANDOM_MACADDR


#include <malloc.h>
#include <net.h>
#include <pci.h>
#include <linux/mii.h>


/*
  SCU88 D[31]: MAC1 MDIO
  SCU88 D[30]: MAC1 MDC
  SCU90 D[2]:  MAC2 MDC/MDIO
  SCU80 D[0]:  MAC1 Link
  SCU80 D[1]:  MAC2 Link
*/
#define pci_find_devices         NULL
#define pci_read_config_dword    NULL
#define SCU_BASE                 0x1E6E2000
#define SCU_RESET_CONTROL        0x04
#define SCU_CLOCK_SELECTION      0x08
#define SCU_CLOCK_CONTROL        0x0C
#define SCU_MAC_CLOCK_DELAY      0x48
#define SCU_SCRATCH_REGISTER     0x40
#define SCU_HARDWARE_TRAPPING    0x70
#define SCU_PIN_MUX              0x74
#define SCU_MULTIFUNCTION_PIN_CTL1_REG     0x80
#define SCU_MULTIFUNCTION_PIN_CTL3_REG     0x88
#define SCU_MULTIFUNCTION_PIN_CTL5_REG     0x90
#define MAC_INTERFACE            0x1C0
#define GMII                     0x0
#define MII                      0x40
#define MAC1_CLOCK_ENABLE        (1 << 20)
#define MAC2_CLOCK_ENABLE        (1 << 21)
#define MAC_AHB_CLOCK_DIVIDER    (0x07 << 16)
#define MAC1_MDIO                (1 << 31)
#define MAC1_MDC                 (1 << 30)
#define MAC1_PHY_LINK            (1 << 0)
#define MAC2_MDC_MDIO            (1 << 2)
#define MAC2_PHY_LINK            (1 << 1)

static unsigned int aspeednic_iobase[] = {
	0x1E660000,
	0x1E680000,
};

/* PHY address */
static u8 g_phy_addr = 0;

/* PCI Registers.
 */
/* MAC chip register */
#define ISR_REG       0x00        // interrups status register
#define IER_REG       0x04        // interrupt maks register
#define MAC_MADR_REG            0x08        // MAC address (Most significant)
#define MAC_LADR_REG            0x0c        // MAC address (Least significant)

#define MAHT0_REG     0x10        // Multicast Address Hash Table 0 register
#define MAHT1_REG     0x14        // Multicast Address Hash Table 1 register
#define TXPD_REG      0x18        // Transmit Poll Demand register
#define RXPD_REG      0x1c        // Receive Poll Demand register
#define TXR_BADR_REG            0x20        // Transmit Ring Base Address register
#define RXR_BADR_REG            0x24        // Receive Ring Base Address register

#define HPTXPD_REG      0x28  //
#define HPTXR_BADR_REG            0x2c  //

#define ITC_REG       0x30        // interrupt timer control register
#define APTC_REG      0x34        // Automatic Polling Timer control register
#define DBLAC_REG     0x38        // DMA Burst Length and Arbitration control register

#define DMAFIFOS_REG            0x3c  //
#define FEAR_REG      0x44  //
#define TPAFCR_REG      0x48  //
#define RBSR_REG      0x4c  //for NC Body
#define MACCR_REG     0x50        // MAC control register
#define MACSR_REG     0x54        // MAC status register
#define PHYCR_REG     0x60        // PHY control register
#define PHYDATA_REG     0x64        // PHY Write Data register
#define FCR_REG       0x68        // Flow Control register
#define BPR_REG       0x6c        // back pressure register
#define WOLCR_REG     0x70        // Wake-On-Lan control register
#define WOLSR_REG     0x74        // Wake-On-Lan status register
#define WFCRC_REG     0x78        // Wake-up Frame CRC register
#define WFBM1_REG     0x80        // wake-up frame byte mask 1st double word register
#define WFBM2_REG     0x84        // wake-up frame byte mask 2nd double word register
#define WFBM3_REG     0x88        // wake-up frame byte mask 3rd double word register
#define WFBM4_REG     0x8c        // wake-up frame byte mask 4th double word register


// --------------------------------------------------------------------
//    MACCR_REG
// --------------------------------------------------------------------

#define SW_RST_bit      (1UL<<31)       // software reset/
#define DIRPATH_bit     (1UL<<21)
#define RX_IPCS_FAIL_bit  (1UL<<20) //
#define RX_TCPCS_FAIL_bit (1UL<<19) //
#define SPEED_100M_MODE_bit     (1UL<<19)
#define RX_UDPCS_FAIL_bit (1UL<<18) //
#define RX_BROADPKT_bit   (1UL<<17)       // Receiving broadcast packet
#define RX_MULTIPKT_bit   (1UL<<16)       // receiving multicast packet
#define RX_HT_EN_bit    (1UL<<15)
#define RX_ALLADR_bit   (1UL<<14)       // not check incoming packet's destination address
#define JUMBO_LF_bit    (1UL<<13) //
#define RX_RUNT_bit     (1UL<<12)       // Store incoming packet even its length is les than 64 byte
#define CRC_CHK_bit     (1UL<<11) //
#define CRC_APD_bit     (1UL<<10)       // append crc to transmit packet
#define GMAC_MODE_bit   (1UL<<9)  //
#define FULLDUP_bit     (1UL<<8)        // full duplex
#define ENRX_IN_HALFTX_bit  (1UL<<7)  //
#define LOOP_EN_bit     (1UL<<6)        // Internal loop-back
#define HPTXR_EN_bit    (1UL<<5)  //
#define REMOVE_VLAN_bit   (1UL<<4)  //
#define RXMAC_EN_bit    (1UL<<3)        // receiver enable
#define TXMAC_EN_bit    (1UL<<2)        // transmitter enable
#define RXDMA_EN_bit    (1UL<<1)        // enable DMA receiving channel
#define TXDMA_EN_bit    (1UL<<0)        // enable DMA transmitting channel

//---------------------------------------------------
//  PHY R/W Register Bit
//---------------------------------------------------
#define MIIWR                   (1UL<<27)
#define MIIRD                   (1UL<<26)
#define MDC_CYCTHR              0x34
#define PHY_SPEED_MASK          0xC000
#define PHY_DUPLEX_MASK         0x2000
#define SPEED_1000M             0x02
#define SPEED_100M              0x01
#define SPEED_10M               0x00
#define DUPLEX_FULL             0x01
#define DUPLEX_HALF             0x00
#define RESOLVED_BIT            0x800

#define PHY_SPEED_DUPLEX_MASK   0x01E0
#define PHY_100M_DUPLEX         0x0100
#define PHY_100M_HALF           0x0080
#define PHY_10M_DUPLEX          0x0040
#define PHY_10M_HALF            0x0020



/* Descriptor bits.
 */
#define TXDMA_OWN 0x80000000  /* Own Bit */
#define RXPKT_RDY       0x00000000
#define RXPKT_STATUS    0x80000000
//#define EDORR   0x00008000  /* Receive End Of Ring */
#define EDORR   0x40000000  /* Receive End Of Ring */
#define LRS   0x10000000  /* Last Descriptor */
#define RD_ES   0x00008000  /* Error Summary */
//#define EDOTR   0x00008000  /* Transmit End Of Ring */
#define EDOTR   0x40000000  /* Transmit End Of Ring */
#define T_OWN   0x80000000  /* Own Bit */
#define LTS   0x10000000  /* Last Segment */
#define FTS   0x20000000  /* First Segment */
#define CRC_ERR         0x00080000
#define TD_ES   0x00008000  /* Error Summary */
#define TD_SET    0x08000000  /* Setup Packet */
#define RX_ERR          0x00040000
#define FTL             0x00100000
#define RUNT            0x00200000
#define RX_ODD_NB       0x00400000

#define POLL_DEMAND 1
#define RESET_DE4X5(dev) {                                              \
    int i;                                                              \
    i=INL(dev, MACCR_REG);                                              \
    udelay(1000);                                                       \
    OUTL(dev, i | SW_RST_bit, MACCR_REG);                               \
    for (; (INL(dev, MACCR_REG ) & SW_RST_bit) != 0; ) {udelay(1000);}  \
    OUTL(dev, 0, IER_REG );                                             \
  }

#define START_MAC(dev) {                                              \
    s32 omr;                                                          \
    omr = INL(dev, MACCR_REG);                                        \
    omr |= RXMAC_EN_bit | TXMAC_EN_bit | RXDMA_EN_bit | TXDMA_EN_bit; \
    OUTL(dev, omr, MACCR_REG);    /* Enable the TX and/or RX */       \
  }

#define STOP_MAC(dev) {                                                 \
    s32 omr;                                                            \
    omr = INL(dev, MACCR_REG);                                          \
    omr &= ~(RXMAC_EN_bit | TXMAC_EN_bit | RXDMA_EN_bit | TXDMA_EN_bit); \
    OUTL(dev, omr, MACCR_REG);    /* Disable the TX and/or RX */        \
  }

#define NUM_RX_DESC PKTBUFSRX
#define NUM_TX_DESC 1     /* Number of TX descriptors   */
#define RX_BUFF_SZ  1600 /* Hardware defaults to this */
#define TX_BUFF_SZ  1514

#define TOUT_LOOP   1000000
#define PHY_LOOP    250
#define ETH_ALEN  6
#define NCSI_LOOP   1500000
#define RETRY_COUNT     1

struct de4x5_desc {
	volatile s32 status;
	u32 des1;
	u32 reserved;
	u32 buf;
};

//PHY Information
#define PHYID_VENDOR_MASK	0xfffffc00
#define PHYID_VENDOR_MODEL_MASK	0xfffffff0
#define PHYID_VENDOR_MARVELL	0x01410c00
#define PHYID_VENDOR_BROADCOM	0x00406000
#define PHYID_VENDOR_REALTEK	0x001cc800
#define PHYID_RTL8201EL		0x001cc810
#define PHYID_RTL8211		0x001cc910
#define PHYID_BCM54612E		0x03625E6A
#define PHYID_BCM54616S		0x03625D12

//NCSI define & structure
//NC-SI Command Packet
typedef struct {
	//Ethernet Header
	unsigned char  DA[6];
	unsigned char  SA[6];
	unsigned short EtherType;           //DMTF NC-SI
	//NC-SI Control Packet
	unsigned char  MC_ID;           //Management Controller should set this field to 0x00
	unsigned char  Header_Revision;         //For NC-SI 1.0 spec, this field has to set 0x01
	unsigned char  Reserved_1;            //Reserved has to set to 0x00
	unsigned char  IID;             //Instance ID
	unsigned char  Command;
	unsigned char  Channel_ID;
	unsigned short Payload_Length;          //Payload Length = 12 bits, 4 bits are reserved
	unsigned long  Reserved_2;
	unsigned long  Reserved_3;
} NCSI_Command_Packet;

unsigned char  Payload_Data[16];
unsigned char  Payload_Pad[4] = {0x00, 0x00, 0x00, 0x00};
unsigned long  Payload_Checksum = 0x00000000;


//Command and Response Type
#define CLEAR_INITIAL_STATE     0x00      //M
#define SELECT_PACKAGE        0x01      //M
#define DESELECT_PACKAGE      0x02      //M
#define ENABLE_CHANNEL        0x03      //M
#define DISABLE_CHANNEL       0x04      //M
#define RESET_CHANNEL       0x05      //M
#define ENABLE_CHANNEL_NETWORK_TX   0x06      //M
#define DISABLE_CHANNEL_NETWORK_TX    0x07      //M
#define AEN_ENABLE        0x08
#define SET_LINK        0x09      //M
#define GET_LINK_STATUS       0x0A      //M
#define SET_VLAN_FILTER       0x0B      //M
#define ENABLE_VLAN       0x0C      //M
#define DISABLE_VLAN        0x0D      //M
#define SET_MAC_ADDRESS       0x0E      //M
#define ENABLE_BROADCAST_FILTERING    0x10      //M
#define DISABLE_BROADCAST_FILTERING   0x11      //M
#define ENABLE_GLOBAL_MULTICAST_FILTERING 0x12
#define DISABLE_GLOBAL_MULTICAST_FILTERING  0x13
#define SET_NCSI_FLOW_CONTROL     0x14
#define GET_VERSION_ID        0x15      //M
#define GET_CAPABILITIES      0x16      //M
#define GET_PARAMETERS        0x17      //M
#define GET_CONTROLLER_PACKET_STATISTICS  0x18
#define GET_NCSI_STATISTICS     0x19
#define GET_NCSI_PASS_THROUGH_STATISTICS  0x1A

//NC-SI Response Packet
typedef struct {
  unsigned char  DA[6];
  unsigned char  SA[6];
  unsigned short EtherType;           //DMTF NC-SI
//NC-SI Control Packet
  unsigned char  MC_ID;           //Management Controller should set this field to 0x00
  unsigned char  Header_Revision;         //For NC-SI 1.0 spec, this field has to set 0x01
  unsigned char  Reserved_1;            //Reserved has to set to 0x00
  unsigned char  IID;             //Instance ID
  unsigned char  Command;
  unsigned char  Channel_ID;
  unsigned short Payload_Length;          //Payload Length = 12 bits, 4 bits are reserved
  unsigned short  Reserved_2;
  unsigned short  Reserved_3;
  unsigned short  Reserved_4;
  unsigned short  Reserved_5;
  unsigned short  Response_Code;
  unsigned short  Reason_Code;
  unsigned char   Payload_Data[64];
}  NCSI_Response_Packet;

NCSI_Command_Packet NCSI_Request;
NCSI_Response_Packet NCSI_Respond;

//Standard Response Code
#define COMMAND_COMPLETED     0x00
#define COMMAND_FAILED        0x01
#define COMMAND_UNAVAILABLE     0x02
#define COMMAND_UNSUPPORTED     0x03

//Standard Reason Code
#define NO_ERROR        0x0000
#define INTERFACE_INITIALIZATION_REQUIRED 0x0001
#define PARAMETER_IS_INVALID      0x0002
#define CHANNEL_NOT_READY     0x0003
#define PACKAGE_NOT_READY     0x0004
#define INVALID_PAYLOAD_LENGTH      0x0005
#define UNKNOWN_COMMAND_TYPE      0x7FFF


struct AEN_Packet {
//Ethernet Header
  unsigned char  DA[6];
  unsigned char  SA[6];           //Network Controller SA = FF:FF:FF:FF:FF:FF
  unsigned short EtherType;           //DMTF NC-SI
//AEN Packet Format
  unsigned char  MC_ID;           //Network Controller should set this field to 0x00
  unsigned char  Header_Revision;         //For NC-SI 1.0 spec, this field has to set 0x01
  unsigned char  Reserved_1;            //Reserved has to set to 0x00
//    unsigned char  IID = 0x00;            //Instance ID = 0 in Network Controller
//    unsigned char  Command = 0xFF;          //AEN = 0xFF
  unsigned char  Channel_ID;
//    unsigned short Payload_Length = 0x04;       //Payload Length = 4 in Network Controller AEN Packet
  unsigned long  Reserved_2;
  unsigned long  Reserved_3;
  unsigned char  AEN_Type;
//    unsigned char  Reserved_4[3] = {0x00, 0x00, 0x00};
  unsigned long  Optional_AEN_Data;
  unsigned long  Payload_Checksum;
};

//AEN Type
#define LINK_STATUS_CHANGE      0x0
#define CONFIGURATION_REQUIRED      0x1
#define HOST_NC_DRIVER_STATUS_CHANGE    0x2

typedef struct {
  unsigned char Package_ID;
  unsigned char Channel_ID;
  unsigned long Capabilities_Flags;
  unsigned long Broadcast_Packet_Filter_Capabilities;
  unsigned long Multicast_Packet_Filter_Capabilities;
  unsigned long Buffering_Capabilities;
  unsigned long AEN_Control_Support;
} NCSI_Capability;
NCSI_Capability NCSI_Cap;

//SET_MAC_ADDRESS
#define UNICAST   (0x00 << 5)
#define MULTICAST (0x01 << 5)
#define DISABLE_MAC_ADDRESS_FILTER  0x00
#define ENABLE_MAC_ADDRESS_FILTER 0x01

//GET_LINK_STATUS
#define LINK_DOWN 0
#define LINK_UP   1

static struct de4x5_desc rx_ring[NUM_RX_DESC] __attribute__ ((aligned(32))); /* RX descriptor ring         */
static struct de4x5_desc tx_ring[NUM_TX_DESC] __attribute__ ((aligned(32))); /* TX descriptor ring         */
static int rx_new;                             /* RX descriptor ring pointer */
static int tx_new;                             /* TX descriptor ring pointer */
static unsigned char tx_buffer[NUM_TX_DESC][TX_BUFF_SZ] __attribute__ ((aligned(32)));
static unsigned char rx_buffer[NUM_RX_DESC][RX_BUFF_SZ] __attribute__ ((aligned(32)));


static char rxRingSize;
static char txRingSize;
static unsigned int InstanceID = 0;
static int Retry = 0;

static int   aspeednic_init(struct eth_device* dev, bd_t* bis);
static int   aspeednic_send(struct eth_device* dev, void *packet, int length);
static int   aspeednic_recv(struct eth_device* dev);
static void  aspeednic_halt(struct eth_device* dev);
static int   aspeednic_write_hwaddr(struct eth_device* dev);
static void  phy_write_register (struct eth_device* dev, u8 PHY_Register, u8 PHY_Address, u16 PHY_Data);
static u16   phy_read_register (struct eth_device* dev, u8 PHY_Register, u8 PHY_Address);
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
static int faraday_mdio_read(const char *devname, uint8_t addr, uint8_t reg,
                             uint16_t *value);
static int faraday_mdio_write(const char *devname, uint8_t addr, uint8_t reg,
                              uint16_t value);
#endif
static void  set_mac_control_register(struct eth_device* dev);

#if defined(CONFIG_E500)
#define phys_to_bus(a) (a)
#else
#define phys_to_bus(a)  pci_phys_to_mem((pci_dev_t)dev->priv, a)
#endif

static int INL(struct eth_device* dev, u_long addr)
{
  return le32_to_cpu(*(volatile u_long *)(addr + dev->iobase));
}

static void OUTL(struct eth_device* dev, int command, u_long addr)
{
	*(volatile u_long *)(addr + dev->iobase) = cpu_to_le32(command);
}


struct eth_device aspeednic_device[CONFIG_ASPEED_MAC_NUMBER];

void NCSI_Struct_Initialize(void)
{
	unsigned long i;

	for (i = 0; i < 6; i++) {
		NCSI_Request.DA[i] = 0xFF;
		NCSI_Respond.DA[i] = 0xFF;
		NCSI_Respond.SA[i] = 0xFF;
	}

	NCSI_Request.EtherType = 0xF888;
	NCSI_Request.MC_ID = 0;
	NCSI_Request.Header_Revision = 0x01;
	NCSI_Request.Reserved_1 = 0;
	NCSI_Request.Reserved_2 = 0;
	NCSI_Request.Reserved_3 = 0;
	NCSI_Respond.EtherType = 0xF888;
	NCSI_Respond.MC_ID = 0;
	NCSI_Respond.Header_Revision = 0x01;
	NCSI_Respond.Reserved_1 = 0;
	NCSI_Respond.Reserved_2 = 0;
	NCSI_Respond.Reserved_3 = 0;
}

static void aspeed_mac1_enable(void)
{
	u32 reg;

	/* MAC1 CLOCK/RESET/PHY_LINK/MDC_MDIO in SCU */
	reg = readl(AST_SCU_BASE + SCU_RESET_CONTROL);
	writel(reg | BIT(11), AST_SCU_BASE + SCU_RESET_CONTROL);
	udelay(100);

	reg = readl(AST_SCU_BASE + SCU_CLOCK_CONTROL);
	writel(reg & ~MAC1_CLOCK_ENABLE, AST_SCU_BASE + SCU_CLOCK_CONTROL);
	udelay(10000);

	reg = readl(AST_SCU_BASE + SCU_RESET_CONTROL);
	writel(reg & ~BIT(11), AST_SCU_BASE + SCU_RESET_CONTROL);

	/* Put pins in RMII/NCSI mode
	 * Strap[6] = 0 and SCUA0[0:3, 12, 14:17]
	 *
	 * RMII1CLKI	SCUA0[12] = 0
	 * RMII1RCLKO	SCUA0[0] = 0
	 * RMII1TXEN	SCUA0[1] = 0
	 * RMII1TXD0	SCUA0[2] = 0
	 * RMII1TXD1	SCUA0[3] = 0
	 * RMII1RXD0	SCUA0[14] = 0
	 * RMII1RXD1	SCUA0[15] = 0
	 * RMII1CRSDV	SCUA0[16] = 0
	 * RMII1RXER	SCUA0[17] = 0
	 */
	reg = readl(AST_SCU_BASE + 0xA0);
	writel(reg & ~0x3d00f, AST_SCU_BASE + 0xA0);

	reg = readl(AST_SCU_BASE + 0x70);
	writel(reg & ~BIT(6), AST_SCU_BASE + 0x70);

	/* RMII1 50MHz RCLK output enable */
	reg = readl(AST_SCU_BASE + 0x48);
	writel(reg | BIT(29), AST_SCU_BASE + 0x48);

#ifdef CONFIG_MAC1_PHY_LINK_INTERRUPT
	reg = readl(SCU_BASE + SCU_MULTIFUNCTION_PIN_CTL1_REG);
	writel(reg | MAC1_PHY_LINK, SCU_BASE + SCU_MULTIFUNCTION_PIN_CTL1_REG);
#endif
}

static void aspeed_mac2_enable(void)
{
	//MAC2 CLOCK/RESET/PHY_LINK/MDC_MDIO
#ifdef CONFIG_MAC2_ENABLE
	u32 reg;

	reg = readl(SCU_BASE + SCU_RESET_CONTROL);
	writel(reg | 0x1000, SCU_BASE + SCU_RESET_CONTROL);
	udelay(10);
	reg = readl(SCU_BASE + SCU_CLOCK_CONTROL);
	writel(reg & ~MAC2_CLOCK_ENABLE, SCU_BASE + SCU_CLOCK_CONTROL);
	udelay(10000);
	reg = readl(SCU_BASE + SCU_RESET_CONTROL);
	writel(reg & ~0x1000, SCU_BASE + SCU_RESET_CONTROL);
	reg = readl(SCU_BASE + SCU_MULTIFUNCTION_PIN_CTL5_REG);
	writel(reg | (MAC2_MDC_MDIO), SCU_BASE + SCU_MULTIFUNCTION_PIN_CTL5_REG);
#ifdef CONFIG_MAC2_PHY_LINK_INTERRUPT
	reg = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_MULTIFUNCTION_PIN_CTL1_REG));
	writel(reg | MAC2_PHY_LINK, SCU_BASE + SCU_MULTIFUNCTION_PIN_CTL1_REG);
#endif
#endif
}

int aspeednic_initialize(bd_t *bis)
{
	int card_number = CONFIG_ASPEED_MAC_CONFIG - 1;
	unsigned int iobase;
	struct eth_device*  dev;

	aspeed_mac1_enable();
	aspeed_mac2_enable();

	iobase = aspeednic_iobase[card_number];

	dev = &aspeednic_device[card_number];

	sprintf(dev->name, "aspeednic#%d", card_number);

	dev->iobase = iobase;

	if (CONFIG_ASPEED_MAC_PHY_SETTING >= 1) {
		//NCSI Struct Initialize
		NCSI_Struct_Initialize();
	}

	dev->init = aspeednic_init;
	dev->halt = aspeednic_halt;
	dev->send = aspeednic_send;
	dev->recv = aspeednic_recv;
	dev->write_hwaddr = aspeednic_write_hwaddr;

	/* Ensure we're not sleeping. */
	if (CONFIG_ASPEED_MAC_PHY_SETTING >= 1) {
		udelay(2000000); //2.0 sec
	}
	else {
		udelay(10 * 1000);
	}

	eth_register(dev);

#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
	miiphy_register(dev->name, faraday_mdio_read, faraday_mdio_write);
#endif

	return 1;
}

void Calculate_Checksum(unsigned char *buffer_base, int Length)
{
	unsigned int i, CheckSum = 0;
	unsigned int Data, Data1;

	for (i = 0; i < ((Length - 14) / 2); i++) {
		Data = buffer_base[i * 2];
		Data1 = buffer_base[i * 2 + 1];
		CheckSum += ((Data << 8) + Data1);
	}
	Payload_Checksum = (~(CheckSum) + 1); //2's complement
	//Inverse for insert into buffer
	Data = (Payload_Checksum & 0xFF000000) >> 24;
	Data1 = (Payload_Checksum & 0x000000FF) << 24;
	Payload_Checksum = (Payload_Checksum & 0x00FFFF00) + Data + Data1;
	Data = (Payload_Checksum & 0x00FF0000) >> 8;
	Data1 = (Payload_Checksum & 0x0000FF00) << 8;
	Payload_Checksum = (Payload_Checksum & 0xFF0000FF) + Data + Data1;
}

void copy_data (int Length)
{
	memcpy ((unsigned char *)(tx_ring[tx_new].buf + 30), &Payload_Data, Length);
	Calculate_Checksum((unsigned char *)(tx_ring[tx_new].buf + 14), 30 + Length);
	memcpy ((unsigned char *)(tx_ring[tx_new].buf + 30 + Length), &Payload_Checksum, 4);
}

void NCSI_Rx (void)
{
	unsigned long status, length, i = 0;

	do {
		status = (s32)le32_to_cpu(rx_ring[rx_new].status);
		i++;
	} while (!(((status & RXPKT_STATUS) != 0) || (i >= NCSI_LOOP)));

	if (i < NCSI_LOOP) {
		if (status & LRS) {
			length = (le32_to_cpu(rx_ring[rx_new].status) & 0x3FFF);
			memcpy (&NCSI_Respond, (unsigned char *)rx_ring[rx_new].buf, length);
		}
		rx_ring[rx_new].status &= cpu_to_le32(0x7FFFFFFF);
		rx_new = (rx_new + 1) % rxRingSize;
	}
}

void DeSelect_Package (struct eth_device* dev, int Package_ID)
{
	unsigned long Combined_Channel_ID;

	//TX
	do {
		InstanceID++;
		NCSI_Request.IID = InstanceID;
		NCSI_Request.Command = DESELECT_PACKAGE;
		Combined_Channel_ID = (Package_ID << 5) + 0x1F; //Internal Channel ID = 0x1F, 0x1F means all channel
		NCSI_Request.Channel_ID = Combined_Channel_ID;
		NCSI_Request.Payload_Length = 0;
		memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
		copy_data (NCSI_Request.Payload_Length);
		aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
		//RX
		NCSI_Rx();
		if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (DESELECT_PACKAGE | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
			printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
			Retry++;
			InstanceID--;
		}
		else {
			Retry = 0;
		}
	} while ((Retry != 0) && (Retry <= RETRY_COUNT));
	Retry = 0;
}

int Select_Package (struct eth_device* dev, int Package_ID)
{
	unsigned long Combined_Channel_ID, Found = 0;

	//TX
	do {
		InstanceID++;
		NCSI_Request.IID = InstanceID;
		NCSI_Request.Command = SELECT_PACKAGE;
		Combined_Channel_ID = (Package_ID << 5) + 0x1F; //Internal Channel ID = 0x1F
		NCSI_Request.Channel_ID = Combined_Channel_ID;
		NCSI_Request.Payload_Length = (4 << 8);
		memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
		NCSI_Request.Payload_Length = 4;
		memset ((void *)Payload_Data, 0, 4);
		Payload_Data[3] = 1; //Arbitration Disable
		copy_data (NCSI_Request.Payload_Length);
		aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
		//RX
		NCSI_Rx();
		if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (SELECT_PACKAGE | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
			printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
			Retry++;
			Found = 0;
			InstanceID--;
		}
		else {
			Retry = 0;
			Found = 1;
		}
	} while ((Retry != 0) && (Retry <= RETRY_COUNT));
	Retry = 0;

	return Found;
}

void DeSelect_Active_Package (struct eth_device* dev)
{
	unsigned long Combined_Channel_ID;
	//TX
	do {
		InstanceID++;
		NCSI_Request.IID = InstanceID;
		NCSI_Request.Command = DESELECT_PACKAGE;
		Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + 0x1F; //Internal Channel ID = 0x1F, 0x1F means all channel
		NCSI_Request.Channel_ID = Combined_Channel_ID;
		NCSI_Request.Payload_Length = 0;
		memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
		copy_data (NCSI_Request.Payload_Length);
		aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
		//RX
		NCSI_Rx();
		if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (DESELECT_PACKAGE | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
			printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
			Retry++;
			InstanceID--;
		}
		else {
			Retry = 0;
		}
	} while ((Retry != 0) && (Retry <= RETRY_COUNT));
	Retry = 0;
}

int Select_Active_Package (struct eth_device* dev)
{
	unsigned long Combined_Channel_ID, Found = 0;
	//TX
	do {
		InstanceID++;
		NCSI_Request.IID = InstanceID;
		NCSI_Request.Command = SELECT_PACKAGE;
		Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + 0x1F; //Internal Channel ID = 0x1F
		NCSI_Request.Channel_ID = Combined_Channel_ID;
		NCSI_Request.Payload_Length = (4 << 8);
		memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
		NCSI_Request.Payload_Length = 4;
		memset ((void *)Payload_Data, 0, 4);
		Payload_Data[3] = 1; //Arbitration Disable
		copy_data (NCSI_Request.Payload_Length);
		aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
		//RX
		NCSI_Rx();
		if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (SELECT_PACKAGE | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
			printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
			Retry++;
			Found = 0;
			InstanceID--;
		}
		else {
			Retry = 0;
			Found = 1;
		}
	} while ((Retry != 0) && (Retry <= RETRY_COUNT));
	Retry = 0;

	return Found;
}

int Clear_Initial_State (struct eth_device* dev, int Channel_ID)
{
	unsigned long Combined_Channel_ID, Found = 0;
	//TX
	do {
		InstanceID++;
		NCSI_Request.IID = InstanceID;
		NCSI_Request.Command = CLEAR_INITIAL_STATE;
		Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + Channel_ID; //Internal Channel ID = 0
		NCSI_Request.Channel_ID = Combined_Channel_ID;
		NCSI_Request.Payload_Length = 0;
		memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
		copy_data (NCSI_Request.Payload_Length);
		aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
		//RX
		NCSI_Rx();
		if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (CLEAR_INITIAL_STATE | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
			printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
			Retry++;
			Found = 0;
			InstanceID--;
		}
		else {
			Retry = 0;
			Found = 1;
		}
	} while ((Retry != 0) && (Retry <= RETRY_COUNT));
	Retry = 0;

	return Found;
}

void Get_Version_ID (struct eth_device* dev)
{
	unsigned long Combined_Channel_ID;
	//TX
	do {
		InstanceID++;
		NCSI_Request.IID = InstanceID;
		NCSI_Request.Command = GET_VERSION_ID;
		Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
		NCSI_Request.Channel_ID = Combined_Channel_ID;
		NCSI_Request.Payload_Length = 0;
		memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
		copy_data (NCSI_Request.Payload_Length);
		aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
		//RX
		NCSI_Rx();
		if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (GET_VERSION_ID | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
			printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
			Retry++;
			InstanceID--;
		}
		else {
			Retry = 0;
		}
	} while ((Retry != 0) && (Retry <= RETRY_COUNT));
	Retry = 0;
}

void Get_Capabilities (struct eth_device* dev)
{
	unsigned long Combined_Channel_ID;
	//TX
	do {
		InstanceID++;
		NCSI_Request.IID = InstanceID;
		NCSI_Request.Command = GET_CAPABILITIES;
		Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
		NCSI_Request.Channel_ID = Combined_Channel_ID;
		NCSI_Request.Payload_Length = 0;
		memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
		copy_data (NCSI_Request.Payload_Length);
		aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
		//RX
		NCSI_Rx();
		if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (GET_CAPABILITIES | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
			printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
			Retry++;
			InstanceID--;
		}
		else {
			Retry = 0;
			NCSI_Cap.Capabilities_Flags = NCSI_Respond.Payload_Data[0];
			NCSI_Cap.Broadcast_Packet_Filter_Capabilities = NCSI_Respond.Payload_Data[1];
			NCSI_Cap.Multicast_Packet_Filter_Capabilities = NCSI_Respond.Payload_Data[2];
			NCSI_Cap.Buffering_Capabilities = NCSI_Respond.Payload_Data[3];
			NCSI_Cap.AEN_Control_Support = NCSI_Respond.Payload_Data[4];
		}
	} while ((Retry != 0) && (Retry <= RETRY_COUNT));
	Retry = 0;
}

void Enable_Set_MAC_Address (struct eth_device* dev)
{
	unsigned long Combined_Channel_ID, i;
	//TX
	do {
		InstanceID++;
		NCSI_Request.IID = InstanceID;
		NCSI_Request.Command = SET_MAC_ADDRESS;
		Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
		NCSI_Request.Channel_ID = Combined_Channel_ID;
		NCSI_Request.Payload_Length = (8 << 8);
		memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
		NCSI_Request.Payload_Length = 8;
		for (i = 0; i < 6; i++) {
			Payload_Data[i] = NCSI_Request.SA[i];
		}
		Payload_Data[6] = 1; //MAC Address Num = 1 --> address filter 1, fixed in sample code
		Payload_Data[7] = UNICAST + 0 + ENABLE_MAC_ADDRESS_FILTER; //AT + Reserved + E
		copy_data (NCSI_Request.Payload_Length);
		aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
		//RX
		NCSI_Rx();
		if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (SET_MAC_ADDRESS | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
			printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
			Retry++;
			InstanceID--;
		}
	} while ((Retry != 0) && (Retry <= RETRY_COUNT));
	Retry = 0;
}

void Enable_Broadcast_Filter (struct eth_device* dev)
{
	unsigned long Combined_Channel_ID;
	//TX
	do {
		InstanceID++;
		NCSI_Request.IID = InstanceID;
		NCSI_Request.Command = ENABLE_BROADCAST_FILTERING;
		Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
		NCSI_Request.Channel_ID = Combined_Channel_ID;
		NCSI_Request.Payload_Length = (4 << 8);
		memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
		NCSI_Request.Payload_Length = 4;
		memset ((void *)Payload_Data, 0, 4);
		Payload_Data[3] = 0xF; //ARP, DHCP, NetBIOS
		copy_data (NCSI_Request.Payload_Length);
		aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
		//RX
		NCSI_Rx();
		if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (ENABLE_BROADCAST_FILTERING | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
			printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
			Retry++;
			InstanceID--;
		}
		else {
			Retry = 0;
		}
	} while ((Retry != 0) && (Retry <= RETRY_COUNT));
	Retry = 0;
}

void Enable_AEN (struct eth_device* dev)
{
	unsigned long Combined_Channel_ID;
	//TX
	do {
		InstanceID++;
		NCSI_Request.IID = InstanceID;
		NCSI_Request.Command = AEN_ENABLE;
		Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
		NCSI_Request.Channel_ID = Combined_Channel_ID;
		NCSI_Request.Payload_Length = (8 << 8);
		memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
		NCSI_Request.Payload_Length = 8;
		memset ((void *)Payload_Data, 0, 8);
		Payload_Data[3] = 0x00; //MC ID
		Payload_Data[7] = 0x01; //Link Status only
		copy_data (NCSI_Request.Payload_Length);
		aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
		//RX
		NCSI_Rx();
		if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (AEN_ENABLE | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
			printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
			Retry++;
			InstanceID--;
		}
		else {
			Retry = 0;
		}
	} while ((Retry != 0) && (Retry <= RETRY_COUNT));
	Retry = 0;
}

void Enable_Network_TX (struct eth_device* dev)
{
	unsigned long Combined_Channel_ID;
	//TX
	do {
		InstanceID++;
		NCSI_Request.IID = InstanceID;
		NCSI_Request.Command = ENABLE_CHANNEL_NETWORK_TX;
		Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
		NCSI_Request.Channel_ID = Combined_Channel_ID;
		NCSI_Request.Payload_Length = 0;
		memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
		copy_data (NCSI_Request.Payload_Length);
		aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
		//RX
		NCSI_Rx();
		if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (ENABLE_CHANNEL_NETWORK_TX | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
			printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
			Retry++;
			InstanceID--;
		}
		else {
			Retry = 0;
		}
	} while ((Retry != 0) && (Retry <= RETRY_COUNT));
	Retry = 0;
}

void Disable_Network_TX (struct eth_device* dev)
{
	unsigned long Combined_Channel_ID;
	//TX
	do {
		InstanceID++;
		NCSI_Request.IID = InstanceID;
		NCSI_Request.Command = DISABLE_CHANNEL_NETWORK_TX;
		Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
		NCSI_Request.Channel_ID = Combined_Channel_ID;
		NCSI_Request.Payload_Length = 0;
		memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
		copy_data (NCSI_Request.Payload_Length);
		aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
		//RX
		NCSI_Rx();
		if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (DISABLE_CHANNEL_NETWORK_TX | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
			printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
			Retry++;
			InstanceID--;
		}
		else {
			Retry = 0;
		}
	} while ((Retry != 0) && (Retry <= RETRY_COUNT));
	Retry = 0;
}

void Enable_Channel (struct eth_device* dev)
{
	unsigned long Combined_Channel_ID;
	//TX
	do {
		InstanceID++;
		NCSI_Request.IID = InstanceID;
		NCSI_Request.Command = ENABLE_CHANNEL;
		Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
		NCSI_Request.Channel_ID = Combined_Channel_ID;
		NCSI_Request.Payload_Length = 0;
		memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
		copy_data (NCSI_Request.Payload_Length);
		aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
		//RX
		NCSI_Rx();
		if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (ENABLE_CHANNEL | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
			printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
			Retry++;
			InstanceID--;
		}
		else {
			Retry = 0;
		}
	} while ((Retry != 0) && (Retry <= RETRY_COUNT));
	Retry = 0;
}

void Disable_Channel (struct eth_device* dev)
{
	unsigned long Combined_Channel_ID;
	//TX
	do {
		InstanceID++;
		NCSI_Request.IID = InstanceID;
		NCSI_Request.Command = DISABLE_CHANNEL;
		Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
		NCSI_Request.Channel_ID = Combined_Channel_ID;
		NCSI_Request.Payload_Length = (4 << 8);
		memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
		NCSI_Request.Payload_Length = 4;
		memset ((void *)Payload_Data, 0, 4);
		Payload_Data[3] = 0x1; //ALD
		copy_data (NCSI_Request.Payload_Length);
		aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
		//RX
		NCSI_Rx();
		if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (DISABLE_CHANNEL | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
			printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
			Retry++;
			InstanceID--;
		}
		else {
			Retry = 0;
		}
	} while ((Retry != 0) && (Retry <= RETRY_COUNT));
	Retry = 0;
}

int Get_Link_Status (struct eth_device* dev)
{
	unsigned long Combined_Channel_ID;
	//TX
	do {
		InstanceID++;
		NCSI_Request.IID = InstanceID;
		NCSI_Request.Command = GET_LINK_STATUS;
		Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
		NCSI_Request.Channel_ID = Combined_Channel_ID;
		NCSI_Request.Payload_Length = 0;
		memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
		copy_data (NCSI_Request.Payload_Length);
		aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
		//RX
		NCSI_Rx();
		if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (GET_LINK_STATUS | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
			printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
			Retry++;
			InstanceID--;
		}
		else {
			Retry = 0;
		}
	} while ((Retry != 0) && (Retry <= RETRY_COUNT));
	Retry = 0;
	if (NCSI_Respond.Payload_Data[3] & 0x40) {
		return (NCSI_Respond.Payload_Data[3] & 0x01); //Link Up or Not
	}
	else {
		return 0; //Auto Negotiate did not finish
	}
}

void Set_Link (struct eth_device* dev)
{
	unsigned long Combined_Channel_ID;
	//TX
	do {
		InstanceID++;
		NCSI_Request.IID = InstanceID;
		NCSI_Request.Command = SET_LINK;
		Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
		NCSI_Request.Channel_ID = Combined_Channel_ID;
		NCSI_Request.Payload_Length = (8 << 8);
		memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
		NCSI_Request.Payload_Length = 8;
		memset ((void *)Payload_Data, 0, 8);
		Payload_Data[2] = 0x02; //full duplex
		Payload_Data[3] = 0x04; //100M, auto-disable
		copy_data (NCSI_Request.Payload_Length);
		aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
		//RX
		NCSI_Rx();
		if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (SET_LINK | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
			printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
			Retry++;
			InstanceID--;
		}
		else {
			Retry = 0;
		}
	} while ((Retry != 0) && (Retry <= RETRY_COUNT));
	Retry = 0;
}

static void aspeednic_probe_phy(struct eth_device *dev)
{
	u8 phy_addr;
	u16 phy_id;

	/* assume it as 0 */
	g_phy_addr = 0;

	/* Check if the PHY is up to snuff..., max phy addr is 0x1f */
	for (phy_addr = 0; phy_addr <= 0x1f; phy_addr++) {
		phy_id = phy_read_register(dev, MII_PHYSID1, phy_addr);
		/*
		 * When it is unable to found PHY,
		 * the interface usually return 0xffff or 0x0000
		 */
		if (phy_id != 0xffff && phy_id != 0x0) {
			g_phy_addr = phy_addr;
			break;
		}
	}
	printf("%s: PHY at 0x%02x\n", dev->name, phy_addr);
}

static int aspeednic_init(struct eth_device* dev, bd_t* bis)
{
	unsigned long i, Package_Found = 0, Channel_Found = 0, Re_Send = 0, Link_Status;

	RESET_DE4X5(dev);

	aspeednic_probe_phy(dev);

	aspeednic_write_hwaddr(dev);

	for (i = 0; i < NUM_RX_DESC; i++) {
		rx_ring[i].status = cpu_to_le32(RXPKT_RDY);
		rx_ring[i].buf = (u32)(&rx_buffer[i]);
		rx_ring[i].reserved = 0;
	}

	for (i=0; i < NUM_TX_DESC; i++) {
		tx_ring[i].status = 0;
		tx_ring[i].des1 = 0;
		tx_ring[i].buf = (u32)(&tx_buffer[i]);
		tx_ring[i].reserved = 0;
	}

	rxRingSize = NUM_RX_DESC;
	txRingSize = NUM_TX_DESC;

	rx_ring[rxRingSize - 1].status |= cpu_to_le32(EDORR);
	tx_ring[txRingSize - 1].status |= cpu_to_le32(EDOTR);

	OUTL(dev, ((u32) &tx_ring), TXR_BADR_REG);
	OUTL(dev, ((u32) &rx_ring), RXR_BADR_REG);
	OUTL(dev, RX_BUFF_SZ, RBSR_REG);

	set_mac_control_register(dev);
	START_MAC(dev);

	tx_new = 0;
	rx_new = 0;

	if (!(CONFIG_ASPEED_MAC_PHY_SETTING >= 1))
		return 1;

	//NCSI Start
	//DeSelect Package/ Select Package
	for (i = 0; i < 4; i++) {
		DeSelect_Package (dev, i);
		Package_Found = Select_Package (dev, i);
		if (Package_Found == 1) {
			//AST2100/AST2050/AST1100 supports 1 package only in current firmware version
			NCSI_Cap.Package_ID = i;
			//        Package_Found = 0;
			break;
		}
	}
	if (!(Package_Found != 0))
		return 1;

	// Initial State
	// Suppose 2 channels in current version, You could modify it to 0x1F
	// to support 31 channels
	for (i = 0; i < 2; i++) {
		Channel_Found = Clear_Initial_State(dev, i);
		if (Channel_Found != 1)
			continue;

		NCSI_Cap.Channel_ID = i;
		printf ("Found NCSI Network Controller at (%d, %d)\n", NCSI_Cap.Package_ID, NCSI_Cap.Channel_ID);
		//Get Version and Capabilities
		Get_Version_ID(dev);
		Get_Capabilities(dev);
		Select_Active_Package(dev);
		//Configuration
		Enable_Set_MAC_Address(dev);
		Enable_Broadcast_Filter(dev);
		//Enable TX
		Enable_Network_TX(dev);
		//Enable Channel
		Enable_Channel(dev);
		//Get Link Status
Re_Get_Link_Status:
		Link_Status = Get_Link_Status(dev);
		if (Link_Status == LINK_UP) {
			printf ("Using NCSI Network Controller (%d, %d)\n", NCSI_Cap.Package_ID, NCSI_Cap.Channel_ID);
			break;
		}
		else if ((Link_Status == LINK_DOWN) && (Re_Send < 2)) {
			Re_Send++;
			goto Re_Get_Link_Status;
		}
		//Disable TX
		Disable_Network_TX(dev);
		//Disable Channel
		//          Disable_Channel(dev);
		Re_Send = 0;
		Channel_Found = 0;
	}
	return 1;
}

static int aspeednic_send(struct eth_device* dev, void *packet, int length)
{
	int   status = -1, oldlength = 0, fail = 0;
	int   i;

	if (length <= 0) {
		printf("%s: bad packet size: %d\n", dev->name, length);
		goto Done;
	}


	for(i = 0; (tx_ring[tx_new].status & cpu_to_le32(TXDMA_OWN)) == 0x80000000; i++) {
		if (i >= TOUT_LOOP) {
			printf("%s: tx error buffer not ready\n", dev->name);
			fail = 1;
			goto Done;
		}
	}


	if (length < 60) {
		oldlength = length;
		//            memset ((void *)cpu_to_le32((u32) (packet + length)), 0, 60 - length);
		length = 60;
	}
	tx_ring[tx_new].buf    = cpu_to_le32(((u32) packet));
	tx_ring[tx_new].status   &= (~(0x3FFF));
	tx_ring[tx_new].status   |= cpu_to_le32(LTS | FTS | length);
	tx_ring[tx_new].status |= cpu_to_le32(TXDMA_OWN);

	OUTL(dev, POLL_DEMAND, TXPD_REG);

	for (i = 0; (tx_ring[tx_new].status & cpu_to_le32(TXDMA_OWN)) == 0x80000000; i++)
	{
		if (i >= TOUT_LOOP)
		{
			printf(".%s: tx buffer not ready\n", dev->name);
			fail = 1;
			goto Done;
		}
	}

	if (fail != 1) {
		status = oldlength;
	}

Done:
	tx_new = (tx_new+1) % NUM_TX_DESC;

	return status;
}

static int aspeednic_recv(struct eth_device* dev)
{
	s32   status;
	int   length    = 0;

	for ( ; ; )
	{
		status = (s32)le32_to_cpu(rx_ring[rx_new].status);

		if ((status & RXPKT_STATUS) == 0) {
			break;
		}

		if (status & LRS) {
			/* Valid frame status.
			*/
			if (status & (RX_ERR | CRC_ERR | FTL | RUNT | RX_ODD_NB)) {

				/* There was an error.
				*/
				printf("RX error status = 0x%08X\n", status);
			} else {
				/* A valid frame received.
				*/
				length = (le32_to_cpu(rx_ring[rx_new].status) & 0x3FFF);
				debug("%s(): RX buffer %d, %x received\n",
						__func__, rx_new, length);


				/* Pass the packet up to the protocol
				 * layers.
				 */
				net_process_received_packet(rx_buffer[rx_new], length - 4);
			}

			/* Change buffer ownership for this frame, back
			 * to the adapter.
			 */
			rx_ring[rx_new].status &= cpu_to_le32(0x7FFFFFFF);

			/*
			 * Ask the hardware for any other packets now that we
			 * have a known spare slot
			 */
			OUTL(dev, POLL_DEMAND, RXPD_REG);
			//      rx_ring[rx_new].status = cpu_to_le32(RXPKT_RDY);
		}

		/* Update entry information.
		*/
		rx_new = (rx_new + 1) % rxRingSize;
	}

	/*
	 * Ask the hardware for more packets so that they'll be DMAed by the
	 * time we return to this loop
	 */
	OUTL(dev, POLL_DEMAND, RXPD_REG);

	return length;
}

static void aspeednic_halt(struct eth_device* dev)
{
	STOP_MAC(dev);
}

static int aspeednic_write_hwaddr(struct eth_device* dev)
{
	OUTL(dev, ((dev->enetaddr[2] << 24) | (dev->enetaddr[3] << 16)
				| (dev->enetaddr[4] << 8) | dev->enetaddr[5]), MAC_LADR_REG);
	OUTL(dev, ((dev->enetaddr[0] << 8) | dev->enetaddr[1]), MAC_MADR_REG);
	if (CONFIG_ASPEED_MAC_PHY_SETTING >= 1) {
		memcpy(NCSI_Request.SA, dev->enetaddr, 6);
	}

	return 0;
}

static u16 phy_read_register (struct eth_device* dev, u8 PHY_Register, u8 PHY_Address)
{
	u32 Data, Status = 0, Loop_Count = 0, PHY_Ready = 1;
	u16 Return_Data;

	//20us * 100 = 2ms > (1 / 2.5Mhz) * 0x34
	OUTL(dev, (PHY_Register << 21) + (PHY_Address << 16) + MIIRD + MDC_CYCTHR, PHYCR_REG);
	do {
		udelay(20);
		Status = (INL (dev, PHYCR_REG) & MIIRD);
		Loop_Count++;
		if (Loop_Count >= 100) {
			PHY_Ready = 0;
			break;
		}
	} while (Status == MIIRD);

	if (PHY_Ready == 0) {
		return 0;
	}
	Data = INL (dev, PHYDATA_REG);
	Return_Data = (Data >> 16);

	return Return_Data;
}


static void phy_write_register (struct eth_device* dev, u8 PHY_Register, u8 PHY_Address, u16 PHY_Data)
{
	u32 Status = 0, Loop_Count = 0;

	//20us * 100 = 2ms > (1 / 2.5Mhz) * 0x34
	OUTL(dev, PHY_Data, PHYDATA_REG);
	OUTL(dev, (PHY_Register << 21) + (PHY_Address << 16) + MIIWR + MDC_CYCTHR, PHYCR_REG);
	do {
		udelay(20);
		Status = (INL (dev, PHYCR_REG) & MIIWR);
		Loop_Count++;
		if (Loop_Count >= 100) {
			break;
		}
	} while (Status == MIIWR);
}

#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)

static int faraday_mdio_read(
		const char *devname, uint8_t addr, uint8_t reg, uint16_t *value)
{
	int ret = 0;
	struct eth_device *dev;

	dev = eth_get_dev_by_name(devname);
	if (dev == NULL) {
		printf("%s: no such device\n", devname);
		ret = -1;
	} else {
		*value = phy_read_register(dev, reg, addr);
	}

	return ret;
}

static int faraday_mdio_write(
		const char *devname, uint8_t addr, uint8_t reg, uint16_t value)
{
	int ret = 0;
	struct eth_device *dev;

	dev = eth_get_dev_by_name(devname);
	if (dev == NULL) {
		printf("%s: no such device\n", devname);
		ret = -1;
	} else {
		phy_write_register(dev, reg, addr, value);
	}

	return ret;
}

#endif    /* #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) */

static void set_mac_control_register (struct eth_device* dev)
{
	unsigned long MAC_CR_Register = 0;
	unsigned int   Loop_Count = 0, PHY_Ready = 1, Chip_ID;
	u16    PHY_Status, PHY_Speed, PHY_Duplex, Resolved_Status = 0, Advertise, Link_Partner;

	if (CONFIG_ASPEED_MAC_PHY_SETTING >= 1) {
		printf("%s %d\n", __func__, __LINE__);
		MAC_CR_Register = SPEED_100M_MODE_bit | RX_BROADPKT_bit |
			FULLDUP_bit | RXMAC_EN_bit | RXDMA_EN_bit |
			TXMAC_EN_bit | TXDMA_EN_bit | CRC_APD_bit;
	}
	else {
		printf("%s %d\n", __func__, __LINE__);
		MAC_CR_Register = SPEED_100M_MODE_bit | FULLDUP_bit |
			RXMAC_EN_bit | RXDMA_EN_bit | TXMAC_EN_bit |
			TXDMA_EN_bit | CRC_APD_bit;
	}

	if (CONFIG_ASPEED_MAC_PHY_SETTING != 2) {
		Chip_ID = ((phy_read_register (dev, 0x02, g_phy_addr)) << 16);
		Chip_ID |= (phy_read_register (dev, 0x03, g_phy_addr) & 0xffff);
		if (((Chip_ID & PHYID_VENDOR_MASK) == PHYID_VENDOR_BROADCOM) ||
				((Chip_ID & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8201EL)) {
			Advertise = phy_read_register (dev, 0x04, g_phy_addr);
			Link_Partner = phy_read_register (dev, 0x05, g_phy_addr);
			Advertise = (Advertise & PHY_SPEED_DUPLEX_MASK);
			Link_Partner = (Link_Partner & PHY_SPEED_DUPLEX_MASK);
			if ((Advertise & Link_Partner) & PHY_100M_DUPLEX) {
				MAC_CR_Register |= SPEED_100M_MODE_bit;
				MAC_CR_Register |= FULLDUP_bit;
			}
			else if ((Advertise & Link_Partner) & PHY_100M_HALF) {
				MAC_CR_Register |= SPEED_100M_MODE_bit;
				MAC_CR_Register &= ~FULLDUP_bit;
			}
			else if ((Advertise & Link_Partner) & PHY_10M_DUPLEX) {
				MAC_CR_Register &= ~SPEED_100M_MODE_bit;
				MAC_CR_Register |= FULLDUP_bit;
			}
			else if ((Advertise & Link_Partner) & PHY_10M_HALF) {
				MAC_CR_Register &= ~SPEED_100M_MODE_bit;
				MAC_CR_Register &= ~FULLDUP_bit;
			}
		}
		else if (((Chip_ID & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) ||
				((Chip_ID & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211)) {
			//Max waiting time = (20 + 2)ms * 250(PHY_LOOP) = 5.5s
			do {
				udelay (20000);
				Resolved_Status = (phy_read_register (dev, 0x11, g_phy_addr)
						& RESOLVED_BIT);
				Loop_Count++;
				if (Loop_Count >= PHY_LOOP) {
					PHY_Ready = 0;
					printf ("PHY NOT READY ");
					break;
				}
			} while (Resolved_Status != RESOLVED_BIT);

			if (PHY_Ready == 1) {
				PHY_Status = phy_read_register (dev, 0x11, g_phy_addr);
				PHY_Speed = (PHY_Status & PHY_SPEED_MASK) >> 14;
				PHY_Duplex = (PHY_Status & PHY_DUPLEX_MASK) >> 13;

				if (PHY_Speed == SPEED_1000M) {
					MAC_CR_Register |= GMAC_MODE_bit;
				}
				else {
					MAC_CR_Register &= ~GMAC_MODE_bit;
					if (PHY_Speed == SPEED_10M) {
						MAC_CR_Register &= ~SPEED_100M_MODE_bit;
					}
				}
				if (PHY_Duplex == DUPLEX_HALF) {
					MAC_CR_Register &= ~FULLDUP_bit;
				}
			}
			//LED Control
			//              if (Chip_ID == 0x1C) {
			//                  PHY_Status = phy_read_register (dev, 0x18, g_phy_addr);
			//                phy_write_register (dev, 0x18, g_phy_addr, (PHY_Status | 0x09));
			//              }
			//LED Control D[0], D[6]
			//              if (Chip_ID == 0x141) {
			//                  PHY_Status = phy_read_register (dev, 0x18, g_phy_addr);
			//                phy_write_register (dev, 0x18, g_phy_addr, ((PHY_Status & ~(0x41)) | 0x01));
			//              }
		}
		else if (Chip_ID == PHYID_BCM54612E || Chip_ID == PHYID_BCM54616S) {
			// Disable GTXCLK Clock Delay Enable
			phy_write_register( dev, 0x1C, g_phy_addr, 0x8C00);
			// Disable RGMII RXD to RXC Skew
			phy_write_register( dev, 0x18, g_phy_addr, 0xF0E7);
			// First Switch shadow register selector
			phy_write_register(dev, 0x1C, g_phy_addr, 0x2000);
			PHY_Status = phy_read_register(dev, 0x1C, g_phy_addr);
			PHY_Duplex = (PHY_Status & 0x0080);
			switch (PHY_Status & 0x0018) {
				case 0x0000:
					PHY_Speed = SPEED_1000M;
					break;
				case 0x0008:
					PHY_Speed = SPEED_100M;
					break;
				case 0x0010:
					PHY_Speed = SPEED_10M;
					break;
				default:
					PHY_Speed = SPEED_100M;
					break;
			}
			if (PHY_Speed == SPEED_1000M) {
				MAC_CR_Register |= GMAC_MODE_bit;
			} else {
				MAC_CR_Register &= ~GMAC_MODE_bit;
				if (PHY_Speed == SPEED_100M) {
					MAC_CR_Register |= SPEED_100M_MODE_bit;
				} else {
					MAC_CR_Register &= ~SPEED_100M_MODE_bit;
				}
			}
			if (PHY_Duplex) {
				MAC_CR_Register |= FULLDUP_bit;
			} else {
				MAC_CR_Register &= ~FULLDUP_bit;
			}
		} else {
			printf("Unknow Chip_ID %x\n",Chip_ID);
		}
	}
	OUTL(dev, MAC_CR_Register, MACCR_REG);
}

//#endif  /* CFG_CMD_NET && CONFIG_NET_MULTI && CONFIG_ASPEEDMAC */
OpenPOWER on IntegriCloud