realtek: dsa: rtl931x: configure phy ability source

The MAC can get PHY abilities, link status, etc. via different ways. In
RTL931x, the corresponding register needs to be setup properly. By
default, all ports use out-of-band MDIO polling to retrieve that
information. Thus, PHY-backed ports usually work with the default
setting.

For SFP ports, there is no MDIO polling available. Instead, the SerDes
ability bus needs to be used to retrieve the link information.

So far, the bootloader (e.g. U-boot) had to properly initialize that
setting. Instead of relying on that, do that properly during MAC setup.

Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/21351
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
This commit is contained in:
Jonas Jelonek
2026-01-01 20:11:17 +00:00
committed by Hauke Mehrtens
parent e782341848
commit e581929341
3 changed files with 34 additions and 0 deletions

View File

@@ -614,6 +614,10 @@ static int rtl93xx_setup(struct dsa_switch *ds)
}
priv->r->traffic_set(priv->cpu_port, BIT_ULL(priv->cpu_port));
/* Configure how MAC gets PHY ability for each port */
if (priv->family_id == RTL9310_FAMILY_ID)
rtldsa_931x_config_phy_ability_source(priv);
if (priv->family_id == RTL9300_FAMILY_ID)
rtl930x_print_matrix();
else if (priv->family_id == RTL9310_FAMILY_ID)

View File

@@ -182,6 +182,7 @@ void rtl930x_print_matrix(void);
/* RTL931x-specific */
irqreturn_t rtl931x_switch_irq(int irq, void *dev_id);
void rtl931x_print_matrix(void);
void rtldsa_931x_config_phy_ability_source(struct rtl838x_switch_priv *priv);
int rtl83xx_lag_add(struct dsa_switch *ds, int group, int port, struct netdev_lag_upper_info *info);
int rtl83xx_lag_del(struct dsa_switch *ds, int group, int port);

View File

@@ -25,6 +25,11 @@
#define RTL931X_VLAN_PORT_TAG_ITPID_IDX_MASK GENMASK(2, 1)
#define RTL931X_VLAN_PORT_TAG_ITPID_KEEP_MASK GENMASK(0, 0)
#define RTLDSA_931X_SMI_PHY_ABLTY_GET_SEL 0x0cac
#define RTLDSA_931X_PHY_ABLTY_OUTBAND_MDIO 0x0
#define RTLDSA_931X_PHY_ABLTY_INBAND_SDS_POLL 0x1
#define RTLDSA_931X_PHY_ABLTY_SDS_ABLTY_BUS 0x2
/* Definition of the RTL931X-specific template field IDs as used in the PIE */
enum template_field_id {
TEMPLATE_FIELD_SPM0 = 1,
@@ -1764,6 +1769,30 @@ static void rtldsa_931x_qos_init(struct rtl838x_switch_priv *priv)
rtldsa_931x_qos_set_scheduling_queue_weights(priv);
}
void rtldsa_931x_config_phy_ability_source(struct rtl838x_switch_priv *priv)
{
u32 phy_ablty_sel[4] = {0};
for (int port = 0; port < priv->cpu_port; port++) {
u32 val = RTLDSA_931X_PHY_ABLTY_OUTBAND_MDIO;
/* port driven by SerDes */
if (!priv->ports[port].phy && priv->pcs[port])
val = RTLDSA_931X_PHY_ABLTY_SDS_ABLTY_BUS;
phy_ablty_sel[port / 16] |= (val & 0x3) << ((port % 16) * 2);
}
pr_debug("%s: phy_ablty_sel [0] %x [1] %x [2] %x [3] %x\n", __func__,
phy_ablty_sel[0], phy_ablty_sel[1], phy_ablty_sel[2],
phy_ablty_sel[3]);
sw_w32(phy_ablty_sel[0], RTLDSA_931X_SMI_PHY_ABLTY_GET_SEL);
sw_w32(phy_ablty_sel[1], RTLDSA_931X_SMI_PHY_ABLTY_GET_SEL + 0x4);
sw_w32(phy_ablty_sel[2], RTLDSA_931X_SMI_PHY_ABLTY_GET_SEL + 0x8);
sw_w32(phy_ablty_sel[3], RTLDSA_931X_SMI_PHY_ABLTY_GET_SEL + 0xc);
}
const struct rtl838x_reg rtl931x_reg = {
.mask_port_reg_be = rtl839x_mask_port_reg_be,
.set_port_reg_be = rtl839x_set_port_reg_be,