18e585f02STsiChung Liew /* 28e585f02STsiChung Liew * (C) Copyright 2000-2004 38e585f02STsiChung Liew * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 48e585f02STsiChung Liew * 5f2208fbcSTsiChungLiew * (C) Copyright 2007 Freescale Semiconductor, Inc. 68e585f02STsiChung Liew * TsiChung Liew (Tsi-Chung.Liew@freescale.com) 78e585f02STsiChung Liew * 88e585f02STsiChung Liew * See file CREDITS for list of people who contributed to this 98e585f02STsiChung Liew * project. 108e585f02STsiChung Liew * 118e585f02STsiChung Liew * This program is free software; you can redistribute it and/or 128e585f02STsiChung Liew * modify it under the terms of the GNU General Public License as 138e585f02STsiChung Liew * published by the Free Software Foundation; either version 2 of 148e585f02STsiChung Liew * the License, or (at your option) any later version. 158e585f02STsiChung Liew * 168e585f02STsiChung Liew * This program is distributed in the hope that it will be useful, 178e585f02STsiChung Liew * but WITHOUT ANY WARRANTY; without even the implied warranty of 188e585f02STsiChung Liew * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 198e585f02STsiChung Liew * GNU General Public License for more details. 208e585f02STsiChung Liew * 218e585f02STsiChung Liew * You should have received a copy of the GNU General Public License 228e585f02STsiChung Liew * along with this program; if not, write to the Free Software 238e585f02STsiChung Liew * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 248e585f02STsiChung Liew * MA 02111-1307 USA 258e585f02STsiChung Liew */ 268e585f02STsiChung Liew 278e585f02STsiChung Liew #include <common.h> 288e585f02STsiChung Liew #include <malloc.h> 298e585f02STsiChung Liew 308e585f02STsiChung Liew #include <command.h> 318e585f02STsiChung Liew #include <net.h> 3289973f8aSBen Warren #include <netdev.h> 338e585f02STsiChung Liew #include <miiphy.h> 348e585f02STsiChung Liew 3554bdcc9fSTsiChung Liew #include <asm/fec.h> 3654bdcc9fSTsiChung Liew #include <asm/immap.h> 3754bdcc9fSTsiChung Liew 388e585f02STsiChung Liew #undef ET_DEBUG 398e585f02STsiChung Liew #undef MII_DEBUG 408e585f02STsiChung Liew 418e585f02STsiChung Liew /* Ethernet Transmit and Receive Buffers */ 428e585f02STsiChung Liew #define DBUF_LENGTH 1520 438e585f02STsiChung Liew #define TX_BUF_CNT 2 448e585f02STsiChung Liew #define PKT_MAXBUF_SIZE 1518 458e585f02STsiChung Liew #define PKT_MINBUF_SIZE 64 468e585f02STsiChung Liew #define PKT_MAXBLR_SIZE 1520 478e585f02STsiChung Liew #define LAST_PKTBUFSRX PKTBUFSRX - 1 488e585f02STsiChung Liew #define BD_ENET_RX_W_E (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY) 498e585f02STsiChung Liew #define BD_ENET_TX_RDY_LST (BD_ENET_TX_READY | BD_ENET_TX_LAST) 508e585f02STsiChung Liew 518e585f02STsiChung Liew DECLARE_GLOBAL_DATA_PTR; 528e585f02STsiChung Liew 538e585f02STsiChung Liew struct fec_info_s fec_info[] = { 546d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FEC0_IOBASE 558e585f02STsiChung Liew { 568e585f02STsiChung Liew 0, /* index */ 576d0f6bcfSJean-Christophe PLAGNIOL-VILLARD CONFIG_SYS_FEC0_IOBASE, /* io base */ 586d0f6bcfSJean-Christophe PLAGNIOL-VILLARD CONFIG_SYS_FEC0_PINMUX, /* gpio pin muxing */ 596d0f6bcfSJean-Christophe PLAGNIOL-VILLARD CONFIG_SYS_FEC0_MIIBASE, /* mii base */ 608e585f02STsiChung Liew -1, /* phy_addr */ 618e585f02STsiChung Liew 0, /* duplex and speed */ 628e585f02STsiChung Liew 0, /* phy name */ 638e585f02STsiChung Liew 0, /* phyname init */ 648e585f02STsiChung Liew 0, /* RX BD */ 658e585f02STsiChung Liew 0, /* TX BD */ 668e585f02STsiChung Liew 0, /* rx Index */ 678e585f02STsiChung Liew 0, /* tx Index */ 688e585f02STsiChung Liew 0, /* tx buffer */ 698e585f02STsiChung Liew 0, /* initialized flag */ 701803f7f9STsiChung Liew (struct fec_info_s *)-1, 718e585f02STsiChung Liew }, 728e585f02STsiChung Liew #endif 736d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FEC1_IOBASE 748e585f02STsiChung Liew { 758e585f02STsiChung Liew 1, /* index */ 766d0f6bcfSJean-Christophe PLAGNIOL-VILLARD CONFIG_SYS_FEC1_IOBASE, /* io base */ 776d0f6bcfSJean-Christophe PLAGNIOL-VILLARD CONFIG_SYS_FEC1_PINMUX, /* gpio pin muxing */ 786d0f6bcfSJean-Christophe PLAGNIOL-VILLARD CONFIG_SYS_FEC1_MIIBASE, /* mii base */ 798e585f02STsiChung Liew -1, /* phy_addr */ 808e585f02STsiChung Liew 0, /* duplex and speed */ 818e585f02STsiChung Liew 0, /* phy name */ 828e585f02STsiChung Liew 0, /* phy name init */ 836d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FEC_BUF_USE_SRAM 841803f7f9STsiChung Liew (cbd_t *)DBUF_LENGTH, /* RX BD */ 851803f7f9STsiChung Liew #else 868e585f02STsiChung Liew 0, /* RX BD */ 871803f7f9STsiChung Liew #endif 888e585f02STsiChung Liew 0, /* TX BD */ 898e585f02STsiChung Liew 0, /* rx Index */ 908e585f02STsiChung Liew 0, /* tx Index */ 918e585f02STsiChung Liew 0, /* tx buffer */ 928e585f02STsiChung Liew 0, /* initialized flag */ 931803f7f9STsiChung Liew (struct fec_info_s *)-1, 948e585f02STsiChung Liew } 958e585f02STsiChung Liew #endif 968e585f02STsiChung Liew }; 978e585f02STsiChung Liew 988e585f02STsiChung Liew int fec_send(struct eth_device *dev, volatile void *packet, int length); 998e585f02STsiChung Liew int fec_recv(struct eth_device *dev); 1008e585f02STsiChung Liew int fec_init(struct eth_device *dev, bd_t * bd); 1018e585f02STsiChung Liew void fec_halt(struct eth_device *dev); 1028e585f02STsiChung Liew void fec_reset(struct eth_device *dev); 1038e585f02STsiChung Liew 1048e585f02STsiChung Liew void setFecDuplexSpeed(volatile fec_t * fecp, bd_t * bd, int dup_spd) 1058e585f02STsiChung Liew { 1068e585f02STsiChung Liew if ((dup_spd >> 16) == FULL) { 1078e585f02STsiChung Liew /* Set maximum frame length */ 1088e585f02STsiChung Liew fecp->rcr = FEC_RCR_MAX_FL(PKT_MAXBUF_SIZE) | FEC_RCR_MII_MODE | 1098e585f02STsiChung Liew FEC_RCR_PROM | 0x100; 1108e585f02STsiChung Liew fecp->tcr = FEC_TCR_FDEN; 1118e585f02STsiChung Liew } else { 1128e585f02STsiChung Liew /* Half duplex mode */ 1138e585f02STsiChung Liew fecp->rcr = FEC_RCR_MAX_FL(PKT_MAXBUF_SIZE) | 1148e585f02STsiChung Liew FEC_RCR_MII_MODE | FEC_RCR_DRT; 1158e585f02STsiChung Liew fecp->tcr &= ~FEC_TCR_FDEN; 1168e585f02STsiChung Liew } 1178e585f02STsiChung Liew 1188e585f02STsiChung Liew if ((dup_spd & 0xFFFF) == _100BASET) { 119ff36fbb2STsiChung Liew #ifdef CONFIG_MCF5445x 120ff36fbb2STsiChung Liew fecp->rcr &= ~0x200; /* disabled 10T base */ 121ff36fbb2STsiChung Liew #endif 1228e585f02STsiChung Liew #ifdef MII_DEBUG 1238e585f02STsiChung Liew printf("100Mbps\n"); 1248e585f02STsiChung Liew #endif 1258e585f02STsiChung Liew bd->bi_ethspeed = 100; 1268e585f02STsiChung Liew } else { 127ff36fbb2STsiChung Liew #ifdef CONFIG_MCF5445x 128ff36fbb2STsiChung Liew fecp->rcr |= 0x200; /* enabled 10T base */ 129ff36fbb2STsiChung Liew #endif 1308e585f02STsiChung Liew #ifdef MII_DEBUG 1318e585f02STsiChung Liew printf("10Mbps\n"); 1328e585f02STsiChung Liew #endif 1338e585f02STsiChung Liew bd->bi_ethspeed = 10; 1348e585f02STsiChung Liew } 1358e585f02STsiChung Liew } 1368e585f02STsiChung Liew 1378e585f02STsiChung Liew int fec_send(struct eth_device *dev, volatile void *packet, int length) 1388e585f02STsiChung Liew { 1398e585f02STsiChung Liew struct fec_info_s *info = dev->priv; 1408e585f02STsiChung Liew volatile fec_t *fecp = (fec_t *) (info->iobase); 1418e585f02STsiChung Liew int j, rc; 1428e585f02STsiChung Liew u16 phyStatus; 1438e585f02STsiChung Liew 1448e585f02STsiChung Liew miiphy_read(dev->name, info->phy_addr, PHY_BMSR, &phyStatus); 1458e585f02STsiChung Liew 1468e585f02STsiChung Liew /* section 16.9.23.3 1478e585f02STsiChung Liew * Wait for ready 1488e585f02STsiChung Liew */ 1498e585f02STsiChung Liew j = 0; 1508e585f02STsiChung Liew while ((info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_READY) && 1518e585f02STsiChung Liew (j < MCFFEC_TOUT_LOOP)) { 1528e585f02STsiChung Liew udelay(1); 1538e585f02STsiChung Liew j++; 1548e585f02STsiChung Liew } 1558e585f02STsiChung Liew if (j >= MCFFEC_TOUT_LOOP) { 1568e585f02STsiChung Liew printf("TX not ready\n"); 1578e585f02STsiChung Liew } 1580dca874dSTsiChung 1598e585f02STsiChung Liew info->txbd[info->txIdx].cbd_bufaddr = (uint) packet; 1608e585f02STsiChung Liew info->txbd[info->txIdx].cbd_datlen = length; 1618e585f02STsiChung Liew info->txbd[info->txIdx].cbd_sc |= BD_ENET_TX_RDY_LST; 1628e585f02STsiChung Liew 1638e585f02STsiChung Liew /* Activate transmit Buffer Descriptor polling */ 1648e585f02STsiChung Liew fecp->tdar = 0x01000000; /* Descriptor polling active */ 1658e585f02STsiChung Liew 1666d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SYS_FEC_BUF_USE_SRAM 1671803f7f9STsiChung Liew /* 1681803f7f9STsiChung Liew * FEC unable to initial transmit data packet. 169f605479dSTsi-Chung Liew * A nop will ensure the descriptor polling active completed. 1701803f7f9STsiChung Liew * CF Internal RAM has shorter cycle access than DRAM. If use 1711803f7f9STsiChung Liew * DRAM as Buffer descriptor and data, a nop is a must. 1721803f7f9STsiChung Liew * Affect only V2 and V3. 173f605479dSTsi-Chung Liew */ 174f605479dSTsi-Chung Liew __asm__ ("nop"); 1751803f7f9STsiChung Liew 176f605479dSTsi-Chung Liew #endif 177f605479dSTsi-Chung Liew 1786d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_UNIFY_CACHE 179f2208fbcSTsiChungLiew icache_invalid(); 180f2208fbcSTsiChungLiew #endif 1811803f7f9STsiChung Liew 1820dca874dSTsiChung j = 0; 1838e585f02STsiChung Liew while ((info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_READY) && 1848e585f02STsiChung Liew (j < MCFFEC_TOUT_LOOP)) { 1858e585f02STsiChung Liew udelay(1); 1868e585f02STsiChung Liew j++; 1878e585f02STsiChung Liew } 1888e585f02STsiChung Liew if (j >= MCFFEC_TOUT_LOOP) { 1898e585f02STsiChung Liew printf("TX timeout\n"); 1908e585f02STsiChung Liew } 1910dca874dSTsiChung 1928e585f02STsiChung Liew #ifdef ET_DEBUG 1938e585f02STsiChung Liew printf("%s[%d] %s: cycles: %d status: %x retry cnt: %d\n", 1948e585f02STsiChung Liew __FILE__, __LINE__, __FUNCTION__, j, 1958e585f02STsiChung Liew info->txbd[info->txIdx].cbd_sc, 1968e585f02STsiChung Liew (info->txbd[info->txIdx].cbd_sc & 0x003C) >> 2); 1978e585f02STsiChung Liew #endif 1988e585f02STsiChung Liew 1990dca874dSTsiChung /* return only status bits */ 2008e585f02STsiChung Liew rc = (info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_STATS); 2018e585f02STsiChung Liew info->txIdx = (info->txIdx + 1) % TX_BUF_CNT; 2028e585f02STsiChung Liew 2038e585f02STsiChung Liew return rc; 2048e585f02STsiChung Liew } 2058e585f02STsiChung Liew 2068e585f02STsiChung Liew int fec_recv(struct eth_device *dev) 2078e585f02STsiChung Liew { 2088e585f02STsiChung Liew struct fec_info_s *info = dev->priv; 2098e585f02STsiChung Liew volatile fec_t *fecp = (fec_t *) (info->iobase); 2108e585f02STsiChung Liew int length; 2118e585f02STsiChung Liew 2128e585f02STsiChung Liew for (;;) { 2136d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SYS_FEC_BUF_USE_SRAM 2141803f7f9STsiChung Liew #endif 2156d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_UNIFY_CACHE 2160dca874dSTsiChung icache_invalid(); 2170dca874dSTsiChung #endif 2188e585f02STsiChung Liew /* section 16.9.23.2 */ 2198e585f02STsiChung Liew if (info->rxbd[info->rxIdx].cbd_sc & BD_ENET_RX_EMPTY) { 2208e585f02STsiChung Liew length = -1; 2218e585f02STsiChung Liew break; /* nothing received - leave for() loop */ 2228e585f02STsiChung Liew } 2238e585f02STsiChung Liew 2248e585f02STsiChung Liew length = info->rxbd[info->rxIdx].cbd_datlen; 2258e585f02STsiChung Liew 2268e585f02STsiChung Liew if (info->rxbd[info->rxIdx].cbd_sc & 0x003f) { 2278e585f02STsiChung Liew printf("%s[%d] err: %x\n", 2288e585f02STsiChung Liew __FUNCTION__, __LINE__, 2298e585f02STsiChung Liew info->rxbd[info->rxIdx].cbd_sc); 2308e585f02STsiChung Liew #ifdef ET_DEBUG 2318e585f02STsiChung Liew printf("%s[%d] err: %x\n", 2328e585f02STsiChung Liew __FUNCTION__, __LINE__, 2338e585f02STsiChung Liew info->rxbd[info->rxIdx].cbd_sc); 2348e585f02STsiChung Liew #endif 2358e585f02STsiChung Liew } else { 2368e585f02STsiChung Liew 2378e585f02STsiChung Liew length -= 4; 2388e585f02STsiChung Liew /* Pass the packet up to the protocol layers. */ 2398e585f02STsiChung Liew NetReceive(NetRxPackets[info->rxIdx], length); 2408e585f02STsiChung Liew 2418e585f02STsiChung Liew fecp->eir |= FEC_EIR_RXF; 2428e585f02STsiChung Liew } 2438e585f02STsiChung Liew 2448e585f02STsiChung Liew /* Give the buffer back to the FEC. */ 2458e585f02STsiChung Liew info->rxbd[info->rxIdx].cbd_datlen = 0; 2468e585f02STsiChung Liew 2478e585f02STsiChung Liew /* wrap around buffer index when necessary */ 2488e585f02STsiChung Liew if (info->rxIdx == LAST_PKTBUFSRX) { 2498e585f02STsiChung Liew info->rxbd[PKTBUFSRX - 1].cbd_sc = BD_ENET_RX_W_E; 2508e585f02STsiChung Liew info->rxIdx = 0; 2518e585f02STsiChung Liew } else { 2528e585f02STsiChung Liew info->rxbd[info->rxIdx].cbd_sc = BD_ENET_RX_EMPTY; 2538e585f02STsiChung Liew info->rxIdx++; 2548e585f02STsiChung Liew } 2558e585f02STsiChung Liew 2568e585f02STsiChung Liew /* Try to fill Buffer Descriptors */ 2578e585f02STsiChung Liew fecp->rdar = 0x01000000; /* Descriptor polling active */ 2588e585f02STsiChung Liew } 2598e585f02STsiChung Liew 2608e585f02STsiChung Liew return length; 2618e585f02STsiChung Liew } 2628e585f02STsiChung Liew 2638e585f02STsiChung Liew #ifdef ET_DEBUG 2648e585f02STsiChung Liew void dbgFecRegs(struct eth_device *dev) 2658e585f02STsiChung Liew { 2668e585f02STsiChung Liew struct fec_info_s *info = dev->priv; 2678e585f02STsiChung Liew volatile fec_t *fecp = (fec_t *) (info->iobase); 2688e585f02STsiChung Liew 2698e585f02STsiChung Liew printf("=====\n"); 2708e585f02STsiChung Liew printf("ievent %x - %x\n", (int)&fecp->eir, fecp->eir); 2718e585f02STsiChung Liew printf("imask %x - %x\n", (int)&fecp->eimr, fecp->eimr); 2728e585f02STsiChung Liew printf("r_des_active %x - %x\n", (int)&fecp->rdar, fecp->rdar); 2738e585f02STsiChung Liew printf("x_des_active %x - %x\n", (int)&fecp->tdar, fecp->tdar); 2748e585f02STsiChung Liew printf("ecntrl %x - %x\n", (int)&fecp->ecr, fecp->ecr); 2758e585f02STsiChung Liew printf("mii_mframe %x - %x\n", (int)&fecp->mmfr, fecp->mmfr); 2768e585f02STsiChung Liew printf("mii_speed %x - %x\n", (int)&fecp->mscr, fecp->mscr); 2778e585f02STsiChung Liew printf("mii_ctrlstat %x - %x\n", (int)&fecp->mibc, fecp->mibc); 2788e585f02STsiChung Liew printf("r_cntrl %x - %x\n", (int)&fecp->rcr, fecp->rcr); 2798e585f02STsiChung Liew printf("x_cntrl %x - %x\n", (int)&fecp->tcr, fecp->tcr); 2808e585f02STsiChung Liew printf("padr_l %x - %x\n", (int)&fecp->palr, fecp->palr); 2818e585f02STsiChung Liew printf("padr_u %x - %x\n", (int)&fecp->paur, fecp->paur); 2828e585f02STsiChung Liew printf("op_pause %x - %x\n", (int)&fecp->opd, fecp->opd); 2838e585f02STsiChung Liew printf("iadr_u %x - %x\n", (int)&fecp->iaur, fecp->iaur); 2848e585f02STsiChung Liew printf("iadr_l %x - %x\n", (int)&fecp->ialr, fecp->ialr); 2858e585f02STsiChung Liew printf("gadr_u %x - %x\n", (int)&fecp->gaur, fecp->gaur); 2868e585f02STsiChung Liew printf("gadr_l %x - %x\n", (int)&fecp->galr, fecp->galr); 2878e585f02STsiChung Liew printf("x_wmrk %x - %x\n", (int)&fecp->tfwr, fecp->tfwr); 2888e585f02STsiChung Liew printf("r_bound %x - %x\n", (int)&fecp->frbr, fecp->frbr); 2898e585f02STsiChung Liew printf("r_fstart %x - %x\n", (int)&fecp->frsr, fecp->frsr); 2908e585f02STsiChung Liew printf("r_drng %x - %x\n", (int)&fecp->erdsr, fecp->erdsr); 2918e585f02STsiChung Liew printf("x_drng %x - %x\n", (int)&fecp->etdsr, fecp->etdsr); 2928e585f02STsiChung Liew printf("r_bufsz %x - %x\n", (int)&fecp->emrbr, fecp->emrbr); 2938e585f02STsiChung Liew 2948e585f02STsiChung Liew printf("\n"); 2958e585f02STsiChung Liew printf("rmon_t_drop %x - %x\n", (int)&fecp->rmon_t_drop, 2968e585f02STsiChung Liew fecp->rmon_t_drop); 2978e585f02STsiChung Liew printf("rmon_t_packets %x - %x\n", (int)&fecp->rmon_t_packets, 2988e585f02STsiChung Liew fecp->rmon_t_packets); 2998e585f02STsiChung Liew printf("rmon_t_bc_pkt %x - %x\n", (int)&fecp->rmon_t_bc_pkt, 3008e585f02STsiChung Liew fecp->rmon_t_bc_pkt); 3018e585f02STsiChung Liew printf("rmon_t_mc_pkt %x - %x\n", (int)&fecp->rmon_t_mc_pkt, 3028e585f02STsiChung Liew fecp->rmon_t_mc_pkt); 3038e585f02STsiChung Liew printf("rmon_t_crc_align %x - %x\n", (int)&fecp->rmon_t_crc_align, 3048e585f02STsiChung Liew fecp->rmon_t_crc_align); 3058e585f02STsiChung Liew printf("rmon_t_undersize %x - %x\n", (int)&fecp->rmon_t_undersize, 3068e585f02STsiChung Liew fecp->rmon_t_undersize); 3078e585f02STsiChung Liew printf("rmon_t_oversize %x - %x\n", (int)&fecp->rmon_t_oversize, 3088e585f02STsiChung Liew fecp->rmon_t_oversize); 3098e585f02STsiChung Liew printf("rmon_t_frag %x - %x\n", (int)&fecp->rmon_t_frag, 3108e585f02STsiChung Liew fecp->rmon_t_frag); 3118e585f02STsiChung Liew printf("rmon_t_jab %x - %x\n", (int)&fecp->rmon_t_jab, 3128e585f02STsiChung Liew fecp->rmon_t_jab); 3138e585f02STsiChung Liew printf("rmon_t_col %x - %x\n", (int)&fecp->rmon_t_col, 3148e585f02STsiChung Liew fecp->rmon_t_col); 3158e585f02STsiChung Liew printf("rmon_t_p64 %x - %x\n", (int)&fecp->rmon_t_p64, 3168e585f02STsiChung Liew fecp->rmon_t_p64); 3178e585f02STsiChung Liew printf("rmon_t_p65to127 %x - %x\n", (int)&fecp->rmon_t_p65to127, 3188e585f02STsiChung Liew fecp->rmon_t_p65to127); 3198e585f02STsiChung Liew printf("rmon_t_p128to255 %x - %x\n", (int)&fecp->rmon_t_p128to255, 3208e585f02STsiChung Liew fecp->rmon_t_p128to255); 3218e585f02STsiChung Liew printf("rmon_t_p256to511 %x - %x\n", (int)&fecp->rmon_t_p256to511, 3228e585f02STsiChung Liew fecp->rmon_t_p256to511); 3238e585f02STsiChung Liew printf("rmon_t_p512to1023 %x - %x\n", (int)&fecp->rmon_t_p512to1023, 3248e585f02STsiChung Liew fecp->rmon_t_p512to1023); 3258e585f02STsiChung Liew printf("rmon_t_p1024to2047 %x - %x\n", (int)&fecp->rmon_t_p1024to2047, 3268e585f02STsiChung Liew fecp->rmon_t_p1024to2047); 3278e585f02STsiChung Liew printf("rmon_t_p_gte2048 %x - %x\n", (int)&fecp->rmon_t_p_gte2048, 3288e585f02STsiChung Liew fecp->rmon_t_p_gte2048); 3298e585f02STsiChung Liew printf("rmon_t_octets %x - %x\n", (int)&fecp->rmon_t_octets, 3308e585f02STsiChung Liew fecp->rmon_t_octets); 3318e585f02STsiChung Liew 3328e585f02STsiChung Liew printf("\n"); 3338e585f02STsiChung Liew printf("ieee_t_drop %x - %x\n", (int)&fecp->ieee_t_drop, 3348e585f02STsiChung Liew fecp->ieee_t_drop); 3358e585f02STsiChung Liew printf("ieee_t_frame_ok %x - %x\n", (int)&fecp->ieee_t_frame_ok, 3368e585f02STsiChung Liew fecp->ieee_t_frame_ok); 3378e585f02STsiChung Liew printf("ieee_t_1col %x - %x\n", (int)&fecp->ieee_t_1col, 3388e585f02STsiChung Liew fecp->ieee_t_1col); 3398e585f02STsiChung Liew printf("ieee_t_mcol %x - %x\n", (int)&fecp->ieee_t_mcol, 3408e585f02STsiChung Liew fecp->ieee_t_mcol); 3418e585f02STsiChung Liew printf("ieee_t_def %x - %x\n", (int)&fecp->ieee_t_def, 3428e585f02STsiChung Liew fecp->ieee_t_def); 3438e585f02STsiChung Liew printf("ieee_t_lcol %x - %x\n", (int)&fecp->ieee_t_lcol, 3448e585f02STsiChung Liew fecp->ieee_t_lcol); 3458e585f02STsiChung Liew printf("ieee_t_excol %x - %x\n", (int)&fecp->ieee_t_excol, 3468e585f02STsiChung Liew fecp->ieee_t_excol); 3478e585f02STsiChung Liew printf("ieee_t_macerr %x - %x\n", (int)&fecp->ieee_t_macerr, 3488e585f02STsiChung Liew fecp->ieee_t_macerr); 3498e585f02STsiChung Liew printf("ieee_t_cserr %x - %x\n", (int)&fecp->ieee_t_cserr, 3508e585f02STsiChung Liew fecp->ieee_t_cserr); 3518e585f02STsiChung Liew printf("ieee_t_sqe %x - %x\n", (int)&fecp->ieee_t_sqe, 3528e585f02STsiChung Liew fecp->ieee_t_sqe); 3538e585f02STsiChung Liew printf("ieee_t_fdxfc %x - %x\n", (int)&fecp->ieee_t_fdxfc, 3548e585f02STsiChung Liew fecp->ieee_t_fdxfc); 3558e585f02STsiChung Liew printf("ieee_t_octets_ok %x - %x\n", (int)&fecp->ieee_t_octets_ok, 3568e585f02STsiChung Liew fecp->ieee_t_octets_ok); 3578e585f02STsiChung Liew 3588e585f02STsiChung Liew printf("\n"); 3598e585f02STsiChung Liew printf("rmon_r_drop %x - %x\n", (int)&fecp->rmon_r_drop, 3608e585f02STsiChung Liew fecp->rmon_r_drop); 3618e585f02STsiChung Liew printf("rmon_r_packets %x - %x\n", (int)&fecp->rmon_r_packets, 3628e585f02STsiChung Liew fecp->rmon_r_packets); 3638e585f02STsiChung Liew printf("rmon_r_bc_pkt %x - %x\n", (int)&fecp->rmon_r_bc_pkt, 3648e585f02STsiChung Liew fecp->rmon_r_bc_pkt); 3658e585f02STsiChung Liew printf("rmon_r_mc_pkt %x - %x\n", (int)&fecp->rmon_r_mc_pkt, 3668e585f02STsiChung Liew fecp->rmon_r_mc_pkt); 3678e585f02STsiChung Liew printf("rmon_r_crc_align %x - %x\n", (int)&fecp->rmon_r_crc_align, 3688e585f02STsiChung Liew fecp->rmon_r_crc_align); 3698e585f02STsiChung Liew printf("rmon_r_undersize %x - %x\n", (int)&fecp->rmon_r_undersize, 3708e585f02STsiChung Liew fecp->rmon_r_undersize); 3718e585f02STsiChung Liew printf("rmon_r_oversize %x - %x\n", (int)&fecp->rmon_r_oversize, 3728e585f02STsiChung Liew fecp->rmon_r_oversize); 3738e585f02STsiChung Liew printf("rmon_r_frag %x - %x\n", (int)&fecp->rmon_r_frag, 3748e585f02STsiChung Liew fecp->rmon_r_frag); 3758e585f02STsiChung Liew printf("rmon_r_jab %x - %x\n", (int)&fecp->rmon_r_jab, 3768e585f02STsiChung Liew fecp->rmon_r_jab); 3778e585f02STsiChung Liew printf("rmon_r_p64 %x - %x\n", (int)&fecp->rmon_r_p64, 3788e585f02STsiChung Liew fecp->rmon_r_p64); 3798e585f02STsiChung Liew printf("rmon_r_p65to127 %x - %x\n", (int)&fecp->rmon_r_p65to127, 3808e585f02STsiChung Liew fecp->rmon_r_p65to127); 3818e585f02STsiChung Liew printf("rmon_r_p128to255 %x - %x\n", (int)&fecp->rmon_r_p128to255, 3828e585f02STsiChung Liew fecp->rmon_r_p128to255); 3838e585f02STsiChung Liew printf("rmon_r_p256to511 %x - %x\n", (int)&fecp->rmon_r_p256to511, 3848e585f02STsiChung Liew fecp->rmon_r_p256to511); 3858e585f02STsiChung Liew printf("rmon_r_p512to1023 %x - %x\n", (int)&fecp->rmon_r_p512to1023, 3868e585f02STsiChung Liew fecp->rmon_r_p512to1023); 3878e585f02STsiChung Liew printf("rmon_r_p1024to2047 %x - %x\n", (int)&fecp->rmon_r_p1024to2047, 3888e585f02STsiChung Liew fecp->rmon_r_p1024to2047); 3898e585f02STsiChung Liew printf("rmon_r_p_gte2048 %x - %x\n", (int)&fecp->rmon_r_p_gte2048, 3908e585f02STsiChung Liew fecp->rmon_r_p_gte2048); 3918e585f02STsiChung Liew printf("rmon_r_octets %x - %x\n", (int)&fecp->rmon_r_octets, 3928e585f02STsiChung Liew fecp->rmon_r_octets); 3938e585f02STsiChung Liew 3948e585f02STsiChung Liew printf("\n"); 3958e585f02STsiChung Liew printf("ieee_r_drop %x - %x\n", (int)&fecp->ieee_r_drop, 3968e585f02STsiChung Liew fecp->ieee_r_drop); 3978e585f02STsiChung Liew printf("ieee_r_frame_ok %x - %x\n", (int)&fecp->ieee_r_frame_ok, 3988e585f02STsiChung Liew fecp->ieee_r_frame_ok); 3998e585f02STsiChung Liew printf("ieee_r_crc %x - %x\n", (int)&fecp->ieee_r_crc, 4008e585f02STsiChung Liew fecp->ieee_r_crc); 4018e585f02STsiChung Liew printf("ieee_r_align %x - %x\n", (int)&fecp->ieee_r_align, 4028e585f02STsiChung Liew fecp->ieee_r_align); 4038e585f02STsiChung Liew printf("ieee_r_macerr %x - %x\n", (int)&fecp->ieee_r_macerr, 4048e585f02STsiChung Liew fecp->ieee_r_macerr); 4058e585f02STsiChung Liew printf("ieee_r_fdxfc %x - %x\n", (int)&fecp->ieee_r_fdxfc, 4068e585f02STsiChung Liew fecp->ieee_r_fdxfc); 4078e585f02STsiChung Liew printf("ieee_r_octets_ok %x - %x\n", (int)&fecp->ieee_r_octets_ok, 4088e585f02STsiChung Liew fecp->ieee_r_octets_ok); 4098e585f02STsiChung Liew 4108e585f02STsiChung Liew printf("\n\n\n"); 4118e585f02STsiChung Liew } 4128e585f02STsiChung Liew #endif 4138e585f02STsiChung Liew 4148e585f02STsiChung Liew int fec_init(struct eth_device *dev, bd_t * bd) 4158e585f02STsiChung Liew { 4168e585f02STsiChung Liew struct fec_info_s *info = dev->priv; 4178e585f02STsiChung Liew volatile fec_t *fecp = (fec_t *) (info->iobase); 4188e585f02STsiChung Liew int i; 419*d3f87148SMike Frysinger uchar ea[6]; 4208e585f02STsiChung Liew 4218e585f02STsiChung Liew fecpin_setclear(dev, 1); 4228e585f02STsiChung Liew 4238e585f02STsiChung Liew fec_reset(dev); 4248e585f02STsiChung Liew 425ab77bc54STsiChungLiew #if defined(CONFIG_CMD_MII) || defined (CONFIG_MII) || \ 4266d0f6bcfSJean-Christophe PLAGNIOL-VILLARD defined (CONFIG_SYS_DISCOVER_PHY) 4278e585f02STsiChung Liew 4288e585f02STsiChung Liew mii_init(); 4298e585f02STsiChung Liew 4308e585f02STsiChung Liew setFecDuplexSpeed(fecp, bd, info->dup_spd); 4318e585f02STsiChung Liew #else 4326d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SYS_DISCOVER_PHY 4338e585f02STsiChung Liew setFecDuplexSpeed(fecp, bd, (FECDUPLEX << 16) | FECSPEED); 4346d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #endif /* ifndef CONFIG_SYS_DISCOVER_PHY */ 435ab77bc54STsiChungLiew #endif /* CONFIG_CMD_MII || CONFIG_MII */ 4368e585f02STsiChung Liew 4378e585f02STsiChung Liew /* We use strictly polling mode only */ 4388e585f02STsiChung Liew fecp->eimr = 0; 4398e585f02STsiChung Liew 4408e585f02STsiChung Liew /* Clear any pending interrupt */ 4418e585f02STsiChung Liew fecp->eir = 0xffffffff; 4428e585f02STsiChung Liew 4438e585f02STsiChung Liew /* Set station address */ 4446d0f6bcfSJean-Christophe PLAGNIOL-VILLARD if ((u32) fecp == CONFIG_SYS_FEC0_IOBASE) { 4456d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FEC1_IOBASE 4466d0f6bcfSJean-Christophe PLAGNIOL-VILLARD volatile fec_t *fecp1 = (fec_t *) (CONFIG_SYS_FEC1_IOBASE); 447*d3f87148SMike Frysinger eth_getenv_enetaddr("eth1addr", ea); 4488ae158cdSTsiChungLiew fecp1->palr = 4498ae158cdSTsiChungLiew (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]); 4508ae158cdSTsiChungLiew fecp1->paur = (ea[4] << 24) | (ea[5] << 16); 4518ae158cdSTsiChungLiew #endif 452*d3f87148SMike Frysinger eth_getenv_enetaddr("ethaddr", ea); 4538ae158cdSTsiChungLiew fecp->palr = 4548ae158cdSTsiChungLiew (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]); 4558ae158cdSTsiChungLiew fecp->paur = (ea[4] << 24) | (ea[5] << 16); 4568e585f02STsiChung Liew } else { 4576d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FEC0_IOBASE 4586d0f6bcfSJean-Christophe PLAGNIOL-VILLARD volatile fec_t *fecp0 = (fec_t *) (CONFIG_SYS_FEC0_IOBASE); 459*d3f87148SMike Frysinger eth_getenv_enetaddr("ethaddr", ea); 4608ae158cdSTsiChungLiew fecp0->palr = 4618ae158cdSTsiChungLiew (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]); 4628ae158cdSTsiChungLiew fecp0->paur = (ea[4] << 24) | (ea[5] << 16); 4638ae158cdSTsiChungLiew #endif 4646d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FEC1_IOBASE 465*d3f87148SMike Frysinger eth_getenv_enetaddr("eth1addr", ea); 4668ae158cdSTsiChungLiew fecp->palr = 4678ae158cdSTsiChungLiew (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]); 4688ae158cdSTsiChungLiew fecp->paur = (ea[4] << 24) | (ea[5] << 16); 4698e585f02STsiChung Liew #endif 4708e585f02STsiChung Liew } 4718e585f02STsiChung Liew 4728e585f02STsiChung Liew /* Clear unicast address hash table */ 4738e585f02STsiChung Liew fecp->iaur = 0; 4748e585f02STsiChung Liew fecp->ialr = 0; 4758e585f02STsiChung Liew 4768e585f02STsiChung Liew /* Clear multicast address hash table */ 4778e585f02STsiChung Liew fecp->gaur = 0; 4788e585f02STsiChung Liew fecp->galr = 0; 4798e585f02STsiChung Liew 4808e585f02STsiChung Liew /* Set maximum receive buffer size. */ 4818e585f02STsiChung Liew fecp->emrbr = PKT_MAXBLR_SIZE; 4828e585f02STsiChung Liew 4838e585f02STsiChung Liew /* 4848e585f02STsiChung Liew * Setup Buffers and Buffer Desriptors 4858e585f02STsiChung Liew */ 4868e585f02STsiChung Liew info->rxIdx = 0; 4878e585f02STsiChung Liew info->txIdx = 0; 4888e585f02STsiChung Liew 4898e585f02STsiChung Liew /* 4908e585f02STsiChung Liew * Setup Receiver Buffer Descriptors (13.14.24.18) 4918e585f02STsiChung Liew * Settings: 4928e585f02STsiChung Liew * Empty, Wrap 4938e585f02STsiChung Liew */ 4948e585f02STsiChung Liew for (i = 0; i < PKTBUFSRX; i++) { 4958e585f02STsiChung Liew info->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY; 4968e585f02STsiChung Liew info->rxbd[i].cbd_datlen = 0; /* Reset */ 4978e585f02STsiChung Liew info->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i]; 4988e585f02STsiChung Liew } 4998e585f02STsiChung Liew info->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP; 5008e585f02STsiChung Liew 5018e585f02STsiChung Liew /* 5028e585f02STsiChung Liew * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19) 5038e585f02STsiChung Liew * Settings: 5048e585f02STsiChung Liew * Last, Tx CRC 5058e585f02STsiChung Liew */ 5068e585f02STsiChung Liew for (i = 0; i < TX_BUF_CNT; i++) { 5078e585f02STsiChung Liew info->txbd[i].cbd_sc = BD_ENET_TX_LAST | BD_ENET_TX_TC; 5088e585f02STsiChung Liew info->txbd[i].cbd_datlen = 0; /* Reset */ 5098e585f02STsiChung Liew info->txbd[i].cbd_bufaddr = (uint) (&info->txbuf[0]); 5108e585f02STsiChung Liew } 5118e585f02STsiChung Liew info->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP; 5128e585f02STsiChung Liew 5138e585f02STsiChung Liew /* Set receive and transmit descriptor base */ 5148e585f02STsiChung Liew fecp->erdsr = (unsigned int)(&info->rxbd[0]); 5158e585f02STsiChung Liew fecp->etdsr = (unsigned int)(&info->txbd[0]); 5168e585f02STsiChung Liew 5178e585f02STsiChung Liew /* Now enable the transmit and receive processing */ 5188e585f02STsiChung Liew fecp->ecr |= FEC_ECR_ETHER_EN; 5198e585f02STsiChung Liew 5208e585f02STsiChung Liew /* And last, try to fill Rx Buffer Descriptors */ 5218e585f02STsiChung Liew fecp->rdar = 0x01000000; /* Descriptor polling active */ 5228e585f02STsiChung Liew 5238e585f02STsiChung Liew return 1; 5248e585f02STsiChung Liew } 5258e585f02STsiChung Liew 5268e585f02STsiChung Liew void fec_reset(struct eth_device *dev) 5278e585f02STsiChung Liew { 5288e585f02STsiChung Liew struct fec_info_s *info = dev->priv; 5298e585f02STsiChung Liew volatile fec_t *fecp = (fec_t *) (info->iobase); 5308e585f02STsiChung Liew int i; 5318e585f02STsiChung Liew 5328e585f02STsiChung Liew fecp->ecr = FEC_ECR_RESET; 5338e585f02STsiChung Liew for (i = 0; (fecp->ecr & FEC_ECR_RESET) && (i < FEC_RESET_DELAY); ++i) { 5348e585f02STsiChung Liew udelay(1); 5358e585f02STsiChung Liew } 5368e585f02STsiChung Liew if (i == FEC_RESET_DELAY) { 5378e585f02STsiChung Liew printf("FEC_RESET_DELAY timeout\n"); 5388e585f02STsiChung Liew } 5398e585f02STsiChung Liew } 5408e585f02STsiChung Liew 5418e585f02STsiChung Liew void fec_halt(struct eth_device *dev) 5428e585f02STsiChung Liew { 5438e585f02STsiChung Liew struct fec_info_s *info = dev->priv; 5448e585f02STsiChung Liew 5458e585f02STsiChung Liew fec_reset(dev); 5468e585f02STsiChung Liew 5478e585f02STsiChung Liew fecpin_setclear(dev, 0); 5488e585f02STsiChung Liew 5498e585f02STsiChung Liew info->rxIdx = info->txIdx = 0; 5508e585f02STsiChung Liew memset(info->rxbd, 0, PKTBUFSRX * sizeof(cbd_t)); 5518e585f02STsiChung Liew memset(info->txbd, 0, TX_BUF_CNT * sizeof(cbd_t)); 5528e585f02STsiChung Liew memset(info->txbuf, 0, DBUF_LENGTH); 5538e585f02STsiChung Liew } 5548e585f02STsiChung Liew 5558e585f02STsiChung Liew int mcffec_initialize(bd_t * bis) 5568e585f02STsiChung Liew { 5578e585f02STsiChung Liew struct eth_device *dev; 5588e585f02STsiChung Liew int i; 5596d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FEC_BUF_USE_SRAM 5606d0f6bcfSJean-Christophe PLAGNIOL-VILLARD u32 tmp = CONFIG_SYS_INIT_RAM_ADDR + 0x1000; 5611803f7f9STsiChung Liew #endif 5628e585f02STsiChung Liew 5638e585f02STsiChung Liew for (i = 0; i < sizeof(fec_info) / sizeof(fec_info[0]); i++) { 5648e585f02STsiChung Liew 565f2208fbcSTsiChungLiew dev = 5666d0f6bcfSJean-Christophe PLAGNIOL-VILLARD (struct eth_device *)memalign(CONFIG_SYS_CACHELINE_SIZE, 567f2208fbcSTsiChungLiew sizeof *dev); 5688e585f02STsiChung Liew if (dev == NULL) 5698e585f02STsiChung Liew hang(); 5708e585f02STsiChung Liew 5718e585f02STsiChung Liew memset(dev, 0, sizeof(*dev)); 5728e585f02STsiChung Liew 5738e585f02STsiChung Liew sprintf(dev->name, "FEC%d", fec_info[i].index); 5748e585f02STsiChung Liew 5758e585f02STsiChung Liew dev->priv = &fec_info[i]; 5768e585f02STsiChung Liew dev->init = fec_init; 5778e585f02STsiChung Liew dev->halt = fec_halt; 5788e585f02STsiChung Liew dev->send = fec_send; 5798e585f02STsiChung Liew dev->recv = fec_recv; 5808e585f02STsiChung Liew 5818e585f02STsiChung Liew /* setup Receive and Transmit buffer descriptor */ 5826d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FEC_BUF_USE_SRAM 5831803f7f9STsiChung Liew fec_info[i].rxbd = (cbd_t *)((u32)fec_info[i].rxbd + tmp); 5841803f7f9STsiChung Liew tmp = (u32)fec_info[i].rxbd; 5851803f7f9STsiChung Liew fec_info[i].txbd = 5861803f7f9STsiChung Liew (cbd_t *)((u32)fec_info[i].txbd + tmp + 5871803f7f9STsiChung Liew (PKTBUFSRX * sizeof(cbd_t))); 5881803f7f9STsiChung Liew tmp = (u32)fec_info[i].txbd; 5891803f7f9STsiChung Liew fec_info[i].txbuf = 5901803f7f9STsiChung Liew (char *)((u32)fec_info[i].txbuf + tmp + 5916d0f6bcfSJean-Christophe PLAGNIOL-VILLARD (CONFIG_SYS_TX_ETH_BUFFER * sizeof(cbd_t))); 5921803f7f9STsiChung Liew tmp = (u32)fec_info[i].txbuf; 5931803f7f9STsiChung Liew #else 5948e585f02STsiChung Liew fec_info[i].rxbd = 5956d0f6bcfSJean-Christophe PLAGNIOL-VILLARD (cbd_t *) memalign(CONFIG_SYS_CACHELINE_SIZE, 596f2208fbcSTsiChungLiew (PKTBUFSRX * sizeof(cbd_t))); 5978e585f02STsiChung Liew fec_info[i].txbd = 5986d0f6bcfSJean-Christophe PLAGNIOL-VILLARD (cbd_t *) memalign(CONFIG_SYS_CACHELINE_SIZE, 599f2208fbcSTsiChungLiew (TX_BUF_CNT * sizeof(cbd_t))); 600f2208fbcSTsiChungLiew fec_info[i].txbuf = 6016d0f6bcfSJean-Christophe PLAGNIOL-VILLARD (char *)memalign(CONFIG_SYS_CACHELINE_SIZE, DBUF_LENGTH); 6021803f7f9STsiChung Liew #endif 6031803f7f9STsiChung Liew 6048e585f02STsiChung Liew #ifdef ET_DEBUG 6058e585f02STsiChung Liew printf("rxbd %x txbd %x\n", 6068e585f02STsiChung Liew (int)fec_info[i].rxbd, (int)fec_info[i].txbd); 6078e585f02STsiChung Liew #endif 6088e585f02STsiChung Liew 6096d0f6bcfSJean-Christophe PLAGNIOL-VILLARD fec_info[i].phy_name = (char *)memalign(CONFIG_SYS_CACHELINE_SIZE, 32); 6108e585f02STsiChung Liew 6118e585f02STsiChung Liew eth_register(dev); 6128e585f02STsiChung Liew 613ab77bc54STsiChungLiew #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) 6148e585f02STsiChung Liew miiphy_register(dev->name, 6158e585f02STsiChung Liew mcffec_miiphy_read, mcffec_miiphy_write); 6168e585f02STsiChung Liew #endif 6171803f7f9STsiChung Liew if (i > 0) 6181803f7f9STsiChung Liew fec_info[i - 1].next = &fec_info[i]; 6198e585f02STsiChung Liew } 6201803f7f9STsiChung Liew fec_info[i - 1].next = &fec_info[0]; 6218e585f02STsiChung Liew 6228e585f02STsiChung Liew /* default speed */ 6238e585f02STsiChung Liew bis->bi_ethspeed = 10; 6248e585f02STsiChung Liew 62586882b80SBen Warren return 0; 6268e585f02STsiChung Liew } 627