uboot/drivers/net/designware.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2010
   3 * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8/*
   9 * Designware ethernet IP driver for U-Boot
  10 */
  11
  12#include <common.h>
  13#include <dm.h>
  14#include <errno.h>
  15#include <miiphy.h>
  16#include <malloc.h>
  17#include <pci.h>
  18#include <linux/compiler.h>
  19#include <linux/err.h>
  20#include <asm/io.h>
  21#include "designware.h"
  22
  23DECLARE_GLOBAL_DATA_PTR;
  24
  25static int dw_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
  26{
  27#ifdef CONFIG_DM_ETH
  28        struct dw_eth_dev *priv = dev_get_priv((struct udevice *)bus->priv);
  29        struct eth_mac_regs *mac_p = priv->mac_regs_p;
  30#else
  31        struct eth_mac_regs *mac_p = bus->priv;
  32#endif
  33        ulong start;
  34        u16 miiaddr;
  35        int timeout = CONFIG_MDIO_TIMEOUT;
  36
  37        miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) |
  38                  ((reg << MIIREGSHIFT) & MII_REGMSK);
  39
  40        writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr);
  41
  42        start = get_timer(0);
  43        while (get_timer(start) < timeout) {
  44                if (!(readl(&mac_p->miiaddr) & MII_BUSY))
  45                        return readl(&mac_p->miidata);
  46                udelay(10);
  47        };
  48
  49        return -ETIMEDOUT;
  50}
  51
  52static int dw_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
  53                        u16 val)
  54{
  55#ifdef CONFIG_DM_ETH
  56        struct dw_eth_dev *priv = dev_get_priv((struct udevice *)bus->priv);
  57        struct eth_mac_regs *mac_p = priv->mac_regs_p;
  58#else
  59        struct eth_mac_regs *mac_p = bus->priv;
  60#endif
  61        ulong start;
  62        u16 miiaddr;
  63        int ret = -ETIMEDOUT, timeout = CONFIG_MDIO_TIMEOUT;
  64
  65        writel(val, &mac_p->miidata);
  66        miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) |
  67                  ((reg << MIIREGSHIFT) & MII_REGMSK) | MII_WRITE;
  68
  69        writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr);
  70
  71        start = get_timer(0);
  72        while (get_timer(start) < timeout) {
  73                if (!(readl(&mac_p->miiaddr) & MII_BUSY)) {
  74                        ret = 0;
  75                        break;
  76                }
  77                udelay(10);
  78        };
  79
  80        return ret;
  81}
  82
  83#if defined(CONFIG_DM_ETH) && defined(CONFIG_DM_GPIO)
  84static int dw_mdio_reset(struct mii_dev *bus)
  85{
  86        struct udevice *dev = bus->priv;
  87        struct dw_eth_dev *priv = dev_get_priv(dev);
  88        struct dw_eth_pdata *pdata = dev_get_platdata(dev);
  89        int ret;
  90
  91        if (!dm_gpio_is_valid(&priv->reset_gpio))
  92                return 0;
  93
  94        /* reset the phy */
  95        ret = dm_gpio_set_value(&priv->reset_gpio, 0);
  96        if (ret)
  97                return ret;
  98
  99        udelay(pdata->reset_delays[0]);
 100
 101        ret = dm_gpio_set_value(&priv->reset_gpio, 1);
 102        if (ret)
 103                return ret;
 104
 105        udelay(pdata->reset_delays[1]);
 106
 107        ret = dm_gpio_set_value(&priv->reset_gpio, 0);
 108        if (ret)
 109                return ret;
 110
 111        udelay(pdata->reset_delays[2]);
 112
 113        return 0;
 114}
 115#endif
 116
 117static int dw_mdio_init(const char *name, void *priv)
 118{
 119        struct mii_dev *bus = mdio_alloc();
 120
 121        if (!bus) {
 122                printf("Failed to allocate MDIO bus\n");
 123                return -ENOMEM;
 124        }
 125
 126        bus->read = dw_mdio_read;
 127        bus->write = dw_mdio_write;
 128        snprintf(bus->name, sizeof(bus->name), "%s", name);
 129#if defined(CONFIG_DM_ETH) && defined(CONFIG_DM_GPIO)
 130        bus->reset = dw_mdio_reset;
 131#endif
 132
 133        bus->priv = priv;
 134
 135        return mdio_register(bus);
 136}
 137
 138static void tx_descs_init(struct dw_eth_dev *priv)
 139{
 140        struct eth_dma_regs *dma_p = priv->dma_regs_p;
 141        struct dmamacdescr *desc_table_p = &priv->tx_mac_descrtable[0];
 142        char *txbuffs = &priv->txbuffs[0];
 143        struct dmamacdescr *desc_p;
 144        u32 idx;
 145
 146        for (idx = 0; idx < CONFIG_TX_DESCR_NUM; idx++) {
 147                desc_p = &desc_table_p[idx];
 148                desc_p->dmamac_addr = (ulong)&txbuffs[idx * CONFIG_ETH_BUFSIZE];
 149                desc_p->dmamac_next = (ulong)&desc_table_p[idx + 1];
 150
 151#if defined(CONFIG_DW_ALTDESCRIPTOR)
 152                desc_p->txrx_status &= ~(DESC_TXSTS_TXINT | DESC_TXSTS_TXLAST |
 153                                DESC_TXSTS_TXFIRST | DESC_TXSTS_TXCRCDIS |
 154                                DESC_TXSTS_TXCHECKINSCTRL |
 155                                DESC_TXSTS_TXRINGEND | DESC_TXSTS_TXPADDIS);
 156
 157                desc_p->txrx_status |= DESC_TXSTS_TXCHAIN;
 158                desc_p->dmamac_cntl = 0;
 159                desc_p->txrx_status &= ~(DESC_TXSTS_MSK | DESC_TXSTS_OWNBYDMA);
 160#else
 161                desc_p->dmamac_cntl = DESC_TXCTRL_TXCHAIN;
 162                desc_p->txrx_status = 0;
 163#endif
 164        }
 165
 166        /* Correcting the last pointer of the chain */
 167        desc_p->dmamac_next = (ulong)&desc_table_p[0];
 168
 169        /* Flush all Tx buffer descriptors at once */
 170        flush_dcache_range((ulong)priv->tx_mac_descrtable,
 171                           (ulong)priv->tx_mac_descrtable +
 172                           sizeof(priv->tx_mac_descrtable));
 173
 174        writel((ulong)&desc_table_p[0], &dma_p->txdesclistaddr);
 175        priv->tx_currdescnum = 0;
 176}
 177
 178static void rx_descs_init(struct dw_eth_dev *priv)
 179{
 180        struct eth_dma_regs *dma_p = priv->dma_regs_p;
 181        struct dmamacdescr *desc_table_p = &priv->rx_mac_descrtable[0];
 182        char *rxbuffs = &priv->rxbuffs[0];
 183        struct dmamacdescr *desc_p;
 184        u32 idx;
 185
 186        /* Before passing buffers to GMAC we need to make sure zeros
 187         * written there right after "priv" structure allocation were
 188         * flushed into RAM.
 189         * Otherwise there's a chance to get some of them flushed in RAM when
 190         * GMAC is already pushing data to RAM via DMA. This way incoming from
 191         * GMAC data will be corrupted. */
 192        flush_dcache_range((ulong)rxbuffs, (ulong)rxbuffs + RX_TOTAL_BUFSIZE);
 193
 194        for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) {
 195                desc_p = &desc_table_p[idx];
 196                desc_p->dmamac_addr = (ulong)&rxbuffs[idx * CONFIG_ETH_BUFSIZE];
 197                desc_p->dmamac_next = (ulong)&desc_table_p[idx + 1];
 198
 199                desc_p->dmamac_cntl =
 200                        (MAC_MAX_FRAME_SZ & DESC_RXCTRL_SIZE1MASK) |
 201                                      DESC_RXCTRL_RXCHAIN;
 202
 203                desc_p->txrx_status = DESC_RXSTS_OWNBYDMA;
 204        }
 205
 206        /* Correcting the last pointer of the chain */
 207        desc_p->dmamac_next = (ulong)&desc_table_p[0];
 208
 209        /* Flush all Rx buffer descriptors at once */
 210        flush_dcache_range((ulong)priv->rx_mac_descrtable,
 211                           (ulong)priv->rx_mac_descrtable +
 212                           sizeof(priv->rx_mac_descrtable));
 213
 214        writel((ulong)&desc_table_p[0], &dma_p->rxdesclistaddr);
 215        priv->rx_currdescnum = 0;
 216}
 217
 218static int _dw_write_hwaddr(struct dw_eth_dev *priv, u8 *mac_id)
 219{
 220        struct eth_mac_regs *mac_p = priv->mac_regs_p;
 221        u32 macid_lo, macid_hi;
 222
 223        macid_lo = mac_id[0] + (mac_id[1] << 8) + (mac_id[2] << 16) +
 224                   (mac_id[3] << 24);
 225        macid_hi = mac_id[4] + (mac_id[5] << 8);
 226
 227        writel(macid_hi, &mac_p->macaddr0hi);
 228        writel(macid_lo, &mac_p->macaddr0lo);
 229
 230        return 0;
 231}
 232
 233static void dw_adjust_link(struct eth_mac_regs *mac_p,
 234                           struct phy_device *phydev)
 235{
 236        u32 conf = readl(&mac_p->conf) | FRAMEBURSTENABLE | DISABLERXOWN;
 237
 238        if (!phydev->link) {
 239                printf("%s: No link.\n", phydev->dev->name);
 240                return;
 241        }
 242
 243        if (phydev->speed != 1000)
 244                conf |= MII_PORTSELECT;
 245        else
 246                conf &= ~MII_PORTSELECT;
 247
 248        if (phydev->speed == 100)
 249                conf |= FES_100;
 250
 251        if (phydev->duplex)
 252                conf |= FULLDPLXMODE;
 253
 254        writel(conf, &mac_p->conf);
 255
 256        printf("Speed: %d, %s duplex%s\n", phydev->speed,
 257               (phydev->duplex) ? "full" : "half",
 258               (phydev->port == PORT_FIBRE) ? ", fiber mode" : "");
 259}
 260
 261static void _dw_eth_halt(struct dw_eth_dev *priv)
 262{
 263        struct eth_mac_regs *mac_p = priv->mac_regs_p;
 264        struct eth_dma_regs *dma_p = priv->dma_regs_p;
 265
 266        writel(readl(&mac_p->conf) & ~(RXENABLE | TXENABLE), &mac_p->conf);
 267        writel(readl(&dma_p->opmode) & ~(RXSTART | TXSTART), &dma_p->opmode);
 268
 269        phy_shutdown(priv->phydev);
 270}
 271
 272static int _dw_eth_init(struct dw_eth_dev *priv, u8 *enetaddr)
 273{
 274        struct eth_mac_regs *mac_p = priv->mac_regs_p;
 275        struct eth_dma_regs *dma_p = priv->dma_regs_p;
 276        unsigned int start;
 277        int ret;
 278
 279        writel(readl(&dma_p->busmode) | DMAMAC_SRST, &dma_p->busmode);
 280
 281        start = get_timer(0);
 282        while (readl(&dma_p->busmode) & DMAMAC_SRST) {
 283                if (get_timer(start) >= CONFIG_MACRESET_TIMEOUT) {
 284                        printf("DMA reset timeout\n");
 285                        return -ETIMEDOUT;
 286                }
 287
 288                mdelay(100);
 289        };
 290
 291        /*
 292         * Soft reset above clears HW address registers.
 293         * So we have to set it here once again.
 294         */
 295        _dw_write_hwaddr(priv, enetaddr);
 296
 297        rx_descs_init(priv);
 298        tx_descs_init(priv);
 299
 300        writel(FIXEDBURST | PRIORXTX_41 | DMA_PBL, &dma_p->busmode);
 301
 302#ifndef CONFIG_DW_MAC_FORCE_THRESHOLD_MODE
 303        writel(readl(&dma_p->opmode) | FLUSHTXFIFO | STOREFORWARD,
 304               &dma_p->opmode);
 305#else
 306        writel(readl(&dma_p->opmode) | FLUSHTXFIFO,
 307               &dma_p->opmode);
 308#endif
 309
 310        writel(readl(&dma_p->opmode) | RXSTART | TXSTART, &dma_p->opmode);
 311
 312#ifdef CONFIG_DW_AXI_BURST_LEN
 313        writel((CONFIG_DW_AXI_BURST_LEN & 0x1FF >> 1), &dma_p->axibus);
 314#endif
 315
 316        /* Start up the PHY */
 317        ret = phy_startup(priv->phydev);
 318        if (ret) {
 319                printf("Could not initialize PHY %s\n",
 320                       priv->phydev->dev->name);
 321                return ret;
 322        }
 323
 324        dw_adjust_link(mac_p, priv->phydev);
 325
 326        if (!priv->phydev->link)
 327                return -EIO;
 328
 329        writel(readl(&mac_p->conf) | RXENABLE | TXENABLE, &mac_p->conf);
 330
 331        return 0;
 332}
 333
 334static int _dw_eth_send(struct dw_eth_dev *priv, void *packet, int length)
 335{
 336        struct eth_dma_regs *dma_p = priv->dma_regs_p;
 337        u32 desc_num = priv->tx_currdescnum;
 338        struct dmamacdescr *desc_p = &priv->tx_mac_descrtable[desc_num];
 339        ulong desc_start = (ulong)desc_p;
 340        ulong desc_end = desc_start +
 341                roundup(sizeof(*desc_p), ARCH_DMA_MINALIGN);
 342        ulong data_start = desc_p->dmamac_addr;
 343        ulong data_end = data_start + roundup(length, ARCH_DMA_MINALIGN);
 344        /*
 345         * Strictly we only need to invalidate the "txrx_status" field
 346         * for the following check, but on some platforms we cannot
 347         * invalidate only 4 bytes, so we flush the entire descriptor,
 348         * which is 16 bytes in total. This is safe because the
 349         * individual descriptors in the array are each aligned to
 350         * ARCH_DMA_MINALIGN and padded appropriately.
 351         */
 352        invalidate_dcache_range(desc_start, desc_end);
 353
 354        /* Check if the descriptor is owned by CPU */
 355        if (desc_p->txrx_status & DESC_TXSTS_OWNBYDMA) {
 356                printf("CPU not owner of tx frame\n");
 357                return -EPERM;
 358        }
 359
 360        memcpy((void *)data_start, packet, length);
 361
 362        /* Flush data to be sent */
 363        flush_dcache_range(data_start, data_end);
 364
 365#if defined(CONFIG_DW_ALTDESCRIPTOR)
 366        desc_p->txrx_status |= DESC_TXSTS_TXFIRST | DESC_TXSTS_TXLAST;
 367        desc_p->dmamac_cntl |= (length << DESC_TXCTRL_SIZE1SHFT) &
 368                               DESC_TXCTRL_SIZE1MASK;
 369
 370        desc_p->txrx_status &= ~(DESC_TXSTS_MSK);
 371        desc_p->txrx_status |= DESC_TXSTS_OWNBYDMA;
 372#else
 373        desc_p->dmamac_cntl |= ((length << DESC_TXCTRL_SIZE1SHFT) &
 374                               DESC_TXCTRL_SIZE1MASK) | DESC_TXCTRL_TXLAST |
 375                               DESC_TXCTRL_TXFIRST;
 376
 377        desc_p->txrx_status = DESC_TXSTS_OWNBYDMA;
 378#endif
 379
 380        /* Flush modified buffer descriptor */
 381        flush_dcache_range(desc_start, desc_end);
 382
 383        /* Test the wrap-around condition. */
 384        if (++desc_num >= CONFIG_TX_DESCR_NUM)
 385                desc_num = 0;
 386
 387        priv->tx_currdescnum = desc_num;
 388
 389        /* Start the transmission */
 390        writel(POLL_DATA, &dma_p->txpolldemand);
 391
 392        return 0;
 393}
 394
 395static int _dw_eth_recv(struct dw_eth_dev *priv, uchar **packetp)
 396{
 397        u32 status, desc_num = priv->rx_currdescnum;
 398        struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num];
 399        int length = -EAGAIN;
 400        ulong desc_start = (ulong)desc_p;
 401        ulong desc_end = desc_start +
 402                roundup(sizeof(*desc_p), ARCH_DMA_MINALIGN);
 403        ulong data_start = desc_p->dmamac_addr;
 404        ulong data_end;
 405
 406        /* Invalidate entire buffer descriptor */
 407        invalidate_dcache_range(desc_start, desc_end);
 408
 409        status = desc_p->txrx_status;
 410
 411        /* Check  if the owner is the CPU */
 412        if (!(status & DESC_RXSTS_OWNBYDMA)) {
 413
 414                length = (status & DESC_RXSTS_FRMLENMSK) >>
 415                         DESC_RXSTS_FRMLENSHFT;
 416
 417                /* Invalidate received data */
 418                data_end = data_start + roundup(length, ARCH_DMA_MINALIGN);
 419                invalidate_dcache_range(data_start, data_end);
 420                *packetp = (uchar *)(ulong)desc_p->dmamac_addr;
 421        }
 422
 423        return length;
 424}
 425
 426static int _dw_free_pkt(struct dw_eth_dev *priv)
 427{
 428        u32 desc_num = priv->rx_currdescnum;
 429        struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num];
 430        ulong desc_start = (ulong)desc_p;
 431        ulong desc_end = desc_start +
 432                roundup(sizeof(*desc_p), ARCH_DMA_MINALIGN);
 433
 434        /*
 435         * Make the current descriptor valid again and go to
 436         * the next one
 437         */
 438        desc_p->txrx_status |= DESC_RXSTS_OWNBYDMA;
 439
 440        /* Flush only status field - others weren't changed */
 441        flush_dcache_range(desc_start, desc_end);
 442
 443        /* Test the wrap-around condition. */
 444        if (++desc_num >= CONFIG_RX_DESCR_NUM)
 445                desc_num = 0;
 446        priv->rx_currdescnum = desc_num;
 447
 448        return 0;
 449}
 450
 451static int dw_phy_init(struct dw_eth_dev *priv, void *dev)
 452{
 453        struct phy_device *phydev;
 454        int mask = 0xffffffff, ret;
 455
 456#ifdef CONFIG_PHY_ADDR
 457        mask = 1 << CONFIG_PHY_ADDR;
 458#endif
 459
 460        phydev = phy_find_by_mask(priv->bus, mask, priv->interface);
 461        if (!phydev)
 462                return -ENODEV;
 463
 464        phy_connect_dev(phydev, dev);
 465
 466        phydev->supported &= PHY_GBIT_FEATURES;
 467        if (priv->max_speed) {
 468                ret = phy_set_supported(phydev, priv->max_speed);
 469                if (ret)
 470                        return ret;
 471        }
 472        phydev->advertising = phydev->supported;
 473
 474        priv->phydev = phydev;
 475        phy_config(phydev);
 476
 477        return 0;
 478}
 479
 480#ifndef CONFIG_DM_ETH
 481static int dw_eth_init(struct eth_device *dev, bd_t *bis)
 482{
 483        return _dw_eth_init(dev->priv, dev->enetaddr);
 484}
 485
 486static int dw_eth_send(struct eth_device *dev, void *packet, int length)
 487{
 488        return _dw_eth_send(dev->priv, packet, length);
 489}
 490
 491static int dw_eth_recv(struct eth_device *dev)
 492{
 493        uchar *packet;
 494        int length;
 495
 496        length = _dw_eth_recv(dev->priv, &packet);
 497        if (length == -EAGAIN)
 498                return 0;
 499        net_process_received_packet(packet, length);
 500
 501        _dw_free_pkt(dev->priv);
 502
 503        return 0;
 504}
 505
 506static void dw_eth_halt(struct eth_device *dev)
 507{
 508        return _dw_eth_halt(dev->priv);
 509}
 510
 511static int dw_write_hwaddr(struct eth_device *dev)
 512{
 513        return _dw_write_hwaddr(dev->priv, dev->enetaddr);
 514}
 515
 516int designware_initialize(ulong base_addr, u32 interface)
 517{
 518        struct eth_device *dev;
 519        struct dw_eth_dev *priv;
 520
 521        dev = (struct eth_device *) malloc(sizeof(struct eth_device));
 522        if (!dev)
 523                return -ENOMEM;
 524
 525        /*
 526         * Since the priv structure contains the descriptors which need a strict
 527         * buswidth alignment, memalign is used to allocate memory
 528         */
 529        priv = (struct dw_eth_dev *) memalign(ARCH_DMA_MINALIGN,
 530                                              sizeof(struct dw_eth_dev));
 531        if (!priv) {
 532                free(dev);
 533                return -ENOMEM;
 534        }
 535
 536        if ((phys_addr_t)priv + sizeof(*priv) > (1ULL << 32)) {
 537                printf("designware: buffers are outside DMA memory\n");
 538                return -EINVAL;
 539        }
 540
 541        memset(dev, 0, sizeof(struct eth_device));
 542        memset(priv, 0, sizeof(struct dw_eth_dev));
 543
 544        sprintf(dev->name, "dwmac.%lx", base_addr);
 545        dev->iobase = (int)base_addr;
 546        dev->priv = priv;
 547
 548        priv->dev = dev;
 549        priv->mac_regs_p = (struct eth_mac_regs *)base_addr;
 550        priv->dma_regs_p = (struct eth_dma_regs *)(base_addr +
 551                        DW_DMA_BASE_OFFSET);
 552
 553        dev->init = dw_eth_init;
 554        dev->send = dw_eth_send;
 555        dev->recv = dw_eth_recv;
 556        dev->halt = dw_eth_halt;
 557        dev->write_hwaddr = dw_write_hwaddr;
 558
 559        eth_register(dev);
 560
 561        priv->interface = interface;
 562
 563        dw_mdio_init(dev->name, priv->mac_regs_p);
 564        priv->bus = miiphy_get_dev_by_name(dev->name);
 565
 566        return dw_phy_init(priv, dev);
 567}
 568#endif
 569
 570#ifdef CONFIG_DM_ETH
 571static int designware_eth_start(struct udevice *dev)
 572{
 573        struct eth_pdata *pdata = dev_get_platdata(dev);
 574
 575        return _dw_eth_init(dev->priv, pdata->enetaddr);
 576}
 577
 578static int designware_eth_send(struct udevice *dev, void *packet, int length)
 579{
 580        struct dw_eth_dev *priv = dev_get_priv(dev);
 581
 582        return _dw_eth_send(priv, packet, length);
 583}
 584
 585static int designware_eth_recv(struct udevice *dev, int flags, uchar **packetp)
 586{
 587        struct dw_eth_dev *priv = dev_get_priv(dev);
 588
 589        return _dw_eth_recv(priv, packetp);
 590}
 591
 592static int designware_eth_free_pkt(struct udevice *dev, uchar *packet,
 593                                   int length)
 594{
 595        struct dw_eth_dev *priv = dev_get_priv(dev);
 596
 597        return _dw_free_pkt(priv);
 598}
 599
 600static void designware_eth_stop(struct udevice *dev)
 601{
 602        struct dw_eth_dev *priv = dev_get_priv(dev);
 603
 604        return _dw_eth_halt(priv);
 605}
 606
 607static int designware_eth_write_hwaddr(struct udevice *dev)
 608{
 609        struct eth_pdata *pdata = dev_get_platdata(dev);
 610        struct dw_eth_dev *priv = dev_get_priv(dev);
 611
 612        return _dw_write_hwaddr(priv, pdata->enetaddr);
 613}
 614
 615static int designware_eth_bind(struct udevice *dev)
 616{
 617#ifdef CONFIG_DM_PCI
 618        static int num_cards;
 619        char name[20];
 620
 621        /* Create a unique device name for PCI type devices */
 622        if (device_is_on_pci_bus(dev)) {
 623                sprintf(name, "eth_designware#%u", num_cards++);
 624                device_set_name(dev, name);
 625        }
 626#endif
 627
 628        return 0;
 629}
 630
 631static int designware_eth_probe(struct udevice *dev)
 632{
 633        struct eth_pdata *pdata = dev_get_platdata(dev);
 634        struct dw_eth_dev *priv = dev_get_priv(dev);
 635        u32 iobase = pdata->iobase;
 636        ulong ioaddr;
 637        int ret;
 638
 639#ifdef CONFIG_DM_PCI
 640        /*
 641         * If we are on PCI bus, either directly attached to a PCI root port,
 642         * or via a PCI bridge, fill in platdata before we probe the hardware.
 643         */
 644        if (device_is_on_pci_bus(dev)) {
 645                dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0, &iobase);
 646                iobase &= PCI_BASE_ADDRESS_MEM_MASK;
 647                iobase = dm_pci_mem_to_phys(dev, iobase);
 648
 649                pdata->iobase = iobase;
 650                pdata->phy_interface = PHY_INTERFACE_MODE_RMII;
 651        }
 652#endif
 653
 654        debug("%s, iobase=%x, priv=%p\n", __func__, iobase, priv);
 655        ioaddr = iobase;
 656        priv->mac_regs_p = (struct eth_mac_regs *)ioaddr;
 657        priv->dma_regs_p = (struct eth_dma_regs *)(ioaddr + DW_DMA_BASE_OFFSET);
 658        priv->interface = pdata->phy_interface;
 659        priv->max_speed = pdata->max_speed;
 660
 661        dw_mdio_init(dev->name, dev);
 662        priv->bus = miiphy_get_dev_by_name(dev->name);
 663
 664        ret = dw_phy_init(priv, dev);
 665        debug("%s, ret=%d\n", __func__, ret);
 666
 667        return ret;
 668}
 669
 670static int designware_eth_remove(struct udevice *dev)
 671{
 672        struct dw_eth_dev *priv = dev_get_priv(dev);
 673
 674        free(priv->phydev);
 675        mdio_unregister(priv->bus);
 676        mdio_free(priv->bus);
 677
 678        return 0;
 679}
 680
 681static const struct eth_ops designware_eth_ops = {
 682        .start                  = designware_eth_start,
 683        .send                   = designware_eth_send,
 684        .recv                   = designware_eth_recv,
 685        .free_pkt               = designware_eth_free_pkt,
 686        .stop                   = designware_eth_stop,
 687        .write_hwaddr           = designware_eth_write_hwaddr,
 688};
 689
 690static int designware_eth_ofdata_to_platdata(struct udevice *dev)
 691{
 692        struct dw_eth_pdata *dw_pdata = dev_get_platdata(dev);
 693#ifdef CONFIG_DM_GPIO
 694        struct dw_eth_dev *priv = dev_get_priv(dev);
 695#endif
 696        struct eth_pdata *pdata = &dw_pdata->eth_pdata;
 697        const char *phy_mode;
 698        const fdt32_t *cell;
 699#ifdef CONFIG_DM_GPIO
 700        int reset_flags = GPIOD_IS_OUT;
 701#endif
 702        int ret = 0;
 703
 704        pdata->iobase = dev_get_addr(dev);
 705        pdata->phy_interface = -1;
 706        phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy-mode", NULL);
 707        if (phy_mode)
 708                pdata->phy_interface = phy_get_interface_by_name(phy_mode);
 709        if (pdata->phy_interface == -1) {
 710                debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
 711                return -EINVAL;
 712        }
 713
 714        pdata->max_speed = 0;
 715        cell = fdt_getprop(gd->fdt_blob, dev->of_offset, "max-speed", NULL);
 716        if (cell)
 717                pdata->max_speed = fdt32_to_cpu(*cell);
 718
 719#ifdef CONFIG_DM_GPIO
 720        if (fdtdec_get_bool(gd->fdt_blob, dev->of_offset,
 721                            "snps,reset-active-low"))
 722                reset_flags |= GPIOD_ACTIVE_LOW;
 723
 724        ret = gpio_request_by_name(dev, "snps,reset-gpio", 0,
 725                &priv->reset_gpio, reset_flags);
 726        if (ret == 0) {
 727                ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
 728                        "snps,reset-delays-us", dw_pdata->reset_delays, 3);
 729        } else if (ret == -ENOENT) {
 730                ret = 0;
 731        }
 732#endif
 733
 734        return ret;
 735}
 736
 737static const struct udevice_id designware_eth_ids[] = {
 738        { .compatible = "allwinner,sun7i-a20-gmac" },
 739        { .compatible = "altr,socfpga-stmmac" },
 740        { .compatible = "amlogic,meson6-dwmac" },
 741        { }
 742};
 743
 744U_BOOT_DRIVER(eth_designware) = {
 745        .name   = "eth_designware",
 746        .id     = UCLASS_ETH,
 747        .of_match = designware_eth_ids,
 748        .ofdata_to_platdata = designware_eth_ofdata_to_platdata,
 749        .bind   = designware_eth_bind,
 750        .probe  = designware_eth_probe,
 751        .remove = designware_eth_remove,
 752        .ops    = &designware_eth_ops,
 753        .priv_auto_alloc_size = sizeof(struct dw_eth_dev),
 754        .platdata_auto_alloc_size = sizeof(struct dw_eth_pdata),
 755        .flags = DM_FLAG_ALLOC_PRIV_DMA,
 756};
 757
 758static struct pci_device_id supported[] = {
 759        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_EMAC) },
 760        { }
 761};
 762
 763U_BOOT_PCI_DEVICE(eth_designware, supported);
 764#endif
 765