1*8e585f02STsiChung Liew /* 2*8e585f02STsiChung Liew * (C) Copyright 2000-2004 3*8e585f02STsiChung Liew * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4*8e585f02STsiChung Liew * 5*8e585f02STsiChung Liew * (C) Copyright 2007 6*8e585f02STsiChung Liew * TsiChung Liew (Tsi-Chung.Liew@freescale.com) 7*8e585f02STsiChung Liew * 8*8e585f02STsiChung Liew * See file CREDITS for list of people who contributed to this 9*8e585f02STsiChung Liew * project. 10*8e585f02STsiChung Liew * 11*8e585f02STsiChung Liew * This program is free software; you can redistribute it and/or 12*8e585f02STsiChung Liew * modify it under the terms of the GNU General Public License as 13*8e585f02STsiChung Liew * published by the Free Software Foundation; either version 2 of 14*8e585f02STsiChung Liew * the License, or (at your option) any later version. 15*8e585f02STsiChung Liew * 16*8e585f02STsiChung Liew * This program is distributed in the hope that it will be useful, 17*8e585f02STsiChung Liew * but WITHOUT ANY WARRANTY; without even the implied warranty of 18*8e585f02STsiChung Liew * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19*8e585f02STsiChung Liew * GNU General Public License for more details. 20*8e585f02STsiChung Liew * 21*8e585f02STsiChung Liew * You should have received a copy of the GNU General Public License 22*8e585f02STsiChung Liew * along with this program; if not, write to the Free Software 23*8e585f02STsiChung Liew * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 24*8e585f02STsiChung Liew * MA 02111-1307 USA 25*8e585f02STsiChung Liew */ 26*8e585f02STsiChung Liew 27*8e585f02STsiChung Liew #include <common.h> 28*8e585f02STsiChung Liew #include <malloc.h> 29*8e585f02STsiChung Liew 30*8e585f02STsiChung Liew #include <asm/fec.h> 31*8e585f02STsiChung Liew #include <asm/m5329.h> 32*8e585f02STsiChung Liew #include <asm/immap_5329.h> 33*8e585f02STsiChung Liew 34*8e585f02STsiChung Liew #include <command.h> 35*8e585f02STsiChung Liew #include <config.h> 36*8e585f02STsiChung Liew #include <net.h> 37*8e585f02STsiChung Liew #include <miiphy.h> 38*8e585f02STsiChung Liew 39*8e585f02STsiChung Liew #ifdef CONFIG_MCFFEC 40*8e585f02STsiChung Liew #undef ET_DEBUG 41*8e585f02STsiChung Liew #undef MII_DEBUG 42*8e585f02STsiChung Liew 43*8e585f02STsiChung Liew /* Ethernet Transmit and Receive Buffers */ 44*8e585f02STsiChung Liew #define DBUF_LENGTH 1520 45*8e585f02STsiChung Liew 46*8e585f02STsiChung Liew #define TX_BUF_CNT 2 47*8e585f02STsiChung Liew 48*8e585f02STsiChung Liew /* 49*8e585f02STsiChung Liew NOTE: PKT_MAXBUF_SIZE must be larger or equal to PKT_MAXBLR_SIZE, 50*8e585f02STsiChung Liew see M54455 User Manual for MAX_FL of Receive Control Register for more 51*8e585f02STsiChung Liew description. If PKT_MAXBUF_SIZE set to 1518, the FEC bandwidth will 52*8e585f02STsiChung Liew reduce to about 20~40% of normal bandwidth. Changing PKT_MAXBLR_SIZE 53*8e585f02STsiChung Liew will not make any improvement on speed 54*8e585f02STsiChung Liew */ 55*8e585f02STsiChung Liew #define PKT_MAXBUF_SIZE 1518 56*8e585f02STsiChung Liew #define PKT_MINBUF_SIZE 64 57*8e585f02STsiChung Liew #define PKT_MAXBLR_SIZE 1520 58*8e585f02STsiChung Liew #define LAST_PKTBUFSRX PKTBUFSRX - 1 59*8e585f02STsiChung Liew #define BD_ENET_RX_W_E (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY) 60*8e585f02STsiChung Liew #define BD_ENET_TX_RDY_LST (BD_ENET_TX_READY | BD_ENET_TX_LAST) 61*8e585f02STsiChung Liew 62*8e585f02STsiChung Liew DECLARE_GLOBAL_DATA_PTR; 63*8e585f02STsiChung Liew 64*8e585f02STsiChung Liew #if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) 65*8e585f02STsiChung Liew 66*8e585f02STsiChung Liew struct fec_info_s fec_info[] = { 67*8e585f02STsiChung Liew #ifdef CFG_FEC0_IOBASE 68*8e585f02STsiChung Liew { 69*8e585f02STsiChung Liew 0, /* index */ 70*8e585f02STsiChung Liew CFG_FEC0_IOBASE, /* io base */ 71*8e585f02STsiChung Liew CFG_FEC0_PINMUX, /* gpio pin muxing */ 72*8e585f02STsiChung Liew CFG_FEC0_MIIBASE, /* mii base */ 73*8e585f02STsiChung Liew -1, /* phy_addr */ 74*8e585f02STsiChung Liew 0, /* duplex and speed */ 75*8e585f02STsiChung Liew 0, /* phy name */ 76*8e585f02STsiChung Liew 0, /* phyname init */ 77*8e585f02STsiChung Liew 0, /* RX BD */ 78*8e585f02STsiChung Liew 0, /* TX BD */ 79*8e585f02STsiChung Liew 0, /* rx Index */ 80*8e585f02STsiChung Liew 0, /* tx Index */ 81*8e585f02STsiChung Liew 0, /* tx buffer */ 82*8e585f02STsiChung Liew 0, /* initialized flag */ 83*8e585f02STsiChung Liew }, 84*8e585f02STsiChung Liew #endif 85*8e585f02STsiChung Liew #ifdef CFG_FEC1_IOBASE 86*8e585f02STsiChung Liew { 87*8e585f02STsiChung Liew 1, /* index */ 88*8e585f02STsiChung Liew CFG_FEC1_IOBASE, /* io base */ 89*8e585f02STsiChung Liew CFG_FEC1_PINMUX, /* gpio pin muxing */ 90*8e585f02STsiChung Liew CFG_FEC1_MIIBASE, /* mii base */ 91*8e585f02STsiChung Liew -1, /* phy_addr */ 92*8e585f02STsiChung Liew 0, /* duplex and speed */ 93*8e585f02STsiChung Liew 0, /* phy name */ 94*8e585f02STsiChung Liew 0, /* phy name init */ 95*8e585f02STsiChung Liew 0, /* RX BD */ 96*8e585f02STsiChung Liew 0, /* TX BD */ 97*8e585f02STsiChung Liew 0, /* rx Index */ 98*8e585f02STsiChung Liew 0, /* tx Index */ 99*8e585f02STsiChung Liew 0, /* tx buffer */ 100*8e585f02STsiChung Liew 0, /* initialized flag */ 101*8e585f02STsiChung Liew } 102*8e585f02STsiChung Liew #endif 103*8e585f02STsiChung Liew }; 104*8e585f02STsiChung Liew 105*8e585f02STsiChung Liew /* 106*8e585f02STsiChung Liew * FEC Ethernet Tx and Rx buffer descriptors allocated at the 107*8e585f02STsiChung Liew * immr->udata_bd address on Dual-Port RAM 108*8e585f02STsiChung Liew * Provide for Double Buffering 109*8e585f02STsiChung Liew */ 110*8e585f02STsiChung Liew 111*8e585f02STsiChung Liew int fec_send(struct eth_device *dev, volatile void *packet, int length); 112*8e585f02STsiChung Liew int fec_recv(struct eth_device *dev); 113*8e585f02STsiChung Liew int fec_init(struct eth_device *dev, bd_t * bd); 114*8e585f02STsiChung Liew void fec_halt(struct eth_device *dev); 115*8e585f02STsiChung Liew void fec_reset(struct eth_device *dev); 116*8e585f02STsiChung Liew 117*8e585f02STsiChung Liew extern int fecpin_setclear(struct eth_device *dev, int setclear); 118*8e585f02STsiChung Liew 119*8e585f02STsiChung Liew #ifdef CFG_DISCOVER_PHY 120*8e585f02STsiChung Liew extern void mii_init(void); 121*8e585f02STsiChung Liew extern uint mii_send(uint mii_cmd); 122*8e585f02STsiChung Liew extern int mii_discover_phy(struct eth_device *dev); 123*8e585f02STsiChung Liew extern int mcffec_miiphy_read(char *devname, unsigned char addr, 124*8e585f02STsiChung Liew unsigned char reg, unsigned short *value); 125*8e585f02STsiChung Liew extern int mcffec_miiphy_write(char *devname, unsigned char addr, 126*8e585f02STsiChung Liew unsigned char reg, unsigned short value); 127*8e585f02STsiChung Liew #endif 128*8e585f02STsiChung Liew 129*8e585f02STsiChung Liew void setFecDuplexSpeed(volatile fec_t * fecp, bd_t * bd, int dup_spd) 130*8e585f02STsiChung Liew { 131*8e585f02STsiChung Liew if ((dup_spd >> 16) == FULL) { 132*8e585f02STsiChung Liew /* Set maximum frame length */ 133*8e585f02STsiChung Liew fecp->rcr = FEC_RCR_MAX_FL(PKT_MAXBUF_SIZE) | FEC_RCR_MII_MODE | 134*8e585f02STsiChung Liew FEC_RCR_PROM | 0x100; 135*8e585f02STsiChung Liew fecp->tcr = FEC_TCR_FDEN; 136*8e585f02STsiChung Liew } else { 137*8e585f02STsiChung Liew /* Half duplex mode */ 138*8e585f02STsiChung Liew fecp->rcr = FEC_RCR_MAX_FL(PKT_MAXBUF_SIZE) | 139*8e585f02STsiChung Liew FEC_RCR_MII_MODE | FEC_RCR_DRT; 140*8e585f02STsiChung Liew fecp->tcr &= ~FEC_TCR_FDEN; 141*8e585f02STsiChung Liew } 142*8e585f02STsiChung Liew 143*8e585f02STsiChung Liew if ((dup_spd & 0xFFFF) == _100BASET) { 144*8e585f02STsiChung Liew #ifdef MII_DEBUG 145*8e585f02STsiChung Liew printf("100Mbps\n"); 146*8e585f02STsiChung Liew #endif 147*8e585f02STsiChung Liew bd->bi_ethspeed = 100; 148*8e585f02STsiChung Liew } else { 149*8e585f02STsiChung Liew #ifdef MII_DEBUG 150*8e585f02STsiChung Liew printf("10Mbps\n"); 151*8e585f02STsiChung Liew #endif 152*8e585f02STsiChung Liew bd->bi_ethspeed = 10; 153*8e585f02STsiChung Liew } 154*8e585f02STsiChung Liew } 155*8e585f02STsiChung Liew 156*8e585f02STsiChung Liew int fec_send(struct eth_device *dev, volatile void *packet, int length) 157*8e585f02STsiChung Liew { 158*8e585f02STsiChung Liew struct fec_info_s *info = dev->priv; 159*8e585f02STsiChung Liew volatile fec_t *fecp = (fec_t *) (info->iobase); 160*8e585f02STsiChung Liew int j, rc; 161*8e585f02STsiChung Liew u16 phyStatus; 162*8e585f02STsiChung Liew 163*8e585f02STsiChung Liew miiphy_read(dev->name, info->phy_addr, PHY_BMSR, &phyStatus); 164*8e585f02STsiChung Liew 165*8e585f02STsiChung Liew /* section 16.9.23.3 166*8e585f02STsiChung Liew * Wait for ready 167*8e585f02STsiChung Liew */ 168*8e585f02STsiChung Liew j = 0; 169*8e585f02STsiChung Liew while ((info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_READY) && 170*8e585f02STsiChung Liew (j < MCFFEC_TOUT_LOOP)) { 171*8e585f02STsiChung Liew udelay(1); 172*8e585f02STsiChung Liew j++; 173*8e585f02STsiChung Liew } 174*8e585f02STsiChung Liew if (j >= MCFFEC_TOUT_LOOP) { 175*8e585f02STsiChung Liew printf("TX not ready\n"); 176*8e585f02STsiChung Liew } 177*8e585f02STsiChung Liew 178*8e585f02STsiChung Liew info->txbd[info->txIdx].cbd_bufaddr = (uint) packet; 179*8e585f02STsiChung Liew info->txbd[info->txIdx].cbd_datlen = length; 180*8e585f02STsiChung Liew info->txbd[info->txIdx].cbd_sc |= BD_ENET_TX_RDY_LST; 181*8e585f02STsiChung Liew 182*8e585f02STsiChung Liew /* Activate transmit Buffer Descriptor polling */ 183*8e585f02STsiChung Liew fecp->tdar = 0x01000000; /* Descriptor polling active */ 184*8e585f02STsiChung Liew 185*8e585f02STsiChung Liew j = 0; 186*8e585f02STsiChung Liew while ((info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_READY) && 187*8e585f02STsiChung Liew (j < MCFFEC_TOUT_LOOP)) { 188*8e585f02STsiChung Liew udelay(1); 189*8e585f02STsiChung Liew j++; 190*8e585f02STsiChung Liew } 191*8e585f02STsiChung Liew if (j >= MCFFEC_TOUT_LOOP) { 192*8e585f02STsiChung Liew printf("TX timeout\n"); 193*8e585f02STsiChung Liew } 194*8e585f02STsiChung Liew #ifdef ET_DEBUG 195*8e585f02STsiChung Liew printf("%s[%d] %s: cycles: %d status: %x retry cnt: %d\n", 196*8e585f02STsiChung Liew __FILE__, __LINE__, __FUNCTION__, j, 197*8e585f02STsiChung Liew info->txbd[info->txIdx].cbd_sc, 198*8e585f02STsiChung Liew (info->txbd[info->txIdx].cbd_sc & 0x003C) >> 2); 199*8e585f02STsiChung Liew #endif 200*8e585f02STsiChung Liew 201*8e585f02STsiChung Liew /* return only status bits */ ; 202*8e585f02STsiChung Liew rc = (info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_STATS); 203*8e585f02STsiChung Liew info->txIdx = (info->txIdx + 1) % TX_BUF_CNT; 204*8e585f02STsiChung Liew 205*8e585f02STsiChung Liew return rc; 206*8e585f02STsiChung Liew } 207*8e585f02STsiChung Liew 208*8e585f02STsiChung Liew int fec_recv(struct eth_device *dev) 209*8e585f02STsiChung Liew { 210*8e585f02STsiChung Liew struct fec_info_s *info = dev->priv; 211*8e585f02STsiChung Liew volatile fec_t *fecp = (fec_t *) (info->iobase); 212*8e585f02STsiChung Liew int length; 213*8e585f02STsiChung Liew 214*8e585f02STsiChung Liew for (;;) { 215*8e585f02STsiChung Liew /* section 16.9.23.2 */ 216*8e585f02STsiChung Liew if (info->rxbd[info->rxIdx].cbd_sc & BD_ENET_RX_EMPTY) { 217*8e585f02STsiChung Liew length = -1; 218*8e585f02STsiChung Liew break; /* nothing received - leave for() loop */ 219*8e585f02STsiChung Liew } 220*8e585f02STsiChung Liew 221*8e585f02STsiChung Liew length = info->rxbd[info->rxIdx].cbd_datlen; 222*8e585f02STsiChung Liew 223*8e585f02STsiChung Liew if (info->rxbd[info->rxIdx].cbd_sc & 0x003f) { 224*8e585f02STsiChung Liew printf("%s[%d] err: %x\n", 225*8e585f02STsiChung Liew __FUNCTION__, __LINE__, 226*8e585f02STsiChung Liew info->rxbd[info->rxIdx].cbd_sc); 227*8e585f02STsiChung Liew #ifdef ET_DEBUG 228*8e585f02STsiChung Liew printf("%s[%d] err: %x\n", 229*8e585f02STsiChung Liew __FUNCTION__, __LINE__, 230*8e585f02STsiChung Liew info->rxbd[info->rxIdx].cbd_sc); 231*8e585f02STsiChung Liew #endif 232*8e585f02STsiChung Liew } else { 233*8e585f02STsiChung Liew 234*8e585f02STsiChung Liew length -= 4; 235*8e585f02STsiChung Liew /* Pass the packet up to the protocol layers. */ 236*8e585f02STsiChung Liew NetReceive(NetRxPackets[info->rxIdx], length); 237*8e585f02STsiChung Liew 238*8e585f02STsiChung Liew fecp->eir |= FEC_EIR_RXF; 239*8e585f02STsiChung Liew } 240*8e585f02STsiChung Liew 241*8e585f02STsiChung Liew /* Give the buffer back to the FEC. */ 242*8e585f02STsiChung Liew info->rxbd[info->rxIdx].cbd_datlen = 0; 243*8e585f02STsiChung Liew 244*8e585f02STsiChung Liew /* wrap around buffer index when necessary */ 245*8e585f02STsiChung Liew if (info->rxIdx == LAST_PKTBUFSRX) { 246*8e585f02STsiChung Liew info->rxbd[PKTBUFSRX - 1].cbd_sc = BD_ENET_RX_W_E; 247*8e585f02STsiChung Liew info->rxIdx = 0; 248*8e585f02STsiChung Liew } else { 249*8e585f02STsiChung Liew info->rxbd[info->rxIdx].cbd_sc = BD_ENET_RX_EMPTY; 250*8e585f02STsiChung Liew info->rxIdx++; 251*8e585f02STsiChung Liew } 252*8e585f02STsiChung Liew 253*8e585f02STsiChung Liew /* Try to fill Buffer Descriptors */ 254*8e585f02STsiChung Liew fecp->rdar = 0x01000000; /* Descriptor polling active */ 255*8e585f02STsiChung Liew } 256*8e585f02STsiChung Liew 257*8e585f02STsiChung Liew return length; 258*8e585f02STsiChung Liew } 259*8e585f02STsiChung Liew 260*8e585f02STsiChung Liew /************************************************************** 261*8e585f02STsiChung Liew * 262*8e585f02STsiChung Liew * FEC Ethernet Initialization Routine 263*8e585f02STsiChung Liew * 264*8e585f02STsiChung Liew *************************************************************/ 265*8e585f02STsiChung Liew 266*8e585f02STsiChung Liew #ifdef ET_DEBUG 267*8e585f02STsiChung Liew void dbgFecRegs(struct eth_device *dev) 268*8e585f02STsiChung Liew { 269*8e585f02STsiChung Liew struct fec_info_s *info = dev->priv; 270*8e585f02STsiChung Liew volatile fec_t *fecp = (fec_t *) (info->iobase); 271*8e585f02STsiChung Liew 272*8e585f02STsiChung Liew printf("=====\n"); 273*8e585f02STsiChung Liew printf("ievent %x - %x\n", (int)&fecp->eir, fecp->eir); 274*8e585f02STsiChung Liew printf("imask %x - %x\n", (int)&fecp->eimr, fecp->eimr); 275*8e585f02STsiChung Liew printf("r_des_active %x - %x\n", (int)&fecp->rdar, fecp->rdar); 276*8e585f02STsiChung Liew printf("x_des_active %x - %x\n", (int)&fecp->tdar, fecp->tdar); 277*8e585f02STsiChung Liew printf("ecntrl %x - %x\n", (int)&fecp->ecr, fecp->ecr); 278*8e585f02STsiChung Liew printf("mii_mframe %x - %x\n", (int)&fecp->mmfr, fecp->mmfr); 279*8e585f02STsiChung Liew printf("mii_speed %x - %x\n", (int)&fecp->mscr, fecp->mscr); 280*8e585f02STsiChung Liew printf("mii_ctrlstat %x - %x\n", (int)&fecp->mibc, fecp->mibc); 281*8e585f02STsiChung Liew printf("r_cntrl %x - %x\n", (int)&fecp->rcr, fecp->rcr); 282*8e585f02STsiChung Liew printf("x_cntrl %x - %x\n", (int)&fecp->tcr, fecp->tcr); 283*8e585f02STsiChung Liew printf("padr_l %x - %x\n", (int)&fecp->palr, fecp->palr); 284*8e585f02STsiChung Liew printf("padr_u %x - %x\n", (int)&fecp->paur, fecp->paur); 285*8e585f02STsiChung Liew printf("op_pause %x - %x\n", (int)&fecp->opd, fecp->opd); 286*8e585f02STsiChung Liew printf("iadr_u %x - %x\n", (int)&fecp->iaur, fecp->iaur); 287*8e585f02STsiChung Liew printf("iadr_l %x - %x\n", (int)&fecp->ialr, fecp->ialr); 288*8e585f02STsiChung Liew printf("gadr_u %x - %x\n", (int)&fecp->gaur, fecp->gaur); 289*8e585f02STsiChung Liew printf("gadr_l %x - %x\n", (int)&fecp->galr, fecp->galr); 290*8e585f02STsiChung Liew printf("x_wmrk %x - %x\n", (int)&fecp->tfwr, fecp->tfwr); 291*8e585f02STsiChung Liew printf("r_bound %x - %x\n", (int)&fecp->frbr, fecp->frbr); 292*8e585f02STsiChung Liew printf("r_fstart %x - %x\n", (int)&fecp->frsr, fecp->frsr); 293*8e585f02STsiChung Liew printf("r_drng %x - %x\n", (int)&fecp->erdsr, fecp->erdsr); 294*8e585f02STsiChung Liew printf("x_drng %x - %x\n", (int)&fecp->etdsr, fecp->etdsr); 295*8e585f02STsiChung Liew printf("r_bufsz %x - %x\n", (int)&fecp->emrbr, fecp->emrbr); 296*8e585f02STsiChung Liew 297*8e585f02STsiChung Liew printf("\n"); 298*8e585f02STsiChung Liew printf("rmon_t_drop %x - %x\n", (int)&fecp->rmon_t_drop, 299*8e585f02STsiChung Liew fecp->rmon_t_drop); 300*8e585f02STsiChung Liew printf("rmon_t_packets %x - %x\n", (int)&fecp->rmon_t_packets, 301*8e585f02STsiChung Liew fecp->rmon_t_packets); 302*8e585f02STsiChung Liew printf("rmon_t_bc_pkt %x - %x\n", (int)&fecp->rmon_t_bc_pkt, 303*8e585f02STsiChung Liew fecp->rmon_t_bc_pkt); 304*8e585f02STsiChung Liew printf("rmon_t_mc_pkt %x - %x\n", (int)&fecp->rmon_t_mc_pkt, 305*8e585f02STsiChung Liew fecp->rmon_t_mc_pkt); 306*8e585f02STsiChung Liew printf("rmon_t_crc_align %x - %x\n", (int)&fecp->rmon_t_crc_align, 307*8e585f02STsiChung Liew fecp->rmon_t_crc_align); 308*8e585f02STsiChung Liew printf("rmon_t_undersize %x - %x\n", (int)&fecp->rmon_t_undersize, 309*8e585f02STsiChung Liew fecp->rmon_t_undersize); 310*8e585f02STsiChung Liew printf("rmon_t_oversize %x - %x\n", (int)&fecp->rmon_t_oversize, 311*8e585f02STsiChung Liew fecp->rmon_t_oversize); 312*8e585f02STsiChung Liew printf("rmon_t_frag %x - %x\n", (int)&fecp->rmon_t_frag, 313*8e585f02STsiChung Liew fecp->rmon_t_frag); 314*8e585f02STsiChung Liew printf("rmon_t_jab %x - %x\n", (int)&fecp->rmon_t_jab, 315*8e585f02STsiChung Liew fecp->rmon_t_jab); 316*8e585f02STsiChung Liew printf("rmon_t_col %x - %x\n", (int)&fecp->rmon_t_col, 317*8e585f02STsiChung Liew fecp->rmon_t_col); 318*8e585f02STsiChung Liew printf("rmon_t_p64 %x - %x\n", (int)&fecp->rmon_t_p64, 319*8e585f02STsiChung Liew fecp->rmon_t_p64); 320*8e585f02STsiChung Liew printf("rmon_t_p65to127 %x - %x\n", (int)&fecp->rmon_t_p65to127, 321*8e585f02STsiChung Liew fecp->rmon_t_p65to127); 322*8e585f02STsiChung Liew printf("rmon_t_p128to255 %x - %x\n", (int)&fecp->rmon_t_p128to255, 323*8e585f02STsiChung Liew fecp->rmon_t_p128to255); 324*8e585f02STsiChung Liew printf("rmon_t_p256to511 %x - %x\n", (int)&fecp->rmon_t_p256to511, 325*8e585f02STsiChung Liew fecp->rmon_t_p256to511); 326*8e585f02STsiChung Liew printf("rmon_t_p512to1023 %x - %x\n", (int)&fecp->rmon_t_p512to1023, 327*8e585f02STsiChung Liew fecp->rmon_t_p512to1023); 328*8e585f02STsiChung Liew printf("rmon_t_p1024to2047 %x - %x\n", (int)&fecp->rmon_t_p1024to2047, 329*8e585f02STsiChung Liew fecp->rmon_t_p1024to2047); 330*8e585f02STsiChung Liew printf("rmon_t_p_gte2048 %x - %x\n", (int)&fecp->rmon_t_p_gte2048, 331*8e585f02STsiChung Liew fecp->rmon_t_p_gte2048); 332*8e585f02STsiChung Liew printf("rmon_t_octets %x - %x\n", (int)&fecp->rmon_t_octets, 333*8e585f02STsiChung Liew fecp->rmon_t_octets); 334*8e585f02STsiChung Liew 335*8e585f02STsiChung Liew printf("\n"); 336*8e585f02STsiChung Liew printf("ieee_t_drop %x - %x\n", (int)&fecp->ieee_t_drop, 337*8e585f02STsiChung Liew fecp->ieee_t_drop); 338*8e585f02STsiChung Liew printf("ieee_t_frame_ok %x - %x\n", (int)&fecp->ieee_t_frame_ok, 339*8e585f02STsiChung Liew fecp->ieee_t_frame_ok); 340*8e585f02STsiChung Liew printf("ieee_t_1col %x - %x\n", (int)&fecp->ieee_t_1col, 341*8e585f02STsiChung Liew fecp->ieee_t_1col); 342*8e585f02STsiChung Liew printf("ieee_t_mcol %x - %x\n", (int)&fecp->ieee_t_mcol, 343*8e585f02STsiChung Liew fecp->ieee_t_mcol); 344*8e585f02STsiChung Liew printf("ieee_t_def %x - %x\n", (int)&fecp->ieee_t_def, 345*8e585f02STsiChung Liew fecp->ieee_t_def); 346*8e585f02STsiChung Liew printf("ieee_t_lcol %x - %x\n", (int)&fecp->ieee_t_lcol, 347*8e585f02STsiChung Liew fecp->ieee_t_lcol); 348*8e585f02STsiChung Liew printf("ieee_t_excol %x - %x\n", (int)&fecp->ieee_t_excol, 349*8e585f02STsiChung Liew fecp->ieee_t_excol); 350*8e585f02STsiChung Liew printf("ieee_t_macerr %x - %x\n", (int)&fecp->ieee_t_macerr, 351*8e585f02STsiChung Liew fecp->ieee_t_macerr); 352*8e585f02STsiChung Liew printf("ieee_t_cserr %x - %x\n", (int)&fecp->ieee_t_cserr, 353*8e585f02STsiChung Liew fecp->ieee_t_cserr); 354*8e585f02STsiChung Liew printf("ieee_t_sqe %x - %x\n", (int)&fecp->ieee_t_sqe, 355*8e585f02STsiChung Liew fecp->ieee_t_sqe); 356*8e585f02STsiChung Liew printf("ieee_t_fdxfc %x - %x\n", (int)&fecp->ieee_t_fdxfc, 357*8e585f02STsiChung Liew fecp->ieee_t_fdxfc); 358*8e585f02STsiChung Liew printf("ieee_t_octets_ok %x - %x\n", (int)&fecp->ieee_t_octets_ok, 359*8e585f02STsiChung Liew fecp->ieee_t_octets_ok); 360*8e585f02STsiChung Liew 361*8e585f02STsiChung Liew printf("\n"); 362*8e585f02STsiChung Liew printf("rmon_r_drop %x - %x\n", (int)&fecp->rmon_r_drop, 363*8e585f02STsiChung Liew fecp->rmon_r_drop); 364*8e585f02STsiChung Liew printf("rmon_r_packets %x - %x\n", (int)&fecp->rmon_r_packets, 365*8e585f02STsiChung Liew fecp->rmon_r_packets); 366*8e585f02STsiChung Liew printf("rmon_r_bc_pkt %x - %x\n", (int)&fecp->rmon_r_bc_pkt, 367*8e585f02STsiChung Liew fecp->rmon_r_bc_pkt); 368*8e585f02STsiChung Liew printf("rmon_r_mc_pkt %x - %x\n", (int)&fecp->rmon_r_mc_pkt, 369*8e585f02STsiChung Liew fecp->rmon_r_mc_pkt); 370*8e585f02STsiChung Liew printf("rmon_r_crc_align %x - %x\n", (int)&fecp->rmon_r_crc_align, 371*8e585f02STsiChung Liew fecp->rmon_r_crc_align); 372*8e585f02STsiChung Liew printf("rmon_r_undersize %x - %x\n", (int)&fecp->rmon_r_undersize, 373*8e585f02STsiChung Liew fecp->rmon_r_undersize); 374*8e585f02STsiChung Liew printf("rmon_r_oversize %x - %x\n", (int)&fecp->rmon_r_oversize, 375*8e585f02STsiChung Liew fecp->rmon_r_oversize); 376*8e585f02STsiChung Liew printf("rmon_r_frag %x - %x\n", (int)&fecp->rmon_r_frag, 377*8e585f02STsiChung Liew fecp->rmon_r_frag); 378*8e585f02STsiChung Liew printf("rmon_r_jab %x - %x\n", (int)&fecp->rmon_r_jab, 379*8e585f02STsiChung Liew fecp->rmon_r_jab); 380*8e585f02STsiChung Liew printf("rmon_r_p64 %x - %x\n", (int)&fecp->rmon_r_p64, 381*8e585f02STsiChung Liew fecp->rmon_r_p64); 382*8e585f02STsiChung Liew printf("rmon_r_p65to127 %x - %x\n", (int)&fecp->rmon_r_p65to127, 383*8e585f02STsiChung Liew fecp->rmon_r_p65to127); 384*8e585f02STsiChung Liew printf("rmon_r_p128to255 %x - %x\n", (int)&fecp->rmon_r_p128to255, 385*8e585f02STsiChung Liew fecp->rmon_r_p128to255); 386*8e585f02STsiChung Liew printf("rmon_r_p256to511 %x - %x\n", (int)&fecp->rmon_r_p256to511, 387*8e585f02STsiChung Liew fecp->rmon_r_p256to511); 388*8e585f02STsiChung Liew printf("rmon_r_p512to1023 %x - %x\n", (int)&fecp->rmon_r_p512to1023, 389*8e585f02STsiChung Liew fecp->rmon_r_p512to1023); 390*8e585f02STsiChung Liew printf("rmon_r_p1024to2047 %x - %x\n", (int)&fecp->rmon_r_p1024to2047, 391*8e585f02STsiChung Liew fecp->rmon_r_p1024to2047); 392*8e585f02STsiChung Liew printf("rmon_r_p_gte2048 %x - %x\n", (int)&fecp->rmon_r_p_gte2048, 393*8e585f02STsiChung Liew fecp->rmon_r_p_gte2048); 394*8e585f02STsiChung Liew printf("rmon_r_octets %x - %x\n", (int)&fecp->rmon_r_octets, 395*8e585f02STsiChung Liew fecp->rmon_r_octets); 396*8e585f02STsiChung Liew 397*8e585f02STsiChung Liew printf("\n"); 398*8e585f02STsiChung Liew printf("ieee_r_drop %x - %x\n", (int)&fecp->ieee_r_drop, 399*8e585f02STsiChung Liew fecp->ieee_r_drop); 400*8e585f02STsiChung Liew printf("ieee_r_frame_ok %x - %x\n", (int)&fecp->ieee_r_frame_ok, 401*8e585f02STsiChung Liew fecp->ieee_r_frame_ok); 402*8e585f02STsiChung Liew printf("ieee_r_crc %x - %x\n", (int)&fecp->ieee_r_crc, 403*8e585f02STsiChung Liew fecp->ieee_r_crc); 404*8e585f02STsiChung Liew printf("ieee_r_align %x - %x\n", (int)&fecp->ieee_r_align, 405*8e585f02STsiChung Liew fecp->ieee_r_align); 406*8e585f02STsiChung Liew printf("ieee_r_macerr %x - %x\n", (int)&fecp->ieee_r_macerr, 407*8e585f02STsiChung Liew fecp->ieee_r_macerr); 408*8e585f02STsiChung Liew printf("ieee_r_fdxfc %x - %x\n", (int)&fecp->ieee_r_fdxfc, 409*8e585f02STsiChung Liew fecp->ieee_r_fdxfc); 410*8e585f02STsiChung Liew printf("ieee_r_octets_ok %x - %x\n", (int)&fecp->ieee_r_octets_ok, 411*8e585f02STsiChung Liew fecp->ieee_r_octets_ok); 412*8e585f02STsiChung Liew 413*8e585f02STsiChung Liew printf("\n\n\n"); 414*8e585f02STsiChung Liew } 415*8e585f02STsiChung Liew #endif 416*8e585f02STsiChung Liew 417*8e585f02STsiChung Liew int fec_init(struct eth_device *dev, bd_t * bd) 418*8e585f02STsiChung Liew { 419*8e585f02STsiChung Liew struct fec_info_s *info = dev->priv; 420*8e585f02STsiChung Liew volatile fec_t *fecp = (fec_t *) (info->iobase); 421*8e585f02STsiChung Liew int i; 422*8e585f02STsiChung Liew u8 *ea; 423*8e585f02STsiChung Liew 424*8e585f02STsiChung Liew fecpin_setclear(dev, 1); 425*8e585f02STsiChung Liew 426*8e585f02STsiChung Liew fec_reset(dev); 427*8e585f02STsiChung Liew 428*8e585f02STsiChung Liew #if (CONFIG_COMMANDS & CFG_CMD_MII) || defined (CONFIG_MII) || \ 429*8e585f02STsiChung Liew defined (CFG_DISCOVER_PHY) 430*8e585f02STsiChung Liew 431*8e585f02STsiChung Liew mii_init(); 432*8e585f02STsiChung Liew 433*8e585f02STsiChung Liew setFecDuplexSpeed(fecp, bd, info->dup_spd); 434*8e585f02STsiChung Liew #else 435*8e585f02STsiChung Liew #ifndef CFG_DISCOVER_PHY 436*8e585f02STsiChung Liew setFecDuplexSpeed(fecp, bd, (FECDUPLEX << 16) | FECSPEED); 437*8e585f02STsiChung Liew #endif /* ifndef CFG_DISCOVER_PHY */ 438*8e585f02STsiChung Liew #endif /* CFG_CMD_MII || CONFIG_MII */ 439*8e585f02STsiChung Liew 440*8e585f02STsiChung Liew /* We use strictly polling mode only */ 441*8e585f02STsiChung Liew fecp->eimr = 0; 442*8e585f02STsiChung Liew 443*8e585f02STsiChung Liew /* Clear any pending interrupt */ 444*8e585f02STsiChung Liew fecp->eir = 0xffffffff; 445*8e585f02STsiChung Liew 446*8e585f02STsiChung Liew /* Set station address */ 447*8e585f02STsiChung Liew if ((u32) fecp == CFG_FEC0_IOBASE) { 448*8e585f02STsiChung Liew ea = &bd->bi_enetaddr[0]; 449*8e585f02STsiChung Liew } else { 450*8e585f02STsiChung Liew #ifdef CFG_FEC1_IOBASE 451*8e585f02STsiChung Liew ea = &bd->bi_enet1addr[0]; 452*8e585f02STsiChung Liew #endif 453*8e585f02STsiChung Liew } 454*8e585f02STsiChung Liew 455*8e585f02STsiChung Liew fecp->palr = (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]); 456*8e585f02STsiChung Liew fecp->paur = (ea[4] << 24) | (ea[5] << 16); 457*8e585f02STsiChung Liew #ifdef ET_DEBUG 458*8e585f02STsiChung Liew printf("Eth Addrs: %02x:%02x:%02x:%02x:%02x:%02x\n", 459*8e585f02STsiChung Liew ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]); 460*8e585f02STsiChung Liew #endif 461*8e585f02STsiChung Liew 462*8e585f02STsiChung Liew /* Clear unicast address hash table */ 463*8e585f02STsiChung Liew fecp->iaur = 0; 464*8e585f02STsiChung Liew fecp->ialr = 0; 465*8e585f02STsiChung Liew 466*8e585f02STsiChung Liew /* Clear multicast address hash table */ 467*8e585f02STsiChung Liew fecp->gaur = 0; 468*8e585f02STsiChung Liew fecp->galr = 0; 469*8e585f02STsiChung Liew 470*8e585f02STsiChung Liew /* Set maximum receive buffer size. */ 471*8e585f02STsiChung Liew fecp->emrbr = PKT_MAXBLR_SIZE; 472*8e585f02STsiChung Liew 473*8e585f02STsiChung Liew /* 474*8e585f02STsiChung Liew * Setup Buffers and Buffer Desriptors 475*8e585f02STsiChung Liew */ 476*8e585f02STsiChung Liew info->rxIdx = 0; 477*8e585f02STsiChung Liew info->txIdx = 0; 478*8e585f02STsiChung Liew 479*8e585f02STsiChung Liew /* 480*8e585f02STsiChung Liew * Setup Receiver Buffer Descriptors (13.14.24.18) 481*8e585f02STsiChung Liew * Settings: 482*8e585f02STsiChung Liew * Empty, Wrap 483*8e585f02STsiChung Liew */ 484*8e585f02STsiChung Liew for (i = 0; i < PKTBUFSRX; i++) { 485*8e585f02STsiChung Liew info->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY; 486*8e585f02STsiChung Liew info->rxbd[i].cbd_datlen = 0; /* Reset */ 487*8e585f02STsiChung Liew info->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i]; 488*8e585f02STsiChung Liew } 489*8e585f02STsiChung Liew info->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP; 490*8e585f02STsiChung Liew 491*8e585f02STsiChung Liew /* 492*8e585f02STsiChung Liew * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19) 493*8e585f02STsiChung Liew * Settings: 494*8e585f02STsiChung Liew * Last, Tx CRC 495*8e585f02STsiChung Liew */ 496*8e585f02STsiChung Liew for (i = 0; i < TX_BUF_CNT; i++) { 497*8e585f02STsiChung Liew info->txbd[i].cbd_sc = BD_ENET_TX_LAST | BD_ENET_TX_TC; 498*8e585f02STsiChung Liew info->txbd[i].cbd_datlen = 0; /* Reset */ 499*8e585f02STsiChung Liew info->txbd[i].cbd_bufaddr = (uint) (&info->txbuf[0]); 500*8e585f02STsiChung Liew } 501*8e585f02STsiChung Liew info->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP; 502*8e585f02STsiChung Liew 503*8e585f02STsiChung Liew /* Set receive and transmit descriptor base */ 504*8e585f02STsiChung Liew fecp->erdsr = (unsigned int)(&info->rxbd[0]); 505*8e585f02STsiChung Liew fecp->etdsr = (unsigned int)(&info->txbd[0]); 506*8e585f02STsiChung Liew 507*8e585f02STsiChung Liew /* Now enable the transmit and receive processing */ 508*8e585f02STsiChung Liew fecp->ecr |= FEC_ECR_ETHER_EN; 509*8e585f02STsiChung Liew 510*8e585f02STsiChung Liew /* And last, try to fill Rx Buffer Descriptors */ 511*8e585f02STsiChung Liew fecp->rdar = 0x01000000; /* Descriptor polling active */ 512*8e585f02STsiChung Liew 513*8e585f02STsiChung Liew return 1; 514*8e585f02STsiChung Liew } 515*8e585f02STsiChung Liew 516*8e585f02STsiChung Liew void fec_reset(struct eth_device *dev) 517*8e585f02STsiChung Liew { 518*8e585f02STsiChung Liew struct fec_info_s *info = dev->priv; 519*8e585f02STsiChung Liew volatile fec_t *fecp = (fec_t *) (info->iobase); 520*8e585f02STsiChung Liew int i; 521*8e585f02STsiChung Liew 522*8e585f02STsiChung Liew fecp->ecr = FEC_ECR_RESET; 523*8e585f02STsiChung Liew for (i = 0; (fecp->ecr & FEC_ECR_RESET) && (i < FEC_RESET_DELAY); ++i) { 524*8e585f02STsiChung Liew udelay(1); 525*8e585f02STsiChung Liew } 526*8e585f02STsiChung Liew if (i == FEC_RESET_DELAY) { 527*8e585f02STsiChung Liew printf("FEC_RESET_DELAY timeout\n"); 528*8e585f02STsiChung Liew } 529*8e585f02STsiChung Liew } 530*8e585f02STsiChung Liew 531*8e585f02STsiChung Liew void fec_halt(struct eth_device *dev) 532*8e585f02STsiChung Liew { 533*8e585f02STsiChung Liew struct fec_info_s *info = dev->priv; 534*8e585f02STsiChung Liew 535*8e585f02STsiChung Liew fec_reset(dev); 536*8e585f02STsiChung Liew 537*8e585f02STsiChung Liew fecpin_setclear(dev, 0); 538*8e585f02STsiChung Liew 539*8e585f02STsiChung Liew info->rxIdx = info->txIdx = 0; 540*8e585f02STsiChung Liew memset(info->rxbd, 0, PKTBUFSRX * sizeof(cbd_t)); 541*8e585f02STsiChung Liew memset(info->txbd, 0, TX_BUF_CNT * sizeof(cbd_t)); 542*8e585f02STsiChung Liew memset(info->txbuf, 0, DBUF_LENGTH); 543*8e585f02STsiChung Liew } 544*8e585f02STsiChung Liew 545*8e585f02STsiChung Liew int mcffec_initialize(bd_t * bis) 546*8e585f02STsiChung Liew { 547*8e585f02STsiChung Liew struct eth_device *dev; 548*8e585f02STsiChung Liew int i; 549*8e585f02STsiChung Liew 550*8e585f02STsiChung Liew for (i = 0; i < sizeof(fec_info) / sizeof(fec_info[0]); i++) { 551*8e585f02STsiChung Liew 552*8e585f02STsiChung Liew dev = (struct eth_device *)malloc(sizeof *dev); 553*8e585f02STsiChung Liew if (dev == NULL) 554*8e585f02STsiChung Liew hang(); 555*8e585f02STsiChung Liew 556*8e585f02STsiChung Liew memset(dev, 0, sizeof(*dev)); 557*8e585f02STsiChung Liew 558*8e585f02STsiChung Liew sprintf(dev->name, "FEC%d", fec_info[i].index); 559*8e585f02STsiChung Liew 560*8e585f02STsiChung Liew dev->priv = &fec_info[i]; 561*8e585f02STsiChung Liew dev->init = fec_init; 562*8e585f02STsiChung Liew dev->halt = fec_halt; 563*8e585f02STsiChung Liew dev->send = fec_send; 564*8e585f02STsiChung Liew dev->recv = fec_recv; 565*8e585f02STsiChung Liew 566*8e585f02STsiChung Liew /* setup Receive and Transmit buffer descriptor */ 567*8e585f02STsiChung Liew fec_info[i].rxbd = 568*8e585f02STsiChung Liew (cbd_t *) memalign(32, (PKTBUFSRX * sizeof(cbd_t) + 31)); 569*8e585f02STsiChung Liew fec_info[i].txbd = 570*8e585f02STsiChung Liew (cbd_t *) memalign(32, (TX_BUF_CNT * sizeof(cbd_t) + 31)); 571*8e585f02STsiChung Liew fec_info[i].txbuf = (char *)memalign(32, DBUF_LENGTH + 31); 572*8e585f02STsiChung Liew #ifdef ET_DEBUG 573*8e585f02STsiChung Liew printf("rxbd %x txbd %x\n", 574*8e585f02STsiChung Liew (int)fec_info[i].rxbd, (int)fec_info[i].txbd); 575*8e585f02STsiChung Liew #endif 576*8e585f02STsiChung Liew 577*8e585f02STsiChung Liew fec_info[i].phy_name = (char *)malloc(32); 578*8e585f02STsiChung Liew 579*8e585f02STsiChung Liew eth_register(dev); 580*8e585f02STsiChung Liew 581*8e585f02STsiChung Liew #if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) 582*8e585f02STsiChung Liew miiphy_register(dev->name, 583*8e585f02STsiChung Liew mcffec_miiphy_read, mcffec_miiphy_write); 584*8e585f02STsiChung Liew #endif 585*8e585f02STsiChung Liew } 586*8e585f02STsiChung Liew 587*8e585f02STsiChung Liew /* default speed */ 588*8e585f02STsiChung Liew bis->bi_ethspeed = 10; 589*8e585f02STsiChung Liew 590*8e585f02STsiChung Liew return 1; 591*8e585f02STsiChung Liew } 592*8e585f02STsiChung Liew 593*8e585f02STsiChung Liew #endif /* CFG_CMD_NET, FEC_ENET & NET_MULTI */ 594*8e585f02STsiChung Liew #endif /* CONFIG_MCFFEC */ 595