net: dsa: microchip: add the support for set_ageing_time
authorArun Ramadoss <arun.ramadoss@microchip.com>
Wed, 7 Sep 2022 07:20:39 +0000 (12:50 +0530)
committerDavid S. Miller <davem@davemloft.net>
Fri, 16 Sep 2022 20:51:47 +0000 (21:51 +0100)
KSZ9477 has the 11 bit ageing count value which is split across the two
registers. And LAN937x has the 20 bit ageing count which is also split
into two registers. Each count in the registers represents 1 second.
This patch add the support for ageing time for KSZ9477 and LAN937x
series of switch.

Signed-off-by: Arun Ramadoss <arun.ramadoss@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/microchip/ksz9477.c
drivers/net/dsa/microchip/ksz9477.h
drivers/net/dsa/microchip/ksz9477_reg.h
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 42d7e4c1245942813cc0422bce62f6f5894a9e58..a6a0321a89310374b52e2d7dd42bdca2e333814a 100644 (file)
@@ -963,6 +963,31 @@ void ksz9477_get_caps(struct ksz_device *dev, int port,
                config->mac_capabilities |= MAC_1000FD;
 }
 
+int ksz9477_set_ageing_time(struct ksz_device *dev, unsigned int msecs)
+{
+       u32 secs = msecs / 1000;
+       u8 value;
+       u8 data;
+       int ret;
+
+       value = FIELD_GET(SW_AGE_PERIOD_7_0_M, secs);
+
+       ret = ksz_write8(dev, REG_SW_LUE_CTRL_3, value);
+       if (ret < 0)
+               return ret;
+
+       data = FIELD_GET(SW_AGE_PERIOD_10_8_M, secs);
+
+       ret = ksz_read8(dev, REG_SW_LUE_CTRL_0, &value);
+       if (ret < 0)
+               return ret;
+
+       value &= ~SW_AGE_CNT_M;
+       value |= FIELD_PREP(SW_AGE_CNT_M, data);
+
+       return ksz_write8(dev, REG_SW_LUE_CTRL_0, value);
+}
+
 void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
 {
        struct dsa_switch *ds = dev->ds;
index ce87e4e09ada8ac766dda3c7a6105c9fe6bbfbd6..00862c4cfb7f1e222ac8cc3e237c487cbfbbfed6 100644 (file)
@@ -16,6 +16,7 @@ u32 ksz9477_get_port_addr(int port, int offset);
 void ksz9477_cfg_port_member(struct ksz_device *dev, int port, u8 member);
 void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port);
 void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port);
+int ksz9477_set_ageing_time(struct ksz_device *dev, unsigned int msecs);
 int ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data);
 int ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val);
 void ksz9477_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt);
index ddf99d1e4bbd32812be38778535d92631774e8fc..53c68d286dd3ad893199a6525b0d458d2abe0d1c 100644 (file)
 
 #define SW_VLAN_ENABLE                 BIT(7)
 #define SW_DROP_INVALID_VID            BIT(6)
-#define SW_AGE_CNT_M                   0x7
+#define SW_AGE_CNT_M                   GENMASK(5, 3)
 #define SW_AGE_CNT_S                   3
+#define SW_AGE_PERIOD_10_8_M           GENMASK(10, 8)
 #define SW_RESV_MCAST_ENABLE           BIT(2)
 #define SW_HASH_OPTION_M               0x03
 #define SW_HASH_OPTION_CRC             1
 #define SW_PRIO_LOWEST_DA_SA           3
 
 #define REG_SW_LUE_CTRL_3              0x0313
+#define SW_AGE_PERIOD_7_0_M            GENMASK(7, 0)
 
 #define REG_SW_LUE_INT_STATUS          0x0314
 #define REG_SW_LUE_INT_ENABLE          0x0315
