Commit 6d5834a1 authored by Vivien Didelot's avatar Vivien Didelot Committed by David S. Miller

net: dsa: mv88e6xxx: factorize PHY indirect access

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: default avatarVivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8c9983a2
...@@ -124,8 +124,8 @@ struct dsa_switch_driver mv88e6171_switch_driver = { ...@@ -124,8 +124,8 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
.probe = mv88e6171_drv_probe, .probe = mv88e6171_drv_probe,
.setup = mv88e6171_setup, .setup = mv88e6171_setup,
.set_addr = mv88e6xxx_set_addr_indirect, .set_addr = mv88e6xxx_set_addr_indirect,
.phy_read = mv88e6xxx_phy_read_indirect, .phy_read = mv88e6xxx_phy_read,
.phy_write = mv88e6xxx_phy_write_indirect, .phy_write = mv88e6xxx_phy_write,
.get_strings = mv88e6xxx_get_strings, .get_strings = mv88e6xxx_get_strings,
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats, .get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
.get_sset_count = mv88e6xxx_get_sset_count, .get_sset_count = mv88e6xxx_get_sset_count,
......
...@@ -344,8 +344,8 @@ struct dsa_switch_driver mv88e6352_switch_driver = { ...@@ -344,8 +344,8 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
.probe = mv88e6352_drv_probe, .probe = mv88e6352_drv_probe,
.setup = mv88e6352_setup, .setup = mv88e6352_setup,
.set_addr = mv88e6xxx_set_addr_indirect, .set_addr = mv88e6xxx_set_addr_indirect,
.phy_read = mv88e6xxx_phy_read_indirect, .phy_read = mv88e6xxx_phy_read,
.phy_write = mv88e6xxx_phy_write_indirect, .phy_write = mv88e6xxx_phy_write,
.get_strings = mv88e6xxx_get_strings, .get_strings = mv88e6xxx_get_strings,
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats, .get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
.get_sset_count = mv88e6xxx_get_sset_count, .get_sset_count = mv88e6xxx_get_sset_count,
......
...@@ -2887,6 +2887,8 @@ mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum) ...@@ -2887,6 +2887,8 @@ mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum)
if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU)) if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
ret = mv88e6xxx_phy_read_ppu(ps, addr, regnum); 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 else
ret = _mv88e6xxx_phy_read(ps, addr, regnum); ret = _mv88e6xxx_phy_read(ps, addr, regnum);
...@@ -2908,6 +2910,8 @@ mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) ...@@ -2908,6 +2910,8 @@ mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU)) if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
ret = mv88e6xxx_phy_write_ppu(ps, addr, regnum, val); ret = mv88e6xxx_phy_write_ppu(ps, addr, regnum, val);
else if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_SMI_PHY))
ret = _mv88e6xxx_phy_write_indirect(ps, addr, regnum, val);
else else
ret = _mv88e6xxx_phy_write(ps, addr, regnum, val); ret = _mv88e6xxx_phy_write(ps, addr, regnum, val);
...@@ -2915,39 +2919,6 @@ mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) ...@@ -2915,39 +2919,6 @@ mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
return ret; return ret;
} }
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 #ifdef CONFIG_NET_DSA_HWMON
static int mv88e61xx_get_temp(struct dsa_switch *ds, int *temp) static int mv88e61xx_get_temp(struct dsa_switch *ds, int *temp)
......
...@@ -355,10 +355,17 @@ enum mv88e6xxx_cap { ...@@ -355,10 +355,17 @@ enum mv88e6xxx_cap {
* See GLOBAL_CONTROL_PPU_ENABLE and GLOBAL_STATUS_PPU_POLLING. * See GLOBAL_CONTROL_PPU_ENABLE and GLOBAL_STATUS_PPU_POLLING.
*/ */
MV88E6XXX_CAP_PPU, 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 */ /* Bitmask of capabilities */
#define MV88E6XXX_FLAG_PPU BIT(MV88E6XXX_CAP_PPU) #define MV88E6XXX_FLAG_PPU BIT(MV88E6XXX_CAP_PPU)
#define MV88E6XXX_FLAG_SMI_PHY BIT(MV88E6XXX_CAP_SMI_PHY)
#define MV88E6XXX_FLAGS_FAMILY_6095 \ #define MV88E6XXX_FLAGS_FAMILY_6095 \
MV88E6XXX_FLAG_PPU MV88E6XXX_FLAG_PPU
...@@ -371,11 +378,14 @@ enum mv88e6xxx_cap { ...@@ -371,11 +378,14 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAGS_FAMILY_6185 \ #define MV88E6XXX_FLAGS_FAMILY_6185 \
MV88E6XXX_FLAG_PPU MV88E6XXX_FLAG_PPU
#define MV88E6XXX_FLAGS_FAMILY_6320 0 #define MV88E6XXX_FLAGS_FAMILY_6320 \
MV88E6XXX_FLAG_SMI_PHY
#define MV88E6XXX_FLAGS_FAMILY_6351 0 #define MV88E6XXX_FLAGS_FAMILY_6351 \
MV88E6XXX_FLAG_SMI_PHY
#define MV88E6XXX_FLAGS_FAMILY_6352 0 #define MV88E6XXX_FLAGS_FAMILY_6352 \
MV88E6XXX_FLAG_SMI_PHY
struct mv88e6xxx_info { struct mv88e6xxx_info {
enum mv88e6xxx_family family; enum mv88e6xxx_family family;
...@@ -497,9 +507,6 @@ int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr); ...@@ -497,9 +507,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_set_addr_indirect(struct dsa_switch *ds, u8 *addr);
int mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum); 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_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_strings(struct dsa_switch *ds, int port, uint8_t *data);
void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port, void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
uint64_t *data); uint64_t *data);
...@@ -516,9 +523,6 @@ int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp); ...@@ -516,9 +523,6 @@ int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp);
int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm); int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm);
int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds); int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds);
int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds); int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds);
int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, int regnum);
int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr, int regnum,
u16 val);
int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e); int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e);
int mv88e6xxx_set_eee(struct dsa_switch *ds, int port, int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
struct phy_device *phydev, struct ethtool_eee *e); struct phy_device *phydev, struct ethtool_eee *e);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment