[U-Boot] [PATCH v3 0/4] Add network support for Jaguar2 SoCs

v3-changes: - move serdes setup in network driver and read serdes configuration from DT.
v2-changes: - create serdes6g_setup and serdes1g_setup functions to be easier to extand for future boards.
Horatiu Vultur (4): net: Add MSCC Jaguar2 network driver. board: mscc: jr2: Update MSCC Jaguar2 boards net: mscc: jaguar2: Add ethenet nodes for Jaguar2. configs: mscc_jr2: Add network support
arch/mips/dts/jr2_pcb110.dts | 76 +++ arch/mips/dts/jr2_pcb111.dts | 400 ++++++++++++ arch/mips/dts/mscc,jr2.dtsi | 116 ++++ arch/mips/dts/serval2_pcb112.dts | 44 ++ board/mscc/jr2/jr2.c | 23 + configs/mscc_jr2_defconfig | 6 +- drivers/net/mscc_eswitch/Kconfig | 7 + drivers/net/mscc_eswitch/Makefile | 1 + drivers/net/mscc_eswitch/jr2_switch.c | 1075 +++++++++++++++++++++++++++++++++ include/configs/vcoreiii.h | 2 +- include/dt-bindings/mscc/jr2_data.h | 19 + 11 files changed, 1767 insertions(+), 2 deletions(-) create mode 100644 drivers/net/mscc_eswitch/jr2_switch.c create mode 100644 include/dt-bindings/mscc/jr2_data.h

