Some switch models have a dedicated register for Switch MAC/WoF/WoL.
This register, when present, is used to indirectly set the switch MAC
address, instead of a direct write to 3 global registers.

Identify this feature and share a common mv88e6xxx_set_addr function.

Signed-off-by: Vivien Didelot <vivien.dide...@savoirfairelinux.com>
---
 drivers/net/dsa/mv88e6123.c |  11 +++--
 drivers/net/dsa/mv88e6131.c |   2 +-
 drivers/net/dsa/mv88e6171.c |   6 ++-
 drivers/net/dsa/mv88e6352.c |   8 ++-
 drivers/net/dsa/mv88e6xxx.c | 115 ++++++++++++++++++++++++--------------------
 drivers/net/dsa/mv88e6xxx.h |  11 ++++-
 6 files changed, 92 insertions(+), 61 deletions(-)

diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 6f4f719..57a6d76 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -24,21 +24,24 @@ static const struct mv88e6xxx_info mv88e6123_table[] = {
                .name = "Marvell 88E6123",
                .num_databases = 4096,
                .num_ports = 3,
-               .flags = MV88E6XXX_FLAG_TEMP,
+               .flags = MV88E6XXX_FLAG_SWITCH_MAC |
+                       MV88E6XXX_FLAG_TEMP,
        }, {
                .prod_num = PORT_SWITCH_ID_PROD_NUM_6161,
                .family = MV88E6XXX_FAMILY_6165,
                .name = "Marvell 88E6161",
                .num_databases = 4096,
                .num_ports = 6,
-               .flags = MV88E6XXX_FLAG_TEMP,
+               .flags = MV88E6XXX_FLAG_SWITCH_MAC |
+                       MV88E6XXX_FLAG_TEMP,
        }, {
                .prod_num = PORT_SWITCH_ID_PROD_NUM_6165,
                .family = MV88E6XXX_FAMILY_6165,
                .name = "Marvell 88E6165",
                .num_databases = 4096,
                .num_ports = 6,
-               .flags = MV88E6XXX_FLAG_TEMP,
+               .flags = MV88E6XXX_FLAG_SWITCH_MAC |
+                       MV88E6XXX_FLAG_TEMP,
        }
 };
 
