diff options
author | Russell King (Oracle) <rmk+kernel@armlinux.org.uk> | 2023-08-12 10:30:33 +0100 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2023-08-14 18:57:17 -0700 |
commit | 479b322ee6feaff612285a0e7f22c022e8cd84eb (patch) | |
tree | d837a1366cd9d73e0caecd44472defe83b057348 | |
parent | f3cc00303cdbc82f719e0cf0dc6f057e8741b5ee (diff) | |
download | linux-stable-479b322ee6feaff612285a0e7f22c022e8cd84eb.tar.gz linux-stable-479b322ee6feaff612285a0e7f22c022e8cd84eb.tar.bz2 linux-stable-479b322ee6feaff612285a0e7f22c022e8cd84eb.zip |
net: dsa: mv88e6060: add phylink_get_caps implementation
Add a phylink_get_caps implementation for Marvell 88e6060 DSA switch.
This is a fast ethernet switch, with internal PHYs for ports 0 through
4. Port 4 also supports MII, REVMII, REVRMII and SNI. Port 5 supports
MII, REVMII, REVRMII and SNI without an internal PHY.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Link: https://lore.kernel.org/r/E1qUkx7-003dMX-9b@rmk-PC.armlinux.org.uk
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r-- | drivers/net/dsa/mv88e6060.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c index fdda62d6eb16..294312b58e4f 100644 --- a/drivers/net/dsa/mv88e6060.c +++ b/drivers/net/dsa/mv88e6060.c @@ -247,11 +247,56 @@ mv88e6060_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) return reg_write(priv, addr, regnum, val); } +static void mv88e6060_phylink_get_caps(struct dsa_switch *ds, int port, + struct phylink_config *config) +{ + unsigned long *interfaces = config->supported_interfaces; + struct mv88e6060_priv *priv = ds->priv; + int addr = REG_PORT(port); + int ret; + + ret = reg_read(priv, addr, PORT_STATUS); + if (ret < 0) { + dev_err(ds->dev, + "port %d: unable to read status register: %pe\n", + port, ERR_PTR(ret)); + return; + } + + /* If the port is configured in SNI mode (acts as a 10Mbps PHY), + * it should have phy-mode = "sni", but that doesn't yet exist, so + * forcibly fail validation until the need arises to introduce it. + */ + if (!(ret & PORT_STATUS_PORTMODE)) { + dev_warn(ds->dev, "port %d: SNI mode not supported\n", port); + return; + } + + config->mac_capabilities = MAC_100 | MAC_10 | MAC_SYM_PAUSE; + + if (port >= 4) { + /* Ports 4 and 5 can support MII, REVMII and REVRMII modes */ + __set_bit(PHY_INTERFACE_MODE_MII, interfaces); + __set_bit(PHY_INTERFACE_MODE_REVMII, interfaces); + __set_bit(PHY_INTERFACE_MODE_REVRMII, interfaces); + } + if (port <= 4) { + /* Ports 0 to 3 have internal PHYs, and port 4 can optionally + * use an internal PHY. + */ + /* Internal PHY */ + __set_bit(PHY_INTERFACE_MODE_INTERNAL, interfaces); + /* Default phylib interface mode */ + __set_bit(PHY_INTERFACE_MODE_GMII, interfaces); + } +} + static const struct dsa_switch_ops mv88e6060_switch_ops = { .get_tag_protocol = mv88e6060_get_tag_protocol, .setup = mv88e6060_setup, .phy_read = mv88e6060_phy_read, .phy_write = mv88e6060_phy_write, + .phylink_get_caps = mv88e6060_phylink_get_caps, }; static int mv88e6060_probe(struct mdio_device *mdiodev) |