This is a preparation patch for adding SERDES support for mv88e6321 version of the ethernet switch. The patch aims to make mv88e6352_pcs_init, as well as some of serdes functions, more generic so they can be reused for mv88e6321. Changes: 1. Add mv88e6352_serdes_get_lane function which checks if the port supports SERDES by reading G2 global scratch register. Then returns the address of the SERDES lane. 2. Add this function as .serdes_get_lane member to all the chip versions which use mv88e6352_pcs_init. 3. Replace serdes check by global register in mv88e6352_pcs_init function by mv88e6xxx_serdes_get_lane function making it more generic. 4. Replace serdes check in mv88e6352_serdes_get_regs_len by mv88e6xxx_serdes_get_lane. This function is the only other function which checks the scratch register with lock; thus, can call mv88e6xxx_serdes_get_lane instead. 5. Add mv88e6352_serdes_get_regs_from_lane helper function and refactor mv88e6352_serdes_get_regs to call this function with MV88E6352_ADDR_SERDES. The helper function will later be reused for 6321. mv88e6352_serdes_get_regs itself is not reused because mv886exxx_serdes_get_lane cannot be called inside 6352's serdes_get_regs. The reason is 6352's serdes_get_lane requires register lock which has already been locked by the serdes_get_regs's caller function. 6. Add lane argument to mv88e6352_serdes_read so it can be reused later for 6321. Co-developed-by: Thomas Eckerman Signed-off-by: Thomas Eckerman Signed-off-by: Fidan Aliyeva --- drivers/net/dsa/mv88e6xxx/chip.c | 4 ++ drivers/net/dsa/mv88e6xxx/pcs-6352.c | 12 +++--- drivers/net/dsa/mv88e6xxx/serdes.c | 58 +++++++++++++++++++--------- drivers/net/dsa/mv88e6xxx/serdes.h | 1 + 4 files changed, 49 insertions(+), 26 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 8ca5fd40df92..15a8028a02a8 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -4662,6 +4662,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, .stu_getnext = mv88e6352_g1_stu_getnext, .stu_loadpurge = mv88e6352_g1_stu_loadpurge, + .serdes_get_lane = mv88e6352_serdes_get_lane, .serdes_get_regs_len = mv88e6352_serdes_get_regs_len, .serdes_get_regs = mv88e6352_serdes_get_regs, .gpio_ops = &mv88e6352_gpio_ops, @@ -4765,6 +4766,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, .stu_getnext = mv88e6352_g1_stu_getnext, .stu_loadpurge = mv88e6352_g1_stu_loadpurge, + .serdes_get_lane = mv88e6352_serdes_get_lane, .serdes_irq_mapping = mv88e6352_serdes_irq_mapping, .serdes_get_regs_len = mv88e6352_serdes_get_regs_len, .serdes_get_regs = mv88e6352_serdes_get_regs, @@ -5040,6 +5042,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, .stu_getnext = mv88e6352_g1_stu_getnext, .stu_loadpurge = mv88e6352_g1_stu_loadpurge, + .serdes_get_lane = mv88e6352_serdes_get_lane, .serdes_irq_mapping = mv88e6352_serdes_irq_mapping, .serdes_get_regs_len = mv88e6352_serdes_get_regs_len, .serdes_get_regs = mv88e6352_serdes_get_regs, @@ -5475,6 +5478,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { .gpio_ops = &mv88e6352_gpio_ops, .avb_ops = &mv88e6352_avb_ops, .ptp_ops = &mv88e6352_ptp_ops, + .serdes_get_lane = mv88e6352_serdes_get_lane, .serdes_get_sset_count = mv88e6352_serdes_get_sset_count, .serdes_get_strings = mv88e6352_serdes_get_strings, .serdes_get_stats = mv88e6352_serdes_get_stats, diff --git a/drivers/net/dsa/mv88e6xxx/pcs-6352.c b/drivers/net/dsa/mv88e6xxx/pcs-6352.c index 9ebf0f89f817..4228ae5bb9db 100644 --- a/drivers/net/dsa/mv88e6xxx/pcs-6352.c +++ b/drivers/net/dsa/mv88e6xxx/pcs-6352.c @@ -324,19 +324,17 @@ static int mv88e6352_pcs_init(struct mv88e6xxx_chip *chip, int port) struct mii_bus *bus; struct device *dev; unsigned int irq; - int err; + int lane, err; - mv88e6xxx_reg_lock(chip); - err = mv88e6352_g2_scratch_port_has_serdes(chip, port); - mv88e6xxx_reg_unlock(chip); - if (err <= 0) - return err; + lane = mv88e6xxx_serdes_get_lane(chip, port); + if (lane < 0) + return 0; irq = mv88e6xxx_serdes_irq_mapping(chip, port); bus = mv88e6xxx_default_mdio_bus(chip); dev = chip->dev; - mpcs = marvell_c22_pcs_alloc(dev, bus, MV88E6352_ADDR_SERDES); + mpcs = marvell_c22_pcs_alloc(dev, bus, lane); if (!mpcs) return -ENOMEM; diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index a936ee80ce00..273c3b169f65 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c @@ -17,10 +17,10 @@ #include "port.h" #include "serdes.h" -static int mv88e6352_serdes_read(struct mv88e6xxx_chip *chip, int reg, - u16 *val) +static int mv88e6352_serdes_read(struct mv88e6xxx_chip *chip, int lane, + int reg, u16 *val) { - return mv88e6xxx_phy_page_read(chip, MV88E6352_ADDR_SERDES, + return mv88e6xxx_phy_page_read(chip, lane, MV88E6352_SERDES_PAGE_FIBER, reg, val); } @@ -102,6 +102,21 @@ int mv88e6xxx_pcs_decode_state(struct device *dev, u16 bmsr, u16 lpa, return 0; } +int mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) +{ + int err; + + mv88e6xxx_reg_lock(chip); + err = mv88e6352_g2_scratch_port_has_serdes(chip, port); + mv88e6xxx_reg_unlock(chip); + if (err < 0) + return err; + else if (err == 0) + return -ENODEV; + + return MV88E6352_ADDR_SERDES; +} + struct mv88e6352_serdes_hw_stat { char string[ETH_GSTRING_LEN]; int sizeof_stat; @@ -141,14 +156,14 @@ int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, int port, return ARRAY_SIZE(mv88e6352_serdes_hw_stats); } -static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip, +static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip, int lane, struct mv88e6352_serdes_hw_stat *stat) { u64 val = 0; u16 reg; int err; - err = mv88e6352_serdes_read(chip, stat->reg, ®); + err = mv88e6352_serdes_read(chip, lane, stat->reg, ®); if (err) { dev_err(chip->dev, "failed to read statistic\n"); return 0; @@ -157,7 +172,7 @@ static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip, val = reg; if (stat->sizeof_stat == 32) { - err = mv88e6352_serdes_read(chip, stat->reg + 1, ®); + err = mv88e6352_serdes_read(chip, lane, stat->reg + 1, ®); if (err) { dev_err(chip->dev, "failed to read statistic\n"); return 0; @@ -185,7 +200,7 @@ size_t mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) { stat = &mv88e6352_serdes_hw_stats[i]; - value = mv88e6352_serdes_get_stat(chip, stat); + value = mv88e6352_serdes_get_stat(chip, MV88E6352_ADDR_SERDES, stat); mv88e6xxx_port->serdes_stats[i] += value; data[i] = mv88e6xxx_port->serdes_stats[i]; } @@ -200,35 +215,40 @@ unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port) { - int err; + int lane = -ENODEV; - mv88e6xxx_reg_lock(chip); - err = mv88e6352_g2_scratch_port_has_serdes(chip, port); - mv88e6xxx_reg_unlock(chip); - if (err <= 0) - return err; + lane = mv88e6xxx_serdes_get_lane(chip, port); + if (lane < 0) + return 0; return 32 * sizeof(u16); } -void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p) +static void mv88e6352_serdes_get_regs_from_lane(struct mv88e6xxx_chip *chip, int lane, void *_p) { u16 *p = _p; u16 reg; int err; int i; - err = mv88e6352_g2_scratch_port_has_serdes(chip, port); - if (err <= 0) - return; - for (i = 0 ; i < 32; i++) { - err = mv88e6352_serdes_read(chip, i, ®); + err = mv88e6352_serdes_read(chip, lane, i, ®); if (!err) p[i] = reg; } } +void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p) +{ + int err; + + err = mv88e6352_g2_scratch_port_has_serdes(chip, port); + if (err <= 0) + return; + + mv88e6352_serdes_get_regs_from_lane(chip, MV88E6352_ADDR_SERDES, _p); +} + int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) { u8 cmode = chip->ports[port].cmode; diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h index 17a3e85fabaa..21e050b328cc 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.h +++ b/drivers/net/dsa/mv88e6xxx/serdes.h @@ -115,6 +115,7 @@ int mv88e6xxx_pcs_decode_state(struct device *dev, u16 bmsr, u16 lpa, u16 status, struct phylink_link_state *state); int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); +int mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); -- 2.36.0