[PATCH net-next 12/14] net: stmmac: add support for reading inband SGMII status
From: Russell King (Oracle) <hidden>
Date: 2026-01-19 12:43:01
Also in:
linux-arm-kernel, linux-arm-msm, linux-phy
Subsystem:
networking drivers, stmmac ethernet driver, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
Report the link, speed and duplex for SGMII links, read from the SGMII, RGMII and SMII status and control register. Signed-off-by: Russell King (Oracle) <redacted> --- rfc->v1: fix setting SGMII's link status - depend on both link status. --- .../net/ethernet/stmicro/stmmac/stmmac_pcs.c | 46 ++++++++++++++++++- .../net/ethernet/stmicro/stmmac/stmmac_pcs.h | 4 ++ 2 files changed, 48 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c
index 73fc56ce5e55..9dd7e78cfbc4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c@@ -17,6 +17,16 @@ #define GMAC_ANE_LPA 0x0c /* ANE link partener ability */ #define GMAC_TBI 0x14 /* TBI extend status */ +/* + * RGSMII status bitfield definitions. + */ +#define GMAC_RGSMIII_LNKMOD BIT(0) +#define GMAC_RGSMIII_SPEED_MASK GENMASK(2, 1) +#define GMAC_RGSMIII_SPEED_125 2 +#define GMAC_RGSMIII_SPEED_25 1 +#define GMAC_RGSMIII_SPEED_2_5 0 +#define GMAC_RGSMIII_LNKSTS BIT(3) + static enum ethtool_link_mode_bit_indices dwmac_hd_mode_bits[] = { ETHTOOL_LINK_MODE_10baseT_Half_BIT, ETHTOOL_LINK_MODE_100baseT_Half_BIT,
@@ -97,7 +107,7 @@ static void dwmac_integrated_pcs_get_state(struct phylink_pcs *pcs, struct phylink_link_state *state) { struct stmmac_pcs *spcs = phylink_pcs_to_stmmac_pcs(pcs); - u32 status, lpa; + u32 status, lpa, rgsmii; status = readl(spcs->base + GMAC_AN_STATUS);
@@ -111,7 +121,37 @@ static void dwmac_integrated_pcs_get_state(struct phylink_pcs *pcs, phylink_mii_c22_pcs_decode_state(state, neg_mode, status, lpa); } else { - state->link = false; + rgsmii = field_get(spcs->rgsmii_status_mask, + readl(spcs->rgsmii)); + + state->link = status & BMSR_LSTATUS && + rgsmii & GMAC_RGSMIII_LNKSTS; + + if (state->link && neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { + /* FIXME: fill in speed and duplex. This requires the + * contents of the dwmac1000 GMAC_RGSMIIIS or dwmac4 + * GMAC_PHYIF_CONTROL_STATUS register. + */ + state->duplex = rgsmii & GMAC_RGSMIII_LNKMOD ? + DUPLEX_FULL : DUPLEX_HALF; + switch (FIELD_GET(GMAC_RGSMIII_SPEED_MASK, rgsmii)) { + case GMAC_RGSMIII_SPEED_2_5: + state->speed = SPEED_10; + break; + + case GMAC_RGSMIII_SPEED_25: + state->speed = SPEED_100; + break; + + case GMAC_RGSMIII_SPEED_125: + state->speed = SPEED_1000; + break; + + default: + state->link = false; + break; + } + } } }
@@ -205,6 +245,8 @@ int stmmac_integrated_pcs_init(struct stmmac_priv *priv, spcs->priv = priv; spcs->base = priv->ioaddr + pcs_info->pcs_offset; + spcs->rgsmii = priv->ioaddr + pcs_info->rgsmii_offset; + spcs->rgsmii_status_mask = pcs_info->rgsmii_status_mask; spcs->int_mask = pcs_info->int_mask; spcs->pcs.ops = &dwmac_integrated_pcs_ops;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h
index a7c71f40f952..f9e7a7ed840b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h@@ -29,12 +29,16 @@ struct stmmac_priv; struct stmmac_pcs_info { unsigned int pcs_offset; + unsigned int rgsmii_offset; + u32 rgsmii_status_mask; u32 int_mask; }; struct stmmac_pcs { struct stmmac_priv *priv; void __iomem *base; + void __iomem *rgsmii; + u32 rgsmii_status_mask; u32 int_mask; phy_interface_t interface; struct phylink_pcs pcs;
--
2.47.3