Add support for RGMII in 100 and 1000 Mbps.

Adjust the CPU port based on the host interface settings: interface
MII type, speed, duplex.

Signed-off-by: Jean Pihet <jean.pi...@newoldbits.com>
---
 drivers/net/dsa/microchip/ksz8795.c | 93 ++++++++++++++++++-----------
 1 file changed, 57 insertions(+), 36 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz8795.c 
b/drivers/net/dsa/microchip/ksz8795.c
index 1e101ab56cea..09c1173cc607 100644
--- a/drivers/net/dsa/microchip/ksz8795.c
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -916,10 +916,53 @@ static void ksz8795_port_mirror_del(struct dsa_switch 
*ds, int port,
                             PORT_MIRROR_SNIFFER, false);
 }
 
+static void ksz8795_mii_config(struct ksz_device *dev, struct ksz_port *p)
+{
+       u8 data8;
+
+       /* Configure MII interface for proper network communication. */
+       ksz_read8(dev, REG_PORT_5_CTRL_6, &data8);
+       data8 &= ~PORT_INTERFACE_TYPE;
+       data8 &= ~PORT_GMII_1GPS_MODE;
+       switch (p->interface) {
+       case PHY_INTERFACE_MODE_MII:
+               p->phydev.speed = SPEED_100;
+               break;
+       case PHY_INTERFACE_MODE_RMII:
+               data8 |= PORT_INTERFACE_RMII;
+               p->phydev.speed = SPEED_100;
+               break;
+       case PHY_INTERFACE_MODE_GMII:
+               data8 |= PORT_GMII_1GPS_MODE;
+               data8 |= PORT_INTERFACE_GMII;
+               p->phydev.speed = SPEED_1000;
+               break;
+       default:
+               data8 &= ~PORT_RGMII_ID_IN_ENABLE;
+               data8 &= ~PORT_RGMII_ID_OUT_ENABLE;
+               if (p->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+                   p->interface == PHY_INTERFACE_MODE_RGMII_RXID)
+                       data8 |= PORT_RGMII_ID_IN_ENABLE;
+               if (p->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+                   p->interface == PHY_INTERFACE_MODE_RGMII_TXID)
+                       data8 |= PORT_RGMII_ID_OUT_ENABLE;
+               /* Support RGMII in 100 and 1000 Mbps */
+               if (p->phydev.speed == SPEED_1000) {
+                       data8 |= PORT_GMII_1GPS_MODE;
+               } else {
+                       p->phydev.speed = SPEED_100;
+               }
+               data8 |= PORT_INTERFACE_RGMII;
+               break;
+       }
+       ksz_write8(dev, REG_PORT_5_CTRL_6, data8);
+       p->phydev.duplex = 1;
+}
+
 static void ksz8795_port_setup(struct ksz_device *dev, int port, bool cpu_port)
 {
        struct ksz_port *p = &dev->ports[port];
-       u8 data8, member;
+       u8 member;
 
        /* enable broadcast storm limit */
        ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, true);
@@ -943,41 +986,7 @@ static void ksz8795_port_setup(struct ksz_device *dev, int 
port, bool cpu_port)
                                 port);
                        p->interface = dev->compat_interface;
                }
-
-               /* Configure MII interface for proper network communication. */
-               ksz_read8(dev, REG_PORT_5_CTRL_6, &data8);
-               data8 &= ~PORT_INTERFACE_TYPE;
-               data8 &= ~PORT_GMII_1GPS_MODE;
-               switch (p->interface) {
-               case PHY_INTERFACE_MODE_MII:
-                       p->phydev.speed = SPEED_100;
-                       break;
-               case PHY_INTERFACE_MODE_RMII:
-                       data8 |= PORT_INTERFACE_RMII;
-                       p->phydev.speed = SPEED_100;
-                       break;
-               case PHY_INTERFACE_MODE_GMII:
-                       data8 |= PORT_GMII_1GPS_MODE;
-                       data8 |= PORT_INTERFACE_GMII;
-                       p->phydev.speed = SPEED_1000;
-                       break;
-               default:
-                       data8 &= ~PORT_RGMII_ID_IN_ENABLE;
-                       data8 &= ~PORT_RGMII_ID_OUT_ENABLE;
-                       if (p->interface == PHY_INTERFACE_MODE_RGMII_ID ||
-                           p->interface == PHY_INTERFACE_MODE_RGMII_RXID)
-                               data8 |= PORT_RGMII_ID_IN_ENABLE;
-                       if (p->interface == PHY_INTERFACE_MODE_RGMII_ID ||
-                           p->interface == PHY_INTERFACE_MODE_RGMII_TXID)
-                               data8 |= PORT_RGMII_ID_OUT_ENABLE;
-                       data8 |= PORT_GMII_1GPS_MODE;
-                       data8 |= PORT_INTERFACE_RGMII;
-                       p->phydev.speed = SPEED_1000;
-                       break;
-               }
-               ksz_write8(dev, REG_PORT_5_CTRL_6, data8);
-               p->phydev.duplex = 1;
-
+        ksz8795_mii_config(dev, p);
                member = dev->port_mask;
        } else {
                member = dev->host_mask | p->vid_member;
@@ -1102,11 +1111,23 @@ static int ksz8795_setup(struct dsa_switch *ds)
        return 0;
 }
 
+void ksz8795_adjust_link(struct dsa_switch *ds, int port,
+                                                struct phy_device *phydev)
+{
+       struct ksz_device *dev = ds->priv;
+       struct ksz_port *p = &dev->ports[port];
+
+       /* Adjust the link interface mode and speed for the CPU port */
+       if (port == dev->cpu_port)
+               ksz8795_mii_config(dev, p);
+}
+
 static const struct dsa_switch_ops ksz8795_switch_ops = {
        .get_tag_protocol       = ksz8795_get_tag_protocol,
        .setup                  = ksz8795_setup,
        .phy_read               = ksz_phy_read16,
        .phy_write              = ksz_phy_write16,
+       .adjust_link            = ksz8795_adjust_link,
        .phylink_mac_link_down  = ksz_mac_link_down,
        .port_enable            = ksz_enable_port,
        .get_strings            = ksz8795_get_strings,
-- 
2.26.2

Reply via email to