net: dsa: microchip: lan937x: add phylink_mac_link_up support
authorArun Ramadoss <arun.ramadoss@microchip.com>
Fri, 1 Jul 2022 15:11:24 +0000 (20:41 +0530)
committerDavid S. Miller <davem@davemloft.net>
Sat, 2 Jul 2022 15:34:05 +0000 (16:34 +0100)
This patch add support for phylink_mac_link_up. It configures the mac
for the speed, flow control and duplex mode.

Signed-off-by: Arun Ramadoss <arun.ramadoss@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/microchip/ksz_common.c
drivers/net/dsa/microchip/ksz_common.h
drivers/net/dsa/microchip/lan937x.h
drivers/net/dsa/microchip/lan937x_main.c
drivers/net/dsa/microchip/lan937x_reg.h

index ca7ca32..9972b2f 100644 (file)
@@ -221,6 +221,7 @@ static const struct ksz_dev_ops lan937x_dev_ops = {
        .mirror_add = ksz9477_port_mirror_add,
        .mirror_del = ksz9477_port_mirror_del,
        .get_caps = lan937x_phylink_get_caps,
+       .phylink_mac_link_up = lan937x_phylink_mac_link_up,
        .fdb_dump = ksz9477_fdb_dump,
        .fdb_add = ksz9477_fdb_add,
        .fdb_del = ksz9477_fdb_del,
@@ -1340,6 +1341,20 @@ static int ksz_max_mtu(struct dsa_switch *ds, int port)
        return dev->dev_ops->max_mtu(dev, port);
 }
 