Add network driver for Microsemi Ethernet switch. It is present on Jaguar2 SoCs.
Signed-off-by: Horatiu Vultur horatiu.vultur@microchip.com --- drivers/net/mscc_eswitch/Kconfig | 7 + drivers/net/mscc_eswitch/Makefile | 1 + drivers/net/mscc_eswitch/jr2_switch.c | 1075 +++++++++++++++++++++++++++++++++ include/configs/vcoreiii.h | 2 +- 4 files changed, 1084 insertions(+), 1 deletion(-) create mode 100644 drivers/net/mscc_eswitch/jr2_switch.c
diff --git a/drivers/net/mscc_eswitch/Kconfig b/drivers/net/mscc_eswitch/Kconfig index 88e5a97..3f9d14b 100644 --- a/drivers/net/mscc_eswitch/Kconfig +++ b/drivers/net/mscc_eswitch/Kconfig @@ -15,3 +15,10 @@ config MSCC_LUTON_SWITCH select PHYLIB help This driver supports the Luton network switch device. + +config MSCC_JR2_SWITCH + bool "Jaguar2 switch driver" + depends on DM_ETH && ARCH_MSCC + select PHYLIB + help + This driver supports the Jaguar2 network switch device. diff --git a/drivers/net/mscc_eswitch/Makefile b/drivers/net/mscc_eswitch/Makefile index 751a839..0a1b863 100644 --- a/drivers/net/mscc_eswitch/Makefile +++ b/drivers/net/mscc_eswitch/Makefile @@ -1,3 +1,4 @@
obj-$(CONFIG_MSCC_OCELOT_SWITCH) += ocelot_switch.o mscc_miim.o mscc_xfer.o mscc_mac_table.o obj-$(CONFIG_MSCC_LUTON_SWITCH) += luton_switch.o mscc_miim.o mscc_xfer.o mscc_mac_table.o +obj-$(CONFIG_MSCC_JR2_SWITCH) += jr2_switch.o mscc_xfer.o diff --git a/drivers/net/mscc_eswitch/jr2_switch.c b/drivers/net/mscc_eswitch/jr2_switch.c new file mode 100644 index 0000000..d4a2498 --- /dev/null +++ b/drivers/net/mscc_eswitch/jr2_switch.c @@ -0,0 +1,1075 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2018 Microsemi Corporation + */ + +#include <common.h> +#include <config.h> +#include <dm.h> +#include <dm/of_access.h> +#include <dm/of_addr.h> +#include <fdt_support.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <miiphy.h> +#include <net.h> +#include <wait_bit.h> + +#include <dt-bindings/mscc/jr2_data.h> +#include "mscc_xfer.h" + +#define GCB_MIIM_MII_STATUS 0x0 +#define GCB_MIIM_STAT_BUSY BIT(3) +#define GCB_MIIM_MII_CMD 0x8 +#define GCB_MIIM_MII_CMD_SCAN BIT(0) +#define GCB_MIIM_MII_CMD_OPR_WRITE BIT(1) +#define GCB_MIIM_MII_CMD_OPR_READ BIT(2) +#define GCB_MIIM_MII_CMD_SINGLE_SCAN BIT(3) +#define GCB_MIIM_MII_CMD_WRDATA(x) ((x) << 4) +#define GCB_MIIM_MII_CMD_REGAD(x) ((x) << 20) +#define GCB_MIIM_MII_CMD_PHYAD(x) ((x) << 25) +#define GCB_MIIM_MII_CMD_VLD BIT(31) +#define GCB_MIIM_DATA 0xC +#define GCB_MIIM_DATA_ERROR (0x3 << 16) + +#define ANA_AC_RAM_CTRL_RAM_INIT 0x94358 +#define ANA_AC_STAT_GLOBAL_CFG_PORT_RESET 0x94370 + +#define ANA_CL_PORT_VLAN_CFG(x) (0x24018 + 0xc8 * (x)) +#define ANA_CL_PORT_VLAN_CFG_AWARE_ENA BIT(19) +#define ANA_CL_PORT_VLAN_CFG_POP_CNT(x) ((x) << 17) + +#define ANA_L2_COMMON_FWD_CFG 0x8a2a8 +#define ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA BIT(6) + +#define ASM_CFG_STAT_CFG 0x3508 +#define ASM_CFG_PORT(x) (0x36c4 + 0x4 * (x)) +#define ASM_CFG_PORT_NO_PREAMBLE_ENA BIT(8) +#define ASM_CFG_PORT_INJ_FORMAT_CFG(x) ((x) << 1) +#define ASM_RAM_CTRL_RAM_INIT 0x39b8 + +#define DEV_DEV_CFG_DEV_RST_CTRL 0x0 +#define DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(x) ((x) << 20) +#define DEV_MAC_CFG_MAC_ENA 0x1c +#define DEV_MAC_CFG_MAC_ENA_RX_ENA BIT(4) +#define DEV_MAC_CFG_MAC_ENA_TX_ENA BIT(0) +#define DEV_MAC_CFG_MAC_IFG 0x34 +#define DEV_MAC_CFG_MAC_IFG_TX_IFG(x) ((x) << 8) +#define DEV_MAC_CFG_MAC_IFG_RX_IFG2(x) ((x) << 4) +#define DEV_MAC_CFG_MAC_IFG_RX_IFG1(x) (x) +#define DEV_PCS1G_CFG_PCS1G_CFG 0x40 +#define DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA BIT(0) +#define DEV_PCS1G_CFG_PCS1G_MODE 0x44 +#define DEV_PCS1G_CFG_PCS1G_SD 0x48 +#define DEV_PCS1G_CFG_PCS1G_ANEG 0x4c +#define DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(x) ((x) << 16) + +#define DSM_RAM_CTRL_RAM_INIT 0x8 + +#define HSIO_ANA_SERDES1G_DES_CFG 0xac +#define HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(x) ((x) << 1) +#define HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(x) ((x) << 5) +#define HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(x) ((x) << 8) +#define HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(x) ((x) << 13) +#define HSIO_ANA_SERDES1G_IB_CFG 0xb0 +#define HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(x) (x) +#define HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(x) ((x) << 6) +#define HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP BIT(9) +#define HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV BIT(11) +#define HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM BIT(13) +#define HSIO_ANA_SERDES1G_IB_CFG_DET_LEV(x) ((x) << 19) +#define HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(x) ((x) << 24) +#define HSIO_ANA_SERDES1G_OB_CFG 0xb4 +#define HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(x) (x) +#define HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(x) ((x) << 4) +#define HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(x) ((x) << 10) +#define HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(x) ((x) << 13) +#define HSIO_ANA_SERDES1G_OB_CFG_SLP(x) ((x) << 17) +#define HSIO_ANA_SERDES1G_SER_CFG 0xb8 +#define HSIO_ANA_SERDES1G_COMMON_CFG 0xbc +#define HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE BIT(0) +#define HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE BIT(18) +#define HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST BIT(31) +#define HSIO_ANA_SERDES1G_PLL_CFG 0xc0 +#define HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA BIT(7) +#define HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(x) ((x) << 8) +#define HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2 BIT(21) +#define HSIO_DIG_SERDES1G_DFT_CFG0 0xc8 +#define HSIO_DIG_SERDES1G_TP_CFG 0xd4 +#define HSIO_DIG_SERDES1G_MISC_CFG 0xdc +#define HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST BIT(0) +#define HSIO_MCB_SERDES1G_CFG 0xe8 +#define HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT BIT(31) +#define HSIO_MCB_SERDES1G_CFG_ADDR(x) (x) + +#define HSIO_ANA_SERDES6G_DES_CFG 0x11c +#define HSIO_ANA_SERDES6G_DES_CFG_SWAP_ANA BIT(0) +#define HSIO_ANA_SERDES6G_DES_CFG_BW_ANA(x) ((x) << 1) +#define HSIO_ANA_SERDES6G_DES_CFG_SWAP_HYST BIT(4) +#define HSIO_ANA_SERDES6G_DES_CFG_BW_HYST(x) ((x) << 5) +#define HSIO_ANA_SERDES6G_DES_CFG_CPMD_SEL(x) ((x) << 8) +#define HSIO_ANA_SERDES6G_DES_CFG_MBTR_CTRL(x) ((x) << 10) +#define HSIO_ANA_SERDES6G_DES_CFG_PHS_CTRL(x) ((x) << 13) +#define HSIO_ANA_SERDES6G_IB_CFG 0x120 +#define HSIO_ANA_SERDES6G_IB_CFG_REG_ENA BIT(0) +#define HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA BIT(1) +#define HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA BIT(2) +#define HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(x) ((x) << 3) +#define HSIO_ANA_SERDES6G_IB_CFG_CONCUR BIT(4) +#define HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA BIT(5) +#define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(x) ((x) << 7) +#define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(x) ((x) << 9) +#define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(x) ((x) << 11) +#define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(x) ((x) << 13) +#define HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(x) ((x) << 15) +#define HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(x) ((x) << 18) +#define HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(x) ((x) << 20) +#define HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(x) ((x) << 24) +#define HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL BIT(28) +#define HSIO_ANA_SERDES6G_IB_CFG_SOFSI(x) ((x) << 29) +#define HSIO_ANA_SERDES6G_IB_CFG1 0x124 +#define HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET BIT(4) +#define HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP BIT(5) +#define HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID BIT(6) +#define HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP BIT(7) +#define HSIO_ANA_SERDES6G_IB_CFG1_SCALY(x) ((x) << 8) +#define HSIO_ANA_SERDES6G_IB_CFG1_TSDET(x) ((x) << 12) +#define HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(x) ((x) << 17) +#define HSIO_ANA_SERDES6G_IB_CFG2 0x128 +#define HSIO_ANA_SERDES6G_IB_CFG2_UREG(x) (x) +#define HSIO_ANA_SERDES6G_IB_CFG2_UMAX(x) ((x) << 3) +#define HSIO_ANA_SERDES6G_IB_CFG2_TCALV(x) ((x) << 5) +#define HSIO_ANA_SERDES6G_IB_CFG2_OCALS(x) ((x) << 10) +#define HSIO_ANA_SERDES6G_IB_CFG2_OINFS(x) ((x) << 16) +#define HSIO_ANA_SERDES6G_IB_CFG2_OINFI(x) ((x) << 22) +#define HSIO_ANA_SERDES6G_IB_CFG2_TINFV(x) ((x) << 27) +#define HSIO_ANA_SERDES6G_IB_CFG3 0x12c +#define HSIO_ANA_SERDES6G_IB_CFG3_INI_OFFSET(x) (x) +#define HSIO_ANA_SERDES6G_IB_CFG3_INI_LP(x) ((x) << 6) +#define HSIO_ANA_SERDES6G_IB_CFG3_INI_MID(x) ((x) << 12) +#define HSIO_ANA_SERDES6G_IB_CFG3_INI_HP(x) ((x) << 18) +#define HSIO_ANA_SERDES6G_IB_CFG4 0x130 +#define HSIO_ANA_SERDES6G_IB_CFG4_MAX_OFFSET(x) (x) +#define HSIO_ANA_SERDES6G_IB_CFG4_MAX_LP(x) ((x) << 6) +#define HSIO_ANA_SERDES6G_IB_CFG4_MAX_MID(x) ((x) << 12) +#define HSIO_ANA_SERDES6G_IB_CFG4_MAX_HP(x) ((x) << 18) +#define HSIO_ANA_SERDES6G_IB_CFG5 0x134 +#define HSIO_ANA_SERDES6G_IB_CFG4_MIN_OFFSET(x) (x) +#define HSIO_ANA_SERDES6G_IB_CFG4_MIN_LP(x) ((x) << 6) +#define HSIO_ANA_SERDES6G_IB_CFG4_MIN_MID(x) ((x) << 12) +#define HSIO_ANA_SERDES6G_IB_CFG4_MIN_HP(x) ((x) << 18) +#define HSIO_ANA_SERDES6G_OB_CFG 0x138 +#define HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(x) (x) +#define HSIO_ANA_SERDES6G_OB_CFG_SR(x) ((x) << 4) +#define HSIO_ANA_SERDES6G_OB_CFG_SR_H BIT(8) +#define HSIO_ANA_SERDES6G_OB_CFG_SEL_RCTRL BIT(9) +#define HSIO_ANA_SERDES6G_OB_CFG_R_COR BIT(10) +#define HSIO_ANA_SERDES6G_OB_CFG_POST1(x) ((x) << 11) +#define HSIO_ANA_SERDES6G_OB_CFG_R_ADJ_PDR BIT(16) +#define HSIO_ANA_SERDES6G_OB_CFG_R_ADJ_MUX BIT(17) +#define HSIO_ANA_SERDES6G_OB_CFG_PREC(x) ((x) << 18) +#define HSIO_ANA_SERDES6G_OB_CFG_POST0(x) ((x) << 23) +#define HSIO_ANA_SERDES6G_OB_CFG_POL BIT(29) +#define HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(x) ((x) << 30) +#define HSIO_ANA_SERDES6G_OB_CFG_IDLE BIT(31) +#define HSIO_ANA_SERDES6G_OB_CFG1 0x13c +#define HSIO_ANA_SERDES6G_OB_CFG1_LEV(x) (x) +#define HSIO_ANA_SERDES6G_OB_CFG1_ENA_CAS(x) ((x) << 6) +#define HSIO_ANA_SERDES6G_SER_CFG 0x140 +#define HSIO_ANA_SERDES6G_COMMON_CFG 0x144 +#define HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(x) (x) +#define HSIO_ANA_SERDES6G_COMMON_CFG_QRATE(x) (x << 2) +#define HSIO_ANA_SERDES6G_COMMON_CFG_ENA_LANE BIT(14) +#define HSIO_ANA_SERDES6G_COMMON_CFG_SYS_RST BIT(16) +#define HSIO_ANA_SERDES6G_PLL_CFG 0x148 +#define HSIO_ANA_SERDES6G_PLL_CFG_ROT_FRQ BIT(0) +#define HSIO_ANA_SERDES6G_PLL_CFG_ROT_DIR BIT(1) +#define HSIO_ANA_SERDES6G_PLL_CFG_RB_DATA_SEL BIT(2) +#define HSIO_ANA_SERDES6G_PLL_CFG_FSM_OOR_RECAL_ENA BIT(3) +#define HSIO_ANA_SERDES6G_PLL_CFG_FSM_FORCE_SET_ENA BIT(4) +#define HSIO_ANA_SERDES6G_PLL_CFG_FSM_ENA BIT(5) +#define HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(x) ((x) << 6) +#define HSIO_ANA_SERDES6G_PLL_CFG_ENA_ROT BIT(14) +#define HSIO_ANA_SERDES6G_PLL_CFG_DIV4 BIT(15) +#define HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(x) ((x) << 16) +#define HSIO_DIG_SERDES6G_MISC_CFG 0x108 +#define HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST BIT(0) +#define HSIO_MCB_SERDES6G_CFG 0x168 +#define HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT BIT(31) +#define HSIO_MCB_SERDES6G_CFG_ADDR(x) (x) +#define HSIO_HW_CFGSTAT_HW_CFG 0x16c + +#define LRN_COMMON_ACCESS_CTRL 0x0 +#define LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT BIT(0) +#define LRN_COMMON_MAC_ACCESS_CFG0 0x4 +#define LRN_COMMON_MAC_ACCESS_CFG1 0x8 +#define LRN_COMMON_MAC_ACCESS_CFG2 0xc +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(x) (x) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(x) ((x) << 12) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD BIT(15) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED BIT(16) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY BIT(23) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(x) ((x) << 24) + +#define QFWD_SYSTEM_SWITCH_PORT_MODE(x) (0x4 * (x)) +#define QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA BIT(17) + +#define QS_XTR_GRP_CFG(x) (0x0 + 4 * (x)) +#define QS_INJ_GRP_CFG(x) (0x24 + (x) * 4) + +#define QSYS_SYSTEM_RESET_CFG 0xf0 +#define QSYS_CALCFG_CAL_AUTO(x) (0x3d4 + 4 * (x)) +#define QSYS_CALCFG_CAL_CTRL 0x3e8 +#define QSYS_CALCFG_CAL_CTRL_CAL_MODE(x) ((x) << 11) +#define QSYS_RAM_CTRL_RAM_INIT 0x3ec + +#define REW_RAM_CTRL_RAM_INIT 0x53528 + +#define VOP_RAM_CTRL_RAM_INIT 0x43638 + +#define XTR_VALID_BYTES(x) (4 - ((x) & 3)) +#define MAC_VID 0 +#define CPU_PORT 53 +#define IFH_LEN 7 +#define JR2_BUF_CELL_SZ 60 +#define ETH_ALEN 6 +#define PGID_BROADCAST 510 +#define PGID_UNICAST 511 + +static char *regs_names[] = { + "port0", "port1", "port2", "port3", "port4", "port5", "port6", "port7", + "port8", "port9", "port10", "port11", "port12", "port13", "port14", + "port15", "port16", "port17", "port18", "port19", "port20", "port21", + "port22", "port23", "port24", "port25", "port26", "port27", "port28", + "port29", "port30", "port31", "port32", "port33", "port34", "port35", + "port36", "port37", "port38", "port39", "port40", "port41", "port42", + "port43", "port44", "port45", "port46", "port47", + "ana_ac", "ana_cl", "ana_l2", "asm", "hsio", "lrn", + "qfwd", "qs", "qsys", "rew", +}; + +#define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1 +#define MAX_PORT 48 + +enum jr2_ctrl_regs { + ANA_AC = MAX_PORT, + ANA_CL, + ANA_L2, + ASM, + HSIO, + LRN, + QFWD, + QS, + QSYS, + REW, +}; + +#define JR2_MIIM_BUS_COUNT 3 + +struct jr2_phy_port_t { + size_t phy_addr; + struct mii_dev *bus; + u8 serdes_index; + u8 phy_mode; +}; + +struct jr2_private { + void __iomem *regs[REGS_NAMES_COUNT]; + struct mii_dev *bus[JR2_MIIM_BUS_COUNT]; + struct jr2_phy_port_t ports[MAX_PORT]; +}; + +struct jr2_miim_dev { + void __iomem *regs; + phys_addr_t miim_base; + unsigned long miim_size; + struct mii_dev *bus; +}; + +static const unsigned long jr2_regs_qs[] = { + [MSCC_QS_XTR_RD] = 0x8, + [MSCC_QS_XTR_FLUSH] = 0x18, + [MSCC_QS_XTR_DATA_PRESENT] = 0x1c, + [MSCC_QS_INJ_WR] = 0x2c, + [MSCC_QS_INJ_CTRL] = 0x34, +}; + +static struct jr2_miim_dev miim[JR2_MIIM_BUS_COUNT]; +static int miim_count = -1; + +static int mscc_miim_wait_ready(struct jr2_miim_dev *miim) +{ + unsigned long deadline; + u32 val; + + deadline = timer_get_us() + 250000; + + do { + val = readl(miim->regs + GCB_MIIM_MII_STATUS); + } while (timer_get_us() <= deadline && (val & GCB_MIIM_STAT_BUSY)); + + if (val & GCB_MIIM_STAT_BUSY) + return -ETIMEDOUT; + + return 0; +} + +static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg) +{ + struct jr2_miim_dev *miim = (struct jr2_miim_dev *)bus->priv; + u32 val; + int ret; + + ret = mscc_miim_wait_ready(miim); + if (ret) + goto out; + + writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) | + GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ, + miim->regs + GCB_MIIM_MII_CMD); + + ret = mscc_miim_wait_ready(miim); + if (ret) + goto out; + + val = readl(miim->regs + GCB_MIIM_DATA); + if (val & GCB_MIIM_DATA_ERROR) { + ret = -EIO; + goto out; + } + + ret = val & 0xFFFF; + out: + return ret; +} + +static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg, + u16 val) +{ + struct jr2_miim_dev *miim = (struct jr2_miim_dev *)bus->priv; + int ret; + + ret = mscc_miim_wait_ready(miim); + if (ret < 0) + goto out; + + writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) | + GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) | + GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD); + + out: + return ret; +} + +static struct mii_dev *jr2_mdiobus_init(phys_addr_t miim_base, + unsigned long miim_size) +{ + struct mii_dev *bus; + + bus = mdio_alloc(); + if (!bus) + return NULL; + + ++miim_count; + sprintf(bus->name, "miim-bus%d", miim_count); + + miim[miim_count].regs = ioremap(miim_base, miim_size); + miim[miim_count].miim_base = miim_base; + miim[miim_count].miim_size = miim_size; + bus->priv = &miim[miim_count]; + bus->read = mscc_miim_read; + bus->write = mscc_miim_write; + + if (mdio_register(bus)) + return NULL; + + miim[miim_count].bus = bus; + return bus; +} + +static void jr2_cpu_capture_setup(struct jr2_private *priv) +{ + /* ASM: No preamble and IFH prefix on CPU injected frames */ + writel(ASM_CFG_PORT_NO_PREAMBLE_ENA | + ASM_CFG_PORT_INJ_FORMAT_CFG(1), + priv->regs[ASM] + ASM_CFG_PORT(CPU_PORT)); + + /* Set Manual injection via DEVCPU_QS registers for CPU queue 0 */ + writel(0x5, priv->regs[QS] + QS_INJ_GRP_CFG(0)); + + /* Set Manual extraction via DEVCPU_QS registers for CPU queue 0 */ + writel(0x7, priv->regs[QS] + QS_XTR_GRP_CFG(0)); + + /* Enable CPU port for any frame transfer */ + setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(CPU_PORT), + QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA); + + /* Send a copy to CPU when found as forwarding entry */ + setbits_le32(priv->regs[ANA_L2] + ANA_L2_COMMON_FWD_CFG, + ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA); +} + +static void jr2_port_init(struct jr2_private *priv, int port) +{ + void __iomem *regs = priv->regs[port]; + + /* Enable PCS */ + writel(DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA, + regs + DEV_PCS1G_CFG_PCS1G_CFG); + + /* Disable Signal Detect */ + writel(0, regs + DEV_PCS1G_CFG_PCS1G_SD); + + /* Enable MAC RX and TX */ + writel(DEV_MAC_CFG_MAC_ENA_RX_ENA | + DEV_MAC_CFG_MAC_ENA_TX_ENA, + regs + DEV_MAC_CFG_MAC_ENA); + + /* Clear sgmii_mode_ena */ + writel(0, regs + DEV_PCS1G_CFG_PCS1G_MODE); + + /* + * Clear sw_resolve_ena(bit 0) and set adv_ability to + * something meaningful just in case + */ + writel(DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(0x20), + regs + DEV_PCS1G_CFG_PCS1G_ANEG); + + /* Set MAC IFG Gaps */ + writel(DEV_MAC_CFG_MAC_IFG_TX_IFG(4) | + DEV_MAC_CFG_MAC_IFG_RX_IFG1(5) | + DEV_MAC_CFG_MAC_IFG_RX_IFG2(1), + regs + DEV_MAC_CFG_MAC_IFG); + + /* Set link speed and release all resets */ + writel(DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(2), + regs + DEV_DEV_CFG_DEV_RST_CTRL); + + /* Make VLAN aware for CPU traffic */ + writel(ANA_CL_PORT_VLAN_CFG_AWARE_ENA | + ANA_CL_PORT_VLAN_CFG_POP_CNT(1) | + MAC_VID, + priv->regs[ANA_CL] + ANA_CL_PORT_VLAN_CFG(port)); + + /* Enable CPU port for any frame transfer */ + setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(port), + QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA); +} + +static void serdes6g_write(void __iomem *base, u32 addr) +{ + u32 data; + + writel(HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT | + HSIO_MCB_SERDES6G_CFG_ADDR(addr), + base + HSIO_MCB_SERDES6G_CFG); + + do { + data = readl(base + HSIO_MCB_SERDES6G_CFG); + } while (data & HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT); +} + +static void serdes6g_setup(void __iomem *base, uint32_t addr, + phy_interface_t interface) +{ + u32 ib_if_mode = 0; + u32 ib_qrate = 0; + u32 ib_cal_ena = 0; + u32 ib1_tsdet = 0; + u32 ob_lev = 0; + u32 ob_ena_cas = 0; + u32 ob_ena1v_mode = 0; + u32 des_bw_ana = 0; + u32 pll_fsm_ctrl_data = 0; + + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: + ib_if_mode = 1; + ib_qrate = 1; + ib_cal_ena = 1; + ib1_tsdet = 3; + ob_lev = 48; + ob_ena_cas = 2; + ob_ena1v_mode = 1; + des_bw_ana = 3; + pll_fsm_ctrl_data = 60; + break; + case PHY_INTERFACE_MODE_QSGMII: + ib_if_mode = 3; + ib1_tsdet = 16; + ob_lev = 24; + des_bw_ana = 5; + pll_fsm_ctrl_data = 120; + break; + default: + pr_err("Interface not supported\n"); + return; + } + + if (interface == PHY_INTERFACE_MODE_QSGMII) + writel(0xfff, base + HSIO_HW_CFGSTAT_HW_CFG); + + writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(3), + base + HSIO_ANA_SERDES6G_COMMON_CFG); + writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(120) | + HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3), + base + HSIO_ANA_SERDES6G_PLL_CFG); + writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA | + HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA | + HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA | + HSIO_ANA_SERDES6G_IB_CFG_CONCUR | + HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) | + HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) | + HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) | + HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) | + HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) | + HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL | + HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1), + base + HSIO_ANA_SERDES6G_IB_CFG); + writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET | + HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP | + HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID | + HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP | + HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) | + HSIO_ANA_SERDES6G_IB_CFG1_TSDET(3) | + HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8), + base + HSIO_ANA_SERDES6G_IB_CFG1); + writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST, + base + HSIO_DIG_SERDES6G_MISC_CFG); + + serdes6g_write(base, addr); + + writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA | + HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA | + HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA | + HSIO_ANA_SERDES6G_IB_CFG_CONCUR | + HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) | + HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) | + HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) | + HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) | + HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) | + HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL | + HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1), + base + HSIO_ANA_SERDES6G_IB_CFG); + writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET | + HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP | + HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID | + HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP | + HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) | + HSIO_ANA_SERDES6G_IB_CFG1_TSDET(16) | + HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8), + base + HSIO_ANA_SERDES6G_IB_CFG1); + + writel(0x0, base + HSIO_ANA_SERDES6G_SER_CFG); + writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(ib_if_mode) | + HSIO_ANA_SERDES6G_COMMON_CFG_QRATE(ib_qrate) | + HSIO_ANA_SERDES6G_COMMON_CFG_ENA_LANE | + HSIO_ANA_SERDES6G_COMMON_CFG_SYS_RST, + base + HSIO_ANA_SERDES6G_COMMON_CFG); + writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST, + base + HSIO_DIG_SERDES6G_MISC_CFG); + + writel(HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(1) | + HSIO_ANA_SERDES6G_OB_CFG_SR(7) | + HSIO_ANA_SERDES6G_OB_CFG_SR_H | + HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(ob_ena1v_mode) | + HSIO_ANA_SERDES6G_OB_CFG_POL, base + HSIO_ANA_SERDES6G_OB_CFG); + writel(HSIO_ANA_SERDES6G_OB_CFG1_LEV(ob_lev) | + HSIO_ANA_SERDES6G_OB_CFG1_ENA_CAS(ob_ena_cas), + base + HSIO_ANA_SERDES6G_OB_CFG1); + + writel(HSIO_ANA_SERDES6G_DES_CFG_BW_ANA(des_bw_ana) | + HSIO_ANA_SERDES6G_DES_CFG_BW_HYST(5) | + HSIO_ANA_SERDES6G_DES_CFG_MBTR_CTRL(2) | + HSIO_ANA_SERDES6G_DES_CFG_PHS_CTRL(6), + base + HSIO_ANA_SERDES6G_DES_CFG); + writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) | + HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3), + base + HSIO_ANA_SERDES6G_PLL_CFG); + + serdes6g_write(base, addr); + + /* set pll_fsm_ena = 1 */ + writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_ENA | + HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) | + HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3), + base + HSIO_ANA_SERDES6G_PLL_CFG); + + serdes6g_write(base, addr); + + /* wait 20ms for pll bringup */ + mdelay(20); + + /* start IB calibration by setting ib_cal_ena and clearing lane_rst */ + writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA | + HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA | + HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA | + HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(ib_cal_ena) | + HSIO_ANA_SERDES6G_IB_CFG_CONCUR | + HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) | + HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) | + HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) | + HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) | + HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) | + HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL | + HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1), + base + HSIO_ANA_SERDES6G_IB_CFG); + writel(0x0, base + HSIO_DIG_SERDES6G_MISC_CFG); + + serdes6g_write(base, addr); + + /* wait 60 for calibration */ + mdelay(60); + + /* set ib_tsdet and ib_reg_pat_sel_offset back to correct values */ + writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA | + HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA | + HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA | + HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(ib_cal_ena) | + HSIO_ANA_SERDES6G_IB_CFG_CONCUR | + HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) | + HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) | + HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) | + HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) | + HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) | + HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL | + HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1), + base + HSIO_ANA_SERDES6G_IB_CFG); + writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET | + HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP | + HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID | + HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP | + HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) | + HSIO_ANA_SERDES6G_IB_CFG1_TSDET(ib1_tsdet) | + HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8), + base + HSIO_ANA_SERDES6G_IB_CFG1); + + serdes6g_write(base, addr); +} + +static void serdes1g_write(void __iomem *base, u32 addr) +{ + u32 data; + + writel(HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT | + HSIO_MCB_SERDES1G_CFG_ADDR(addr), + base + HSIO_MCB_SERDES1G_CFG); + + do { + data = readl(base + HSIO_MCB_SERDES1G_CFG); + } while (data & HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT); +} + +static void serdes1g_setup(void __iomem *base, uint32_t addr, + phy_interface_t interface) +{ + writel(0x0, base + HSIO_ANA_SERDES1G_SER_CFG); + writel(0x0, base + HSIO_DIG_SERDES1G_TP_CFG); + writel(0x0, base + HSIO_DIG_SERDES1G_DFT_CFG0); + writel(HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(1) | + HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(4) | + HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(2) | + HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(12) | + HSIO_ANA_SERDES1G_OB_CFG_SLP(3), + base + HSIO_ANA_SERDES1G_OB_CFG); + writel(HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(13) | + HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(2) | + HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP | + HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV | + HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM | + HSIO_ANA_SERDES1G_IB_CFG_DET_LEV(3) | + HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(1), + base + HSIO_ANA_SERDES1G_IB_CFG); + writel(HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(7) | + HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(6) | + HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(2) | + HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(6), + base + HSIO_ANA_SERDES1G_DES_CFG); + writel(HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST, + base + HSIO_DIG_SERDES1G_MISC_CFG); + writel(HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA | + HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(0xc8) | + HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2, + base + HSIO_ANA_SERDES1G_PLL_CFG); + writel(HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE | + HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE | + HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST, + base + HSIO_ANA_SERDES1G_COMMON_CFG); + + serdes1g_write(base, addr); + + setbits_le32(base + HSIO_ANA_SERDES1G_COMMON_CFG, + HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST); + + serdes1g_write(base, addr); + + clrbits_le32(base + HSIO_DIG_SERDES1G_MISC_CFG, + HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST); + + serdes1g_write(base, addr); +} + +static int ram_init(u32 val, void __iomem *addr) +{ + writel(val, addr); + + if (wait_for_bit_le32(addr, BIT(1), false, 2000, false)) { + printf("Timeout in memory reset, reg = 0x%08x\n", val); + return 1; + } + + return 0; +} + +static int jr2_switch_init(struct jr2_private *priv) +{ + /* Initialize memories */ + ram_init(0x3, priv->regs[QSYS] + QSYS_RAM_CTRL_RAM_INIT); + ram_init(0x3, priv->regs[ASM] + ASM_RAM_CTRL_RAM_INIT); + ram_init(0x3, priv->regs[ANA_AC] + ANA_AC_RAM_CTRL_RAM_INIT); + ram_init(0x3, priv->regs[REW] + REW_RAM_CTRL_RAM_INIT); + + /* Reset counters */ + writel(0x1, priv->regs[ANA_AC] + ANA_AC_STAT_GLOBAL_CFG_PORT_RESET); + writel(0x1, priv->regs[ASM] + ASM_CFG_STAT_CFG); + + /* Enable switch-core and queue system */ + writel(0x1, priv->regs[QSYS] + QSYS_SYSTEM_RESET_CFG); + + return 0; +} + +static void jr2_switch_config(struct jr2_private *priv) +{ + writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(0)); + writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(1)); + writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(2)); + writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(3)); + + writel(readl(priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL) | + QSYS_CALCFG_CAL_CTRL_CAL_MODE(8), + priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL); +} + +static int jr2_initialize(struct jr2_private *priv) +{ + int ret, i; + + /* Initialize switch memories, enable core */ + ret = jr2_switch_init(priv); + if (ret) + return ret; + + jr2_switch_config(priv); + + for (i = 0; i < MAX_PORT; i++) + jr2_port_init(priv, i); + + jr2_cpu_capture_setup(priv); + + return 0; +} + +static inline int jr2_vlant_wait_for_completion(struct jr2_private *priv) +{ + if (wait_for_bit_le32(priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL, + LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT, + false, 2000, false)) + return -ETIMEDOUT; + + return 0; +} + +static int jr2_mac_table_add(struct jr2_private *priv, + const unsigned char mac[ETH_ALEN], int pgid) +{ + u32 macl = 0, mach = 0; + + /* + * Set the MAC address to handle and the vlan associated in a format + * understood by the hardware. + */ + mach |= MAC_VID << 16; + mach |= ((u32)mac[0]) << 8; + mach |= ((u32)mac[1]) << 0; + macl |= ((u32)mac[2]) << 24; + macl |= ((u32)mac[3]) << 16; + macl |= ((u32)mac[4]) << 8; + macl |= ((u32)mac[5]) << 0; + + writel(mach, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG0); + writel(macl, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG1); + + writel(LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(pgid) | + LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(0x3) | + LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY | + LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(0) | + LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD | + LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED, + priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG2); + + writel(LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT, + priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL); + + return jr2_vlant_wait_for_completion(priv); +} + +static int jr2_write_hwaddr(struct udevice *dev) +{ + struct jr2_private *priv = dev_get_priv(dev); + struct eth_pdata *pdata = dev_get_platdata(dev); + + return jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST); +} + +static void serdes_setup(struct jr2_private *priv) +{ + size_t mask; + int i = 0; + + for (i = 0; i < MAX_PORT; ++i) { + if (!priv->ports[i].bus || priv->ports[i].serdes_index == 0xff) + continue; + + mask = BIT(priv->ports[i].serdes_index); + if (priv->ports[i].serdes_index < SERDES1G_MAX) { + serdes1g_setup(priv->regs[HSIO], mask, + priv->ports[i].phy_mode); + } else { + mask >>= SERDES6G(0); + serdes6g_setup(priv->regs[HSIO], mask, + priv->ports[i].phy_mode); + } + } +} + +static int jr2_start(struct udevice *dev) +{ + struct jr2_private *priv = dev_get_priv(dev); + struct eth_pdata *pdata = dev_get_platdata(dev); + const unsigned char mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, + 0xff }; + int ret; + + ret = jr2_initialize(priv); + if (ret) + return ret; + + /* Set MAC address tables entries for CPU redirection */ + ret = jr2_mac_table_add(priv, mac, PGID_BROADCAST); + if (ret) + return ret; + + ret = jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST); + if (ret) + return ret; + + serdes_setup(priv); + + return 0; +} + +static void jr2_stop(struct udevice *dev) +{ +} + +static int jr2_send(struct udevice *dev, void *packet, int length) +{ + struct jr2_private *priv = dev_get_priv(dev); + u32 ifh[IFH_LEN]; + u32 *buf = packet; + + memset(ifh, '\0', IFH_LEN); + + /* Set DST PORT_MASK */ + ifh[0] = htonl(0); + ifh[1] = htonl(0x1FFFFF); + ifh[2] = htonl(~0); + /* Set DST_MODE to INJECT and UPDATE_FCS */ + ifh[5] = htonl(0x4c0); + + return mscc_send(priv->regs[QS], jr2_regs_qs, + ifh, IFH_LEN, buf, length); +} + +static int jr2_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct jr2_private *priv = dev_get_priv(dev); + u32 *rxbuf = (u32 *)net_rx_packets[0]; + int byte_cnt = 0; + + byte_cnt = mscc_recv(priv->regs[QS], jr2_regs_qs, rxbuf, IFH_LEN, + false); + + *packetp = net_rx_packets[0]; + + return byte_cnt; +} + +static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size) +{ + int i = 0; + + for (i = 0; i < JR2_MIIM_BUS_COUNT; ++i) + if (miim[i].miim_base == base && miim[i].miim_size == size) + return miim[i].bus; + + return NULL; +} + +static void add_port_entry(struct jr2_private *priv, size_t index, + size_t phy_addr, struct mii_dev *bus, + u8 serdes_index, u8 phy_mode) +{ + priv->ports[index].phy_addr = phy_addr; + priv->ports[index].bus = bus; + priv->ports[index].serdes_index = serdes_index; + priv->ports[index].phy_mode = phy_mode; +} + +static int jr2_probe(struct udevice *dev) +{ + struct jr2_private *priv = dev_get_priv(dev); + int i; + int ret; + struct resource res; + fdt32_t faddr; + phys_addr_t addr_base; + unsigned long addr_size; + ofnode eth_node, node, mdio_node; + size_t phy_addr; + struct mii_dev *bus; + struct ofnode_phandle_args phandle; + struct phy_device *phy; + + if (!priv) + return -EINVAL; + + /* Get registers and map them to the private structure */ + for (i = 0; i < ARRAY_SIZE(regs_names); i++) { + priv->regs[i] = dev_remap_addr_name(dev, regs_names[i]); + if (!priv->regs[i]) { + debug + ("Error can't get regs base addresses for %s\n", + regs_names[i]); + return -ENOMEM; + } + } + + /* Initialize miim buses */ + memset(&miim, 0x0, sizeof(struct jr2_miim_dev) * JR2_MIIM_BUS_COUNT); + + /* iterate all the ports and find out on which bus they are */ + i = 0; + eth_node = dev_read_first_subnode(dev); + for (node = ofnode_first_subnode(eth_node); + ofnode_valid(node); + node = ofnode_next_subnode(node)) { + if (ofnode_read_resource(node, 0, &res)) + return -ENOMEM; + i = res.start; + + ret = ofnode_parse_phandle_with_args(node, "phy-handle", NULL, + 0, 0, &phandle); + if (ret) + continue; + + /* Get phy address on mdio bus */ + if (ofnode_read_resource(phandle.node, 0, &res)) + return -ENOMEM; + phy_addr = res.start; + + /* Get mdio node */ + mdio_node = ofnode_get_parent(phandle.node); + + if (ofnode_read_resource(mdio_node, 0, &res)) + return -ENOMEM; + faddr = cpu_to_fdt32(res.start); + + addr_base = ofnode_translate_address(mdio_node, &faddr); + addr_size = res.end - res.start; + + /* If the bus is new then create a new bus */ + if (!get_mdiobus(addr_base, addr_size)) + priv->bus[miim_count] = + jr2_mdiobus_init(addr_base, addr_size); + + /* Connect mdio bus with the port */ + bus = get_mdiobus(addr_base, addr_size); + + /* Get serdes info */ + ret = ofnode_parse_phandle_with_args(node, "phys", NULL, + 3, 0, &phandle); + if (ret) + return -ENOMEM; + + add_port_entry(priv, i, phy_addr, bus, phandle.args[1], + phandle.args[2]); + } + + for (i = 0; i < MAX_PORT; i++) { + if (!priv->ports[i].bus) + continue; + + phy = phy_connect(priv->ports[i].bus, + priv->ports[i].phy_addr, dev, + PHY_INTERFACE_MODE_NONE); + if (phy) + board_phy_config(phy); + } + + return 0; +} + +static int jr2_remove(struct udevice *dev) +{ + struct jr2_private *priv = dev_get_priv(dev); + int i; + + for (i = 0; i < JR2_MIIM_BUS_COUNT; i++) { + mdio_unregister(priv->bus[i]); + mdio_free(priv->bus[i]); + } + + return 0; +} + +static const struct eth_ops jr2_ops = { + .start = jr2_start, + .stop = jr2_stop, + .send = jr2_send, + .recv = jr2_recv, + .write_hwaddr = jr2_write_hwaddr, +}; + +static const struct udevice_id mscc_jr2_ids[] = { + {.compatible = "mscc,vsc7454-switch" }, + { /* Sentinel */ } +}; + +U_BOOT_DRIVER(jr2) = { + .name = "jr2-switch", + .id = UCLASS_ETH, + .of_match = mscc_jr2_ids, + .probe = jr2_probe, + .remove = jr2_remove, + .ops = &jr2_ops, + .priv_auto_alloc_size = sizeof(struct jr2_private), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), +}; diff --git a/include/configs/vcoreiii.h b/include/configs/vcoreiii.h index 2840c7b..aeef58d 100644 --- a/include/configs/vcoreiii.h +++ b/include/configs/vcoreiii.h @@ -10,7 +10,7 @@
/* Onboard devices */
-#define CONFIG_SYS_MALLOC_LEN 0x100000 +#define CONFIG_SYS_MALLOC_LEN 0x1F0000 #define CONFIG_SYS_LOAD_ADDR 0x00100000 #define CONFIG_SYS_INIT_SP_OFFSET 0x400000

