summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c287
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.h152
-rw-r--r--drivers/net/dsa/mv88e6xxx/global2.c102
-rw-r--r--drivers/net/dsa/mv88e6xxx/global2.h41
-rw-r--r--drivers/net/dsa/mv88e6xxx/phy.c97
-rw-r--r--drivers/net/dsa/mv88e6xxx/phy.h22
-rw-r--r--drivers/net/dsa/mv88e6xxx/port.c17
-rw-r--r--drivers/net/dsa/mv88e6xxx/port.h6
8 files changed, 457 insertions, 267 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 53b088166c28..947ea352a57a 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -810,31 +810,40 @@ static void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
mutex_unlock(&chip->reg_lock);
}
-static int mv88e6xxx_get_eee(struct dsa_switch *ds, int port,
- struct ethtool_eee *e)
+static int mv88e6xxx_energy_detect_read(struct mv88e6xxx_chip *chip, int port,
+ struct ethtool_eee *eee)
{
- struct mv88e6xxx_chip *chip = ds->priv;
- u16 reg;
int err;
- if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_EEE))
+ if (!chip->info->ops->phy_energy_detect_read)
return -EOPNOTSUPP;
- mutex_lock(&chip->reg_lock);
-
- err = mv88e6xxx_phy_read(chip, port, 16, &reg);
+ /* assign eee->eee_enabled and eee->tx_lpi_enabled */
+ err = chip->info->ops->phy_energy_detect_read(chip, port, eee);
if (err)
- goto out;
+ return err;
- e->eee_enabled = !!(reg & 0x0200);
- e->tx_lpi_enabled = !!(reg & 0x0100);
+ /* assign eee->eee_active */
+ return mv88e6xxx_port_status_eee(chip, port, eee);
+}
- err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
- if (err)
- goto out;
+static int mv88e6xxx_energy_detect_write(struct mv88e6xxx_chip *chip, int port,
+ struct ethtool_eee *eee)
+{
+ if (!chip->info->ops->phy_energy_detect_write)
+ return -EOPNOTSUPP;
- e->eee_active = !!(reg & MV88E6352_PORT_STS_EEE);
-out:
+ return chip->info->ops->phy_energy_detect_write(chip, port, eee);
+}
+
+static int mv88e6xxx_get_eee(struct dsa_switch *ds, int port,
+ struct ethtool_eee *e)
+{
+ struct mv88e6xxx_chip *chip = ds->priv;
+ int err;
+
+ mutex_lock(&chip->reg_lock);
+ err = mv88e6xxx_energy_detect_read(chip, port, e);
mutex_unlock(&chip->reg_lock);
return err;
@@ -844,26 +853,10 @@ static int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
struct phy_device *phydev, struct ethtool_eee *e)
{
struct mv88e6xxx_chip *chip = ds->priv;
- u16 reg;
int err;
- if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_EEE))
- return -EOPNOTSUPP;
-
mutex_lock(&chip->reg_lock);
-
- err = mv88e6xxx_phy_read(chip, port, 16, &reg);
- if (err)
- goto out;
-
- reg &= ~0x0300;
- if (e->eee_enabled)
- reg |= 0x0200;
- if (e->tx_lpi_enabled)
- reg |= 0x0100;
-
- err = mv88e6xxx_phy_write(chip, port, 16, reg);
-out:
+ err = mv88e6xxx_energy_detect_write(chip, port, e);
mutex_unlock(&chip->reg_lock);
return err;
@@ -926,6 +919,22 @@ static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port,
dev_err(ds->dev, "p%d: failed to update state\n", port);
}
+static int mv88e6xxx_pot_setup(struct mv88e6xxx_chip *chip)
+{
+ if (chip->info->ops->pot_clear)
+ return chip->info->ops->pot_clear(chip);
+
+ return 0;
+}
+
+static int mv88e6xxx_rsvd2cpu_setup(struct mv88e6xxx_chip *chip)
+{
+ if (chip->info->ops->mgmt_rsvd2cpu)
+ return chip->info->ops->mgmt_rsvd2cpu(chip);
+
+ return 0;
+}
+
static int mv88e6xxx_atu_setup(struct mv88e6xxx_chip *chip)
{
int err;
@@ -2116,7 +2125,7 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
goto unlock;
/* Setup Switch Global 2 Registers */
- if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_GLOBAL2)) {
+ if (chip->info->global2_addr) {
err = mv88e6xxx_g2_setup(chip);
if (err)
goto unlock;
@@ -2142,16 +2151,13 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
if (err)
goto unlock;
- /* Some generations have the configuration of sending reserved
- * management frames to the CPU in global2, others in
- * global1. Hence it does not fit the two setup functions
- * above.
- */
- if (chip->info->ops->mgmt_rsvd2cpu) {
- err = chip->info->ops->mgmt_rsvd2cpu(chip);
- if (err)
- goto unlock;
- }
+ err = mv88e6xxx_pot_setup(chip);
+ if (err)
+ goto unlock;
+
+ err = mv88e6xxx_rsvd2cpu_setup(chip);
+ if (err)
+ goto unlock;
unlock:
mutex_unlock(&chip->reg_lock);
@@ -2385,7 +2391,8 @@ static const struct mv88e6xxx_ops mv88e6085_ops = {
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
- .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.ppu_enable = mv88e6185_g1_ppu_enable,
.ppu_disable = mv88e6185_g1_ppu_disable,
.reset = mv88e6185_g1_reset,
@@ -2408,7 +2415,7 @@ static const struct mv88e6xxx_ops mv88e6095_ops = {
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
.stats_get_stats = mv88e6095_stats_get_stats,
- .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
.ppu_enable = mv88e6185_g1_ppu_enable,
.ppu_disable = mv88e6185_g1_ppu_disable,
.reset = mv88e6185_g1_reset,
@@ -2441,7 +2448,8 @@ static const struct mv88e6xxx_ops mv88e6097_ops = {
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
- .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6352_g1_vtu_getnext,
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
@@ -2467,7 +2475,8 @@ static const struct mv88e6xxx_ops mv88e6123_ops = {
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
- .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6352_g1_vtu_getnext,
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
@@ -2496,7 +2505,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = {
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
- .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
.ppu_enable = mv88e6185_g1_ppu_enable,
.ppu_disable = mv88e6185_g1_ppu_disable,
.reset = mv88e6185_g1_reset,
@@ -2512,6 +2521,8 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_energy_detect_read = mv88e6352_phy_energy_detect_read,
+ .phy_energy_detect_write = mv88e6352_phy_energy_detect_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
@@ -2533,6 +2544,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
.set_egress_port = mv88e6390_g1_set_egress_port,
.watchdog_ops = &mv88e6390_watchdog_ops,
.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6352_g1_vtu_getnext,
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
@@ -2563,7 +2575,8 @@ static const struct mv88e6xxx_ops mv88e6161_ops = {
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
- .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6352_g1_vtu_getnext,
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
@@ -2587,7 +2600,8 @@ static const struct mv88e6xxx_ops mv88e6165_ops = {
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
- .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6352_g1_vtu_getnext,
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
@@ -2619,7 +2633,8 @@ static const struct mv88e6xxx_ops mv88e6171_ops = {
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
- .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6352_g1_vtu_getnext,
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
@@ -2633,6 +2648,8 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_energy_detect_read = mv88e6352_phy_energy_detect_read,
+ .phy_energy_detect_write = mv88e6352_phy_energy_detect_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
@@ -2653,7 +2670,8 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
- .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6352_g1_vtu_getnext,
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
@@ -2686,7 +2704,8 @@ static const struct mv88e6xxx_ops mv88e6175_ops = {
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
- .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6352_g1_vtu_getnext,
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
@@ -2700,6 +2719,8 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_energy_detect_read = mv88e6352_phy_energy_detect_read,
+ .phy_energy_detect_write = mv88e6352_phy_energy_detect_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
@@ -2720,7 +2741,8 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
- .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6352_g1_vtu_getnext,
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
@@ -2746,7 +2768,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = {
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
- .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
.ppu_enable = mv88e6185_g1_ppu_enable,
.ppu_disable = mv88e6185_g1_ppu_disable,
.reset = mv88e6185_g1_reset,
@@ -2762,6 +2784,8 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_energy_detect_read = mv88e6390_phy_energy_detect_read,
+ .phy_energy_detect_write = mv88e6390_phy_energy_detect_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
@@ -2782,6 +2806,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
.set_egress_port = mv88e6390_g1_set_egress_port,
.watchdog_ops = &mv88e6390_watchdog_ops,
.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6390_g1_vtu_getnext,
.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
@@ -2796,6 +2821,8 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_energy_detect_read = mv88e6390_phy_energy_detect_read,
+ .phy_energy_detect_write = mv88e6390_phy_energy_detect_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
@@ -2816,6 +2843,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
.set_egress_port = mv88e6390_g1_set_egress_port,
.watchdog_ops = &mv88e6390_watchdog_ops,
.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6390_g1_vtu_getnext,
.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
@@ -2830,6 +2858,8 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_energy_detect_read = mv88e6390_phy_energy_detect_read,
+ .phy_energy_detect_write = mv88e6390_phy_energy_detect_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
@@ -2850,6 +2880,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
.set_egress_port = mv88e6390_g1_set_egress_port,
.watchdog_ops = &mv88e6390_watchdog_ops,
.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6390_g1_vtu_getnext,
.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
@@ -2864,6 +2895,8 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_energy_detect_read = mv88e6352_phy_energy_detect_read,
+ .phy_energy_detect_write = mv88e6352_phy_energy_detect_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
@@ -2884,7 +2917,8 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
- .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6352_g1_vtu_getnext,
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
@@ -2899,6 +2933,8 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_energy_detect_read = mv88e6390_phy_energy_detect_read,
+ .phy_energy_detect_write = mv88e6390_phy_energy_detect_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
@@ -2920,6 +2956,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
.set_egress_port = mv88e6390_g1_set_egress_port,
.watchdog_ops = &mv88e6390_watchdog_ops,
.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6390_g1_vtu_getnext,
.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
@@ -2934,6 +2971,8 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_energy_detect_read = mv88e6352_phy_energy_detect_read,
+ .phy_energy_detect_write = mv88e6352_phy_energy_detect_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_speed = mv88e6185_port_set_speed,
@@ -2952,20 +2991,23 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
.stats_get_stats = mv88e6320_stats_get_stats,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
- .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6185_g1_vtu_getnext,
.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
};
static const struct mv88e6xxx_ops mv88e6321_ops = {
- /* MV88E6XXX_FAMILY_6321 */
+ /* MV88E6XXX_FAMILY_6320 */
.irl_init_all = mv88e6352_g2_irl_init_all,
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_energy_detect_read = mv88e6352_phy_energy_detect_read,
+ .phy_energy_detect_write = mv88e6352_phy_energy_detect_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_speed = mv88e6185_port_set_speed,
@@ -2997,6 +3039,8 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_energy_detect_read = mv88e6352_phy_energy_detect_read,
+ .phy_energy_detect_write = mv88e6352_phy_energy_detect_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
@@ -3018,6 +3062,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
.set_egress_port = mv88e6390_g1_set_egress_port,
.watchdog_ops = &mv88e6390_watchdog_ops,
.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6352_g1_vtu_getnext,
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
@@ -3049,7 +3094,8 @@ static const struct mv88e6xxx_ops mv88e6350_ops = {
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
- .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6352_g1_vtu_getnext,
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
@@ -3081,7 +3127,8 @@ static const struct mv88e6xxx_ops mv88e6351_ops = {
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
- .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6352_g1_vtu_getnext,
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
@@ -3095,6 +3142,8 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_energy_detect_read = mv88e6352_phy_energy_detect_read,
+ .phy_energy_detect_write = mv88e6352_phy_energy_detect_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
@@ -3115,7 +3164,8 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
- .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6352_g1_vtu_getnext,
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
@@ -3130,6 +3180,8 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_energy_detect_read = mv88e6390_phy_energy_detect_read,
+ .phy_energy_detect_write = mv88e6390_phy_energy_detect_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
@@ -3153,6 +3205,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
.set_egress_port = mv88e6390_g1_set_egress_port,
.watchdog_ops = &mv88e6390_watchdog_ops,
.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6390_g1_vtu_getnext,
.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
@@ -3167,6 +3220,8 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_energy_detect_read = mv88e6390_phy_energy_detect_read,
+ .phy_energy_detect_write = mv88e6390_phy_energy_detect_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
@@ -3189,6 +3244,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
.set_egress_port = mv88e6390_g1_set_egress_port,
.watchdog_ops = &mv88e6390_watchdog_ops,
.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6390_g1_vtu_getnext,
.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
@@ -3205,12 +3261,14 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 4095,
.port_base_addr = 0x10,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 15000,
.g1_irqs = 8,
+ .g2_irqs = 10,
.atu_move_port_mask = 0xf,
.pvt = true,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_DSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6097,
.ops = &mv88e6085_ops,
},
@@ -3223,11 +3281,12 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 4095,
.port_base_addr = 0x10,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 15000,
.g1_irqs = 8,
.atu_move_port_mask = 0xf,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_DSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6095,
.ops = &mv88e6095_ops,
},
@@ -3240,12 +3299,14 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 4095,
.port_base_addr = 0x10,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 15000,
.g1_irqs = 8,
+ .g2_irqs = 10,
.atu_move_port_mask = 0xf,
.pvt = true,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6097,
.ops = &mv88e6097_ops,
},
@@ -3258,12 +3319,14 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 4095,
.port_base_addr = 0x10,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 15000,
.g1_irqs = 9,
+ .g2_irqs = 10,
.atu_move_port_mask = 0xf,
.pvt = true,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6165,
.ops = &mv88e6123_ops,
},
@@ -3276,11 +3339,12 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 4095,
.port_base_addr = 0x10,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 15000,
.g1_irqs = 9,
.atu_move_port_mask = 0xf,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_DSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6185,
.ops = &mv88e6131_ops,
},
@@ -3293,11 +3357,13 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 4095,
.port_base_addr = 0x10,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 3750,
.atu_move_port_mask = 0x1f,
+ .g2_irqs = 10,
.pvt = true,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6341,
.ops = &mv88e6141_ops,
},
@@ -3310,12 +3376,14 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 4095,
.port_base_addr = 0x10,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 15000,
.g1_irqs = 9,
+ .g2_irqs = 10,
.atu_move_port_mask = 0xf,
.pvt = true,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6165,
.ops = &mv88e6161_ops,
},
@@ -3328,12 +3396,14 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 4095,
.port_base_addr = 0x10,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 15000,
.g1_irqs = 9,
+ .g2_irqs = 10,
.atu_move_port_mask = 0xf,
.pvt = true,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_DSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6165,
.ops = &mv88e6165_ops,
},
@@ -3346,12 +3416,14 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 4095,
.port_base_addr = 0x10,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 15000,
.g1_irqs = 9,
+ .g2_irqs = 10,
.atu_move_port_mask = 0xf,
.pvt = true,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6351,
.ops = &mv88e6171_ops,
},
@@ -3364,12 +3436,14 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 4095,
.port_base_addr = 0x10,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 15000,
.g1_irqs = 9,
+ .g2_irqs = 10,
.atu_move_port_mask = 0xf,
.pvt = true,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6352,
.ops = &mv88e6172_ops,
},
@@ -3382,12 +3456,14 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 4095,
.port_base_addr = 0x10,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 15000,
.g1_irqs = 9,
+ .g2_irqs = 10,
.atu_move_port_mask = 0xf,
.pvt = true,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6351,
.ops = &mv88e6175_ops,
},
@@ -3400,12 +3476,14 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 4095,
.port_base_addr = 0x10,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 15000,
.g1_irqs = 9,
+ .g2_irqs = 10,
.atu_move_port_mask = 0xf,
.pvt = true,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6352,
.ops = &mv88e6176_ops,
},
@@ -3418,11 +3496,12 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 4095,
.port_base_addr = 0x10,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 15000,
.g1_irqs = 8,
.atu_move_port_mask = 0xf,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6185,
.ops = &mv88e6185_ops,
},
@@ -3435,12 +3514,14 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 8191,
.port_base_addr = 0x0,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.tag_protocol = DSA_TAG_PROTO_DSA,
.age_time_coeff = 3750,
.g1_irqs = 9,
+ .g2_irqs = 14,
.pvt = true,
+ .multi_chip = true,
.atu_move_port_mask = 0x1f,
- .flags = MV88E6XXX_FLAGS_FAMILY_6390,
.ops = &mv88e6190_ops,
},
@@ -3453,12 +3534,14 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 8191,
.port_base_addr = 0x0,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 3750,
.g1_irqs = 9,
+ .g2_irqs = 14,
.atu_move_port_mask = 0x1f,
.pvt = true,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_DSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6390,
.ops = &mv88e6190x_ops,
},
@@ -3471,12 +3554,14 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 8191,
.port_base_addr = 0x0,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 3750,
.g1_irqs = 9,
+ .g2_irqs = 14,
.atu_move_port_mask = 0x1f,
.pvt = true,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_DSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6390,
.ops = &mv88e6191_ops,
},
@@ -3489,12 +3574,14 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 4095,
.port_base_addr = 0x10,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 15000,
.g1_irqs = 9,
+ .g2_irqs = 10,
.atu_move_port_mask = 0xf,
.pvt = true,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6352,
.ops = &mv88e6240_ops,
},
@@ -3507,12 +3594,14 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 8191,
.port_base_addr = 0x0,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 3750,
.g1_irqs = 9,
+ .g2_irqs = 14,
.atu_move_port_mask = 0x1f,
.pvt = true,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_DSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6390,
.ops = &mv88e6290_ops,
},
@@ -3525,12 +3614,13 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 4095,
.port_base_addr = 0x10,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 15000,
.g1_irqs = 8,
.atu_move_port_mask = 0xf,
.pvt = true,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6320,
.ops = &mv88e6320_ops,
},
@@ -3543,11 +3633,12 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 4095,
.port_base_addr = 0x10,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 15000,
.g1_irqs = 8,
.atu_move_port_mask = 0xf,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6320,
.ops = &mv88e6321_ops,
},
@@ -3560,11 +3651,13 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 4095,
.port_base_addr = 0x10,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 3750,
.atu_move_port_mask = 0x1f,
+ .g2_irqs = 10,
.pvt = true,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6341,
.ops = &mv88e6341_ops,
},
@@ -3577,12 +3670,14 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 4095,
.port_base_addr = 0x10,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 15000,
.g1_irqs = 9,
+ .g2_irqs = 10,
.atu_move_port_mask = 0xf,
.pvt = true,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6351,
.ops = &mv88e6350_ops,
},
@@ -3595,12 +3690,14 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 4095,
.port_base_addr = 0x10,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 15000,
.g1_irqs = 9,
+ .g2_irqs = 10,
.atu_move_port_mask = 0xf,
.pvt = true,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6351,
.ops = &mv88e6351_ops,
},
@@ -3613,12 +3710,14 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 4095,
.port_base_addr = 0x10,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 15000,
.g1_irqs = 9,
+ .g2_irqs = 10,
.atu_move_port_mask = 0xf,
.pvt = true,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6352,
.ops = &mv88e6352_ops,
},
[MV88E6390] = {
@@ -3630,12 +3729,14 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 8191,
.port_base_addr = 0x0,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 3750,
.g1_irqs = 9,
+ .g2_irqs = 14,
.atu_move_port_mask = 0x1f,
.pvt = true,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_DSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6390,
.ops = &mv88e6390_ops,
},
[MV88E6390X] = {
@@ -3647,12 +3748,14 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.max_vid = 8191,
.port_base_addr = 0x0,
.global1_addr = 0x1b,
+ .global2_addr = 0x1c,
.age_time_coeff = 3750,
.g1_irqs = 9,
+ .g2_irqs = 14,
.atu_move_port_mask = 0x1f,
.pvt = true,
+ .multi_chip = true,
.tag_protocol = DSA_TAG_PROTO_DSA,
- .flags = MV88E6XXX_FLAGS_FAMILY_6390,
.ops = &mv88e6390x_ops,
},
};
@@ -3722,7 +3825,7 @@ static int mv88e6xxx_smi_init(struct mv88e6xxx_chip *chip,
{
if (sw_addr == 0)
chip->smi_ops = &mv88e6xxx_smi_single_chip_ops;
- else if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_MULTI_CHIP))
+ else if (chip->info->multi_chip)
chip->smi_ops = &mv88e6xxx_smi_multi_chip_ops;
else
return -EINVAL;
@@ -3970,7 +4073,7 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
if (err)
goto out;
- if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT)) {
+ if (chip->info->g2_irqs > 0) {
err = mv88e6xxx_g2_irq_setup(chip);
if (err)
goto out_g1_irq;
@@ -3990,7 +4093,7 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
out_mdio:
mv88e6xxx_mdios_unregister(chip);
out_g2_irq:
- if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT) && chip->irq > 0)
+ if (chip->info->g2_irqs > 0 && chip->irq > 0)
mv88e6xxx_g2_irq_free(chip);
out_g1_irq:
if (chip->irq > 0) {
@@ -4012,7 +4115,7 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev)
mv88e6xxx_mdios_unregister(chip);
if (chip->irq > 0) {
- if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT))
+ if (chip->info->g2_irqs > 0)
mv88e6xxx_g2_irq_free(chip);
mv88e6xxx_g1_irq_free(chip);
}
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 086444016352..9111e1316250 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -97,133 +97,6 @@ enum mv88e6xxx_family {
MV88E6XXX_FAMILY_6390, /* 6190 6190X 6191 6290 6390 6390X */
};
-enum mv88e6xxx_cap {
- /* Energy Efficient Ethernet.
- */
- MV88E6XXX_CAP_EEE,
-
- /* Multi-chip Addressing Mode.
- * Some chips respond to only 2 registers of its own SMI device address
- * when it is non-zero, and use indirect access to internal registers.
- */
- MV88E6XXX_CAP_SMI_CMD, /* (0x00) SMI Command */
- MV88E6XXX_CAP_SMI_DATA, /* (0x01) SMI Data */
-
- /* Switch Global (1) Registers.
- */
- MV88E6XXX_CAP_G1_ATU_FID, /* (0x01) ATU FID Register */
- MV88E6XXX_CAP_G1_VTU_FID, /* (0x02) VTU FID Register */
-
- /* Switch Global 2 Registers.
- * The device contains a second set of global 16-bit registers.
- */
- MV88E6XXX_CAP_GLOBAL2,
- MV88E6XXX_CAP_G2_INT, /* (0x00) Interrupt Status */
- MV88E6XXX_CAP_G2_MGMT_EN_2X, /* (0x02) MGMT Enable Register 2x */
- MV88E6XXX_CAP_G2_MGMT_EN_0X, /* (0x03) MGMT Enable Register 0x */
- MV88E6XXX_CAP_G2_POT, /* (0x0f) Priority Override Table */
-
- /* Per VLAN Spanning Tree Unit (STU).
- * The Port State database, if present, is accessed through VTU
- * operations and dedicated SID registers. See MV88E6352_G1_VTU_SID.
- */
- MV88E6XXX_CAP_STU,
-
- /* VLAN Table Unit.
- * The VTU is used to program 802.1Q VLANs. See MV88E6XXX_G1_VTU_OP.
- */
- MV88E6XXX_CAP_VTU,
-};
-
-/* Bitmask of capabilities */
-#define MV88E6XXX_FLAG_EEE BIT_ULL(MV88E6XXX_CAP_EEE)
-
-#define MV88E6XXX_FLAG_SMI_CMD BIT_ULL(MV88E6XXX_CAP_SMI_CMD)
-#define MV88E6XXX_FLAG_SMI_DATA BIT_ULL(MV88E6XXX_CAP_SMI_DATA)
-
-#define MV88E6XXX_FLAG_G1_VTU_FID BIT_ULL(MV88E6XXX_CAP_G1_VTU_FID)
-
-#define MV88E6XXX_FLAG_GLOBAL2 BIT_ULL(MV88E6XXX_CAP_GLOBAL2)
-#define MV88E6XXX_FLAG_G2_INT BIT_ULL(MV88E6XXX_CAP_G2_INT)
-#define MV88E6XXX_FLAG_G2_MGMT_EN_2X BIT_ULL(MV88E6XXX_CAP_G2_MGMT_EN_2X)
-#define MV88E6XXX_FLAG_G2_MGMT_EN_0X BIT_ULL(MV88E6XXX_CAP_G2_MGMT_EN_0X)
-#define MV88E6XXX_FLAG_G2_POT BIT_ULL(MV88E6XXX_CAP_G2_POT)
-
-/* Multi-chip Addressing Mode */
-#define MV88E6XXX_FLAGS_MULTI_CHIP \
- (MV88E6XXX_FLAG_SMI_CMD | \
- MV88E6XXX_FLAG_SMI_DATA)
-
-#define MV88E6XXX_FLAGS_FAMILY_6095 \
- (MV88E6XXX_FLAG_GLOBAL2 | \
- MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
- MV88E6XXX_FLAGS_MULTI_CHIP)
-
-#define MV88E6XXX_FLAGS_FAMILY_6097 \
- (MV88E6XXX_FLAG_G1_VTU_FID | \
- MV88E6XXX_FLAG_GLOBAL2 | \
- MV88E6XXX_FLAG_G2_INT | \
- MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
- MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
- MV88E6XXX_FLAG_G2_POT | \
- MV88E6XXX_FLAGS_MULTI_CHIP)
-
-#define MV88E6XXX_FLAGS_FAMILY_6165 \
- (MV88E6XXX_FLAG_G1_VTU_FID | \
- MV88E6XXX_FLAG_GLOBAL2 | \
- MV88E6XXX_FLAG_G2_INT | \
- MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
- MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
- MV88E6XXX_FLAG_G2_POT | \
- MV88E6XXX_FLAGS_MULTI_CHIP)
-
-#define MV88E6XXX_FLAGS_FAMILY_6185 \
- (MV88E6XXX_FLAG_GLOBAL2 | \
- MV88E6XXX_FLAG_G2_INT | \
- MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
- MV88E6XXX_FLAGS_MULTI_CHIP)
-
-#define MV88E6XXX_FLAGS_FAMILY_6320 \
- (MV88E6XXX_FLAG_EEE | \
- MV88E6XXX_FLAG_GLOBAL2 | \
- MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
- MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
- MV88E6XXX_FLAG_G2_POT | \
- MV88E6XXX_FLAGS_MULTI_CHIP)
-
-#define MV88E6XXX_FLAGS_FAMILY_6341 \
- (MV88E6XXX_FLAG_EEE | \
- MV88E6XXX_FLAG_G1_VTU_FID | \
- MV88E6XXX_FLAG_GLOBAL2 | \
- MV88E6XXX_FLAG_G2_INT | \
- MV88E6XXX_FLAG_G2_POT | \
- MV88E6XXX_FLAGS_MULTI_CHIP)
-
-#define MV88E6XXX_FLAGS_FAMILY_6351 \
- (MV88E6XXX_FLAG_G1_VTU_FID | \
- MV88E6XXX_FLAG_GLOBAL2 | \
- MV88E6XXX_FLAG_G2_INT | \
- MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
- MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
- MV88E6XXX_FLAG_G2_POT | \
- MV88E6XXX_FLAGS_MULTI_CHIP)
-
-#define MV88E6XXX_FLAGS_FAMILY_6352 \
- (MV88E6XXX_FLAG_EEE | \
- MV88E6XXX_FLAG_G1_VTU_FID | \
- MV88E6XXX_FLAG_GLOBAL2 | \
- MV88E6XXX_FLAG_G2_INT | \
- MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
- MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
- MV88E6XXX_FLAG_G2_POT | \
- MV88E6XXX_FLAGS_MULTI_CHIP)
-
-#define MV88E6XXX_FLAGS_FAMILY_6390 \
- (MV88E6XXX_FLAG_EEE | \
- MV88E6XXX_FLAG_GLOBAL2 | \
- MV88E6XXX_FLAG_G2_INT | \
- MV88E6XXX_FLAGS_MULTI_CHIP)
-
struct mv88e6xxx_ops;
struct mv88e6xxx_info {
@@ -235,11 +108,18 @@ struct mv88e6xxx_info {
unsigned int max_vid;
unsigned int port_base_addr;
unsigned int global1_addr;
+ unsigned int global2_addr;
unsigned int age_time_coeff;
unsigned int g1_irqs;
+ unsigned int g2_irqs;
bool pvt;
+
+ /* Multi-chip Addressing Mode.
+ * Some chips respond to only 2 registers of its own SMI device address
+ * when it is non-zero, and use indirect access to internal registers.
+ */
+ bool multi_chip;
enum dsa_tag_protocol tag_protocol;
- unsigned long long flags;
/* Mask for FromPort and ToPort value of PortVec used in ATU Move
* operation. 0 means that the ATU Move operation is not supported.
@@ -359,6 +239,15 @@ struct mv88e6xxx_ops {
struct mii_bus *bus,
int addr, int reg, u16 val);
+ /* Copper Energy Detect operations */
+ int (*phy_energy_detect_read)(struct mv88e6xxx_chip *chip, int phy,
+ struct ethtool_eee *eee);
+ int (*phy_energy_detect_write)(struct mv88e6xxx_chip *chip, int phy,
+ struct ethtool_eee *eee);
+
+ /* Priority Override Table operations */
+ int (*pot_clear)(struct mv88e6xxx_chip *chip);
+
/* PHY Polling Unit (PPU) operations */
int (*ppu_enable)(struct mv88e6xxx_chip *chip);
int (*ppu_disable)(struct mv88e6xxx_chip *chip);
@@ -449,7 +338,6 @@ struct mv88e6xxx_ops {
int (*set_egress_port)(struct mv88e6xxx_chip *chip, int port);
const struct mv88e6xxx_irq_ops *watchdog_ops;
- /* Can be either in g1 or g2, so don't use a prefix */
int (*mgmt_rsvd2cpu)(struct mv88e6xxx_chip *chip);
/* Power on/off a SERDES interface */
@@ -482,12 +370,6 @@ struct mv88e6xxx_hw_stat {
int type;
};
-static inline bool mv88e6xxx_has(struct mv88e6xxx_chip *chip,
- unsigned long flags)
-{
- return (chip->info->flags & flags) == flags;
-}
-
static inline bool mv88e6xxx_has_pvt(struct mv88e6xxx_chip *chip)
{
return chip->info->pvt;
diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c
index 158d0f499874..16f556261022 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -22,48 +22,99 @@
static int mv88e6xxx_g2_read(struct mv88e6xxx_chip *chip, int reg, u16 *val)
{
- return mv88e6xxx_read(chip, MV88E6XXX_G2, reg, val);
+ return mv88e6xxx_read(chip, chip->info->global2_addr, reg, val);
}
static int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
{
- return mv88e6xxx_write(chip, MV88E6XXX_G2, reg, val);
+ return mv88e6xxx_write(chip, chip->info->global2_addr, reg, val);
}
static int mv88e6xxx_g2_update(struct mv88e6xxx_chip *chip, int reg, u16 update)
{
- return mv88e6xxx_update(chip, MV88E6XXX_G2, reg, update);
+ return mv88e6xxx_update(chip, chip->info->global2_addr, reg, update);
}
static int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
{
- return mv88e6xxx_wait(chip, MV88E6XXX_G2, reg, mask);
+ return mv88e6xxx_wait(chip, chip->info->global2_addr, reg, mask);
+}
+
+/* Offset 0x00: Interrupt Source Register */
+
+static int mv88e6xxx_g2_int_source(struct mv88e6xxx_chip *chip, u16 *src)
+{
+ /* Read (and clear most of) the Interrupt Source bits */
+ return mv88e6xxx_g2_read(chip, MV88E6XXX_G2_INT_SRC, src);
+}
+
+/* Offset 0x01: Interrupt Mask Register */
+
+static int mv88e6xxx_g2_int_mask(struct mv88e6xxx_chip *chip, u16 mask)
+{
+ return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_INT_MASK, mask);
}
/* Offset 0x02: Management Enable 2x */
+
+static int mv88e6xxx_g2_mgmt_enable_2x(struct mv88e6xxx_chip *chip, u16 en2x)
+{
+ return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_MGMT_EN_2X, en2x);
+}
+
/* Offset 0x03: Management Enable 0x */
-int mv88e6095_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
+static int mv88e6xxx_g2_mgmt_enable_0x(struct mv88e6xxx_chip *chip, u16 en0x)
+{
+ return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_MGMT_EN_0X, en0x);
+}
+
+/* Offset 0x05: Switch Management Register */
+
+static int mv88e6xxx_g2_switch_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip,
+ bool enable)
+{
+ u16 val;
+ int err;
+
+ err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_SWITCH_MGMT, &val);
+ if (err)
+ return err;
+
+ if (enable)
+ val |= MV88E6XXX_G2_SWITCH_MGMT_RSVD2CPU;
+ else
+ val &= ~MV88E6XXX_G2_SWITCH_MGMT_RSVD2CPU;
+
+ return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SWITCH_MGMT, val);
+}
+
+int mv88e6185_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
{
int err;
/* Consider the frames with reserved multicast destination
- * addresses matching 01:80:c2:00:00:2x as MGMT.
+ * addresses matching 01:80:c2:00:00:0x as MGMT.
*/
- if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X)) {
- err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_MGMT_EN_2X, 0xffff);
- if (err)
- return err;
- }
+ err = mv88e6xxx_g2_mgmt_enable_0x(chip, 0xffff);
+ if (err)
+ return err;
+
+ return mv88e6xxx_g2_switch_mgmt_rsvd2cpu(chip, true);
+}
+
+int mv88e6352_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
+{
+ int err;
/* Consider the frames with reserved multicast destination
- * addresses matching 01:80:c2:00:00:0x as MGMT.
+ * addresses matching 01:80:c2:00:00:2x as MGMT.
*/
- if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X))
- return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_MGMT_EN_0X,
- 0xffff);
+ err = mv88e6xxx_g2_mgmt_enable_2x(chip, 0xffff);
+ if (err)
+ return err;
- return 0;
+ return mv88e6185_g2_mgmt_rsvd2cpu(chip);
}
/* Offset 0x06: Device Mapping Table register */
@@ -260,7 +311,7 @@ static int mv88e6xxx_g2_pot_write(struct mv88e6xxx_chip *chip, int pointer,
return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_PRIO_OVERRIDE, val);
}
-static int mv88e6xxx_g2_clear_pot(struct mv88e6xxx_chip *chip)
+int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip)
{
int i, err;
@@ -933,7 +984,7 @@ static irqreturn_t mv88e6xxx_g2_irq_thread_fn(int irq, void *dev_id)
u16 reg;
mutex_lock(&chip->reg_lock);
- err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_INT_SOURCE, &reg);
+ err = mv88e6xxx_g2_int_source(chip, &reg);
mutex_unlock(&chip->reg_lock);
if (err)
goto out;
@@ -959,8 +1010,11 @@ static void mv88e6xxx_g2_irq_bus_lock(struct irq_data *d)
static void mv88e6xxx_g2_irq_bus_sync_unlock(struct irq_data *d)
{
struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+ int err;
- mv88e6xxx_g2_write(chip, MV88E6XXX_G2_INT_MASK, ~chip->g2_irq.masked);
+ err = mv88e6xxx_g2_int_mask(chip, ~chip->g2_irq.masked);
+ if (err)
+ dev_err(chip->dev, "failed to mask interrupts\n");
mutex_unlock(&chip->reg_lock);
}
@@ -1063,9 +1117,6 @@ int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip)
* port at the highest priority.
*/
reg = MV88E6XXX_G2_SWITCH_MGMT_FORCE_FLOW_CTL_PRI | (0x7 << 4);
- if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X) ||
- mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X))
- reg |= MV88E6XXX_G2_SWITCH_MGMT_RSVD2CPU | 0x7;
err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SWITCH_MGMT, reg);
if (err)
return err;
@@ -1080,12 +1131,5 @@ int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip)
if (err)
return err;
- if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_POT)) {
- /* Clear the priority override table. */
- err = mv88e6xxx_g2_clear_pot(chip);
- if (err)
- return err;
- }
-
return 0;
}
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h
index 317ffd8f323d..669f59017b12 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -17,14 +17,27 @@
#include "chip.h"
-#define MV88E6XXX_G2 0x1c
-
/* Offset 0x00: Interrupt Source Register */
-#define MV88E6XXX_G2_INT_SOURCE 0x00
+#define MV88E6XXX_G2_INT_SRC 0x00
+#define MV88E6XXX_G2_INT_SRC_WDOG 0x8000
+#define MV88E6XXX_G2_INT_SRC_JAM_LIMIT 0x4000
+#define MV88E6XXX_G2_INT_SRC_DUPLEX_MISMATCH 0x2000
+#define MV88E6XXX_G2_INT_SRC_WAKE_EVENT 0x1000
+#define MV88E6352_G2_INT_SRC_SERDES 0x0800
+#define MV88E6352_G2_INT_SRC_PHY 0x001f
+#define MV88E6390_G2_INT_SRC_PHY 0x07fe
+
#define MV88E6XXX_G2_INT_SOURCE_WATCHDOG 15
/* Offset 0x01: Interrupt Mask Register */
-#define MV88E6XXX_G2_INT_MASK 0x01
+#define MV88E6XXX_G2_INT_MASK 0x01
+#define MV88E6XXX_G2_INT_MASK_WDOG 0x8000
+#define MV88E6XXX_G2_INT_MASK_JAM_LIMIT 0x4000
+#define MV88E6XXX_G2_INT_MASK_DUPLEX_MISMATCH 0x2000
+#define MV88E6XXX_G2_INT_MASK_WAKE_EVENT 0x1000
+#define MV88E6352_G2_INT_MASK_SERDES 0x0800
+#define MV88E6352_G2_INT_MASK_PHY 0x001f
+#define MV88E6390_G2_INT_MASK_PHY 0x07fe
/* Offset 0x02: MGMT Enable Register 2x */
#define MV88E6XXX_G2_MGMT_EN_2X 0x02
@@ -245,7 +258,11 @@ int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip);
int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip);
int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip);
void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip);
-int mv88e6095_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip);
+
+int mv88e6185_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip);
+int mv88e6352_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip);
+
+int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip);
extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops;
extern const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops;
@@ -254,7 +271,7 @@ extern const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops;
static inline int mv88e6xxx_g2_require(struct mv88e6xxx_chip *chip)
{
- if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_GLOBAL2)) {
+ if (chip->info->global2_addr) {
dev_err(chip->dev, "this chip requires CONFIG_NET_DSA_MV88E6XXX_GLOBAL2 enabled\n");
return -EOPNOTSUPP;
}
@@ -347,7 +364,17 @@ static inline void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip)
{
}
-static inline int mv88e6095_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
+static inline int mv88e6185_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int mv88e6352_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip)
{
return -EOPNOTSUPP;
}
diff --git a/drivers/net/dsa/mv88e6xxx/phy.c b/drivers/net/dsa/mv88e6xxx/phy.c
index 3500ac0ea848..317ae89cfa68 100644
--- a/drivers/net/dsa/mv88e6xxx/phy.c
+++ b/drivers/net/dsa/mv88e6xxx/phy.c
@@ -13,7 +13,6 @@
#include <linux/mdio.h>
#include <linux/module.h>
-#include <net/dsa.h>
#include "chip.h"
#include "phy.h"
@@ -247,3 +246,99 @@ int mv88e6xxx_phy_setup(struct mv88e6xxx_chip *chip)
{
return mv88e6xxx_phy_ppu_enable(chip);
}
+
+/* Page 0, Register 16: Copper Specific Control Register 1 */
+
+int mv88e6352_phy_energy_detect_read(struct mv88e6xxx_chip *chip, int phy,
+ struct ethtool_eee *eee)
+{
+ u16 val;
+ int err;
+
+ err = mv88e6xxx_phy_read(chip, phy, MV88E6XXX_PHY_CSCTL1, &val);
+ if (err)
+ return err;
+
+ val &= MV88E6352_PHY_CSCTL1_ENERGY_DETECT_MASK;
+
+ eee->eee_enabled = false;
+ eee->tx_lpi_enabled = false;
+
+ switch (val) {
+ case MV88E6352_PHY_CSCTL1_ENERGY_DETECT_SENSE_NLP:
+ eee->tx_lpi_enabled = true;
+ /* fall through... */
+ case MV88E6352_PHY_CSCTL1_ENERGY_DETECT_SENSE_RCV:
+ eee->eee_enabled = true;
+ }
+
+ return 0;
+}
+
+int mv88e6352_phy_energy_detect_write(struct mv88e6xxx_chip *chip, int phy,
+ struct ethtool_eee *eee)
+{
+ u16 val;
+ int err;
+
+ err = mv88e6xxx_phy_read(chip, phy, MV88E6XXX_PHY_CSCTL1, &val);
+ if (err)
+ return err;
+
+ val &= ~MV88E6352_PHY_CSCTL1_ENERGY_DETECT_MASK;
+
+ if (eee->eee_enabled)
+ val |= MV88E6352_PHY_CSCTL1_ENERGY_DETECT_SENSE_RCV;
+ if (eee->tx_lpi_enabled)
+ val |= MV88E6352_PHY_CSCTL1_ENERGY_DETECT_SENSE_NLP;
+
+ return mv88e6xxx_phy_write(chip, phy, MV88E6XXX_PHY_CSCTL1, val);
+}
+
+int mv88e6390_phy_energy_detect_read(struct mv88e6xxx_chip *chip, int phy,
+ struct ethtool_eee *eee)
+{
+ u16 val;
+ int err;
+
+ err = mv88e6xxx_phy_read(chip, phy, MV88E6XXX_PHY_CSCTL1, &val);
+ if (err)
+ return err;
+
+ val &= MV88E6390_PHY_CSCTL1_ENERGY_DETECT_MASK;
+
+ eee->eee_enabled = false;
+ eee->tx_lpi_enabled = false;
+
+ switch (val) {
+ case MV88E6390_PHY_CSCTL1_ENERGY_DETECT_SENSE_NLP_AUTO:
+ case MV88E6390_PHY_CSCTL1_ENERGY_DETECT_SENSE_NLP_SW:
+ eee->tx_lpi_enabled = true;
+ /* fall through... */
+ case MV88E6390_PHY_CSCTL1_ENERGY_DETECT_SENSE_RCV_AUTO:
+ case MV88E6390_PHY_CSCTL1_ENERGY_DETECT_SENSE_RCV_SW:
+ eee->eee_enabled = true;
+ }
+
+ return 0;
+}
+
+int mv88e6390_phy_energy_detect_write(struct mv88e6xxx_chip *chip, int phy,
+ struct ethtool_eee *eee)
+{
+ u16 val;
+ int err;
+
+ err = mv88e6xxx_phy_read(chip, phy, MV88E6XXX_PHY_CSCTL1, &val);
+ if (err)
+ return err;
+
+ val &= ~MV88E6390_PHY_CSCTL1_ENERGY_DETECT_MASK;
+
+ if (eee->eee_enabled)
+ val |= MV88E6390_PHY_CSCTL1_ENERGY_DETECT_SENSE_RCV_AUTO;
+ if (eee->tx_lpi_enabled)
+ val |= MV88E6390_PHY_CSCTL1_ENERGY_DETECT_SENSE_NLP_AUTO;
+
+ return mv88e6xxx_phy_write(chip, phy, MV88E6XXX_PHY_CSCTL1, val);
+}
diff --git a/drivers/net/dsa/mv88e6xxx/phy.h b/drivers/net/dsa/mv88e6xxx/phy.h
index 556b74a0502a..988802799ad6 100644
--- a/drivers/net/dsa/mv88e6xxx/phy.h
+++ b/drivers/net/dsa/mv88e6xxx/phy.h
@@ -17,6 +17,19 @@
#define MV88E6XXX_PHY_PAGE 0x16
#define MV88E6XXX_PHY_PAGE_COPPER 0x00
+/* Page 0, Register 16: Copper Specific Control Register 1 */
+#define MV88E6XXX_PHY_CSCTL1 16
+#define MV88E6352_PHY_CSCTL1_ENERGY_DETECT_MASK 0x0300
+#define MV88E6352_PHY_CSCTL1_ENERGY_DETECT_OFF_MASK 0x0100 /* 0x */
+#define MV88E6352_PHY_CSCTL1_ENERGY_DETECT_SENSE_RCV 0x0200
+#define MV88E6352_PHY_CSCTL1_ENERGY_DETECT_SENSE_NLP 0x0300
+#define MV88E6390_PHY_CSCTL1_ENERGY_DETECT_MASK 0x0380
+#define MV88E6390_PHY_CSCTL1_ENERGY_DETECT_OFF_MASK 0x0180 /* 0xx */
+#define MV88E6390_PHY_CSCTL1_ENERGY_DETECT_SENSE_RCV_AUTO 0x0200
+#define MV88E6390_PHY_CSCTL1_ENERGY_DETECT_SENSE_RCV_SW 0x0280
+#define MV88E6390_PHY_CSCTL1_ENERGY_DETECT_SENSE_NLP_AUTO 0x0300
+#define MV88E6390_PHY_CSCTL1_ENERGY_DETECT_SENSE_NLP_SW 0x0380
+
/* PHY Registers accesses implementations */
int mv88e6165_phy_read(struct mv88e6xxx_chip *chip, struct mii_bus *bus,
int addr, int reg, u16 *val);
@@ -40,4 +53,13 @@ void mv88e6xxx_phy_init(struct mv88e6xxx_chip *chip);
void mv88e6xxx_phy_destroy(struct mv88e6xxx_chip *chip);
int mv88e6xxx_phy_setup(struct mv88e6xxx_chip *chip);
+int mv88e6352_phy_energy_detect_read(struct mv88e6xxx_chip *chip, int phy,
+ struct ethtool_eee *eee);
+int mv88e6352_phy_energy_detect_write(struct mv88e6xxx_chip *chip, int phy,
+ struct ethtool_eee *eee);
+int mv88e6390_phy_energy_detect_read(struct mv88e6xxx_chip *chip, int phy,
+ struct ethtool_eee *eee);
+int mv88e6390_phy_energy_detect_write(struct mv88e6xxx_chip *chip, int phy,
+ struct ethtool_eee *eee);
+
#endif /*_MV88E6XXX_PHY_H */
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index a7801f6668a5..2837a9128557 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -35,6 +35,23 @@ int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
return mv88e6xxx_write(chip, addr, reg, val);
}
+/* Offset 0x00: Port Status Register */
+
+int mv88e6xxx_port_status_eee(struct mv88e6xxx_chip *chip, int port,
+ struct ethtool_eee *eee)
+{
+ u16 val;
+ int err;
+
+ err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &val);
+ if (err)
+ return err;
+
+ eee->eee_active = !!(val & MV88E6352_PORT_STS_EEE);
+
+ return 0;
+}
+
/* Offset 0x01: MAC (or PCS or Physical) Control Register
*
* Link, Duplex and Flow Control have one force bit, one value bit.
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index 8f3991bf1851..6fcab309cd85 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -216,9 +216,6 @@
/* Offset 0x13: OutFiltered Counter */
#define MV88E6XXX_PORT_OUT_FILTERED 0x13
-/* Offset 0x16: LED Control */
-#define MV88E6XXX_PORT_LED_CONTROL 0x16
-
/* Offset 0x18: IEEE Priority Mapping Table */
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE 0x18
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE 0x8000
@@ -244,6 +241,9 @@ int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
u16 val);
+int mv88e6xxx_port_status_eee(struct mv88e6xxx_chip *chip, int port,
+ struct ethtool_eee *eee);
+
int mv88e6352_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
phy_interface_t mode);
int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,