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