1 /* 2 * Faraday FTGMAC100 Ethernet 3 * 4 * (C) Copyright 2009 Faraday Technology 5 * Po-Yu Chuang <ratbert@faraday-tech.com> 6 * 7 * (C) Copyright 2010 Andes Technology 8 * Macpaul Lin <macpaul@andestech.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 23 */ 24 25 #include <config.h> 26 #include <common.h> 27 #include <malloc.h> 28 #include <net.h> 29 #include <asm/io.h> 30 #include <linux/mii.h> 31 32 #include "ftgmac100.h" 33 34 #define ETH_ZLEN 60 35 36 /* RBSR - hw default init value is also 0x640 */ 37 #define RBSR_DEFAULT_VALUE 0x640 38 39 /* PKTBUFSTX/PKTBUFSRX must both be power of 2 */ 40 #define PKTBUFSTX 4 /* must be power of 2 */ 41 42 struct ftgmac100_data { 43 struct ftgmac100_txdes txdes[PKTBUFSTX]; 44 struct ftgmac100_rxdes rxdes[PKTBUFSRX]; 45 int tx_index; 46 int rx_index; 47 int phy_addr; 48 }; 49 50 /* 51 * struct mii_bus functions 52 */ 53 static int ftgmac100_mdiobus_read(struct eth_device *dev, int phy_addr, 54 int regnum) 55 { 56 struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase; 57 int phycr; 58 int i; 59 60 phycr = readl(&ftgmac100->phycr); 61 62 /* preserve MDC cycle threshold */ 63 phycr &= FTGMAC100_PHYCR_MDC_CYCTHR_MASK; 64 65 phycr |= FTGMAC100_PHYCR_PHYAD(phy_addr) 66 | FTGMAC100_PHYCR_REGAD(regnum) 67 | FTGMAC100_PHYCR_MIIRD; 68 69 writel(phycr, &ftgmac100->phycr); 70 71 for (i = 0; i < 10; i++) { 72 phycr = readl(&ftgmac100->phycr); 73 74 if ((phycr & FTGMAC100_PHYCR_MIIRD) == 0) { 75 int data; 76 77 data = readl(&ftgmac100->phydata); 78 return FTGMAC100_PHYDATA_MIIRDATA(data); 79 } 80 81 mdelay(10); 82 } 83 84 debug("mdio read timed out\n"); 85 return -1; 86 } 87 88 static int ftgmac100_mdiobus_write(struct eth_device *dev, int phy_addr, 89 int regnum, u16 value) 90 { 91 struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase; 92 int phycr; 93 int data; 94 int i; 95 96 phycr = readl(&ftgmac100->phycr); 97 98 /* preserve MDC cycle threshold */ 99 phycr &= FTGMAC100_PHYCR_MDC_CYCTHR_MASK; 100 101 phycr |= FTGMAC100_PHYCR_PHYAD(phy_addr) 102 | FTGMAC100_PHYCR_REGAD(regnum) 103 | FTGMAC100_PHYCR_MIIWR; 104 105 data = FTGMAC100_PHYDATA_MIIWDATA(value); 106 107 writel(data, &ftgmac100->phydata); 108 writel(phycr, &ftgmac100->phycr); 109 110 for (i = 0; i < 10; i++) { 111 phycr = readl(&ftgmac100->phycr); 112 113 if ((phycr & FTGMAC100_PHYCR_MIIWR) == 0) { 114 debug("(phycr & FTGMAC100_PHYCR_MIIWR) == 0: " \ 115 "phy_addr: %x\n", phy_addr); 116 return 0; 117 } 118 119 mdelay(1); 120 } 121 122 debug("mdio write timed out\n"); 123 return -1; 124 } 125 126 int ftgmac100_phy_read(struct eth_device *dev, int addr, int reg, u16 *value) 127 { 128 *value = ftgmac100_mdiobus_read(dev , addr, reg); 129 130 if (*value == -1) 131 return -1; 132 133 return 0; 134 } 135 136 int ftgmac100_phy_write(struct eth_device *dev, int addr, int reg, u16 value) 137 { 138 if (ftgmac100_mdiobus_write(dev, addr, reg, value) == -1) 139 return -1; 140 141 return 0; 142 } 143 144 static int ftgmac100_phy_reset(struct eth_device *dev) 145 { 146 struct ftgmac100_data *priv = dev->priv; 147 int i; 148 u16 status, adv; 149 150 adv = ADVERTISE_CSMA | ADVERTISE_ALL; 151 152 ftgmac100_phy_write(dev, priv->phy_addr, MII_ADVERTISE, adv); 153 154 printf("%s: Starting autonegotiation...\n", dev->name); 155 156 ftgmac100_phy_write(dev, priv->phy_addr, 157 MII_BMCR, (BMCR_ANENABLE | BMCR_ANRESTART)); 158 159 for (i = 0; i < 100000 / 100; i++) { 160 ftgmac100_phy_read(dev, priv->phy_addr, MII_BMSR, &status); 161 162 if (status & BMSR_ANEGCOMPLETE) 163 break; 164 mdelay(1); 165 } 166 167 if (status & BMSR_ANEGCOMPLETE) { 168 printf("%s: Autonegotiation complete\n", dev->name); 169 } else { 170 printf("%s: Autonegotiation timed out (status=0x%04x)\n", 171 dev->name, status); 172 return 0; 173 } 174 175 return 1; 176 } 177 178 static int ftgmac100_phy_init(struct eth_device *dev) 179 { 180 struct ftgmac100_data *priv = dev->priv; 181 182 int phy_addr; 183 u16 phy_id, status, adv, lpa, stat_ge; 184 int media, speed, duplex; 185 int i; 186 187 /* Check if the PHY is up to snuff... */ 188 for (phy_addr = 0; phy_addr < CONFIG_PHY_MAX_ADDR; phy_addr++) { 189 190 ftgmac100_phy_read(dev, phy_addr, MII_PHYSID1, &phy_id); 191 192 /* 193 * When it is unable to found PHY, 194 * the interface usually return 0xffff or 0x0000 195 */ 196 if (phy_id != 0xffff && phy_id != 0x0) { 197 printf("%s: found PHY at 0x%02x\n", 198 dev->name, phy_addr); 199 priv->phy_addr = phy_addr; 200 break; 201 } 202 } 203 204 if (phy_id == 0xffff || phy_id == 0x0) { 205 printf("%s: no PHY present\n", dev->name); 206 return 0; 207 } 208 209 ftgmac100_phy_read(dev, priv->phy_addr, MII_BMSR, &status); 210 211 if (!(status & BMSR_LSTATUS)) { 212 /* Try to re-negotiate if we don't have link already. */ 213 ftgmac100_phy_reset(dev); 214 215 for (i = 0; i < 100000 / 100; i++) { 216 ftgmac100_phy_read(dev, priv->phy_addr, 217 MII_BMSR, &status); 218 if (status & BMSR_LSTATUS) 219 break; 220 udelay(100); 221 } 222 } 223 224 if (!(status & BMSR_LSTATUS)) { 225 printf("%s: link down\n", dev->name); 226 return 0; 227 } 228 229 #ifdef CONFIG_FTGMAC100_EGIGA 230 /* 1000 Base-T Status Register */ 231 ftgmac100_phy_read(dev, priv->phy_addr, 232 MII_STAT1000, &stat_ge); 233 234 speed = (stat_ge & (LPA_1000FULL | LPA_1000HALF) 235 ? 1 : 0); 236 237 duplex = ((stat_ge & LPA_1000FULL) 238 ? 1 : 0); 239 240 if (speed) { /* Speed is 1000 */ 241 printf("%s: link up, 1000bps %s-duplex\n", 242 dev->name, duplex ? "full" : "half"); 243 return 0; 244 } 245 #endif 246 247 ftgmac100_phy_read(dev, priv->phy_addr, MII_ADVERTISE, &adv); 248 ftgmac100_phy_read(dev, priv->phy_addr, MII_LPA, &lpa); 249 250 media = mii_nway_result(lpa & adv); 251 speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? 1 : 0); 252 duplex = (media & ADVERTISE_FULL) ? 1 : 0; 253 254 printf("%s: link up, %sMbps %s-duplex\n", 255 dev->name, speed ? "100" : "10", duplex ? "full" : "half"); 256 257 return 1; 258 } 259 260 static int ftgmac100_update_link_speed(struct eth_device *dev) 261 { 262 struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase; 263 struct ftgmac100_data *priv = dev->priv; 264 265 unsigned short stat_fe; 266 unsigned short stat_ge; 267 unsigned int maccr; 268 269 #ifdef CONFIG_FTGMAC100_EGIGA 270 /* 1000 Base-T Status Register */ 271 ftgmac100_phy_read(dev, priv->phy_addr, MII_STAT1000, &stat_ge); 272 #endif 273 274 ftgmac100_phy_read(dev, priv->phy_addr, MII_BMSR, &stat_fe); 275 276 if (!(stat_fe & BMSR_LSTATUS)) /* link status up? */ 277 return 0; 278 279 /* read MAC control register and clear related bits */ 280 maccr = readl(&ftgmac100->maccr) & 281 ~(FTGMAC100_MACCR_GIGA_MODE | 282 FTGMAC100_MACCR_FAST_MODE | 283 FTGMAC100_MACCR_FULLDUP); 284 285 #ifdef CONFIG_FTGMAC100_EGIGA 286 if (stat_ge & LPA_1000FULL) { 287 /* set gmac for 1000BaseTX and Full Duplex */ 288 maccr |= FTGMAC100_MACCR_GIGA_MODE | FTGMAC100_MACCR_FULLDUP; 289 } 290 291 if (stat_ge & LPA_1000HALF) { 292 /* set gmac for 1000BaseTX and Half Duplex */ 293 maccr |= FTGMAC100_MACCR_GIGA_MODE; 294 } 295 #endif 296 297 if (stat_fe & BMSR_100FULL) { 298 /* set MII for 100BaseTX and Full Duplex */ 299 maccr |= FTGMAC100_MACCR_FAST_MODE | FTGMAC100_MACCR_FULLDUP; 300 } 301 302 if (stat_fe & BMSR_10FULL) { 303 /* set MII for 10BaseT and Full Duplex */ 304 maccr |= FTGMAC100_MACCR_FULLDUP; 305 } 306 307 if (stat_fe & BMSR_100HALF) { 308 /* set MII for 100BaseTX and Half Duplex */ 309 maccr |= FTGMAC100_MACCR_FAST_MODE; 310 } 311 312 if (stat_fe & BMSR_10HALF) { 313 /* set MII for 10BaseT and Half Duplex */ 314 /* we have already clear these bits, do nothing */ 315 ; 316 } 317 318 /* update MII config into maccr */ 319 writel(maccr, &ftgmac100->maccr); 320 321 return 1; 322 } 323 324 /* 325 * Reset MAC 326 */ 327 static void ftgmac100_reset(struct eth_device *dev) 328 { 329 struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase; 330 331 debug("%s()\n", __func__); 332 333 writel(FTGMAC100_MACCR_SW_RST, &ftgmac100->maccr); 334 335 while (readl(&ftgmac100->maccr) & FTGMAC100_MACCR_SW_RST) 336 ; 337 } 338 339 /* 340 * Set MAC address 341 */ 342 static void ftgmac100_set_mac(struct eth_device *dev, 343 const unsigned char *mac) 344 { 345 struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase; 346 unsigned int maddr = mac[0] << 8 | mac[1]; 347 unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5]; 348 349 debug("%s(%x %x)\n", __func__, maddr, laddr); 350 351 writel(maddr, &ftgmac100->mac_madr); 352 writel(laddr, &ftgmac100->mac_ladr); 353 } 354 355 static void ftgmac100_set_mac_from_env(struct eth_device *dev) 356 { 357 eth_getenv_enetaddr("ethaddr", dev->enetaddr); 358 359 ftgmac100_set_mac(dev, dev->enetaddr); 360 } 361 362 /* 363 * disable transmitter, receiver 364 */ 365 static void ftgmac100_halt(struct eth_device *dev) 366 { 367 struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase; 368 369 debug("%s()\n", __func__); 370 371 writel(0, &ftgmac100->maccr); 372 } 373 374 static int ftgmac100_init(struct eth_device *dev, bd_t *bd) 375 { 376 struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase; 377 struct ftgmac100_data *priv = dev->priv; 378 struct ftgmac100_txdes *txdes = priv->txdes; 379 struct ftgmac100_rxdes *rxdes = priv->rxdes; 380 unsigned int maccr; 381 int i; 382 383 debug("%s()\n", __func__); 384 385 /* set the ethernet address */ 386 ftgmac100_set_mac_from_env(dev); 387 388 /* disable all interrupts */ 389 writel(0, &ftgmac100->ier); 390 391 /* initialize descriptors */ 392 priv->tx_index = 0; 393 priv->rx_index = 0; 394 395 txdes[PKTBUFSTX - 1].txdes0 = FTGMAC100_TXDES0_EDOTR; 396 rxdes[PKTBUFSRX - 1].rxdes0 = FTGMAC100_RXDES0_EDORR; 397 398 for (i = 0; i < PKTBUFSTX; i++) { 399 /* TXBUF_BADR */ 400 txdes[i].txdes3 = 0; 401 txdes[i].txdes1 = 0; 402 } 403 404 for (i = 0; i < PKTBUFSRX; i++) { 405 /* RXBUF_BADR */ 406 rxdes[i].rxdes3 = (unsigned int)NetRxPackets[i]; 407 rxdes[i].rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY; 408 } 409 410 /* transmit ring */ 411 writel((unsigned int)txdes, &ftgmac100->txr_badr); 412 413 /* receive ring */ 414 writel((unsigned int)rxdes, &ftgmac100->rxr_badr); 415 416 /* poll receive descriptor automatically */ 417 writel(FTGMAC100_APTC_RXPOLL_CNT(1), &ftgmac100->aptc); 418 419 /* config receive buffer size register */ 420 writel(FTGMAC100_RBSR_SIZE(RBSR_DEFAULT_VALUE), &ftgmac100->rbsr); 421 422 /* enable transmitter, receiver */ 423 maccr = FTGMAC100_MACCR_TXMAC_EN | 424 FTGMAC100_MACCR_RXMAC_EN | 425 FTGMAC100_MACCR_TXDMA_EN | 426 FTGMAC100_MACCR_RXDMA_EN | 427 FTGMAC100_MACCR_CRC_APD | 428 FTGMAC100_MACCR_FULLDUP | 429 FTGMAC100_MACCR_RX_RUNT | 430 FTGMAC100_MACCR_RX_BROADPKT; 431 432 writel(maccr, &ftgmac100->maccr); 433 434 if (!ftgmac100_phy_init(dev)) { 435 if (!ftgmac100_update_link_speed(dev)) 436 return -1; 437 } 438 439 return 0; 440 } 441 442 /* 443 * Get a data block via Ethernet 444 */ 445 static int ftgmac100_recv(struct eth_device *dev) 446 { 447 struct ftgmac100_data *priv = dev->priv; 448 struct ftgmac100_rxdes *curr_des; 449 unsigned short rxlen; 450 451 curr_des = &priv->rxdes[priv->rx_index]; 452 453 if (!(curr_des->rxdes0 & FTGMAC100_RXDES0_RXPKT_RDY)) 454 return -1; 455 456 if (curr_des->rxdes0 & (FTGMAC100_RXDES0_RX_ERR | 457 FTGMAC100_RXDES0_CRC_ERR | 458 FTGMAC100_RXDES0_FTL | 459 FTGMAC100_RXDES0_RUNT | 460 FTGMAC100_RXDES0_RX_ODD_NB)) { 461 return -1; 462 } 463 464 rxlen = FTGMAC100_RXDES0_VDBC(curr_des->rxdes0); 465 466 debug("%s(): RX buffer %d, %x received\n", 467 __func__, priv->rx_index, rxlen); 468 469 /* pass the packet up to the protocol layers. */ 470 NetReceive((void *)curr_des->rxdes3, rxlen); 471 472 /* release buffer to DMA */ 473 curr_des->rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY; 474 475 priv->rx_index = (priv->rx_index + 1) % PKTBUFSRX; 476 477 return 0; 478 } 479 480 /* 481 * Send a data block via Ethernet 482 */ 483 static int ftgmac100_send(struct eth_device *dev, void *packet, int length) 484 { 485 struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase; 486 struct ftgmac100_data *priv = dev->priv; 487 struct ftgmac100_txdes *curr_des = &priv->txdes[priv->tx_index]; 488 int start; 489 490 if (curr_des->txdes0 & FTGMAC100_TXDES0_TXDMA_OWN) { 491 debug("%s(): no TX descriptor available\n", __func__); 492 return -1; 493 } 494 495 debug("%s(%x, %x)\n", __func__, (int)packet, length); 496 497 length = (length < ETH_ZLEN) ? ETH_ZLEN : length; 498 499 /* initiate a transmit sequence */ 500 curr_des->txdes3 = (unsigned int)packet; /* TXBUF_BADR */ 501 502 /* only one descriptor on TXBUF */ 503 curr_des->txdes0 &= FTGMAC100_TXDES0_EDOTR; 504 curr_des->txdes0 |= FTGMAC100_TXDES0_FTS | 505 FTGMAC100_TXDES0_LTS | 506 FTGMAC100_TXDES0_TXBUF_SIZE(length) | 507 FTGMAC100_TXDES0_TXDMA_OWN ; 508 509 /* start transmit */ 510 writel(1, &ftgmac100->txpd); 511 512 /* wait for transfer to succeed */ 513 start = get_timer(0); 514 while (curr_des->txdes0 & FTGMAC100_TXDES0_TXDMA_OWN) { 515 if (get_timer(0) >= 5) { 516 debug("%s(): timed out\n", __func__); 517 return -1; 518 } 519 } 520 521 debug("%s(): packet sent\n", __func__); 522 523 priv->tx_index = (priv->tx_index + 1) % PKTBUFSTX; 524 525 return 0; 526 } 527 528 int ftgmac100_initialize(bd_t *bd) 529 { 530 struct eth_device *dev; 531 struct ftgmac100_data *priv; 532 533 dev = malloc(sizeof *dev); 534 if (!dev) { 535 printf("%s(): failed to allocate dev\n", __func__); 536 goto out; 537 } 538 539 /* Transmit and receive descriptors should align to 16 bytes */ 540 priv = memalign(16, sizeof(struct ftgmac100_data)); 541 if (!priv) { 542 printf("%s(): failed to allocate priv\n", __func__); 543 goto free_dev; 544 } 545 546 memset(dev, 0, sizeof(*dev)); 547 memset(priv, 0, sizeof(*priv)); 548 549 sprintf(dev->name, "FTGMAC100"); 550 dev->iobase = CONFIG_FTGMAC100_BASE; 551 dev->init = ftgmac100_init; 552 dev->halt = ftgmac100_halt; 553 dev->send = ftgmac100_send; 554 dev->recv = ftgmac100_recv; 555 dev->priv = priv; 556 557 eth_register(dev); 558 559 ftgmac100_reset(dev); 560 561 return 1; 562 563 free_dev: 564 free(dev); 565 out: 566 return 0; 567 } 568