diff options
| author | Serge Semin <fancer.lancer@gmail.com> | 2026-08-07 17:44:03 +0300 |
|---|---|---|
| committer | Serge Semin <fancer.lancer@gmail.com> | 2026-08-13 20:37:17 +0300 |
| commit | e480f0e6acb66a987cd77e72615f9bdd000e56b4 (patch) | |
| tree | 96ff88886acec36a1812d348cb846910c8154f49 | |
| parent | 8f0ed82ac028f4396094b0a4fa330c9b458f4a73 (diff) | |
| download | linux-e480f0e6acb66a987cd77e72615f9bdd000e56b4.tar.gz linux-e480f0e6acb66a987cd77e72615f9bdd000e56b4.zip | |
net: stmmac: Add PHY link status change IRQ support
DW GMAC and DW QoS Ether controllers support getting PHY link status
reported via the RGMII, SGMII or SMII interfaces. The status reading has
already been added in the commit 083757866735 ("net: stmmac: add support
for reading inband SGMII status"). The interface link change support has
been implemented long before that but just recently has been converted to
properly working with phylink. What has been missing is the SRGMII IRQ
enabling and handling in case if in-band getting the status is supported.
Let's do that in the framework of so well prepared PCS module.
Note the stmmac_integrated_pcs_irq() method doesn't pass the link state to
the PCS core intentionally, so to be compatible with the case when
PCS-based AN isn't support. It's relevant for the RGMII in-band PHY-link
status signaling which is going to be added in one of the next commits.
Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c | 5 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 4 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c | 17 |
3 files changed, 21 insertions, 5 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c index fed0e4592090..3714b98cd8c7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c @@ -29,7 +29,8 @@ static const struct stmmac_pcs_info dwmac1000_pcs_info = { .pcs_offset = GMAC_PCS_BASE, .rgsmii_offset = GMAC_RGSMIIIS, .rgsmii_status_mask = GMAC_RSGMIIIS_MASK, - .int_mask = GMAC_INT_DISABLE_PCSLINK | GMAC_INT_DISABLE_PCSAN, + .int_mask = GMAC_INT_DISABLE_RGMII | GMAC_INT_DISABLE_PCSLINK | + GMAC_INT_DISABLE_PCSAN, }; static int dwmac1000_pcs_init(struct stmmac_priv *priv) @@ -656,7 +657,7 @@ static int dwmac1000_irq_status(struct stmmac_priv *priv, x->irq_rx_path_exit_lpi_mode_n++; } - if (intr_status & (PCS_ANE_IRQ | PCS_LINK_IRQ)) + if (intr_status & (PCS_ANE_IRQ | PCS_LINK_IRQ | PCS_RGSMIIIS_IRQ)) stmmac_integrated_pcs_irq(priv, intr_status, x); return ret; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c index 330445306e86..369bc2535e92 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -26,7 +26,7 @@ static const struct stmmac_pcs_info dwmac4_pcs_info = { .pcs_offset = GMAC_PCS_BASE, .rgsmii_offset = GMAC_PHYIF_CONTROL_STATUS, .rgsmii_status_mask = GMAC_PHYIF_CTRLSTATUS_RSGMII_MASK, - .int_mask = GMAC_INT_PCS_LINK | GMAC_INT_PCS_ANE, + .int_mask = GMAC_INT_RGSMIIS | GMAC_INT_PCS_LINK | GMAC_INT_PCS_ANE, }; static int dwmac4_pcs_init(struct stmmac_priv *priv) @@ -721,7 +721,7 @@ static int dwmac4_irq_status(struct stmmac_priv *priv, x->irq_rx_path_exit_lpi_mode_n++; } - if (intr_status & (PCS_ANE_IRQ | PCS_LINK_IRQ)) + if (intr_status & (PCS_ANE_IRQ | PCS_LINK_IRQ | PCS_RGSMIIIS_IRQ)) stmmac_integrated_pcs_irq(priv, intr_status, x); return ret; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c index df72f7c5a6a7..23b56a7ae221 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c @@ -109,6 +109,7 @@ void stmmac_integrated_pcs_irq(struct stmmac_priv *priv, u32 status, { struct stmmac_pcs *spcs = priv->integrated_pcs; u32 val = readl(spcs->base + GMAC_AN_STATUS); + bool link_changed = false; if (status & PCS_ANE_IRQ) { x->irq_pcs_ane_n++; @@ -122,8 +123,22 @@ void stmmac_integrated_pcs_irq(struct stmmac_priv *priv, u32 status, dev_info(priv->device, "PCS Link %s\n", val & BMSR_LSTATUS ? "Up" : "Down"); - phylink_pcs_change(&spcs->pcs, val & BMSR_LSTATUS); + link_changed = true; } + + if (status & PCS_RGSMIIIS_IRQ) { + x->irq_rgmii_n++; + + val = field_get(spcs->rgsmii_status_mask, readl(spcs->rgsmii)); + dev_info(priv->device, "PHY Link %s\n", + val & GMAC_RGSMII_LNKSTS ? "Up" : "Down"); + + link_changed = true; + } + + /* Let phylink re-read the state again for any supported mode */ + if (link_changed) + phylink_pcs_change(&spcs->pcs, false); } int stmmac_integrated_pcs_get_phy_intf_sel(struct phylink_pcs *pcs, |
