[PATCH net-next v2 12/14] net: stmmac: add support for reading inband SGMII status
From: Russell King (Oracle) <hidden>
Date: 2026-01-23 10:04:21
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. v2: - fill in rsgmii offset and status fields in dwmac cores - rename new GMAC_RGSMIII_xxx constants to GMAC_RGSMII_xxx --- .../net/ethernet/stmicro/stmmac/dwmac1000.h | 12 +---- .../ethernet/stmicro/stmmac/dwmac1000_core.c | 2 + drivers/net/ethernet/stmicro/stmmac/dwmac4.h | 10 +--- .../net/ethernet/stmicro/stmmac/dwmac4_core.c | 2 + .../net/ethernet/stmicro/stmmac/stmmac_pcs.c | 46 ++++++++++++++++++- .../net/ethernet/stmicro/stmmac/stmmac_pcs.h | 4 ++ 6 files changed, 54 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
index b3135df0a359..03e8c2534673 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h@@ -70,18 +70,8 @@ enum power_event { #define GMAC_RGSMIIIS 0x000000d8 /* RGMII/SMII status */ /* SGMII/RGMII status register */ -#define GMAC_RGSMIIIS_LNKMODE BIT(0) -#define GMAC_RGSMIIIS_SPEED GENMASK(2, 1) -#define GMAC_RGSMIIIS_LNKSTS BIT(3) -#define GMAC_RGSMIIIS_JABTO BIT(4) -#define GMAC_RGSMIIIS_FALSECARDET BIT(5) +#define GMAC_RSGMIIIS_MASK GENMASK(15, 0) #define GMAC_RGSMIIIS_SMIDRXS BIT(16) -/* LNKMOD */ -#define GMAC_RGSMIIIS_LNKMOD_MASK 0x1 -/* LNKSPEED */ -#define GMAC_RGSMIIIS_SPEED_125 0x2 -#define GMAC_RGSMIIIS_SPEED_25 0x1 -#define GMAC_RGSMIIIS_SPEED_2_5 0x0 /* GMAC Configuration defines */ #define GMAC_CONTROL_2K 0x08000000 /* IEEE 802.3as 2K packets */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index a3ef237de1b8..18a0b678295d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c@@ -24,6 +24,8 @@ static const struct stmmac_pcs_info dwmac1000_pcs_info = { .pcs_offset = GMAC_PCS_BASE, + .rsgmii_offset = GMAC_RGSMIIIS, + .rsgmii_status_mask = GMAC_RSGMIIIS_MASK, .int_mask = GMAC_INT_DISABLE_PCSLINK | GMAC_INT_DISABLE_PCSAN, };
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
index d797d936aee1..ffcd036d4c02 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h@@ -470,15 +470,7 @@ static inline u32 mtl_low_credx_base_addr(const struct dwmac4_addrs *addrs, #define GMAC_PHYIF_CTRLSTATUS_TC BIT(0) #define GMAC_PHYIF_CTRLSTATUS_LUD BIT(1) #define GMAC_PHYIF_CTRLSTATUS_SMIDRXS BIT(4) -#define GMAC_PHYIF_CTRLSTATUS_LNKMOD BIT(16) -#define GMAC_PHYIF_CTRLSTATUS_SPEED GENMASK(18, 17) -#define GMAC_PHYIF_CTRLSTATUS_LNKSTS BIT(19) -#define GMAC_PHYIF_CTRLSTATUS_JABTO BIT(20) -#define GMAC_PHYIF_CTRLSTATUS_FALSECARDET BIT(21) -/* LNKSPEED */ -#define GMAC_PHYIF_CTRLSTATUS_SPEED_125 0x2 -#define GMAC_PHYIF_CTRLSTATUS_SPEED_25 0x1 -#define GMAC_PHYIF_CTRLSTATUS_SPEED_2_5 0x0 +#define GMAC_PHYIF_CTRLSTATUS_RSGMII_MASK GENMASK(31, 16) extern const struct stmmac_dma_ops dwmac4_dma_ops; extern const struct stmmac_dma_ops dwmac410_dma_ops;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index 7f4949229288..e7836bb27a9b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c@@ -24,6 +24,8 @@ static const struct stmmac_pcs_info dwmac4_pcs_info = { .pcs_offset = GMAC_PCS_BASE, + .rsgmii_offset = GMAC_PHYIF_CONTROL_STATUS, + .rsgmii_status_mask = GMAC_PHYIF_CTRLSTATUS_RSGMII_MASK, .int_mask = GMAC_INT_PCS_LINK | GMAC_INT_PCS_ANE, };
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c
index c67041c49d9b..3b450e7f794c 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_RGSMII_LNKMOD BIT(0) +#define GMAC_RGSMII_SPEED_MASK GENMASK(2, 1) +#define GMAC_RGSMII_SPEED_125 2 +#define GMAC_RGSMII_SPEED_25 1 +#define GMAC_RGSMII_SPEED_2_5 0 +#define GMAC_RGSMII_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,
@@ -99,7 +109,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);
@@ -113,7 +123,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_RGSMII_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_RGSMIIS or dwmac4 + * GMAC_PHYIF_CONTROL_STATUS register. + */ + state->duplex = rgsmii & GMAC_RGSMII_LNKMOD ? + DUPLEX_FULL : DUPLEX_HALF; + switch (FIELD_GET(GMAC_RGSMII_SPEED_MASK, rgsmii)) { + case GMAC_RGSMII_SPEED_2_5: + state->speed = SPEED_10; + break; + + case GMAC_RGSMII_SPEED_25: + state->speed = SPEED_100; + break; + + case GMAC_RGSMII_SPEED_125: + state->speed = SPEED_1000; + break; + + default: + state->link = false; + break; + } + } } }
@@ -207,6 +247,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