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 int dw_adjust_link(struct dw_eth_dev *priv, 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 0;
 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        return 0;
 261}
 262
 263static void _dw_eth_halt(struct dw_eth_dev *priv)
 264{
 265        struct eth_mac_regs *mac_p = priv->mac_regs_p;
 266        struct eth_dma_regs *dma_p = priv->dma_regs_p;
 267
 268        writel(readl(&mac_p->conf) & ~(RXENABLE | TXENABLE), &mac_p->conf);
 269        writel(readl(&dma_p->opmode) & ~(RXSTART | TXSTART), &dma_p->opmode);
 270
 271        phy_shutdown(priv->phydev);
 272}
 273
 274int designware_eth_init(struct dw_eth_dev *priv, u8 *enetaddr)
 275{
 276        struct eth_mac_regs *mac_p = priv->mac_regs_p;
 277        struct eth_dma_regs *dma_p = priv->dma_regs_p;
 278        unsigned int start;
 279        int ret;
 280
 281        writel(readl(&dma_p->busmode) | DMAMAC_SRST, &dma_p->busmode);
 282
 283        start = get_timer(0);
 284        while (readl(&dma_p->busmode) & DMAMAC_SRST) {
 285                if (get_timer(start) >= CONFIG_MACRESET_TIMEOUT) {
 286                        printf("DMA reset timeout\n");
 287                        return -ETIMEDOUT;
 288                }
 289
 290                mdelay(100);
 291        };
 292
 293        /*
 294         * Soft reset above clears HW address registers.
 295         * So we have to set it here once again.
 296         */
 297        _dw_write_hwaddr(priv, enetaddr);
 298
 299        rx_descs_init(priv);
 300        tx_descs_init(priv);
 301
 302        writel(FIXEDBURST | PRIORXTX_41 | DMA_PBL, &dma_p->busmode);
 303
 304#ifndef CONFIG_DW_MAC_FORCE_THRESHOLD_MODE
 305        writel(readl(&dma_p->opmode) | FLUSHTXFIFO | STOREFORWARD,
 306               &dma_p->opmode);
 307#else
 308        writel(readl(&dma_p->opmode) | FLUSHTXFIFO,
 309               &dma_p->opmode);
 310#endif
 311
 312        writel(readl(&dma_p->opmode) | RXSTART | TXSTART, &dma_p->opmode);
 313
 314#ifdef CONFIG_DW_AXI_BURST_LEN
 315        writel((CONFIG_DW_AXI_BURST_LEN & 0x1FF >> 1), &dma_p->axibus);
 316#endif
 317
 318        /* Start up the PHY */
 319        ret = phy_startup(priv->phydev);
 320        if (ret) {
 321                printf("Could not initialize PHY %s\n",
 322                       priv->phydev->dev->name);
 323                return ret;
 324        }
 325
 326        ret = dw_adjust_link(priv, mac_p, priv->phydev);
 327        if (ret)
 328                return ret;
 329
 330        return 0;
 331}
 332
 333int designware_eth_enable(struct dw_eth_dev *priv)
 334{
 335        struct eth_mac_regs *mac_p = priv->mac_regs_p;
 336
 337        if (!priv->phydev->link)
 338                return -EIO;
 339
 340        writel(readl(&mac_p->conf) | RXENABLE | TXENABLE, &mac_p->conf);
 341
 342        return 0;
 343}
 344
 345static int _dw_eth_send(struct dw_eth_dev *priv, void *packet, int length)
 346{
 347        struct eth_dma_regs *dma_p = priv->dma_regs_p;
 348        u32 desc_num = priv->tx_currdescnum;
 349        struct dmamacdescr *desc_p = &priv->tx_mac_descrtable[desc_num];
 350        ulong desc_start = (ulong)desc_p;
 351        ulong desc_end = desc_start +
 352                roundup(sizeof(*desc_p), ARCH_DMA_MINALIGN);
 353        ulong data_start = desc_p->dmamac_addr;
 354        ulong data_end = data_start + roundup(length, ARCH_DMA_MINALIGN);
 355        /*
 356         * Strictly we only need to invalidate the "txrx_status" field
 357         * for the following check, but on some platforms we cannot
 358         * invalidate only 4 bytes, so we flush the entire descriptor,
 359         * which is 16 bytes in total. This is safe because the
 360         * individual descriptors in the array are each aligned to
 361         * ARCH_DMA_MINALIGN and padded appropriately.
 362         */
 363        invalidate_dcache_range(desc_start, desc_end);
 364
 365        /* Check if the descriptor is owned by CPU */
 366        if (desc_p->txrx_status & DESC_TXSTS_OWNBYDMA) {
 367                printf("CPU not owner of tx frame\n");
 368                return -EPERM;
 369        }
 370
 371        memcpy((void *)data_start, packet, length);
 372
 373        /* Flush data to be sent */
 374        flush_dcache_range(data_start, data_end);
 375
 376#if defined(CONFIG_DW_ALTDESCRIPTOR)
 377        desc_p->txrx_status |= DESC_TXSTS_TXFIRST | DESC_TXSTS_TXLAST;
 378        desc_p->dmamac_cntl |= (length << DESC_TXCTRL_SIZE1SHFT) &
 379                               DESC_TXCTRL_SIZE1MASK;
 380
 381        desc_p->txrx_status &= ~(DESC_TXSTS_MSK);
 382        desc_p->txrx_status |= DESC_TXSTS_OWNBYDMA;
 383#else
 384        desc_p->dmamac_cntl |= ((length << DESC_TXCTRL_SIZE1SHFT) &
 385                               DESC_TXCTRL_SIZE1MASK) | DESC_TXCTRL_TXLAST |
 386                               DESC_TXCTRL_TXFIRST;
 387
 388        desc_p->txrx_status = DESC_TXSTS_OWNBYDMA;
 389#endif
 390
 391        /* Flush modified buffer descriptor */
 392        flush_dcache_range(desc_start, desc_end);
 393
 394        /* Test the wrap-around condition. */
 395        if (++desc_num >= CONFIG_TX_DESCR_NUM)
 396                desc_num = 0;
 397
 398        priv->tx_currdescnum = desc_num;
 399
 400        /* Start the transmission */
 401        writel(POLL_DATA, &dma_p->txpolldemand);
 402
 403        return 0;
 404}
 405
 406static int _dw_eth_recv(struct dw_eth_dev *priv, uchar **packetp)
 407{
 408        u32 status, desc_num = priv->rx_currdescnum;
 409        struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num];
 410        int length = -EAGAIN;
 411        ulong desc_start = (ulong)desc_p;
 412        ulong desc_end = desc_start +
 413                roundup(sizeof(*desc_p), ARCH_DMA_MINALIGN);
 414        ulong data_start = desc_p->dmamac_addr;
 415        ulong data_end;
 416
 417        /* Invalidate entire buffer descriptor */
 418        invalidate_dcache_range(desc_start, desc_end);
 419
 420        status = desc_p->txrx_status;
 421
 422        /* Check  if the owner is the CPU */
 423        if (!(status & DESC_RXSTS_OWNBYDMA)) {
 424
 425                length = (status & DESC_RXSTS_FRMLENMSK) >>
 426                         DESC_RXSTS_FRMLENSHFT;
 427
 428                /* Invalidate received data */
 429                data_end = data_start + roundup(length, ARCH_DMA_MINALIGN);
 430                invalidate_dcache_range(data_start, data_end);
 431                *packetp = (uchar *)(ulong)desc_p->dmamac_addr;
 432        }
 433
 434        return length;
 435}
 436
 437static int _dw_free_pkt(struct dw_eth_dev *priv)
 438{
 439        u32 desc_num = priv->rx_currdescnum;
 440        struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num];
 441        ulong desc_start = (ulong)desc_p;
 442        ulong desc_end = desc_start +
 443                roundup(sizeof(*desc_p), ARCH_DMA_MINALIGN);
 444
 445        /*
 446         * Make the current descriptor valid again and go to
 447         * the next one
 448         */
 449        desc_p->txrx_status |= DESC_RXSTS_OWNBYDMA;
 450
 451        /* Flush only status field - others weren't changed */
 452        flush_dcache_range(desc_start, desc_end);
 453
 454        /* Test the wrap-around condition. */
 455        if (++desc_num >= CONFIG_RX_DESCR_NUM)
 456                desc_num = 0;
 457        priv->rx_currdescnum = desc_num;
 458
 459        return 0;
 460}
 461
 462static int dw_phy_init(struct dw_eth_dev *priv, void *dev)
 463{
 464        struct phy_device *phydev;
 465        int mask = 0xffffffff, ret;
 466
 467#ifdef CONFIG_PHY_ADDR
 468        mask = 1 << CONFIG_PHY_ADDR;
 469#endif
 470
 471        phydev = phy_find_by_mask(priv->bus, mask, priv->interface);
 472        if (!phydev)
 473                return -ENODEV;
 474
 475        phy_connect_dev(phydev, dev);
 476
 477        phydev->supported &= PHY_GBIT_FEATURES;
 478        if (priv->max_speed) {
 479                ret = phy_set_supported(phydev, priv->max_speed);
 480                if (ret)
 481                        return ret;
 482        }
 483        phydev->advertising = phydev->supported;
 484
 485        priv->phydev = phydev;
 486        phy_config(phydev);
 487
 488        return 0;
 489}
 490
 491#ifndef CONFIG_DM_ETH
 492static int dw_eth_init(struct eth_device *dev, bd_t *bis)
 493{
 494        int ret;
 495
 496        ret = designware_eth_init(dev->priv, dev->enetaddr);
 497        if (!ret)
 498                ret = designware_eth_enable(dev->priv);
 499
 500        return ret;
 501}
 502
 503static int dw_eth_send(struct eth_device *dev, void *packet, int length)
 504{
 505        return _dw_eth_send(dev->priv, packet, length);
 506}
 507
 508static int dw_eth_recv(struct eth_device *dev)
 509{
 510        uchar *packet;
 511        int length;
 512
 513        length = _dw_eth_recv(dev->priv, &packet);
 514        if (length == -EAGAIN)
 515                return 0;
 516        net_process_received_packet(packet, length);
 517
 518        _dw_free_pkt(dev->priv);
 519
 520        return 0;
 521}
 522
 523static void dw_eth_halt(struct eth_device *dev)
 524{
 525        return _dw_eth_halt(dev->priv);
 526}
 527
 528static int dw_write_hwaddr(struct eth_device *dev)
 529{
 530        return _dw_write_hwaddr(dev->priv, dev->enetaddr);
 531}
 532
 533int designware_initialize(ulong base_addr, u32 interface)
 534{
 535        struct eth_device *dev;
 536        struct dw_eth_dev *priv;
 537
 538        dev = (struct eth_device *) malloc(sizeof(struct eth_device));
 539        if (!dev)
 540                return -ENOMEM;
 541
 542        /*
 543         * Since the priv structure contains the descriptors which need a strict
 544         * buswidth alignment, memalign is used to allocate memory
 545         */
 546        priv = (struct dw_eth_dev *) memalign(ARCH_DMA_MINALIGN,
 547                                              sizeof(struct dw_eth_dev));
 548        if (!priv) {
 549                free(dev);
 550                return -ENOMEM;
 551        }
 552
 553        if ((phys_addr_t)priv + sizeof(*priv) > (1ULL << 32)) {
 554                printf("designware: buffers are outside DMA memory\n");
 555                return -EINVAL;
 556        }
 557
 558        memset(dev, 0, sizeof(struct eth_device));
 559        memset(priv, 0, sizeof(struct dw_eth_dev));
 560
 561        sprintf(dev->name, "dwmac.%lx", base_addr);
 562        dev->iobase = (int)base_addr;
 563        dev->priv = priv;
 564
 565        priv->dev = dev;
 566        priv->mac_regs_p = (struct eth_mac_regs *)base_addr;
 567        priv->dma_regs_p = (struct eth_dma_regs *)(base_addr +
 568                        DW_DMA_BASE_OFFSET);
 569
 570        dev->init = dw_eth_init;
 571        dev->send = dw_eth_send;
 572        dev->recv = dw_eth_recv;
 573        dev->halt = dw_eth_halt;
 574        dev->write_hwaddr = dw_write_hwaddr;
 575
 576        eth_register(dev);
 577
 578        priv->interface = interface;
 579
 580        dw_mdio_init(dev->name, priv->mac_regs_p);
 581        priv->bus = miiphy_get_dev_by_name(dev->name);
 582
 583        return dw_phy_init(priv, dev);
 584}
 585#endif
 586
 587#ifdef CONFIG_DM_ETH
 588static int designware_eth_start(struct udevice *dev)
 589{
 590        struct eth_pdata *pdata = dev_get_platdata(dev);
 591        struct dw_eth_dev *priv = dev_get_priv(dev);
 592        int ret;
 593
 594        ret = designware_eth_init(priv, pdata->enetaddr);
 595        if (ret)
 596                return ret;
 597        ret = designware_eth_enable(priv);
 598        if (ret)
 599                return ret;
 600
 601        return 0;
 602}
 603
 604int designware_eth_send(struct udevice *dev, void *packet, int length)
 605{
 606        struct dw_eth_dev *priv = dev_get_priv(dev);
 607
 608        return _dw_eth_send(priv, packet, length);
 609}
 610
 611int designware_eth_recv(struct udevice *dev, int flags, uchar **packetp)
 612{
 613        struct dw_eth_dev *priv = dev_get_priv(dev);
 614
 615        return _dw_eth_recv(priv, packetp);
 616}
 617
 618int designware_eth_free_pkt(struct udevice *dev, uchar *packet, int length)
 619{
 620        struct dw_eth_dev *priv = dev_get_priv(dev);
 621
 622        return _dw_free_pkt(priv);
 623}
 624
 625void designware_eth_stop(struct udevice *dev)
 626{
 627        struct dw_eth_dev *priv = dev_get_priv(dev);
 628
 629        return _dw_eth_halt(priv);
 630}
 631
 632int designware_eth_write_hwaddr(struct udevice *dev)
 633{
 634        struct eth_pdata *pdata = dev_get_platdata(dev);
 635        struct dw_eth_dev *priv = dev_get_priv(dev);
 636
 637        return _dw_write_hwaddr(priv, pdata->enetaddr);
 638}
 639
 640static int designware_eth_bind(struct udevice *dev)
 641{
 642#ifdef CONFIG_DM_PCI
 643        static int num_cards;
 644        char name[20];
 645
 646        /* Create a unique device name for PCI type devices */
 647        if (device_is_on_pci_bus(dev)) {
 648                sprintf(name, "eth_designware#%u", num_cards++);
 649                device_set_name(dev, name);
 650        }
 651#endif
 652
 653        return 0;
 654}
 655
 656int designware_eth_probe(struct udevice *dev)
 657{
 658        struct eth_pdata *pdata = dev_get_platdata(dev);
 659        struct dw_eth_dev *priv = dev_get_priv(dev);
 660        u32 iobase = pdata->iobase;
 661        ulong ioaddr;
 662        int ret;
 663
 664#ifdef CONFIG_DM_PCI
 665        /*
 666         * If we are on PCI bus, either directly attached to a PCI root port,
 667         * or via a PCI bridge, fill in platdata before we probe the hardware.
 668         */
 669        if (device_is_on_pci_bus(dev)) {
 670                dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0, &iobase);
 671                iobase &= PCI_BASE_ADDRESS_MEM_MASK;
 672                iobase = dm_pci_mem_to_phys(dev, iobase);
 673
 674                pdata->iobase = iobase;
 675                pdata->phy_interface = PHY_INTERFACE_MODE_RMII;
 676        }
 677#endif
 678
 679        debug("%s, iobase=%x, priv=%p\n", __func__, iobase, priv);
 680        ioaddr = iobase;
 681        priv->mac_regs_p = (struct eth_mac_regs *)ioaddr;
 682        priv->dma_regs_p = (struct eth_dma_regs *)(ioaddr + DW_DMA_BASE_OFFSET);
 683        priv->interface = pdata->phy_interface;
 684        priv->max_speed = pdata->max_speed;
 685
 686        dw_mdio_init(dev->name, dev);
 687        priv->bus = miiphy_get_dev_by_name(dev->name);
 688
 689        ret = dw_phy_init(priv, dev);
 690        debug("%s, ret=%d\n", __func__, ret);
 691
 692        return ret;
 693}
 694
 695static int designware_eth_remove(struct udevice *dev)
 696{
 697        struct dw_eth_dev *priv = dev_get_priv(dev);
 698
 699        free(priv->phydev);
 700        mdio_unregister(priv->bus);
 701        mdio_free(priv->bus);
 702
 703        return 0;
 704}
 705
 706const struct eth_ops designware_eth_ops = {
 707        .start                  = designware_eth_start,
 708        .send                   = designware_eth_send,
 709        .recv                   = designware_eth_recv,
 710        .free_pkt               = designware_eth_free_pkt,
 711        .stop                   = designware_eth_stop,
 712        .write_hwaddr           = designware_eth_write_hwaddr,
 713};
 714
 715int designware_eth_ofdata_to_platdata(struct udevice *dev)
 716{
 717        struct dw_eth_pdata *dw_pdata = dev_get_platdata(dev);
 718#ifdef CONFIG_DM_GPIO
 719        struct dw_eth_dev *priv = dev_get_priv(dev);
 720#endif
 721        struct eth_pdata *pdata = &dw_pdata->eth_pdata;
 722        const char *phy_mode;
 723        const fdt32_t *cell;
 724#ifdef CONFIG_DM_GPIO
 725        int reset_flags = GPIOD_IS_OUT;
 726#endif
 727        int ret = 0;
 728
 729        pdata->iobase = dev_get_addr(dev);
 730        pdata->phy_interface = -1;
 731        phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
 732                               NULL);
 733        if (phy_mode)
 734                pdata->phy_interface = phy_get_interface_by_name(phy_mode);
 735        if (pdata->phy_interface == -1) {
 736                debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
 737                return -EINVAL;
 738        }
 739
 740        pdata->max_speed = 0;
 741        cell = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "max-speed", NULL);
 742        if (cell)
 743                pdata->max_speed = fdt32_to_cpu(*cell);
 744
 745#ifdef CONFIG_DM_GPIO
 746        if (fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
 747                            "snps,reset-active-low"))
 748                reset_flags |= GPIOD_ACTIVE_LOW;
 749
 750        ret = gpio_request_by_name(dev, "snps,reset-gpio", 0,
 751                &priv->reset_gpio, reset_flags);
 752        if (ret == 0) {
 753                ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev),
 754                        "snps,reset-delays-us", dw_pdata->reset_delays, 3);
 755        } else if (ret == -ENOENT) {
 756                ret = 0;
 757        }
 758#endif
 759
 760        return ret;
 761}
 762
 763static const struct udevice_id designware_eth_ids[] = {
 764        { .compatible = "allwinner,sun7i-a20-gmac" },
 765        { .compatible = "altr,socfpga-stmmac" },
 766        { .compatible = "amlogic,meson6-dwmac" },
 767        { .compatible = "amlogic,meson-gx-dwmac" },
 768        { .compatible = "st,stm32-dwmac" },
 769        { }
 770};
 771
 772U_BOOT_DRIVER(eth_designware) = {
 773        .name   = "eth_designware",
 774        .id     = UCLASS_ETH,
 775        .of_match = designware_eth_ids,
 776        .ofdata_to_platdata = designware_eth_ofdata_to_platdata,
 777        .bind   = designware_eth_bind,
 778        .probe  = designware_eth_probe,
 779        .remove = designware_eth_remove,
 780        .ops    = &designware_eth_ops,
 781        .priv_auto_alloc_size = sizeof(struct dw_eth_dev),
 782        .platdata_auto_alloc_size = sizeof(struct dw_eth_pdata),
 783        .flags = DM_FLAG_ALLOC_PRIV_DMA,
 784};
 785
 786static struct pci_device_id supported[] = {
 787        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_EMAC) },
 788        { }
 789};
 790
 791U_BOOT_PCI_DEVICE(eth_designware, supported);
 792#endif
 793