net: mvpp2: use resolved link config in mac_link_up()
authorRussell King <rmk+kernel@armlinux.org.uk>
Wed, 26 Feb 2020 10:24:17 +0000 (10:24 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 27 Feb 2020 20:02:14 +0000 (12:02 -0800)
Convert the Marvell mvpp2 ethernet driver to use the finalised link
parameters in mac_link_up() rather than the parameters in mac_config().

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c

index ed8042d97e298ef2039981b24d549dec4ac77d20..6b9c7ed2547ef58031cba76887741844a4bcee61 100644 (file)
@@ -4976,15 +4976,13 @@ static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode,
        old_ctrl2 = ctrl2 = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
        old_ctrl4 = ctrl4 = readl(port->base + MVPP22_GMAC_CTRL_4_REG);
 
-       an &= ~(MVPP2_GMAC_CONFIG_MII_SPEED | MVPP2_GMAC_CONFIG_GMII_SPEED |
-               MVPP2_GMAC_AN_SPEED_EN | MVPP2_GMAC_FC_ADV_EN |
+       an &= ~(MVPP2_GMAC_AN_SPEED_EN | MVPP2_GMAC_FC_ADV_EN |
                MVPP2_GMAC_FC_ADV_ASM_EN | MVPP2_GMAC_FLOW_CTRL_AUTONEG |
-               MVPP2_GMAC_CONFIG_FULL_DUPLEX | MVPP2_GMAC_AN_DUPLEX_EN |
-               MVPP2_GMAC_IN_BAND_AUTONEG | MVPP2_GMAC_IN_BAND_AUTONEG_BYPASS);
+               MVPP2_GMAC_AN_DUPLEX_EN | MVPP2_GMAC_IN_BAND_AUTONEG |
+               MVPP2_GMAC_IN_BAND_AUTONEG_BYPASS);
        ctrl0 &= ~MVPP2_GMAC_PORT_TYPE_MASK;
        ctrl2 &= ~(MVPP2_GMAC_INBAND_AN_MASK | MVPP2_GMAC_PORT_RESET_MASK |
                   MVPP2_GMAC_PCS_ENABLE_MASK);
-       ctrl4 &= ~(MVPP22_CTRL4_RX_FC_EN | MVPP22_CTRL4_TX_FC_EN);
 
        /* Configure port type */
        if (phy_interface_mode_is_8023z(state->interface)) {
@@ -5014,31 +5012,20 @@ static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode,
 
        /* Configure negotiation style */
        if (!phylink_autoneg_inband(mode)) {
-               /* Phy or fixed speed - no in-band AN */
-               if (state->duplex)
-                       an |= MVPP2_GMAC_CONFIG_FULL_DUPLEX;
-
-               if (state->speed == SPEED_1000 || state->speed == SPEED_2500)
-                       an |= MVPP2_GMAC_CONFIG_GMII_SPEED;
-               else if (state->speed == SPEED_100)
-                       an |= MVPP2_GMAC_CONFIG_MII_SPEED;
-
-               if (state->pause & MLO_PAUSE_TX)
-                       ctrl4 |= MVPP22_CTRL4_TX_FC_EN;
-               if (state->pause & MLO_PAUSE_RX)
-                       ctrl4 |= MVPP22_CTRL4_RX_FC_EN;
+               /* Phy or fixed speed - no in-band AN, nothing to do, leave the
+                * configured speed, duplex and flow control as-is.
+                */
        } else if (state->interface == PHY_INTERFACE_MODE_SGMII) {
                /* SGMII in-band mode receives the speed and duplex from
                 * the PHY. Flow control information is not received. */
-               an &= ~(MVPP2_GMAC_FORCE_LINK_DOWN | MVPP2_GMAC_FORCE_LINK_PASS);
+               an &= ~(MVPP2_GMAC_FORCE_LINK_DOWN |
+                       MVPP2_GMAC_FORCE_LINK_PASS |
+                       MVPP2_GMAC_CONFIG_MII_SPEED |
+                       MVPP2_GMAC_CONFIG_GMII_SPEED |
+                       MVPP2_GMAC_CONFIG_FULL_DUPLEX);
                an |= MVPP2_GMAC_IN_BAND_AUTONEG |
                      MVPP2_GMAC_AN_SPEED_EN |
                      MVPP2_GMAC_AN_DUPLEX_EN;
-
-               if (state->pause & MLO_PAUSE_TX)
-                       ctrl4 |= MVPP22_CTRL4_TX_FC_EN;
-               if (state->pause & MLO_PAUSE_RX)
-                       ctrl4 |= MVPP22_CTRL4_RX_FC_EN;
        } else if (phy_interface_mode_is_8023z(state->interface)) {
                /* 1000BaseX and 2500BaseX ports cannot negotiate speed nor can
                 * they negotiate duplex: they are always operating with a fixed
@@ -5046,19 +5033,17 @@ static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode,
                 * speed and full duplex here.
                 */
                ctrl0 |= MVPP2_GMAC_PORT_TYPE_MASK;
-               an &= ~(MVPP2_GMAC_FORCE_LINK_DOWN | MVPP2_GMAC_FORCE_LINK_PASS);
+               an &= ~(MVPP2_GMAC_FORCE_LINK_DOWN |
+                       MVPP2_GMAC_FORCE_LINK_PASS |
+                       MVPP2_GMAC_CONFIG_MII_SPEED |
+                       MVPP2_GMAC_CONFIG_GMII_SPEED |
+                       MVPP2_GMAC_CONFIG_FULL_DUPLEX);
                an |= MVPP2_GMAC_IN_BAND_AUTONEG |
                      MVPP2_GMAC_CONFIG_GMII_SPEED |
                      MVPP2_GMAC_CONFIG_FULL_DUPLEX;
 
-               if (state->pause & MLO_PAUSE_AN && state->an_enabled) {
+               if (state->pause & MLO_PAUSE_AN && state->an_enabled)
                        an |= MVPP2_GMAC_FLOW_CTRL_AUTONEG;
-               } else {
-                       if (state->pause & MLO_PAUSE_TX)
-                               ctrl4 |= MVPP22_CTRL4_TX_FC_EN;
-                       if (state->pause & MLO_PAUSE_RX)
-                               ctrl4 |= MVPP22_CTRL4_RX_FC_EN;
-               }
        }
 
 /* Some fields of the auto-negotiation register require the port to be down when
@@ -5155,18 +5140,44 @@ static void mvpp2_mac_link_up(struct phylink_config *config,
        struct mvpp2_port *port = netdev_priv(dev);
        u32 val;
 
-       if (!phylink_autoneg_inband(mode)) {
-               if (mvpp2_is_xlg(interface)) {
+       if (mvpp2_is_xlg(interface)) {
+               if (!phylink_autoneg_inband(mode)) {
                        val = readl(port->base + MVPP22_XLG_CTRL0_REG);
                        val &= ~MVPP22_XLG_CTRL0_FORCE_LINK_DOWN;
                        val |= MVPP22_XLG_CTRL0_FORCE_LINK_PASS;
                        writel(val, port->base + MVPP22_XLG_CTRL0_REG);
-               } else {
+               }
+       } else {
+               if (!phylink_autoneg_inband(mode)) {
                        val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
-                       val &= ~MVPP2_GMAC_FORCE_LINK_DOWN;
+                       val &= ~(MVPP2_GMAC_FORCE_LINK_DOWN |
+                                MVPP2_GMAC_CONFIG_MII_SPEED |
+                                MVPP2_GMAC_CONFIG_GMII_SPEED |
+                                MVPP2_GMAC_CONFIG_FULL_DUPLEX);
                        val |= MVPP2_GMAC_FORCE_LINK_PASS;
+
+                       if (speed == SPEED_1000 || speed == SPEED_2500)
+                               val |= MVPP2_GMAC_CONFIG_GMII_SPEED;
+                       else if (speed == SPEED_100)
+                               val |= MVPP2_GMAC_CONFIG_MII_SPEED;
+
+                       if (duplex == DUPLEX_FULL)
+                               val |= MVPP2_GMAC_CONFIG_FULL_DUPLEX;
+
                        writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
                }
+
+               /* We can always update the flow control enable bits;
+                * these will only be effective if flow control AN
+                * (MVPP2_GMAC_FLOW_CTRL_AUTONEG) is disabled.
+                */
+               val = readl(port->base + MVPP22_GMAC_CTRL_4_REG);
+               val &= ~(MVPP22_CTRL4_RX_FC_EN | MVPP22_CTRL4_TX_FC_EN);
+               if (tx_pause)
+                       val |= MVPP22_CTRL4_TX_FC_EN;
+               if (rx_pause)
+                       val |= MVPP22_CTRL4_RX_FC_EN;
+               writel(val, port->base + MVPP22_GMAC_CTRL_4_REG);
        }
 
        mvpp2_port_enable(port);