diff mbox

[U-Boot,v1,36/41] net: mvpp2: Add Group-of-Ports and Net-Compex configuration for PPv2.2

Message ID 20170321142802.24276-37-sr@denx.de
State Superseded
Delegated to: Stefan Roese
Headers show

Commit Message

Stefan Roese March 21, 2017, 2:27 p.m. UTC
This patch adds the GoP (Group of Ports) and NetC (Net Complex) setup to
the Marvell mvpp2 ethernet driver. This code is mostly copied from the
Marvell U-Boot version and was written by Stefan Chulski.

Currently only MAC2 (SGMII) and MAC3 (RGMII) are tested on the
Armada-7040 DB. Testing of the other MACs on other boards in all possible
PHY interface modes still needs to be done.

Signed-off-by: Stefan Roese <sr@denx.de>
Cc: Stefan Chulski <stefanc@marvell.com>
Cc: Kostya Porotchkin <kostap@marvell.com>
Cc: Nadav Haklai <nadavh@marvell.com>
---

 drivers/net/mvpp2.c | 1212 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 1174 insertions(+), 38 deletions(-)

Comments

Joe Hershberger March 21, 2017, 6:03 p.m. UTC | #1
On Tue, Mar 21, 2017 at 9:27 AM, Stefan Roese <sr@denx.de> wrote:
> This patch adds the GoP (Group of Ports) and NetC (Net Complex) setup to
> the Marvell mvpp2 ethernet driver. This code is mostly copied from the
> Marvell U-Boot version and was written by Stefan Chulski.
>
> Currently only MAC2 (SGMII) and MAC3 (RGMII) are tested on the
> Armada-7040 DB. Testing of the other MACs on other boards in all possible
> PHY interface modes still needs to be done.
>
> Signed-off-by: Stefan Roese <sr@denx.de>
> Cc: Stefan Chulski <stefanc@marvell.com>
> Cc: Kostya Porotchkin <kostap@marvell.com>
> Cc: Nadav Haklai <nadavh@marvell.com>
> ---
>
>  drivers/net/mvpp2.c | 1212 +++++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 1174 insertions(+), 38 deletions(-)

Please break this into more digestible pieces. Maybe also remove
unused / untested code.
Stefan Roese March 22, 2017, 7:50 a.m. UTC | #2
On 21.03.2017 19:03, Joe Hershberger wrote:
> On Tue, Mar 21, 2017 at 9:27 AM, Stefan Roese <sr@denx.de> wrote:
>> This patch adds the GoP (Group of Ports) and NetC (Net Complex) setup to
>> the Marvell mvpp2 ethernet driver. This code is mostly copied from the
>> Marvell U-Boot version and was written by Stefan Chulski.
>>
>> Currently only MAC2 (SGMII) and MAC3 (RGMII) are tested on the
>> Armada-7040 DB. Testing of the other MACs on other boards in all possible
>> PHY interface modes still needs to be done.
>>
>> Signed-off-by: Stefan Roese <sr@denx.de>
>> Cc: Stefan Chulski <stefanc@marvell.com>
>> Cc: Kostya Porotchkin <kostap@marvell.com>
>> Cc: Nadav Haklai <nadavh@marvell.com>
>> ---
>>
>>  drivers/net/mvpp2.c | 1212 +++++++++++++++++++++++++++++++++++++++++++++++++--
>>  1 file changed, 1174 insertions(+), 38 deletions(-)
>
> Please break this into more digestible pieces.

Okay, I'll try to split this patch into smaller parts.

> Maybe also remove unused / untested code.

I will think about this as well. Currently I'm trying to get other
interfaces and boards tested.

Thanks,
Stefan
diff mbox

Patch

diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c
index d5120a8929..c940b95d05 100644
--- a/drivers/net/mvpp2.c
+++ b/drivers/net/mvpp2.c
@@ -355,6 +355,7 @@  do {									\
 /* Per-port registers */
 #define MVPP2_GMAC_CTRL_0_REG			0x0
 #define      MVPP2_GMAC_PORT_EN_MASK		BIT(0)
+#define      MVPP2_GMAC_PORT_TYPE_MASK		BIT(1)
 #define      MVPP2_GMAC_MAX_RX_SIZE_OFFS	2
 #define      MVPP2_GMAC_MAX_RX_SIZE_MASK	0x7ffc
 #define      MVPP2_GMAC_MIB_CNTR_EN_MASK	BIT(15)
@@ -366,30 +367,141 @@  do {									\
 #define      MVPP2_GMAC_SA_LOW_OFFS		7
 #define MVPP2_GMAC_CTRL_2_REG			0x8
 #define      MVPP2_GMAC_INBAND_AN_MASK		BIT(0)
+#define      MVPP2_GMAC_SGMII_MODE_MASK		BIT(0)
 #define      MVPP2_GMAC_PCS_ENABLE_MASK		BIT(3)
 #define      MVPP2_GMAC_PORT_RGMII_MASK		BIT(4)
+#define      MVPP2_GMAC_PORT_DIS_PADING_MASK	BIT(5)
 #define      MVPP2_GMAC_PORT_RESET_MASK		BIT(6)
+#define      MVPP2_GMAC_CLK_125_BYPS_EN_MASK	BIT(9)
 #define MVPP2_GMAC_AUTONEG_CONFIG		0xc
 #define      MVPP2_GMAC_FORCE_LINK_DOWN		BIT(0)
 #define      MVPP2_GMAC_FORCE_LINK_PASS		BIT(1)
+#define      MVPP2_GMAC_EN_PCS_AN		BIT(2)
+#define      MVPP2_GMAC_AN_BYPASS_EN		BIT(3)
 #define      MVPP2_GMAC_CONFIG_MII_SPEED	BIT(5)
 #define      MVPP2_GMAC_CONFIG_GMII_SPEED	BIT(6)
 #define      MVPP2_GMAC_AN_SPEED_EN		BIT(7)
 #define      MVPP2_GMAC_FC_ADV_EN		BIT(9)
+#define      MVPP2_GMAC_EN_FC_AN		BIT(11)
 #define      MVPP2_GMAC_CONFIG_FULL_DUPLEX	BIT(12)
 #define      MVPP2_GMAC_AN_DUPLEX_EN		BIT(13)
+#define      MVPP2_GMAC_CHOOSE_SAMPLE_TX_CONFIG	BIT(15)
 #define MVPP2_GMAC_PORT_FIFO_CFG_1_REG		0x1c
 #define      MVPP2_GMAC_TX_FIFO_MIN_TH_OFFS	6
 #define      MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK	0x1fc0
 #define      MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(v)	(((v) << 6) & \
 					MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK)
+#define MVPP2_GMAC_CTRL_4_REG			0x90
+#define      MVPP2_GMAC_CTRL4_EXT_PIN_GMII_SEL_MASK	BIT(0)
+#define      MVPP2_GMAC_CTRL4_DP_CLK_SEL_MASK	BIT(5)
+#define      MVPP2_GMAC_CTRL4_SYNC_BYPASS_MASK	BIT(6)
+#define      MVPP2_GMAC_CTRL4_QSGMII_BYPASS_ACTIVE_MASK	BIT(7)
+
+/*
+ * Per-port XGMAC registers. PPv2.2 only, only for GOP port 0,
+ * relative to port->base.
+ */
+
+/* Port Mac Control0 */
+#define MVPP22_XLG_CTRL0_REG			0x100
+#define      MVPP22_XLG_PORT_EN			BIT(0)
+#define      MVPP22_XLG_MAC_RESETN		BIT(1)
+#define      MVPP22_XLG_RX_FC_EN		BIT(7)
+#define      MVPP22_XLG_MIBCNT_DIS		BIT(13)
+/* Port Mac Control1 */
+#define MVPP22_XLG_CTRL1_REG			0x104
+#define      MVPP22_XLG_MAX_RX_SIZE_OFFS	0
+#define      MVPP22_XLG_MAX_RX_SIZE_MASK	0x1fff
+/* Port Interrupt Mask */
+#define MVPP22_XLG_INTERRUPT_MASK_REG		0x118
+#define      MVPP22_XLG_INTERRUPT_LINK_CHANGE	BIT(1)
+/* Port Mac Control3 */
+#define MVPP22_XLG_CTRL3_REG			0x11c
+#define      MVPP22_XLG_CTRL3_MACMODESELECT_MASK	(7 << 13)
+#define      MVPP22_XLG_CTRL3_MACMODESELECT_GMAC	(0 << 13)
+#define      MVPP22_XLG_CTRL3_MACMODESELECT_10GMAC	(1 << 13)
+/* Port Mac Control4 */
+#define MVPP22_XLG_CTRL4_REG			0x184
+#define      MVPP22_XLG_FORWARD_802_3X_FC_EN	BIT(5)
+#define      MVPP22_XLG_FORWARD_PFC_EN		BIT(6)
+#define      MVPP22_XLG_MODE_DMA_1G		BIT(12)
+#define      MVPP22_XLG_EN_IDLE_CHECK_FOR_LINK	BIT(14)
+
+/* XPCS registers */
+
+/* Global Configuration 0 */
+#define MVPP22_XPCS_GLOBAL_CFG_0_REG		0x0
+#define      MVPP22_XPCS_PCSRESET		BIT(0)
+#define      MVPP22_XPCS_PCSMODE_OFFS		3
+#define      MVPP22_XPCS_PCSMODE_MASK		(0x3 << \
+						 MVPP22_XPCS_PCSMODE_OFFS)
+#define      MVPP22_XPCS_LANEACTIVE_OFFS	5
+#define      MVPP22_XPCS_LANEACTIVE_MASK	(0x3 << \
+						 MVPP22_XPCS_LANEACTIVE_OFFS)
+
+/* MPCS registers */
+
+#define PCS40G_COMMON_CONTROL			0x14
+#define      FORWARD_ERROR_CORRECTION_MASK	BIT(1)
+
+#define PCS_CLOCK_RESET				0x14c
+#define      TX_SD_CLK_RESET_MASK		BIT(0)
+#define      RX_SD_CLK_RESET_MASK		BIT(1)
+#define      MAC_CLK_RESET_MASK			BIT(2)
+#define      CLK_DIVISION_RATIO_OFFS		4
+#define      CLK_DIVISION_RATIO_MASK		(0x7 << CLK_DIVISION_RATIO_OFFS)
+#define      CLK_DIV_PHASE_SET_MASK		BIT(11)
+
+/* System Soft Reset 1 */
+#define GOP_SOFT_RESET_1_REG			0x108
+#define     NETC_GOP_SOFT_RESET_OFFS		6
+#define     NETC_GOP_SOFT_RESET_MASK		(0x1 << \
+						 NETC_GOP_SOFT_RESET_OFFS)
+
+/* Ports Control 0 */
+#define NETCOMP_PORTS_CONTROL_0_REG		0x110
+#define     NETC_BUS_WIDTH_SELECT_OFFS		1
+#define     NETC_BUS_WIDTH_SELECT_MASK		(0x1 << \
+						 NETC_BUS_WIDTH_SELECT_OFFS)
+#define     NETC_GIG_RX_DATA_SAMPLE_OFFS	29
+#define     NETC_GIG_RX_DATA_SAMPLE_MASK	(0x1 << \
+						 NETC_GIG_RX_DATA_SAMPLE_OFFS)
+#define     NETC_CLK_DIV_PHASE_OFFS		31
+#define     NETC_CLK_DIV_PHASE_MASK		(0x1 << NETC_CLK_DIV_PHASE_OFFS)
+/* Ports Control 1 */
+#define NETCOMP_PORTS_CONTROL_1_REG		0x114
+#define     NETC_PORTS_ACTIVE_OFFSET(p)		(0 + p)
+#define     NETC_PORTS_ACTIVE_MASK(p)		(0x1 << \
+						 NETC_PORTS_ACTIVE_OFFSET(p))
+#define     NETC_PORT_GIG_RF_RESET_OFFS(p)	(28 + p)
+#define     NETC_PORT_GIG_RF_RESET_MASK(p)	(0x1 << \
+						 NETC_PORT_GIG_RF_RESET_OFFS(p))
+#define NETCOMP_CONTROL_0_REG			0x120
+#define     NETC_GBE_PORT0_SGMII_MODE_OFFS	0
+#define     NETC_GBE_PORT0_SGMII_MODE_MASK	(0x1 << \
+						 NETC_GBE_PORT0_SGMII_MODE_OFFS)
+#define     NETC_GBE_PORT1_SGMII_MODE_OFFS	1
+#define     NETC_GBE_PORT1_SGMII_MODE_MASK	(0x1 << \
+						 NETC_GBE_PORT1_SGMII_MODE_OFFS)
+#define     NETC_GBE_PORT1_MII_MODE_OFFS	2
+#define     NETC_GBE_PORT1_MII_MODE_MASK	(0x1 << \
+						 NETC_GBE_PORT1_MII_MODE_OFFS)
+
+/* SD1 Control1 */
+#define SD1_CONTROL_1_REG			0x148
+#define     SD1_CONTROL_RXAUI1_L45_EN_OFFS	26
+#define     SD1_CONTROL_RXAUI1_L45_EN_MASK	(0x1 << \
+						 SD1_CONTROL_RXAUI1_L45_EN_OFFS)
+#define     SD1_CONTROL_RXAUI0_L23_EN_OFFS	27
+#define     SD1_CONTROL_RXAUI0_L23_EN_MASK	(0x1 << \
+						 SD1_CONTROL_RXAUI0_L23_EN_OFFS)
+#define     SD1_CONTROL_XAUI_EN_OFFS		28
+#define     SD1_CONTROL_XAUI_EN_MASK		(0x1 << \
+						 SD1_CONTROL_XAUI_EN_OFFS)
 
 #define MVPP22_SMI_MISC_CFG_REG			0x1204
 #define      MVPP22_SMI_POLLING_EN		BIT(10)
 
-#define MVPP22_PORT_BASE			0x30e00
-#define MVPP22_PORT_OFFSET			0x1000
-
 #define MVPP2_CAUSE_TXQ_SENT_DESC_ALL_MASK	0xff
 
 /* Descriptor ring Macros */
