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