uboot/drivers/net/mscc_eswitch/felix_switch.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
   2/*
   3 * Felix (VSC9959) Ethernet switch driver
   4 * Copyright 2018-2021 NXP Semiconductors
   5 */
   6
   7/*
   8 * This driver is used for the Ethernet switch integrated into NXP LS1028A.
   9 * Felix switch is derived from Microsemi Ocelot but there are several NXP
  10 * adaptations that makes the two U-Boot drivers largely incompatible.
  11 *
  12 * Felix on LS1028A has 4 front panel ports and two internal ports, connected
  13 * to ENETC interfaces.  We're using one of the ENETC interfaces to push traffic
  14 * into the switch.  Injection/extraction headers are used to identify
  15 * egress/ingress ports in the switch for Tx/Rx.
  16 */
  17
  18#include <dm/device_compat.h>
  19#include <linux/delay.h>
  20#include <net/dsa.h>
  21#include <asm/io.h>
  22#include <miiphy.h>
  23#include <pci.h>
  24
  25/* defines especially around PCS are reused from enetc */
  26#include "../fsl_enetc.h"
  27
  28#define PCI_DEVICE_ID_FELIX_ETHSW       0xEEF0
  29
  30/* Felix has in fact 6 ports, but we don't use the last internal one */
  31#define FELIX_PORT_COUNT                5
  32/* Front panel port mask */
  33#define FELIX_FP_PORT_MASK              0xf
  34
  35/* Register map for BAR4 */
  36#define FELIX_SYS                       0x010000
  37#define FELIX_ES0                       0x040000
  38#define FELIX_IS1                       0x050000
  39#define FELIX_IS2                       0x060000
  40#define FELIX_GMII(port)                (0x100000 + (port) * 0x10000)
  41#define FELIX_QSYS                      0x200000
  42
  43#define FELIX_SYS_SYSTEM                (FELIX_SYS + 0x00000E00)
  44#define  FELIX_SYS_SYSTEM_EN            BIT(0)
  45#define FELIX_SYS_RAM_CTRL              (FELIX_SYS + 0x00000F24)
  46#define  FELIX_SYS_RAM_CTRL_INIT        BIT(1)
  47#define FELIX_SYS_SYSTEM_PORT_MODE(a)   (FELIX_SYS_SYSTEM + 0xC + (a) * 4)
  48#define  FELIX_SYS_SYSTEM_PORT_MODE_CPU 0x0000001e
  49
  50#define FELIX_ES0_TCAM_CTRL             (FELIX_ES0 + 0x000003C0)
  51#define  FELIX_ES0_TCAM_CTRL_EN         BIT(0)
  52#define FELIX_IS1_TCAM_CTRL             (FELIX_IS1 + 0x000003C0)
  53#define  FELIX_IS1_TCAM_CTRL_EN         BIT(0)
  54#define FELIX_IS2_TCAM_CTRL             (FELIX_IS2 + 0x000003C0)
  55#define  FELIX_IS2_TCAM_CTRL_EN         BIT(0)
  56
  57#define FELIX_GMII_CLOCK_CFG(port)      (FELIX_GMII(port) + 0x00000000)
  58#define  FELIX_GMII_CLOCK_CFG_LINK_1G   1
  59#define  FELIX_GMII_CLOCK_CFG_LINK_100M 2
  60#define  FELIX_GMII_CLOCK_CFG_LINK_10M  3
  61#define FELIX_GMII_MAC_ENA_CFG(port)    (FELIX_GMII(port) + 0x0000001C)
  62#define  FELIX_GMII_MAX_ENA_CFG_TX      BIT(0)
  63#define  FELIX_GMII_MAX_ENA_CFG_RX      BIT(4)
  64#define FELIX_GMII_MAC_IFG_CFG(port)    (FELIX_GMII(port) + 0x0000001C + 0x14)
  65#define  FELIX_GMII_MAC_IFG_CFG_DEF     0x515
  66
  67#define FELIX_QSYS_SYSTEM               (FELIX_QSYS + 0x0000F460)
  68#define FELIX_QSYS_SYSTEM_SW_PORT_MODE(a)       \
  69                                        (FELIX_QSYS_SYSTEM + 0x20 + (a) * 4)
  70#define  FELIX_QSYS_SYSTEM_SW_PORT_ENA          BIT(14)
  71#define  FELIX_QSYS_SYSTEM_SW_PORT_LOSSY        BIT(9)
  72#define  FELIX_QSYS_SYSTEM_SW_PORT_SCH(a)       (((a) & 0x3800) << 11)
  73#define FELIX_QSYS_SYSTEM_EXT_CPU_CFG   (FELIX_QSYS_SYSTEM + 0x80)
  74#define  FELIX_QSYS_SYSTEM_EXT_CPU_PORT(a)      (((a) & 0xf) << 8 | 0xff)
  75
  76/* internal MDIO in BAR0 */
  77#define FELIX_PM_IMDIO_BASE             0x8030
  78
  79/* Serdes block on LS1028A */
  80#define FELIX_SERDES_BASE               0x1ea0000L
  81#define FELIX_SERDES_LNATECR0(lane)     (FELIX_SERDES_BASE + 0x818 + \
  82                                         (lane) * 0x40)
  83#define  FELIX_SERDES_LNATECR0_ADPT_EQ  0x00003000
  84#define FELIX_SERDES_SGMIICR1(lane)     (FELIX_SERDES_BASE + 0x1804 + \
  85                                         (lane) * 0x10)
  86#define  FELIX_SERDES_SGMIICR1_SGPCS    BIT(11)
  87#define  FELIX_SERDES_SGMIICR1_MDEV(a)  (((a) & 0x1f) << 27)
  88
  89#define FELIX_PCS_CTRL                  0
  90#define  FELIX_PCS_CTRL_RST             BIT(15)
  91
  92/*
  93 * The long prefix format used here contains two dummy MAC addresses, a magic
  94 * value in place of a VLAN tag followed by the extraction/injection header and
  95 * the original L2 frame.  Out of all this we only use the port ID.
  96 */
  97#define FELIX_DSA_TAG_LEN               sizeof(struct felix_dsa_tag)
  98#define FELIX_DSA_TAG_MAGIC             0x0a008088
  99#define FELIX_DSA_TAG_INJ_PORT          7
 100#define  FELIX_DSA_TAG_INJ_PORT_SET(a)  (0x1 << ((a) & FELIX_FP_PORT_MASK))
 101#define FELIX_DSA_TAG_EXT_PORT          10
 102#define  FELIX_DSA_TAG_EXT_PORT_GET(a)  ((a) >> 3)
 103
 104struct felix_dsa_tag {
 105        uchar d_mac[6];
 106        uchar s_mac[6];
 107        u32   magic;
 108        uchar meta[16];
 109};
 110
 111struct felix_priv {
 112        void *regs_base;
 113        void *imdio_base;
 114        struct mii_dev imdio;
 115};
 116
 117/* MDIO wrappers, we're using these to drive internal MDIO to get to serdes */
 118static int felix_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
 119{
 120        struct enetc_mdio_priv priv;
 121
 122        priv.regs_base = bus->priv;
 123        return enetc_mdio_read_priv(&priv, addr, devad, reg);
 124}
 125
 126static int felix_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
 127                            u16 val)
 128{
 129        struct enetc_mdio_priv priv;
 130
 131        priv.regs_base = bus->priv;
 132        return enetc_mdio_write_priv(&priv, addr, devad, reg, val);
 133}
 134
 135/* set up serdes for SGMII */
 136static void felix_init_sgmii(struct mii_dev *imdio, int pidx, bool an)
 137{
 138        u16 reg;
 139
 140        /* set up PCS lane address */
 141        out_le32(FELIX_SERDES_SGMIICR1(pidx), FELIX_SERDES_SGMIICR1_SGPCS |
 142                 FELIX_SERDES_SGMIICR1_MDEV(pidx));
 143
 144        /*
 145         * Set to SGMII mode, for 1Gbps enable AN, for 2.5Gbps set fixed speed.
 146         * Although fixed speed is 1Gbps, we could be running at 2.5Gbps based
 147         * on PLL configuration.  Setting 1G for 2.5G here is counter intuitive
 148         * but intentional.
 149         */
 150        reg = ENETC_PCS_IF_MODE_SGMII;
 151        reg |= an ? ENETC_PCS_IF_MODE_SGMII_AN : ENETC_PCS_IF_MODE_SPEED_1G;
 152        felix_mdio_write(imdio, pidx, MDIO_DEVAD_NONE,
 153                         ENETC_PCS_IF_MODE, reg);
 154
 155        /* Dev ability - SGMII */
 156        felix_mdio_write(imdio, pidx, MDIO_DEVAD_NONE,
 157                         ENETC_PCS_DEV_ABILITY, ENETC_PCS_DEV_ABILITY_SGMII);
 158
 159        /* Adjust link timer for SGMII */
 160        felix_mdio_write(imdio, pidx, MDIO_DEVAD_NONE,
 161                         ENETC_PCS_LINK_TIMER1, ENETC_PCS_LINK_TIMER1_VAL);
 162        felix_mdio_write(imdio, pidx, MDIO_DEVAD_NONE,
 163                         ENETC_PCS_LINK_TIMER2, ENETC_PCS_LINK_TIMER2_VAL);
 164
 165        reg = ENETC_PCS_CR_DEF_VAL;
 166        reg |= an ? ENETC_PCS_CR_RESET_AN : ENETC_PCS_CR_RST;
 167        /* restart PCS AN */
 168        felix_mdio_write(imdio, pidx, MDIO_DEVAD_NONE,
 169                         ENETC_PCS_CR, reg);
 170}
 171
 172/* set up MAC and serdes for (Q)SXGMII */
 173static int felix_init_sxgmii(struct mii_dev *imdio, int pidx)
 174{
 175        int timeout = 1000;
 176
 177        /* set up transit equalization control on serdes lane */
 178        out_le32(FELIX_SERDES_LNATECR0(1), FELIX_SERDES_LNATECR0_ADPT_EQ);
 179
 180        /*reset lane */
 181        felix_mdio_write(imdio, pidx, MDIO_MMD_PCS, FELIX_PCS_CTRL,
 182                         FELIX_PCS_CTRL_RST);
 183        while (felix_mdio_read(imdio, pidx, MDIO_MMD_PCS,
 184                               FELIX_PCS_CTRL) & FELIX_PCS_CTRL_RST &&
 185                        --timeout) {
 186                mdelay(10);
 187        }
 188        if (felix_mdio_read(imdio, pidx, MDIO_MMD_PCS,
 189                            FELIX_PCS_CTRL) & FELIX_PCS_CTRL_RST)
 190                return -ETIME;
 191
 192        /* Dev ability - SXGMII */
 193        felix_mdio_write(imdio, pidx, ENETC_PCS_DEVAD_REPL,
 194                         ENETC_PCS_DEV_ABILITY, ENETC_PCS_DEV_ABILITY_SXGMII);
 195
 196        /* Restart PCS AN */
 197        felix_mdio_write(imdio, pidx, ENETC_PCS_DEVAD_REPL, ENETC_PCS_CR,
 198                         ENETC_PCS_CR_RST | ENETC_PCS_CR_RESET_AN);
 199        felix_mdio_write(imdio, pidx, ENETC_PCS_DEVAD_REPL,
 200                         ENETC_PCS_REPL_LINK_TIMER_1,
 201                         ENETC_PCS_REPL_LINK_TIMER_1_DEF);
 202        felix_mdio_write(imdio, pidx, ENETC_PCS_DEVAD_REPL,
 203                         ENETC_PCS_REPL_LINK_TIMER_2,
 204                         ENETC_PCS_REPL_LINK_TIMER_2_DEF);
 205
 206        return 0;
 207}
 208
 209/* Apply protocol specific configuration to MAC, serdes as needed */
 210static void felix_start_pcs(struct udevice *dev, int port,
 211                            struct phy_device *phy, struct mii_dev *imdio)
 212{
 213        bool autoneg = true;
 214
 215        if (phy->phy_id == PHY_FIXED_ID ||
 216            phy->interface == PHY_INTERFACE_MODE_SGMII_2500)
 217                autoneg = false;
 218
 219        switch (phy->interface) {
 220        case PHY_INTERFACE_MODE_SGMII:
 221        case PHY_INTERFACE_MODE_SGMII_2500:
 222        case PHY_INTERFACE_MODE_QSGMII:
 223                felix_init_sgmii(imdio, port, autoneg);
 224                break;
 225        case PHY_INTERFACE_MODE_XGMII:
 226        case PHY_INTERFACE_MODE_XFI:
 227        case PHY_INTERFACE_MODE_USXGMII:
 228                if (felix_init_sxgmii(imdio, port))
 229                        dev_err(dev, "PCS reset timeout on port %d\n", port);
 230                break;
 231        default:
 232                break;
 233        }
 234}
 235
 236void felix_init(struct udevice *dev)
 237{
 238        struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
 239        struct felix_priv *priv = dev_get_priv(dev);
 240        void *base = priv->regs_base;
 241        int timeout = 100;
 242
 243        /* Init core memories */
 244        out_le32(base + FELIX_SYS_RAM_CTRL, FELIX_SYS_RAM_CTRL_INIT);
 245        while (in_le32(base + FELIX_SYS_RAM_CTRL) & FELIX_SYS_RAM_CTRL_INIT &&
 246               --timeout)
 247                udelay(10);
 248        if (in_le32(base + FELIX_SYS_RAM_CTRL) & FELIX_SYS_RAM_CTRL_INIT)
 249                dev_err(dev, "Timeout waiting for switch memories\n");
 250
 251        /* Start switch core, set up ES0, IS1, IS2 */
 252        out_le32(base + FELIX_SYS_SYSTEM, FELIX_SYS_SYSTEM_EN);
 253        out_le32(base + FELIX_ES0_TCAM_CTRL, FELIX_ES0_TCAM_CTRL_EN);
 254        out_le32(base + FELIX_IS1_TCAM_CTRL, FELIX_IS1_TCAM_CTRL_EN);
 255        out_le32(base + FELIX_IS2_TCAM_CTRL, FELIX_IS2_TCAM_CTRL_EN);
 256        udelay(20);
 257
 258        priv->imdio.read = felix_mdio_read;
 259        priv->imdio.write = felix_mdio_write;
 260        priv->imdio.priv = priv->imdio_base + FELIX_PM_IMDIO_BASE;
 261        strncpy(priv->imdio.name, dev->name, MDIO_NAME_LEN);
 262
 263        /* set up CPU port */
 264        out_le32(base + FELIX_QSYS_SYSTEM_EXT_CPU_CFG,
 265                 FELIX_QSYS_SYSTEM_EXT_CPU_PORT(pdata->cpu_port));
 266        out_le32(base + FELIX_SYS_SYSTEM_PORT_MODE(pdata->cpu_port),
 267                 FELIX_SYS_SYSTEM_PORT_MODE_CPU);
 268}
 269
 270/*
 271 * Probe Felix:
 272 * - enable the PCI function
 273 * - map BAR 4
 274 * - init switch core and port registers
 275 */
 276static int felix_probe(struct udevice *dev)
 277{
 278        struct felix_priv *priv = dev_get_priv(dev);
 279
 280        if (ofnode_valid(dev_ofnode(dev)) &&
 281            !ofnode_is_available(dev_ofnode(dev))) {
 282                dev_dbg(dev, "switch disabled\n");
 283                return -ENODEV;
 284        }
 285
 286        priv->imdio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0);
 287        if (!priv->imdio_base) {
 288                dev_err(dev, "failed to map BAR0\n");
 289                return -EINVAL;
 290        }
 291
 292        priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_4, 0);
 293        if (!priv->regs_base) {
 294                dev_err(dev, "failed to map BAR4\n");
 295                return -EINVAL;
 296        }
 297
 298        /* register internal MDIO for debug */
 299        if (!miiphy_get_dev_by_name(dev->name)) {
 300                struct mii_dev *mii_bus;
 301
 302                mii_bus = mdio_alloc();
 303                mii_bus->read = felix_mdio_read;
 304                mii_bus->write = felix_mdio_write;
 305                mii_bus->priv = priv->imdio_base + FELIX_PM_IMDIO_BASE;
 306                strncpy(mii_bus->name, dev->name, MDIO_NAME_LEN);
 307                mdio_register(mii_bus);
 308        }
 309
 310        dm_pci_clrset_config16(dev, PCI_COMMAND, 0, PCI_COMMAND_MEMORY);
 311
 312        dsa_set_tagging(dev, FELIX_DSA_TAG_LEN, 0);
 313
 314        /* set up registers */
 315        felix_init(dev);
 316
 317        return 0;
 318}
 319
 320static int felix_port_enable(struct udevice *dev, int port,
 321                             struct phy_device *phy)
 322{
 323        int supported = PHY_GBIT_FEATURES | SUPPORTED_2500baseX_Full;
 324        struct felix_priv *priv = dev_get_priv(dev);
 325        void *base = priv->regs_base;
 326
 327        /* Set up MAC registers */
 328        out_le32(base + FELIX_GMII_CLOCK_CFG(port),
 329                 FELIX_GMII_CLOCK_CFG_LINK_1G);
 330
 331        out_le32(base + FELIX_GMII_MAC_IFG_CFG(port),
 332                 FELIX_GMII_MAC_IFG_CFG_DEF);
 333
 334        out_le32(base + FELIX_GMII_MAC_ENA_CFG(port),
 335                 FELIX_GMII_MAX_ENA_CFG_TX | FELIX_GMII_MAX_ENA_CFG_RX);
 336
 337        out_le32(base + FELIX_QSYS_SYSTEM_SW_PORT_MODE(port),
 338                 FELIX_QSYS_SYSTEM_SW_PORT_ENA |
 339                 FELIX_QSYS_SYSTEM_SW_PORT_LOSSY |
 340                 FELIX_QSYS_SYSTEM_SW_PORT_SCH(1));
 341
 342        felix_start_pcs(dev, port, phy, &priv->imdio);
 343
 344        phy->supported &= supported;
 345        phy->advertising &= supported;
 346        phy_config(phy);
 347
 348        phy_startup(phy);
 349
 350        return 0;
 351}
 352
 353static void felix_port_disable(struct udevice *dev, int pidx,
 354                               struct phy_device *phy)
 355{
 356        struct felix_priv *priv = dev_get_priv(dev);
 357        void *base = priv->regs_base;
 358
 359        out_le32(base + FELIX_GMII_MAC_ENA_CFG(pidx), 0);
 360
 361        out_le32(base + FELIX_QSYS_SYSTEM_SW_PORT_MODE(pidx),
 362                 FELIX_QSYS_SYSTEM_SW_PORT_LOSSY |
 363                 FELIX_QSYS_SYSTEM_SW_PORT_SCH(1));
 364
 365        /*
 366         * we don't call phy_shutdown here to avoid waiting next time we use
 367         * the port, but the downside is that remote side will think we're
 368         * actively processing traffic although we are not.
 369         */
 370}
 371
 372static int felix_xmit(struct udevice *dev, int pidx, void *packet, int length)
 373{
 374        struct felix_dsa_tag *tag = packet;
 375
 376        tag->magic = FELIX_DSA_TAG_MAGIC;
 377        tag->meta[FELIX_DSA_TAG_INJ_PORT] = FELIX_DSA_TAG_INJ_PORT_SET(pidx);
 378
 379        return 0;
 380}
 381
 382static int felix_rcv(struct udevice *dev, int *pidx, void *packet, int length)
 383{
 384        struct felix_dsa_tag *tag = packet;
 385
 386        if (tag->magic != FELIX_DSA_TAG_MAGIC)
 387                return -EINVAL;
 388
 389        *pidx = FELIX_DSA_TAG_EXT_PORT_GET(tag->meta[FELIX_DSA_TAG_EXT_PORT]);
 390
 391        return 0;
 392}
 393
 394static const struct dsa_ops felix_dsa_ops = {
 395        .port_enable    = felix_port_enable,
 396        .port_disable   = felix_port_disable,
 397        .xmit           = felix_xmit,
 398        .rcv            = felix_rcv,
 399};
 400
 401U_BOOT_DRIVER(felix_ethsw) = {
 402        .name           = "felix-switch",
 403        .id             = UCLASS_DSA,
 404        .probe          = felix_probe,
 405        .ops            = &felix_dsa_ops,
 406        .priv_auto      = sizeof(struct felix_priv),
 407};
 408
 409static struct pci_device_id felix_ethsw_ids[] = {
 410        { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_FELIX_ETHSW) },
 411        {}
 412};
 413
 414U_BOOT_PCI_DEVICE(felix_ethsw, felix_ethsw_ids);
 415