1
0
mirror of https://git.openwrt.org/openwrt/openwrt.git synced 2024-10-19 05:58:53 +02:00

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@birger-koblitz.de>
This commit is contained in:
Birger Koblitz 2021-09-06 07:24:09 +02:00 committed by John Crispin
parent 2ab4d40293
commit a6678accbd

@ -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));
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);
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);
// 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));
// 1-to-1 mapping of port to phy-address
for (i = 0; i < 24; i++) {
// 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, i << pos, RTL930X_SMI_PORT0_5_ADDR + (i / 6) * 4);
sw_w32_mask(0x1f << pos, priv->smi_addr[i] << pos,
RTL930X_SMI_PORT0_5_ADDR + (i / 6) * 4);
pos = (i * 2) % 32;
poll_sel[i / 16] |= priv->smi_bus[i] << pos;
poll_ctrl |= BIT(20 + priv->smi_bus[i]);
}
// 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);
// 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);
// 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);
// Enable polling on the respective SMI busses
sw_w32_mask(0, poll_ctrl, RTL930X_SMI_GLB_CTRL);
// SMI bus 1 and 2 speak Clause 45 TODO: Configure from .dts
sw_w32_mask(0, BIT(17) | BIT(18), RTL930X_SMI_GLB_CTRL);
// 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 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);
pr_info("c45_mask: %08x\n", c45_mask);
sw_w32_mask(0, c45_mask, 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);
}
// 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);