mirror of
https://github.com/openwrt/openwrt.git
synced 2025-02-18 16:40:29 +00: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:
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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user