uboot/drivers/net/pch_gbe.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
   4 *
   5 * Intel Platform Controller Hub EG20T (codename Topcliff) GMAC Driver
   6 */
   7
   8#include <common.h>
   9#include <cpu_func.h>
  10#include <dm.h>
  11#include <errno.h>
  12#include <log.h>
  13#include <malloc.h>
  14#include <asm/io.h>
  15#include <pci.h>
  16#include <miiphy.h>
  17#include <linux/delay.h>
  18#include "pch_gbe.h"
  19
  20#if !defined(CONFIG_PHYLIB)
  21# error "PCH Gigabit Ethernet driver requires PHYLIB - missing CONFIG_PHYLIB"
  22#endif
  23
  24static struct pci_device_id supported[] = {
  25        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_GBE) },
  26        { }
  27};
  28
  29static void pch_gbe_mac_read(struct pch_gbe_regs *mac_regs, u8 *addr)
  30{
  31        u32 macid_hi, macid_lo;
  32
  33        macid_hi = readl(&mac_regs->mac_adr[0].high);
  34        macid_lo = readl(&mac_regs->mac_adr[0].low) & 0xffff;
  35        debug("pch_gbe: macid_hi %#x macid_lo %#x\n", macid_hi, macid_lo);
  36
  37        addr[0] = (u8)(macid_hi & 0xff);
  38        addr[1] = (u8)((macid_hi >> 8) & 0xff);
  39        addr[2] = (u8)((macid_hi >> 16) & 0xff);
  40        addr[3] = (u8)((macid_hi >> 24) & 0xff);
  41        addr[4] = (u8)(macid_lo & 0xff);
  42        addr[5] = (u8)((macid_lo >> 8) & 0xff);
  43}
  44
  45static int pch_gbe_mac_write(struct pch_gbe_regs *mac_regs, u8 *addr)
  46{
  47        u32 macid_hi, macid_lo;
  48        ulong start;
  49
  50        macid_hi = addr[0] + (addr[1] << 8) + (addr[2] << 16) + (addr[3] << 24);
  51        macid_lo = addr[4] + (addr[5] << 8);
  52
  53        writel(macid_hi, &mac_regs->mac_adr[0].high);
  54        writel(macid_lo, &mac_regs->mac_adr[0].low);
  55        writel(0xfffe, &mac_regs->addr_mask);
  56
  57        start = get_timer(0);
  58        while (get_timer(start) < PCH_GBE_TIMEOUT) {
  59                if (!(readl(&mac_regs->addr_mask) & PCH_GBE_BUSY))
  60                        return 0;
  61
  62                udelay(10);
  63        }
  64
  65        return -ETIME;
  66}
  67
  68static int pch_gbe_reset(struct udevice *dev)
  69{
  70        struct pch_gbe_priv *priv = dev_get_priv(dev);
  71        struct eth_pdata *plat = dev_get_plat(dev);
  72        struct pch_gbe_regs *mac_regs = priv->mac_regs;
  73        ulong start;
  74
  75        priv->rx_idx = 0;
  76        priv->tx_idx = 0;
  77
  78        writel(PCH_GBE_ALL_RST, &mac_regs->reset);
  79
  80        /*
  81         * Configure the MAC to RGMII mode after reset
  82         *
  83         * For some unknown reason, we must do the configuration here right
  84         * after resetting the whole MAC, otherwise the reset bit in the RESET
  85         * register will never be cleared by the hardware. And there is another
  86         * way of having the same magic, that is to configure the MODE register
  87         * to have the MAC work in MII/GMII mode, which is how current Linux
  88         * pch_gbe driver does. Since anyway we need program the MAC to RGMII
  89         * mode in the driver, we just do it here.
  90         *
  91         * Note: this behavior is not documented in the hardware manual.
  92         */
  93        writel(PCH_GBE_RGMII_MODE_RGMII | PCH_GBE_CHIP_TYPE_INTERNAL,
  94               &mac_regs->rgmii_ctrl);
  95
  96        start = get_timer(0);
  97        while (get_timer(start) < PCH_GBE_TIMEOUT) {
  98                if (!(readl(&mac_regs->reset) & PCH_GBE_ALL_RST)) {
  99                        /*
 100                         * Soft reset clears hardware MAC address registers,
 101                         * so we have to reload MAC address here in order to
 102                         * make linux pch_gbe driver happy.
 103                         */
 104                        return pch_gbe_mac_write(mac_regs, plat->enetaddr);
 105                }
 106
 107                udelay(10);
 108        }
 109
 110        debug("pch_gbe: reset timeout\n");
 111        return -ETIME;
 112}
 113
 114static void pch_gbe_rx_descs_init(struct udevice *dev)
 115{
 116        struct pch_gbe_priv *priv = dev_get_priv(dev);
 117        struct pch_gbe_regs *mac_regs = priv->mac_regs;
 118        struct pch_gbe_rx_desc *rx_desc = &priv->rx_desc[0];
 119        int i;
 120
 121        memset(rx_desc, 0, sizeof(struct pch_gbe_rx_desc) * PCH_GBE_DESC_NUM);
 122        for (i = 0; i < PCH_GBE_DESC_NUM; i++)
 123                rx_desc[i].buffer_addr = dm_pci_virt_to_mem(priv->dev,
 124                        priv->rx_buff[i]);
 125
 126        flush_dcache_range((ulong)rx_desc, (ulong)&rx_desc[PCH_GBE_DESC_NUM]);
 127
 128        writel(dm_pci_virt_to_mem(priv->dev, rx_desc),
 129               &mac_regs->rx_dsc_base);
 130        writel(sizeof(struct pch_gbe_rx_desc) * (PCH_GBE_DESC_NUM - 1),
 131               &mac_regs->rx_dsc_size);
 132
 133        writel(dm_pci_virt_to_mem(priv->dev, rx_desc + 1),
 134               &mac_regs->rx_dsc_sw_p);
 135}
 136
 137static void pch_gbe_tx_descs_init(struct udevice *dev)
 138{
 139        struct pch_gbe_priv *priv = dev_get_priv(dev);
 140        struct pch_gbe_regs *mac_regs = priv->mac_regs;
 141        struct pch_gbe_tx_desc *tx_desc = &priv->tx_desc[0];
 142
 143        memset(tx_desc, 0, sizeof(struct pch_gbe_tx_desc) * PCH_GBE_DESC_NUM);
 144
 145        flush_dcache_range((ulong)tx_desc, (ulong)&tx_desc[PCH_GBE_DESC_NUM]);
 146
 147        writel(dm_pci_virt_to_mem(priv->dev, tx_desc),
 148               &mac_regs->tx_dsc_base);
 149        writel(sizeof(struct pch_gbe_tx_desc) * (PCH_GBE_DESC_NUM - 1),
 150               &mac_regs->tx_dsc_size);
 151        writel(dm_pci_virt_to_mem(priv->dev, tx_desc + 1),
 152               &mac_regs->tx_dsc_sw_p);
 153}
 154
 155static void pch_gbe_adjust_link(struct pch_gbe_regs *mac_regs,
 156                                struct phy_device *phydev)
 157{
 158        if (!phydev->link) {
 159                printf("%s: No link.\n", phydev->dev->name);
 160                return;
 161        }
 162
 163        clrbits_le32(&mac_regs->rgmii_ctrl,
 164                     PCH_GBE_RGMII_RATE_2_5M | PCH_GBE_CRS_SEL);
 165        clrbits_le32(&mac_regs->mode,
 166                     PCH_GBE_MODE_GMII_ETHER | PCH_GBE_MODE_FULL_DUPLEX);
 167
 168        switch (phydev->speed) {
 169        case 1000:
 170                setbits_le32(&mac_regs->rgmii_ctrl, PCH_GBE_RGMII_RATE_125M);
 171                setbits_le32(&mac_regs->mode, PCH_GBE_MODE_GMII_ETHER);
 172                break;
 173        case 100:
 174                setbits_le32(&mac_regs->rgmii_ctrl, PCH_GBE_RGMII_RATE_25M);
 175                setbits_le32(&mac_regs->mode, PCH_GBE_MODE_MII_ETHER);
 176                break;
 177        case 10:
 178                setbits_le32(&mac_regs->rgmii_ctrl, PCH_GBE_RGMII_RATE_2_5M);
 179                setbits_le32(&mac_regs->mode, PCH_GBE_MODE_MII_ETHER);
 180                break;
 181        }
 182
 183        if (phydev->duplex) {
 184                setbits_le32(&mac_regs->rgmii_ctrl, PCH_GBE_CRS_SEL);
 185                setbits_le32(&mac_regs->mode, PCH_GBE_MODE_FULL_DUPLEX);
 186        }
 187
 188        printf("Speed: %d, %s duplex\n", phydev->speed,
 189               (phydev->duplex) ? "full" : "half");
 190
 191        return;
 192}
 193
 194static int pch_gbe_start(struct udevice *dev)
 195{
 196        struct pch_gbe_priv *priv = dev_get_priv(dev);
 197        struct pch_gbe_regs *mac_regs = priv->mac_regs;
 198
 199        if (pch_gbe_reset(dev))
 200                return -1;
 201
 202        pch_gbe_rx_descs_init(dev);
 203        pch_gbe_tx_descs_init(dev);
 204
 205        /* Enable frame bursting */
 206        writel(PCH_GBE_MODE_FR_BST, &mac_regs->mode);
 207        /* Disable TCP/IP accelerator */
 208        writel(PCH_GBE_RX_TCPIPACC_OFF, &mac_regs->tcpip_acc);
 209        /* Disable RX flow control */
 210        writel(0, &mac_regs->rx_fctrl);
 211        /* Configure RX/TX mode */
 212        writel(PCH_GBE_RH_ALM_EMP_16 | PCH_GBE_RH_ALM_FULL_16 |
 213               PCH_GBE_RH_RD_TRG_32, &mac_regs->rx_mode);
 214        writel(PCH_GBE_TM_TH_TX_STRT_32 | PCH_GBE_TM_TH_ALM_EMP_16 |
 215               PCH_GBE_TM_TH_ALM_FULL_32 | PCH_GBE_TM_ST_AND_FD |
 216               PCH_GBE_TM_SHORT_PKT, &mac_regs->tx_mode);
 217
 218        /* Start up the PHY */
 219        if (phy_startup(priv->phydev)) {
 220                printf("Could not initialize PHY %s\n",
 221                       priv->phydev->dev->name);
 222                return -1;
 223        }
 224
 225        pch_gbe_adjust_link(mac_regs, priv->phydev);
 226
 227        if (!priv->phydev->link)
 228                return -1;
 229
 230        /* Enable TX & RX */
 231        writel(PCH_GBE_RX_DMA_EN | PCH_GBE_TX_DMA_EN, &mac_regs->dma_ctrl);
 232        writel(PCH_GBE_MRE_MAC_RX_EN, &mac_regs->mac_rx_en);
 233
 234        return 0;
 235}
 236
 237static void pch_gbe_stop(struct udevice *dev)
 238{
 239        struct pch_gbe_priv *priv = dev_get_priv(dev);
 240
 241        pch_gbe_reset(dev);
 242
 243        phy_shutdown(priv->phydev);
 244}
 245
 246static int pch_gbe_send(struct udevice *dev, void *packet, int length)
 247{
 248        struct pch_gbe_priv *priv = dev_get_priv(dev);
 249        struct pch_gbe_regs *mac_regs = priv->mac_regs;
 250        struct pch_gbe_tx_desc *tx_head, *tx_desc;
 251        u16 frame_ctrl = 0;
 252        u32 int_st;
 253        ulong start;
 254
 255        flush_dcache_range((ulong)packet, (ulong)packet + length);
 256
 257        tx_head = &priv->tx_desc[0];
 258        tx_desc = &priv->tx_desc[priv->tx_idx];
 259
 260        if (length < 64)
 261                frame_ctrl |= PCH_GBE_TXD_CTRL_APAD;
 262
 263        tx_desc->buffer_addr = dm_pci_virt_to_mem(priv->dev, packet);
 264        tx_desc->length = length;
 265        tx_desc->tx_words_eob = length + 3;
 266        tx_desc->tx_frame_ctrl = frame_ctrl;
 267        tx_desc->dma_status = 0;
 268        tx_desc->gbec_status = 0;
 269
 270        flush_dcache_range((ulong)tx_desc, (ulong)&tx_desc[1]);
 271
 272        /* Test the wrap-around condition */
 273        if (++priv->tx_idx >= PCH_GBE_DESC_NUM)
 274                priv->tx_idx = 0;
 275
 276        writel(dm_pci_virt_to_mem(priv->dev, tx_head + priv->tx_idx),
 277               &mac_regs->tx_dsc_sw_p);
 278
 279        start = get_timer(0);
 280        while (get_timer(start) < PCH_GBE_TIMEOUT) {
 281                int_st = readl(&mac_regs->int_st);
 282                if (int_st & PCH_GBE_INT_TX_CMPLT)
 283                        return 0;
 284
 285                udelay(10);
 286        }
 287
 288        debug("pch_gbe: sent failed\n");
 289        return -ETIME;
 290}
 291
 292static int pch_gbe_recv(struct udevice *dev, int flags, uchar **packetp)
 293{
 294        struct pch_gbe_priv *priv = dev_get_priv(dev);
 295        struct pch_gbe_regs *mac_regs = priv->mac_regs;
 296        struct pch_gbe_rx_desc *rx_desc;
 297        ulong hw_desc, length;
 298        void *buffer;
 299
 300        rx_desc = &priv->rx_desc[priv->rx_idx];
 301
 302        readl(&mac_regs->int_st);
 303        hw_desc = readl(&mac_regs->rx_dsc_hw_p_hld);
 304
 305        /* Just return if not receiving any packet */
 306        if (virt_to_phys(rx_desc) == hw_desc)
 307                return -EAGAIN;
 308
 309        /* Invalidate the descriptor */
 310        invalidate_dcache_range((ulong)rx_desc, (ulong)&rx_desc[1]);
 311
 312        length = rx_desc->rx_words_eob - 3 - ETH_FCS_LEN;
 313        buffer = dm_pci_mem_to_virt(priv->dev, rx_desc->buffer_addr, length, 0);
 314        invalidate_dcache_range((ulong)buffer, (ulong)buffer + length);
 315        *packetp = (uchar *)buffer;
 316
 317        return length;
 318}
 319
 320static int pch_gbe_free_pkt(struct udevice *dev, uchar *packet, int length)
 321{
 322        struct pch_gbe_priv *priv = dev_get_priv(dev);
 323        struct pch_gbe_regs *mac_regs = priv->mac_regs;
 324        struct pch_gbe_rx_desc *rx_head = &priv->rx_desc[0];
 325        int rx_swp;
 326
 327        /* Test the wrap-around condition */
 328        if (++priv->rx_idx >= PCH_GBE_DESC_NUM)
 329                priv->rx_idx = 0;
 330        rx_swp = priv->rx_idx;
 331        if (++rx_swp >= PCH_GBE_DESC_NUM)
 332                rx_swp = 0;
 333
 334        writel(dm_pci_virt_to_mem(priv->dev, rx_head + rx_swp),
 335               &mac_regs->rx_dsc_sw_p);
 336
 337        return 0;
 338}
 339
 340static int pch_gbe_mdio_ready(struct pch_gbe_regs *mac_regs)
 341{
 342        ulong start = get_timer(0);
 343
 344        while (get_timer(start) < PCH_GBE_TIMEOUT) {
 345                if (readl(&mac_regs->miim) & PCH_GBE_MIIM_OPER_READY)
 346                        return 0;
 347
 348                udelay(10);
 349        }
 350
 351        return -ETIME;
 352}
 353
 354static int pch_gbe_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
 355{
 356        struct pch_gbe_regs *mac_regs = bus->priv;
 357        u32 miim;
 358
 359        if (pch_gbe_mdio_ready(mac_regs))
 360                return -ETIME;
 361
 362        miim = (addr << PCH_GBE_MIIM_PHY_ADDR_SHIFT) |
 363               (reg << PCH_GBE_MIIM_REG_ADDR_SHIFT) |
 364               PCH_GBE_MIIM_OPER_READ;
 365        writel(miim, &mac_regs->miim);
 366
 367        if (pch_gbe_mdio_ready(mac_regs))
 368                return -ETIME;
 369
 370        return readl(&mac_regs->miim) & 0xffff;
 371}
 372
 373static int pch_gbe_mdio_write(struct mii_dev *bus, int addr, int devad,
 374                              int reg, u16 val)
 375{
 376        struct pch_gbe_regs *mac_regs = bus->priv;
 377        u32 miim;
 378
 379        if (pch_gbe_mdio_ready(mac_regs))
 380                return -ETIME;
 381
 382        miim = (addr << PCH_GBE_MIIM_PHY_ADDR_SHIFT) |
 383               (reg << PCH_GBE_MIIM_REG_ADDR_SHIFT) |
 384               PCH_GBE_MIIM_OPER_WRITE | val;
 385        writel(miim, &mac_regs->miim);
 386
 387        if (pch_gbe_mdio_ready(mac_regs))
 388                return -ETIME;
 389        else
 390                return 0;
 391}
 392
 393static int pch_gbe_mdio_init(const char *name, struct pch_gbe_regs *mac_regs)
 394{
 395        struct mii_dev *bus;
 396
 397        bus = mdio_alloc();
 398        if (!bus) {
 399                debug("pch_gbe: failed to allocate MDIO bus\n");
 400                return -ENOMEM;
 401        }
 402
 403        bus->read = pch_gbe_mdio_read;
 404        bus->write = pch_gbe_mdio_write;
 405        strcpy(bus->name, name);
 406
 407        bus->priv = (void *)mac_regs;
 408
 409        return mdio_register(bus);
 410}
 411
 412static int pch_gbe_phy_init(struct udevice *dev)
 413{
 414        struct pch_gbe_priv *priv = dev_get_priv(dev);
 415        struct eth_pdata *plat = dev_get_plat(dev);
 416        struct phy_device *phydev;
 417        int mask = 0xffffffff;
 418
 419        phydev = phy_find_by_mask(priv->bus, mask, plat->phy_interface);
 420        if (!phydev) {
 421                printf("pch_gbe: cannot find the phy\n");
 422                return -1;
 423        }
 424
 425        phy_connect_dev(phydev, dev);
 426
 427        phydev->supported &= PHY_GBIT_FEATURES;
 428        phydev->advertising = phydev->supported;
 429
 430        priv->phydev = phydev;
 431        phy_config(phydev);
 432
 433        return 0;
 434}
 435
 436static int pch_gbe_probe(struct udevice *dev)
 437{
 438        struct pch_gbe_priv *priv;
 439        struct eth_pdata *plat = dev_get_plat(dev);
 440        void *iobase;
 441        int err;
 442
 443        /*
 444         * The priv structure contains the descriptors and frame buffers which
 445         * need a strict buswidth alignment (64 bytes). This is guaranteed by
 446         * DM_FLAG_ALLOC_PRIV_DMA flag in the U_BOOT_DRIVER.
 447         */
 448        priv = dev_get_priv(dev);
 449
 450        priv->dev = dev;
 451
 452        iobase = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_1, PCI_REGION_MEM);
 453
 454        plat->iobase = (ulong)iobase;
 455        priv->mac_regs = (struct pch_gbe_regs *)iobase;
 456
 457        /* Read MAC address from SROM and initialize dev->enetaddr with it */
 458        pch_gbe_mac_read(priv->mac_regs, plat->enetaddr);
 459
 460        plat->phy_interface = PHY_INTERFACE_MODE_RGMII;
 461        pch_gbe_mdio_init(dev->name, priv->mac_regs);
 462        priv->bus = miiphy_get_dev_by_name(dev->name);
 463
 464        err = pch_gbe_reset(dev);
 465        if (err)
 466                return err;
 467
 468        return pch_gbe_phy_init(dev);
 469}
 470
 471static int pch_gbe_remove(struct udevice *dev)
 472{
 473        struct pch_gbe_priv *priv = dev_get_priv(dev);
 474
 475        free(priv->phydev);
 476        mdio_unregister(priv->bus);
 477        mdio_free(priv->bus);
 478
 479        return 0;
 480}
 481
 482static const struct eth_ops pch_gbe_ops = {
 483        .start = pch_gbe_start,
 484        .send = pch_gbe_send,
 485        .recv = pch_gbe_recv,
 486        .free_pkt = pch_gbe_free_pkt,
 487        .stop = pch_gbe_stop,
 488};
 489
 490static const struct udevice_id pch_gbe_ids[] = {
 491        { .compatible = "intel,pch-gbe" },
 492        { }
 493};
 494
 495U_BOOT_DRIVER(eth_pch_gbe) = {
 496        .name = "pch_gbe",
 497        .id = UCLASS_ETH,
 498        .of_match = pch_gbe_ids,
 499        .probe = pch_gbe_probe,
 500        .remove = pch_gbe_remove,
 501        .ops = &pch_gbe_ops,
 502        .priv_auto      = sizeof(struct pch_gbe_priv),
 503        .plat_auto      = sizeof(struct eth_pdata),
 504        .flags = DM_FLAG_ALLOC_PRIV_DMA,
 505};
 506
 507U_BOOT_PCI_DEVICE(eth_pch_gbe, supported);
 508