Am 30.03.19 um 11:17 schrieb Horatiu Vultur:
Add network driver for Microsemi Ethernet switch. It is present on Jaguar2 SoCs.
Signed-off-by: Horatiu Vultur horatiu.vultur@microchip.com
drivers/net/mscc_eswitch/Kconfig | 7 + drivers/net/mscc_eswitch/Makefile | 1 + drivers/net/mscc_eswitch/jr2_switch.c | 1075 +++++++++++++++++++++++++++++++++ include/configs/vcoreiii.h | 2 +- 4 files changed, 1084 insertions(+), 1 deletion(-) create mode 100644 drivers/net/mscc_eswitch/jr2_switch.c
Reviewed-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com
nits below
diff --git a/drivers/net/mscc_eswitch/Kconfig b/drivers/net/mscc_eswitch/Kconfig index 88e5a97..3f9d14b 100644 --- a/drivers/net/mscc_eswitch/Kconfig +++ b/drivers/net/mscc_eswitch/Kconfig @@ -15,3 +15,10 @@ config MSCC_LUTON_SWITCH select PHYLIB help This driver supports the Luton network switch device.
+config MSCC_JR2_SWITCH
- bool "Jaguar2 switch driver"
- depends on DM_ETH && ARCH_MSCC
- select PHYLIB
- help
This driver supports the Jaguar2 network switch device.
diff --git a/drivers/net/mscc_eswitch/Makefile b/drivers/net/mscc_eswitch/Makefile index 751a839..0a1b863 100644 --- a/drivers/net/mscc_eswitch/Makefile +++ b/drivers/net/mscc_eswitch/Makefile @@ -1,3 +1,4 @@
obj-$(CONFIG_MSCC_OCELOT_SWITCH) += ocelot_switch.o mscc_miim.o mscc_xfer.o mscc_mac_table.o obj-$(CONFIG_MSCC_LUTON_SWITCH) += luton_switch.o mscc_miim.o mscc_xfer.o mscc_mac_table.o +obj-$(CONFIG_MSCC_JR2_SWITCH) += jr2_switch.o mscc_xfer.o diff --git a/drivers/net/mscc_eswitch/jr2_switch.c b/drivers/net/mscc_eswitch/jr2_switch.c new file mode 100644 index 0000000..d4a2498 --- /dev/null +++ b/drivers/net/mscc_eswitch/jr2_switch.c @@ -0,0 +1,1075 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/*
- Copyright (c) 2018 Microsemi Corporation
- */
+#include <common.h> +#include <config.h> +#include <dm.h> +#include <dm/of_access.h> +#include <dm/of_addr.h> +#include <fdt_support.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <miiphy.h> +#include <net.h> +#include <wait_bit.h>
+#include <dt-bindings/mscc/jr2_data.h> +#include "mscc_xfer.h"
+#define GCB_MIIM_MII_STATUS 0x0 +#define GCB_MIIM_STAT_BUSY BIT(3) +#define GCB_MIIM_MII_CMD 0x8 +#define GCB_MIIM_MII_CMD_SCAN BIT(0) +#define GCB_MIIM_MII_CMD_OPR_WRITE BIT(1) +#define GCB_MIIM_MII_CMD_OPR_READ BIT(2) +#define GCB_MIIM_MII_CMD_SINGLE_SCAN BIT(3) +#define GCB_MIIM_MII_CMD_WRDATA(x) ((x) << 4) +#define GCB_MIIM_MII_CMD_REGAD(x) ((x) << 20) +#define GCB_MIIM_MII_CMD_PHYAD(x) ((x) << 25) +#define GCB_MIIM_MII_CMD_VLD BIT(31) +#define GCB_MIIM_DATA 0xC +#define GCB_MIIM_DATA_ERROR (0x3 << 16)
+#define ANA_AC_RAM_CTRL_RAM_INIT 0x94358 +#define ANA_AC_STAT_GLOBAL_CFG_PORT_RESET 0x94370
+#define ANA_CL_PORT_VLAN_CFG(x) (0x24018 + 0xc8 * (x)) +#define ANA_CL_PORT_VLAN_CFG_AWARE_ENA BIT(19) +#define ANA_CL_PORT_VLAN_CFG_POP_CNT(x) ((x) << 17)
+#define ANA_L2_COMMON_FWD_CFG 0x8a2a8 +#define ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA BIT(6)
+#define ASM_CFG_STAT_CFG 0x3508 +#define ASM_CFG_PORT(x) (0x36c4 + 0x4 * (x)) +#define ASM_CFG_PORT_NO_PREAMBLE_ENA BIT(8) +#define ASM_CFG_PORT_INJ_FORMAT_CFG(x) ((x) << 1) +#define ASM_RAM_CTRL_RAM_INIT 0x39b8
+#define DEV_DEV_CFG_DEV_RST_CTRL 0x0 +#define DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(x) ((x) << 20) +#define DEV_MAC_CFG_MAC_ENA 0x1c +#define DEV_MAC_CFG_MAC_ENA_RX_ENA BIT(4) +#define DEV_MAC_CFG_MAC_ENA_TX_ENA BIT(0) +#define DEV_MAC_CFG_MAC_IFG 0x34 +#define DEV_MAC_CFG_MAC_IFG_TX_IFG(x) ((x) << 8) +#define DEV_MAC_CFG_MAC_IFG_RX_IFG2(x) ((x) << 4) +#define DEV_MAC_CFG_MAC_IFG_RX_IFG1(x) (x) +#define DEV_PCS1G_CFG_PCS1G_CFG 0x40 +#define DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA BIT(0) +#define DEV_PCS1G_CFG_PCS1G_MODE 0x44 +#define DEV_PCS1G_CFG_PCS1G_SD 0x48 +#define DEV_PCS1G_CFG_PCS1G_ANEG 0x4c +#define DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(x) ((x) << 16)
+#define DSM_RAM_CTRL_RAM_INIT 0x8
+#define HSIO_ANA_SERDES1G_DES_CFG 0xac +#define HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(x) ((x) << 1) +#define HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(x) ((x) << 5) +#define HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(x) ((x) << 8) +#define HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(x) ((x) << 13) +#define HSIO_ANA_SERDES1G_IB_CFG 0xb0 +#define HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(x) (x) +#define HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(x) ((x) << 6) +#define HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP BIT(9) +#define HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV BIT(11) +#define HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM BIT(13) +#define HSIO_ANA_SERDES1G_IB_CFG_DET_LEV(x) ((x) << 19) +#define HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(x) ((x) << 24) +#define HSIO_ANA_SERDES1G_OB_CFG 0xb4 +#define HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(x) (x) +#define HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(x) ((x) << 4) +#define HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(x) ((x) << 10) +#define HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(x) ((x) << 13) +#define HSIO_ANA_SERDES1G_OB_CFG_SLP(x) ((x) << 17) +#define HSIO_ANA_SERDES1G_SER_CFG 0xb8 +#define HSIO_ANA_SERDES1G_COMMON_CFG 0xbc +#define HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE BIT(0) +#define HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE BIT(18) +#define HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST BIT(31) +#define HSIO_ANA_SERDES1G_PLL_CFG 0xc0 +#define HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA BIT(7) +#define HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(x) ((x) << 8) +#define HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2 BIT(21) +#define HSIO_DIG_SERDES1G_DFT_CFG0 0xc8 +#define HSIO_DIG_SERDES1G_TP_CFG 0xd4 +#define HSIO_DIG_SERDES1G_MISC_CFG 0xdc +#define HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST BIT(0) +#define HSIO_MCB_SERDES1G_CFG 0xe8 +#define HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT BIT(31) +#define HSIO_MCB_SERDES1G_CFG_ADDR(x) (x)
+#define HSIO_ANA_SERDES6G_DES_CFG 0x11c +#define HSIO_ANA_SERDES6G_DES_CFG_SWAP_ANA BIT(0) +#define HSIO_ANA_SERDES6G_DES_CFG_BW_ANA(x) ((x) << 1) +#define HSIO_ANA_SERDES6G_DES_CFG_SWAP_HYST BIT(4) +#define HSIO_ANA_SERDES6G_DES_CFG_BW_HYST(x) ((x) << 5) +#define HSIO_ANA_SERDES6G_DES_CFG_CPMD_SEL(x) ((x) << 8) +#define HSIO_ANA_SERDES6G_DES_CFG_MBTR_CTRL(x) ((x) << 10) +#define HSIO_ANA_SERDES6G_DES_CFG_PHS_CTRL(x) ((x) << 13) +#define HSIO_ANA_SERDES6G_IB_CFG 0x120 +#define HSIO_ANA_SERDES6G_IB_CFG_REG_ENA BIT(0) +#define HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA BIT(1) +#define HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA BIT(2) +#define HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(x) ((x) << 3) +#define HSIO_ANA_SERDES6G_IB_CFG_CONCUR BIT(4) +#define HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA BIT(5) +#define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(x) ((x) << 7) +#define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(x) ((x) << 9) +#define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(x) ((x) << 11) +#define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(x) ((x) << 13) +#define HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(x) ((x) << 15) +#define HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(x) ((x) << 18) +#define HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(x) ((x) << 20) +#define HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(x) ((x) << 24) +#define HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL BIT(28) +#define HSIO_ANA_SERDES6G_IB_CFG_SOFSI(x) ((x) << 29) +#define HSIO_ANA_SERDES6G_IB_CFG1 0x124 +#define HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET BIT(4) +#define HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP BIT(5) +#define HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID BIT(6) +#define HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP BIT(7) +#define HSIO_ANA_SERDES6G_IB_CFG1_SCALY(x) ((x) << 8) +#define HSIO_ANA_SERDES6G_IB_CFG1_TSDET(x) ((x) << 12) +#define HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(x) ((x) << 17) +#define HSIO_ANA_SERDES6G_IB_CFG2 0x128 +#define HSIO_ANA_SERDES6G_IB_CFG2_UREG(x) (x) +#define HSIO_ANA_SERDES6G_IB_CFG2_UMAX(x) ((x) << 3) +#define HSIO_ANA_SERDES6G_IB_CFG2_TCALV(x) ((x) << 5) +#define HSIO_ANA_SERDES6G_IB_CFG2_OCALS(x) ((x) << 10) +#define HSIO_ANA_SERDES6G_IB_CFG2_OINFS(x) ((x) << 16) +#define HSIO_ANA_SERDES6G_IB_CFG2_OINFI(x) ((x) << 22) +#define HSIO_ANA_SERDES6G_IB_CFG2_TINFV(x) ((x) << 27) +#define HSIO_ANA_SERDES6G_IB_CFG3 0x12c +#define HSIO_ANA_SERDES6G_IB_CFG3_INI_OFFSET(x) (x) +#define HSIO_ANA_SERDES6G_IB_CFG3_INI_LP(x) ((x) << 6) +#define HSIO_ANA_SERDES6G_IB_CFG3_INI_MID(x) ((x) << 12) +#define HSIO_ANA_SERDES6G_IB_CFG3_INI_HP(x) ((x) << 18) +#define HSIO_ANA_SERDES6G_IB_CFG4 0x130 +#define HSIO_ANA_SERDES6G_IB_CFG4_MAX_OFFSET(x) (x) +#define HSIO_ANA_SERDES6G_IB_CFG4_MAX_LP(x) ((x) << 6) +#define HSIO_ANA_SERDES6G_IB_CFG4_MAX_MID(x) ((x) << 12) +#define HSIO_ANA_SERDES6G_IB_CFG4_MAX_HP(x) ((x) << 18) +#define HSIO_ANA_SERDES6G_IB_CFG5 0x134 +#define HSIO_ANA_SERDES6G_IB_CFG4_MIN_OFFSET(x) (x) +#define HSIO_ANA_SERDES6G_IB_CFG4_MIN_LP(x) ((x) << 6) +#define HSIO_ANA_SERDES6G_IB_CFG4_MIN_MID(x) ((x) << 12) +#define HSIO_ANA_SERDES6G_IB_CFG4_MIN_HP(x) ((x) << 18) +#define HSIO_ANA_SERDES6G_OB_CFG 0x138 +#define HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(x) (x) +#define HSIO_ANA_SERDES6G_OB_CFG_SR(x) ((x) << 4) +#define HSIO_ANA_SERDES6G_OB_CFG_SR_H BIT(8) +#define HSIO_ANA_SERDES6G_OB_CFG_SEL_RCTRL BIT(9) +#define HSIO_ANA_SERDES6G_OB_CFG_R_COR BIT(10) +#define HSIO_ANA_SERDES6G_OB_CFG_POST1(x) ((x) << 11) +#define HSIO_ANA_SERDES6G_OB_CFG_R_ADJ_PDR BIT(16) +#define HSIO_ANA_SERDES6G_OB_CFG_R_ADJ_MUX BIT(17) +#define HSIO_ANA_SERDES6G_OB_CFG_PREC(x) ((x) << 18) +#define HSIO_ANA_SERDES6G_OB_CFG_POST0(x) ((x) << 23) +#define HSIO_ANA_SERDES6G_OB_CFG_POL BIT(29) +#define HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(x) ((x) << 30) +#define HSIO_ANA_SERDES6G_OB_CFG_IDLE BIT(31) +#define HSIO_ANA_SERDES6G_OB_CFG1 0x13c +#define HSIO_ANA_SERDES6G_OB_CFG1_LEV(x) (x) +#define HSIO_ANA_SERDES6G_OB_CFG1_ENA_CAS(x) ((x) << 6) +#define HSIO_ANA_SERDES6G_SER_CFG 0x140 +#define HSIO_ANA_SERDES6G_COMMON_CFG 0x144 +#define HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(x) (x) +#define HSIO_ANA_SERDES6G_COMMON_CFG_QRATE(x) (x << 2) +#define HSIO_ANA_SERDES6G_COMMON_CFG_ENA_LANE BIT(14) +#define HSIO_ANA_SERDES6G_COMMON_CFG_SYS_RST BIT(16) +#define HSIO_ANA_SERDES6G_PLL_CFG 0x148 +#define HSIO_ANA_SERDES6G_PLL_CFG_ROT_FRQ BIT(0) +#define HSIO_ANA_SERDES6G_PLL_CFG_ROT_DIR BIT(1) +#define HSIO_ANA_SERDES6G_PLL_CFG_RB_DATA_SEL BIT(2) +#define HSIO_ANA_SERDES6G_PLL_CFG_FSM_OOR_RECAL_ENA BIT(3) +#define HSIO_ANA_SERDES6G_PLL_CFG_FSM_FORCE_SET_ENA BIT(4) +#define HSIO_ANA_SERDES6G_PLL_CFG_FSM_ENA BIT(5) +#define HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(x) ((x) << 6) +#define HSIO_ANA_SERDES6G_PLL_CFG_ENA_ROT BIT(14) +#define HSIO_ANA_SERDES6G_PLL_CFG_DIV4 BIT(15) +#define HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(x) ((x) << 16) +#define HSIO_DIG_SERDES6G_MISC_CFG 0x108 +#define HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST BIT(0) +#define HSIO_MCB_SERDES6G_CFG 0x168 +#define HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT BIT(31) +#define HSIO_MCB_SERDES6G_CFG_ADDR(x) (x) +#define HSIO_HW_CFGSTAT_HW_CFG 0x16c
+#define LRN_COMMON_ACCESS_CTRL 0x0 +#define LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT BIT(0) +#define LRN_COMMON_MAC_ACCESS_CFG0 0x4 +#define LRN_COMMON_MAC_ACCESS_CFG1 0x8 +#define LRN_COMMON_MAC_ACCESS_CFG2 0xc +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(x) (x) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(x) ((x) << 12) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD BIT(15) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED BIT(16) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY BIT(23) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(x) ((x) << 24)
+#define QFWD_SYSTEM_SWITCH_PORT_MODE(x) (0x4 * (x)) +#define QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA BIT(17)
+#define QS_XTR_GRP_CFG(x) (0x0 + 4 * (x)) +#define QS_INJ_GRP_CFG(x) (0x24 + (x) * 4)
+#define QSYS_SYSTEM_RESET_CFG 0xf0 +#define QSYS_CALCFG_CAL_AUTO(x) (0x3d4 + 4 * (x)) +#define QSYS_CALCFG_CAL_CTRL 0x3e8 +#define QSYS_CALCFG_CAL_CTRL_CAL_MODE(x) ((x) << 11) +#define QSYS_RAM_CTRL_RAM_INIT 0x3ec
+#define REW_RAM_CTRL_RAM_INIT 0x53528
+#define VOP_RAM_CTRL_RAM_INIT 0x43638
+#define XTR_VALID_BYTES(x) (4 - ((x) & 3)) +#define MAC_VID 0 +#define CPU_PORT 53 +#define IFH_LEN 7 +#define JR2_BUF_CELL_SZ 60 +#define ETH_ALEN 6 +#define PGID_BROADCAST 510 +#define PGID_UNICAST 511
+static char *regs_names[] = {
- "port0", "port1", "port2", "port3", "port4", "port5", "port6", "port7",
- "port8", "port9", "port10", "port11", "port12", "port13", "port14",
- "port15", "port16", "port17", "port18", "port19", "port20", "port21",
- "port22", "port23", "port24", "port25", "port26", "port27", "port28",
- "port29", "port30", "port31", "port32", "port33", "port34", "port35",
- "port36", "port37", "port38", "port39", "port40", "port41", "port42",
- "port43", "port44", "port45", "port46", "port47",
- "ana_ac", "ana_cl", "ana_l2", "asm", "hsio", "lrn",
- "qfwd", "qs", "qsys", "rew",
+};
this could be made const
+#define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1 +#define MAX_PORT 48
+enum jr2_ctrl_regs {
- ANA_AC = MAX_PORT,
- ANA_CL,
- ANA_L2,
- ASM,
- HSIO,
- LRN,
- QFWD,
- QS,
- QSYS,
- REW,
+};
+#define JR2_MIIM_BUS_COUNT 3
+struct jr2_phy_port_t {
- size_t phy_addr;
- struct mii_dev *bus;
- u8 serdes_index;
- u8 phy_mode;
+};
+struct jr2_private {
- void __iomem *regs[REGS_NAMES_COUNT];
- struct mii_dev *bus[JR2_MIIM_BUS_COUNT];
- struct jr2_phy_port_t ports[MAX_PORT];
+};
+struct jr2_miim_dev {
- void __iomem *regs;
- phys_addr_t miim_base;
- unsigned long miim_size;
- struct mii_dev *bus;
+};
+static const unsigned long jr2_regs_qs[] = {
- [MSCC_QS_XTR_RD] = 0x8,
- [MSCC_QS_XTR_FLUSH] = 0x18,
- [MSCC_QS_XTR_DATA_PRESENT] = 0x1c,
- [MSCC_QS_INJ_WR] = 0x2c,
- [MSCC_QS_INJ_CTRL] = 0x34,
+};
+static struct jr2_miim_dev miim[JR2_MIIM_BUS_COUNT]; +static int miim_count = -1;
+static int mscc_miim_wait_ready(struct jr2_miim_dev *miim) +{
- unsigned long deadline;
- u32 val;
- deadline = timer_get_us() + 250000;
- do {
val = readl(miim->regs + GCB_MIIM_MII_STATUS);
- } while (timer_get_us() <= deadline && (val & GCB_MIIM_STAT_BUSY));
- if (val & GCB_MIIM_STAT_BUSY)
return -ETIMEDOUT;
- return 0;
+}
+static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg) +{
- struct jr2_miim_dev *miim = (struct jr2_miim_dev *)bus->priv;
- u32 val;
- int ret;
- ret = mscc_miim_wait_ready(miim);
- if (ret)
goto out;
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
miim->regs + GCB_MIIM_MII_CMD);
- ret = mscc_miim_wait_ready(miim);
- if (ret)
goto out;
- val = readl(miim->regs + GCB_MIIM_DATA);
- if (val & GCB_MIIM_DATA_ERROR) {
ret = -EIO;
goto out;
- }
- ret = val & 0xFFFF;
- out:
- return ret;
+}
+static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
u16 val)
+{
- struct jr2_miim_dev *miim = (struct jr2_miim_dev *)bus->priv;
- int ret;
- ret = mscc_miim_wait_ready(miim);
- if (ret < 0)
goto out;
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
- out:
- return ret;
+}
+static struct mii_dev *jr2_mdiobus_init(phys_addr_t miim_base,
unsigned long miim_size)
+{
- struct mii_dev *bus;
- bus = mdio_alloc();
- if (!bus)
return NULL;
- ++miim_count;
- sprintf(bus->name, "miim-bus%d", miim_count);
- miim[miim_count].regs = ioremap(miim_base, miim_size);
- miim[miim_count].miim_base = miim_base;
- miim[miim_count].miim_size = miim_size;
- bus->priv = &miim[miim_count];
- bus->read = mscc_miim_read;
- bus->write = mscc_miim_write;
- if (mdio_register(bus))
return NULL;
- miim[miim_count].bus = bus;
- return bus;
+}
+static void jr2_cpu_capture_setup(struct jr2_private *priv) +{
- /* ASM: No preamble and IFH prefix on CPU injected frames */
- writel(ASM_CFG_PORT_NO_PREAMBLE_ENA |
ASM_CFG_PORT_INJ_FORMAT_CFG(1),
priv->regs[ASM] + ASM_CFG_PORT(CPU_PORT));
- /* Set Manual injection via DEVCPU_QS registers for CPU queue 0 */
- writel(0x5, priv->regs[QS] + QS_INJ_GRP_CFG(0));
- /* Set Manual extraction via DEVCPU_QS registers for CPU queue 0 */
- writel(0x7, priv->regs[QS] + QS_XTR_GRP_CFG(0));
- /* Enable CPU port for any frame transfer */
- setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(CPU_PORT),
QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
- /* Send a copy to CPU when found as forwarding entry */
- setbits_le32(priv->regs[ANA_L2] + ANA_L2_COMMON_FWD_CFG,
ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA);
+}
+static void jr2_port_init(struct jr2_private *priv, int port) +{
- void __iomem *regs = priv->regs[port];
- /* Enable PCS */
- writel(DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA,
regs + DEV_PCS1G_CFG_PCS1G_CFG);
- /* Disable Signal Detect */
- writel(0, regs + DEV_PCS1G_CFG_PCS1G_SD);
- /* Enable MAC RX and TX */
- writel(DEV_MAC_CFG_MAC_ENA_RX_ENA |
DEV_MAC_CFG_MAC_ENA_TX_ENA,
regs + DEV_MAC_CFG_MAC_ENA);
- /* Clear sgmii_mode_ena */
- writel(0, regs + DEV_PCS1G_CFG_PCS1G_MODE);
- /*
* Clear sw_resolve_ena(bit 0) and set adv_ability to
* something meaningful just in case
*/
- writel(DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(0x20),
regs + DEV_PCS1G_CFG_PCS1G_ANEG);
- /* Set MAC IFG Gaps */
- writel(DEV_MAC_CFG_MAC_IFG_TX_IFG(4) |
DEV_MAC_CFG_MAC_IFG_RX_IFG1(5) |
DEV_MAC_CFG_MAC_IFG_RX_IFG2(1),
regs + DEV_MAC_CFG_MAC_IFG);
- /* Set link speed and release all resets */
- writel(DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(2),
regs + DEV_DEV_CFG_DEV_RST_CTRL);
- /* Make VLAN aware for CPU traffic */
- writel(ANA_CL_PORT_VLAN_CFG_AWARE_ENA |
ANA_CL_PORT_VLAN_CFG_POP_CNT(1) |
MAC_VID,
priv->regs[ANA_CL] + ANA_CL_PORT_VLAN_CFG(port));
- /* Enable CPU port for any frame transfer */
- setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(port),
QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
+}
+static void serdes6g_write(void __iomem *base, u32 addr) +{
- u32 data;
- writel(HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT |
HSIO_MCB_SERDES6G_CFG_ADDR(addr),
base + HSIO_MCB_SERDES6G_CFG);
- do {
data = readl(base + HSIO_MCB_SERDES6G_CFG);
- } while (data & HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT);
+}
+static void serdes6g_setup(void __iomem *base, uint32_t addr,
phy_interface_t interface)
+{
- u32 ib_if_mode = 0;
- u32 ib_qrate = 0;
- u32 ib_cal_ena = 0;
- u32 ib1_tsdet = 0;
- u32 ob_lev = 0;
- u32 ob_ena_cas = 0;
- u32 ob_ena1v_mode = 0;
- u32 des_bw_ana = 0;
- u32 pll_fsm_ctrl_data = 0;
- switch (interface) {
- case PHY_INTERFACE_MODE_SGMII:
ib_if_mode = 1;
ib_qrate = 1;
ib_cal_ena = 1;
ib1_tsdet = 3;
ob_lev = 48;
ob_ena_cas = 2;
ob_ena1v_mode = 1;
des_bw_ana = 3;
pll_fsm_ctrl_data = 60;
break;
- case PHY_INTERFACE_MODE_QSGMII:
ib_if_mode = 3;
ib1_tsdet = 16;
ob_lev = 24;
des_bw_ana = 5;
pll_fsm_ctrl_data = 120;
break;
- default:
pr_err("Interface not supported\n");
return;
- }
- if (interface == PHY_INTERFACE_MODE_QSGMII)
writel(0xfff, base + HSIO_HW_CFGSTAT_HW_CFG);
- writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(3),
base + HSIO_ANA_SERDES6G_COMMON_CFG);
- writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(120) |
HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
base + HSIO_ANA_SERDES6G_PLL_CFG);
- writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) |
HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
base + HSIO_ANA_SERDES6G_IB_CFG);
- writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
HSIO_ANA_SERDES6G_IB_CFG1_TSDET(3) |
HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
base + HSIO_ANA_SERDES6G_IB_CFG1);
- writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST,
base + HSIO_DIG_SERDES6G_MISC_CFG);
- serdes6g_write(base, addr);
- writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) |
HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
base + HSIO_ANA_SERDES6G_IB_CFG);
- writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
HSIO_ANA_SERDES6G_IB_CFG1_TSDET(16) |
HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
base + HSIO_ANA_SERDES6G_IB_CFG1);
- writel(0x0, base + HSIO_ANA_SERDES6G_SER_CFG);
- writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(ib_if_mode) |
HSIO_ANA_SERDES6G_COMMON_CFG_QRATE(ib_qrate) |
HSIO_ANA_SERDES6G_COMMON_CFG_ENA_LANE |
HSIO_ANA_SERDES6G_COMMON_CFG_SYS_RST,
base + HSIO_ANA_SERDES6G_COMMON_CFG);
- writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST,
base + HSIO_DIG_SERDES6G_MISC_CFG);
- writel(HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(1) |
HSIO_ANA_SERDES6G_OB_CFG_SR(7) |
HSIO_ANA_SERDES6G_OB_CFG_SR_H |
HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(ob_ena1v_mode) |
HSIO_ANA_SERDES6G_OB_CFG_POL, base + HSIO_ANA_SERDES6G_OB_CFG);
- writel(HSIO_ANA_SERDES6G_OB_CFG1_LEV(ob_lev) |
HSIO_ANA_SERDES6G_OB_CFG1_ENA_CAS(ob_ena_cas),
base + HSIO_ANA_SERDES6G_OB_CFG1);
- writel(HSIO_ANA_SERDES6G_DES_CFG_BW_ANA(des_bw_ana) |
HSIO_ANA_SERDES6G_DES_CFG_BW_HYST(5) |
HSIO_ANA_SERDES6G_DES_CFG_MBTR_CTRL(2) |
HSIO_ANA_SERDES6G_DES_CFG_PHS_CTRL(6),
base + HSIO_ANA_SERDES6G_DES_CFG);
- writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) |
HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
base + HSIO_ANA_SERDES6G_PLL_CFG);
- serdes6g_write(base, addr);
- /* set pll_fsm_ena = 1 */
- writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_ENA |
HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) |
HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
base + HSIO_ANA_SERDES6G_PLL_CFG);
- serdes6g_write(base, addr);
- /* wait 20ms for pll bringup */
- mdelay(20);
- /* start IB calibration by setting ib_cal_ena and clearing lane_rst */
- writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(ib_cal_ena) |
HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) |
HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
base + HSIO_ANA_SERDES6G_IB_CFG);
- writel(0x0, base + HSIO_DIG_SERDES6G_MISC_CFG);
- serdes6g_write(base, addr);
- /* wait 60 for calibration */
- mdelay(60);
- /* set ib_tsdet and ib_reg_pat_sel_offset back to correct values */
- writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(ib_cal_ena) |
HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) |
HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
base + HSIO_ANA_SERDES6G_IB_CFG);
- writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
HSIO_ANA_SERDES6G_IB_CFG1_TSDET(ib1_tsdet) |
HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
base + HSIO_ANA_SERDES6G_IB_CFG1);
- serdes6g_write(base, addr);
+}
+static void serdes1g_write(void __iomem *base, u32 addr) +{
- u32 data;
- writel(HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT |
HSIO_MCB_SERDES1G_CFG_ADDR(addr),
base + HSIO_MCB_SERDES1G_CFG);
- do {
data = readl(base + HSIO_MCB_SERDES1G_CFG);
- } while (data & HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT);
+}
+static void serdes1g_setup(void __iomem *base, uint32_t addr,
phy_interface_t interface)
+{
- writel(0x0, base + HSIO_ANA_SERDES1G_SER_CFG);
- writel(0x0, base + HSIO_DIG_SERDES1G_TP_CFG);
- writel(0x0, base + HSIO_DIG_SERDES1G_DFT_CFG0);
- writel(HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(1) |
HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(4) |
HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(2) |
HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(12) |
HSIO_ANA_SERDES1G_OB_CFG_SLP(3),
base + HSIO_ANA_SERDES1G_OB_CFG);
- writel(HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(13) |
HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(2) |
HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP |
HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV |
HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM |
HSIO_ANA_SERDES1G_IB_CFG_DET_LEV(3) |
HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(1),
base + HSIO_ANA_SERDES1G_IB_CFG);
- writel(HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(7) |
HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(6) |
HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(2) |
HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(6),
base + HSIO_ANA_SERDES1G_DES_CFG);
- writel(HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST,
base + HSIO_DIG_SERDES1G_MISC_CFG);
- writel(HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA |
HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(0xc8) |
HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2,
base + HSIO_ANA_SERDES1G_PLL_CFG);
- writel(HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE |
HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE |
HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST,
base + HSIO_ANA_SERDES1G_COMMON_CFG);
- serdes1g_write(base, addr);
- setbits_le32(base + HSIO_ANA_SERDES1G_COMMON_CFG,
HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST);
- serdes1g_write(base, addr);
- clrbits_le32(base + HSIO_DIG_SERDES1G_MISC_CFG,
HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST);
- serdes1g_write(base, addr);
+}
+static int ram_init(u32 val, void __iomem *addr) +{
- writel(val, addr);
- if (wait_for_bit_le32(addr, BIT(1), false, 2000, false)) {
printf("Timeout in memory reset, reg = 0x%08x\n", val);
return 1;
- }
- return 0;
+}
+static int jr2_switch_init(struct jr2_private *priv) +{
- /* Initialize memories */
- ram_init(0x3, priv->regs[QSYS] + QSYS_RAM_CTRL_RAM_INIT);
- ram_init(0x3, priv->regs[ASM] + ASM_RAM_CTRL_RAM_INIT);
- ram_init(0x3, priv->regs[ANA_AC] + ANA_AC_RAM_CTRL_RAM_INIT);
- ram_init(0x3, priv->regs[REW] + REW_RAM_CTRL_RAM_INIT);
- /* Reset counters */
- writel(0x1, priv->regs[ANA_AC] + ANA_AC_STAT_GLOBAL_CFG_PORT_RESET);
- writel(0x1, priv->regs[ASM] + ASM_CFG_STAT_CFG);
- /* Enable switch-core and queue system */
- writel(0x1, priv->regs[QSYS] + QSYS_SYSTEM_RESET_CFG);
- return 0;
+}
+static void jr2_switch_config(struct jr2_private *priv) +{
- writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(0));
- writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(1));
- writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(2));
- writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(3));
- writel(readl(priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL) |
QSYS_CALCFG_CAL_CTRL_CAL_MODE(8),
priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL);
+}
+static int jr2_initialize(struct jr2_private *priv) +{
- int ret, i;
- /* Initialize switch memories, enable core */
- ret = jr2_switch_init(priv);
- if (ret)
return ret;
- jr2_switch_config(priv);
- for (i = 0; i < MAX_PORT; i++)
jr2_port_init(priv, i);
- jr2_cpu_capture_setup(priv);
- return 0;
+}
+static inline int jr2_vlant_wait_for_completion(struct jr2_private *priv) +{
- if (wait_for_bit_le32(priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL,
LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
false, 2000, false))
return -ETIMEDOUT;
- return 0;
+}
+static int jr2_mac_table_add(struct jr2_private *priv,
const unsigned char mac[ETH_ALEN], int pgid)
+{
- u32 macl = 0, mach = 0;
- /*
* Set the MAC address to handle and the vlan associated in a format
* understood by the hardware.
*/
- mach |= MAC_VID << 16;
- mach |= ((u32)mac[0]) << 8;
- mach |= ((u32)mac[1]) << 0;
- macl |= ((u32)mac[2]) << 24;
- macl |= ((u32)mac[3]) << 16;
- macl |= ((u32)mac[4]) << 8;
- macl |= ((u32)mac[5]) << 0;
- writel(mach, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG0);
- writel(macl, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG1);
- writel(LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(pgid) |
LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(0x3) |
LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY |
LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(0) |
LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD |
LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED,
priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG2);
- writel(LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL);
- return jr2_vlant_wait_for_completion(priv);
+}
+static int jr2_write_hwaddr(struct udevice *dev) +{
- struct jr2_private *priv = dev_get_priv(dev);
- struct eth_pdata *pdata = dev_get_platdata(dev);
- return jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
+}
+static void serdes_setup(struct jr2_private *priv) +{
- size_t mask;
- int i = 0;
- for (i = 0; i < MAX_PORT; ++i) {
if (!priv->ports[i].bus || priv->ports[i].serdes_index == 0xff)
continue;
mask = BIT(priv->ports[i].serdes_index);
if (priv->ports[i].serdes_index < SERDES1G_MAX) {
serdes1g_setup(priv->regs[HSIO], mask,
priv->ports[i].phy_mode);
} else {
mask >>= SERDES6G(0);
serdes6g_setup(priv->regs[HSIO], mask,
priv->ports[i].phy_mode);
}
- }
+}
+static int jr2_start(struct udevice *dev) +{
- struct jr2_private *priv = dev_get_priv(dev);
- struct eth_pdata *pdata = dev_get_platdata(dev);
- const unsigned char mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff,
0xff };
- int ret;
- ret = jr2_initialize(priv);
- if (ret)
return ret;
- /* Set MAC address tables entries for CPU redirection */
- ret = jr2_mac_table_add(priv, mac, PGID_BROADCAST);
- if (ret)
return ret;
- ret = jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
- if (ret)
return ret;
- serdes_setup(priv);
- return 0;
+}
+static void jr2_stop(struct udevice *dev) +{
if you leave this empty I assume you can call jr2_start() multiple times without site effects and don't need to reverse some init stuff? Note that start() and stop() are called for each executed network command.
+}
+static int jr2_send(struct udevice *dev, void *packet, int length) +{
- struct jr2_private *priv = dev_get_priv(dev);
- u32 ifh[IFH_LEN];
- u32 *buf = packet;
- memset(ifh, '\0', IFH_LEN);
- /* Set DST PORT_MASK */
- ifh[0] = htonl(0);
- ifh[1] = htonl(0x1FFFFF);
- ifh[2] = htonl(~0);
- /* Set DST_MODE to INJECT and UPDATE_FCS */
- ifh[5] = htonl(0x4c0);
- return mscc_send(priv->regs[QS], jr2_regs_qs,
ifh, IFH_LEN, buf, length);
+}
+static int jr2_recv(struct udevice *dev, int flags, uchar **packetp) +{
- struct jr2_private *priv = dev_get_priv(dev);
- u32 *rxbuf = (u32 *)net_rx_packets[0];
- int byte_cnt = 0;
- byte_cnt = mscc_recv(priv->regs[QS], jr2_regs_qs, rxbuf, IFH_LEN,
false);
- *packetp = net_rx_packets[0];
- return byte_cnt;
+}
+static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size) +{
- int i = 0;
- for (i = 0; i < JR2_MIIM_BUS_COUNT; ++i)
if (miim[i].miim_base == base && miim[i].miim_size == size)
return miim[i].bus;
- return NULL;
+}
+static void add_port_entry(struct jr2_private *priv, size_t index,
size_t phy_addr, struct mii_dev *bus,
u8 serdes_index, u8 phy_mode)
+{
- priv->ports[index].phy_addr = phy_addr;
- priv->ports[index].bus = bus;
- priv->ports[index].serdes_index = serdes_index;
- priv->ports[index].phy_mode = phy_mode;
+}
+static int jr2_probe(struct udevice *dev) +{
- struct jr2_private *priv = dev_get_priv(dev);
- int i;
- int ret;
- struct resource res;
- fdt32_t faddr;
- phys_addr_t addr_base;
- unsigned long addr_size;
- ofnode eth_node, node, mdio_node;
- size_t phy_addr;
- struct mii_dev *bus;
- struct ofnode_phandle_args phandle;
- struct phy_device *phy;
- if (!priv)
return -EINVAL;
- /* Get registers and map them to the private structure */
- for (i = 0; i < ARRAY_SIZE(regs_names); i++) {
priv->regs[i] = dev_remap_addr_name(dev, regs_names[i]);
if (!priv->regs[i]) {
debug
("Error can't get regs base addresses for %s\n",
regs_names[i]);
return -ENOMEM;
}
- }
- /* Initialize miim buses */
- memset(&miim, 0x0, sizeof(struct jr2_miim_dev) * JR2_MIIM_BUS_COUNT);
- /* iterate all the ports and find out on which bus they are */
- i = 0;
- eth_node = dev_read_first_subnode(dev);
- for (node = ofnode_first_subnode(eth_node);
ofnode_valid(node);
node = ofnode_next_subnode(node)) {
if (ofnode_read_resource(node, 0, &res))
return -ENOMEM;
i = res.start;
ret = ofnode_parse_phandle_with_args(node, "phy-handle", NULL,
0, 0, &phandle);
if (ret)
continue;
/* Get phy address on mdio bus */
if (ofnode_read_resource(phandle.node, 0, &res))
return -ENOMEM;
phy_addr = res.start;
/* Get mdio node */
mdio_node = ofnode_get_parent(phandle.node);
if (ofnode_read_resource(mdio_node, 0, &res))
return -ENOMEM;
faddr = cpu_to_fdt32(res.start);
addr_base = ofnode_translate_address(mdio_node, &faddr);
addr_size = res.end - res.start;
/* If the bus is new then create a new bus */
if (!get_mdiobus(addr_base, addr_size))
priv->bus[miim_count] =
jr2_mdiobus_init(addr_base, addr_size);
/* Connect mdio bus with the port */
bus = get_mdiobus(addr_base, addr_size);
/* Get serdes info */
ret = ofnode_parse_phandle_with_args(node, "phys", NULL,
3, 0, &phandle);
if (ret)
return -ENOMEM;
add_port_entry(priv, i, phy_addr, bus, phandle.args[1],
phandle.args[2]);
- }
- for (i = 0; i < MAX_PORT; i++) {
if (!priv->ports[i].bus)
continue;
phy = phy_connect(priv->ports[i].bus,
priv->ports[i].phy_addr, dev,
PHY_INTERFACE_MODE_NONE);
if (phy)
board_phy_config(phy);
- }
- return 0;
+}
+static int jr2_remove(struct udevice *dev) +{
- struct jr2_private *priv = dev_get_priv(dev);
- int i;
- for (i = 0; i < JR2_MIIM_BUS_COUNT; i++) {
mdio_unregister(priv->bus[i]);
mdio_free(priv->bus[i]);
- }
- return 0;
+}
+static const struct eth_ops jr2_ops = {
- .start = jr2_start,
- .stop = jr2_stop,
- .send = jr2_send,
- .recv = jr2_recv,
- .write_hwaddr = jr2_write_hwaddr,
+};
+static const struct udevice_id mscc_jr2_ids[] = {
- {.compatible = "mscc,vsc7454-switch" },
- { /* Sentinel */ }
+};
+U_BOOT_DRIVER(jr2) = {
- .name = "jr2-switch",
- .id = UCLASS_ETH,
- .of_match = mscc_jr2_ids,
- .probe = jr2_probe,
- .remove = jr2_remove,
- .ops = &jr2_ops,
- .priv_auto_alloc_size = sizeof(struct jr2_private),
- .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+}; diff --git a/include/configs/vcoreiii.h b/include/configs/vcoreiii.h index 2840c7b..aeef58d 100644 --- a/include/configs/vcoreiii.h +++ b/include/configs/vcoreiii.h @@ -10,7 +10,7 @@
/* Onboard devices */
-#define CONFIG_SYS_MALLOC_LEN 0x100000 +#define CONFIG_SYS_MALLOC_LEN 0x1F0000 #define CONFIG_SYS_LOAD_ADDR 0x00100000 #define CONFIG_SYS_INIT_SP_OFFSET 0x400000

