net: mvpp2: set the XPCS and MPCS in reset when not used
authorAntoine Tenart <antoine.tenart@bootlin.com>
Fri, 1 Mar 2019 10:52:16 +0000 (11:52 +0100)
committerDavid S. Miller <davem@davemloft.net>
Sat, 2 Mar 2019 07:23:35 +0000 (23:23 -0800)
This patch sets both the XPCS and MPCS blocks in reset when they aren't
used. This is done both at boot time and when reconfiguring a port mode.
The advantage now is that only the PCS used is set out of reset when the
port is configured (10GKR uses the MCPS while RXAUI uses the XPCS).

Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/marvell/mvpp2/mvpp2.h
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c

index c9edeac9ec01c2a1261ef2aecd98576ef911156a..ff0f4c503f534a792e22114af9395a81d896d4ef 100644 (file)
 /* XPCS registers. PPv2.2 only */
 #define MVPP22_XPCS_BASE(port)                 (0x7400 + (port) * 0x1000)
 #define MVPP22_XPCS_CFG0                       0x0
+#define     MVPP22_XPCS_CFG0_RESET_DIS         BIT(0)
 #define     MVPP22_XPCS_CFG0_PCS_MODE(n)       ((n) << 3)
 #define     MVPP22_XPCS_CFG0_ACTIVE_LANE(n)    ((n) << 5)
 
index 57a23c96ad4d0d87fef7e2e1362292429ea05503..18ca3257a3ad06425fde8fd07b1529e66c5c157f 100644 (file)
@@ -1015,27 +1015,20 @@ static void mvpp22_gop_init_10gkr(struct mvpp2_port *port)
        void __iomem *xpcs = priv->iface_base + MVPP22_XPCS_BASE(port->gop_id);
        u32 val;
 
-       /* XPCS */
        val = readl(xpcs + MVPP22_XPCS_CFG0);
        val &= ~(MVPP22_XPCS_CFG0_PCS_MODE(0x3) |
                 MVPP22_XPCS_CFG0_ACTIVE_LANE(0x3));
        val |= MVPP22_XPCS_CFG0_ACTIVE_LANE(2);
        writel(val, xpcs + MVPP22_XPCS_CFG0);
 
-       /* MPCS */
        val = readl(mpcs + MVPP22_MPCS_CTRL);
        val &= ~MVPP22_MPCS_CTRL_FWD_ERR_CONN;
        writel(val, mpcs + MVPP22_MPCS_CTRL);
 
        val = readl(mpcs + MVPP22_MPCS_CLK_RESET);
-       val &= ~(MVPP22_MPCS_CLK_RESET_DIV_RATIO(0x7) | MAC_CLK_RESET_MAC |
-                MAC_CLK_RESET_SD_RX | MAC_CLK_RESET_SD_TX);
+       val &= ~MVPP22_MPCS_CLK_RESET_DIV_RATIO(0x7);
        val |= MVPP22_MPCS_CLK_RESET_DIV_RATIO(1);
        writel(val, mpcs + MVPP22_MPCS_CLK_RESET);
-
-       val &= ~MVPP22_MPCS_CLK_RESET_DIV_SET;
-       val |= MAC_CLK_RESET_MAC | MAC_CLK_RESET_SD_RX | MAC_CLK_RESET_SD_TX;
-       writel(val, mpcs + MVPP22_MPCS_CLK_RESET);
 }
 
 static int mvpp22_gop_init(struct mvpp2_port *port)
@@ -1384,6 +1377,57 @@ static void mvpp2_mac_reset_assert(struct mvpp2_port *port)
        }
 }
 
+static void mvpp22_pcs_reset_assert(struct mvpp2_port *port)
+{
+       struct mvpp2 *priv = port->priv;
+       void __iomem *mpcs, *xpcs;
+       u32 val;
+
+       if (port->priv->hw_version != MVPP22 || port->gop_id != 0)
+               return;
+
+       mpcs = priv->iface_base + MVPP22_MPCS_BASE(port->gop_id);
+       xpcs = priv->iface_base + MVPP22_XPCS_BASE(port->gop_id);
+
+       val = readl(mpcs + MVPP22_MPCS_CLK_RESET);
+       val &= ~(MAC_CLK_RESET_MAC | MAC_CLK_RESET_SD_RX | MAC_CLK_RESET_SD_TX);
+       val |= MVPP22_MPCS_CLK_RESET_DIV_SET;
+       writel(val, mpcs + MVPP22_MPCS_CLK_RESET);
+
+       val = readl(xpcs + MVPP22_XPCS_CFG0);
+       writel(val & ~MVPP22_XPCS_CFG0_RESET_DIS, xpcs + MVPP22_XPCS_CFG0);
+}
+
+static void mvpp22_pcs_reset_deassert(struct mvpp2_port *port)
+{
+       struct mvpp2 *priv = port->priv;
+       void __iomem *mpcs, *xpcs;
+       u32 val;
+
+       if (port->priv->hw_version != MVPP22 || port->gop_id != 0)
+               return;
+
+       mpcs = priv->iface_base + MVPP22_MPCS_BASE(port->gop_id);
+       xpcs = priv->iface_base + MVPP22_XPCS_BASE(port->gop_id);
+
+       switch (port->phy_interface) {
+       case PHY_INTERFACE_MODE_10GKR:
+               val = readl(mpcs + MVPP22_MPCS_CLK_RESET);
+               val |= MAC_CLK_RESET_MAC | MAC_CLK_RESET_SD_RX |
+                      MAC_CLK_RESET_SD_TX;
+               val &= ~MVPP22_MPCS_CLK_RESET_DIV_SET;
+               writel(val, mpcs + MVPP22_MPCS_CLK_RESET);
+               break;
+       case PHY_INTERFACE_MODE_XAUI:
+       case PHY_INTERFACE_MODE_RXAUI:
+               val = readl(xpcs + MVPP22_XPCS_CFG0);
+               writel(val | MVPP22_XPCS_CFG0_RESET_DIS, xpcs + MVPP22_XPCS_CFG0);
+               break;
+       default:
+               break;
+       }
+}
+
 /* Change maximum receive size of the port */
 static inline void mvpp2_gmac_max_rx_size_set(struct mvpp2_port *port)
 {
@@ -3139,12 +3183,17 @@ static void mvpp22_mode_reconfigure(struct mvpp2_port *port)
        /* Set the GMAC & XLG MAC in reset */
        mvpp2_mac_reset_assert(port);
 
+       /* Set the MPCS and XPCS in reset */
+       mvpp22_pcs_reset_assert(port);
+
        /* comphy reconfiguration */
        mvpp22_comphy_init(port);
 
        /* gop reconfiguration */
        mvpp22_gop_init(port);
 
+       mvpp22_pcs_reset_deassert(port);
+
        /* Only GOP port 0 has an XLG MAC */
        if (port->gop_id == 0) {
                ctrl3 = readl(port->base + MVPP22_XLG_CTRL3_REG);
@@ -4959,6 +5008,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
        mvpp2_port_periodic_xon_disable(port);
 
        mvpp2_mac_reset_assert(port);
+       mvpp22_pcs_reset_assert(port);
 
        port->pcpu = alloc_percpu(struct mvpp2_port_pcpu);
        if (!port->pcpu) {