uboot/drivers/net/mscc_eswitch/ocelot_switch.c
<<
>>
Prefs
   1// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
   2/*
   3 * Copyright (c) 2018 Microsemi Corporation
   4 */
   5
   6#include <common.h>
   7#include <config.h>
   8#include <dm.h>
   9#include <dm/of_access.h>
  10#include <dm/of_addr.h>
  11#include <fdt_support.h>
  12#include <linux/io.h>
  13#include <linux/ioport.h>
  14#include <miiphy.h>
  15#include <net.h>
  16#include <wait_bit.h>
  17
  18#include "mscc_xfer.h"
  19#include "mscc_mac_table.h"
  20#include "mscc_miim.h"
  21
  22#define PHY_CFG                         0x0
  23#define PHY_CFG_ENA                             0xF
  24#define PHY_CFG_COMMON_RST                      BIT(4)
  25#define PHY_CFG_RST                             (0xF << 5)
  26#define PHY_STAT                        0x4
  27#define PHY_STAT_SUPERVISOR_COMPLETE            BIT(0)
  28
  29#define ANA_PORT_VLAN_CFG(x)            (0x7000 + 0x100 * (x))
  30#define         ANA_PORT_VLAN_CFG_AWARE_ENA     BIT(20)
  31#define         ANA_PORT_VLAN_CFG_POP_CNT(x)    ((x) << 18)
  32#define ANA_PORT_PORT_CFG(x)            (0x7070 + 0x100 * (x))
  33#define         ANA_PORT_PORT_CFG_RECV_ENA      BIT(6)
  34#define ANA_PGID(x)                     (0x8c00 + 4 * (x))
  35
  36#define HSIO_ANA_SERDES1G_DES_CFG               0x4c
  37#define         HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(x)            ((x) << 1)
  38#define         HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(x)             ((x) << 5)
  39#define         HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(x)          ((x) << 8)
  40#define         HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(x)           ((x) << 13)
  41#define HSIO_ANA_SERDES1G_IB_CFG                0x50
  42#define         HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(x)       (x)
  43#define         HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(x)             ((x) << 6)
  44#define         HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP        BIT(9)
  45#define         HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV             BIT(11)
  46#define         HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM           BIT(13)
  47#define         HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(x)         ((x) << 24)
  48#define HSIO_ANA_SERDES1G_OB_CFG                0x54
  49#define         HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(x)       (x)
  50#define         HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(x)            ((x) << 4)
  51#define         HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(x)       ((x) << 10)
  52#define         HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(x)            ((x) << 13)
  53#define         HSIO_ANA_SERDES1G_OB_CFG_SLP(x)                 ((x) << 17)
  54#define HSIO_ANA_SERDES1G_SER_CFG               0x58
  55#define HSIO_ANA_SERDES1G_COMMON_CFG            0x5c
  56#define         HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE            BIT(0)
  57#define         HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE           BIT(18)
  58#define         HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST            BIT(31)
  59#define HSIO_ANA_SERDES1G_PLL_CFG               0x60
  60#define         HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA               BIT(7)
  61#define         HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(x)      ((x) << 8)
  62#define         HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2           BIT(21)
  63#define HSIO_DIG_SERDES1G_DFT_CFG0              0x68
  64#define HSIO_DIG_SERDES1G_MISC_CFG              0x7c
  65#define         HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST             BIT(0)
  66#define HSIO_MCB_SERDES1G_CFG                   0x88
  67#define         HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT               BIT(31)
  68#define         HSIO_MCB_SERDES1G_CFG_ADDR(x)                   (x)
  69#define HSIO_HW_CFGSTAT_HW_CFG                  0x10c
  70
  71#define SYS_FRM_AGING                   0x574
  72#define         SYS_FRM_AGING_ENA               BIT(20)
  73
  74#define SYS_SYSTEM_RST_CFG              0x508
  75#define         SYS_SYSTEM_RST_MEM_INIT         BIT(0)
  76#define         SYS_SYSTEM_RST_MEM_ENA          BIT(1)
  77#define         SYS_SYSTEM_RST_CORE_ENA         BIT(2)
  78#define SYS_PORT_MODE(x)                (0x514 + 0x4 * (x))
  79#define         SYS_PORT_MODE_INCL_INJ_HDR(x)   ((x) << 3)
  80#define         SYS_PORT_MODE_INCL_INJ_HDR_M    GENMASK(4, 3)
  81#define         SYS_PORT_MODE_INCL_XTR_HDR(x)   ((x) << 1)
  82#define         SYS_PORT_MODE_INCL_XTR_HDR_M    GENMASK(2, 1)
  83#define SYS_PAUSE_CFG(x)                (0x608 + 0x4 * (x))
  84#define         SYS_PAUSE_CFG_PAUSE_ENA         BIT(0)
  85
  86#define QSYS_SWITCH_PORT_MODE(x)        (0x11234 + 0x4 * (x))
  87#define         QSYS_SWITCH_PORT_MODE_PORT_ENA  BIT(14)
  88#define QSYS_QMAP                       0x112d8
  89#define QSYS_EGR_NO_SHARING             0x1129c
  90
  91/* Port registers */
  92#define DEV_CLOCK_CFG                   0x0
  93#define DEV_CLOCK_CFG_LINK_SPEED_1000           1
  94#define DEV_MAC_ENA_CFG                 0x1c
  95#define         DEV_MAC_ENA_CFG_RX_ENA          BIT(4)
  96#define         DEV_MAC_ENA_CFG_TX_ENA          BIT(0)
  97
  98#define DEV_MAC_IFG_CFG                 0x30
  99#define         DEV_MAC_IFG_CFG_TX_IFG(x)       ((x) << 8)
 100#define         DEV_MAC_IFG_CFG_RX_IFG2(x)      ((x) << 4)
 101#define         DEV_MAC_IFG_CFG_RX_IFG1(x)      (x)
 102
 103#define PCS1G_CFG                       0x48
 104#define         PCS1G_MODE_CFG_SGMII_MODE_ENA   BIT(0)
 105#define PCS1G_MODE_CFG                  0x4c
 106#define         PCS1G_MODE_CFG_UNIDIR_MODE_ENA  BIT(4)
 107#define         PCS1G_MODE_CFG_SGMII_MODE_ENA   BIT(0)
 108#define PCS1G_SD_CFG                    0x50
 109#define PCS1G_ANEG_CFG                  0x54
 110#define         PCS1G_ANEG_CFG_ADV_ABILITY(x)   ((x) << 16)
 111
 112#define QS_XTR_GRP_CFG(x)               (4 * (x))
 113#define QS_XTR_GRP_CFG_MODE(x)                  ((x) << 2)
 114#define         QS_XTR_GRP_CFG_STATUS_WORD_POS  BIT(1)
 115#define         QS_XTR_GRP_CFG_BYTE_SWAP        BIT(0)
 116#define QS_INJ_GRP_CFG(x)               (0x24 + (x) * 4)
 117#define         QS_INJ_GRP_CFG_MODE(x)          ((x) << 2)
 118#define         QS_INJ_GRP_CFG_BYTE_SWAP        BIT(0)
 119
 120#define IFH_INJ_BYPASS          BIT(31)
 121#define IFH_TAG_TYPE_C          0
 122#define MAC_VID                 1
 123#define CPU_PORT                11
 124#define INTERNAL_PORT_MSK       0x2FF
 125#define IFH_LEN                 4
 126#define ETH_ALEN                6
 127#define PGID_BROADCAST          13
 128#define PGID_UNICAST            14
 129#define PGID_SRC                80
 130
 131static const char * const regs_names[] = {
 132        "port0", "port1", "port2", "port3", "port4", "port5", "port6", "port7",
 133        "port8", "port9", "port10", "sys", "rew", "qs", "hsio", "qsys", "ana",
 134};
 135
 136#define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1
 137#define MAX_PORT 11
 138
 139enum ocelot_ctrl_regs {
 140        SYS = MAX_PORT,
 141        REW,
 142        QS,
 143        HSIO,
 144        QSYS,
 145        ANA,
 146};
 147
 148#define OCELOT_MIIM_BUS_COUNT 2
 149
 150struct ocelot_phy_port_t {
 151        size_t phy_addr;
 152        struct mii_dev *bus;
 153        u8 serdes_index;
 154        u8 phy_mode;
 155};
 156
 157struct ocelot_private {
 158        void __iomem *regs[REGS_NAMES_COUNT];
 159        struct mii_dev *bus[OCELOT_MIIM_BUS_COUNT];
 160        struct ocelot_phy_port_t ports[MAX_PORT];
 161};
 162
 163static struct mscc_miim_dev miim[OCELOT_MIIM_BUS_COUNT];
 164static int miim_count = -1;
 165
 166static const unsigned long ocelot_regs_qs[] = {
 167        [MSCC_QS_XTR_RD] = 0x8,
 168        [MSCC_QS_XTR_FLUSH] = 0x18,
 169        [MSCC_QS_XTR_DATA_PRESENT] = 0x1c,
 170        [MSCC_QS_INJ_WR] = 0x2c,
 171        [MSCC_QS_INJ_CTRL] = 0x34,
 172};
 173
 174static const unsigned long ocelot_regs_ana_table[] = {
 175        [MSCC_ANA_TABLES_MACHDATA] = 0x8b34,
 176        [MSCC_ANA_TABLES_MACLDATA] = 0x8b38,
 177        [MSCC_ANA_TABLES_MACACCESS] = 0x8b3c,
 178};
 179
 180static void mscc_phy_reset(void)
 181{
 182        writel(0, BASE_DEVCPU_GCB + PERF_PHY_CFG + PHY_CFG);
 183        writel(PHY_CFG_RST | PHY_CFG_COMMON_RST
 184               | PHY_CFG_ENA, BASE_DEVCPU_GCB + PERF_PHY_CFG + PHY_CFG);
 185        if (wait_for_bit_le32((const void *)(BASE_DEVCPU_GCB + PERF_PHY_CFG) +
 186                              PHY_STAT, PHY_STAT_SUPERVISOR_COMPLETE,
 187                              true, 2000, false)) {
 188                pr_err("Timeout in phy reset\n");
 189        }
 190}
 191
 192__weak void mscc_switch_reset(void)
 193{
 194}
 195
 196static void ocelot_stop(struct udevice *dev)
 197{
 198        mscc_switch_reset();
 199        mscc_phy_reset();
 200}
 201
 202static void ocelot_cpu_capture_setup(struct ocelot_private *priv)
 203{
 204        int i;
 205
 206        /* map the 8 CPU extraction queues to CPU port 11 */
 207        writel(0, priv->regs[QSYS] + QSYS_QMAP);
 208
 209        for (i = 0; i <= 1; i++) {
 210                /*
 211                 * Do byte-swap and expect status after last data word
 212                 * Extraction: Mode: manual extraction) | Byte_swap
 213                 */
 214                writel(QS_XTR_GRP_CFG_MODE(1) | QS_XTR_GRP_CFG_BYTE_SWAP,
 215                       priv->regs[QS] + QS_XTR_GRP_CFG(i));
 216                /*
 217                 * Injection: Mode: manual extraction | Byte_swap
 218                 */
 219                writel(QS_INJ_GRP_CFG_MODE(1) | QS_INJ_GRP_CFG_BYTE_SWAP,
 220                       priv->regs[QS] + QS_INJ_GRP_CFG(i));
 221        }
 222
 223        for (i = 0; i <= 1; i++)
 224                /* Enable IFH insertion/parsing on CPU ports */
 225                writel(SYS_PORT_MODE_INCL_INJ_HDR(1) |
 226                       SYS_PORT_MODE_INCL_XTR_HDR(1),
 227                       priv->regs[SYS] + SYS_PORT_MODE(CPU_PORT + i));
 228        /*
 229         * Setup the CPU port as VLAN aware to support switching frames
 230         * based on tags
 231         */
 232        writel(ANA_PORT_VLAN_CFG_AWARE_ENA | ANA_PORT_VLAN_CFG_POP_CNT(1) |
 233               MAC_VID, priv->regs[ANA] + ANA_PORT_VLAN_CFG(CPU_PORT));
 234
 235        /* Disable learning (only RECV_ENA must be set) */
 236        writel(ANA_PORT_PORT_CFG_RECV_ENA,
 237               priv->regs[ANA] + ANA_PORT_PORT_CFG(CPU_PORT));
 238
 239        /* Enable switching to/from cpu port */
 240        setbits_le32(priv->regs[QSYS] + QSYS_SWITCH_PORT_MODE(CPU_PORT),
 241                     QSYS_SWITCH_PORT_MODE_PORT_ENA);
 242
 243        /* No pause on CPU port - not needed (off by default) */
 244        clrbits_le32(priv->regs[SYS] + SYS_PAUSE_CFG(CPU_PORT),
 245                     SYS_PAUSE_CFG_PAUSE_ENA);
 246
 247        setbits_le32(priv->regs[QSYS] + QSYS_EGR_NO_SHARING, BIT(CPU_PORT));
 248}
 249
 250static void ocelot_port_init(struct ocelot_private *priv, int port)
 251{
 252        void __iomem *regs = priv->regs[port];
 253
 254        /* Enable PCS */
 255        writel(PCS1G_MODE_CFG_SGMII_MODE_ENA, regs + PCS1G_CFG);
 256
 257        /* Disable Signal Detect */
 258        writel(0, regs + PCS1G_SD_CFG);
 259
 260        /* Enable MAC RX and TX */
 261        writel(DEV_MAC_ENA_CFG_RX_ENA | DEV_MAC_ENA_CFG_TX_ENA,
 262               regs + DEV_MAC_ENA_CFG);
 263
 264        /* Clear sgmii_mode_ena */
 265        writel(0, regs + PCS1G_MODE_CFG);
 266
 267        /*
 268         * Clear sw_resolve_ena(bit 0) and set adv_ability to
 269         * something meaningful just in case
 270         */
 271        writel(PCS1G_ANEG_CFG_ADV_ABILITY(0x20), regs + PCS1G_ANEG_CFG);
 272
 273        /* Set MAC IFG Gaps */
 274        writel(DEV_MAC_IFG_CFG_TX_IFG(5) | DEV_MAC_IFG_CFG_RX_IFG1(5) |
 275               DEV_MAC_IFG_CFG_RX_IFG2(1), regs + DEV_MAC_IFG_CFG);
 276
 277        /* Set link speed and release all resets */
 278        writel(DEV_CLOCK_CFG_LINK_SPEED_1000, regs + DEV_CLOCK_CFG);
 279
 280        /* Make VLAN aware for CPU traffic */
 281        writel(ANA_PORT_VLAN_CFG_AWARE_ENA | ANA_PORT_VLAN_CFG_POP_CNT(1) |
 282               MAC_VID, priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
 283
 284        /* Enable the port in the core */
 285        setbits_le32(priv->regs[QSYS] + QSYS_SWITCH_PORT_MODE(port),
 286                     QSYS_SWITCH_PORT_MODE_PORT_ENA);
 287}
 288
 289static void serdes1g_write(void __iomem *base, u32 addr)
 290{
 291        u32 data;
 292
 293        writel(HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT |
 294               HSIO_MCB_SERDES1G_CFG_ADDR(addr),
 295               base + HSIO_MCB_SERDES1G_CFG);
 296
 297        do {
 298                data = readl(base + HSIO_MCB_SERDES1G_CFG);
 299        } while (data & HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT);
 300}
 301
 302static void serdes1g_setup(void __iomem *base, uint32_t addr,
 303                           phy_interface_t interface)
 304{
 305        writel(0x34, base + HSIO_HW_CFGSTAT_HW_CFG);
 306
 307        writel(0x0, base + HSIO_ANA_SERDES1G_SER_CFG);
 308        writel(0x0, base + HSIO_DIG_SERDES1G_DFT_CFG0);
 309        writel(HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(11) |
 310               HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(0) |
 311               HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP |
 312               HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM |
 313               HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(1),
 314               base + HSIO_ANA_SERDES1G_IB_CFG);
 315        writel(HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(7) |
 316               HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(6) |
 317               HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(2) |
 318               HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(6),
 319               base + HSIO_ANA_SERDES1G_DES_CFG);
 320        writel(HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(1) |
 321               HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(4) |
 322               HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(2) |
 323               HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(12) |
 324               HSIO_ANA_SERDES1G_OB_CFG_SLP(3),
 325               base + HSIO_ANA_SERDES1G_OB_CFG);
 326        writel(HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE |
 327               HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE,
 328               base + HSIO_ANA_SERDES1G_COMMON_CFG);
 329        writel(HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA |
 330               HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(200) |
 331               HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2,
 332               base + HSIO_ANA_SERDES1G_PLL_CFG);
 333        writel(HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST,
 334               base + HSIO_DIG_SERDES1G_MISC_CFG);
 335
 336        serdes1g_write(base, addr);
 337
 338        writel(HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE |
 339               HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE |
 340               HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST,
 341               base + HSIO_ANA_SERDES1G_COMMON_CFG);
 342        serdes1g_write(base, addr);
 343
 344        writel(0x0, base + HSIO_DIG_SERDES1G_MISC_CFG);
 345        serdes1g_write(base, addr);
 346}
 347
 348static void serdes_setup(struct ocelot_private *priv)
 349{
 350        size_t mask;
 351        int i = 0;
 352
 353        for (i = 0; i < MAX_PORT; ++i) {
 354                if (!priv->ports[i].bus || priv->ports[i].serdes_index == 0xff)
 355                        continue;
 356
 357                mask = BIT(priv->ports[i].serdes_index);
 358                serdes1g_setup(priv->regs[HSIO], mask,
 359                               priv->ports[i].phy_mode);
 360        }
 361}
 362
 363static int ocelot_switch_init(struct ocelot_private *priv)
 364{
 365        /* Reset switch & memories */
 366        writel(SYS_SYSTEM_RST_MEM_ENA | SYS_SYSTEM_RST_MEM_INIT,
 367               priv->regs[SYS] + SYS_SYSTEM_RST_CFG);
 368
 369        /* Wait to complete */
 370        if (wait_for_bit_le32(priv->regs[SYS] + SYS_SYSTEM_RST_CFG,
 371                              SYS_SYSTEM_RST_MEM_INIT, false, 2000, false)) {
 372                pr_err("Timeout in memory reset\n");
 373                return -EIO;
 374        }
 375
 376        /* Enable switch core */
 377        setbits_le32(priv->regs[SYS] + SYS_SYSTEM_RST_CFG,
 378                     SYS_SYSTEM_RST_CORE_ENA);
 379
 380        serdes_setup(priv);
 381        return 0;
 382}
 383
 384static int ocelot_initialize(struct ocelot_private *priv)
 385{
 386        int ret, i;
 387
 388        /* Initialize switch memories, enable core */
 389        ret = ocelot_switch_init(priv);
 390        if (ret)
 391                return ret;
 392        /*
 393         * Disable port-to-port by switching
 394         * Put fron ports in "port isolation modes" - i.e. they cant send
 395         * to other ports - via the PGID sorce masks.
 396         */
 397        for (i = 0; i < MAX_PORT; i++)
 398                writel(0, priv->regs[ANA] + ANA_PGID(PGID_SRC + i));
 399
 400        /* Flush queues */
 401        mscc_flush(priv->regs[QS], ocelot_regs_qs);
 402
 403        /* Setup frame ageing - "2 sec" - The unit is 6.5us on Ocelot */
 404        writel(SYS_FRM_AGING_ENA | (20000000 / 65),
 405               priv->regs[SYS] + SYS_FRM_AGING);
 406
 407        for (i = 0; i < MAX_PORT; i++)
 408                ocelot_port_init(priv, i);
 409
 410        ocelot_cpu_capture_setup(priv);
 411
 412        debug("Ports enabled\n");
 413
 414        return 0;
 415}
 416
 417static int ocelot_write_hwaddr(struct udevice *dev)
 418{
 419        struct ocelot_private *priv = dev_get_priv(dev);
 420        struct eth_pdata *pdata = dev_get_platdata(dev);
 421
 422        mscc_mac_table_add(priv->regs[ANA], ocelot_regs_ana_table,
 423                           pdata->enetaddr, PGID_UNICAST);
 424
 425        writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST));
 426
 427        return 0;
 428}
 429
 430static int ocelot_start(struct udevice *dev)
 431{
 432        struct ocelot_private *priv = dev_get_priv(dev);
 433        struct eth_pdata *pdata = dev_get_platdata(dev);
 434        const unsigned char mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff,
 435                                              0xff };
 436        int ret;
 437
 438        ret = ocelot_initialize(priv);
 439        if (ret)
 440                return ret;
 441
 442        /* Set MAC address tables entries for CPU redirection */
 443        mscc_mac_table_add(priv->regs[ANA], ocelot_regs_ana_table, mac,
 444                           PGID_BROADCAST);
 445
 446        writel(BIT(CPU_PORT) | INTERNAL_PORT_MSK,
 447               priv->regs[ANA] + ANA_PGID(PGID_BROADCAST));
 448
 449        /* It should be setup latter in ocelot_write_hwaddr */
 450        mscc_mac_table_add(priv->regs[ANA], ocelot_regs_ana_table,
 451                           pdata->enetaddr, PGID_UNICAST);
 452
 453        writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST));
 454
 455        return 0;
 456}
 457
 458static int ocelot_send(struct udevice *dev, void *packet, int length)
 459{
 460        struct ocelot_private *priv = dev_get_priv(dev);
 461        u32 ifh[IFH_LEN];
 462        int port = BIT(0);      /* use port 0 */
 463        u32 *buf = packet;
 464
 465        /*
 466         * Generate the IFH for frame injection
 467         *
 468         * The IFH is a 128bit-value
 469         * bit 127: bypass the analyzer processing
 470         * bit 56-67: destination mask
 471         * bit 28-29: pop_cnt: 3 disables all rewriting of the frame
 472         * bit 20-27: cpu extraction queue mask
 473         * bit 16: tag type 0: C-tag, 1: S-tag
 474         * bit 0-11: VID
 475         */
 476        ifh[0] = IFH_INJ_BYPASS;
 477        ifh[1] = (0xf00 & port) >> 8;
 478        ifh[2] = (0xff & port) << 24;
 479        ifh[3] = (IFH_TAG_TYPE_C << 16);
 480
 481        return mscc_send(priv->regs[QS], ocelot_regs_qs,
 482                         ifh, IFH_LEN, buf, length);
 483}
 484
 485static int ocelot_recv(struct udevice *dev, int flags, uchar **packetp)
 486{
 487        struct ocelot_private *priv = dev_get_priv(dev);
 488        u32 *rxbuf = (u32 *)net_rx_packets[0];
 489        int byte_cnt;
 490
 491        byte_cnt = mscc_recv(priv->regs[QS], ocelot_regs_qs, rxbuf, IFH_LEN,
 492                             false);
 493
 494        *packetp = net_rx_packets[0];
 495
 496        return byte_cnt;
 497}
 498
 499static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size)
 500{
 501        int i = 0;
 502
 503        for (i = 0; i < OCELOT_MIIM_BUS_COUNT; ++i)
 504                if (miim[i].miim_base == base && miim[i].miim_size == size)
 505                        return miim[i].bus;
 506
 507        return NULL;
 508}
 509
 510static void add_port_entry(struct ocelot_private *priv, size_t index,
 511                           size_t phy_addr, struct mii_dev *bus,
 512                           u8 serdes_index, u8 phy_mode)
 513{
 514        priv->ports[index].phy_addr = phy_addr;
 515        priv->ports[index].bus = bus;
 516        priv->ports[index].serdes_index = serdes_index;
 517        priv->ports[index].phy_mode = phy_mode;
 518}
 519
 520static int external_bus(struct ocelot_private *priv, size_t port_index)
 521{
 522        return priv->ports[port_index].serdes_index != 0xff;
 523}
 524
 525static int ocelot_probe(struct udevice *dev)
 526{
 527        struct ocelot_private *priv = dev_get_priv(dev);
 528        int i, ret;
 529        struct resource res;
 530        fdt32_t faddr;
 531        phys_addr_t addr_base;
 532        unsigned long addr_size;
 533        ofnode eth_node, node, mdio_node;
 534        size_t phy_addr;
 535        struct mii_dev *bus;
 536        struct ofnode_phandle_args phandle;
 537        struct phy_device *phy;
 538
 539        if (!priv)
 540                return -EINVAL;
 541
 542        for (i = 0; i < ARRAY_SIZE(regs_names); i++) {
 543                priv->regs[i] = dev_remap_addr_name(dev, regs_names[i]);
 544                if (!priv->regs[i]) {
 545                        debug
 546                            ("Error can't get regs base addresses for %s\n",
 547                             regs_names[i]);
 548                        return -ENOMEM;
 549                }
 550        }
 551
 552        /* Initialize miim buses */
 553        memset(&miim, 0x0, sizeof(struct mscc_miim_dev) *
 554               OCELOT_MIIM_BUS_COUNT);
 555
 556        /* iterate all the ports and find out on which bus they are */
 557        i = 0;
 558        eth_node = dev_read_first_subnode(dev);
 559        for (node = ofnode_first_subnode(eth_node); ofnode_valid(node);
 560             node = ofnode_next_subnode(node)) {
 561                if (ofnode_read_resource(node, 0, &res))
 562                        return -ENOMEM;
 563                i = res.start;
 564
 565                ofnode_parse_phandle_with_args(node, "phy-handle", NULL, 0, 0,
 566                                               &phandle);
 567
 568                /* Get phy address on mdio bus */
 569                if (ofnode_read_resource(phandle.node, 0, &res))
 570                        return -ENOMEM;
 571                phy_addr = res.start;
 572
 573                /* Get mdio node */
 574                mdio_node = ofnode_get_parent(phandle.node);
 575
 576                if (ofnode_read_resource(mdio_node, 0, &res))
 577                        return -ENOMEM;
 578                faddr = cpu_to_fdt32(res.start);
 579
 580                addr_base = ofnode_translate_address(mdio_node, &faddr);
 581                addr_size = res.end - res.start;
 582
 583                /* If the bus is new then create a new bus */
 584                if (!get_mdiobus(addr_base, addr_size))
 585                        priv->bus[miim_count] =
 586                                mscc_mdiobus_init(miim, &miim_count, addr_base,
 587                                                  addr_size);
 588
 589                /* Connect mdio bus with the port */
 590                bus = get_mdiobus(addr_base, addr_size);
 591
 592                /* Get serdes info */
 593                ret = ofnode_parse_phandle_with_args(node, "phys", NULL,
 594                                                     3, 0, &phandle);
 595                if (ret)
 596                        add_port_entry(priv, i, phy_addr, bus, 0xff, 0xff);
 597                else
 598                        add_port_entry(priv, i, phy_addr, bus, phandle.args[1],
 599                                       phandle.args[2]);
 600        }
 601
 602        mscc_phy_reset();
 603
 604        for (i = 0; i < MAX_PORT; i++) {
 605                if (!priv->ports[i].bus)
 606                        continue;
 607
 608                phy = phy_connect(priv->ports[i].bus,
 609                                  priv->ports[i].phy_addr, dev,
 610                                  PHY_INTERFACE_MODE_NONE);
 611                if (phy && external_bus(priv, i))
 612                        board_phy_config(phy);
 613        }
 614
 615        return 0;
 616}
 617
 618static int ocelot_remove(struct udevice *dev)
 619{
 620        struct ocelot_private *priv = dev_get_priv(dev);
 621        int i;
 622
 623        for (i = 0; i < OCELOT_MIIM_BUS_COUNT; i++) {
 624                mdio_unregister(priv->bus[i]);
 625                mdio_free(priv->bus[i]);
 626        }
 627
 628        return 0;
 629}
 630
 631static const struct eth_ops ocelot_ops = {
 632        .start        = ocelot_start,
 633        .stop         = ocelot_stop,
 634        .send         = ocelot_send,
 635        .recv         = ocelot_recv,
 636        .write_hwaddr = ocelot_write_hwaddr,
 637};
 638
 639static const struct udevice_id mscc_ocelot_ids[] = {
 640        {.compatible = "mscc,vsc7514-switch"},
 641        { /* Sentinel */ }
 642};
 643
 644U_BOOT_DRIVER(ocelot) = {
 645        .name     = "ocelot-switch",
 646        .id       = UCLASS_ETH,
 647        .of_match = mscc_ocelot_ids,
 648        .probe    = ocelot_probe,
 649        .remove   = ocelot_remove,
 650        .ops      = &ocelot_ops,
 651        .priv_auto_alloc_size = sizeof(struct ocelot_private),
 652        .platdata_auto_alloc_size = sizeof(struct eth_pdata),
 653};
 654