All of lore.kernel.org
 help / color / mirror / Atom feed
From: Horatiu Vultur <horatiu.vultur@microchip.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v3 1/4] net: Add MSCC Jaguar2 network driver.
Date: Sat, 30 Mar 2019 11:17:00 +0100	[thread overview]
Message-ID: <1553941023-13732-2-git-send-email-horatiu.vultur@microchip.com> (raw)
In-Reply-To: <1553941023-13732-1-git-send-email-horatiu.vultur@microchip.com>

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
 
-- 
2.7.4

  reply	other threads:[~2019-03-30 10:17 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-30 10:16 [U-Boot] [PATCH v3 0/4] Add network support for Jaguar2 SoCs Horatiu Vultur
2019-03-30 10:17 ` Horatiu Vultur [this message]
2019-04-03 10:18   ` [U-Boot] [PATCH v3 1/4] net: Add MSCC Jaguar2 network driver Daniel Schwierzeck
2019-04-03 10:59     ` Horatiu Vultur
2019-03-30 10:17 ` [U-Boot] [PATCH v3 2/4] board: mscc: jr2: Update MSCC Jaguar2 boards Horatiu Vultur
2019-03-30 10:17 ` [U-Boot] [PATCH v3 3/4] net: mscc: jaguar2: Add ethenet nodes for Jaguar2 Horatiu Vultur
2019-03-30 10:17 ` [U-Boot] [PATCH v3 4/4] configs: mscc_jr2: Add network support Horatiu Vultur

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1553941023-13732-2-git-send-email-horatiu.vultur@microchip.com \
    --to=horatiu.vultur@microchip.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.