index 3b3b2046da2eddadb72b13620808590bd4de27b7..fcaa71f66322d4a4b64f93e19bd43bf28d76032f 100644 (file)
@@ -183,6 +183,7 @@ static const struct ksz_dev_ops ksz9477_dev_ops = {
        .cfg_port_member = ksz9477_cfg_port_member,
        .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
        .port_setup = ksz9477_port_setup,
+       .set_ageing_time = ksz9477_set_ageing_time,
        .r_phy = ksz9477_r_phy,
        .w_phy = ksz9477_w_phy,
        .r_mib_cnt = ksz9477_r_mib_cnt,
@@ -218,6 +219,7 @@ static const struct ksz_dev_ops lan937x_dev_ops = {
        .cfg_port_member = ksz9477_cfg_port_member,
        .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
        .port_setup = lan937x_port_setup,
+       .set_ageing_time = lan937x_set_ageing_time,
        .r_phy = lan937x_r_phy,
        .w_phy = lan937x_w_phy,
        .r_mib_cnt = ksz9477_r_mib_cnt,
@@ -1893,6 +1895,16 @@ static void ksz_port_fast_age(struct dsa_switch *ds, int port)
        dev->dev_ops->flush_dyn_mac_table(dev, port);
 }
 
+static int ksz_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)
+{
+       struct ksz_device *dev = ds->priv;
+
+       if (!dev->dev_ops->set_ageing_time)
+               return -EOPNOTSUPP;
+
+       return dev->dev_ops->set_ageing_time(dev, msecs);
+}
+
 static int ksz_port_fdb_add(struct dsa_switch *ds, int port,
                            const unsigned char *addr, u16 vid,
                            struct dsa_db db)
@@ -2475,6 +2487,7 @@ static const struct dsa_switch_ops ksz_switch_ops = {
        .phylink_mac_link_up    = ksz_phylink_mac_link_up,
        .phylink_mac_link_down  = ksz_mac_link_down,
        .port_enable            = ksz_enable_port,
+       .set_ageing_time        = ksz_set_ageing_time,
        .get_strings            = ksz_get_strings,
        .get_ethtool_stats      = ksz_get_ethtool_stats,
        .get_sset_count         = ksz_sset_count,
index 7c63f900dfcebc4827875d7e51f25d26977acbab..6203dcd8c8f73d42a9dd683e7ad80b8d9e1200e9 100644 (file)
@@ -281,6 +281,7 @@ struct ksz_dev_ops {
        void (*flush_dyn_mac_table)(struct ksz_device *dev, int port);
        void (*port_cleanup)(struct ksz_device *dev, int port);
        void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port);
+       int (*set_ageing_time)(struct ksz_device *dev, unsigned int msecs);
        int (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
        int (*w_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
        void (*r_mib_cnt)(struct ksz_device *dev, int port, u16 addr,
index 1b7f077946f3b8aeea2e1578439bad48a827da7c..8e9e66d6728d64c3ab93cc4dee8c5716ec6f6ec9 100644 (file)
@@ -19,4 +19,5 @@ 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_setup_rgmii_delay(struct ksz_device *dev, int port);
+int lan937x_set_ageing_time(struct ksz_device *dev, unsigned int msecs);
 #endif
index 4867aa62dd4cdd7605c4c97463fd5cd420c15ee2..9b6760b1e572300a15345ef48f0332085eda994e 100644 (file)
@@ -367,6 +367,23 @@ int lan937x_change_mtu(struct ksz_device *dev, int port, int new_mtu)
        return 0;
 }
 
+int lan937x_set_ageing_time(struct ksz_device *dev, unsigned int msecs)
+{
+       u32 secs = msecs / 1000;
+       u32 value;
+       int ret;
+
+       value = FIELD_GET(SW_AGE_PERIOD_7_0_M, secs);
+
+       ret = ksz_write8(dev, REG_SW_AGE_PERIOD__1, value);
+       if (ret < 0)
+               return ret;
+
+       value = FIELD_GET(SW_AGE_PERIOD_19_8_M, secs);
+
+       return ksz_write16(dev, REG_SW_AGE_PERIOD__2, value);
+}
+
 static void lan937x_set_tune_adj(struct ksz_device *dev, int port,
                                 u16 reg, u8 val)
 {
index a3c669d86e512ad96ea262bf1020ebcbb5884c5b..5bc16a4c444165d20dca63e389aa351ec5085dec 100644 (file)
 #define SW_FAST_AGING                  BIT(1)
 #define SW_LINK_AUTO_AGING             BIT(0)
 
+#define REG_SW_AGE_PERIOD__1           0x0313
+#define SW_AGE_PERIOD_7_0_M            GENMASK(7, 0)
+
+#define REG_SW_AGE_PERIOD__2           0x0320
+#define SW_AGE_PERIOD_19_8_M           GENMASK(19, 8)
+
 #define REG_SW_MAC_CTRL_0              0x0330
 #define SW_NEW_BACKOFF                 BIT(7)
 #define SW_PAUSE_UNH_MODE              BIT(1)