Some switch has dedicated SMI PHY Command and Data registers, used to indirectly access the PHYs, instead of direct access.
Identify these switch models and make mv88e6xxx_phy_{read,write} generic enough to support every models. Signed-off-by: Vivien Didelot <vivien.dide...@savoirfairelinux.com> --- drivers/net/dsa/mv88e6171.c | 8 ++++++-- drivers/net/dsa/mv88e6352.c | 10 ++++++++-- drivers/net/dsa/mv88e6xxx.c | 37 ++++--------------------------------- drivers/net/dsa/mv88e6xxx.h | 10 +++++++--- 4 files changed, 25 insertions(+), 40 deletions(-) diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index f75164d..304e25e 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -24,24 +24,28 @@ static const struct mv88e6xxx_info mv88e6171_table[] = { .name = "Marvell 88E6171", .num_databases = 4096, .num_ports = 7, + .flags = MV88E6XXX_FLAG_SMI_PHY, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6175, .family = MV88E6XXX_FAMILY_6351, .name = "Marvell 88E6175", .num_databases = 4096, .num_ports = 7, + .flags = MV88E6XXX_FLAG_SMI_PHY, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6350, .family = MV88E6XXX_FAMILY_6351, .name = "Marvell 88E6350", .num_databases = 4096, .num_ports = 7, + .flags = MV88E6XXX_FLAG_SMI_PHY, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6351, .family = MV88E6XXX_FAMILY_6351, .name = "Marvell 88E6351", .num_databases = 4096, .num_ports = 7, + .flags = MV88E6XXX_FLAG_SMI_PHY, } }; @@ -120,8 +124,8 @@ struct dsa_switch_driver mv88e6171_switch_driver = { .probe = mv88e6171_drv_probe, .setup = mv88e6171_setup, .set_addr = mv88e6xxx_set_addr_indirect, - .phy_read = mv88e6xxx_phy_read_indirect, - .phy_write = mv88e6xxx_phy_write_indirect, + .phy_read = mv88e6xxx_phy_read, + .phy_write = mv88e6xxx_phy_write, .get_strings = mv88e6xxx_get_strings, .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, .get_sset_count = mv88e6xxx_get_sset_count, diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index c622a1d..df9f944 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -29,36 +29,42 @@ static const struct mv88e6xxx_info mv88e6352_table[] = { .name = "Marvell 88E6320", .num_databases = 4096, .num_ports = 7, + .flags = MV88E6XXX_FLAG_SMI_PHY, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6321, .family = MV88E6XXX_FAMILY_6320, .name = "Marvell 88E6321", .num_databases = 4096, .num_ports = 7, + .flags = MV88E6XXX_FLAG_SMI_PHY, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6172, .family = MV88E6XXX_FAMILY_6352, .name = "Marvell 88E6172", .num_databases = 4096, .num_ports = 7, + .flags = MV88E6XXX_FLAG_SMI_PHY, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6176, .family = MV88E6XXX_FAMILY_6352, .name = "Marvell 88E6176", .num_databases = 4096, .num_ports = 7, + .flags = MV88E6XXX_FLAG_SMI_PHY, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6240, .family = MV88E6XXX_FAMILY_6352, .name = "Marvell 88E6240", .num_databases = 4096, .num_ports = 7, + .flags = MV88E6XXX_FLAG_SMI_PHY, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6352, .family = MV88E6XXX_FAMILY_6352, .name = "Marvell 88E6352", .num_databases = 4096, .num_ports = 7, + .flags = MV88E6XXX_FLAG_SMI_PHY, } }; @@ -338,8 +344,8 @@ struct dsa_switch_driver mv88e6352_switch_driver = { .probe = mv88e6352_drv_probe, .setup = mv88e6352_setup, .set_addr = mv88e6xxx_set_addr_indirect, - .phy_read = mv88e6xxx_phy_read_indirect, - .phy_write = mv88e6xxx_phy_write_indirect, + .phy_read = mv88e6xxx_phy_read, + .phy_write = mv88e6xxx_phy_write, .get_strings = mv88e6xxx_get_strings, .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, .get_sset_count = mv88e6xxx_get_sset_count, diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 4e031aa..e48271c 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -2868,6 +2868,8 @@ mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum) if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU)) ret = _mv88e6xxx_phy_read_ppu(ps, addr, regnum); + else if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_SMI_PHY)) + ret = _mv88e6xxx_phy_read_indirect(ps, addr, regnum); else ret = _mv88e6xxx_phy_read(ps, addr, regnum); @@ -2891,6 +2893,8 @@ mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU)) err = _mv88e6xxx_phy_write_ppu(ps, addr, regnum, val); + else if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_SMI_PHY)) + err = _mv88e6xxx_phy_write_indirect(ps, addr, regnum, val); else err = _mv88e6xxx_phy_write(ps, addr, regnum, val); @@ -2899,39 +2903,6 @@ mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) return err; } -int -mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum) -{ - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - int addr = mv88e6xxx_port_to_phy_addr(ps, port); - int ret; - - if (addr < 0) - return 0xffff; - - mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_phy_read_indirect(ps, addr, regnum); - mutex_unlock(&ps->smi_mutex); - return ret; -} - -int -mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum, - u16 val) -{ - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - int addr = mv88e6xxx_port_to_phy_addr(ps, port); - int ret; - - if (addr < 0) - return addr; - - mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_phy_write_indirect(ps, addr, regnum, val); - mutex_unlock(&ps->smi_mutex); - return ret; -} - #ifdef CONFIG_NET_DSA_HWMON static int mv88e61xx_get_temp(struct dsa_switch *ds, int *temp) diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 3e77985..95cbb8b 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -355,10 +355,17 @@ enum mv88e6xxx_cap { * See GLOBAL_CONTROL_PPU_ENABLE and GLOBAL_STATUS_PPU_POLLING. */ MV88E6XXX_CAP_PPU, + + /* SMI PHY Command and Data registers. + * This requires an indirect access to PHY registers through + * GLOBAL2_SMI_OP, otherwise direct access to PHY registers is done. + */ + MV88E6XXX_CAP_SMI_PHY, }; /* Bitmask of capabilities */ #define MV88E6XXX_FLAG_PPU BIT(MV88E6XXX_CAP_PPU) +#define MV88E6XXX_FLAG_SMI_PHY BIT(MV88E6XXX_CAP_SMI_PHY) struct mv88e6xxx_info { enum mv88e6xxx_family family; @@ -480,9 +487,6 @@ int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr); int mv88e6xxx_set_addr_indirect(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); -int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum); -int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum, - u16 val); void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data); void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data); -- 2.8.2