net: mvpp2: dynamic reconfiguration of the comphy/GoP/MAC
authorAntoine Tenart <antoine.tenart@free-electrons.com>
Wed, 30 Aug 2017 08:29:19 +0000 (10:29 +0200)
committerDavid S. Miller <davem@davemloft.net>
Wed, 30 Aug 2017 22:17:46 +0000 (15:17 -0700)
This patch adds logic to reconfigure the comphy/GoP/MAC when the link
state is updated at runtime. This is very useful on boards where many
link speed are supported: depending on what is negotiated the PPv2
driver will automatically reconfigures the link between the PHY and the
MAC.

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

index 670395235932a91cf8faf99a4dbfd4cabce648e6..358a9de9daa7ac71a8d730173facb3f889e54782 100644 (file)
@@ -5771,9 +5771,28 @@ static void mvpp2_link_event(struct net_device *dev)
 {
        struct mvpp2_port *port = netdev_priv(dev);
        struct phy_device *phydev = dev->phydev;
+       bool link_reconfigured = false;
        u32 val;
 
        if (phydev->link) {
+               if (port->phy_interface != phydev->interface && port->comphy) {
+                       /* disable current port for reconfiguration */
+                       mvpp2_interrupts_disable(port);
+                       netif_carrier_off(port->dev);
+                       mvpp2_port_disable(port);
+                       phy_power_off(port->comphy);
+
+                       /* comphy reconfiguration */
+                       port->phy_interface = phydev->interface;
+                       mvpp22_comphy_init(port);
+
+                       /* gop/mac reconfiguration */
+                       mvpp22_gop_init(port);
+                       mvpp2_port_mii_set(port);
+
+                       link_reconfigured = true;
+               }
+
                if ((port->speed != phydev->speed) ||
                    (port->duplex != phydev->duplex)) {
                        mvpp2_gmac_set_autoneg(port, phydev);
@@ -5783,7 +5802,7 @@ static void mvpp2_link_event(struct net_device *dev)
                }
        }
 
-       if (phydev->link != port->link) {
+       if (phydev->link != port->link || link_reconfigured) {
                port->link = phydev->link;
 
                if (phydev->link) {