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