diff options
author | Russell King <rmk+kernel@armlinux.org.uk> | 2020-11-03 13:39:31 +0000 |
---|---|---|
committer | Russell King <rmk+kernel@armlinux.org.uk> | 2020-11-03 13:39:31 +0000 |
commit | 951a1e06dea3b51260f6016d30a4072a8ac12844 (patch) | |
tree | 470803044fcd3454fa729309f75514c83d717051 | |
parent | 055a67a6d1ab6378b589d4e9a06c2d70f46c4ead (diff) | |
parent | 35bb7b3425f66974c9ddbec2e6a30136eeee727e (diff) |
Merge branches 'mvneta' and 'net-queue' into mcbin
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.c | 57 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.h | 2 | ||||
-rw-r--r-- | drivers/net/phy/phylink.c | 44 | ||||
-rw-r--r-- | include/linux/phylink.h | 3 | ||||
-rw-r--r-- | include/net/dsa.h | 2 | ||||
-rw-r--r-- | net/dsa/slave.c | 4 |
6 files changed, 112 insertions, 0 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 545c973fdab3..081222ba46dd 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -659,6 +659,50 @@ static void mv88e6xxx_validate(struct dsa_switch *ds, int port, phylink_helper_basex_speed(state); } +static void mv88e6352_phylink_get_interfaces(struct mv88e6xxx_chip *chip, + int port, + unsigned long *supported) +{ + if (mv88e6xxx_serdes_get_lane(chip, port)) { + /* FIXME: does code for 6352 family support changing between + * SGMII and 1000base-x? + */ + __set_bit(PHY_INTERFACE_MODE_SGMII, supported); + __set_bit(PHY_INTERFACE_MODE_1000BASEX, supported); + } +} + +static void mv88e6341_phylink_get_interfaces(struct mv88e6xxx_chip *chip, + int port, + unsigned long *supported) +{ + if (port == 5) { + __set_bit(PHY_INTERFACE_MODE_SGMII, supported); + __set_bit(PHY_INTERFACE_MODE_1000BASEX, supported); + __set_bit(PHY_INTERFACE_MODE_2500BASEX, supported); + } +} + +static void mv88e6390_phylink_get_interfaces(struct mv88e6xxx_chip *chip, + int port, + unsigned long *supported) +{ + if (port == 9 || port == 10) { + __set_bit(PHY_INTERFACE_MODE_SGMII, supported); + __set_bit(PHY_INTERFACE_MODE_1000BASEX, supported); + __set_bit(PHY_INTERFACE_MODE_2500BASEX, supported); + } +} + +static void mv88e6xxx_get_interfaces(struct dsa_switch *ds, int port, + unsigned long *supported) +{ + struct mv88e6xxx_chip *chip = ds->priv; + + if (chip->info->ops->phylink_get_interfaces) + chip->info->ops->phylink_get_interfaces(chip, port, supported); +} + static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port, unsigned int mode, const struct phylink_link_state *state) @@ -3664,6 +3708,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = { .serdes_irq_enable = mv88e6390_serdes_irq_enable, .serdes_irq_status = mv88e6390_serdes_irq_status, .gpio_ops = &mv88e6352_gpio_ops, + .phylink_get_interfaces = mv88e6341_phylink_get_interfaces, .phylink_validate = mv88e6341_phylink_validate, }; @@ -3832,6 +3877,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { .serdes_get_regs_len = mv88e6352_serdes_get_regs_len, .serdes_get_regs = mv88e6352_serdes_get_regs, .gpio_ops = &mv88e6352_gpio_ops, + .phylink_get_interfaces = mv88e6352_phylink_get_interfaces, .phylink_validate = mv88e6352_phylink_validate, }; @@ -3928,6 +3974,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { .serdes_get_regs_len = mv88e6352_serdes_get_regs_len, .serdes_get_regs = mv88e6352_serdes_get_regs, .gpio_ops = &mv88e6352_gpio_ops, + .phylink_get_interfaces = mv88e6352_phylink_get_interfaces, .phylink_validate = mv88e6352_phylink_validate, }; @@ -4022,6 +4069,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = { .serdes_get_regs_len = mv88e6390_serdes_get_regs_len, .serdes_get_regs = mv88e6390_serdes_get_regs, .gpio_ops = &mv88e6352_gpio_ops, + .phylink_get_interfaces = mv88e6390_phylink_get_interfaces, .phylink_validate = mv88e6390_phylink_validate, }; @@ -4081,6 +4129,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = { .serdes_get_regs_len = mv88e6390_serdes_get_regs_len, .serdes_get_regs = mv88e6390_serdes_get_regs, .gpio_ops = &mv88e6352_gpio_ops, + .phylink_get_interfaces = mv88e6390_phylink_get_interfaces, .phylink_validate = mv88e6390x_phylink_validate, }; @@ -4139,6 +4188,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = { .serdes_get_regs = mv88e6390_serdes_get_regs, .avb_ops = &mv88e6390_avb_ops, .ptp_ops = &mv88e6352_ptp_ops, + .phylink_get_interfaces = mv88e6390_phylink_get_interfaces, .phylink_validate = mv88e6390_phylink_validate, }; @@ -4197,6 +4247,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { .gpio_ops = &mv88e6352_gpio_ops, .avb_ops = &mv88e6352_avb_ops, .ptp_ops = &mv88e6352_ptp_ops, + .phylink_get_interfaces = mv88e6352_phylink_get_interfaces, .phylink_validate = mv88e6352_phylink_validate, }; @@ -4295,6 +4346,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { .gpio_ops = &mv88e6352_gpio_ops, .avb_ops = &mv88e6390_avb_ops, .ptp_ops = &mv88e6352_ptp_ops, + .phylink_get_interfaces = mv88e6390_phylink_get_interfaces, .phylink_validate = mv88e6390_phylink_validate, }; @@ -4432,6 +4484,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = { .gpio_ops = &mv88e6352_gpio_ops, .avb_ops = &mv88e6390_avb_ops, .ptp_ops = &mv88e6352_ptp_ops, + .phylink_get_interfaces = mv88e6341_phylink_get_interfaces, .phylink_validate = mv88e6341_phylink_validate, }; @@ -4575,6 +4628,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { .serdes_get_stats = mv88e6352_serdes_get_stats, .serdes_get_regs_len = mv88e6352_serdes_get_regs_len, .serdes_get_regs = mv88e6352_serdes_get_regs, + .phylink_get_interfaces = mv88e6352_phylink_get_interfaces, .phylink_validate = mv88e6352_phylink_validate, }; @@ -4638,6 +4692,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = { .serdes_get_stats = mv88e6390_serdes_get_stats, .serdes_get_regs_len = mv88e6390_serdes_get_regs_len, .serdes_get_regs = mv88e6390_serdes_get_regs, + .phylink_get_interfaces = mv88e6390_phylink_get_interfaces, .phylink_validate = mv88e6390_phylink_validate, }; @@ -4700,6 +4755,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = { .gpio_ops = &mv88e6352_gpio_ops, .avb_ops = &mv88e6390_avb_ops, .ptp_ops = &mv88e6352_ptp_ops, + .phylink_get_interfaces = mv88e6390_phylink_get_interfaces, .phylink_validate = mv88e6390x_phylink_validate, }; @@ -5566,6 +5622,7 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { .get_tag_protocol = mv88e6xxx_get_tag_protocol, .setup = mv88e6xxx_setup, .teardown = mv88e6xxx_teardown, + .phylink_get_interfaces = mv88e6xxx_get_interfaces, .phylink_validate = mv88e6xxx_validate, .phylink_mac_link_state = mv88e6xxx_serdes_pcs_get_state, .phylink_mac_config = mv88e6xxx_mac_config, diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 823ae89e5fca..648c3b72174e 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -550,6 +550,8 @@ struct mv88e6xxx_ops { const struct mv88e6xxx_ptp_ops *ptp_ops; /* Phylink */ + void (*phylink_get_interfaces)(struct mv88e6xxx_chip *chip, int port, + unsigned long *supported); void (*phylink_validate)(struct mv88e6xxx_chip *chip, int port, unsigned long *mask, struct phylink_link_state *state); diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 6680de39e338..9c4f4e50ec26 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -2406,6 +2406,49 @@ static void phylink_decode_sgmii_word(struct phylink_link_state *state, } /** + * phylink_decode_usxgmii_word() - decode the USXGMII word from a MAC PCS + * @state: a pointer to a struct phylink_link_state. + * @lpa: a 16 bit value which stores the USXGMII auto-negotiation word + * + * Helper for MAC PCS supporting the USXGMII protocol and the auto-negotiation + * code word. Decode the USXGMII code word and populate the corresponding fields + * (speed, duplex) into the phylink_link_state structure. + */ +void phylink_decode_usxgmii_word(struct phylink_link_state *state, + uint16_t lpa) +{ + switch (lpa & MDIO_USXGMII_SPD_MASK) { + case MDIO_USXGMII_10: + state->speed = SPEED_10; + break; + case MDIO_USXGMII_100: + state->speed = SPEED_100; + break; + case MDIO_USXGMII_1000: + state->speed = SPEED_1000; + break; + case MDIO_USXGMII_2500: + state->speed = SPEED_2500; + break; + case MDIO_USXGMII_5000: + state->speed = SPEED_5000; + break; + case MDIO_USXGMII_10G: + state->speed = SPEED_10000; + break; + default: + state->link = false; + return; + } + + if (lpa & MDIO_USXGMII_FULL_DUPLEX) + state->duplex = DUPLEX_FULL; + else + state->duplex = DUPLEX_HALF; +} +EXPORT_SYMBOL_GPL(phylink_decode_usxgmii_word); + +/** * phylink_mii_c22_pcs_get_state() - read the MAC PCS state * @pcs: a pointer to a &struct mdio_device. * @state: a pointer to a &struct phylink_link_state. @@ -2448,6 +2491,7 @@ void phylink_mii_c22_pcs_get_state(struct mdio_device *pcs, break; case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_QSGMII: phylink_decode_sgmii_word(state, lpa); break; diff --git a/include/linux/phylink.h b/include/linux/phylink.h index f19cd028afb0..d2874f815a47 100644 --- a/include/linux/phylink.h +++ b/include/linux/phylink.h @@ -491,4 +491,7 @@ void phylink_mii_c22_pcs_an_restart(struct mdio_device *pcs); void phylink_mii_c45_pcs_get_state(struct mdio_device *pcs, struct phylink_link_state *state); + +void phylink_decode_usxgmii_word(struct phylink_link_state *state, + uint16_t lpa); #endif diff --git a/include/net/dsa.h b/include/net/dsa.h index 75c8fac82017..710900b6019b 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -438,6 +438,8 @@ struct dsa_switch_ops { /* * PHYLINK integration */ + void (*phylink_get_interfaces)(struct dsa_switch *ds, int port, + unsigned long *supported_interfaces); void (*phylink_validate)(struct dsa_switch *ds, int port, unsigned long *supported, struct phylink_link_state *state); diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 16e5f98d4882..0f24d2f28737 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1639,6 +1639,10 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev) dp->pl_config.poll_fixed_state = true; } + if (ds->ops->phylink_get_interfaces) + ds->ops->phylink_get_interfaces(ds, dp->index, + dp->pl_config.supported_interfaces); + dp->pl = phylink_create(&dp->pl_config, of_fwnode_handle(port_dn), mode, &dsa_port_phylink_mac_ops); if (IS_ERR(dp->pl)) { |