[openwrt/openwrt] realtek: Add port to smi-bus address mapping
LEDE Commits
lede-commits at lists.infradead.org
Fri Oct 8 23:26:18 PDT 2021
blogic pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/a6678accbd3da00a002158618125af155cc27b37
commit a6678accbd3da00a002158618125af155cc27b37
Author: Birger Koblitz <git at birger-koblitz.de>
AuthorDate: Mon Sep 6 07:24:09 2021 +0200
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 <git at birger-koblitz.de>
---
.../files-5.10/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);
More information about the lede-commits
mailing list