Hi Daniel,
The 04/03/2019 12:18, Daniel Schwierzeck wrote:
External E-Mail
Am 30.03.19 um 11:17 schrieb Horatiu Vultur:
Add network driver for Microsemi Ethernet switch. It is present on Jaguar2 SoCs.
Signed-off-by: Horatiu Vultur horatiu.vultur@microchip.com
drivers/net/mscc_eswitch/Kconfig | 7 + drivers/net/mscc_eswitch/Makefile | 1 + drivers/net/mscc_eswitch/jr2_switch.c | 1075 +++++++++++++++++++++++++++++++++ include/configs/vcoreiii.h | 2 +- 4 files changed, 1084 insertions(+), 1 deletion(-) create mode 100644 drivers/net/mscc_eswitch/jr2_switch.c
Reviewed-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com
nits below
diff --git a/drivers/net/mscc_eswitch/Kconfig b/drivers/net/mscc_eswitch/Kconfig index 88e5a97..3f9d14b 100644 --- a/drivers/net/mscc_eswitch/Kconfig +++ b/drivers/net/mscc_eswitch/Kconfig @@ -15,3 +15,10 @@ config MSCC_LUTON_SWITCH select PHYLIB help This driver supports the Luton network switch device.
+config MSCC_JR2_SWITCH
- bool "Jaguar2 switch driver"
- depends on DM_ETH && ARCH_MSCC
- select PHYLIB
- help
This driver supports the Jaguar2 network switch device.
diff --git a/drivers/net/mscc_eswitch/Makefile b/drivers/net/mscc_eswitch/Makefile index 751a839..0a1b863 100644 --- a/drivers/net/mscc_eswitch/Makefile +++ b/drivers/net/mscc_eswitch/Makefile @@ -1,3 +1,4 @@
obj-$(CONFIG_MSCC_OCELOT_SWITCH) += ocelot_switch.o mscc_miim.o mscc_xfer.o mscc_mac_table.o obj-$(CONFIG_MSCC_LUTON_SWITCH) += luton_switch.o mscc_miim.o mscc_xfer.o mscc_mac_table.o +obj-$(CONFIG_MSCC_JR2_SWITCH) += jr2_switch.o mscc_xfer.o diff --git a/drivers/net/mscc_eswitch/jr2_switch.c b/drivers/net/mscc_eswitch/jr2_switch.c new file mode 100644 index 0000000..d4a2498 --- /dev/null +++ b/drivers/net/mscc_eswitch/jr2_switch.c @@ -0,0 +1,1075 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/*
- Copyright (c) 2018 Microsemi Corporation
- */
+#include <common.h> +#include <config.h> +#include <dm.h> +#include <dm/of_access.h> +#include <dm/of_addr.h> +#include <fdt_support.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <miiphy.h> +#include <net.h> +#include <wait_bit.h>
+#include <dt-bindings/mscc/jr2_data.h> +#include "mscc_xfer.h"
+#define GCB_MIIM_MII_STATUS 0x0 +#define GCB_MIIM_STAT_BUSY BIT(3) +#define GCB_MIIM_MII_CMD 0x8 +#define GCB_MIIM_MII_CMD_SCAN BIT(0) +#define GCB_MIIM_MII_CMD_OPR_WRITE BIT(1) +#define GCB_MIIM_MII_CMD_OPR_READ BIT(2) +#define GCB_MIIM_MII_CMD_SINGLE_SCAN BIT(3) +#define GCB_MIIM_MII_CMD_WRDATA(x) ((x) << 4) +#define GCB_MIIM_MII_CMD_REGAD(x) ((x) << 20) +#define GCB_MIIM_MII_CMD_PHYAD(x) ((x) << 25) +#define GCB_MIIM_MII_CMD_VLD BIT(31) +#define GCB_MIIM_DATA 0xC +#define GCB_MIIM_DATA_ERROR (0x3 << 16)
+#define ANA_AC_RAM_CTRL_RAM_INIT 0x94358 +#define ANA_AC_STAT_GLOBAL_CFG_PORT_RESET 0x94370
+#define ANA_CL_PORT_VLAN_CFG(x) (0x24018 + 0xc8 * (x)) +#define ANA_CL_PORT_VLAN_CFG_AWARE_ENA BIT(19) +#define ANA_CL_PORT_VLAN_CFG_POP_CNT(x) ((x) << 17)
+#define ANA_L2_COMMON_FWD_CFG 0x8a2a8 +#define ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA BIT(6)
+#define ASM_CFG_STAT_CFG 0x3508 +#define ASM_CFG_PORT(x) (0x36c4 + 0x4 * (x)) +#define ASM_CFG_PORT_NO_PREAMBLE_ENA BIT(8) +#define ASM_CFG_PORT_INJ_FORMAT_CFG(x) ((x) << 1) +#define ASM_RAM_CTRL_RAM_INIT 0x39b8
+#define DEV_DEV_CFG_DEV_RST_CTRL 0x0 +#define DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(x) ((x) << 20) +#define DEV_MAC_CFG_MAC_ENA 0x1c +#define DEV_MAC_CFG_MAC_ENA_RX_ENA BIT(4) +#define DEV_MAC_CFG_MAC_ENA_TX_ENA BIT(0) +#define DEV_MAC_CFG_MAC_IFG 0x34 +#define DEV_MAC_CFG_MAC_IFG_TX_IFG(x) ((x) << 8) +#define DEV_MAC_CFG_MAC_IFG_RX_IFG2(x) ((x) << 4) +#define DEV_MAC_CFG_MAC_IFG_RX_IFG1(x) (x) +#define DEV_PCS1G_CFG_PCS1G_CFG 0x40 +#define DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA BIT(0) +#define DEV_PCS1G_CFG_PCS1G_MODE 0x44 +#define DEV_PCS1G_CFG_PCS1G_SD 0x48 +#define DEV_PCS1G_CFG_PCS1G_ANEG 0x4c +#define DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(x) ((x) << 16)
+#define DSM_RAM_CTRL_RAM_INIT 0x8
+#define HSIO_ANA_SERDES1G_DES_CFG 0xac +#define HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(x) ((x) << 1) +#define HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(x) ((x) << 5) +#define HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(x) ((x) << 8) +#define HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(x) ((x) << 13) +#define HSIO_ANA_SERDES1G_IB_CFG 0xb0 +#define HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(x) (x) +#define HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(x) ((x) << 6) +#define HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP BIT(9) +#define HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV BIT(11) +#define HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM BIT(13) +#define HSIO_ANA_SERDES1G_IB_CFG_DET_LEV(x) ((x) << 19) +#define HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(x) ((x) << 24) +#define HSIO_ANA_SERDES1G_OB_CFG 0xb4 +#define HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(x) (x) +#define HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(x) ((x) << 4) +#define HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(x) ((x) << 10) +#define HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(x) ((x) << 13) +#define HSIO_ANA_SERDES1G_OB_CFG_SLP(x) ((x) << 17) +#define HSIO_ANA_SERDES1G_SER_CFG 0xb8 +#define HSIO_ANA_SERDES1G_COMMON_CFG 0xbc +#define HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE BIT(0) +#define HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE BIT(18) +#define HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST BIT(31) +#define HSIO_ANA_SERDES1G_PLL_CFG 0xc0 +#define HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA BIT(7) +#define HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(x) ((x) << 8) +#define HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2 BIT(21) +#define HSIO_DIG_SERDES1G_DFT_CFG0 0xc8 +#define HSIO_DIG_SERDES1G_TP_CFG 0xd4 +#define HSIO_DIG_SERDES1G_MISC_CFG 0xdc +#define HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST BIT(0) +#define HSIO_MCB_SERDES1G_CFG 0xe8 +#define HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT BIT(31) +#define HSIO_MCB_SERDES1G_CFG_ADDR(x) (x)
+#define HSIO_ANA_SERDES6G_DES_CFG 0x11c +#define HSIO_ANA_SERDES6G_DES_CFG_SWAP_ANA BIT(0) +#define HSIO_ANA_SERDES6G_DES_CFG_BW_ANA(x) ((x) << 1) +#define HSIO_ANA_SERDES6G_DES_CFG_SWAP_HYST BIT(4) +#define HSIO_ANA_SERDES6G_DES_CFG_BW_HYST(x) ((x) << 5) +#define HSIO_ANA_SERDES6G_DES_CFG_CPMD_SEL(x) ((x) << 8) +#define HSIO_ANA_SERDES6G_DES_CFG_MBTR_CTRL(x) ((x) << 10) +#define HSIO_ANA_SERDES6G_DES_CFG_PHS_CTRL(x) ((x) << 13) +#define HSIO_ANA_SERDES6G_IB_CFG 0x120 +#define HSIO_ANA_SERDES6G_IB_CFG_REG_ENA BIT(0) +#define HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA BIT(1) +#define HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA BIT(2) +#define HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(x) ((x) << 3) +#define HSIO_ANA_SERDES6G_IB_CFG_CONCUR BIT(4) +#define HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA BIT(5) +#define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(x) ((x) << 7) +#define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(x) ((x) << 9) +#define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(x) ((x) << 11) +#define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(x) ((x) << 13) +#define HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(x) ((x) << 15) +#define HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(x) ((x) << 18) +#define HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(x) ((x) << 20) +#define HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(x) ((x) << 24) +#define HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL BIT(28) +#define HSIO_ANA_SERDES6G_IB_CFG_SOFSI(x) ((x) << 29) +#define HSIO_ANA_SERDES6G_IB_CFG1 0x124 +#define HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET BIT(4) +#define HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP BIT(5) +#define HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID BIT(6) +#define HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP BIT(7) +#define HSIO_ANA_SERDES6G_IB_CFG1_SCALY(x) ((x) << 8) +#define HSIO_ANA_SERDES6G_IB_CFG1_TSDET(x) ((x) << 12) +#define HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(x) ((x) << 17) +#define HSIO_ANA_SERDES6G_IB_CFG2 0x128 +#define HSIO_ANA_SERDES6G_IB_CFG2_UREG(x) (x) +#define HSIO_ANA_SERDES6G_IB_CFG2_UMAX(x) ((x) << 3) +#define HSIO_ANA_SERDES6G_IB_CFG2_TCALV(x) ((x) << 5) +#define HSIO_ANA_SERDES6G_IB_CFG2_OCALS(x) ((x) << 10) +#define HSIO_ANA_SERDES6G_IB_CFG2_OINFS(x) ((x) << 16) +#define HSIO_ANA_SERDES6G_IB_CFG2_OINFI(x) ((x) << 22) +#define HSIO_ANA_SERDES6G_IB_CFG2_TINFV(x) ((x) << 27) +#define HSIO_ANA_SERDES6G_IB_CFG3 0x12c +#define HSIO_ANA_SERDES6G_IB_CFG3_INI_OFFSET(x) (x) +#define HSIO_ANA_SERDES6G_IB_CFG3_INI_LP(x) ((x) << 6) +#define HSIO_ANA_SERDES6G_IB_CFG3_INI_MID(x) ((x) << 12) +#define HSIO_ANA_SERDES6G_IB_CFG3_INI_HP(x) ((x) << 18) +#define HSIO_ANA_SERDES6G_IB_CFG4 0x130 +#define HSIO_ANA_SERDES6G_IB_CFG4_MAX_OFFSET(x) (x) +#define HSIO_ANA_SERDES6G_IB_CFG4_MAX_LP(x) ((x) << 6) +#define HSIO_ANA_SERDES6G_IB_CFG4_MAX_MID(x) ((x) << 12) +#define HSIO_ANA_SERDES6G_IB_CFG4_MAX_HP(x) ((x) << 18) +#define HSIO_ANA_SERDES6G_IB_CFG5 0x134 +#define HSIO_ANA_SERDES6G_IB_CFG4_MIN_OFFSET(x) (x) +#define HSIO_ANA_SERDES6G_IB_CFG4_MIN_LP(x) ((x) << 6) +#define HSIO_ANA_SERDES6G_IB_CFG4_MIN_MID(x) ((x) << 12) +#define HSIO_ANA_SERDES6G_IB_CFG4_MIN_HP(x) ((x) << 18) +#define HSIO_ANA_SERDES6G_OB_CFG 0x138 +#define HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(x) (x) +#define HSIO_ANA_SERDES6G_OB_CFG_SR(x) ((x) << 4) +#define HSIO_ANA_SERDES6G_OB_CFG_SR_H BIT(8) +#define HSIO_ANA_SERDES6G_OB_CFG_SEL_RCTRL BIT(9) +#define HSIO_ANA_SERDES6G_OB_CFG_R_COR BIT(10) +#define HSIO_ANA_SERDES6G_OB_CFG_POST1(x) ((x) << 11) +#define HSIO_ANA_SERDES6G_OB_CFG_R_ADJ_PDR BIT(16) +#define HSIO_ANA_SERDES6G_OB_CFG_R_ADJ_MUX BIT(17) +#define HSIO_ANA_SERDES6G_OB_CFG_PREC(x) ((x) << 18) +#define HSIO_ANA_SERDES6G_OB_CFG_POST0(x) ((x) << 23) +#define HSIO_ANA_SERDES6G_OB_CFG_POL BIT(29) +#define HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(x) ((x) << 30) +#define HSIO_ANA_SERDES6G_OB_CFG_IDLE BIT(31) +#define HSIO_ANA_SERDES6G_OB_CFG1 0x13c +#define HSIO_ANA_SERDES6G_OB_CFG1_LEV(x) (x) +#define HSIO_ANA_SERDES6G_OB_CFG1_ENA_CAS(x) ((x) << 6) +#define HSIO_ANA_SERDES6G_SER_CFG 0x140 +#define HSIO_ANA_SERDES6G_COMMON_CFG 0x144 +#define HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(x) (x) +#define HSIO_ANA_SERDES6G_COMMON_CFG_QRATE(x) (x << 2) +#define HSIO_ANA_SERDES6G_COMMON_CFG_ENA_LANE BIT(14) +#define HSIO_ANA_SERDES6G_COMMON_CFG_SYS_RST BIT(16) +#define HSIO_ANA_SERDES6G_PLL_CFG 0x148 +#define HSIO_ANA_SERDES6G_PLL_CFG_ROT_FRQ BIT(0) +#define HSIO_ANA_SERDES6G_PLL_CFG_ROT_DIR BIT(1) +#define HSIO_ANA_SERDES6G_PLL_CFG_RB_DATA_SEL BIT(2) +#define HSIO_ANA_SERDES6G_PLL_CFG_FSM_OOR_RECAL_ENA BIT(3) +#define HSIO_ANA_SERDES6G_PLL_CFG_FSM_FORCE_SET_ENA BIT(4) +#define HSIO_ANA_SERDES6G_PLL_CFG_FSM_ENA BIT(5) +#define HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(x) ((x) << 6) +#define HSIO_ANA_SERDES6G_PLL_CFG_ENA_ROT BIT(14) +#define HSIO_ANA_SERDES6G_PLL_CFG_DIV4 BIT(15) +#define HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(x) ((x) << 16) +#define HSIO_DIG_SERDES6G_MISC_CFG 0x108 +#define HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST BIT(0) +#define HSIO_MCB_SERDES6G_CFG 0x168 +#define HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT BIT(31) +#define HSIO_MCB_SERDES6G_CFG_ADDR(x) (x) +#define HSIO_HW_CFGSTAT_HW_CFG 0x16c
+#define LRN_COMMON_ACCESS_CTRL 0x0 +#define LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT BIT(0) +#define LRN_COMMON_MAC_ACCESS_CFG0 0x4 +#define LRN_COMMON_MAC_ACCESS_CFG1 0x8 +#define LRN_COMMON_MAC_ACCESS_CFG2 0xc +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(x) (x) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(x) ((x) << 12) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD BIT(15) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED BIT(16) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY BIT(23) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(x) ((x) << 24)
+#define QFWD_SYSTEM_SWITCH_PORT_MODE(x) (0x4 * (x)) +#define QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA BIT(17)
+#define QS_XTR_GRP_CFG(x) (0x0 + 4 * (x)) +#define QS_INJ_GRP_CFG(x) (0x24 + (x) * 4)
+#define QSYS_SYSTEM_RESET_CFG 0xf0 +#define QSYS_CALCFG_CAL_AUTO(x) (0x3d4 + 4 * (x)) +#define QSYS_CALCFG_CAL_CTRL 0x3e8 +#define QSYS_CALCFG_CAL_CTRL_CAL_MODE(x) ((x) << 11) +#define QSYS_RAM_CTRL_RAM_INIT 0x3ec
+#define REW_RAM_CTRL_RAM_INIT 0x53528
+#define VOP_RAM_CTRL_RAM_INIT 0x43638
+#define XTR_VALID_BYTES(x) (4 - ((x) & 3)) +#define MAC_VID 0 +#define CPU_PORT 53 +#define IFH_LEN 7 +#define JR2_BUF_CELL_SZ 60 +#define ETH_ALEN 6 +#define PGID_BROADCAST 510 +#define PGID_UNICAST 511
+static char *regs_names[] = {
- "port0", "port1", "port2", "port3", "port4", "port5", "port6", "port7",
- "port8", "port9", "port10", "port11", "port12", "port13", "port14",
- "port15", "port16", "port17", "port18", "port19", "port20", "port21",
- "port22", "port23", "port24", "port25", "port26", "port27", "port28",
- "port29", "port30", "port31", "port32", "port33", "port34", "port35",
- "port36", "port37", "port38", "port39", "port40", "port41", "port42",
- "port43", "port44", "port45", "port46", "port47",
- "ana_ac", "ana_cl", "ana_l2", "asm", "hsio", "lrn",
- "qfwd", "qs", "qsys", "rew",
+};
this could be made const
+#define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1 +#define MAX_PORT 48
+enum jr2_ctrl_regs {
- ANA_AC = MAX_PORT,
- ANA_CL,
- ANA_L2,
- ASM,
- HSIO,
- LRN,
- QFWD,
- QS,
- QSYS,
- REW,
+};
+#define JR2_MIIM_BUS_COUNT 3
+struct jr2_phy_port_t {
- size_t phy_addr;
- struct mii_dev *bus;
- u8 serdes_index;
- u8 phy_mode;
+};
+struct jr2_private {
- void __iomem *regs[REGS_NAMES_COUNT];
- struct mii_dev *bus[JR2_MIIM_BUS_COUNT];
- struct jr2_phy_port_t ports[MAX_PORT];
+};
+struct jr2_miim_dev {
- void __iomem *regs;
- phys_addr_t miim_base;
- unsigned long miim_size;
- struct mii_dev *bus;
+};
+static const unsigned long jr2_regs_qs[] = {
- [MSCC_QS_XTR_RD] = 0x8,
- [MSCC_QS_XTR_FLUSH] = 0x18,
- [MSCC_QS_XTR_DATA_PRESENT] = 0x1c,
- [MSCC_QS_INJ_WR] = 0x2c,
- [MSCC_QS_INJ_CTRL] = 0x34,
+};
+static struct jr2_miim_dev miim[JR2_MIIM_BUS_COUNT]; +static int miim_count = -1;
+static int mscc_miim_wait_ready(struct jr2_miim_dev *miim) +{
- unsigned long deadline;
- u32 val;
- deadline = timer_get_us() + 250000;
- do {
val = readl(miim->regs + GCB_MIIM_MII_STATUS);
- } while (timer_get_us() <= deadline && (val & GCB_MIIM_STAT_BUSY));
- if (val & GCB_MIIM_STAT_BUSY)
return -ETIMEDOUT;
- return 0;
+}
+static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg) +{
- struct jr2_miim_dev *miim = (struct jr2_miim_dev *)bus->priv;
- u32 val;
- int ret;
- ret = mscc_miim_wait_ready(miim);
- if (ret)
goto out;
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
miim->regs + GCB_MIIM_MII_CMD);
- ret = mscc_miim_wait_ready(miim);
- if (ret)
goto out;
- val = readl(miim->regs + GCB_MIIM_DATA);
- if (val & GCB_MIIM_DATA_ERROR) {
ret = -EIO;
goto out;
- }
- ret = val & 0xFFFF;
- out:
- return ret;
+}
+static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
u16 val)
+{
- struct jr2_miim_dev *miim = (struct jr2_miim_dev *)bus->priv;
- int ret;
- ret = mscc_miim_wait_ready(miim);
- if (ret < 0)
goto out;
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
- out:
- return ret;
+}
+static struct mii_dev *jr2_mdiobus_init(phys_addr_t miim_base,
unsigned long miim_size)
+{
- struct mii_dev *bus;
- bus = mdio_alloc();
- if (!bus)
return NULL;
- ++miim_count;
- sprintf(bus->name, "miim-bus%d", miim_count);
- miim[miim_count].regs = ioremap(miim_base, miim_size);
- miim[miim_count].miim_base = miim_base;
- miim[miim_count].miim_size = miim_size;
- bus->priv = &miim[miim_count];
- bus->read = mscc_miim_read;
- bus->write = mscc_miim_write;
- if (mdio_register(bus))
return NULL;
- miim[miim_count].bus = bus;
- return bus;
+}
+static void jr2_cpu_capture_setup(struct jr2_private *priv) +{
- /* ASM: No preamble and IFH prefix on CPU injected frames */
- writel(ASM_CFG_PORT_NO_PREAMBLE_ENA |
ASM_CFG_PORT_INJ_FORMAT_CFG(1),
priv->regs[ASM] + ASM_CFG_PORT(CPU_PORT));
- /* Set Manual injection via DEVCPU_QS registers for CPU queue 0 */
- writel(0x5, priv->regs[QS] + QS_INJ_GRP_CFG(0));
- /* Set Manual extraction via DEVCPU_QS registers for CPU queue 0 */
- writel(0x7, priv->regs[QS] + QS_XTR_GRP_CFG(0));
- /* Enable CPU port for any frame transfer */
- setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(CPU_PORT),
QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
- /* Send a copy to CPU when found as forwarding entry */
- setbits_le32(priv->regs[ANA_L2] + ANA_L2_COMMON_FWD_CFG,
ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA);
+}
+static void jr2_port_init(struct jr2_private *priv, int port) +{
- void __iomem *regs = priv->regs[port];
- /* Enable PCS */
- writel(DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA,
regs + DEV_PCS1G_CFG_PCS1G_CFG);
- /* Disable Signal Detect */
- writel(0, regs + DEV_PCS1G_CFG_PCS1G_SD);
- /* Enable MAC RX and TX */
- writel(DEV_MAC_CFG_MAC_ENA_RX_ENA |
DEV_MAC_CFG_MAC_ENA_TX_ENA,
regs + DEV_MAC_CFG_MAC_ENA);
- /* Clear sgmii_mode_ena */
- writel(0, regs + DEV_PCS1G_CFG_PCS1G_MODE);
- /*
* Clear sw_resolve_ena(bit 0) and set adv_ability to
* something meaningful just in case
*/
- writel(DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(0x20),
regs + DEV_PCS1G_CFG_PCS1G_ANEG);
- /* Set MAC IFG Gaps */
- writel(DEV_MAC_CFG_MAC_IFG_TX_IFG(4) |
DEV_MAC_CFG_MAC_IFG_RX_IFG1(5) |
DEV_MAC_CFG_MAC_IFG_RX_IFG2(1),
regs + DEV_MAC_CFG_MAC_IFG);
- /* Set link speed and release all resets */
- writel(DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(2),
regs + DEV_DEV_CFG_DEV_RST_CTRL);
- /* Make VLAN aware for CPU traffic */
- writel(ANA_CL_PORT_VLAN_CFG_AWARE_ENA |
ANA_CL_PORT_VLAN_CFG_POP_CNT(1) |
MAC_VID,
priv->regs[ANA_CL] + ANA_CL_PORT_VLAN_CFG(port));
- /* Enable CPU port for any frame transfer */
- setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(port),
QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
+}
+static void serdes6g_write(void __iomem *base, u32 addr) +{
- u32 data;
- writel(HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT |
HSIO_MCB_SERDES6G_CFG_ADDR(addr),
base + HSIO_MCB_SERDES6G_CFG);
- do {
data = readl(base + HSIO_MCB_SERDES6G_CFG);
- } while (data & HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT);
+}
+static void serdes6g_setup(void __iomem *base, uint32_t addr,
phy_interface_t interface)
+{
- u32 ib_if_mode = 0;
- u32 ib_qrate = 0;
- u32 ib_cal_ena = 0;
- u32 ib1_tsdet = 0;
- u32 ob_lev = 0;
- u32 ob_ena_cas = 0;
- u32 ob_ena1v_mode = 0;
- u32 des_bw_ana = 0;
- u32 pll_fsm_ctrl_data = 0;
- switch (interface) {
- case PHY_INTERFACE_MODE_SGMII:
ib_if_mode = 1;
ib_qrate = 1;
ib_cal_ena = 1;
ib1_tsdet = 3;
ob_lev = 48;
ob_ena_cas = 2;
ob_ena1v_mode = 1;
des_bw_ana = 3;
pll_fsm_ctrl_data = 60;
break;
- case PHY_INTERFACE_MODE_QSGMII:
ib_if_mode = 3;
ib1_tsdet = 16;
ob_lev = 24;
des_bw_ana = 5;
pll_fsm_ctrl_data = 120;
break;
- default:
pr_err("Interface not supported\n");
return;
- }
- if (interface == PHY_INTERFACE_MODE_QSGMII)
writel(0xfff, base + HSIO_HW_CFGSTAT_HW_CFG);
- writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(3),
base + HSIO_ANA_SERDES6G_COMMON_CFG);
- writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(120) |
HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
base + HSIO_ANA_SERDES6G_PLL_CFG);
- writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) |
HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
base + HSIO_ANA_SERDES6G_IB_CFG);
- writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
HSIO_ANA_SERDES6G_IB_CFG1_TSDET(3) |
HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
base + HSIO_ANA_SERDES6G_IB_CFG1);
- writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST,
base + HSIO_DIG_SERDES6G_MISC_CFG);
- serdes6g_write(base, addr);
- writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) |
HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
base + HSIO_ANA_SERDES6G_IB_CFG);
- writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
HSIO_ANA_SERDES6G_IB_CFG1_TSDET(16) |
HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
base + HSIO_ANA_SERDES6G_IB_CFG1);
- writel(0x0, base + HSIO_ANA_SERDES6G_SER_CFG);
- writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(ib_if_mode) |
HSIO_ANA_SERDES6G_COMMON_CFG_QRATE(ib_qrate) |
HSIO_ANA_SERDES6G_COMMON_CFG_ENA_LANE |
HSIO_ANA_SERDES6G_COMMON_CFG_SYS_RST,
base + HSIO_ANA_SERDES6G_COMMON_CFG);
- writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST,
base + HSIO_DIG_SERDES6G_MISC_CFG);
- writel(HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(1) |
HSIO_ANA_SERDES6G_OB_CFG_SR(7) |
HSIO_ANA_SERDES6G_OB_CFG_SR_H |
HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(ob_ena1v_mode) |
HSIO_ANA_SERDES6G_OB_CFG_POL, base + HSIO_ANA_SERDES6G_OB_CFG);
- writel(HSIO_ANA_SERDES6G_OB_CFG1_LEV(ob_lev) |
HSIO_ANA_SERDES6G_OB_CFG1_ENA_CAS(ob_ena_cas),
base + HSIO_ANA_SERDES6G_OB_CFG1);
- writel(HSIO_ANA_SERDES6G_DES_CFG_BW_ANA(des_bw_ana) |
HSIO_ANA_SERDES6G_DES_CFG_BW_HYST(5) |
HSIO_ANA_SERDES6G_DES_CFG_MBTR_CTRL(2) |
HSIO_ANA_SERDES6G_DES_CFG_PHS_CTRL(6),
base + HSIO_ANA_SERDES6G_DES_CFG);
- writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) |
HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
base + HSIO_ANA_SERDES6G_PLL_CFG);
- serdes6g_write(base, addr);
- /* set pll_fsm_ena = 1 */
- writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_ENA |
HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) |
HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
base + HSIO_ANA_SERDES6G_PLL_CFG);
- serdes6g_write(base, addr);
- /* wait 20ms for pll bringup */
- mdelay(20);
- /* start IB calibration by setting ib_cal_ena and clearing lane_rst */
- writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(ib_cal_ena) |
HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) |
HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
base + HSIO_ANA_SERDES6G_IB_CFG);
- writel(0x0, base + HSIO_DIG_SERDES6G_MISC_CFG);
- serdes6g_write(base, addr);
- /* wait 60 for calibration */
- mdelay(60);
- /* set ib_tsdet and ib_reg_pat_sel_offset back to correct values */
- writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(ib_cal_ena) |
HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) |
HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
base + HSIO_ANA_SERDES6G_IB_CFG);
- writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
HSIO_ANA_SERDES6G_IB_CFG1_TSDET(ib1_tsdet) |
HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
base + HSIO_ANA_SERDES6G_IB_CFG1);
- serdes6g_write(base, addr);
+}
+static void serdes1g_write(void __iomem *base, u32 addr) +{
- u32 data;
- writel(HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT |
HSIO_MCB_SERDES1G_CFG_ADDR(addr),
base + HSIO_MCB_SERDES1G_CFG);
- do {
data = readl(base + HSIO_MCB_SERDES1G_CFG);
- } while (data & HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT);
+}
+static void serdes1g_setup(void __iomem *base, uint32_t addr,
phy_interface_t interface)
+{
- writel(0x0, base + HSIO_ANA_SERDES1G_SER_CFG);
- writel(0x0, base + HSIO_DIG_SERDES1G_TP_CFG);
- writel(0x0, base + HSIO_DIG_SERDES1G_DFT_CFG0);
- writel(HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(1) |
HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(4) |
HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(2) |
HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(12) |
HSIO_ANA_SERDES1G_OB_CFG_SLP(3),
base + HSIO_ANA_SERDES1G_OB_CFG);
- writel(HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(13) |
HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(2) |
HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP |
HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV |
HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM |
HSIO_ANA_SERDES1G_IB_CFG_DET_LEV(3) |
HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(1),
base + HSIO_ANA_SERDES1G_IB_CFG);
- writel(HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(7) |
HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(6) |
HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(2) |
HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(6),
base + HSIO_ANA_SERDES1G_DES_CFG);
- writel(HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST,
base + HSIO_DIG_SERDES1G_MISC_CFG);
- writel(HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA |
HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(0xc8) |
HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2,
base + HSIO_ANA_SERDES1G_PLL_CFG);
- writel(HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE |
HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE |
HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST,
base + HSIO_ANA_SERDES1G_COMMON_CFG);
- serdes1g_write(base, addr);
- setbits_le32(base + HSIO_ANA_SERDES1G_COMMON_CFG,
HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST);
- serdes1g_write(base, addr);
- clrbits_le32(base + HSIO_DIG_SERDES1G_MISC_CFG,
HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST);
- serdes1g_write(base, addr);
+}
+static int ram_init(u32 val, void __iomem *addr) +{
- writel(val, addr);
- if (wait_for_bit_le32(addr, BIT(1), false, 2000, false)) {
printf("Timeout in memory reset, reg = 0x%08x\n", val);
return 1;
- }
- return 0;
+}
+static int jr2_switch_init(struct jr2_private *priv) +{
- /* Initialize memories */
- ram_init(0x3, priv->regs[QSYS] + QSYS_RAM_CTRL_RAM_INIT);
- ram_init(0x3, priv->regs[ASM] + ASM_RAM_CTRL_RAM_INIT);
- ram_init(0x3, priv->regs[ANA_AC] + ANA_AC_RAM_CTRL_RAM_INIT);
- ram_init(0x3, priv->regs[REW] + REW_RAM_CTRL_RAM_INIT);
- /* Reset counters */
- writel(0x1, priv->regs[ANA_AC] + ANA_AC_STAT_GLOBAL_CFG_PORT_RESET);
- writel(0x1, priv->regs[ASM] + ASM_CFG_STAT_CFG);
- /* Enable switch-core and queue system */
- writel(0x1, priv->regs[QSYS] + QSYS_SYSTEM_RESET_CFG);
- return 0;
+}
+static void jr2_switch_config(struct jr2_private *priv) +{
- writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(0));
- writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(1));
- writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(2));
- writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(3));
- writel(readl(priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL) |
QSYS_CALCFG_CAL_CTRL_CAL_MODE(8),
priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL);
+}
+static int jr2_initialize(struct jr2_private *priv) +{
- int ret, i;
- /* Initialize switch memories, enable core */
- ret = jr2_switch_init(priv);
- if (ret)
return ret;
- jr2_switch_config(priv);
- for (i = 0; i < MAX_PORT; i++)
jr2_port_init(priv, i);
- jr2_cpu_capture_setup(priv);
- return 0;
+}
+static inline int jr2_vlant_wait_for_completion(struct jr2_private *priv) +{
- if (wait_for_bit_le32(priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL,
LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
false, 2000, false))
return -ETIMEDOUT;
- return 0;
+}
+static int jr2_mac_table_add(struct jr2_private *priv,
const unsigned char mac[ETH_ALEN], int pgid)
+{
- u32 macl = 0, mach = 0;
- /*
* Set the MAC address to handle and the vlan associated in a format
* understood by the hardware.
*/
- mach |= MAC_VID << 16;
- mach |= ((u32)mac[0]) << 8;
- mach |= ((u32)mac[1]) << 0;
- macl |= ((u32)mac[2]) << 24;
- macl |= ((u32)mac[3]) << 16;
- macl |= ((u32)mac[4]) << 8;
- macl |= ((u32)mac[5]) << 0;
- writel(mach, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG0);
- writel(macl, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG1);
- writel(LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(pgid) |
LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(0x3) |
LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY |
LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(0) |
LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD |
LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED,
priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG2);
- writel(LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL);
- return jr2_vlant_wait_for_completion(priv);
+}
+static int jr2_write_hwaddr(struct udevice *dev) +{
- struct jr2_private *priv = dev_get_priv(dev);
- struct eth_pdata *pdata = dev_get_platdata(dev);
- return jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
+}
+static void serdes_setup(struct jr2_private *priv) +{
- size_t mask;
- int i = 0;
- for (i = 0; i < MAX_PORT; ++i) {
if (!priv->ports[i].bus || priv->ports[i].serdes_index == 0xff)
continue;
mask = BIT(priv->ports[i].serdes_index);
if (priv->ports[i].serdes_index < SERDES1G_MAX) {
serdes1g_setup(priv->regs[HSIO], mask,
priv->ports[i].phy_mode);
} else {
mask >>= SERDES6G(0);
serdes6g_setup(priv->regs[HSIO], mask,
priv->ports[i].phy_mode);
}
- }
+}
+static int jr2_start(struct udevice *dev) +{
- struct jr2_private *priv = dev_get_priv(dev);
- struct eth_pdata *pdata = dev_get_platdata(dev);
- const unsigned char mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff,
0xff };
- int ret;
- ret = jr2_initialize(priv);
- if (ret)
return ret;
- /* Set MAC address tables entries for CPU redirection */
- ret = jr2_mac_table_add(priv, mac, PGID_BROADCAST);
- if (ret)
return ret;
- ret = jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
- if (ret)
return ret;
- serdes_setup(priv);
- return 0;
+}
+static void jr2_stop(struct udevice *dev) +{
if you leave this empty I assume you can call jr2_start() multiple times without site effects and don't need to reverse some init stuff? Note that start() and stop() are called for each executed network command.
Yes, you are right, there are no side effects by calling jr2_start() multiple times.
+}
+static int jr2_send(struct udevice *dev, void *packet, int length) +{
- struct jr2_private *priv = dev_get_priv(dev);
- u32 ifh[IFH_LEN];
- u32 *buf = packet;
- memset(ifh, '\0', IFH_LEN);
- /* Set DST PORT_MASK */
- ifh[0] = htonl(0);
- ifh[1] = htonl(0x1FFFFF);
- ifh[2] = htonl(~0);
- /* Set DST_MODE to INJECT and UPDATE_FCS */
- ifh[5] = htonl(0x4c0);
- return mscc_send(priv->regs[QS], jr2_regs_qs,
ifh, IFH_LEN, buf, length);
+}
+static int jr2_recv(struct udevice *dev, int flags, uchar **packetp) +{
- struct jr2_private *priv = dev_get_priv(dev);
- u32 *rxbuf = (u32 *)net_rx_packets[0];
- int byte_cnt = 0;
- byte_cnt = mscc_recv(priv->regs[QS], jr2_regs_qs, rxbuf, IFH_LEN,
false);
- *packetp = net_rx_packets[0];
- return byte_cnt;
+}
+static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size) +{
- int i = 0;
- for (i = 0; i < JR2_MIIM_BUS_COUNT; ++i)
if (miim[i].miim_base == base && miim[i].miim_size == size)
return miim[i].bus;
- return NULL;
+}
+static void add_port_entry(struct jr2_private *priv, size_t index,
size_t phy_addr, struct mii_dev *bus,
u8 serdes_index, u8 phy_mode)
+{
- priv->ports[index].phy_addr = phy_addr;
- priv->ports[index].bus = bus;
- priv->ports[index].serdes_index = serdes_index;
- priv->ports[index].phy_mode = phy_mode;
+}
+static int jr2_probe(struct udevice *dev) +{
- struct jr2_private *priv = dev_get_priv(dev);
- int i;
- int ret;
- struct resource res;
- fdt32_t faddr;
- phys_addr_t addr_base;
- unsigned long addr_size;
- ofnode eth_node, node, mdio_node;
- size_t phy_addr;
- struct mii_dev *bus;
- struct ofnode_phandle_args phandle;
- struct phy_device *phy;
- if (!priv)
return -EINVAL;
- /* Get registers and map them to the private structure */
- for (i = 0; i < ARRAY_SIZE(regs_names); i++) {
priv->regs[i] = dev_remap_addr_name(dev, regs_names[i]);
if (!priv->regs[i]) {
debug
("Error can't get regs base addresses for %s\n",
regs_names[i]);
return -ENOMEM;
}
- }
- /* Initialize miim buses */
- memset(&miim, 0x0, sizeof(struct jr2_miim_dev) * JR2_MIIM_BUS_COUNT);
- /* iterate all the ports and find out on which bus they are */
- i = 0;
- eth_node = dev_read_first_subnode(dev);
- for (node = ofnode_first_subnode(eth_node);
ofnode_valid(node);
node = ofnode_next_subnode(node)) {
if (ofnode_read_resource(node, 0, &res))
return -ENOMEM;
i = res.start;
ret = ofnode_parse_phandle_with_args(node, "phy-handle", NULL,
0, 0, &phandle);
if (ret)
continue;
/* Get phy address on mdio bus */
if (ofnode_read_resource(phandle.node, 0, &res))
return -ENOMEM;
phy_addr = res.start;
/* Get mdio node */
mdio_node = ofnode_get_parent(phandle.node);
if (ofnode_read_resource(mdio_node, 0, &res))
return -ENOMEM;
faddr = cpu_to_fdt32(res.start);
addr_base = ofnode_translate_address(mdio_node, &faddr);
addr_size = res.end - res.start;
/* If the bus is new then create a new bus */
if (!get_mdiobus(addr_base, addr_size))
priv->bus[miim_count] =
jr2_mdiobus_init(addr_base, addr_size);
/* Connect mdio bus with the port */
bus = get_mdiobus(addr_base, addr_size);
/* Get serdes info */
ret = ofnode_parse_phandle_with_args(node, "phys", NULL,
3, 0, &phandle);
if (ret)
return -ENOMEM;
add_port_entry(priv, i, phy_addr, bus, phandle.args[1],
phandle.args[2]);
- }
- for (i = 0; i < MAX_PORT; i++) {
if (!priv->ports[i].bus)
continue;
phy = phy_connect(priv->ports[i].bus,
priv->ports[i].phy_addr, dev,
PHY_INTERFACE_MODE_NONE);
if (phy)
board_phy_config(phy);
- }
- return 0;
+}
+static int jr2_remove(struct udevice *dev) +{
- struct jr2_private *priv = dev_get_priv(dev);
- int i;
- for (i = 0; i < JR2_MIIM_BUS_COUNT; i++) {
mdio_unregister(priv->bus[i]);
mdio_free(priv->bus[i]);
- }
- return 0;
+}
+static const struct eth_ops jr2_ops = {
- .start = jr2_start,
- .stop = jr2_stop,
- .send = jr2_send,
- .recv = jr2_recv,
- .write_hwaddr = jr2_write_hwaddr,
+};
+static const struct udevice_id mscc_jr2_ids[] = {
- {.compatible = "mscc,vsc7454-switch" },
- { /* Sentinel */ }
+};
+U_BOOT_DRIVER(jr2) = {
- .name = "jr2-switch",
- .id = UCLASS_ETH,
- .of_match = mscc_jr2_ids,
- .probe = jr2_probe,
- .remove = jr2_remove,
- .ops = &jr2_ops,
- .priv_auto_alloc_size = sizeof(struct jr2_private),
- .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+}; diff --git a/include/configs/vcoreiii.h b/include/configs/vcoreiii.h index 2840c7b..aeef58d 100644 --- a/include/configs/vcoreiii.h +++ b/include/configs/vcoreiii.h @@ -10,7 +10,7 @@
/* Onboard devices */
-#define CONFIG_SYS_MALLOC_LEN 0x100000 +#define CONFIG_SYS_MALLOC_LEN 0x1F0000 #define CONFIG_SYS_LOAD_ADDR 0x00100000 #define CONFIG_SYS_INIT_SP_OFFSET 0x400000
--
- Daniel

