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

Reply via email to