Implement a new operation to enable the Remote Management Unit (RMU) on a specified port. Add such support for 88E6352 and 88E6390 switches.
Signed-off-by: Vivien Didelot <vivien.dide...@gmail.com> --- drivers/net/dsa/mv88e6xxx/chip.c | 10 ++++++ drivers/net/dsa/mv88e6xxx/chip.h | 1 + drivers/net/dsa/mv88e6xxx/global1.c | 56 +++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/global1.h | 2 ++ 4 files changed, 69 insertions(+) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 96e1886e05f0..3aa2b315b96d 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3142,6 +3142,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, + .rmu_enable = mv88e6352_g1_rmu_enable, .rmu_disable = mv88e6352_g1_rmu_disable, .vtu_getnext = mv88e6352_g1_vtu_getnext, .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, @@ -3225,6 +3226,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, + .rmu_enable = mv88e6352_g1_rmu_enable, .rmu_disable = mv88e6352_g1_rmu_disable, .vtu_getnext = mv88e6352_g1_vtu_getnext, .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, @@ -3305,6 +3307,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = { .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, + .rmu_enable = mv88e6390_g1_rmu_enable, .rmu_disable = mv88e6390_g1_rmu_disable, .vtu_getnext = mv88e6390_g1_vtu_getnext, .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, @@ -3350,6 +3353,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = { .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, + .rmu_enable = mv88e6390_g1_rmu_enable, .rmu_disable = mv88e6390_g1_rmu_disable, .vtu_getnext = mv88e6390_g1_vtu_getnext, .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, @@ -3395,6 +3399,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = { .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, + .rmu_enable = mv88e6390_g1_rmu_enable, .rmu_disable = mv88e6390_g1_rmu_disable, .vtu_getnext = mv88e6390_g1_vtu_getnext, .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, @@ -3442,6 +3447,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, + .rmu_enable = mv88e6352_g1_rmu_enable, .rmu_disable = mv88e6352_g1_rmu_disable, .vtu_getnext = mv88e6352_g1_vtu_getnext, .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, @@ -3489,6 +3495,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, + .rmu_enable = mv88e6390_g1_rmu_enable, .rmu_disable = mv88e6390_g1_rmu_disable, .vtu_getnext = mv88e6390_g1_vtu_getnext, .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, @@ -3747,6 +3754,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, + .rmu_enable = mv88e6352_g1_rmu_enable, .rmu_disable = mv88e6352_g1_rmu_disable, .vtu_getnext = mv88e6352_g1_vtu_getnext, .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, @@ -3799,6 +3807,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = { .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, + .rmu_enable = mv88e6390_g1_rmu_enable, .rmu_disable = mv88e6390_g1_rmu_disable, .vtu_getnext = mv88e6390_g1_vtu_getnext, .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, @@ -3848,6 +3857,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = { .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, + .rmu_enable = mv88e6390_g1_rmu_enable, .rmu_disable = mv88e6390_g1_rmu_disable, .vtu_getnext = mv88e6390_g1_vtu_getnext, .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 860816ebb7ee..2af574169e14 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -459,6 +459,7 @@ struct mv88e6xxx_ops { const struct mv88e6xxx_avb_ops *avb_ops; /* Remote Management Unit operations */ + int (*rmu_enable)(struct mv88e6xxx_chip *chip, int port, bool da_check); int (*rmu_disable)(struct mv88e6xxx_chip *chip); /* Precision Time Protocol operations */ diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c index 38e399e0f30e..523a7e297577 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.c +++ b/drivers/net/dsa/mv88e6xxx/global1.c @@ -443,12 +443,68 @@ int mv88e6352_g1_rmu_disable(struct mv88e6xxx_chip *chip) MV88E6352_G1_CTL2_RMU_MODE_DISABLED); } +int mv88e6352_g1_rmu_enable(struct mv88e6xxx_chip *chip, int port, bool da_check) +{ + u16 mask = MV88E6352_G1_CTL2_RMU_MODE_MASK | MV88E6352_G1_CTL2_DA_CHECK; + u16 val; + + switch (port) { + case 4: + val = MV88E6352_G1_CTL2_RMU_MODE_PORT_4; + break; + case 5: + val = MV88E6352_G1_CTL2_RMU_MODE_PORT_5; + break; + case 6: + val = MV88E6352_G1_CTL2_RMU_MODE_PORT_6; + break; + default: + return -EINVAL; + } + + if (da_check) + val |= MV88E6352_G1_CTL2_DA_CHECK; + + return mv88e6xxx_g1_ctl2_mask(chip, mask, val); +} + int mv88e6390_g1_rmu_disable(struct mv88e6xxx_chip *chip) { return mv88e6xxx_g1_ctl2_mask(chip, MV88E6390_G1_CTL2_RMU_MODE_MASK, MV88E6390_G1_CTL2_RMU_MODE_DISABLED); } +int mv88e6390_g1_rmu_enable(struct mv88e6xxx_chip *chip, int port, bool da_check) +{ + u16 mask = MV88E6390_G1_CTL2_RMU_MODE_MASK | MV88E6352_G1_CTL2_DA_CHECK; + u16 val; + + switch (port) { + case 0: + val = MV88E6390_G1_CTL2_RMU_MODE_PORT_0; + break; + case 1: + val = MV88E6390_G1_CTL2_RMU_MODE_PORT_1; + break; + case 9: + val = MV88E6390_G1_CTL2_RMU_MODE_PORT_9; + break; + case 10: + val = MV88E6390_G1_CTL2_RMU_MODE_PORT_10; + break; + default: + /* 88E6390X can enable RMU on all (E)DSA ports as well, + * but let's request a specific port for the moment. + */ + return -EINVAL; + } + + if (da_check) + val |= MV88E6352_G1_CTL2_DA_CHECK; + + return mv88e6xxx_g1_ctl2_mask(chip, mask, val); +} + int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip) { return mv88e6xxx_g1_ctl2_mask(chip, MV88E6390_G1_CTL2_HIST_MODE_MASK, diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h index bef01331266f..c6057cdd547f 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.h +++ b/drivers/net/dsa/mv88e6xxx/global1.h @@ -283,7 +283,9 @@ int mv88e6085_g1_ieee_pri_map(struct mv88e6xxx_chip *chip); int mv88e6185_g1_set_cascade_port(struct mv88e6xxx_chip *chip, int port); int mv88e6085_g1_rmu_disable(struct mv88e6xxx_chip *chip); +int mv88e6352_g1_rmu_enable(struct mv88e6xxx_chip *chip, int port, bool da_check); int mv88e6352_g1_rmu_disable(struct mv88e6xxx_chip *chip); +int mv88e6390_g1_rmu_enable(struct mv88e6xxx_chip *chip, int port, bool da_check); int mv88e6390_g1_rmu_disable(struct mv88e6xxx_chip *chip); int mv88e6xxx_g1_set_device_number(struct mv88e6xxx_chip *chip, int index); -- 2.21.0