In Jaguar2 SoC family there are 3 different pcb. Each of this needs to configure the phys in different ways. Therefore implement the function board_phy_config and based on pcb configure them accordingly.
Signed-off-by: Horatiu Vultur horatiu.vultur@microchip.com --- board/mscc/jr2/jr2.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
diff --git a/board/mscc/jr2/jr2.c b/board/mscc/jr2/jr2.c index 58a4a04..6e5ef4c 100644 --- a/board/mscc/jr2/jr2.c +++ b/board/mscc/jr2/jr2.c @@ -6,6 +6,7 @@ #include <common.h> #include <asm/io.h> #include <led.h> +#include <miiphy.h>
enum { BOARD_TYPE_PCB110 = 0xAABBCE00, @@ -64,6 +65,28 @@ static void vcoreiii_gpio_set_alternate(int gpio, int mode) } }
+int board_phy_config(struct phy_device *phydev) +{ + if (gd->board_type == BOARD_TYPE_PCB110 || + gd->board_type == BOARD_TYPE_PCB112) { + phy_write(phydev, 0, 31, 0x10); + phy_write(phydev, 0, 18, 0x80F0); + while (phy_read(phydev, 0, 18) & 0x8000) + ; + phy_write(phydev, 0, 31, 0); + } + if (gd->board_type == BOARD_TYPE_PCB111) { + phy_write(phydev, 0, 31, 0x10); + phy_write(phydev, 0, 18, 0x80A0); + while (phy_read(phydev, 0, 18) & 0x8000) + ; + phy_write(phydev, 0, 14, 0x800); + phy_write(phydev, 0, 31, 0); + } + + return 0; +} + void board_debug_uart_init(void) { /* too early for the pinctrl driver, so configure the UART pins here */

Add ethernet nodes for Jaguar2 SoCs family. There are 3 pcb in this family: pcb110, pcb111 and pcb112.
Signed-off-by: Horatiu Vultur horatiu.vultur@microchip.com --- arch/mips/dts/jr2_pcb110.dts | 76 +++++++ arch/mips/dts/jr2_pcb111.dts | 400 ++++++++++++++++++++++++++++++++++++ arch/mips/dts/mscc,jr2.dtsi | 116 +++++++++++ arch/mips/dts/serval2_pcb112.dts | 44 ++++ include/dt-bindings/mscc/jr2_data.h | 19 ++ 5 files changed, 655 insertions(+) create mode 100644 include/dt-bindings/mscc/jr2_data.h
diff --git a/arch/mips/dts/jr2_pcb110.dts b/arch/mips/dts/jr2_pcb110.dts index ddc30ff..4a5a584 100644 --- a/arch/mips/dts/jr2_pcb110.dts +++ b/arch/mips/dts/jr2_pcb110.dts @@ -5,6 +5,7 @@
/dts-v1/; #include "mscc,jr2.dtsi" +#include <dt-bindings/mscc/jr2_data.h>
/ { model = "Jaguar2 Cu8-Sfp16 PCB110 Reference Board"; @@ -72,3 +73,78 @@ sgpio-ports = <0x3f00ffff>; gpio-ranges = <&sgpio2 0 0 96>; }; + +&mdio1 { + status = "okay"; + + phy0: ethernet-phy@0 { + reg = <0>; + }; + phy1: ethernet-phy@1 { + reg = <1>; + }; + phy2: ethernet-phy@2 { + reg = <2>; + }; + phy3: ethernet-phy@3 { + reg = <3>; + }; + phy4: ethernet-phy@4 { + reg = <4>; + }; + phy5: ethernet-phy@5 { + reg = <5>; + }; + phy6: ethernet-phy@6 { + reg = <6>; + }; + phy7: ethernet-phy@7 { + reg = <7>; + }; +}; + +&switch { + ethernet-ports { + + port0: port@0 { + reg = <0>; + phy-handle = <&phy0>; + phys = <&serdes_hsio 0 SERDES1G(1) PHY_MODE_SGMII>; + }; + port1: port@1 { + reg = <1>; + phy-handle = <&phy1>; + phys = <&serdes_hsio 1 SERDES1G(2) PHY_MODE_SGMII>; + }; + port2: port@2 { + reg = <2>; + phy-handle = <&phy2>; + phys = <&serdes_hsio 2 SERDES1G(3) PHY_MODE_SGMII>; + }; + port3: port@3 { + reg = <3>; + phy-handle = <&phy3>; + phys = <&serdes_hsio 3 SERDES1G(4) PHY_MODE_SGMII>; + }; + port4: port@4 { + reg = <4>; + phy-handle = <&phy4>; + phys = <&serdes_hsio 4 SERDES1G(5) PHY_MODE_SGMII>; + }; + port5: port@5 { + reg = <5>; + phy-handle = <&phy5>; + phys = <&serdes_hsio 5 SERDES1G(6) PHY_MODE_SGMII>; + }; + port6: port@6 { + reg = <6>; + phy-handle = <&phy6>; + phys = <&serdes_hsio 6 SERDES1G(7) PHY_MODE_SGMII>; + }; + port7: port@7 { + reg = <7>; + phy-handle = <&phy7>; + phys = <&serdes_hsio 7 SERDES1G(8) PHY_MODE_SGMII>; + }; + }; +}; diff --git a/arch/mips/dts/jr2_pcb111.dts b/arch/mips/dts/jr2_pcb111.dts index 4d411b6..f37ebc7 100644 --- a/arch/mips/dts/jr2_pcb111.dts +++ b/arch/mips/dts/jr2_pcb111.dts @@ -5,6 +5,7 @@
/dts-v1/; #include "mscc,jr2.dtsi" +#include <dt-bindings/mscc/jr2_data.h>
/ { model = "Jaguar2 Cu48 PCB111 Reference Board"; @@ -72,3 +73,402 @@ sgpio-ports = <0xff000000>; gpio-ranges = <&sgpio2 0 0 96>; }; + +&mdio1 { + status = "okay"; + + phy0: ethernet-phy@0 { + reg = <0>; + }; + phy1: ethernet-phy@1 { + reg = <1>; + }; + phy2: ethernet-phy@2 { + reg = <2>; + }; + phy3: ethernet-phy@3 { + reg = <3>; + }; + phy4: ethernet-phy@4 { + reg = <4>; + }; + phy5: ethernet-phy@5 { + reg = <5>; + }; + phy6: ethernet-phy@6 { + reg = <6>; + }; + phy7: ethernet-phy@7 { + reg = <7>; + }; + phy8: ethernet-phy@8 { + reg = <8>; + }; + phy9: ethernet-phy@9 { + reg = <9>; + }; + phy10: ethernet-phy@10 { + reg = <10>; + }; + phy11: ethernet-phy@11 { + reg = <11>; + }; + phy12: ethernet-phy@12 { + reg = <12>; + }; + phy13: ethernet-phy@13 { + reg = <13>; + }; + phy14: ethernet-phy@14 { + reg = <14>; + }; + phy15: ethernet-phy@15 { + reg = <15>; + }; + phy16: ethernet-phy@16 { + reg = <16>; + }; + phy17: ethernet-phy@17 { + reg = <17>; + }; + phy18: ethernet-phy@18 { + reg = <18>; + }; + phy19: ethernet-phy@19 { + reg = <19>; + }; + phy20: ethernet-phy@20 { + reg = <20>; + }; + phy21: ethernet-phy@21 { + reg = <21>; + }; + phy22: ethernet-phy@22 { + reg = <22>; + }; + phy23: ethernet-phy@23 { + reg = <23>; + }; +}; + +&mdio2 { + status = "okay"; + + phy24: ethernet-phy@24 { + reg = <0>; + }; + phy25: ethernet-phy@25 { + reg = <1>; + }; + phy26: ethernet-phy@26 { + reg = <2>; + }; + phy27: ethernet-phy@27 { + reg = <3>; + }; + phy28: ethernet-phy@28 { + reg = <4>; + }; + phy29: ethernet-phy@29 { + reg = <5>; + }; + phy30: ethernet-phy@30 { + reg = <6>; + }; + phy31: ethernet-phy@31 { + reg = <7>; + }; + phy32: ethernet-phy@32 { + reg = <8>; + }; + phy33: ethernet-phy@33 { + reg = <9>; + }; + phy34: ethernet-phy@34 { + reg = <10>; + }; + phy35: ethernet-phy@35 { + reg = <11>; + }; + phy36: ethernet-phy@36 { + reg = <12>; + }; + phy37: ethernet-phy@37 { + reg = <13>; + }; + phy38: ethernet-phy@38 { + reg = <14>; + }; + phy39: ethernet-phy@39 { + reg = <15>; + }; + phy40: ethernet-phy@40 { + reg = <16>; + }; + phy41: ethernet-phy@41 { + reg = <17>; + }; + phy42: ethernet-phy@42 { + reg = <18>; + }; + phy43: ethernet-phy@43 { + reg = <19>; + }; + phy44: ethernet-phy@44 { + reg = <20>; + }; + phy45: ethernet-phy@45 { + reg = <21>; + }; + phy46: ethernet-phy@46 { + reg = <22>; + }; + phy47: ethernet-phy@47 { + reg = <23>; + }; +}; + +&switch { + ethernet-ports { + port0: port@0 { + reg = <0>; + phy-handle = <&phy0>; + phys = <&serdes_hsio 0 SERDES6G(4) PHY_MODE_QSGMII>; + }; + port1: port@1 { + reg = <1>; + phy-handle = <&phy1>; + phys = <&serdes_hsio 1 0xff PHY_MODE_QSGMII>; + }; + port2: port@2 { + reg = <2>; + phy-handle = <&phy2>; + phys = <&serdes_hsio 2 0xff PHY_MODE_QSGMII>; + }; + port3: port@3 { + reg = <3>; + phy-handle = <&phy3>; + phys = <&serdes_hsio 3 0xff PHY_MODE_QSGMII>; + }; + port4: port@4 { + reg = <4>; + phy-handle = <&phy4>; + phys = <&serdes_hsio 4 SERDES6G(5) PHY_MODE_QSGMII>; + }; + port5: port@5 { + reg = <5>; + phy-handle = <&phy5>; + phys = <&serdes_hsio 5 0xff PHY_MODE_QSGMII>; + }; + port6: port@6 { + reg = <6>; + phy-handle = <&phy6>; + phys = <&serdes_hsio 6 0xff PHY_MODE_QSGMII>; + }; + port7: port@7 { + reg = <7>; + phy-handle = <&phy7>; + phys = <&serdes_hsio 7 0xff PHY_MODE_QSGMII>; + }; + port8: port@8 { + reg = <8>; + phy-handle = <&phy8>; + phys = <&serdes_hsio 8 SERDES6G(6) PHY_MODE_QSGMII>; + }; + port9: port@9 { + reg = <9>; + phy-handle = <&phy9>; + phys = <&serdes_hsio 9 0xff PHY_MODE_QSGMII>; + }; + port10: port@10 { + reg = <10>; + phy-handle = <&phy10>; + phys = <&serdes_hsio 10 0xff PHY_MODE_QSGMII>; + }; + port11: port@11 { + reg = <11>; + phy-handle = <&phy11>; + phys = <&serdes_hsio 11 0xff PHY_MODE_QSGMII>; + }; + port12: port@12 { + reg = <12>; + phy-handle = <&phy12>; + phys = <&serdes_hsio 12 SERDES6G(7) PHY_MODE_QSGMII>; + }; + port13: port@13 { + reg = <13>; + phy-handle = <&phy13>; + phys = <&serdes_hsio 13 0xff PHY_MODE_QSGMII>; + }; + port14: port@14 { + reg = <14>; + phy-handle = <&phy14>; + phys = <&serdes_hsio 14 0xff PHY_MODE_QSGMII>; + }; + port15: port@15 { + reg = <15>; + phy-handle = <&phy15>; + phys = <&serdes_hsio 15 0xff PHY_MODE_QSGMII>; + }; + port16: port@16 { + reg = <16>; + phy-handle = <&phy16>; + phys = <&serdes_hsio 16 SERDES6G(8) PHY_MODE_QSGMII>; + }; + port17: port@17 { + reg = <17>; + phy-handle = <&phy17>; + phys = <&serdes_hsio 17 0xff PHY_MODE_QSGMII>; + }; + port18: port@18 { + reg = <18>; + phy-handle = <&phy18>; + phys = <&serdes_hsio 18 0xff PHY_MODE_QSGMII>; + }; + port19: port@19 { + reg = <19>; + phy-handle = <&phy19>; + phys = <&serdes_hsio 19 0xff PHY_MODE_QSGMII>; + }; + port20: port@20 { + reg = <20>; + phy-handle = <&phy20>; + phys = <&serdes_hsio 20 SERDES6G(9) PHY_MODE_QSGMII>; + }; + port21: port@21 { + reg = <21>; + phy-handle = <&phy21>; + phys = <&serdes_hsio 21 0xff PHY_MODE_QSGMII>; + }; + port22: port@22 { + reg = <22>; + phy-handle = <&phy22>; + phys = <&serdes_hsio 22 0xff PHY_MODE_QSGMII>; + }; + port23: port@23 { + reg = <23>; + phy-handle = <&phy23>; + phys = <&serdes_hsio 23 0xff PHY_MODE_QSGMII>; + }; + port24: port@24 { + reg = <24>; + phy-handle = <&phy24>; + phys = <&serdes_hsio 24 SERDES6G(10) PHY_MODE_QSGMII>; + }; + port25: port@25 { + reg = <25>; + phy-handle = <&phy25>; + phys = <&serdes_hsio 25 0xff PHY_MODE_QSGMII>; + }; + port26: port@26 { + reg = <26>; + phy-handle = <&phy26>; + phys = <&serdes_hsio 26 0xff PHY_MODE_QSGMII>; + }; + port27: port@27 { + reg = <27>; + phy-handle = <&phy27>; + phys = <&serdes_hsio 27 0xff PHY_MODE_QSGMII>; + }; + port28: port@28 { + reg = <28>; + phy-handle = <&phy28>; + phys = <&serdes_hsio 28 SERDES6G(11) PHY_MODE_QSGMII>; + }; + port29: port@29 { + reg = <29>; + phy-handle = <&phy29>; + phys = <&serdes_hsio 29 0xff PHY_MODE_QSGMII>; + }; + port30: port@30 { + reg = <30>; + phy-handle = <&phy30>; + phys = <&serdes_hsio 30 0xff PHY_MODE_QSGMII>; + }; + port31: port@31 { + reg = <31>; + phy-handle = <&phy31>; + phys = <&serdes_hsio 31 0xff PHY_MODE_QSGMII>; + }; + port32: port@32 { + reg = <32>; + phy-handle = <&phy32>; + phys = <&serdes_hsio 32 SERDES6G(12) PHY_MODE_QSGMII>; + }; + port33: port@33 { + reg = <33>; + phy-handle = <&phy33>; + phys = <&serdes_hsio 33 0xff PHY_MODE_QSGMII>; + }; + port34: port@34 { + reg = <34>; + phy-handle = <&phy34>; + phys = <&serdes_hsio 34 0xff PHY_MODE_QSGMII>; + }; + port35: port@35 { + reg = <35>; + phy-handle = <&phy35>; + phys = <&serdes_hsio 35 0xff PHY_MODE_QSGMII>; + }; + port36: port@36 { + reg = <36>; + phy-handle = <&phy36>; + phys = <&serdes_hsio 36 SERDES6G(13) PHY_MODE_QSGMII>; + }; + port37: port@37 { + reg = <37>; + phy-handle = <&phy37>; + phys = <&serdes_hsio 37 0xff PHY_MODE_QSGMII>; + }; + port38: port@38 { + reg = <38>; + phy-handle = <&phy38>; + phys = <&serdes_hsio 38 0xff PHY_MODE_QSGMII>; + }; + port39: port@39 { + reg = <39>; + phy-handle = <&phy39>; + phys = <&serdes_hsio 39 0xff PHY_MODE_QSGMII>; + }; + port40: port@40 { + reg = <40>; + phy-handle = <&phy40>; + phys = <&serdes_hsio 40 SERDES6G(14) PHY_MODE_QSGMII>; + }; + port41: port@41 { + reg = <41>; + phy-handle = <&phy41>; + phys = <&serdes_hsio 41 0xff PHY_MODE_QSGMII>; + }; + port42: port@42 { + reg = <42>; + phy-handle = <&phy42>; + phys = <&serdes_hsio 42 0xff PHY_MODE_QSGMII>; + }; + port43: port@43 { + reg = <43>; + phy-handle = <&phy43>; + phys = <&serdes_hsio 43 0xff PHY_MODE_QSGMII>; + }; + port44: port@44 { + reg = <44>; + phy-handle = <&phy44>; + phys = <&serdes_hsio 44 SERDES6G(15) PHY_MODE_QSGMII>; + }; + port45: port@45 { + reg = <45>; + phy-handle = <&phy45>; + phys = <&serdes_hsio 45 0xff PHY_MODE_QSGMII>; + }; + port46: port@46 { + reg = <46>; + phy-handle = <&phy46>; + phys = <&serdes_hsio 46 0xff PHY_MODE_QSGMII>; + }; + port47: port@47 { + reg = <47>; + phy-handle = <&phy47>; + phys = <&serdes_hsio 47 0xff PHY_MODE_QSGMII>; + }; + }; +}; diff --git a/arch/mips/dts/mscc,jr2.dtsi b/arch/mips/dts/mscc,jr2.dtsi index 0900926..7f5a96f 100644 --- a/arch/mips/dts/mscc,jr2.dtsi +++ b/arch/mips/dts/mscc,jr2.dtsi @@ -183,5 +183,121 @@ gpio-bank-name = "sgpio2_"; sgpio-clock = <0x14>; }; + + switch: switch@1010000 { + compatible = "mscc,vsc7454-switch"; + reg = <0x01040000 0x0100>, // VTSS_TO_DEV_0 + <0x01050000 0x0100>, // VTSS_TO_DEV_1 + <0x01060000 0x0100>, // VTSS_TO_DEV_2 + <0x01070000 0x0100>, // VTSS_TO_DEV_3 + <0x01080000 0x0100>, // VTSS_TO_DEV_4 + <0x01090000 0x0100>, // VTSS_TO_DEV_5 + <0x010a0000 0x0100>, // VTSS_TO_DEV_6 + <0x010b0000 0x0100>, // VTSS_TO_DEV_7 + <0x010c0000 0x0100>, // VTSS_TO_DEV_8 + <0x010d0000 0x0100>, // VTSS_TO_DEV_9 + <0x010e0000 0x0100>, // VTSS_TO_DEV_10 + <0x010f0000 0x0100>, // VTSS_TO_DEV_11 + <0x01100000 0x0100>, // VTSS_TO_DEV_12 + <0x01110000 0x0100>, // VTSS_TO_DEV_13 + <0x01120000 0x0100>, // VTSS_TO_DEV_14 + <0x01130000 0x0100>, // VTSS_TO_DEV_15 + <0x01140000 0x0100>, // VTSS_TO_DEV_16 + <0x01150000 0x0100>, // VTSS_TO_DEV_17 + <0x01160000 0x0100>, // VTSS_TO_DEV_18 + <0x01170000 0x0100>, // VTSS_TO_DEV_19 + <0x01180000 0x0100>, // VTSS_TO_DEV_20 + <0x01190000 0x0100>, // VTSS_TO_DEV_21 + <0x011a0000 0x0100>, // VTSS_TO_DEV_22 + <0x011b0000 0x0100>, // VTSS_TO_DEV_23 + <0x011c0000 0x0100>, // VTSS_TO_DEV_24 + <0x011d0000 0x0100>, // VTSS_TO_DEV_25 + <0x011e0000 0x0100>, // VTSS_TO_DEV_26 + <0x011f0000 0x0100>, // VTSS_TO_DEV_27 + <0x01200000 0x0100>, // VTSS_TO_DEV_28 + <0x01210000 0x0100>, // VTSS_TO_DEV_29 + <0x01220000 0x0100>, // VTSS_TO_DEV_30 + <0x01230000 0x0100>, // VTSS_TO_DEV_31 + <0x01240000 0x0100>, // VTSS_TO_DEV_32 + <0x01250000 0x0100>, // VTSS_TO_DEV_33 + <0x01260000 0x0100>, // VTSS_TO_DEV_34 + <0x01270000 0x0100>, // VTSS_TO_DEV_35 + <0x01280000 0x0100>, // VTSS_TO_DEV_36 + <0x01290000 0x0100>, // VTSS_TO_DEV_37 + <0x012a0000 0x0100>, // VTSS_TO_DEV_38 + <0x012b0000 0x0100>, // VTSS_TO_DEV_39 + <0x012c0000 0x0100>, // VTSS_TO_DEV_40 + <0x012d0000 0x0100>, // VTSS_TO_DEV_41 + <0x012e0000 0x0100>, // VTSS_TO_DEV_42 + <0x012f0000 0x0100>, // VTSS_TO_DEV_43 + <0x01300000 0x0100>, // VTSS_TO_DEV_44 + <0x01310000 0x0100>, // VTSS_TO_DEV_45 + <0x01320000 0x0100>, // VTSS_TO_DEV_46 + <0x01330000 0x0100>, // VTSS_TO_DEV_47 + <0x01f00000 0x100000>, // ANA_AC + <0x01d00000 0x100000>, // ANA_CL + <0x01e00000 0x100000>, // ANA_L2 + <0x01410000 0x10000>, // ASM + <0x01460000 0x10000>, // HSIO + <0x01420000 0x00000>, // LRN + <0x017d0000 0x10000>, // QFWD + <0x01020000 0x20000>, // QS + <0x017e0000 0x10000>, // QSYS + <0x01b00000 0x80000>; // REW + reg-names = "port0", "port1", "port2", "port3", "port4", + "port5", "port6", "port7", "port8", "port9", + "port10", "port11", "port12", "port13", + "port14", "port15", "port16", "port17", + "port18", "port19", "port20", "port21", + "port22", "port23", "port24", "port25", + "port26", "port27", "port28", "port29", + "port30", "port31", "port32", "port33", + "port34", "port35", "port36", "port37", + "port38", "port39", "port40", "port41", + "port42", "port43", "port44", "port45", + "port46", "port47", "ana_ac", "ana_cl", + "ana_l2", "asm", "hsio", "lrn", "qfwd", + "qs", "qsys", "rew"; + status = "okay"; + + ethernet-ports { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + mdio0: mdio@010100c8 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "mscc,jr2-miim"; + reg = <0x010100c8 0x24>; + status = "disabled"; + }; + + mdio1: mdio@010100ec { + #address-cells = <1>; + #size-cells = <0>; + compatible = "mscc,jr2-miim"; + reg = <0x010100ec 0x24>; + status = "disabled"; + }; + + mdio2: mdio@01010110 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "mscc,jr2-miim"; + reg = <0x01010110 0x24>; + status = "disabled"; + }; + + hsio: syscon@10d0000 { + compatible = "mscc,jr2-hsio", "syscon", "simple-mfd"; + reg = <0x10d0000 0x10000>; + + serdes_hsio: serdes_hsio { + compatible = "mscc,vsc7454-serdes"; + #phy-cells = <3>; + }; + }; }; }; diff --git a/arch/mips/dts/serval2_pcb112.dts b/arch/mips/dts/serval2_pcb112.dts index fe025f4..7a9d595 100644 --- a/arch/mips/dts/serval2_pcb112.dts +++ b/arch/mips/dts/serval2_pcb112.dts @@ -5,6 +5,7 @@
/dts-v1/; #include "mscc,jr2.dtsi" +#include <dt-bindings/mscc/jr2_data.h>
/ { model = "Serval2 NID PCB112 Reference Board"; @@ -58,3 +59,46 @@ status = "okay"; sgpio-ports = <0x3fe0ffff>; }; + +&mdio0 { + status = "okay"; + + phy16: ethernet-phy@16 { + reg = <16>; + }; + phy17: ethernet-phy@17 { + reg = <17>; + }; + phy18: ethernet-phy@18 { + reg = <18>; + }; + phy19: ethernet-phy@19 { + reg = <19>; + }; +}; + +&switch { + ethernet-ports { + + port0: port@0 { + reg = <24>; + phy-handle = <&phy16>; + phys = <&serdes_hsio 24 SERDES6G(0) PHY_MODE_SGMII>; + }; + port1: port@1 { + reg = <25>; + phy-handle = <&phy17>; + phys = <&serdes_hsio 25 SERDES6G(1) PHY_MODE_SGMII>; + }; + port2: port@2 { + reg = <26>; + phy-handle = <&phy18>; + phys = <&serdes_hsio 26 SERDES6G(2) PHY_MODE_SGMII>; + }; + port3: port@3 { + reg = <27>; + phy-handle = <&phy19>; + phys = <&serdes_hsio 27 SERDES6G(3) PHY_MODE_SGMII>; + }; + }; +}; diff --git a/include/dt-bindings/mscc/jr2_data.h b/include/dt-bindings/mscc/jr2_data.h new file mode 100644 index 0000000..2f06fc5 --- /dev/null +++ b/include/dt-bindings/mscc/jr2_data.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ +/* + * Copyright (c) 2018 Microsemi Corporation + */ + +#ifndef _JR2_DATA_H_ +#define _JR2_DATA_H_ + +#define SERDES1G(x) (x) +#define SERDES1G_MAX SERDES1G(10) +#define SERDES6G(x) (SERDES1G_MAX + 1 + (x)) +#define SERDES6G_MAX SERDES6G(17) +#define SERDES_MAX (SERDES6G_MAX + 1) + +/* similar with phy_interface_t */ +#define PHY_MODE_SGMII 2 +#define PHY_MODE_QSGMII 4 + +#endif

Update default confing to use network driver for Jaguar2 SoCs.
Signed-off-by: Horatiu Vultur horatiu.vultur@microchip.com --- configs/mscc_jr2_defconfig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/configs/mscc_jr2_defconfig b/configs/mscc_jr2_defconfig index 95562b7..92c22b8 100644 --- a/configs/mscc_jr2_defconfig +++ b/configs/mscc_jr2_defconfig @@ -28,7 +28,10 @@ CONFIG_CMD_MEMTEST=y CONFIG_CMD_GPIO=y CONFIG_CMD_SF=y CONFIG_CMD_SPI=y -# CONFIG_CMD_NET is not set +CONFIG_CMD_DHCP=y +# CONFIG_NET_TFTP_VARS is not set +# CONFIG_CMD_NFS is not set +CONFIG_CMD_PING=y CONFIG_CMD_MTDPARTS=y CONFIG_MTDIDS_DEFAULT="nor0=spi_flash" CONFIG_MTDPARTS_DEFAULT="mtdparts=spi_flash:1m(UBoot),256k(Env),256k(Env.bk)" @@ -66,3 +69,4 @@ CONFIG_SYS_NS16550=y CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_LZMA=y +CONFIG_MSCC_JR2_SWITCH=y
participants (2)
-
Daniel Schwierzeck
-
Horatiu Vultur