[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20260126172503.238724-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
Date: Mon, 26 Jan 2026 17:25:03 +0000
From: Prabhakar <prabhakar.csengg@...il.com>
To: Andrew Lunn <andrew+netdev@...n.ch>,
"David S. Miller" <davem@...emloft.net>,
Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>,
Paolo Abeni <pabeni@...hat.com>,
Maxime Coquelin <mcoquelin.stm32@...il.com>,
Alexandre Torgue <alexandre.torgue@...s.st.com>,
Philipp Zabel <p.zabel@...gutronix.de>,
"Russell King (Oracle)" <rmk+kernel@...linux.org.uk>,
Geert Uytterhoeven <geert+renesas@...der.be>,
netdev@...r.kernel.org
Cc: linux-stm32@...md-mailman.stormreply.com,
linux-arm-kernel@...ts.infradead.org,
linux-kernel@...r.kernel.org,
linux-renesas-soc@...r.kernel.org,
Prabhakar <prabhakar.csengg@...il.com>,
Biju Das <biju.das.jz@...renesas.com>,
Fabrizio Castro <fabrizio.castro.jz@...esas.com>,
Lad Prabhakar <prabhakar.mahadev-lad.rj@...renesas.com>
Subject: [RFC PATCH net-next] net: stmmac: Preserve bootloader MAC address across unconditional reset
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@...renesas.com>
Commit 90f522a20e3d1 ("NET: dwmac: Make dwmac reset unconditional")
asserts a reset in probe when a reset controller is present. This reset
clears the MAC address registers, so a valid address programmed by the
bootloader gets lost and the driver falls back to a random address.
Read the MAC address from the hardware registers before resetting the
hardware. Keep the existing address selection logic when no valid
address is found, and program the selected address back into the MAC
after probe so it remains consistent in hardware.
Export stmmac_bus_clks_config() so the early read path can enable the
bus clocks before accessing the MAC registers.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@...renesas.com>
---
Hi all,
Sending this patch as an RFC if there is an alternative/better way to
achieve this.
Cheers,
Prabhakar
---
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 66 ++++++++++++++++++-
.../ethernet/stmicro/stmmac/stmmac_platform.c | 3 +-
.../ethernet/stmicro/stmmac/stmmac_platform.h | 2 +
3 files changed, 69 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 347a0078f622..171bf08d6242 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -44,6 +44,7 @@
#include <net/page_pool/helpers.h>
#include <net/pkt_cls.h>
#include <net/xdp_sock_drv.h>
+#include "stmmac_platform.h"
#include "stmmac_ptp.h"
#include "stmmac_fpe.h"
#include "stmmac.h"
@@ -7659,11 +7660,65 @@ struct plat_stmmacenet_data *stmmac_plat_dat_alloc(struct device *dev)
}
EXPORT_SYMBOL_GPL(stmmac_plat_dat_alloc);
+static int stmmac_read_mac_before_reset(struct stmmac_priv *priv,
+ u8 *mac_addr)
+{
+ unsigned int hi_addr, lo_addr;
+ int ret;
+
+ eth_zero_addr(mac_addr);
+
+ /* Deassert reset to allow hardware access */
+ if (priv->plat->stmmac_rst) {
+ ret = reset_control_deassert(priv->plat->stmmac_rst);
+ if (ret)
+ return ret;
+ }
+
+ /* Enable bus clocks to read MAC address */
+ ret = stmmac_bus_clks_config(priv, true);
+ if (ret) {
+ dev_warn(priv->device, "failed to enable clocks: %d\n", ret);
+ goto assert_reset;
+ }
+
+ switch (priv->plat->core_type) {
+ case DWMAC_CORE_GMAC4:
+ case DWMAC_CORE_XGMAC:
+ /* GMAC4/XGMAC: MAC Address0 High/Low Register */
+ hi_addr = 0x300; /* GMAC_ADDR_HIGH(0) */
+ lo_addr = 0x304; /* GMAC_ADDR_LOW(0) */
+ break;
+ case DWMAC_CORE_GMAC:
+ case DWMAC_CORE_MAC100:
+ /* GMAC/GMAC3/MAC100: MAC Address0 High/Low Register */
+ hi_addr = 0x40; /* GMAC_ADDR_HIGH(0) */
+ lo_addr = 0x44; /* GMAC_ADDR_LOW(0) */
+ break;
+ default:
+ hi_addr = 0;
+ }
+
+ if (hi_addr)
+ stmmac_get_mac_addr(priv->ioaddr, mac_addr, hi_addr, lo_addr);
+
+ ret = 0;
+
+ stmmac_bus_clks_config(priv, false);
+
+assert_reset:
+ if (priv->plat->stmmac_rst)
+ reset_control_assert(priv->plat->stmmac_rst);
+
+ return ret;
+}
+
static int __stmmac_dvr_probe(struct device *device,
struct plat_stmmacenet_data *plat_dat,
struct stmmac_resources *res)
{
struct net_device *ndev = NULL;
+ u8 saved_mac_addr[ETH_ALEN];
struct stmmac_priv *priv;
u32 rxq;
int i, ret = 0;
@@ -7740,6 +7795,9 @@ static int __stmmac_dvr_probe(struct device *device,
if ((phyaddr >= 0) && (phyaddr <= 31))
priv->plat->phy_addr = phyaddr;
+ /* Save MAC address before reset (if bootloader programmed it) */
+ stmmac_read_mac_before_reset(priv, saved_mac_addr);
+
if (priv->plat->stmmac_rst) {
ret = reset_control_assert(priv->plat->stmmac_rst);
reset_control_deassert(priv->plat->stmmac_rst);
@@ -7768,7 +7826,13 @@ static int __stmmac_dvr_probe(struct device *device,
if (priv->synopsys_id < DWMAC_CORE_5_20)
priv->plat->dma_cfg->dche = false;
- stmmac_check_ether_addr(priv);
+ if (is_valid_ether_addr(saved_mac_addr))
+ eth_hw_addr_set(priv->dev, saved_mac_addr);
+ else
+ stmmac_check_ether_addr(priv);
+
+ /* Store the MAC address in hardware */
+ stmmac_set_umac_addr(priv, priv->hw, priv->dev->dev_addr, 0);
ndev->netdev_ops = &stmmac_netdev_ops;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 8979a50b5507..6f0393f2992d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -857,7 +857,7 @@ void stmmac_pltfr_remove(struct platform_device *pdev)
}
EXPORT_SYMBOL_GPL(stmmac_pltfr_remove);
-static int stmmac_bus_clks_config(struct stmmac_priv *priv, bool enabled)
+int stmmac_bus_clks_config(struct stmmac_priv *priv, bool enabled)
{
struct plat_stmmacenet_data *plat_dat = priv->plat;
int ret;
@@ -888,6 +888,7 @@ static int stmmac_bus_clks_config(struct stmmac_priv *priv, bool enabled)
return 0;
}
+EXPORT_SYMBOL_GPL(stmmac_bus_clks_config);
static int __maybe_unused stmmac_runtime_suspend(struct device *dev)
{
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
index 6e6561e29d6e..2d52197020a7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
@@ -20,6 +20,8 @@ struct clk *stmmac_pltfr_find_clk(struct plat_stmmacenet_data *plat_dat,
int stmmac_get_platform_resources(struct platform_device *pdev,
struct stmmac_resources *stmmac_res);
+int stmmac_bus_clks_config(struct stmmac_priv *priv, bool enabled);
+
int stmmac_pltfr_probe(struct platform_device *pdev,
struct plat_stmmacenet_data *plat,
struct stmmac_resources *res);
--
2.52.0
Powered by blists - more mailing lists