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