1*a47a12beSStefan Roese /* 2*a47a12beSStefan Roese * MPC8560 FCC Fast Ethernet 3*a47a12beSStefan Roese * Copyright (c) 2003 Motorola,Inc. 4*a47a12beSStefan Roese * Xianghua Xiao, (X.Xiao@motorola.com) 5*a47a12beSStefan Roese * 6*a47a12beSStefan Roese * Copyright (c) 2000 MontaVista Software, Inc. Dan Malek (dmalek@jlc.net) 7*a47a12beSStefan Roese * 8*a47a12beSStefan Roese * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com> 9*a47a12beSStefan Roese * Marius Groeger <mgroeger@sysgo.de> 10*a47a12beSStefan Roese * 11*a47a12beSStefan Roese * See file CREDITS for list of people who contributed to this 12*a47a12beSStefan Roese * project. 13*a47a12beSStefan Roese * 14*a47a12beSStefan Roese * This program is free software; you can redistribute it and/or 15*a47a12beSStefan Roese * modify it under the terms of the GNU General Public License as 16*a47a12beSStefan Roese * published by the Free Software Foundation; either version 2 of 17*a47a12beSStefan Roese * the License, or (at your option) any later version. 18*a47a12beSStefan Roese * 19*a47a12beSStefan Roese * This program is distributed in the hope that it will be useful, 20*a47a12beSStefan Roese * but WITHOUT ANY WARRANTY; without even the implied warranty of 21*a47a12beSStefan Roese * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22*a47a12beSStefan Roese * GNU General Public License for more details. 23*a47a12beSStefan Roese * 24*a47a12beSStefan Roese * You should have received a copy of the GNU General Public License 25*a47a12beSStefan Roese * along with this program; if not, write to the Free Software 26*a47a12beSStefan Roese * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 27*a47a12beSStefan Roese * MA 02111-1307 USA 28*a47a12beSStefan Roese */ 29*a47a12beSStefan Roese 30*a47a12beSStefan Roese /* 31*a47a12beSStefan Roese * MPC8560 FCC Fast Ethernet 32*a47a12beSStefan Roese * Basic ET HW initialization and packet RX/TX routines 33*a47a12beSStefan Roese * 34*a47a12beSStefan Roese * This code will not perform the IO port configuration. This should be 35*a47a12beSStefan Roese * done in the iop_conf_t structure specific for the board. 36*a47a12beSStefan Roese * 37*a47a12beSStefan Roese * TODO: 38*a47a12beSStefan Roese * add a PHY driver to do the negotiation 39*a47a12beSStefan Roese * reflect negotiation results in FPSMR 40*a47a12beSStefan Roese * look for ways to configure the board specific stuff elsewhere, eg. 41*a47a12beSStefan Roese * config_xxx.h or the board directory 42*a47a12beSStefan Roese */ 43*a47a12beSStefan Roese 44*a47a12beSStefan Roese #include <common.h> 45*a47a12beSStefan Roese #include <malloc.h> 46*a47a12beSStefan Roese #include <asm/cpm_85xx.h> 47*a47a12beSStefan Roese #include <command.h> 48*a47a12beSStefan Roese #include <config.h> 49*a47a12beSStefan Roese #include <net.h> 50*a47a12beSStefan Roese 51*a47a12beSStefan Roese #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) 52*a47a12beSStefan Roese #include <miiphy.h> 53*a47a12beSStefan Roese #endif 54*a47a12beSStefan Roese 55*a47a12beSStefan Roese #if defined(CONFIG_ETHER_ON_FCC) && defined(CONFIG_CMD_NET) && \ 56*a47a12beSStefan Roese defined(CONFIG_NET_MULTI) 57*a47a12beSStefan Roese 58*a47a12beSStefan Roese static struct ether_fcc_info_s 59*a47a12beSStefan Roese { 60*a47a12beSStefan Roese int ether_index; 61*a47a12beSStefan Roese int proff_enet; 62*a47a12beSStefan Roese ulong cpm_cr_enet_sblock; 63*a47a12beSStefan Roese ulong cpm_cr_enet_page; 64*a47a12beSStefan Roese ulong cmxfcr_mask; 65*a47a12beSStefan Roese ulong cmxfcr_value; 66*a47a12beSStefan Roese } 67*a47a12beSStefan Roese ether_fcc_info[] = 68*a47a12beSStefan Roese { 69*a47a12beSStefan Roese #ifdef CONFIG_ETHER_ON_FCC1 70*a47a12beSStefan Roese { 71*a47a12beSStefan Roese 0, 72*a47a12beSStefan Roese PROFF_FCC1, 73*a47a12beSStefan Roese CPM_CR_FCC1_SBLOCK, 74*a47a12beSStefan Roese CPM_CR_FCC1_PAGE, 75*a47a12beSStefan Roese CONFIG_SYS_CMXFCR_MASK1, 76*a47a12beSStefan Roese CONFIG_SYS_CMXFCR_VALUE1 77*a47a12beSStefan Roese }, 78*a47a12beSStefan Roese #endif 79*a47a12beSStefan Roese 80*a47a12beSStefan Roese #ifdef CONFIG_ETHER_ON_FCC2 81*a47a12beSStefan Roese { 82*a47a12beSStefan Roese 1, 83*a47a12beSStefan Roese PROFF_FCC2, 84*a47a12beSStefan Roese CPM_CR_FCC2_SBLOCK, 85*a47a12beSStefan Roese CPM_CR_FCC2_PAGE, 86*a47a12beSStefan Roese CONFIG_SYS_CMXFCR_MASK2, 87*a47a12beSStefan Roese CONFIG_SYS_CMXFCR_VALUE2 88*a47a12beSStefan Roese }, 89*a47a12beSStefan Roese #endif 90*a47a12beSStefan Roese 91*a47a12beSStefan Roese #ifdef CONFIG_ETHER_ON_FCC3 92*a47a12beSStefan Roese { 93*a47a12beSStefan Roese 2, 94*a47a12beSStefan Roese PROFF_FCC3, 95*a47a12beSStefan Roese CPM_CR_FCC3_SBLOCK, 96*a47a12beSStefan Roese CPM_CR_FCC3_PAGE, 97*a47a12beSStefan Roese CONFIG_SYS_CMXFCR_MASK3, 98*a47a12beSStefan Roese CONFIG_SYS_CMXFCR_VALUE3 99*a47a12beSStefan Roese }, 100*a47a12beSStefan Roese #endif 101*a47a12beSStefan Roese }; 102*a47a12beSStefan Roese 103*a47a12beSStefan Roese /*---------------------------------------------------------------------*/ 104*a47a12beSStefan Roese 105*a47a12beSStefan Roese /* Maximum input DMA size. Must be a should(?) be a multiple of 4. */ 106*a47a12beSStefan Roese #define PKT_MAXDMA_SIZE 1520 107*a47a12beSStefan Roese 108*a47a12beSStefan Roese /* The FCC stores dest/src/type, data, and checksum for receive packets. */ 109*a47a12beSStefan Roese #define PKT_MAXBUF_SIZE 1518 110*a47a12beSStefan Roese #define PKT_MINBUF_SIZE 64 111*a47a12beSStefan Roese 112*a47a12beSStefan Roese /* Maximum input buffer size. Must be a multiple of 32. */ 113*a47a12beSStefan Roese #define PKT_MAXBLR_SIZE 1536 114*a47a12beSStefan Roese 115*a47a12beSStefan Roese #define TOUT_LOOP 1000000 116*a47a12beSStefan Roese 117*a47a12beSStefan Roese #define TX_BUF_CNT 2 118*a47a12beSStefan Roese 119*a47a12beSStefan Roese static uint rxIdx; /* index of the current RX buffer */ 120*a47a12beSStefan Roese static uint txIdx; /* index of the current TX buffer */ 121*a47a12beSStefan Roese 122*a47a12beSStefan Roese /* 123*a47a12beSStefan Roese * FCC Ethernet Tx and Rx buffer descriptors. 124*a47a12beSStefan Roese * Provide for Double Buffering 125*a47a12beSStefan Roese * Note: PKTBUFSRX is defined in net.h 126*a47a12beSStefan Roese */ 127*a47a12beSStefan Roese 128*a47a12beSStefan Roese typedef volatile struct rtxbd { 129*a47a12beSStefan Roese cbd_t rxbd[PKTBUFSRX]; 130*a47a12beSStefan Roese cbd_t txbd[TX_BUF_CNT]; 131*a47a12beSStefan Roese } RTXBD; 132*a47a12beSStefan Roese 133*a47a12beSStefan Roese /* Good news: the FCC supports external BDs! */ 134*a47a12beSStefan Roese #ifdef __GNUC__ 135*a47a12beSStefan Roese static RTXBD rtx __attribute__ ((aligned(8))); 136*a47a12beSStefan Roese #else 137*a47a12beSStefan Roese #error "rtx must be 64-bit aligned" 138*a47a12beSStefan Roese #endif 139*a47a12beSStefan Roese 140*a47a12beSStefan Roese #undef ET_DEBUG 141*a47a12beSStefan Roese 142*a47a12beSStefan Roese static int fec_send(struct eth_device* dev, volatile void *packet, int length) 143*a47a12beSStefan Roese { 144*a47a12beSStefan Roese int i = 0; 145*a47a12beSStefan Roese int result = 0; 146*a47a12beSStefan Roese 147*a47a12beSStefan Roese if (length <= 0) { 148*a47a12beSStefan Roese printf("fec: bad packet size: %d\n", length); 149*a47a12beSStefan Roese goto out; 150*a47a12beSStefan Roese } 151*a47a12beSStefan Roese 152*a47a12beSStefan Roese for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) { 153*a47a12beSStefan Roese if (i >= TOUT_LOOP) { 154*a47a12beSStefan Roese printf("fec: tx buffer not ready\n"); 155*a47a12beSStefan Roese goto out; 156*a47a12beSStefan Roese } 157*a47a12beSStefan Roese } 158*a47a12beSStefan Roese 159*a47a12beSStefan Roese rtx.txbd[txIdx].cbd_bufaddr = (uint)packet; 160*a47a12beSStefan Roese rtx.txbd[txIdx].cbd_datlen = length; 161*a47a12beSStefan Roese rtx.txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST | \ 162*a47a12beSStefan Roese BD_ENET_TX_TC | BD_ENET_TX_PAD); 163*a47a12beSStefan Roese 164*a47a12beSStefan Roese for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) { 165*a47a12beSStefan Roese if (i >= TOUT_LOOP) { 166*a47a12beSStefan Roese printf("fec: tx error\n"); 167*a47a12beSStefan Roese goto out; 168*a47a12beSStefan Roese } 169*a47a12beSStefan Roese } 170*a47a12beSStefan Roese 171*a47a12beSStefan Roese #ifdef ET_DEBUG 172*a47a12beSStefan Roese printf("cycles: 0x%x txIdx=0x%04x status: 0x%04x\n", i, txIdx,rtx.txbd[txIdx].cbd_sc); 173*a47a12beSStefan Roese printf("packets at 0x%08x, length_in_bytes=0x%x\n",(uint)packet,length); 174*a47a12beSStefan Roese for(i=0;i<(length/16 + 1);i++) { 175*a47a12beSStefan Roese printf("%08x %08x %08x %08x\n",*((uint *)rtx.txbd[txIdx].cbd_bufaddr+i*4),\ 176*a47a12beSStefan Roese *((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 1),*((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 2), \ 177*a47a12beSStefan Roese *((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 3)); 178*a47a12beSStefan Roese } 179*a47a12beSStefan Roese #endif 180*a47a12beSStefan Roese 181*a47a12beSStefan Roese /* return only status bits */ 182*a47a12beSStefan Roese result = rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_STATS; 183*a47a12beSStefan Roese txIdx = (txIdx + 1) % TX_BUF_CNT; 184*a47a12beSStefan Roese 185*a47a12beSStefan Roese out: 186*a47a12beSStefan Roese return result; 187*a47a12beSStefan Roese } 188*a47a12beSStefan Roese 189*a47a12beSStefan Roese static int fec_recv(struct eth_device* dev) 190*a47a12beSStefan Roese { 191*a47a12beSStefan Roese int length; 192*a47a12beSStefan Roese 193*a47a12beSStefan Roese for (;;) 194*a47a12beSStefan Roese { 195*a47a12beSStefan Roese if (rtx.rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) { 196*a47a12beSStefan Roese length = -1; 197*a47a12beSStefan Roese break; /* nothing received - leave for() loop */ 198*a47a12beSStefan Roese } 199*a47a12beSStefan Roese length = rtx.rxbd[rxIdx].cbd_datlen; 200*a47a12beSStefan Roese 201*a47a12beSStefan Roese if (rtx.rxbd[rxIdx].cbd_sc & 0x003f) { 202*a47a12beSStefan Roese printf("fec: rx error %04x\n", rtx.rxbd[rxIdx].cbd_sc); 203*a47a12beSStefan Roese } 204*a47a12beSStefan Roese else { 205*a47a12beSStefan Roese /* Pass the packet up to the protocol layers. */ 206*a47a12beSStefan Roese NetReceive(NetRxPackets[rxIdx], length - 4); 207*a47a12beSStefan Roese } 208*a47a12beSStefan Roese 209*a47a12beSStefan Roese 210*a47a12beSStefan Roese /* Give the buffer back to the FCC. */ 211*a47a12beSStefan Roese rtx.rxbd[rxIdx].cbd_datlen = 0; 212*a47a12beSStefan Roese 213*a47a12beSStefan Roese /* wrap around buffer index when necessary */ 214*a47a12beSStefan Roese if ((rxIdx + 1) >= PKTBUFSRX) { 215*a47a12beSStefan Roese rtx.rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY); 216*a47a12beSStefan Roese rxIdx = 0; 217*a47a12beSStefan Roese } 218*a47a12beSStefan Roese else { 219*a47a12beSStefan Roese rtx.rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY; 220*a47a12beSStefan Roese rxIdx++; 221*a47a12beSStefan Roese } 222*a47a12beSStefan Roese } 223*a47a12beSStefan Roese return length; 224*a47a12beSStefan Roese } 225*a47a12beSStefan Roese 226*a47a12beSStefan Roese 227*a47a12beSStefan Roese static int fec_init(struct eth_device* dev, bd_t *bis) 228*a47a12beSStefan Roese { 229*a47a12beSStefan Roese struct ether_fcc_info_s * info = dev->priv; 230*a47a12beSStefan Roese int i; 231*a47a12beSStefan Roese volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR; 232*a47a12beSStefan Roese volatile ccsr_cpm_cp_t *cp = &(cpm->im_cpm_cp); 233*a47a12beSStefan Roese fcc_enet_t *pram_ptr; 234*a47a12beSStefan Roese unsigned long mem_addr; 235*a47a12beSStefan Roese 236*a47a12beSStefan Roese #if 0 237*a47a12beSStefan Roese mii_discover_phy(); 238*a47a12beSStefan Roese #endif 239*a47a12beSStefan Roese 240*a47a12beSStefan Roese /* 28.9 - (1-2): ioports have been set up already */ 241*a47a12beSStefan Roese 242*a47a12beSStefan Roese /* 28.9 - (3): connect FCC's tx and rx clocks */ 243*a47a12beSStefan Roese cpm->im_cpm_mux.cmxuar = 0; /* ATM */ 244*a47a12beSStefan Roese cpm->im_cpm_mux.cmxfcr = (cpm->im_cpm_mux.cmxfcr & ~info->cmxfcr_mask) | 245*a47a12beSStefan Roese info->cmxfcr_value; 246*a47a12beSStefan Roese 247*a47a12beSStefan Roese /* 28.9 - (4): GFMR: disable tx/rx, CCITT CRC, set Mode Ethernet */ 248*a47a12beSStefan Roese if(info->ether_index == 0) { 249*a47a12beSStefan Roese cpm->im_cpm_fcc1.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32; 250*a47a12beSStefan Roese } else if (info->ether_index == 1) { 251*a47a12beSStefan Roese cpm->im_cpm_fcc2.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32; 252*a47a12beSStefan Roese } else if (info->ether_index == 2) { 253*a47a12beSStefan Roese cpm->im_cpm_fcc3.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32; 254*a47a12beSStefan Roese } 255*a47a12beSStefan Roese 256*a47a12beSStefan Roese /* 28.9 - (5): FPSMR: enable full duplex, select CCITT CRC for Ethernet,MII */ 257*a47a12beSStefan Roese if(info->ether_index == 0) { 258*a47a12beSStefan Roese cpm->im_cpm_fcc1.fpsmr = CONFIG_SYS_FCC_PSMR | FCC_PSMR_ENCRC; 259*a47a12beSStefan Roese } else if (info->ether_index == 1){ 260*a47a12beSStefan Roese cpm->im_cpm_fcc2.fpsmr = CONFIG_SYS_FCC_PSMR | FCC_PSMR_ENCRC; 261*a47a12beSStefan Roese } else if (info->ether_index == 2){ 262*a47a12beSStefan Roese cpm->im_cpm_fcc3.fpsmr = CONFIG_SYS_FCC_PSMR | FCC_PSMR_ENCRC; 263*a47a12beSStefan Roese } 264*a47a12beSStefan Roese 265*a47a12beSStefan Roese /* 28.9 - (6): FDSR: Ethernet Syn */ 266*a47a12beSStefan Roese if(info->ether_index == 0) { 267*a47a12beSStefan Roese cpm->im_cpm_fcc1.fdsr = 0xD555; 268*a47a12beSStefan Roese } else if (info->ether_index == 1) { 269*a47a12beSStefan Roese cpm->im_cpm_fcc2.fdsr = 0xD555; 270*a47a12beSStefan Roese } else if (info->ether_index == 2) { 271*a47a12beSStefan Roese cpm->im_cpm_fcc3.fdsr = 0xD555; 272*a47a12beSStefan Roese } 273*a47a12beSStefan Roese 274*a47a12beSStefan Roese /* reset indeces to current rx/tx bd (see eth_send()/eth_rx()) */ 275*a47a12beSStefan Roese rxIdx = 0; 276*a47a12beSStefan Roese txIdx = 0; 277*a47a12beSStefan Roese 278*a47a12beSStefan Roese /* Setup Receiver Buffer Descriptors */ 279*a47a12beSStefan Roese for (i = 0; i < PKTBUFSRX; i++) 280*a47a12beSStefan Roese { 281*a47a12beSStefan Roese rtx.rxbd[i].cbd_sc = BD_ENET_RX_EMPTY; 282*a47a12beSStefan Roese rtx.rxbd[i].cbd_datlen = 0; 283*a47a12beSStefan Roese rtx.rxbd[i].cbd_bufaddr = (uint)NetRxPackets[i]; 284*a47a12beSStefan Roese } 285*a47a12beSStefan Roese rtx.rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP; 286*a47a12beSStefan Roese 287*a47a12beSStefan Roese /* Setup Ethernet Transmitter Buffer Descriptors */ 288*a47a12beSStefan Roese for (i = 0; i < TX_BUF_CNT; i++) 289*a47a12beSStefan Roese { 290*a47a12beSStefan Roese rtx.txbd[i].cbd_sc = 0; 291*a47a12beSStefan Roese rtx.txbd[i].cbd_datlen = 0; 292*a47a12beSStefan Roese rtx.txbd[i].cbd_bufaddr = 0; 293*a47a12beSStefan Roese } 294*a47a12beSStefan Roese rtx.txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP; 295*a47a12beSStefan Roese 296*a47a12beSStefan Roese /* 28.9 - (7): initialize parameter ram */ 297*a47a12beSStefan Roese pram_ptr = (fcc_enet_t *)&(cpm->im_dprambase[info->proff_enet]); 298*a47a12beSStefan Roese 299*a47a12beSStefan Roese /* clear whole structure to make sure all reserved fields are zero */ 300*a47a12beSStefan Roese memset((void*)pram_ptr, 0, sizeof(fcc_enet_t)); 301*a47a12beSStefan Roese 302*a47a12beSStefan Roese /* 303*a47a12beSStefan Roese * common Parameter RAM area 304*a47a12beSStefan Roese * 305*a47a12beSStefan Roese * Allocate space in the reserved FCC area of DPRAM for the 306*a47a12beSStefan Roese * internal buffers. No one uses this space (yet), so we 307*a47a12beSStefan Roese * can do this. Later, we will add resource management for 308*a47a12beSStefan Roese * this area. 309*a47a12beSStefan Roese * CPM_FCC_SPECIAL_BASE: 0xB000 for MPC8540, MPC8560 310*a47a12beSStefan Roese * 0x9000 for MPC8541, MPC8555 311*a47a12beSStefan Roese */ 312*a47a12beSStefan Roese mem_addr = CPM_FCC_SPECIAL_BASE + ((info->ether_index) * 64); 313*a47a12beSStefan Roese pram_ptr->fen_genfcc.fcc_riptr = mem_addr; 314*a47a12beSStefan Roese pram_ptr->fen_genfcc.fcc_tiptr = mem_addr+32; 315*a47a12beSStefan Roese /* 316*a47a12beSStefan Roese * Set maximum bytes per receive buffer. 317*a47a12beSStefan Roese * It must be a multiple of 32. 318*a47a12beSStefan Roese */ 319*a47a12beSStefan Roese pram_ptr->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE; /* 1536 */ 320*a47a12beSStefan Roese /* localbus SDRAM should be preferred */ 321*a47a12beSStefan Roese pram_ptr->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB | 322*a47a12beSStefan Roese CONFIG_SYS_CPMFCR_RAMTYPE) << 24; 323*a47a12beSStefan Roese pram_ptr->fen_genfcc.fcc_rbase = (unsigned int)(&rtx.rxbd[rxIdx]); 324*a47a12beSStefan Roese pram_ptr->fen_genfcc.fcc_rbdstat = 0; 325*a47a12beSStefan Roese pram_ptr->fen_genfcc.fcc_rbdlen = 0; 326*a47a12beSStefan Roese pram_ptr->fen_genfcc.fcc_rdptr = 0; 327*a47a12beSStefan Roese /* localbus SDRAM should be preferred */ 328*a47a12beSStefan Roese pram_ptr->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB | 329*a47a12beSStefan Roese CONFIG_SYS_CPMFCR_RAMTYPE) << 24; 330*a47a12beSStefan Roese pram_ptr->fen_genfcc.fcc_tbase = (unsigned int)(&rtx.txbd[txIdx]); 331*a47a12beSStefan Roese pram_ptr->fen_genfcc.fcc_tbdstat = 0; 332*a47a12beSStefan Roese pram_ptr->fen_genfcc.fcc_tbdlen = 0; 333*a47a12beSStefan Roese pram_ptr->fen_genfcc.fcc_tdptr = 0; 334*a47a12beSStefan Roese 335*a47a12beSStefan Roese /* protocol-specific area */ 336*a47a12beSStefan Roese pram_ptr->fen_statbuf = 0x0; 337*a47a12beSStefan Roese pram_ptr->fen_cmask = 0xdebb20e3; /* CRC mask */ 338*a47a12beSStefan Roese pram_ptr->fen_cpres = 0xffffffff; /* CRC preset */ 339*a47a12beSStefan Roese pram_ptr->fen_crcec = 0; 340*a47a12beSStefan Roese pram_ptr->fen_alec = 0; 341*a47a12beSStefan Roese pram_ptr->fen_disfc = 0; 342*a47a12beSStefan Roese pram_ptr->fen_retlim = 15; /* Retry limit threshold */ 343*a47a12beSStefan Roese pram_ptr->fen_retcnt = 0; 344*a47a12beSStefan Roese pram_ptr->fen_pper = 0; 345*a47a12beSStefan Roese pram_ptr->fen_boffcnt = 0; 346*a47a12beSStefan Roese pram_ptr->fen_gaddrh = 0; 347*a47a12beSStefan Roese pram_ptr->fen_gaddrl = 0; 348*a47a12beSStefan Roese pram_ptr->fen_mflr = PKT_MAXBUF_SIZE; /* maximum frame length register */ 349*a47a12beSStefan Roese /* 350*a47a12beSStefan Roese * Set Ethernet station address. 351*a47a12beSStefan Roese * 352*a47a12beSStefan Roese * This is supplied in the board information structure, so we 353*a47a12beSStefan Roese * copy that into the controller. 354*a47a12beSStefan Roese * So far we have only been given one Ethernet address. We make 355*a47a12beSStefan Roese * it unique by setting a few bits in the upper byte of the 356*a47a12beSStefan Roese * non-static part of the address. 357*a47a12beSStefan Roese */ 358*a47a12beSStefan Roese #define ea eth_get_dev()->enetaddr 359*a47a12beSStefan Roese pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4]; 360*a47a12beSStefan Roese pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2]; 361*a47a12beSStefan Roese pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0]; 362*a47a12beSStefan Roese #undef ea 363*a47a12beSStefan Roese pram_ptr->fen_ibdcount = 0; 364*a47a12beSStefan Roese pram_ptr->fen_ibdstart = 0; 365*a47a12beSStefan Roese pram_ptr->fen_ibdend = 0; 366*a47a12beSStefan Roese pram_ptr->fen_txlen = 0; 367*a47a12beSStefan Roese pram_ptr->fen_iaddrh = 0; /* disable hash */ 368*a47a12beSStefan Roese pram_ptr->fen_iaddrl = 0; 369*a47a12beSStefan Roese pram_ptr->fen_minflr = PKT_MINBUF_SIZE; /* minimum frame length register: 64 */ 370*a47a12beSStefan Roese /* pad pointer. use tiptr since we don't need a specific padding char */ 371*a47a12beSStefan Roese pram_ptr->fen_padptr = pram_ptr->fen_genfcc.fcc_tiptr; 372*a47a12beSStefan Roese pram_ptr->fen_maxd1 = PKT_MAXDMA_SIZE; /* maximum DMA1 length:1520 */ 373*a47a12beSStefan Roese pram_ptr->fen_maxd2 = PKT_MAXDMA_SIZE; /* maximum DMA2 length:1520 */ 374*a47a12beSStefan Roese 375*a47a12beSStefan Roese #if defined(ET_DEBUG) 376*a47a12beSStefan Roese printf("parm_ptr(0xff788500) = %p\n",pram_ptr); 377*a47a12beSStefan Roese printf("pram_ptr->fen_genfcc.fcc_rbase %08x\n", 378*a47a12beSStefan Roese pram_ptr->fen_genfcc.fcc_rbase); 379*a47a12beSStefan Roese printf("pram_ptr->fen_genfcc.fcc_tbase %08x\n", 380*a47a12beSStefan Roese pram_ptr->fen_genfcc.fcc_tbase); 381*a47a12beSStefan Roese #endif 382*a47a12beSStefan Roese 383*a47a12beSStefan Roese /* 28.9 - (8)(9): clear out events in FCCE */ 384*a47a12beSStefan Roese /* 28.9 - (9): FCCM: mask all events */ 385*a47a12beSStefan Roese if(info->ether_index == 0) { 386*a47a12beSStefan Roese cpm->im_cpm_fcc1.fcce = ~0x0; 387*a47a12beSStefan Roese cpm->im_cpm_fcc1.fccm = 0; 388*a47a12beSStefan Roese } else if (info->ether_index == 1) { 389*a47a12beSStefan Roese cpm->im_cpm_fcc2.fcce = ~0x0; 390*a47a12beSStefan Roese cpm->im_cpm_fcc2.fccm = 0; 391*a47a12beSStefan Roese } else if (info->ether_index == 2) { 392*a47a12beSStefan Roese cpm->im_cpm_fcc3.fcce = ~0x0; 393*a47a12beSStefan Roese cpm->im_cpm_fcc3.fccm = 0; 394*a47a12beSStefan Roese } 395*a47a12beSStefan Roese 396*a47a12beSStefan Roese /* 28.9 - (10-12): we don't use ethernet interrupts */ 397*a47a12beSStefan Roese 398*a47a12beSStefan Roese /* 28.9 - (13) 399*a47a12beSStefan Roese * 400*a47a12beSStefan Roese * Let's re-initialize the channel now. We have to do it later 401*a47a12beSStefan Roese * than the manual describes because we have just now finished 402*a47a12beSStefan Roese * the BD initialization. 403*a47a12beSStefan Roese */ 404*a47a12beSStefan Roese cp->cpcr = mk_cr_cmd(info->cpm_cr_enet_page, 405*a47a12beSStefan Roese info->cpm_cr_enet_sblock, 406*a47a12beSStefan Roese 0x0c, 407*a47a12beSStefan Roese CPM_CR_INIT_TRX) | CPM_CR_FLG; 408*a47a12beSStefan Roese do { 409*a47a12beSStefan Roese __asm__ __volatile__ ("eieio"); 410*a47a12beSStefan Roese } while (cp->cpcr & CPM_CR_FLG); 411*a47a12beSStefan Roese 412*a47a12beSStefan Roese /* 28.9 - (14): enable tx/rx in gfmr */ 413*a47a12beSStefan Roese if(info->ether_index == 0) { 414*a47a12beSStefan Roese cpm->im_cpm_fcc1.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR; 415*a47a12beSStefan Roese } else if (info->ether_index == 1) { 416*a47a12beSStefan Roese cpm->im_cpm_fcc2.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR; 417*a47a12beSStefan Roese } else if (info->ether_index == 2) { 418*a47a12beSStefan Roese cpm->im_cpm_fcc3.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR; 419*a47a12beSStefan Roese } 420*a47a12beSStefan Roese 421*a47a12beSStefan Roese return 1; 422*a47a12beSStefan Roese } 423*a47a12beSStefan Roese 424*a47a12beSStefan Roese static void fec_halt(struct eth_device* dev) 425*a47a12beSStefan Roese { 426*a47a12beSStefan Roese struct ether_fcc_info_s * info = dev->priv; 427*a47a12beSStefan Roese volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR; 428*a47a12beSStefan Roese 429*a47a12beSStefan Roese /* write GFMR: disable tx/rx */ 430*a47a12beSStefan Roese if(info->ether_index == 0) { 431*a47a12beSStefan Roese cpm->im_cpm_fcc1.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR); 432*a47a12beSStefan Roese } else if(info->ether_index == 1) { 433*a47a12beSStefan Roese cpm->im_cpm_fcc2.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR); 434*a47a12beSStefan Roese } else if(info->ether_index == 2) { 435*a47a12beSStefan Roese cpm->im_cpm_fcc3.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR); 436*a47a12beSStefan Roese } 437*a47a12beSStefan Roese } 438*a47a12beSStefan Roese 439*a47a12beSStefan Roese int fec_initialize(bd_t *bis) 440*a47a12beSStefan Roese { 441*a47a12beSStefan Roese struct eth_device* dev; 442*a47a12beSStefan Roese int i; 443*a47a12beSStefan Roese 444*a47a12beSStefan Roese for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++) 445*a47a12beSStefan Roese { 446*a47a12beSStefan Roese dev = (struct eth_device*) malloc(sizeof *dev); 447*a47a12beSStefan Roese memset(dev, 0, sizeof *dev); 448*a47a12beSStefan Roese 449*a47a12beSStefan Roese sprintf(dev->name, "FCC%d ETHERNET", 450*a47a12beSStefan Roese ether_fcc_info[i].ether_index + 1); 451*a47a12beSStefan Roese dev->priv = ðer_fcc_info[i]; 452*a47a12beSStefan Roese dev->init = fec_init; 453*a47a12beSStefan Roese dev->halt = fec_halt; 454*a47a12beSStefan Roese dev->send = fec_send; 455*a47a12beSStefan Roese dev->recv = fec_recv; 456*a47a12beSStefan Roese 457*a47a12beSStefan Roese eth_register(dev); 458*a47a12beSStefan Roese 459*a47a12beSStefan Roese #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) \ 460*a47a12beSStefan Roese && defined(CONFIG_BITBANGMII) 461*a47a12beSStefan Roese miiphy_register(dev->name, 462*a47a12beSStefan Roese bb_miiphy_read, bb_miiphy_write); 463*a47a12beSStefan Roese #endif 464*a47a12beSStefan Roese } 465*a47a12beSStefan Roese 466*a47a12beSStefan Roese return 1; 467*a47a12beSStefan Roese } 468*a47a12beSStefan Roese 469*a47a12beSStefan Roese #endif 470