uboot/drivers/net/mscc_eswitch/jr2_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 <malloc.h>
  10#include <dm/of_access.h>
  11#include <dm/of_addr.h>
  12#include <fdt_support.h>
  13#include <linux/bitops.h>
  14#include <linux/delay.h>
  15#include <linux/io.h>
  16#include <linux/ioport.h>
  17#include <miiphy.h>
  18#include <net.h>
  19#include <wait_bit.h>
  20
  21#include <dt-bindings/mscc/jr2_data.h>
  22#include "mscc_xfer.h"
  23#include "mscc_miim.h"
  24
  25#define ANA_AC_RAM_CTRL_RAM_INIT                0x94358
  26#define ANA_AC_STAT_GLOBAL_CFG_PORT_RESET       0x94370
  27
  28#define ANA_CL_PORT_VLAN_CFG(x)                 (0x24018 + 0xc8 * (x))
  29#define         ANA_CL_PORT_VLAN_CFG_AWARE_ENA                  BIT(19)
  30#define         ANA_CL_PORT_VLAN_CFG_POP_CNT(x)                 ((x) << 17)
  31
  32#define ANA_L2_COMMON_FWD_CFG                   0x8a2a8
  33#define         ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA BIT(6)
  34
  35#define ASM_CFG_STAT_CFG                        0x3508
  36#define ASM_CFG_PORT(x)                         (0x36c4 + 0x4 * (x))
  37#define         ASM_CFG_PORT_NO_PREAMBLE_ENA            BIT(8)
  38#define         ASM_CFG_PORT_INJ_FORMAT_CFG(x)          ((x) << 1)
  39#define ASM_RAM_CTRL_RAM_INIT                   0x39b8
  40
  41#define DEV_DEV_CFG_DEV_RST_CTRL                0x0
  42#define         DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(x)   ((x) << 20)
  43#define DEV_MAC_CFG_MAC_ENA             0x1c
  44#define         DEV_MAC_CFG_MAC_ENA_RX_ENA              BIT(4)
  45#define         DEV_MAC_CFG_MAC_ENA_TX_ENA              BIT(0)
  46#define DEV_MAC_CFG_MAC_IFG             0x34
  47#define         DEV_MAC_CFG_MAC_IFG_TX_IFG(x)           ((x) << 8)
  48#define         DEV_MAC_CFG_MAC_IFG_RX_IFG2(x)          ((x) << 4)
  49#define         DEV_MAC_CFG_MAC_IFG_RX_IFG1(x)          (x)
  50#define DEV_PCS1G_CFG_PCS1G_CFG         0x40
  51#define         DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA         BIT(0)
  52#define DEV_PCS1G_CFG_PCS1G_MODE        0x44
  53#define DEV_PCS1G_CFG_PCS1G_SD          0x48
  54#define DEV_PCS1G_CFG_PCS1G_ANEG        0x4c
  55#define         DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(x) ((x) << 16)
  56
  57#define DSM_RAM_CTRL_RAM_INIT           0x8
  58
  59#define HSIO_ANA_SERDES1G_DES_CFG               0xac
  60#define         HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(x)            ((x) << 1)
  61#define         HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(x)             ((x) << 5)
  62#define         HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(x)          ((x) << 8)
  63#define         HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(x)           ((x) << 13)
  64#define HSIO_ANA_SERDES1G_IB_CFG                0xb0
  65#define         HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(x)       (x)
  66#define         HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(x)             ((x) << 6)
  67#define         HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP        BIT(9)
  68#define         HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV             BIT(11)
  69#define         HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM           BIT(13)
  70#define         HSIO_ANA_SERDES1G_IB_CFG_DET_LEV(x)             ((x) << 19)
  71#define         HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(x)         ((x) << 24)
  72#define HSIO_ANA_SERDES1G_OB_CFG                0xb4
  73#define         HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(x)       (x)
  74#define         HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(x)            ((x) << 4)
  75#define         HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(x)       ((x) << 10)
  76#define         HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(x)            ((x) << 13)
  77#define         HSIO_ANA_SERDES1G_OB_CFG_SLP(x)                 ((x) << 17)
  78#define HSIO_ANA_SERDES1G_SER_CFG               0xb8
  79#define HSIO_ANA_SERDES1G_COMMON_CFG            0xbc
  80#define         HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE            BIT(0)
  81#define         HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE           BIT(18)
  82#define         HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST            BIT(31)
  83#define HSIO_ANA_SERDES1G_PLL_CFG               0xc0
  84#define         HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA               BIT(7)
  85#define         HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(x)      ((x) << 8)
  86#define         HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2           BIT(21)
  87#define HSIO_DIG_SERDES1G_DFT_CFG0              0xc8
  88#define HSIO_DIG_SERDES1G_TP_CFG                0xd4
  89#define HSIO_DIG_SERDES1G_MISC_CFG              0xdc
  90#define         HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST             BIT(0)
  91#define HSIO_MCB_SERDES1G_CFG                   0xe8
  92#define         HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT               BIT(31)
  93#define         HSIO_MCB_SERDES1G_CFG_ADDR(x)                   (x)
  94
  95#define HSIO_ANA_SERDES6G_DES_CFG               0x11c
  96#define         HSIO_ANA_SERDES6G_DES_CFG_SWAP_ANA              BIT(0)
  97#define         HSIO_ANA_SERDES6G_DES_CFG_BW_ANA(x)             ((x) << 1)
  98#define         HSIO_ANA_SERDES6G_DES_CFG_SWAP_HYST             BIT(4)
  99#define         HSIO_ANA_SERDES6G_DES_CFG_BW_HYST(x)            ((x) << 5)
 100#define         HSIO_ANA_SERDES6G_DES_CFG_CPMD_SEL(x)           ((x) << 8)
 101#define         HSIO_ANA_SERDES6G_DES_CFG_MBTR_CTRL(x)          ((x) << 10)
 102#define         HSIO_ANA_SERDES6G_DES_CFG_PHS_CTRL(x)           ((x) << 13)
 103#define HSIO_ANA_SERDES6G_IB_CFG                0x120
 104#define         HSIO_ANA_SERDES6G_IB_CFG_REG_ENA                BIT(0)
 105#define         HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA                BIT(1)
 106#define         HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA                BIT(2)
 107#define         HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(x)             ((x) << 3)
 108#define         HSIO_ANA_SERDES6G_IB_CFG_CONCUR                 BIT(4)
 109#define         HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA            BIT(5)
 110#define         HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(x)     ((x) << 7)
 111#define         HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(x)      ((x) << 9)
 112#define         HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(x)     ((x) << 11)
 113#define         HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(x)      ((x) << 13)
 114#define         HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(x)     ((x) << 15)
 115#define         HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(x)       ((x) << 18)
 116#define         HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(x)            ((x) << 20)
 117#define         HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(x)            ((x) << 24)
 118#define         HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL              BIT(28)
 119#define         HSIO_ANA_SERDES6G_IB_CFG_SOFSI(x)               ((x) << 29)
 120#define HSIO_ANA_SERDES6G_IB_CFG1               0x124
 121#define         HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET           BIT(4)
 122#define         HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP               BIT(5)
 123#define         HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID              BIT(6)
 124#define         HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP               BIT(7)
 125#define         HSIO_ANA_SERDES6G_IB_CFG1_SCALY(x)              ((x) << 8)
 126#define         HSIO_ANA_SERDES6G_IB_CFG1_TSDET(x)              ((x) << 12)
 127#define         HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(x)              ((x) << 17)
 128#define HSIO_ANA_SERDES6G_IB_CFG2               0x128
 129#define         HSIO_ANA_SERDES6G_IB_CFG2_UREG(x)               (x)
 130#define         HSIO_ANA_SERDES6G_IB_CFG2_UMAX(x)               ((x) << 3)
 131#define         HSIO_ANA_SERDES6G_IB_CFG2_TCALV(x)              ((x) << 5)
 132#define         HSIO_ANA_SERDES6G_IB_CFG2_OCALS(x)              ((x) << 10)
 133#define         HSIO_ANA_SERDES6G_IB_CFG2_OINFS(x)              ((x) << 16)
 134#define         HSIO_ANA_SERDES6G_IB_CFG2_OINFI(x)              ((x) << 22)
 135#define         HSIO_ANA_SERDES6G_IB_CFG2_TINFV(x)              ((x) << 27)
 136#define HSIO_ANA_SERDES6G_IB_CFG3               0x12c
 137#define         HSIO_ANA_SERDES6G_IB_CFG3_INI_OFFSET(x)         (x)
 138#define         HSIO_ANA_SERDES6G_IB_CFG3_INI_LP(x)             ((x) << 6)
 139#define         HSIO_ANA_SERDES6G_IB_CFG3_INI_MID(x)            ((x) << 12)
 140#define         HSIO_ANA_SERDES6G_IB_CFG3_INI_HP(x)             ((x) << 18)
 141#define HSIO_ANA_SERDES6G_IB_CFG4               0x130
 142#define         HSIO_ANA_SERDES6G_IB_CFG4_MAX_OFFSET(x)         (x)
 143#define         HSIO_ANA_SERDES6G_IB_CFG4_MAX_LP(x)             ((x) << 6)
 144#define         HSIO_ANA_SERDES6G_IB_CFG4_MAX_MID(x)            ((x) << 12)
 145#define         HSIO_ANA_SERDES6G_IB_CFG4_MAX_HP(x)             ((x) << 18)
 146#define HSIO_ANA_SERDES6G_IB_CFG5               0x134
 147#define         HSIO_ANA_SERDES6G_IB_CFG4_MIN_OFFSET(x)         (x)
 148#define         HSIO_ANA_SERDES6G_IB_CFG4_MIN_LP(x)             ((x) << 6)
 149#define         HSIO_ANA_SERDES6G_IB_CFG4_MIN_MID(x)            ((x) << 12)
 150#define         HSIO_ANA_SERDES6G_IB_CFG4_MIN_HP(x)             ((x) << 18)
 151#define HSIO_ANA_SERDES6G_OB_CFG                0x138
 152#define         HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(x)       (x)
 153#define         HSIO_ANA_SERDES6G_OB_CFG_SR(x)                  ((x) << 4)
 154#define         HSIO_ANA_SERDES6G_OB_CFG_SR_H                   BIT(8)
 155#define         HSIO_ANA_SERDES6G_OB_CFG_SEL_RCTRL              BIT(9)
 156#define         HSIO_ANA_SERDES6G_OB_CFG_R_COR                  BIT(10)
 157#define         HSIO_ANA_SERDES6G_OB_CFG_POST1(x)               ((x) << 11)
 158#define         HSIO_ANA_SERDES6G_OB_CFG_R_ADJ_PDR              BIT(16)
 159#define         HSIO_ANA_SERDES6G_OB_CFG_R_ADJ_MUX              BIT(17)
 160#define         HSIO_ANA_SERDES6G_OB_CFG_PREC(x)                ((x) << 18)
 161#define         HSIO_ANA_SERDES6G_OB_CFG_POST0(x)               ((x) << 23)
 162#define         HSIO_ANA_SERDES6G_OB_CFG_POL                    BIT(29)
 163#define         HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(x)          ((x) << 30)
 164#define         HSIO_ANA_SERDES6G_OB_CFG_IDLE                   BIT(31)
 165#define HSIO_ANA_SERDES6G_OB_CFG1               0x13c
 166#define         HSIO_ANA_SERDES6G_OB_CFG1_LEV(x)                (x)
 167#define         HSIO_ANA_SERDES6G_OB_CFG1_ENA_CAS(x)            ((x) << 6)
 168#define HSIO_ANA_SERDES6G_SER_CFG               0x140
 169#define HSIO_ANA_SERDES6G_COMMON_CFG            0x144
 170#define         HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(x)         (x)
 171#define         HSIO_ANA_SERDES6G_COMMON_CFG_QRATE(x)           (x << 2)
 172#define         HSIO_ANA_SERDES6G_COMMON_CFG_ENA_LANE           BIT(14)
 173#define         HSIO_ANA_SERDES6G_COMMON_CFG_SYS_RST            BIT(16)
 174#define HSIO_ANA_SERDES6G_PLL_CFG               0x148
 175#define         HSIO_ANA_SERDES6G_PLL_CFG_ROT_FRQ               BIT(0)
 176#define         HSIO_ANA_SERDES6G_PLL_CFG_ROT_DIR               BIT(1)
 177#define         HSIO_ANA_SERDES6G_PLL_CFG_RB_DATA_SEL           BIT(2)
 178#define         HSIO_ANA_SERDES6G_PLL_CFG_FSM_OOR_RECAL_ENA     BIT(3)
 179#define         HSIO_ANA_SERDES6G_PLL_CFG_FSM_FORCE_SET_ENA     BIT(4)
 180#define         HSIO_ANA_SERDES6G_PLL_CFG_FSM_ENA               BIT(5)
 181#define         HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(x)      ((x) << 6)
 182#define         HSIO_ANA_SERDES6G_PLL_CFG_ENA_ROT               BIT(14)
 183#define         HSIO_ANA_SERDES6G_PLL_CFG_DIV4                  BIT(15)
 184#define         HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(x)           ((x) << 16)
 185#define HSIO_DIG_SERDES6G_MISC_CFG              0x108
 186#define         HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST             BIT(0)
 187#define HSIO_MCB_SERDES6G_CFG                   0x168
 188#define         HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT               BIT(31)
 189#define         HSIO_MCB_SERDES6G_CFG_ADDR(x)                   (x)
 190#define HSIO_HW_CFGSTAT_HW_CFG                  0x16c
 191
 192#define LRN_COMMON_ACCESS_CTRL                  0x0
 193#define         LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT    BIT(0)
 194#define LRN_COMMON_MAC_ACCESS_CFG0              0x4
 195#define LRN_COMMON_MAC_ACCESS_CFG1              0x8
 196#define LRN_COMMON_MAC_ACCESS_CFG2              0xc
 197#define         LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(x)    (x)
 198#define         LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(x)    ((x) << 12)
 199#define         LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD        BIT(15)
 200#define         LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED     BIT(16)
 201#define         LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY   BIT(23)
 202#define         LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(x)  ((x) << 24)
 203
 204#define QFWD_SYSTEM_SWITCH_PORT_MODE(x)         (0x4 * (x))
 205#define         QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA           BIT(17)
 206
 207#define QS_XTR_GRP_CFG(x)               (0x0 + 4 * (x))
 208#define QS_INJ_GRP_CFG(x)               (0x24 + (x) * 4)
 209
 210#define QSYS_SYSTEM_RESET_CFG                   0xf0
 211#define QSYS_CALCFG_CAL_AUTO(x)                 (0x3d4 + 4 * (x))
 212#define QSYS_CALCFG_CAL_CTRL                    0x3e8
 213#define         QSYS_CALCFG_CAL_CTRL_CAL_MODE(x)                ((x) << 11)
 214#define QSYS_RAM_CTRL_RAM_INIT                  0x3ec
 215
 216#define REW_RAM_CTRL_RAM_INIT                   0x53528
 217
 218#define VOP_RAM_CTRL_RAM_INIT                   0x43638
 219
 220#define XTR_VALID_BYTES(x)      (4 - ((x) & 3))
 221#define MAC_VID                 0
 222#define CPU_PORT                53
 223#define IFH_LEN                 7
 224#define JR2_BUF_CELL_SZ         60
 225#define ETH_ALEN                6
 226#define PGID_BROADCAST          510
 227#define PGID_UNICAST            511
 228
 229static const char * const regs_names[] = {
 230        "port0", "port1", "port2", "port3", "port4", "port5", "port6", "port7",
 231        "port8", "port9", "port10", "port11", "port12", "port13", "port14",
 232        "port15", "port16", "port17", "port18", "port19", "port20", "port21",
 233        "port22", "port23", "port24", "port25", "port26", "port27", "port28",
 234        "port29", "port30", "port31", "port32", "port33", "port34", "port35",
 235        "port36", "port37", "port38", "port39", "port40", "port41", "port42",
 236        "port43", "port44", "port45", "port46", "port47",
 237        "ana_ac", "ana_cl", "ana_l2", "asm", "hsio", "lrn",
 238        "qfwd", "qs", "qsys", "rew", "gcb", "icpu",
 239};
 240
 241#define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1
 242#define MAX_PORT 48
 243
 244enum jr2_ctrl_regs {
 245        ANA_AC = MAX_PORT,
 246        ANA_CL,
 247        ANA_L2,
 248        ASM,
 249        HSIO,
 250        LRN,
 251        QFWD,
 252        QS,
 253        QSYS,
 254        REW,
 255        GCB,
 256        ICPU,
 257};
 258
 259#define JR2_MIIM_BUS_COUNT 3
 260
 261struct jr2_phy_port_t {
 262        size_t phy_addr;
 263        struct mii_dev *bus;
 264        u8 serdes_index;
 265        u8 phy_mode;
 266};
 267
 268struct jr2_private {
 269        void __iomem *regs[REGS_NAMES_COUNT];
 270        struct mii_dev *bus[JR2_MIIM_BUS_COUNT];
 271        struct jr2_phy_port_t ports[MAX_PORT];
 272};
 273
 274static const unsigned long jr2_regs_qs[] = {
 275        [MSCC_QS_XTR_RD] = 0x8,
 276        [MSCC_QS_XTR_FLUSH] = 0x18,
 277        [MSCC_QS_XTR_DATA_PRESENT] = 0x1c,
 278        [MSCC_QS_INJ_WR] = 0x2c,
 279        [MSCC_QS_INJ_CTRL] = 0x34,
 280};
 281
 282static struct mscc_miim_dev miim[JR2_MIIM_BUS_COUNT];
 283static int miim_count = -1;
 284
 285static void jr2_cpu_capture_setup(struct jr2_private *priv)
 286{
 287        /* ASM: No preamble and IFH prefix on CPU injected frames */
 288        writel(ASM_CFG_PORT_NO_PREAMBLE_ENA |
 289               ASM_CFG_PORT_INJ_FORMAT_CFG(1),
 290               priv->regs[ASM] + ASM_CFG_PORT(CPU_PORT));
 291
 292        /* Set Manual injection via DEVCPU_QS registers for CPU queue 0 */
 293        writel(0x5, priv->regs[QS] + QS_INJ_GRP_CFG(0));
 294
 295        /* Set Manual extraction via DEVCPU_QS registers for CPU queue 0 */
 296        writel(0x7, priv->regs[QS] + QS_XTR_GRP_CFG(0));
 297
 298        /* Enable CPU port for any frame transfer */
 299        setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(CPU_PORT),
 300                     QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
 301
 302        /* Send a copy to CPU when found as forwarding entry */
 303        setbits_le32(priv->regs[ANA_L2] + ANA_L2_COMMON_FWD_CFG,
 304                     ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA);
 305}
 306
 307static void jr2_port_init(struct jr2_private *priv, int port)
 308{
 309        void __iomem *regs = priv->regs[port];
 310
 311        /* Enable PCS */
 312        writel(DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA,
 313               regs + DEV_PCS1G_CFG_PCS1G_CFG);
 314
 315        /* Disable Signal Detect */
 316        writel(0, regs + DEV_PCS1G_CFG_PCS1G_SD);
 317
 318        /* Enable MAC RX and TX */
 319        writel(DEV_MAC_CFG_MAC_ENA_RX_ENA |
 320               DEV_MAC_CFG_MAC_ENA_TX_ENA,
 321               regs + DEV_MAC_CFG_MAC_ENA);
 322
 323        /* Clear sgmii_mode_ena */
 324        writel(0, regs + DEV_PCS1G_CFG_PCS1G_MODE);
 325
 326        /*
 327         * Clear sw_resolve_ena(bit 0) and set adv_ability to
 328         * something meaningful just in case
 329         */
 330        writel(DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(0x20),
 331               regs + DEV_PCS1G_CFG_PCS1G_ANEG);
 332
 333        /* Set MAC IFG Gaps */
 334        writel(DEV_MAC_CFG_MAC_IFG_TX_IFG(4) |
 335               DEV_MAC_CFG_MAC_IFG_RX_IFG1(5) |
 336               DEV_MAC_CFG_MAC_IFG_RX_IFG2(1),
 337               regs + DEV_MAC_CFG_MAC_IFG);
 338
 339        /* Set link speed and release all resets */
 340        writel(DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(2),
 341               regs + DEV_DEV_CFG_DEV_RST_CTRL);
 342
 343        /* Make VLAN aware for CPU traffic */
 344        writel(ANA_CL_PORT_VLAN_CFG_AWARE_ENA |
 345               ANA_CL_PORT_VLAN_CFG_POP_CNT(1) |
 346               MAC_VID,
 347               priv->regs[ANA_CL] + ANA_CL_PORT_VLAN_CFG(port));
 348
 349        /* Enable CPU port for any frame transfer */
 350        setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(port),
 351                     QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
 352}
 353
 354static void serdes6g_write(void __iomem *base, u32 addr)
 355{
 356        u32 data;
 357
 358        writel(HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT |
 359               HSIO_MCB_SERDES6G_CFG_ADDR(addr),
 360               base + HSIO_MCB_SERDES6G_CFG);
 361
 362        do {
 363                data = readl(base + HSIO_MCB_SERDES6G_CFG);
 364        } while (data & HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT);
 365}
 366
 367static void serdes6g_setup(void __iomem *base, uint32_t addr,
 368                           phy_interface_t interface)
 369{
 370        u32 ib_if_mode = 0;
 371        u32 ib_qrate = 0;
 372        u32 ib1_tsdet = 0;
 373        u32 ob_lev = 0;
 374        u32 ob_ena_cas = 0;
 375        u32 ob_ena1v_mode = 0;
 376        u32 des_bw_ana = 0;
 377        u32 pll_fsm_ctrl_data = 0;
 378
 379        switch (interface) {
 380        case PHY_INTERFACE_MODE_SGMII:
 381                ib_if_mode = 1;
 382                ib_qrate = 1;
 383                ib1_tsdet = 3;
 384                ob_lev = 48;
 385                ob_ena_cas = 2;
 386                ob_ena1v_mode = 1;
 387                des_bw_ana = 3;
 388                pll_fsm_ctrl_data = 60;
 389                break;
 390        case PHY_INTERFACE_MODE_QSGMII:
 391                ib_if_mode = 3;
 392                ib1_tsdet = 16;
 393                ob_lev = 24;
 394                des_bw_ana = 5;
 395                pll_fsm_ctrl_data = 120;
 396                break;
 397        default:
 398                pr_err("Interface not supported\n");
 399                return;
 400        }
 401
 402        if (interface == PHY_INTERFACE_MODE_QSGMII)
 403                writel(0xfff, base + HSIO_HW_CFGSTAT_HW_CFG);
 404
 405        writel(HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(1) |
 406               HSIO_ANA_SERDES6G_OB_CFG_SR(7) |
 407               HSIO_ANA_SERDES6G_OB_CFG_SR_H |
 408               HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(ob_ena1v_mode) |
 409               HSIO_ANA_SERDES6G_OB_CFG_POL, base + HSIO_ANA_SERDES6G_OB_CFG);
 410
 411        writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(3),
 412               base + HSIO_ANA_SERDES6G_COMMON_CFG);
 413        writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(120) |
 414               HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
 415               base + HSIO_ANA_SERDES6G_PLL_CFG);
 416        writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
 417               HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
 418               HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
 419               HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
 420               HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
 421               HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
 422               HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
 423               HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
 424               HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
 425               HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) |
 426               HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
 427               HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
 428               HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
 429               HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
 430               HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
 431               base + HSIO_ANA_SERDES6G_IB_CFG);
 432        writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
 433               HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
 434               HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
 435               HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
 436               HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
 437               HSIO_ANA_SERDES6G_IB_CFG1_TSDET(3) |
 438               HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
 439               base + HSIO_ANA_SERDES6G_IB_CFG1);
 440
 441        writel(HSIO_ANA_SERDES6G_IB_CFG2_UREG(4) |
 442               HSIO_ANA_SERDES6G_IB_CFG2_UMAX(2) |
 443               HSIO_ANA_SERDES6G_IB_CFG2_TCALV(12) |
 444               HSIO_ANA_SERDES6G_IB_CFG2_OCALS(32) |
 445               HSIO_ANA_SERDES6G_IB_CFG2_OINFS(7) |
 446               HSIO_ANA_SERDES6G_IB_CFG2_OINFI(0x1f) |
 447               HSIO_ANA_SERDES6G_IB_CFG2_TINFV(3),
 448               base + HSIO_ANA_SERDES6G_IB_CFG2);
 449
 450        writel(HSIO_ANA_SERDES6G_IB_CFG3_INI_OFFSET(0x1f) |
 451               HSIO_ANA_SERDES6G_IB_CFG3_INI_LP(1) |
 452               HSIO_ANA_SERDES6G_IB_CFG3_INI_MID(0x1f),
 453               base + HSIO_ANA_SERDES6G_IB_CFG3);
 454
 455        writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST,
 456               base + HSIO_DIG_SERDES6G_MISC_CFG);
 457
 458        serdes6g_write(base, addr);
 459
 460        writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
 461               HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
 462               HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
 463               HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
 464               HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
 465               HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
 466               HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
 467               HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
 468               HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
 469               HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) |
 470               HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
 471               HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
 472               HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
 473               HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
 474               HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
 475               base + HSIO_ANA_SERDES6G_IB_CFG);
 476        writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
 477               HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
 478               HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
 479               HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
 480               HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
 481               HSIO_ANA_SERDES6G_IB_CFG1_TSDET(16) |
 482               HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
 483               base + HSIO_ANA_SERDES6G_IB_CFG1);
 484
 485        writel(0x0, base + HSIO_ANA_SERDES6G_SER_CFG);
 486        writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(ib_if_mode) |
 487               HSIO_ANA_SERDES6G_COMMON_CFG_QRATE(ib_qrate) |
 488               HSIO_ANA_SERDES6G_COMMON_CFG_ENA_LANE |
 489               HSIO_ANA_SERDES6G_COMMON_CFG_SYS_RST,
 490               base + HSIO_ANA_SERDES6G_COMMON_CFG);
 491        writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST,
 492               base + HSIO_DIG_SERDES6G_MISC_CFG);
 493
 494        writel(HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(1) |
 495               HSIO_ANA_SERDES6G_OB_CFG_SR(7) |
 496               HSIO_ANA_SERDES6G_OB_CFG_SR_H |
 497               HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(ob_ena1v_mode) |
 498               HSIO_ANA_SERDES6G_OB_CFG_POL, base + HSIO_ANA_SERDES6G_OB_CFG);
 499        writel(HSIO_ANA_SERDES6G_OB_CFG1_LEV(ob_lev) |
 500               HSIO_ANA_SERDES6G_OB_CFG1_ENA_CAS(ob_ena_cas),
 501               base + HSIO_ANA_SERDES6G_OB_CFG1);
 502
 503        writel(HSIO_ANA_SERDES6G_DES_CFG_BW_ANA(des_bw_ana) |
 504               HSIO_ANA_SERDES6G_DES_CFG_BW_HYST(5) |
 505               HSIO_ANA_SERDES6G_DES_CFG_MBTR_CTRL(2) |
 506               HSIO_ANA_SERDES6G_DES_CFG_PHS_CTRL(6),
 507               base + HSIO_ANA_SERDES6G_DES_CFG);
 508        writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) |
 509               HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
 510               base + HSIO_ANA_SERDES6G_PLL_CFG);
 511
 512        serdes6g_write(base, addr);
 513
 514        /* set pll_fsm_ena = 1 */
 515        writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_ENA |
 516               HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) |
 517               HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
 518               base + HSIO_ANA_SERDES6G_PLL_CFG);
 519
 520        serdes6g_write(base, addr);
 521
 522        /* wait 20ms for pll bringup */
 523        mdelay(20);
 524
 525        /* start IB calibration by setting ib_cal_ena and clearing lane_rst */
 526        writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
 527               HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
 528               HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
 529               HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(1) |
 530               HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
 531               HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
 532               HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
 533               HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
 534               HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
 535               HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
 536               HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) |
 537               HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
 538               HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
 539               HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
 540               HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
 541               HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
 542               base + HSIO_ANA_SERDES6G_IB_CFG);
 543        writel(0x0, base + HSIO_DIG_SERDES6G_MISC_CFG);
 544
 545        serdes6g_write(base, addr);
 546
 547        /* wait 60 for calibration */
 548        mdelay(60);
 549
 550        /* set ib_tsdet and ib_reg_pat_sel_offset back to correct values */
 551        writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
 552               HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
 553               HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
 554               HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(1) |
 555               HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
 556               HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
 557               HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
 558               HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
 559               HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
 560               HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
 561               HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) |
 562               HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
 563               HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
 564               HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
 565               HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
 566               HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
 567               base + HSIO_ANA_SERDES6G_IB_CFG);
 568        writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
 569               HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
 570               HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
 571               HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
 572               HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
 573               HSIO_ANA_SERDES6G_IB_CFG1_TSDET(ib1_tsdet) |
 574               HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
 575               base + HSIO_ANA_SERDES6G_IB_CFG1);
 576
 577        serdes6g_write(base, addr);
 578}
 579
 580static void serdes1g_write(void __iomem *base, u32 addr)
 581{
 582        u32 data;
 583
 584        writel(HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT |
 585               HSIO_MCB_SERDES1G_CFG_ADDR(addr),
 586               base + HSIO_MCB_SERDES1G_CFG);
 587
 588        do {
 589                data = readl(base + HSIO_MCB_SERDES1G_CFG);
 590        } while (data & HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT);
 591}
 592
 593static void serdes1g_setup(void __iomem *base, uint32_t addr,
 594                           phy_interface_t interface)
 595{
 596        writel(0x0, base + HSIO_ANA_SERDES1G_SER_CFG);
 597        writel(0x0, base + HSIO_DIG_SERDES1G_TP_CFG);
 598        writel(0x0, base + HSIO_DIG_SERDES1G_DFT_CFG0);
 599        writel(HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(1) |
 600               HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(4) |
 601               HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(2) |
 602               HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(12) |
 603               HSIO_ANA_SERDES1G_OB_CFG_SLP(3),
 604               base + HSIO_ANA_SERDES1G_OB_CFG);
 605        writel(HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(13) |
 606               HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(2) |
 607               HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP |
 608               HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV |
 609               HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM |
 610               HSIO_ANA_SERDES1G_IB_CFG_DET_LEV(3) |
 611               HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(1),
 612               base + HSIO_ANA_SERDES1G_IB_CFG);
 613        writel(HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(7) |
 614               HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(6) |
 615               HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(2) |
 616               HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(6),
 617               base + HSIO_ANA_SERDES1G_DES_CFG);
 618        writel(HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST,
 619               base + HSIO_DIG_SERDES1G_MISC_CFG);
 620        writel(HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA |
 621               HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(0xc8) |
 622               HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2,
 623               base + HSIO_ANA_SERDES1G_PLL_CFG);
 624        writel(HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE |
 625               HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE |
 626               HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST,
 627               base + HSIO_ANA_SERDES1G_COMMON_CFG);
 628
 629        serdes1g_write(base, addr);
 630
 631        setbits_le32(base + HSIO_ANA_SERDES1G_COMMON_CFG,
 632                     HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST);
 633
 634        serdes1g_write(base, addr);
 635
 636        clrbits_le32(base + HSIO_DIG_SERDES1G_MISC_CFG,
 637                     HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST);
 638
 639        serdes1g_write(base, addr);
 640}
 641
 642static int ram_init(u32 val, void __iomem *addr)
 643{
 644        writel(val, addr);
 645
 646        if (wait_for_bit_le32(addr, BIT(1), false, 2000, false)) {
 647                printf("Timeout in memory reset, reg = 0x%08x\n", val);
 648                return 1;
 649        }
 650
 651        return 0;
 652}
 653
 654static int jr2_switch_init(struct jr2_private *priv)
 655{
 656        /* Initialize memories */
 657        ram_init(0x3, priv->regs[QSYS] + QSYS_RAM_CTRL_RAM_INIT);
 658        ram_init(0x3, priv->regs[ASM] + ASM_RAM_CTRL_RAM_INIT);
 659        ram_init(0x3, priv->regs[ANA_AC] + ANA_AC_RAM_CTRL_RAM_INIT);
 660        ram_init(0x3, priv->regs[REW] + REW_RAM_CTRL_RAM_INIT);
 661
 662        /* Reset counters */
 663        writel(0x1, priv->regs[ANA_AC] + ANA_AC_STAT_GLOBAL_CFG_PORT_RESET);
 664        writel(0x1, priv->regs[ASM] + ASM_CFG_STAT_CFG);
 665
 666        /* Enable switch-core and queue system */
 667        writel(0x1, priv->regs[QSYS] + QSYS_SYSTEM_RESET_CFG);
 668
 669        return 0;
 670}
 671
 672static void jr2_switch_config(struct jr2_private *priv)
 673{
 674        writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(0));
 675        writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(1));
 676        writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(2));
 677        writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(3));
 678
 679        writel(readl(priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL) |
 680               QSYS_CALCFG_CAL_CTRL_CAL_MODE(8),
 681               priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL);
 682}
 683
 684static int jr2_initialize(struct jr2_private *priv)
 685{
 686        int ret, i;
 687
 688        /* Initialize switch memories, enable core */
 689        ret = jr2_switch_init(priv);
 690        if (ret)
 691                return ret;
 692
 693        jr2_switch_config(priv);
 694
 695        for (i = 0; i < MAX_PORT; i++)
 696                jr2_port_init(priv, i);
 697
 698        jr2_cpu_capture_setup(priv);
 699
 700        return 0;
 701}
 702
 703static inline int jr2_vlant_wait_for_completion(struct jr2_private *priv)
 704{
 705        if (wait_for_bit_le32(priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL,
 706                              LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
 707                              false, 2000, false))
 708                return -ETIMEDOUT;
 709
 710        return 0;
 711}
 712
 713static int jr2_mac_table_add(struct jr2_private *priv,
 714                             const unsigned char mac[ETH_ALEN], int pgid)
 715{
 716        u32 macl = 0, mach = 0;
 717
 718        /*
 719         * Set the MAC address to handle and the vlan associated in a format
 720         * understood by the hardware.
 721         */
 722        mach |= MAC_VID << 16;
 723        mach |= ((u32)mac[0]) << 8;
 724        mach |= ((u32)mac[1]) << 0;
 725        macl |= ((u32)mac[2]) << 24;
 726        macl |= ((u32)mac[3]) << 16;
 727        macl |= ((u32)mac[4]) << 8;
 728        macl |= ((u32)mac[5]) << 0;
 729
 730        writel(mach, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG0);
 731        writel(macl, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG1);
 732
 733        writel(LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(pgid) |
 734               LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(0x3) |
 735               LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY |
 736               LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(0) |
 737               LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD |
 738               LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED,
 739               priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG2);
 740
 741        writel(LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
 742               priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL);
 743
 744        return jr2_vlant_wait_for_completion(priv);
 745}
 746
 747static int jr2_write_hwaddr(struct udevice *dev)
 748{
 749        struct jr2_private *priv = dev_get_priv(dev);
 750        struct eth_pdata *pdata = dev_get_plat(dev);
 751
 752        return jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
 753}
 754
 755static void serdes_setup(struct jr2_private *priv)
 756{
 757        size_t mask;
 758        int i = 0;
 759
 760        for (i = 0; i < MAX_PORT; ++i) {
 761                if (!priv->ports[i].bus || priv->ports[i].serdes_index == 0xff)
 762                        continue;
 763
 764                mask = BIT(priv->ports[i].serdes_index);
 765                if (priv->ports[i].serdes_index < SERDES1G_MAX) {
 766                        serdes1g_setup(priv->regs[HSIO], mask,
 767                                       priv->ports[i].phy_mode);
 768                } else {
 769                        mask >>= SERDES6G(0);
 770                        serdes6g_setup(priv->regs[HSIO], mask,
 771                                       priv->ports[i].phy_mode);
 772                }
 773        }
 774}
 775
 776static int jr2_start(struct udevice *dev)
 777{
 778        struct jr2_private *priv = dev_get_priv(dev);
 779        struct eth_pdata *pdata = dev_get_plat(dev);
 780        const unsigned char mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff,
 781                0xff };
 782        int ret;
 783
 784        ret = jr2_initialize(priv);
 785        if (ret)
 786                return ret;
 787
 788        /* Set MAC address tables entries for CPU redirection */
 789        ret = jr2_mac_table_add(priv, mac, PGID_BROADCAST);
 790        if (ret)
 791                return ret;
 792
 793        ret = jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
 794        if (ret)
 795                return ret;
 796
 797        serdes_setup(priv);
 798
 799        return 0;
 800}
 801
 802static void jr2_stop(struct udevice *dev)
 803{
 804}
 805
 806static int jr2_send(struct udevice *dev, void *packet, int length)
 807{
 808        struct jr2_private *priv = dev_get_priv(dev);
 809        u32 ifh[IFH_LEN];
 810        u32 *buf = packet;
 811
 812        memset(ifh, '\0', IFH_LEN);
 813
 814        /* Set DST PORT_MASK */
 815        ifh[0] = htonl(0);
 816        ifh[1] = htonl(0x1FFFFF);
 817        ifh[2] = htonl(~0);
 818        /* Set DST_MODE to INJECT and UPDATE_FCS */
 819        ifh[5] = htonl(0x4c0);
 820
 821        return mscc_send(priv->regs[QS], jr2_regs_qs,
 822                         ifh, IFH_LEN, buf, length);
 823}
 824
 825static int jr2_recv(struct udevice *dev, int flags, uchar **packetp)
 826{
 827        struct jr2_private *priv = dev_get_priv(dev);
 828        u32 *rxbuf = (u32 *)net_rx_packets[0];
 829        int byte_cnt = 0;
 830
 831        byte_cnt = mscc_recv(priv->regs[QS], jr2_regs_qs, rxbuf, IFH_LEN,
 832                             false);
 833
 834        *packetp = net_rx_packets[0];
 835
 836        return byte_cnt;
 837}
 838
 839static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size)
 840{
 841        int i = 0;
 842
 843        for (i = 0; i < JR2_MIIM_BUS_COUNT; ++i)
 844                if (miim[i].miim_base == base && miim[i].miim_size == size)
 845                        return miim[i].bus;
 846
 847        return NULL;
 848}
 849
 850static void add_port_entry(struct jr2_private *priv, size_t index,
 851                           size_t phy_addr, struct mii_dev *bus,
 852                           u8 serdes_index, u8 phy_mode)
 853{
 854        priv->ports[index].phy_addr = phy_addr;
 855        priv->ports[index].bus = bus;
 856        priv->ports[index].serdes_index = serdes_index;
 857        priv->ports[index].phy_mode = phy_mode;
 858}
 859
 860static int jr2_probe(struct udevice *dev)
 861{
 862        struct jr2_private *priv = dev_get_priv(dev);
 863        int i;
 864        int ret;
 865        struct resource res;
 866        phys_addr_t addr_base;
 867        unsigned long addr_size;
 868        ofnode eth_node, node, mdio_node;
 869        size_t phy_addr;
 870        struct mii_dev *bus;
 871        struct ofnode_phandle_args phandle;
 872        struct phy_device *phy;
 873        u32 val;
 874
 875        if (!priv)
 876                return -EINVAL;
 877
 878        /* Get registers and map them to the private structure */
 879        for (i = 0; i < ARRAY_SIZE(regs_names); i++) {
 880                priv->regs[i] = dev_remap_addr_name(dev, regs_names[i]);
 881                if (!priv->regs[i]) {
 882                        debug
 883                            ("Error can't get regs base addresses for %s\n",
 884                             regs_names[i]);
 885                        return -ENOMEM;
 886                }
 887        }
 888
 889        val = readl(priv->regs[ICPU] + ICPU_RESET);
 890        val |= ICPU_RESET_CORE_RST_PROTECT;
 891        writel(val, priv->regs[ICPU] + ICPU_RESET);
 892
 893        val = readl(priv->regs[GCB] + PERF_SOFT_RST);
 894        val |= PERF_SOFT_RST_SOFT_SWC_RST;
 895        writel(val, priv->regs[GCB] + PERF_SOFT_RST);
 896
 897        while (readl(priv->regs[GCB] + PERF_SOFT_RST) & PERF_SOFT_RST_SOFT_SWC_RST)
 898                ;
 899
 900        /* Initialize miim buses */
 901        memset(&miim, 0x0, sizeof(struct mscc_miim_dev) * JR2_MIIM_BUS_COUNT);
 902
 903        /* iterate all the ports and find out on which bus they are */
 904        i = 0;
 905        eth_node = dev_read_first_subnode(dev);
 906        for (node = ofnode_first_subnode(eth_node);
 907             ofnode_valid(node);
 908             node = ofnode_next_subnode(node)) {
 909                if (ofnode_read_resource(node, 0, &res))
 910                        return -ENOMEM;
 911                i = res.start;
 912
 913                ret = ofnode_parse_phandle_with_args(node, "phy-handle", NULL,
 914                                                     0, 0, &phandle);
 915                if (ret)
 916                        continue;
 917
 918                /* Get phy address on mdio bus */
 919                if (ofnode_read_resource(phandle.node, 0, &res))
 920                        return -ENOMEM;
 921                phy_addr = res.start;
 922
 923                /* Get mdio node */
 924                mdio_node = ofnode_get_parent(phandle.node);
 925
 926                if (ofnode_read_resource(mdio_node, 0, &res))
 927                        return -ENOMEM;
 928
 929                addr_base = res.start;
 930                addr_size = res.end - res.start;
 931
 932                /* If the bus is new then create a new bus */
 933                if (!get_mdiobus(addr_base, addr_size))
 934                        priv->bus[miim_count] =
 935                                mscc_mdiobus_init(miim, &miim_count, addr_base,
 936                                                  addr_size);
 937
 938                /* Connect mdio bus with the port */
 939                bus = get_mdiobus(addr_base, addr_size);
 940
 941                /* Get serdes info */
 942                ret = ofnode_parse_phandle_with_args(node, "phys", NULL,
 943                                                     3, 0, &phandle);
 944                if (ret)
 945                        return -ENOMEM;
 946
 947                add_port_entry(priv, i, phy_addr, bus, phandle.args[1],
 948                               phandle.args[2]);
 949        }
 950
 951        for (i = 0; i < MAX_PORT; i++) {
 952                if (!priv->ports[i].bus)
 953                        continue;
 954
 955                phy = phy_connect(priv->ports[i].bus,
 956                                  priv->ports[i].phy_addr, dev,
 957                                  PHY_INTERFACE_MODE_NONE);
 958                if (phy)
 959                        board_phy_config(phy);
 960        }
 961
 962        return 0;
 963}
 964
 965static int jr2_remove(struct udevice *dev)
 966{
 967        struct jr2_private *priv = dev_get_priv(dev);
 968        int i;
 969
 970        for (i = 0; i < JR2_MIIM_BUS_COUNT; i++) {
 971                mdio_unregister(priv->bus[i]);
 972                mdio_free(priv->bus[i]);
 973        }
 974
 975        return 0;
 976}
 977
 978static const struct eth_ops jr2_ops = {
 979        .start        = jr2_start,
 980        .stop         = jr2_stop,
 981        .send         = jr2_send,
 982        .recv         = jr2_recv,
 983        .write_hwaddr = jr2_write_hwaddr,
 984};
 985
 986static const struct udevice_id mscc_jr2_ids[] = {
 987        {.compatible = "mscc,vsc7454-switch" },
 988        { /* Sentinel */ }
 989};
 990
 991U_BOOT_DRIVER(jr2) = {
 992        .name                           = "jr2-switch",
 993        .id                             = UCLASS_ETH,
 994        .of_match                       = mscc_jr2_ids,
 995        .probe                          = jr2_probe,
 996        .remove                         = jr2_remove,
 997        .ops                            = &jr2_ops,
 998        .priv_auto              = sizeof(struct jr2_private),
 999        .plat_auto      = sizeof(struct eth_pdata),
1000};
1001