diff options
author | Florian Fainelli <f.fainelli@gmail.com> | 2018-09-05 21:42:14 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-09-06 16:48:34 +0200 |
commit | a8e8b98531369c9d9f21a81587b630935c64cb59 (patch) | |
tree | 120f10c3d7758fa9429fe6e6a2daeafb14e3f304 /drivers/net/dsa/b53 | |
parent | net: dsa: b53: Add helper to set link parameters (diff) | |
download | linux-a8e8b98531369c9d9f21a81587b630935c64cb59.tar.xz linux-a8e8b98531369c9d9f21a81587b630935c64cb59.zip |
net: dsa: b53: Add PHYLINK support
Add support for PHYLINK, things are reasonably straight forward since we
do not yet support SerDes interfaces, that leaves us with just
MLO_AN_PHY and MLO_AN_FIXED to deal with.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/dsa/b53')
-rw-r--r-- | drivers/net/dsa/b53/b53_common.c | 122 | ||||
-rw-r--r-- | drivers/net/dsa/b53/b53_priv.h | 17 |
2 files changed, 139 insertions, 0 deletions
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 78aeaccf19a1..3d5e822bb17c 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -1109,6 +1109,122 @@ static void b53_adjust_link(struct dsa_switch *ds, int port, p->eee_enabled = b53_eee_init(ds, port, phydev); } +void b53_port_event(struct dsa_switch *ds, int port) +{ + struct b53_device *dev = ds->priv; + bool link; + u16 sts; + + b53_read16(dev, B53_STAT_PAGE, B53_LINK_STAT, &sts); + link = !!(sts & BIT(port)); + dsa_port_phylink_mac_change(ds, port, link); +} +EXPORT_SYMBOL(b53_port_event); + +void b53_phylink_validate(struct dsa_switch *ds, int port, + unsigned long *supported, + struct phylink_link_state *state) +{ + struct b53_device *dev = ds->priv; + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; + + /* Allow all the expected bits */ + phylink_set(mask, Autoneg); + phylink_set_port_modes(mask); + phylink_set(mask, Pause); + phylink_set(mask, Asym_Pause); + + /* With the exclusion of 5325/5365, MII, Reverse MII and 802.3z, we + * support Gigabit, including Half duplex. + */ + if (state->interface != PHY_INTERFACE_MODE_MII && + state->interface != PHY_INTERFACE_MODE_REVMII && + !phy_interface_mode_is_8023z(state->interface) && + !(is5325(dev) || is5365(dev))) { + phylink_set(mask, 1000baseT_Full); + phylink_set(mask, 1000baseT_Half); + } + + if (!phy_interface_mode_is_8023z(state->interface)) { + phylink_set(mask, 10baseT_Half); + phylink_set(mask, 10baseT_Full); + phylink_set(mask, 100baseT_Half); + phylink_set(mask, 100baseT_Full); + } + + bitmap_and(supported, supported, mask, + __ETHTOOL_LINK_MODE_MASK_NBITS); + bitmap_and(state->advertising, state->advertising, mask, + __ETHTOOL_LINK_MODE_MASK_NBITS); + + phylink_helper_basex_speed(state); +} +EXPORT_SYMBOL(b53_phylink_validate); + +int b53_phylink_mac_link_state(struct dsa_switch *ds, int port, + struct phylink_link_state *state) +{ + int ret = -EOPNOTSUPP; + + return ret; +} +EXPORT_SYMBOL(b53_phylink_mac_link_state); + +void b53_phylink_mac_config(struct dsa_switch *ds, int port, + unsigned int mode, + const struct phylink_link_state *state) +{ + struct b53_device *dev = ds->priv; + + if (mode == MLO_AN_PHY) + return; + + if (mode == MLO_AN_FIXED) { + b53_force_port_config(dev, port, state->speed, + state->duplex, state->pause); + return; + } +} +EXPORT_SYMBOL(b53_phylink_mac_config); + +void b53_phylink_mac_an_restart(struct dsa_switch *ds, int port) +{ +} +EXPORT_SYMBOL(b53_phylink_mac_an_restart); + +void b53_phylink_mac_link_down(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface) +{ + struct b53_device *dev = ds->priv; + + if (mode == MLO_AN_PHY) + return; + + if (mode == MLO_AN_FIXED) { + b53_force_link(dev, port, false); + return; + } +} +EXPORT_SYMBOL(b53_phylink_mac_link_down); + +void b53_phylink_mac_link_up(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface, + struct phy_device *phydev) +{ + struct b53_device *dev = ds->priv; + + if (mode == MLO_AN_PHY) + return; + + if (mode == MLO_AN_FIXED) { + b53_force_link(dev, port, true); + return; + } +} +EXPORT_SYMBOL(b53_phylink_mac_link_up); + int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering) { return 0; @@ -1750,6 +1866,12 @@ static const struct dsa_switch_ops b53_switch_ops = { .phy_read = b53_phy_read16, .phy_write = b53_phy_write16, .adjust_link = b53_adjust_link, + .phylink_validate = b53_phylink_validate, + .phylink_mac_link_state = b53_phylink_mac_link_state, + .phylink_mac_config = b53_phylink_mac_config, + .phylink_mac_an_restart = b53_phylink_mac_an_restart, + .phylink_mac_link_down = b53_phylink_mac_link_down, + .phylink_mac_link_up = b53_phylink_mac_link_up, .port_enable = b53_enable_port, .port_disable = b53_disable_port, .get_mac_eee = b53_get_mac_eee, diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h index 2980a5838f58..3f79dc07c00f 100644 --- a/drivers/net/dsa/b53/b53_priv.h +++ b/drivers/net/dsa/b53/b53_priv.h @@ -300,6 +300,23 @@ int b53_br_join(struct dsa_switch *ds, int port, struct net_device *bridge); void b53_br_leave(struct dsa_switch *ds, int port, struct net_device *bridge); void b53_br_set_stp_state(struct dsa_switch *ds, int port, u8 state); void b53_br_fast_age(struct dsa_switch *ds, int port); +void b53_port_event(struct dsa_switch *ds, int port); +void b53_phylink_validate(struct dsa_switch *ds, int port, + unsigned long *supported, + struct phylink_link_state *state); +int b53_phylink_mac_link_state(struct dsa_switch *ds, int port, + struct phylink_link_state *state); +void b53_phylink_mac_config(struct dsa_switch *ds, int port, + unsigned int mode, + const struct phylink_link_state *state); +void b53_phylink_mac_an_restart(struct dsa_switch *ds, int port); +void b53_phylink_mac_link_down(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface); +void b53_phylink_mac_link_up(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface, + struct phy_device *phydev); int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering); int b53_vlan_prepare(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan); |