summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerge Semin <fancer.lancer@gmail.com>2026-08-07 17:44:03 +0300
committerSerge Semin <fancer.lancer@gmail.com>2026-08-13 20:37:17 +0300
commite480f0e6acb66a987cd77e72615f9bdd000e56b4 (patch)
tree96ff88886acec36a1812d348cb846910c8154f49
parent8f0ed82ac028f4396094b0a4fa330c9b458f4a73 (diff)
downloadlinux-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.c5
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c17
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,