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