@@ -114,7 +117,7 @@ struct dsa_switch_driver mv88e6123_switch_driver = {
        .tag_protocol           = DSA_TAG_PROTO_EDSA,
        .probe                  = mv88e6123_drv_probe,
        .setup                  = mv88e6123_setup,
-       .set_addr               = mv88e6xxx_set_addr_indirect,
+       .set_addr               = mv88e6xxx_set_addr,
        .phy_read               = mv88e6xxx_phy_read,
        .phy_write              = mv88e6xxx_phy_write,
        .get_strings            = mv88e6xxx_get_strings,
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index e8eb9a6..519d1eb 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -147,7 +147,7 @@ struct dsa_switch_driver mv88e6131_switch_driver = {
        .tag_protocol           = DSA_TAG_PROTO_DSA,
        .probe                  = mv88e6131_drv_probe,
        .setup                  = mv88e6131_setup,
-       .set_addr               = mv88e6xxx_set_addr_direct,
+       .set_addr               = mv88e6xxx_set_addr,
        .phy_read               = mv88e6xxx_phy_read,
        .phy_write              = mv88e6xxx_phy_write,
        .get_strings            = mv88e6xxx_get_strings,
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index bd2082e..f947950 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -25,6 +25,7 @@ static const struct mv88e6xxx_info mv88e6171_table[] = {
                .num_databases = 4096,
                .num_ports = 7,
                .flags = MV88E6XXX_FLAG_SMI_PHY |
+                       MV88E6XXX_FLAG_SWITCH_MAC |
                        MV88E6XXX_FLAG_TEMP,
        }, {
                .prod_num = PORT_SWITCH_ID_PROD_NUM_6175,
@@ -33,6 +34,7 @@ static const struct mv88e6xxx_info mv88e6171_table[] = {
                .num_databases = 4096,
                .num_ports = 7,
                .flags = MV88E6XXX_FLAG_SMI_PHY |
+                       MV88E6XXX_FLAG_SWITCH_MAC |
                        MV88E6XXX_FLAG_TEMP,
        }, {
                .prod_num = PORT_SWITCH_ID_PROD_NUM_6350,
@@ -41,6 +43,7 @@ static const struct mv88e6xxx_info mv88e6171_table[] = {
                .num_databases = 4096,
                .num_ports = 7,
                .flags = MV88E6XXX_FLAG_SMI_PHY |
+                       MV88E6XXX_FLAG_SWITCH_MAC |
                        MV88E6XXX_FLAG_TEMP,
        }, {
                .prod_num = PORT_SWITCH_ID_PROD_NUM_6351,
@@ -49,6 +52,7 @@ static const struct mv88e6xxx_info mv88e6171_table[] = {
                .num_databases = 4096,
                .num_ports = 7,
                .flags = MV88E6XXX_FLAG_SMI_PHY |
+                       MV88E6XXX_FLAG_SWITCH_MAC |
                        MV88E6XXX_FLAG_TEMP,
        }
 };
@@ -127,7 +131,7 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
        .tag_protocol           = DSA_TAG_PROTO_EDSA,
        .probe                  = mv88e6171_drv_probe,
        .setup                  = mv88e6171_setup,
-       .set_addr               = mv88e6xxx_set_addr_indirect,
+       .set_addr               = mv88e6xxx_set_addr,
        .phy_read               = mv88e6xxx_phy_read,
        .phy_write              = mv88e6xxx_phy_write,
        .get_strings            = mv88e6xxx_get_strings,
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index f588e2f..90732da 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -31,6 +31,7 @@ static const struct mv88e6xxx_info mv88e6352_table[] = {
                .num_ports = 7,
                .flags = MV88E6XXX_FLAG_EEPROM |
                        MV88E6XXX_FLAG_SMI_PHY |
+                       MV88E6XXX_FLAG_SWITCH_MAC |
                        MV88E6XXX_FLAG_TEMP |
                        MV88E6XXX_FLAG_TEMP_LIMIT,
        }, {
@@ -41,6 +42,7 @@ static const struct mv88e6xxx_info mv88e6352_table[] = {
                .num_ports = 7,
                .flags = MV88E6XXX_FLAG_EEPROM |
                        MV88E6XXX_FLAG_SMI_PHY |
+                       MV88E6XXX_FLAG_SWITCH_MAC |
                        MV88E6XXX_FLAG_TEMP |
                        MV88E6XXX_FLAG_TEMP_LIMIT,
        }, {
@@ -51,6 +53,7 @@ static const struct mv88e6xxx_info mv88e6352_table[] = {
                .num_ports = 7,
                .flags = MV88E6XXX_FLAG_EEPROM |
                        MV88E6XXX_FLAG_SMI_PHY |
+                       MV88E6XXX_FLAG_SWITCH_MAC |
                        MV88E6XXX_FLAG_TEMP |
                        MV88E6XXX_FLAG_TEMP_LIMIT,
        }, {
@@ -61,6 +64,7 @@ static const struct mv88e6xxx_info mv88e6352_table[] = {
                .num_ports = 7,
                .flags = MV88E6XXX_FLAG_EEPROM |
                        MV88E6XXX_FLAG_SMI_PHY |
+                       MV88E6XXX_FLAG_SWITCH_MAC |
                        MV88E6XXX_FLAG_TEMP |
                        MV88E6XXX_FLAG_TEMP_LIMIT,
        }, {
@@ -71,6 +75,7 @@ static const struct mv88e6xxx_info mv88e6352_table[] = {
                .num_ports = 7,
                .flags = MV88E6XXX_FLAG_EEPROM |
                        MV88E6XXX_FLAG_SMI_PHY |
+                       MV88E6XXX_FLAG_SWITCH_MAC |
                        MV88E6XXX_FLAG_TEMP |
                        MV88E6XXX_FLAG_TEMP_LIMIT,
        }, {
@@ -81,6 +86,7 @@ static const struct mv88e6xxx_info mv88e6352_table[] = {
                .num_ports = 7,
                .flags = MV88E6XXX_FLAG_EEPROM |
                        MV88E6XXX_FLAG_SMI_PHY |
+                       MV88E6XXX_FLAG_SWITCH_MAC |
                        MV88E6XXX_FLAG_TEMP |
                        MV88E6XXX_FLAG_TEMP_LIMIT,
        }
@@ -158,7 +164,7 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
        .tag_protocol           = DSA_TAG_PROTO_EDSA,
        .probe                  = mv88e6352_drv_probe,
        .setup                  = mv88e6352_setup,
-       .set_addr               = mv88e6xxx_set_addr_indirect,
+       .set_addr               = mv88e6xxx_set_addr,
        .phy_read               = mv88e6xxx_phy_read,
        .phy_write              = mv88e6xxx_phy_write,
        .get_strings            = mv88e6xxx_get_strings,
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 5f7851e..5483e69 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -173,58 +173,6 @@ int mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, 
int addr,
        return ret;
 }
 
-int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr)
-{
-       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-       int err;
-
-       err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MAC_01,
-                                 (addr[0] << 8) | addr[1]);
-       if (err)
-               return err;
-
-       err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MAC_23,
-                                 (addr[2] << 8) | addr[3]);
-       if (err)
-               return err;
-
-       return mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MAC_45,
-                                  (addr[4] << 8) | addr[5]);
-}
-
-int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
-{
-       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-       int ret;
-       int i;
-
-       for (i = 0; i < 6; i++) {
-               int j;
-
-               /* Write the MAC address byte. */
-               ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_SWITCH_MAC,
-                                         GLOBAL2_SWITCH_MAC_BUSY |
-                                         (i << 8) | addr[i]);
-               if (ret)
-                       return ret;
-
-               /* Wait for the write to complete. */
-               for (j = 0; j < 16; j++) {
-                       ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2,
-                                                GLOBAL2_SWITCH_MAC);
-                       if (ret < 0)
-                               return ret;
-
-                       if ((ret & GLOBAL2_SWITCH_MAC_BUSY) == 0)
-                               break;
-               }
-               if (j == 16)
-                       return -ETIMEDOUT;
-       }
-
-       return 0;
-}
-
 static int _mv88e6xxx_phy_read(struct mv88e6xxx_priv_state *ps, int addr,
                               int regnum)
 {
@@ -1131,6 +1079,69 @@ out:
        return ret;
 }
 
+static int _mv88e6xxx_set_addr_direct(struct mv88e6xxx_priv_state *ps, u8 
*addr)
+{
+       int err;
+
+       err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MAC_01,
+                                  (addr[0] << 8) | addr[1]);
+       if (err)
+               return err;
+
+       err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MAC_23,
+                                  (addr[2] << 8) | addr[3]);
+       if (err)
+               return err;
+
+       return _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MAC_45,
+                                   (addr[4] << 8) | addr[5]);
+}
+
+static int _mv88e6xxx_switch_mac_wait(struct mv88e6xxx_priv_state *ps)
+{
+       return _mv88e6xxx_wait(ps, REG_GLOBAL2, GLOBAL2_SWITCH_MAC,
+                              GLOBAL2_SWITCH_MAC_BUSY);
+}
+
+static int _mv88e6xxx_set_addr_indirect(struct mv88e6xxx_priv_state *ps,
+                                       u8 *addr)
+{
+       int i, err;
+
+       for (i = 0; i < 6; i++) {
+               /* Write the MAC address byte. */
+               err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_SWITCH_MAC,
+                                          GLOBAL2_SWITCH_MAC_BUSY |
+                                          (i << 8) | addr[i]);
+               if (err)
+                       break;
+
+               /* Wait for the write to complete. */
+               err = _mv88e6xxx_switch_mac_wait(ps);
+               if (err)
+                       break;
+       }
+
+       return err;
+}
+
+int mv88e6xxx_set_addr(struct dsa_switch *ds, u8 *addr)
+{
+       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+       int err;
+
+       mutex_lock(&ps->smi_mutex);
+
+       if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_SWITCH_MAC))
+               err = _mv88e6xxx_set_addr_indirect(ps, addr);
+       else
+               err = _mv88e6xxx_set_addr_direct(ps, addr);
+
+       mutex_unlock(&ps->smi_mutex);
+
+       return err;
+}
+
 static int _mv88e6xxx_atu_cmd(struct mv88e6xxx_priv_state *ps, u16 fid, u16 
cmd)
 {
        int ret;
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index e7c2e45..72b563e 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -367,6 +367,13 @@ enum mv88e6xxx_cap {
         */
        MV88E6XXX_CAP_SMI_PHY,
 
+       /* Switch MAC/WoL/WoF register.
+        * This requires an indirect access to set the switch MAC address
+        * through GLOBAL2_SWITCH_MAC, otherwise GLOBAL_MAC_01, GLOBAL_MAC_23,
+        * and GLOBAL_MAC_45 are used with a direct access.
+        */
+       MV88E6XXX_CAP_SWITCH_MAC_WOL_WOF,
+
        /* Internal temperature sensor.
         * Available from any enabled port's PHY register 26, page 6.
         */
@@ -378,6 +385,7 @@ enum mv88e6xxx_cap {
 #define MV88E6XXX_FLAG_EEPROM          BIT(MV88E6XXX_CAP_EEPROM)
 #define MV88E6XXX_FLAG_PPU             BIT(MV88E6XXX_CAP_PPU)
 #define MV88E6XXX_FLAG_SMI_PHY         BIT(MV88E6XXX_CAP_SMI_PHY)
+#define MV88E6XXX_FLAG_SWITCH_MAC      BIT(MV88E6XXX_CAP_SWITCH_MAC_WOL_WOF)
 #define MV88E6XXX_FLAG_TEMP            BIT(MV88E6XXX_CAP_TEMP)
 #define MV88E6XXX_FLAG_TEMP_LIMIT      BIT(MV88E6XXX_CAP_TEMP_LIMIT)
 
@@ -497,8 +505,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds);
 int mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps, int addr, int reg);
 int mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
                        int reg, u16 val);
-int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr);
-int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr);
+int mv88e6xxx_set_addr(struct dsa_switch *ds, u8 *addr);
 int mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum);
 int mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val);
 void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data);
-- 
2.8.2

Reply via email to