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