The mdio-realtek-rtl9300 driver currently relies on the bootloader to correctly setup polling registers depending on the PHY type. On quite a lot of switches the bootloader only does this in case the user interrupts the boot process and loads firmware via TFTP, otherwise Ethernet remains uninitialized. On some devices the U-Boot environment can be customized so they always initialize the switch and MDIO controller before launching Linux, and rarely vendors decide to just always do it. Setup the polling registers based on the PHYs detected on the bus, and setup registers for non-standard Clause-45 registers used in polling in case the PHY vendor is known and commonly used in those switches. Signed-off-by: Daniel Golle --- drivers/net/mdio/mdio-realtek-rtl9300.c | 82 +++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/drivers/net/mdio/mdio-realtek-rtl9300.c b/drivers/net/mdio/mdio-realtek-rtl9300.c index 405a07075dd11..9e030be497ab3 100644 --- a/drivers/net/mdio/mdio-realtek-rtl9300.c +++ b/drivers/net/mdio/mdio-realtek-rtl9300.c @@ -24,6 +24,9 @@ #define SMI_GLB_CTRL 0xca00 #define GLB_CTRL_INTF_SEL(intf) BIT(16 + (intf)) +#define SMI_MAC_TYPE_CTRL 0xca04 +#define SMI_MAC_TYPE_CTRL_1G 3 +#define SMI_MAC_TYPE_CTRL_2G_PLUS 1 #define SMI_PORT0_15_POLLING_SEL 0xca08 #define SMI_ACCESS_PHY_CTRL_0 0xcb70 #define SMI_ACCESS_PHY_CTRL_1 0xcb74 @@ -43,6 +46,13 @@ #define PHY_CTRL_MMD_DEVAD GENMASK(20, 16) #define PHY_CTRL_MMD_REG GENMASK(15, 0) #define SMI_PORT0_5_ADDR_CTRL 0xcb80 +#define SMI_PRVTE_POLLING_CTRL 0xca10 +#define SMI_10G_POLLING_REG0_CFG 0xcbb4 +#define SMI_10G_POLLING_REG9_CFG 0xcbb8 +#define SMI_10G_POLLING_REG10_CFG 0xcbbc + +#define RTMDIO_PHY_POLL_MMD(dev, reg, bit) \ + (((bit) << 21) | ((dev) << 16) | (reg)) #define MAX_PORTS 28 #define MAX_SMI_BUSSES 4 @@ -56,6 +66,7 @@ struct rtl9300_mdio_priv { u8 smi_addr[MAX_PORTS]; bool smi_bus_is_c45[MAX_SMI_BUSSES]; struct mii_bus *bus[MAX_SMI_BUSSES]; + bool c45_polling_is_setup; }; struct rtl9300_mdio_chan { @@ -350,6 +361,74 @@ static int rtl9300_mdiobus_init(struct rtl9300_mdio_priv *priv) return 0; } +static int rtl9300_register_phy(struct phy_device *phydev) +{ + u32 mask, val, poll_duplex, poll_adv_1000, poll_lpa_1000; + struct mii_bus *bus = phydev->mdio.bus; + struct rtl9300_mdio_chan *chan; + struct rtl9300_mdio_priv *priv; + struct regmap *regmap; + int port, ret; + u8 mac_type; + + chan = bus->priv; + priv = chan->priv; + regmap = priv->regmap; + port = rtl9300_mdio_phy_to_port(bus, phydev->mdio.addr); + + /* Detect if PHY has 2.5G/5G/10G capabilities */ + if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported) || + linkmode_test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, phydev->supported) || + linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, phydev->supported)) + mac_type = SMI_MAC_TYPE_CTRL_2G_PLUS; + else + mac_type = SMI_MAC_TYPE_CTRL_1G; + + mask = port > 23 ? 0x7 << ((port - 24) * 3 + 12) : 0x3 << ((port / 4) * 2); + val = mac_type << (ffs(mask) - 1); + ret = regmap_update_bits(regmap, SMI_MAC_TYPE_CTRL, mask, val); + if (ret < 0) + return ret; + + /* Setup Clause-45 registers to be polled for the first >1G PHY. + * All >1G PHYs connected to the switch SoC have to be of the same type. + */ + if (mac_type == SMI_MAC_TYPE_CTRL_1G || priv->c45_polling_is_setup) + return 0; + + priv->c45_polling_is_setup = true; + + switch (phydev->phy_id & PHY_ID_MATCH_VENDOR_MASK) { + case 0x001cc800: /* RealTek */ + poll_duplex = RTMDIO_PHY_POLL_MMD(MDIO_MMD_VEND2, 0xa400, 8); + poll_adv_1000 = RTMDIO_PHY_POLL_MMD(MDIO_MMD_VEND2, 0xa412, 9); + poll_lpa_1000 = RTMDIO_PHY_POLL_MMD(MDIO_MMD_VEND2, 0xa414, 11); + break; + case 0x03a1b400: /* Aquantia */ + case 0x31c31c00: + poll_duplex = RTMDIO_PHY_POLL_MMD(MDIO_MMD_PMAPMD, MDIO_CTRL1, 8); + poll_adv_1000 = RTMDIO_PHY_POLL_MMD(MDIO_MMD_AN, 0xc400, 15); + poll_lpa_1000 = RTMDIO_PHY_POLL_MMD(MDIO_MMD_AN, 0xe820, 15); + break; + default: + dev_warn(&phydev->mdio.dev, + "Unknown register layout, relying on bootloader network setup.\n"); + return 0; + }; + + ret = regmap_write(regmap, SMI_10G_POLLING_REG0_CFG, poll_duplex); + if (ret < 0) + return ret; + ret = regmap_write(regmap, SMI_10G_POLLING_REG9_CFG, poll_adv_1000); + if (ret < 0) + return ret; + ret = regmap_write(regmap, SMI_10G_POLLING_REG10_CFG, poll_lpa_1000); + if (ret < 0) + return ret; + + return 0; +} + static int rtl9300_mdiobus_probe_one(struct device *dev, struct rtl9300_mdio_priv *priv, struct fwnode_handle *node) { @@ -387,6 +466,7 @@ static int rtl9300_mdiobus_probe_one(struct device *dev, struct rtl9300_mdio_pri bus->write = rtl9300_mdio_write_c22; } bus->parent = dev; + bus->register_phy = rtl9300_register_phy; chan = bus->priv; chan->mdio_bus = mdio_bus; chan->priv = priv; @@ -481,6 +561,8 @@ static int rtl9300_mdiobus_probe(struct platform_device *pdev) if (IS_ERR(priv->regmap)) return PTR_ERR(priv->regmap); + priv->c45_polling_is_setup = false; + platform_set_drvdata(pdev, priv); err = rtl9300_mdiobus_map_ports(dev); -- 2.52.0