+static void ksz_phylink_mac_link_up(struct dsa_switch *ds, int port,
+                                   unsigned int mode,
+                                   phy_interface_t interface,
+                                   struct phy_device *phydev, int speed,
+                                   int duplex, bool tx_pause, bool rx_pause)
+{
+       struct ksz_device *dev = ds->priv;
+
+       if (dev->dev_ops->phylink_mac_link_up)
+               dev->dev_ops->phylink_mac_link_up(dev, port, mode, interface,
+                                                 phydev, speed, duplex,
+                                                 tx_pause, rx_pause);
+}
+
 static int ksz_switch_detect(struct ksz_device *dev)
 {
        u8 id1, id2;
@@ -1413,6 +1428,7 @@ static const struct dsa_switch_ops ksz_switch_ops = {
        .phy_read               = ksz_phy_read16,
        .phy_write              = ksz_phy_write16,
        .phylink_get_caps       = ksz_phylink_get_caps,
+       .phylink_mac_link_up    = ksz_phylink_mac_link_up,
        .phylink_mac_link_down  = ksz_mac_link_down,
        .port_enable            = ksz_enable_port,
        .get_strings            = ksz_get_strings,
index bf4f3f3..f449fea 100644 (file)
@@ -271,6 +271,11 @@ struct ksz_dev_ops {
        int (*max_mtu)(struct ksz_device *dev, int port);
        void (*freeze_mib)(struct ksz_device *dev, int port, bool freeze);
        void (*port_init_cnt)(struct ksz_device *dev, int port);
+       void (*phylink_mac_link_up)(struct ksz_device *dev, int port,
+                                   unsigned int mode,
+                                   phy_interface_t interface,
+                                   struct phy_device *phydev, int speed,
+                                   int duplex, bool tx_pause, bool rx_pause);
        void (*config_cpu_port)(struct dsa_switch *ds);
        int (*enable_stp_addr)(struct ksz_device *dev);
        int (*reset)(struct ksz_device *dev);
index d4207e9..145770a 100644 (file)
@@ -17,4 +17,8 @@ void lan937x_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val);
 int lan937x_change_mtu(struct ksz_device *dev, int port, int new_mtu);
 void lan937x_phylink_get_caps(struct ksz_device *dev, int port,
                              struct phylink_config *config);
+void lan937x_phylink_mac_link_up(struct ksz_device *dev, int port,
+                                unsigned int mode, phy_interface_t interface,
+                                struct phy_device *phydev, int speed,
+                                int duplex, bool tx_pause, bool rx_pause);
 #endif
index 8cb46ca..2f480bf 100644 (file)
@@ -312,6 +312,39 @@ int lan937x_change_mtu(struct ksz_device *dev, int port, int new_mtu)
        return 0;
 }
 
+static void lan937x_config_interface(struct ksz_device *dev, int port,
+                                    int speed, int duplex,
+                                    bool tx_pause, bool rx_pause)
+{
+       u8 xmii_ctrl0, xmii_ctrl1;
+
+       ksz_pread8(dev, port, REG_PORT_XMII_CTRL_0, &xmii_ctrl0);
+       ksz_pread8(dev, port, REG_PORT_XMII_CTRL_1, &xmii_ctrl1);
+
+       xmii_ctrl0 &= ~(PORT_MII_100MBIT | PORT_MII_FULL_DUPLEX |
+                       PORT_MII_TX_FLOW_CTRL | PORT_MII_RX_FLOW_CTRL);
+
+       if (speed == SPEED_1000)
+               xmii_ctrl1 &= ~PORT_MII_NOT_1GBIT;
+       else
+               xmii_ctrl1 |= PORT_MII_NOT_1GBIT;
+
+       if (speed == SPEED_100)
+               xmii_ctrl0 |= PORT_MII_100MBIT;
+
+       if (duplex)
+               xmii_ctrl0 |= PORT_MII_FULL_DUPLEX;
+
+       if (tx_pause)
+               xmii_ctrl0 |= PORT_MII_TX_FLOW_CTRL;
+
+       if (rx_pause)
+               xmii_ctrl0 |= PORT_MII_RX_FLOW_CTRL;
+
+       ksz_pwrite8(dev, port, REG_PORT_XMII_CTRL_0, xmii_ctrl0);
+       ksz_pwrite8(dev, port, REG_PORT_XMII_CTRL_1, xmii_ctrl1);
+}
+
 void lan937x_phylink_get_caps(struct ksz_device *dev, int port,
                              struct phylink_config *config)
 {
@@ -324,6 +357,19 @@ void lan937x_phylink_get_caps(struct ksz_device *dev, int port,
        }
 }
 
+void lan937x_phylink_mac_link_up(struct ksz_device *dev, int port,
+                                unsigned int mode, phy_interface_t interface,
+                                struct phy_device *phydev, int speed,
+                                int duplex, bool tx_pause, bool rx_pause)
+{
+       /* Internal PHYs */
+       if (dev->info->internal_phy[port])
+               return;
+
+       lan937x_config_interface(dev, port, speed, duplex,
+                                tx_pause, rx_pause);
+}
+
 int lan937x_setup(struct dsa_switch *ds)
 {
        struct ksz_device *dev = ds->priv;
index 19f3aa3..c187d0a 100644 (file)
 #define PORT_MII_RX_FLOW_CTRL          BIT(3)
 #define PORT_GRXC_ENABLE               BIT(0)
 
+#define REG_PORT_XMII_CTRL_1           0x0301
+#define PORT_MII_NOT_1GBIT             BIT(6)
+#define PORT_MII_SEL_EDGE              BIT(5)
+#define PORT_RGMII_ID_IG_ENABLE                BIT(4)
+#define PORT_RGMII_ID_EG_ENABLE                BIT(3)
+#define PORT_MII_MAC_MODE              BIT(2)
+#define PORT_MII_SEL_M                 0x3
+#define PORT_RGMII_SEL                 0x0
+#define PORT_RMII_SEL                  0x1
+#define PORT_MII_SEL                   0x2
+
 /* 4 - MAC */
 #define REG_PORT_MAC_CTRL_0            0x0400
 #define PORT_CHECK_LENGTH              BIT(2)