@@ -414,6 +526,55 @@  do {									\
 #define     MVPP2_PHY_ADDR_MASK			0x1f
 #define     MVPP2_PHY_REG_MASK			0x1f
 
+/* Additional PPv2.2 offsets */
+#define MVPP22_MPCS				0x007000
+#define MVPP22_XPCS				0x007400
+#define MVPP22_PORT_BASE			0x007e00
+#define MVPP22_PORT_OFFSET			0x001000
+#define MVPP22_RFU1				0x318000
+
+/* Maximum number of ports */
+#define MVPP22_GOP_MAC_NUM			4
+
+/* Sets the field located at the specified in data */
+#define MVPP2_RGMII_TX_FIFO_MIN_TH		0x41
+#define MVPP2_SGMII_TX_FIFO_MIN_TH		0x5
+#define MVPP2_SGMII2_5_TX_FIFO_MIN_TH		0xb
+
+enum mv_reset {RESET, UNRESET};
+
+enum sd_media_mode {MV_RXAUI, MV_XAUI};
+
+/* Net Complex */
+enum mv_netc_topology {
+	MV_NETC_GE_MAC0_RXAUI_L23	=	BIT(0),
+	MV_NETC_GE_MAC0_RXAUI_L45	=	BIT(1),
+	MV_NETC_GE_MAC0_XAUI		=	BIT(2),
+	MV_NETC_GE_MAC2_SGMII		=	BIT(3),
+	MV_NETC_GE_MAC3_SGMII		=	BIT(4),
+	MV_NETC_GE_MAC3_RGMII		=	BIT(5),
+};
+
+enum mv_netc_phase {
+	MV_NETC_FIRST_PHASE,
+	MV_NETC_SECOND_PHASE,
+};
+
+enum mv_netc_sgmii_xmi_mode {
+	MV_NETC_GBE_SGMII,
+	MV_NETC_GBE_XMII,
+};
+
+enum mv_netc_mii_mode {
+	MV_NETC_GBE_RGMII,
+	MV_NETC_GBE_MII,
+};
+
+enum mv_netc_lanes {
+	MV_NETC_LANE_23,
+	MV_NETC_LANE_45,
+};
+
 /* Various constants */
 
 /* Coalescing */
@@ -763,6 +924,12 @@  struct mvpp2 {
 	void __iomem *iface_base;
 	void __iomem *mdio_base;
 
+	void __iomem *mpcs_base;
+	void __iomem *xpcs_base;
+	void __iomem *rfu1_base;
+
+	u32 netc_config;
+
 	/* List of pointers to port structures */
 	struct mvpp2_port **port_list;
 
@@ -800,6 +967,7 @@  struct mvpp2_pcpu_stats {
 
 struct mvpp2_port {
 	u8 id;
+	int gop_id;
 
 	int irq;
 
@@ -834,6 +1002,8 @@  struct mvpp2_port {
 	unsigned int duplex;
 	unsigned int speed;
 
+	unsigned int phy_speed;		/* SGMII 1Gbps vs 2.5Gbps */
+
 	struct mvpp2_bm_pool *pool_long;
 	struct mvpp2_bm_pool *pool_short;
 
@@ -2736,6 +2906,7 @@  static void mvpp2_port_mii_set(struct mvpp2_port *port)
 		val |= MVPP2_GMAC_INBAND_AN_MASK;
 		break;
 	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_RGMII_ID:
 		val |= MVPP2_GMAC_PORT_RGMII_MASK;
 	default:
 		val &= ~MVPP2_GMAC_PCS_ENABLE_MASK;
@@ -2827,6 +2998,913 @@  static inline void mvpp2_gmac_max_rx_size_set(struct mvpp2_port *port)
 	writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
 }
 
+/* PPv2.2 GoP/GMAC config */
+
+/* Set the MAC to reset or exit from reset */
+static int gop_gmac_reset(struct mvpp2_port *port, enum mv_reset reset)
+{
+	u32 val;
+
+	/* read - modify - write */
+	val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+	if (reset == RESET)
+		val |= MVPP2_GMAC_PORT_RESET_MASK;
+	else
+		val &= ~MVPP2_GMAC_PORT_RESET_MASK;
+	writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+
+	return 0;
+}
+
+/*
+ * gop_gpcs_mode_cfg
+ *
+ * Configure port to working with Gig PCS or don't.
+ */
+static int gop_gpcs_mode_cfg(struct mvpp2_port *port, bool en)
+{
+	u32 val;
+
+	val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+	if (en)
+		val |= MVPP2_GMAC_PCS_ENABLE_MASK;
+	else
+		val &= ~MVPP2_GMAC_PCS_ENABLE_MASK;
+	/* enable / disable PCS on this port */
+	writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+
+	return 0;
+}
+
+static int gop_bypass_clk_cfg(struct mvpp2_port *port, bool en)
+{
+	u32 val;
+
+	val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+	if (en)
+		val |= MVPP2_GMAC_CLK_125_BYPS_EN_MASK;
+	else
+		val &= ~MVPP2_GMAC_CLK_125_BYPS_EN_MASK;
+	/* enable / disable PCS on this port */
+	writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+
+	return 0;
+}
+
+static void gop_gmac_sgmii2_5_cfg(struct mvpp2_port *port)
+{
+	u32 val, thresh;
+
+	/*
+	 * Configure minimal level of the Tx FIFO before the lower part
+	 * starts to read a packet
+	 */
+	thresh = MVPP2_SGMII2_5_TX_FIFO_MIN_TH;
+	val = readl(port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+	val &= ~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK;
+	val |= MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(thresh);
+	writel(val, port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+
+	/* Disable bypass of sync module */
+	val = readl(port->base + MVPP2_GMAC_CTRL_4_REG);
+	val |= MVPP2_GMAC_CTRL4_SYNC_BYPASS_MASK;
+	/* configure DP clock select according to mode */
+	val |= MVPP2_GMAC_CTRL4_DP_CLK_SEL_MASK;
+	/* configure QSGMII bypass according to mode */
+	val |= MVPP2_GMAC_CTRL4_QSGMII_BYPASS_ACTIVE_MASK;
+	writel(val, port->base + MVPP2_GMAC_CTRL_4_REG);
+
+	val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+	val |= MVPP2_GMAC_PORT_DIS_PADING_MASK;
+	writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+
+	val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+	/*
+	 * Configure GIG MAC to 1000Base-X mode connected to a fiber
+	 * transceiver
+	 */
+	val |= MVPP2_GMAC_PORT_TYPE_MASK;
+	writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+
+	/* configure AN 0x9268 */
+	val = MVPP2_GMAC_EN_PCS_AN |
+		MVPP2_GMAC_AN_BYPASS_EN |
+		MVPP2_GMAC_CONFIG_MII_SPEED  |
+		MVPP2_GMAC_CONFIG_GMII_SPEED     |
+		MVPP2_GMAC_FC_ADV_EN    |
+		MVPP2_GMAC_CONFIG_FULL_DUPLEX |
+		MVPP2_GMAC_CHOOSE_SAMPLE_TX_CONFIG;
+	writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+}
+
+static void gop_gmac_sgmii_cfg(struct mvpp2_port *port)
+{
+	u32 val, thresh;
+
+	/*
+	 * Configure minimal level of the Tx FIFO before the lower part
+	 * starts to read a packet
+	 */
+	thresh = MVPP2_SGMII_TX_FIFO_MIN_TH;
+	val = readl(port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+	val &= ~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK;
+	val |= MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(thresh);
+	writel(val, port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+
+	/* Disable bypass of sync module */
+	val = readl(port->base + MVPP2_GMAC_CTRL_4_REG);
+	val |= MVPP2_GMAC_CTRL4_SYNC_BYPASS_MASK;
+	/* configure DP clock select according to mode */
+	val &= ~MVPP2_GMAC_CTRL4_DP_CLK_SEL_MASK;
+	/* configure QSGMII bypass according to mode */
+	val |= MVPP2_GMAC_CTRL4_QSGMII_BYPASS_ACTIVE_MASK;
+	writel(val, port->base + MVPP2_GMAC_CTRL_4_REG);
+
+	val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+	val |= MVPP2_GMAC_PORT_DIS_PADING_MASK;
+	writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+
+	val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+	/* configure GIG MAC to SGMII mode */
+	val &= ~MVPP2_GMAC_PORT_TYPE_MASK;
+	writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+
+	/* configure AN */
+	val = MVPP2_GMAC_EN_PCS_AN |
+		MVPP2_GMAC_AN_BYPASS_EN |
+		MVPP2_GMAC_AN_SPEED_EN  |
+		MVPP2_GMAC_EN_FC_AN     |
+		MVPP2_GMAC_AN_DUPLEX_EN |
+		MVPP2_GMAC_CHOOSE_SAMPLE_TX_CONFIG;
+	writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+}
+
+static void gop_gmac_rgmii_cfg(struct mvpp2_port *port)
+{
+	u32 val, thresh;
+
+	/*
+	 * Configure minimal level of the Tx FIFO before the lower part
+	 * starts to read a packet
+	 */
+	thresh = MVPP2_RGMII_TX_FIFO_MIN_TH;
+	val = readl(port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+	val &= ~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK;
+	val |= MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(thresh);
+	writel(val, port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+
+	/* Disable bypass of sync module */
+	val = readl(port->base + MVPP2_GMAC_CTRL_4_REG);
+	val |= MVPP2_GMAC_CTRL4_SYNC_BYPASS_MASK;
+	/* configure DP clock select according to mode */
+	val &= ~MVPP2_GMAC_CTRL4_DP_CLK_SEL_MASK;
+	val |= MVPP2_GMAC_CTRL4_QSGMII_BYPASS_ACTIVE_MASK;
+	val |= MVPP2_GMAC_CTRL4_EXT_PIN_GMII_SEL_MASK;
+	writel(val, port->base + MVPP2_GMAC_CTRL_4_REG);
+
+	val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+	val &= ~MVPP2_GMAC_PORT_DIS_PADING_MASK;
+	writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+
+	val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+	/* configure GIG MAC to SGMII mode */
+	val &= ~MVPP2_GMAC_PORT_TYPE_MASK;
+	writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+
+	/* configure AN 0xb8e8 */
+	val = MVPP2_GMAC_AN_BYPASS_EN |
+		MVPP2_GMAC_AN_SPEED_EN   |
+		MVPP2_GMAC_EN_FC_AN      |
+		MVPP2_GMAC_AN_DUPLEX_EN  |
+		MVPP2_GMAC_CHOOSE_SAMPLE_TX_CONFIG;
+	writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+}
+
+static void gop_gmac_qsgmii_cfg(struct mvpp2_port *port)
+{
+	u32 val, thresh;
+
+	/*
+	 * Configure minimal level of the Tx FIFO before the lower part
+	 * starts to read a packet
+	 */
+	thresh = MVPP2_SGMII_TX_FIFO_MIN_TH;
+	val = readl(port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+	val &= ~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK;
+	val |= MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(thresh);
+	writel(val, port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+
+	/* Disable bypass of sync module */
+	val = readl(port->base + MVPP2_GMAC_CTRL_4_REG);
+	val |= MVPP2_GMAC_CTRL4_SYNC_BYPASS_MASK;
+	/* configure DP clock select according to mode */
+	val &= ~MVPP2_GMAC_CTRL4_DP_CLK_SEL_MASK;
+	val &= ~MVPP2_GMAC_CTRL4_EXT_PIN_GMII_SEL_MASK;
+	/* configure QSGMII bypass according to mode */
+	val &= ~MVPP2_GMAC_CTRL4_QSGMII_BYPASS_ACTIVE_MASK;
+	writel(val, port->base + MVPP2_GMAC_CTRL_4_REG);
+
+	val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+	val &= ~MVPP2_GMAC_PORT_DIS_PADING_MASK;
+	writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+
+	val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+	/* configure GIG MAC to SGMII mode */
+	val &= ~MVPP2_GMAC_PORT_TYPE_MASK;
+	writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+
+	/* configure AN 0xB8EC */
+	val = MVPP2_GMAC_EN_PCS_AN |
+		MVPP2_GMAC_AN_BYPASS_EN |
+		MVPP2_GMAC_AN_SPEED_EN  |
+		MVPP2_GMAC_EN_FC_AN     |
+		MVPP2_GMAC_AN_DUPLEX_EN |
+		MVPP2_GMAC_CHOOSE_SAMPLE_TX_CONFIG;
+	writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+}
+
+/* Set the internal mux's to the required MAC in the GOP */
+static int gop_gmac_mode_cfg(struct mvpp2_port *port)
+{
+	u32 val;
+
+	/* Set TX FIFO thresholds */
+	switch (port->phy_interface) {
+	case PHY_INTERFACE_MODE_SGMII:
+		if (port->phy_speed == 2500)
+			gop_gmac_sgmii2_5_cfg(port);
+		else
+			gop_gmac_sgmii_cfg(port);
+		break;
+
+	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_RGMII_ID:
+		gop_gmac_rgmii_cfg(port);
+		break;
+
+	case PHY_INTERFACE_MODE_QSGMII:
+		gop_gmac_qsgmii_cfg(port);
+		break;
+
+	default:
+		return -1;
+	}
+
+	/* Jumbo frame support - 0x1400*2= 0x2800 bytes */
+	val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+	val &= ~MVPP2_GMAC_MAX_RX_SIZE_MASK;
+	val |= 0x1400 << MVPP2_GMAC_MAX_RX_SIZE_OFFS;
+	writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+
+	/* PeriodicXonEn disable */
+	val = readl(port->base + MVPP2_GMAC_CTRL_1_REG);
+	val &= ~MVPP2_GMAC_PERIODIC_XON_EN_MASK;
+	writel(val, port->base + MVPP2_GMAC_CTRL_1_REG);
+
+	return 0;
+}
+
+static void gop_xlg_2_gig_mac_cfg(struct mvpp2_port *port)
+{
+	u32 val;
+
+	/* relevant only for MAC0 (XLG0 and GMAC0) */
+	if (port->gop_id > 0)
+		return;
+
+	/* configure 1Gig MAC mode */
+	val = readl(port->base + MVPP22_XLG_CTRL3_REG);
+	val &= ~MVPP22_XLG_CTRL3_MACMODESELECT_MASK;
+	val |= MVPP22_XLG_CTRL3_MACMODESELECT_GMAC;
+	writel(val, port->base + MVPP22_XLG_CTRL3_REG);
+}
+
+static int gop_gpcs_reset(struct mvpp2_port *port, enum mv_reset act)
+{
+	u32 val;
+
+	val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+	if (act == RESET)
+		val &= ~MVPP2_GMAC_SGMII_MODE_MASK;
+	else
+		val |= MVPP2_GMAC_SGMII_MODE_MASK;
+	writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+
+	return 0;
+}
+
+/* Set the internal mux's to the required PCS in the PI */
+static int gop_xpcs_mode(struct mvpp2_port *port, int num_of_lanes)
+{
+	u32 val;
+	int lane;
+
+	switch (num_of_lanes) {
+	case 1:
+		lane = 0;
+		break;
+	case 2:
+		lane = 1;
+		break;
+	case 4:
+		lane = 2;
+		break;
+	default:
+		return -1;
+	}
+
+	/* configure XG MAC mode */
+	val = readl(port->priv->xpcs_base + MVPP22_XPCS_GLOBAL_CFG_0_REG);
+	val &= ~MVPP22_XPCS_PCSMODE_OFFS;
+	val &= ~MVPP22_XPCS_LANEACTIVE_MASK;
+	val |= (2 * lane) << MVPP22_XPCS_LANEACTIVE_OFFS;
+	writel(val, port->priv->xpcs_base + MVPP22_XPCS_GLOBAL_CFG_0_REG);
+
+	return 0;
+}
+
+static int gop_mpcs_mode(struct mvpp2_port *port)
+{
+	u32 val;
+
+	/* configure PCS40G COMMON CONTROL */
+	val = readl(port->priv->mpcs_base + PCS40G_COMMON_CONTROL);
+	val &= ~FORWARD_ERROR_CORRECTION_MASK;
+	writel(val, port->priv->mpcs_base + PCS40G_COMMON_CONTROL);
+
+	/* configure PCS CLOCK RESET */
+	val = readl(port->priv->mpcs_base + PCS_CLOCK_RESET);
+	val &= ~CLK_DIVISION_RATIO_MASK;
+	val |= 1 << CLK_DIVISION_RATIO_OFFS;
+	writel(val, port->priv->mpcs_base + PCS_CLOCK_RESET);
+
+	val &= ~CLK_DIV_PHASE_SET_MASK;
+	val |= MAC_CLK_RESET_MASK;
+	val |= RX_SD_CLK_RESET_MASK;
+	val |= TX_SD_CLK_RESET_MASK;
+	writel(val, port->priv->mpcs_base + PCS_CLOCK_RESET);
+
+	return 0;
+}
+
+/* Set the internal mux's to the required MAC in the GOP */
+static int gop_xlg_mac_mode_cfg(struct mvpp2_port *port, int num_of_act_lanes)
+{
+	u32 val;
+
+	/* configure 10G MAC mode */
+	val = readl(port->base + MVPP22_XLG_CTRL0_REG);
+	val |= MVPP22_XLG_RX_FC_EN;
+	writel(val, port->base + MVPP22_XLG_CTRL0_REG);
+
+	val = readl(port->base + MVPP22_XLG_CTRL3_REG);
+	val &= ~MVPP22_XLG_CTRL3_MACMODESELECT_MASK;
+	val |= MVPP22_XLG_CTRL3_MACMODESELECT_10GMAC;
+	writel(val, port->base + MVPP22_XLG_CTRL3_REG);
+
+	/* read - modify - write */
+	val = readl(port->base + MVPP22_XLG_CTRL4_REG);
+	val &= ~MVPP22_XLG_MODE_DMA_1G;
+	val |= MVPP22_XLG_FORWARD_PFC_EN;
+	val |= MVPP22_XLG_FORWARD_802_3X_FC_EN;
+	val &= ~MVPP22_XLG_EN_IDLE_CHECK_FOR_LINK;
+	writel(val, port->base + MVPP22_XLG_CTRL4_REG);
+
+	/* Jumbo frame support: 0x1400 * 2 = 0x2800 bytes */
+	val = readl(port->base + MVPP22_XLG_CTRL1_REG);
+	val &= ~MVPP22_XLG_MAX_RX_SIZE_MASK;
+	val |= 0x1400 << MVPP22_XLG_MAX_RX_SIZE_OFFS;
+	writel(val, port->base + MVPP22_XLG_CTRL1_REG);
+
+	/* unmask link change interrupt */
+	val = readl(port->base + MVPP22_XLG_INTERRUPT_MASK_REG);
+	val |= MVPP22_XLG_INTERRUPT_LINK_CHANGE;
+	val |= 1; /* unmask summary bit */
+	writel(val, port->base + MVPP22_XLG_INTERRUPT_MASK_REG);
+
+	return 0;
+}
+
+/* Set PCS to reset or exit from reset */
+int gop_xpcs_reset(struct mvpp2_port *port, enum mv_reset reset)
+{
+	u32 val;
+
+	/* read - modify - write */
+	val = readl(port->priv->xpcs_base + MVPP22_XPCS_GLOBAL_CFG_0_REG);
+	if (reset == RESET)
+		val &= ~MVPP22_XPCS_PCSRESET;
+	else
+		val |= MVPP22_XPCS_PCSRESET;
+	writel(val, port->priv->xpcs_base + MVPP22_XPCS_GLOBAL_CFG_0_REG);
+
+	return 0;
+}
+
+/* Set the MAC to reset or exit from reset */
+static int gop_xlg_mac_reset(struct mvpp2_port *port, enum mv_reset reset)
+{
+	u32 val;
+
+	/* read - modify - write */
+	val = readl(port->base + MVPP22_XLG_CTRL0_REG);
+	if (reset == RESET)
+		val &= ~MVPP22_XLG_MAC_RESETN;
+	else
+		val |= MVPP22_XLG_MAC_RESETN;
+	writel(val, port->base + MVPP22_XLG_CTRL0_REG);
+
+	return 0;
+}
+
+/*
+ * gop_port_init
+ *
+ * Init physical port. Configures the port mode and all it's elements
+ * accordingly.
+ * Does not verify that the selected mode/port number is valid at the
+ * core level.
+ */
+static int gop_port_init(struct mvpp2_port *port)
+{
+	int mac_num = port->gop_id;
+	int num_of_act_lanes;
+
+	if (mac_num >= MVPP22_GOP_MAC_NUM) {
+		netdev_err(NULL, "%s: illegal port number %d", __func__,
+			   mac_num);
+		return -1;
+	}
+
+	switch (port->phy_interface) {
+	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_RGMII_ID:
+		gop_gmac_reset(port, RESET);
+
+		/* configure PCS */
+		gop_gpcs_mode_cfg(port, false);
+		gop_bypass_clk_cfg(port, true);
+
+		/* configure MAC */
+		gop_gmac_mode_cfg(port);
+		/* pcs unreset */
+		gop_gpcs_reset(port, UNRESET);
+
+		/* mac unreset */
+		gop_gmac_reset(port, UNRESET);
+		break;
+
+	case PHY_INTERFACE_MODE_SGMII:
+	case PHY_INTERFACE_MODE_QSGMII:
+		/* configure PCS */
+		gop_gpcs_mode_cfg(port, true);
+
+		/* configure MAC */
+		gop_gmac_mode_cfg(port);
+		/* select proper Mac mode */
+		gop_xlg_2_gig_mac_cfg(port);
+
+		/* pcs unreset */
+		gop_gpcs_reset(port, UNRESET);
+		/* mac unreset */
+		gop_gmac_reset(port, UNRESET);
+		break;
+
+	case PHY_INTERFACE_MODE_XAUI:
+		num_of_act_lanes = 4;
+		mac_num = 0;
+		/* configure PCS */
+		gop_xpcs_mode(port, num_of_act_lanes);
+		/* configure MAC */
+		gop_xlg_mac_mode_cfg(port, num_of_act_lanes);
+
+		/* pcs unreset */
+		gop_xpcs_reset(port, UNRESET);
+		/* mac unreset */
+		gop_xlg_mac_reset(port, UNRESET);
+		break;
+
+	case PHY_INTERFACE_MODE_RXAUI:
+		num_of_act_lanes = 2;
+
+		mac_num = 0;
+		/* configure PCS */
+		gop_xpcs_mode(port, num_of_act_lanes);
+		/* configure MAC */
+		gop_xlg_mac_mode_cfg(port, num_of_act_lanes);
+
+		/* pcs unreset */
+		gop_xpcs_reset(port, UNRESET);
+
+		/* mac unreset */;
+		gop_xlg_mac_reset(port, UNRESET);
+		break;
+
+	case PHY_INTERFACE_MODE_SFI:
+		num_of_act_lanes = 2;
+		mac_num = 0;
+		/* configure PCS */
+		gop_xpcs_mode(port, num_of_act_lanes);
+		gop_mpcs_mode(port);
+		/* configure MAC */
+		gop_xlg_mac_mode_cfg(port, num_of_act_lanes);
+
+		/* pcs unreset */
+		gop_xpcs_reset(port, UNRESET);
+
+		/* mac unreset */
+		gop_xlg_mac_reset(port, UNRESET);
+		break;
+
+	default:
+		netdev_err(NULL, "%s: Requested port mode (%d) not supported\n",
+			   __func__, port->phy_interface);
+		return -1;
+	}
+
+	return 0;
+}
+
+static void gop_xlg_mac_port_enable(struct mvpp2_port *port, bool enable)
+{
+	u32 val;
+
+	val = readl(port->base + MVPP22_XLG_CTRL0_REG);
+	if (enable) {
+		/* Enable port and MIB counters update */
+		val |= MVPP22_XLG_PORT_EN;
+		val &= ~MVPP22_XLG_MIBCNT_DIS;
+	} else {
+		/* Disable port */
+		val &= ~MVPP22_XLG_PORT_EN;
+	}
+	writel(val, port->base + MVPP22_XLG_CTRL0_REG);
+}
+
+static void gop_port_enable(struct mvpp2_port *port, bool enable)
+{
+	switch (port->phy_interface) {
+	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_RGMII_ID:
+	case PHY_INTERFACE_MODE_SGMII:
+	case PHY_INTERFACE_MODE_QSGMII:
+		if (enable)
+			mvpp2_port_enable(port);
+		else
+			mvpp2_port_disable(port);
+		break;
+
+	case PHY_INTERFACE_MODE_XAUI:
+	case PHY_INTERFACE_MODE_RXAUI:
+	case PHY_INTERFACE_MODE_SFI:
+		gop_xlg_mac_port_enable(port, enable);
+
+		break;
+	default:
+		netdev_err(NULL, "%s: Wrong port mode (%d)\n", __func__,
+			   port->phy_interface);
+		return;
+	}
+}
+
+/* RFU1 functions */
+static inline u32 gop_rfu1_read(struct mvpp2 *priv, u32 offset)
+{
+	return readl(priv->rfu1_base + offset);
+}
+
+static inline void gop_rfu1_write(struct mvpp2 *priv, u32 offset, u32 data)
+{
+	writel(data, priv->rfu1_base + offset);
+}
+
+static u32 mvpp2_netc_cfg_create(int gop_id, phy_interface_t phy_type)
+{
+	u32 val = 0;
+
+	if (gop_id == 0) {
+		if (phy_type == PHY_INTERFACE_MODE_XAUI)
+			val |= MV_NETC_GE_MAC0_XAUI;
+		else if (phy_type == PHY_INTERFACE_MODE_RXAUI)
+			val |= MV_NETC_GE_MAC0_RXAUI_L23;
+	}
+
+	if (gop_id == 2) {
+		if (phy_type == PHY_INTERFACE_MODE_SGMII)
+			val |= MV_NETC_GE_MAC2_SGMII;
+	}
+
+	if (gop_id == 3) {
+		if (phy_type == PHY_INTERFACE_MODE_SGMII)
+			val |= MV_NETC_GE_MAC3_SGMII;
+		else if (phy_type == PHY_INTERFACE_MODE_RGMII ||
+			 phy_type == PHY_INTERFACE_MODE_RGMII_ID)
+			val |= MV_NETC_GE_MAC3_RGMII;
+	}
+
+	return val;
+}
+
+static void gop_netc_active_port(struct mvpp2 *priv, int gop_id, u32 val)
+{
+	u32 reg;
+
+	reg = gop_rfu1_read(priv, NETCOMP_PORTS_CONTROL_1_REG);
+	reg &= ~(NETC_PORTS_ACTIVE_MASK(gop_id));
+
+	val <<= NETC_PORTS_ACTIVE_OFFSET(gop_id);
+	val &= NETC_PORTS_ACTIVE_MASK(gop_id);
+
+	reg |= val;
+
+	gop_rfu1_write(priv, NETCOMP_PORTS_CONTROL_1_REG, reg);
+}
+
+static void gop_netc_xaui_enable(struct mvpp2 *priv, int gop_id, u32 val)
+{
+	u32 reg;
+
+	reg = gop_rfu1_read(priv, SD1_CONTROL_1_REG);
+	reg &= ~SD1_CONTROL_XAUI_EN_MASK;
+
+	val <<= SD1_CONTROL_XAUI_EN_OFFS;
+	val &= SD1_CONTROL_XAUI_EN_MASK;
+
+	reg |= val;
+
+	gop_rfu1_write(priv, SD1_CONTROL_1_REG, reg);
+}
+
+static void gop_netc_rxaui0_enable(struct mvpp2 *priv, int gop_id, u32 val)
+{
+	u32 reg;
+
+	reg = gop_rfu1_read(priv, SD1_CONTROL_1_REG);
+	reg &= ~SD1_CONTROL_RXAUI0_L23_EN_MASK;
+
+	val <<= SD1_CONTROL_RXAUI0_L23_EN_OFFS;
+	val &= SD1_CONTROL_RXAUI0_L23_EN_MASK;
+
+	reg |= val;
+
+	gop_rfu1_write(priv, SD1_CONTROL_1_REG, reg);
+}
+
+static void gop_netc_rxaui1_enable(struct mvpp2 *priv, int gop_id, u32 val)
+{
+	u32 reg;
+
+	reg = gop_rfu1_read(priv, SD1_CONTROL_1_REG);
+	reg &= ~SD1_CONTROL_RXAUI1_L45_EN_MASK;
+
+	val <<= SD1_CONTROL_RXAUI1_L45_EN_OFFS;
+	val &= SD1_CONTROL_RXAUI1_L45_EN_MASK;
+
+	reg |= val;
+
+	gop_rfu1_write(priv, SD1_CONTROL_1_REG, reg);
+}
+
+static void gop_netc_mii_mode(struct mvpp2 *priv, int gop_id, u32 val)
+{
+	u32 reg;
+
+	reg = gop_rfu1_read(priv, NETCOMP_CONTROL_0_REG);
+	reg &= ~NETC_GBE_PORT1_MII_MODE_MASK;
+
+	val <<= NETC_GBE_PORT1_MII_MODE_OFFS;
+	val &= NETC_GBE_PORT1_MII_MODE_MASK;
+
+	reg |= val;
+
+	gop_rfu1_write(priv, NETCOMP_CONTROL_0_REG, reg);
+}
+
+static void gop_netc_gop_reset(struct mvpp2 *priv, u32 val)
+{
+	u32 reg;
+
+	reg = gop_rfu1_read(priv, GOP_SOFT_RESET_1_REG);
+	reg &= ~NETC_GOP_SOFT_RESET_MASK;
+
+	val <<= NETC_GOP_SOFT_RESET_OFFS;
+	val &= NETC_GOP_SOFT_RESET_MASK;
+
+	reg |= val;
+
+	gop_rfu1_write(priv, GOP_SOFT_RESET_1_REG, reg);
+}
+
+static void gop_netc_gop_clock_logic_set(struct mvpp2 *priv, u32 val)
+{
+	u32 reg;
+
+	reg = gop_rfu1_read(priv, NETCOMP_PORTS_CONTROL_0_REG);
+	reg &= ~NETC_CLK_DIV_PHASE_MASK;
+
+	val <<= NETC_CLK_DIV_PHASE_OFFS;
+	val &= NETC_CLK_DIV_PHASE_MASK;
+
+	reg |= val;
+
+	gop_rfu1_write(priv, NETCOMP_PORTS_CONTROL_0_REG, reg);
+}
+
+static void gop_netc_port_rf_reset(struct mvpp2 *priv, int gop_id, u32 val)
+{
+	u32 reg;
+
+	reg = gop_rfu1_read(priv, NETCOMP_PORTS_CONTROL_1_REG);
+	reg &= ~(NETC_PORT_GIG_RF_RESET_MASK(gop_id));
+
+	val <<= NETC_PORT_GIG_RF_RESET_OFFS(gop_id);
+	val &= NETC_PORT_GIG_RF_RESET_MASK(gop_id);
+
+	reg |= val;
+
+	gop_rfu1_write(priv, NETCOMP_PORTS_CONTROL_1_REG, reg);
+}
+
+static void gop_netc_gbe_sgmii_mode_select(struct mvpp2 *priv, int gop_id,
+					   u32 val)
+{
+	u32 reg, mask, offset;
+
+	if (gop_id == 2) {
+		mask = NETC_GBE_PORT0_SGMII_MODE_MASK;
+		offset = NETC_GBE_PORT0_SGMII_MODE_OFFS;
+	} else {
+		mask = NETC_GBE_PORT1_SGMII_MODE_MASK;
+		offset = NETC_GBE_PORT1_SGMII_MODE_OFFS;
+	}
+	reg = gop_rfu1_read(priv, NETCOMP_CONTROL_0_REG);
+	reg &= ~mask;
+
+	val <<= offset;
+	val &= mask;
+
+	reg |= val;
+
+	gop_rfu1_write(priv, NETCOMP_CONTROL_0_REG, reg);
+}
+
+static void gop_netc_bus_width_select(struct mvpp2 *priv, u32 val)
+{
+	u32 reg;
+
+	reg = gop_rfu1_read(priv, NETCOMP_PORTS_CONTROL_0_REG);
+	reg &= ~NETC_BUS_WIDTH_SELECT_MASK;
+
+	val <<= NETC_BUS_WIDTH_SELECT_OFFS;
+	val &= NETC_BUS_WIDTH_SELECT_MASK;
+
+	reg |= val;
+
+	gop_rfu1_write(priv, NETCOMP_PORTS_CONTROL_0_REG, reg);
+}
+
+static void gop_netc_sample_stages_timing(struct mvpp2 *priv, u32 val)
+{
+	u32 reg;
+
+	reg = gop_rfu1_read(priv, NETCOMP_PORTS_CONTROL_0_REG);
+	reg &= ~NETC_GIG_RX_DATA_SAMPLE_MASK;
+
+	val <<= NETC_GIG_RX_DATA_SAMPLE_OFFS;
+	val &= NETC_GIG_RX_DATA_SAMPLE_MASK;
+
+	reg |= val;
+
+	gop_rfu1_write(priv, NETCOMP_PORTS_CONTROL_0_REG, reg);
+}
+
+static void gop_netc_mac_to_xgmii(struct mvpp2 *priv, int gop_id,
+				  enum mv_netc_phase phase)
+{
+	switch (phase) {
+	case MV_NETC_FIRST_PHASE:
+		/* Set Bus Width to HB mode = 1 */
+		gop_netc_bus_width_select(priv, 1);
+		/* Select RGMII mode */
+		gop_netc_gbe_sgmii_mode_select(priv, gop_id, MV_NETC_GBE_XMII);
+		break;
+
+	case MV_NETC_SECOND_PHASE:
+		/* De-assert the relevant port HB reset */
+		gop_netc_port_rf_reset(priv, gop_id, 1);
+		break;
+	}
+}
+
+static void gop_netc_mac_to_sgmii(struct mvpp2 *priv, int gop_id,
+				  enum mv_netc_phase phase)
+{
+	switch (phase) {
+	case MV_NETC_FIRST_PHASE:
+		/* Set Bus Width to HB mode = 1 */
+		gop_netc_bus_width_select(priv, 1);
+		/* Select SGMII mode */
+		if (gop_id >= 1) {
+			gop_netc_gbe_sgmii_mode_select(priv, gop_id,
+						       MV_NETC_GBE_SGMII);
+		}
+
+		/* Configure the sample stages */
+		gop_netc_sample_stages_timing(priv, 0);
+		/* Configure the ComPhy Selector */
+		/* gop_netc_com_phy_selector_config(netComplex); */
+		break;
+
+	case MV_NETC_SECOND_PHASE:
+		/* De-assert the relevant port HB reset */
+		gop_netc_port_rf_reset(priv, gop_id, 1);
+		break;
+	}
+}
+
+static void gop_netc_mac_to_rxaui(struct mvpp2 *priv, int gop_id,
+				  enum mv_netc_phase phase,
+				  enum mv_netc_lanes lanes)
+{
+	/* Currently only RXAUI0 supported */
+	if (gop_id != 0)
+		return;
+
+	switch (phase) {
+	case MV_NETC_FIRST_PHASE:
+		/* RXAUI Serdes/s Clock alignment */
+		if (lanes == MV_NETC_LANE_23)
+			gop_netc_rxaui0_enable(priv, gop_id, 1);
+		else
+			gop_netc_rxaui1_enable(priv, gop_id, 1);
+		break;
+
+	case MV_NETC_SECOND_PHASE:
+		/* De-assert the relevant port HB reset */
+		gop_netc_port_rf_reset(priv, gop_id, 1);
+		break;
+	}
+}
+
+static void gop_netc_mac_to_xaui(struct mvpp2 *priv, int gop_id,
+				 enum mv_netc_phase phase)
+{
+	switch (phase) {
+	case MV_NETC_FIRST_PHASE:
+		/* RXAUI Serdes/s Clock alignment */
+		gop_netc_xaui_enable(priv, gop_id, 1);
+		break;
+
+	case MV_NETC_SECOND_PHASE:
+		/* De-assert the relevant port HB reset */
+		gop_netc_port_rf_reset(priv, gop_id, 1);
+		break;
+	}
+}
+
+static int gop_netc_init(struct mvpp2 *priv, enum mv_netc_phase phase)
+{
+	u32 c = priv->netc_config;
+
+	if (c & MV_NETC_GE_MAC0_RXAUI_L23)
+		gop_netc_mac_to_rxaui(priv, 0, phase, MV_NETC_LANE_23);
+
+	if (c & MV_NETC_GE_MAC0_RXAUI_L45)
+		gop_netc_mac_to_rxaui(priv, 0, phase, MV_NETC_LANE_45);
+
+	if (c & MV_NETC_GE_MAC0_XAUI)
+		gop_netc_mac_to_xaui(priv, 0, phase);
+
+	if (c & MV_NETC_GE_MAC2_SGMII)
+		gop_netc_mac_to_sgmii(priv, 2, phase);
+	else
+		gop_netc_mac_to_xgmii(priv, 2, phase);
+
+	if (c & MV_NETC_GE_MAC3_SGMII) {
+		gop_netc_mac_to_sgmii(priv, 3, phase);
+	} else {
+		gop_netc_mac_to_xgmii(priv, 3, phase);
+		if (c & MV_NETC_GE_MAC3_RGMII)
+			gop_netc_mii_mode(priv, 3, MV_NETC_GBE_RGMII);
+		else
+			gop_netc_mii_mode(priv, 3, MV_NETC_GBE_MII);
+	}
+
+	/* Activate gop ports 0, 2, 3 */
+	gop_netc_active_port(priv, 0, 1);
+	gop_netc_active_port(priv, 2, 1);
+	gop_netc_active_port(priv, 3, 1);
+
+	if (phase == MV_NETC_SECOND_PHASE) {
+		/* Enable the GOP internal clock logic */
+		gop_netc_gop_clock_logic_set(priv, 1);
+		/* De-assert GOP unit reset */
+		gop_netc_gop_reset(priv, 1);
+	}
+
+	return 0;
+}
+
 /* Set defaults to the MVPP2 port */
 static void mvpp2_defaults_set(struct mvpp2_port *port)
 {
@@ -3603,7 +4681,10 @@  static void mvpp2_start_dev(struct mvpp2_port *port)
 	mvpp2_gmac_max_rx_size_set(port);
 	mvpp2_txp_max_tx_size_set(port);
 
-	mvpp2_port_enable(port);
+	if (port->priv->hw_version == MVPP21)
+		mvpp2_port_enable(port);
+	else
+		gop_port_enable(port, true);
 }
 
 /* Set hw internals when stopping port */
@@ -3613,7 +4694,11 @@  static void mvpp2_stop_dev(struct mvpp2_port *port)
 	mvpp2_ingress_disable(port);
 
 	mvpp2_egress_disable(port);
-	mvpp2_port_disable(port);
+
+	if (port->priv->hw_version == MVPP21)
+		mvpp2_port_disable(port);
+	else
+		gop_port_enable(port, false);
 }
 
 static int mvpp2_phy_connect(struct udevice *dev, struct mvpp2_port *port)
@@ -3707,7 +4792,9 @@  static void mvpp2_port_power_up(struct mvpp2_port *port)
 {
 	struct mvpp2 *priv = port->priv;
 
-	mvpp2_port_mii_set(port);
+	/* On PPv2.2 the GoP / interface configuration has already been done */
+	if (priv->hw_version == MVPP21)
+		mvpp2_port_mii_set(port);
 	mvpp2_port_periodic_xon_disable(port);
 	if (priv->hw_version == MVPP21)
 		mvpp2_port_fc_adv_enable(port);
@@ -3727,7 +4814,10 @@  static int mvpp2_port_init(struct udevice *dev, struct mvpp2_port *port)
 
 	/* Disable port */
 	mvpp2_egress_disable(port);
-	mvpp2_port_disable(port);
+	if (priv->hw_version == MVPP21)
+		mvpp2_port_disable(port);
+	else
+		gop_port_enable(port, false);
 
 	port->txqs = devm_kcalloc(dev, txq_number, sizeof(*port->txqs),
 				  GFP_KERNEL);
@@ -3826,19 +4916,14 @@  static int mvpp2_port_init(struct udevice *dev, struct mvpp2_port *port)
 	return 0;
 }
 
-/* Ports initialization */
-static int mvpp2_port_probe(struct udevice *dev,
-			    struct mvpp2_port *port,
-			    int port_node,
-			    struct mvpp2 *priv)
+static int phy_info_parse(struct udevice *dev, struct mvpp2_port *port)
 {
+	int port_node = dev_of_offset(dev);
+	const char *phy_mode_str;
 	int phy_node;
 	u32 id;
 	u32 phyaddr;
-	const char *phy_mode_str;
 	int phy_mode = -1;
-	int priv_common_regs_num = 2;
-	int err;
 
 	phy_node = fdtdec_lookup_phandle(gd->fdt_blob, port_node, "phy");
 	if (phy_node < 0) {
@@ -3860,48 +4945,48 @@  static int mvpp2_port_probe(struct udevice *dev,
 		return -EINVAL;
 	}
 
+	/*
+	 * ToDo:
+	 * Not sure if this DT property "phy-speed" will get accepted, so
+	 * this might change later
+	 */
+	/* Get phy-speed for SGMII 2.5Gbps vs 1Gbps setup */
+	port->phy_speed = fdtdec_get_int(gd->fdt_blob, port_node,
+					 "phy-speed", 1000);
+
 	phyaddr = fdtdec_get_int(gd->fdt_blob, phy_node, "reg", 0);
 
-	port->priv = priv;
 	port->id = id;
-	if (priv->hw_version == MVPP21)
+	if (port->priv->hw_version == MVPP21)
 		port->first_rxq = port->id * rxq_number;
 	else
-		port->first_rxq = port->id * priv->max_port_rxqs;
+		port->first_rxq = port->id * port->priv->max_port_rxqs;
 	port->phy_node = phy_node;
 	port->phy_interface = phy_mode;
 	port->phyaddr = phyaddr;
 
-	if (priv->hw_version == MVPP21) {
-		port->base = (void __iomem *)dev_get_addr_index(
-			dev->parent, priv_common_regs_num + id);
-		if (IS_ERR(port->base))
-			return PTR_ERR(port->base);
-	} else {
-		u32 gop_id;
-
-		gop_id = fdtdec_get_int(gd->fdt_blob, port_node,
-					"gop-port-id", -1);
-		if (id == -1) {
-			dev_err(&pdev->dev, "missing gop-port-id value\n");
-			return -EINVAL;
-		}
+	return 0;
+}
 
-		port->base = priv->iface_base + MVPP22_PORT_BASE +
-			gop_id * MVPP22_PORT_OFFSET;
-	}
+/* Ports initialization */
+static int mvpp2_port_probe(struct udevice *dev,
+			    struct mvpp2_port *port,
+			    int port_node,
+			    struct mvpp2 *priv)
+{
+	int err;
 
 	port->tx_ring_size = MVPP2_MAX_TXD;
 	port->rx_ring_size = MVPP2_MAX_RXD;
 
 	err = mvpp2_port_init(dev, port);
 	if (err < 0) {
-		dev_err(&pdev->dev, "failed to init port %d\n", id);
+		dev_err(&pdev->dev, "failed to init port %d\n", port->id);
 		return err;
 	}
 	mvpp2_port_power_up(port);
 
-	priv->port_list[id] = port;
+	priv->port_list[port->id] = port;
 	return 0;
 }
 
@@ -4516,6 +5601,11 @@  static int mvpp2_base_probe(struct udevice *dev)
 			return PTR_ERR(priv->iface_base);
 
 		priv->mdio_base = priv->iface_base + MVPP22_SMI;
+
+		/* Store common base addresses for all ports */
+		priv->mpcs_base = priv->iface_base + MVPP22_MPCS;
+		priv->xpcs_base = priv->iface_base + MVPP22_XPCS;
+		priv->rfu1_base = priv->iface_base + MVPP22_RFU1;
 	}
 
 	if (priv->hw_version == MVPP21)
@@ -4550,6 +5640,39 @@  static int mvpp2_probe(struct udevice *dev)
 		err = mvpp2_base_probe(dev->parent);
 		priv->probe_done = 1;
 	}
+
+	port->priv = dev_get_priv(dev->parent);
+
+	err = phy_info_parse(dev, port);
+	if (err)
+		return err;
+
+	/*
+	 * We need the port specific io base addresses at this stage, since
+	 * gop_port_init() accesses these registers
+	 */
+	if (priv->hw_version == MVPP21) {
+		int priv_common_regs_num = 2;
+
+		port->base = (void __iomem *)dev_get_addr_index(
+			dev->parent, priv_common_regs_num + port->id);
+		if (IS_ERR(port->base))
+			return PTR_ERR(port->base);
+	} else {
+		port->gop_id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+					      "gop-port-id", -1);
+		if (port->id == -1) {
+			dev_err(&pdev->dev, "missing gop-port-id value\n");
+			return -EINVAL;
+		}
+
+		port->base = priv->iface_base + MVPP22_PORT_BASE +
+			port->gop_id * MVPP22_PORT_OFFSET;
+
+		/* GoP Init */
+		gop_port_init(port);
+	}
+
 	/* Initialize network controller */
 	err = mvpp2_init(dev, priv);
 	if (err < 0) {
@@ -4557,7 +5680,20 @@  static int mvpp2_probe(struct udevice *dev)
 		return err;
 	}
 
-	return mvpp2_port_probe(dev, port, dev_of_offset(dev), priv);
+	err = mvpp2_port_probe(dev, port, dev_of_offset(dev), priv);
+	if (err)
+		return err;
+
+	if (priv->hw_version == MVPP22) {
+		priv->netc_config |= mvpp2_netc_cfg_create(port->gop_id,
+							   port->phy_interface);
+
+		/* Netcomplex configurations for all ports */
+		gop_netc_init(priv, MV_NETC_FIRST_PHASE);
+		gop_netc_init(priv, MV_NETC_SECOND_PHASE);
+	}
+
+	return 0;
 }
 
 /*