uboot/drivers/net/ftgmac100.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Faraday FTGMAC100 Ethernet
   4 *
   5 * (C) Copyright 2009 Faraday Technology
   6 * Po-Yu Chuang <ratbert@faraday-tech.com>
   7 *
   8 * (C) Copyright 2010 Andes Technology
   9 * Macpaul Lin <macpaul@andestech.com>
  10 *
  11 * Copyright (C) 2018, IBM Corporation.
  12 */
  13
  14#include <clk.h>
  15#include <dm.h>
  16#include <miiphy.h>
  17#include <net.h>
  18#include <wait_bit.h>
  19#include <linux/io.h>
  20#include <linux/iopoll.h>
  21
  22#include "ftgmac100.h"
  23
  24/* Min frame ethernet frame size without FCS */
  25#define ETH_ZLEN                        60
  26
  27/* Receive Buffer Size Register - HW default is 0x640 */
  28#define FTGMAC100_RBSR_DEFAULT          0x640
  29
  30/* PKTBUFSTX/PKTBUFSRX must both be power of 2 */
  31#define PKTBUFSTX       4       /* must be power of 2 */
  32
  33/* Timeout for transmit */
  34#define FTGMAC100_TX_TIMEOUT_MS         1000
  35
  36/* Timeout for a mdio read/write operation */
  37#define FTGMAC100_MDIO_TIMEOUT_USEC     10000
  38
  39/*
  40 * MDC clock cycle threshold
  41 *
  42 * 20us * 100 = 2ms > (1 / 2.5Mhz) * 0x34
  43 */
  44#define MDC_CYCTHR                      0x34
  45
  46/*
  47 * ftgmac100 model variants
  48 */
  49enum ftgmac100_model {
  50        FTGMAC100_MODEL_FARADAY,
  51        FTGMAC100_MODEL_ASPEED,
  52};
  53
  54/**
  55 * struct ftgmac100_data - private data for the FTGMAC100 driver
  56 *
  57 * @iobase: The base address of the hardware registers
  58 * @txdes: The array of transmit descriptors
  59 * @rxdes: The array of receive descriptors
  60 * @tx_index: Transmit descriptor index in @txdes
  61 * @rx_index: Receive descriptor index in @rxdes
  62 * @phy_addr: The PHY interface address to use
  63 * @phydev: The PHY device backing the MAC
  64 * @bus: The mdio bus
  65 * @phy_mode: The mode of the PHY interface (rgmii, rmii, ...)
  66 * @max_speed: Maximum speed of Ethernet connection supported by MAC
  67 * @clks: The bulk of clocks assigned to the device in the DT
  68 * @rxdes0_edorr_mask: The bit number identifying the end of the RX ring buffer
  69 * @txdes0_edotr_mask: The bit number identifying the end of the TX ring buffer
  70 */
  71struct ftgmac100_data {
  72        struct ftgmac100 *iobase;
  73
  74        struct ftgmac100_txdes txdes[PKTBUFSTX];
  75        struct ftgmac100_rxdes rxdes[PKTBUFSRX];
  76        int tx_index;
  77        int rx_index;
  78
  79        u32 phy_addr;
  80        struct phy_device *phydev;
  81        struct mii_dev *bus;
  82        u32 phy_mode;
  83        u32 max_speed;
  84
  85        struct clk_bulk clks;
  86
  87        /* End of RX/TX ring buffer bits. Depend on model */
  88        u32 rxdes0_edorr_mask;
  89        u32 txdes0_edotr_mask;
  90};
  91
  92/*
  93 * struct mii_bus functions
  94 */
  95static int ftgmac100_mdio_read(struct mii_dev *bus, int phy_addr, int dev_addr,
  96                               int reg_addr)
  97{
  98        struct ftgmac100_data *priv = bus->priv;
  99        struct ftgmac100 *ftgmac100 = priv->iobase;
 100        int phycr;
 101        int data;
 102        int ret;
 103
 104        phycr = FTGMAC100_PHYCR_MDC_CYCTHR(MDC_CYCTHR) |
 105                FTGMAC100_PHYCR_PHYAD(phy_addr) |
 106                FTGMAC100_PHYCR_REGAD(reg_addr) |
 107                FTGMAC100_PHYCR_MIIRD;
 108        writel(phycr, &ftgmac100->phycr);
 109
 110        ret = readl_poll_timeout(&ftgmac100->phycr, phycr,
 111                                 !(phycr & FTGMAC100_PHYCR_MIIRD),
 112                                 FTGMAC100_MDIO_TIMEOUT_USEC);
 113        if (ret) {
 114                pr_err("%s: mdio read failed (phy:%d reg:%x)\n",
 115                       priv->phydev->dev->name, phy_addr, reg_addr);
 116                return ret;
 117        }
 118
 119        data = readl(&ftgmac100->phydata);
 120
 121        return FTGMAC100_PHYDATA_MIIRDATA(data);
 122}
 123
 124static int ftgmac100_mdio_write(struct mii_dev *bus, int phy_addr, int dev_addr,
 125                                int reg_addr, u16 value)
 126{
 127        struct ftgmac100_data *priv = bus->priv;
 128        struct ftgmac100 *ftgmac100 = priv->iobase;
 129        int phycr;
 130        int data;
 131        int ret;
 132
 133        phycr = FTGMAC100_PHYCR_MDC_CYCTHR(MDC_CYCTHR) |
 134                FTGMAC100_PHYCR_PHYAD(phy_addr) |
 135                FTGMAC100_PHYCR_REGAD(reg_addr) |
 136                FTGMAC100_PHYCR_MIIWR;
 137        data = FTGMAC100_PHYDATA_MIIWDATA(value);
 138
 139        writel(data, &ftgmac100->phydata);
 140        writel(phycr, &ftgmac100->phycr);
 141
 142        ret = readl_poll_timeout(&ftgmac100->phycr, phycr,
 143                                 !(phycr & FTGMAC100_PHYCR_MIIWR),
 144                                 FTGMAC100_MDIO_TIMEOUT_USEC);
 145        if (ret) {
 146                pr_err("%s: mdio write failed (phy:%d reg:%x)\n",
 147                       priv->phydev->dev->name, phy_addr, reg_addr);
 148        }
 149
 150        return ret;
 151}
 152
 153static int ftgmac100_mdio_init(struct udevice *dev)
 154{
 155        struct ftgmac100_data *priv = dev_get_priv(dev);
 156        struct mii_dev *bus;
 157        int ret;
 158
 159        bus = mdio_alloc();
 160        if (!bus)
 161                return -ENOMEM;
 162
 163        bus->read  = ftgmac100_mdio_read;
 164        bus->write = ftgmac100_mdio_write;
 165        bus->priv  = priv;
 166
 167        ret = mdio_register_seq(bus, dev->seq);
 168        if (ret) {
 169                free(bus);
 170                return ret;
 171        }
 172
 173        priv->bus = bus;
 174
 175        return 0;
 176}
 177
 178static int ftgmac100_phy_adjust_link(struct ftgmac100_data *priv)
 179{
 180        struct ftgmac100 *ftgmac100 = priv->iobase;
 181        struct phy_device *phydev = priv->phydev;
 182        u32 maccr;
 183
 184        if (!phydev->link) {
 185                dev_err(phydev->dev, "No link\n");
 186                return -EREMOTEIO;
 187        }
 188
 189        /* read MAC control register and clear related bits */
 190        maccr = readl(&ftgmac100->maccr) &
 191                ~(FTGMAC100_MACCR_GIGA_MODE |
 192                  FTGMAC100_MACCR_FAST_MODE |
 193                  FTGMAC100_MACCR_FULLDUP);
 194
 195        if (phy_interface_is_rgmii(phydev) && phydev->speed == 1000)
 196                maccr |= FTGMAC100_MACCR_GIGA_MODE;
 197
 198        if (phydev->speed == 100)
 199                maccr |= FTGMAC100_MACCR_FAST_MODE;
 200
 201        if (phydev->duplex)
 202                maccr |= FTGMAC100_MACCR_FULLDUP;
 203
 204        /* update MII config into maccr */
 205        writel(maccr, &ftgmac100->maccr);
 206
 207        return 0;
 208}
 209
 210static int ftgmac100_phy_init(struct udevice *dev)
 211{
 212        struct ftgmac100_data *priv = dev_get_priv(dev);
 213        struct phy_device *phydev;
 214        int ret;
 215
 216        phydev = phy_connect(priv->bus, priv->phy_addr, dev, priv->phy_mode);
 217        if (!phydev)
 218                return -ENODEV;
 219
 220        phydev->supported &= PHY_GBIT_FEATURES;
 221        if (priv->max_speed) {
 222                ret = phy_set_supported(phydev, priv->max_speed);
 223                if (ret)
 224                        return ret;
 225        }
 226        phydev->advertising = phydev->supported;
 227        priv->phydev = phydev;
 228        phy_config(phydev);
 229
 230        return 0;
 231}
 232
 233/*
 234 * Reset MAC
 235 */
 236static void ftgmac100_reset(struct ftgmac100_data *priv)
 237{
 238        struct ftgmac100 *ftgmac100 = priv->iobase;
 239
 240        debug("%s()\n", __func__);
 241
 242        setbits_le32(&ftgmac100->maccr, FTGMAC100_MACCR_SW_RST);
 243
 244        while (readl(&ftgmac100->maccr) & FTGMAC100_MACCR_SW_RST)
 245                ;
 246}
 247
 248/*
 249 * Set MAC address
 250 */
 251static int ftgmac100_set_mac(struct ftgmac100_data *priv,
 252                             const unsigned char *mac)
 253{
 254        struct ftgmac100 *ftgmac100 = priv->iobase;
 255        unsigned int maddr = mac[0] << 8 | mac[1];
 256        unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
 257
 258        debug("%s(%x %x)\n", __func__, maddr, laddr);
 259
 260        writel(maddr, &ftgmac100->mac_madr);
 261        writel(laddr, &ftgmac100->mac_ladr);
 262
 263        return 0;
 264}
 265
 266/*
 267 * disable transmitter, receiver
 268 */
 269static void ftgmac100_stop(struct udevice *dev)
 270{
 271        struct ftgmac100_data *priv = dev_get_priv(dev);
 272        struct ftgmac100 *ftgmac100 = priv->iobase;
 273
 274        debug("%s()\n", __func__);
 275
 276        writel(0, &ftgmac100->maccr);
 277
 278        phy_shutdown(priv->phydev);
 279}
 280
 281static int ftgmac100_start(struct udevice *dev)
 282{
 283        struct eth_pdata *plat = dev_get_platdata(dev);
 284        struct ftgmac100_data *priv = dev_get_priv(dev);
 285        struct ftgmac100 *ftgmac100 = priv->iobase;
 286        struct phy_device *phydev = priv->phydev;
 287        unsigned int maccr;
 288        ulong start, end;
 289        int ret;
 290        int i;
 291
 292        debug("%s()\n", __func__);
 293
 294        ftgmac100_reset(priv);
 295
 296        /* set the ethernet address */
 297        ftgmac100_set_mac(priv, plat->enetaddr);
 298
 299        /* disable all interrupts */
 300        writel(0, &ftgmac100->ier);
 301
 302        /* initialize descriptors */
 303        priv->tx_index = 0;
 304        priv->rx_index = 0;
 305
 306        for (i = 0; i < PKTBUFSTX; i++) {
 307                priv->txdes[i].txdes3 = 0;
 308                priv->txdes[i].txdes0 = 0;
 309        }
 310        priv->txdes[PKTBUFSTX - 1].txdes0 = priv->txdes0_edotr_mask;
 311
 312        start = (ulong)&priv->txdes[0];
 313        end = start + roundup(sizeof(priv->txdes), ARCH_DMA_MINALIGN);
 314        flush_dcache_range(start, end);
 315
 316        for (i = 0; i < PKTBUFSRX; i++) {
 317                priv->rxdes[i].rxdes3 = (unsigned int)net_rx_packets[i];
 318                priv->rxdes[i].rxdes0 = 0;
 319        }
 320        priv->rxdes[PKTBUFSRX - 1].rxdes0 = priv->rxdes0_edorr_mask;
 321
 322        start = (ulong)&priv->rxdes[0];
 323        end = start + roundup(sizeof(priv->rxdes), ARCH_DMA_MINALIGN);
 324        flush_dcache_range(start, end);
 325
 326        /* transmit ring */
 327        writel((u32)priv->txdes, &ftgmac100->txr_badr);
 328
 329        /* receive ring */
 330        writel((u32)priv->rxdes, &ftgmac100->rxr_badr);
 331
 332        /* poll receive descriptor automatically */
 333        writel(FTGMAC100_APTC_RXPOLL_CNT(1), &ftgmac100->aptc);
 334
 335        /* config receive buffer size register */
 336        writel(FTGMAC100_RBSR_SIZE(FTGMAC100_RBSR_DEFAULT), &ftgmac100->rbsr);
 337
 338        /* enable transmitter, receiver */
 339        maccr = FTGMAC100_MACCR_TXMAC_EN |
 340                FTGMAC100_MACCR_RXMAC_EN |
 341                FTGMAC100_MACCR_TXDMA_EN |
 342                FTGMAC100_MACCR_RXDMA_EN |
 343                FTGMAC100_MACCR_CRC_APD |
 344                FTGMAC100_MACCR_FULLDUP |
 345                FTGMAC100_MACCR_RX_RUNT |
 346                FTGMAC100_MACCR_RX_BROADPKT;
 347
 348        writel(maccr, &ftgmac100->maccr);
 349
 350        ret = phy_startup(phydev);
 351        if (ret) {
 352                dev_err(phydev->dev, "Could not start PHY\n");
 353                return ret;
 354        }
 355
 356        ret = ftgmac100_phy_adjust_link(priv);
 357        if (ret) {
 358                dev_err(phydev->dev,  "Could not adjust link\n");
 359                return ret;
 360        }
 361
 362        printf("%s: link up, %d Mbps %s-duplex mac:%pM\n", phydev->dev->name,
 363               phydev->speed, phydev->duplex ? "full" : "half", plat->enetaddr);
 364
 365        return 0;
 366}
 367
 368static int ftgmac100_free_pkt(struct udevice *dev, uchar *packet, int length)
 369{
 370        struct ftgmac100_data *priv = dev_get_priv(dev);
 371        struct ftgmac100_rxdes *curr_des = &priv->rxdes[priv->rx_index];
 372        ulong des_start = (ulong)curr_des;
 373        ulong des_end = des_start +
 374                roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
 375
 376        /* Release buffer to DMA and flush descriptor */
 377        curr_des->rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
 378        flush_dcache_range(des_start, des_end);
 379
 380        /* Move to next descriptor */
 381        priv->rx_index = (priv->rx_index + 1) % PKTBUFSRX;
 382
 383        return 0;
 384}
 385
 386/*
 387 * Get a data block via Ethernet
 388 */
 389static int ftgmac100_recv(struct udevice *dev, int flags, uchar **packetp)
 390{
 391        struct ftgmac100_data *priv = dev_get_priv(dev);
 392        struct ftgmac100_rxdes *curr_des = &priv->rxdes[priv->rx_index];
 393        unsigned short rxlen;
 394        ulong des_start = (ulong)curr_des;
 395        ulong des_end = des_start +
 396                roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
 397        ulong data_start = curr_des->rxdes3;
 398        ulong data_end;
 399
 400        invalidate_dcache_range(des_start, des_end);
 401
 402        if (!(curr_des->rxdes0 & FTGMAC100_RXDES0_RXPKT_RDY))
 403                return -EAGAIN;
 404
 405        if (curr_des->rxdes0 & (FTGMAC100_RXDES0_RX_ERR |
 406                                FTGMAC100_RXDES0_CRC_ERR |
 407                                FTGMAC100_RXDES0_FTL |
 408                                FTGMAC100_RXDES0_RUNT |
 409                                FTGMAC100_RXDES0_RX_ODD_NB)) {
 410                return -EAGAIN;
 411        }
 412
 413        rxlen = FTGMAC100_RXDES0_VDBC(curr_des->rxdes0);
 414
 415        debug("%s(): RX buffer %d, %x received\n",
 416               __func__, priv->rx_index, rxlen);
 417
 418        /* Invalidate received data */
 419        data_end = data_start + roundup(rxlen, ARCH_DMA_MINALIGN);
 420        invalidate_dcache_range(data_start, data_end);
 421        *packetp = (uchar *)data_start;
 422
 423        return rxlen;
 424}
 425
 426static u32 ftgmac100_read_txdesc(const void *desc)
 427{
 428        const struct ftgmac100_txdes *txdes = desc;
 429        ulong des_start = (ulong)txdes;
 430        ulong des_end = des_start + roundup(sizeof(*txdes), ARCH_DMA_MINALIGN);
 431
 432        invalidate_dcache_range(des_start, des_end);
 433
 434        return txdes->txdes0;
 435}
 436
 437BUILD_WAIT_FOR_BIT(ftgmac100_txdone, u32, ftgmac100_read_txdesc)
 438
 439/*
 440 * Send a data block via Ethernet
 441 */
 442static int ftgmac100_send(struct udevice *dev, void *packet, int length)
 443{
 444        struct ftgmac100_data *priv = dev_get_priv(dev);
 445        struct ftgmac100 *ftgmac100 = priv->iobase;
 446        struct ftgmac100_txdes *curr_des = &priv->txdes[priv->tx_index];
 447        ulong des_start = (ulong)curr_des;
 448        ulong des_end = des_start +
 449                roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
 450        ulong data_start;
 451        ulong data_end;
 452        int rc;
 453
 454        invalidate_dcache_range(des_start, des_end);
 455
 456        if (curr_des->txdes0 & FTGMAC100_TXDES0_TXDMA_OWN) {
 457                dev_err(dev, "no TX descriptor available\n");
 458                return -EPERM;
 459        }
 460
 461        debug("%s(%x, %x)\n", __func__, (int)packet, length);
 462
 463        length = (length < ETH_ZLEN) ? ETH_ZLEN : length;
 464
 465        curr_des->txdes3 = (unsigned int)packet;
 466
 467        /* Flush data to be sent */
 468        data_start = curr_des->txdes3;
 469        data_end = data_start + roundup(length, ARCH_DMA_MINALIGN);
 470        flush_dcache_range(data_start, data_end);
 471
 472        /* Only one segment on TXBUF */
 473        curr_des->txdes0 &= priv->txdes0_edotr_mask;
 474        curr_des->txdes0 |= FTGMAC100_TXDES0_FTS |
 475                            FTGMAC100_TXDES0_LTS |
 476                            FTGMAC100_TXDES0_TXBUF_SIZE(length) |
 477                            FTGMAC100_TXDES0_TXDMA_OWN ;
 478
 479        /* Flush modified buffer descriptor */
 480        flush_dcache_range(des_start, des_end);
 481
 482        /* Start transmit */
 483        writel(1, &ftgmac100->txpd);
 484
 485        rc = wait_for_bit_ftgmac100_txdone(curr_des,
 486                                           FTGMAC100_TXDES0_TXDMA_OWN, false,
 487                                           FTGMAC100_TX_TIMEOUT_MS, true);
 488        if (rc)
 489                return rc;
 490
 491        debug("%s(): packet sent\n", __func__);
 492
 493        /* Move to next descriptor */
 494        priv->tx_index = (priv->tx_index + 1) % PKTBUFSTX;
 495
 496        return 0;
 497}
 498
 499static int ftgmac100_write_hwaddr(struct udevice *dev)
 500{
 501        struct eth_pdata *pdata = dev_get_platdata(dev);
 502        struct ftgmac100_data *priv = dev_get_priv(dev);
 503
 504        return ftgmac100_set_mac(priv, pdata->enetaddr);
 505}
 506
 507static int ftgmac100_ofdata_to_platdata(struct udevice *dev)
 508{
 509        struct eth_pdata *pdata = dev_get_platdata(dev);
 510        struct ftgmac100_data *priv = dev_get_priv(dev);
 511        const char *phy_mode;
 512
 513        pdata->iobase = devfdt_get_addr(dev);
 514        pdata->phy_interface = -1;
 515        phy_mode = dev_read_string(dev, "phy-mode");
 516        if (phy_mode)
 517                pdata->phy_interface = phy_get_interface_by_name(phy_mode);
 518        if (pdata->phy_interface == -1) {
 519                dev_err(dev, "Invalid PHY interface '%s'\n", phy_mode);
 520                return -EINVAL;
 521        }
 522
 523        pdata->max_speed = dev_read_u32_default(dev, "max-speed", 0);
 524
 525        if (dev_get_driver_data(dev) == FTGMAC100_MODEL_ASPEED) {
 526                priv->rxdes0_edorr_mask = BIT(30);
 527                priv->txdes0_edotr_mask = BIT(30);
 528        } else {
 529                priv->rxdes0_edorr_mask = BIT(15);
 530                priv->txdes0_edotr_mask = BIT(15);
 531        }
 532
 533        return clk_get_bulk(dev, &priv->clks);
 534}
 535
 536static int ftgmac100_probe(struct udevice *dev)
 537{
 538        struct eth_pdata *pdata = dev_get_platdata(dev);
 539        struct ftgmac100_data *priv = dev_get_priv(dev);
 540        int ret;
 541
 542        priv->iobase = (struct ftgmac100 *)pdata->iobase;
 543        priv->phy_mode = pdata->phy_interface;
 544        priv->max_speed = pdata->max_speed;
 545        priv->phy_addr = 0;
 546
 547        ret = clk_enable_bulk(&priv->clks);
 548        if (ret)
 549                goto out;
 550
 551        ret = ftgmac100_mdio_init(dev);
 552        if (ret) {
 553                dev_err(dev, "Failed to initialize mdiobus: %d\n", ret);
 554                goto out;
 555        }
 556
 557        ret = ftgmac100_phy_init(dev);
 558        if (ret) {
 559                dev_err(dev, "Failed to initialize PHY: %d\n", ret);
 560                goto out;
 561        }
 562
 563out:
 564        if (ret)
 565                clk_release_bulk(&priv->clks);
 566
 567        return ret;
 568}
 569
 570static int ftgmac100_remove(struct udevice *dev)
 571{
 572        struct ftgmac100_data *priv = dev_get_priv(dev);
 573
 574        free(priv->phydev);
 575        mdio_unregister(priv->bus);
 576        mdio_free(priv->bus);
 577        clk_release_bulk(&priv->clks);
 578
 579        return 0;
 580}
 581
 582static const struct eth_ops ftgmac100_ops = {
 583        .start  = ftgmac100_start,
 584        .send   = ftgmac100_send,
 585        .recv   = ftgmac100_recv,
 586        .stop   = ftgmac100_stop,
 587        .free_pkt = ftgmac100_free_pkt,
 588        .write_hwaddr = ftgmac100_write_hwaddr,
 589};
 590
 591static const struct udevice_id ftgmac100_ids[] = {
 592        { .compatible = "faraday,ftgmac100",  .data = FTGMAC100_MODEL_FARADAY },
 593        { .compatible = "aspeed,ast2500-mac", .data = FTGMAC100_MODEL_ASPEED  },
 594        { }
 595};
 596
 597U_BOOT_DRIVER(ftgmac100) = {
 598        .name   = "ftgmac100",
 599        .id     = UCLASS_ETH,
 600        .of_match = ftgmac100_ids,
 601        .ofdata_to_platdata = ftgmac100_ofdata_to_platdata,
 602        .probe  = ftgmac100_probe,
 603        .remove = ftgmac100_remove,
 604        .ops    = &ftgmac100_ops,
 605        .priv_auto_alloc_size = sizeof(struct ftgmac100_data),
 606        .platdata_auto_alloc_size = sizeof(struct eth_pdata),
 607        .flags  = DM_FLAG_ALLOC_PRIV_DMA,
 608};
 609