[RFC PATCH net-next 05/20] net: dsa: mv88e6xxx: factorize MAC address setting
From: Vivien Didelot <hidden>
Date: 2016-05-05 22:45:51
Also in:
lkml
Subsystem:
networking drivers, networking [dsa], the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Andrew Lunn, Vladimir Oltean, Linus Torvalds
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 <redacted> --- 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