From a6678accbd3da00a002158618125af155cc27b37 Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Mon, 6 Sep 2021 07:24:09 +0200 Subject: [PATCH] realtek: Add port to smi-bus address mapping All RTL SoCs addresss PHYs via their port number, which is mapped to an SMI address. Add support for configuring this mapping via the .dts on all SoCs apart from the 839x, where the mapping to the 64 ports is fixed. Signed-off-by: Birger Koblitz --- .../drivers/net/ethernet/rtl838x_eth.c | 101 ++++++++++++------ 1 file changed, 69 insertions(+), 32 deletions(-) diff --git a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c index dfec2e55ee..0d9ced9b6c 100644 --- a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c @@ -47,6 +47,8 @@ extern struct rtl83xx_soc_info soc_info; #define RX_EN_93XX 0x10 #define TX_DO 0x2 #define WRAP 0x2 +#define MAX_PORTS 57 +#define MAX_SMI_BUSSES 4 #define RING_BUFFER 1600 @@ -185,6 +187,10 @@ struct rtl838x_eth_priv { u32 lastEvent; u16 rxrings; u16 rxringlen; + u8 smi_bus[MAX_PORTS]; + u8 smi_addr[MAX_PORTS]; + bool smi_bus_isc45[MAX_SMI_BUSSES]; + bool phy_is_internal[MAX_PORTS]; }; extern int rtl838x_phy_init(struct rtl838x_eth_priv *priv); @@ -1727,52 +1733,56 @@ static int rtl930x_mdio_reset(struct mii_bus *bus) { int i; int pos; + struct rtl838x_eth_priv *priv = bus->priv; + u32 c45_mask = 0; + u32 poll_sel[2]; + u32 poll_ctrl = 0; - pr_info("RTL930X_SMI_PORT0_15_POLLING_SEL %08x 16-27: %08x\n", - sw_r32(RTL930X_SMI_PORT0_15_POLLING_SEL), - sw_r32(RTL930X_SMI_PORT16_27_POLLING_SEL)); + // Mapping of port to phy-addresses on an SMI bus + poll_sel[0] = poll_sel[1] = 0; + for (i = 0; i < 28; i++) { + pos = (i % 6) * 5; + sw_w32_mask(0x1f << pos, priv->smi_addr[i] << pos, + RTL930X_SMI_PORT0_5_ADDR + (i / 6) * 4); - pr_info("%s: Enable SMI polling on SMI bus 0, SMI1, SMI2, disable on SMI3\n", __func__); - sw_w32_mask(BIT(20) | BIT(21) | BIT(22), BIT(23), RTL930X_SMI_GLB_CTRL); + pos = (i * 2) % 32; + poll_sel[i / 16] |= priv->smi_bus[i] << pos; + poll_ctrl |= BIT(20 + priv->smi_bus[i]); + } - pr_info("RTL9300 Powering on SerDes ports\n"); - rtl9300_sds_power(24, 1); - rtl9300_sds_power(25, 1); - rtl9300_sds_power(26, 1); - rtl9300_sds_power(27, 1); - mdelay(200); + // Configure which SMI bus is behind which port number + sw_w32(poll_sel[0], RTL930X_SMI_PORT0_15_POLLING_SEL); + sw_w32(poll_sel[1], RTL930X_SMI_PORT16_27_POLLING_SEL); - // RTL930X_SMI_PORT0_15_POLLING_SEL 55550000 16-27: 00f9aaaa - // i.e SMI=0 for all ports - for (i = 0; i < 5; i++) - pr_info("port phy: %08x\n", sw_r32(RTL930X_SMI_PORT0_5_ADDR + i *4)); + // Enable polling on the respective SMI busses + sw_w32_mask(0, poll_ctrl, RTL930X_SMI_GLB_CTRL); - // 1-to-1 mapping of port to phy-address - for (i = 0; i < 24; i++) { - pos = (i % 6) * 5; - sw_w32_mask(0x1f << pos, i << pos, RTL930X_SMI_PORT0_5_ADDR + (i / 6) * 4); - } + // Configure which SMI busses are polled in c45 based on a c45 PHY being on that bus + for (i = 0; i < 4; i++) + if (priv->smi_bus_isc45[i]) + c45_mask |= BIT(i + 16); - // ports 24 and 25 have PHY addresses 8 and 9, ports 26/27 PHY 26/27 - sw_w32(8 | 9 << 5 | 26 << 10 | 27 << 15, RTL930X_SMI_PORT0_5_ADDR + 4 * 4); + pr_info("c45_mask: %08x\n", c45_mask); + sw_w32_mask(0, c45_mask, RTL930X_SMI_GLB_CTRL); - // Ports 24 and 25 live on SMI bus 1 and 2 - sw_w32_mask(0x3 << 16, 0x1 << 16, RTL930X_SMI_PORT16_27_POLLING_SEL); - sw_w32_mask(0x3 << 18, 0x2 << 18, RTL930X_SMI_PORT16_27_POLLING_SEL); - - // SMI bus 1 and 2 speak Clause 45 TODO: Configure from .dts - sw_w32_mask(0, BIT(17) | BIT(18), RTL930X_SMI_GLB_CTRL); + // Ports 24 to 27 are 2.5 or 10Gig, set this type (1) or (0) for internal SerDes + for (i = 24; i < 28; i++) { + pos = (i - 24) * 3 + 12; + if (priv->phy_is_internal[i]) + sw_w32_mask(0x7 << pos, 0 << pos, RTL930X_SMI_MAC_TYPE_CTRL); + else + sw_w32_mask(0x7 << pos, 1 << pos, RTL930X_SMI_MAC_TYPE_CTRL); + } - // Ports 24 and 25 are 2.5 Gig, set this type (1) - sw_w32_mask(0x7 << 12, 1 << 12, RTL930X_SMI_MAC_TYPE_CTRL); - sw_w32_mask(0x7 << 15, 1 << 15, RTL930X_SMI_MAC_TYPE_CTRL); + // TODO: Set up RTL9300_SMI_10GPHY_POLLING_SEL_0 for Aquantia PHYs on e.g. XGS 1250 return 0; } static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv) { - struct device_node *mii_np; + struct device_node *mii_np, *dn; + u32 pn; int ret; pr_debug("%s called\n", __func__); @@ -1825,6 +1835,33 @@ static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv) priv->mii_bus->priv = priv; priv->mii_bus->parent = &priv->pdev->dev; + for_each_node_by_name(dn, "ethernet-phy") { + u32 smi_addr[2]; + + if (of_property_read_u32(dn, "reg", &pn)) + continue; + + if (of_property_read_u32_array(dn, "rtl9300,smi-address", &smi_addr[0], 2)) { + smi_addr[0] = 0; + smi_addr[1] = pn; + } + + if (pn < MAX_PORTS) { + priv->smi_bus[pn] = smi_addr[0]; + priv->smi_addr[pn] = smi_addr[1]; + } else { + pr_err("%s: illegal port number %d\n", __func__, pn); + } + + if (of_device_is_compatible(dn, "ethernet-phy-ieee802.3-c45")) + priv->smi_bus_isc45[smi_addr[0]] = true; + + if (of_property_read_bool(dn, "phy-is-integrated")) { + priv->phy_is_internal[pn] = true; + } + + } + snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%pOFn", mii_np); ret = of_mdiobus_register(priv->mii_bus, mii_np); -- 2.30.2