net: stmmac: xgmac: Correct supported speed modes
authorRohan G Thomas <rohan.g.thomas@altera.com>
Mon, 25 Aug 2025 04:36:53 +0000 (12:36 +0800)
committerJakub Kicinski <kuba@kernel.org>
Wed, 27 Aug 2025 01:12:42 +0000 (18:12 -0700)
Correct supported speed modes as per the XGMAC databook.
Commit 9cb54af214a7 ("net: stmmac: Fix IP-cores specific
MAC capabilities") removes support for 10M, 100M and
1000HD. 1000HD is not supported by XGMAC IP, but it does
support 10M and 100M FD mode for XGMAC version >= 2_20,
and it also supports 10M and 100M HD mode if the HDSEL bit
is set in the MAC_HW_FEATURE0 reg. This commit enables support
for 10M and 100M speed modes for XGMAC IP based on XGMAC
version and MAC capabilities.

Fixes: 9cb54af214a7 ("net: stmmac: Fix IP-cores specific MAC capabilities")
Signed-off-by: Rohan G Thomas <rohan.g.thomas@altera.com>
Reviewed-by: Matthew Gerlach <matthew.gerlach@altera.com>
Link: https://patch.msgid.link/20250825-xgmac-minor-fixes-v3-2-c225fe4444c0@altera.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c

index 6cadf8de4fdfdb18af1a112b883b3d33a53da638..00e929bf280baec7aa8d2a75fc5ceea4a52c9979 100644 (file)
@@ -49,6 +49,14 @@ static void dwxgmac2_core_init(struct mac_device_info *hw,
        writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN);
 }
 
+static void dwxgmac2_update_caps(struct stmmac_priv *priv)
+{
+       if (!priv->dma_cap.mbps_10_100)
+               priv->hw->link.caps &= ~(MAC_10 | MAC_100);
+       else if (!priv->dma_cap.half_duplex)
+               priv->hw->link.caps &= ~(MAC_10HD | MAC_100HD);
+}
+
 static void dwxgmac2_set_mac(void __iomem *ioaddr, bool enable)
 {
        u32 tx = readl(ioaddr + XGMAC_TX_CONFIG);
@@ -1424,6 +1432,7 @@ static void dwxgmac2_set_arp_offload(struct mac_device_info *hw, bool en,
 
 const struct stmmac_ops dwxgmac210_ops = {
        .core_init = dwxgmac2_core_init,
+       .update_caps = dwxgmac2_update_caps,
        .set_mac = dwxgmac2_set_mac,
        .rx_ipc = dwxgmac2_rx_ipc,
        .rx_queue_enable = dwxgmac2_rx_queue_enable,
@@ -1532,8 +1541,8 @@ int dwxgmac2_setup(struct stmmac_priv *priv)
                mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
 
        mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
-                        MAC_1000FD | MAC_2500FD | MAC_5000FD |
-                        MAC_10000FD;
+                        MAC_10 | MAC_100 | MAC_1000FD |
+                        MAC_2500FD | MAC_5000FD | MAC_10000FD;
        mac->link.duplex = 0;
        mac->link.speed10 = XGMAC_CONFIG_SS_10_MII;
        mac->link.speed100 = XGMAC_CONFIG_SS_100_MII;
index 7201a38842651a865493fce0cefe757d6ae9bafa..4d6bb995d8d84cd31b8c552036a647281de06fbb 100644 (file)
@@ -382,8 +382,11 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv,
 static int dwxgmac2_get_hw_feature(void __iomem *ioaddr,
                                   struct dma_features *dma_cap)
 {
+       struct stmmac_priv *priv;
        u32 hw_cap;
 
+       priv = container_of(dma_cap, struct stmmac_priv, dma_cap);
+
        /* MAC HW feature 0 */
        hw_cap = readl(ioaddr + XGMAC_HW_FEATURE0);
        dma_cap->edma = (hw_cap & XGMAC_HWFEAT_EDMA) >> 31;
@@ -406,6 +409,8 @@ static int dwxgmac2_get_hw_feature(void __iomem *ioaddr,
        dma_cap->vlhash = (hw_cap & XGMAC_HWFEAT_VLHASH) >> 4;
        dma_cap->half_duplex = (hw_cap & XGMAC_HWFEAT_HDSEL) >> 3;
        dma_cap->mbps_1000 = (hw_cap & XGMAC_HWFEAT_GMIISEL) >> 1;
+       if (dma_cap->mbps_1000 && priv->synopsys_id >= DWXGMAC_CORE_2_20)
+               dma_cap->mbps_10_100 = 1;
 
        /* MAC HW feature 1 */
        hw_cap = readl(ioaddr + XGMAC_HW_FEATURE1);