From: Igor Velkov <[email protected]>

Helios4 has no factory MAC address, so without a saved eth1addr it
gets a random one on every boot. Derive a stable, locally administered
address from the SHA-256 of the 64-bit unique ID of the SPI NOR on the
SoM, the way rockchip_setup_macaddr() does with the CPU ID. A saved
eth1addr still takes precedence.

Signed-off-by: Igor Velkov <[email protected]>
---
Tested on Helios4: two power cycles give the same address and DHCP
uses it. With the same change on v2026.07, Linux gets the address
through the device tree and a saved eth1addr is left untouched.
---
 board/kobol/helios4/helios4.c | 58 +++++++++++++++++++++++++++++++++++++++++++
 configs/helios4_defconfig     |  3 +++
 2 files changed, 61 insertions(+)

diff --git a/board/kobol/helios4/helios4.c b/board/kobol/helios4/helios4.c
index 7714076edf1..342a3cb3c73 100644
--- a/board/kobol/helios4/helios4.c
+++ b/board/kobol/helios4/helios4.c
@@ -5,15 +5,21 @@
  */
 
 #include <config.h>
+#include <env.h>
 #include <i2c.h>
 #include <init.h>
 #include <miiphy.h>
 #include <net.h>
 #include <netdev.h>
+#include <spi-mem.h>
+#include <spi_flash.h>
 #include <asm/global_data.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/soc.h>
+#include <dm/device.h>
+#include <linux/string.h>
+#include <u-boot/sha256.h>
 
 #include "../drivers/ddr/marvell/a38x/ddr3_init.h"
 #include <../serdes/a38x/high_speed_env_spec.h>
@@ -133,3 +139,55 @@ int board_eth_init(struct bd_info *bis)
        cpu_eth_init(bis); /* Built in controller(s) come first */
        return pci_eth_init(bis);
 }
+
+#define SPINOR_OP_RDUID                0x4b
+#define SPINOR_UID_LEN         8
+
+static int helios4_read_flash_uid(u8 *uid)
+{
+       struct spi_mem_op op =
+               SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDUID, 1),
+                          SPI_MEM_OP_NO_ADDR,
+                          SPI_MEM_OP_DUMMY(4, 1),
+                          SPI_MEM_OP_DATA_IN(SPINOR_UID_LEN, uid, 1));
+       struct spi_flash *flash;
+       struct udevice *dev;
+       int ret;
+
+       ret = spi_flash_probe_bus_cs(CONFIG_SF_DEFAULT_BUS,
+                                    CONFIG_SF_DEFAULT_CS, &dev);
+       if (ret)
+               return ret;
+
+       flash = dev_get_uclass_priv(dev);
+       ret = spi_mem_exec_op(flash->spi, &op);
+       if (ret)
+               return ret;
+
+       if (!memchr_inv(uid, 0x00, SPINOR_UID_LEN) ||
+           !memchr_inv(uid, 0xff, SPINOR_UID_LEN))
+               return -ENODATA;
+
+       return 0;
+}
+
+/*
+ * The board has no factory MAC address, so derive a stable one from the
+ * unique ID of the SPI NOR on the SoM.
+ */
+int misc_init_r(void)
+{
+       u8 uid[SPINOR_UID_LEN];
+       u8 mac[SHA256_SUM_LEN];
+
+       /* ethernet@70000 is aliased as ethernet1 */
+       if (env_get("eth1addr") || helios4_read_flash_uid(uid))
+               return 0;
+
+       sha256_csum_wd(uid, sizeof(uid), mac, CHUNKSZ_SHA256);
+       mac[0] &= 0xfe; /* unicast */
+       mac[0] |= 0x02; /* locally administered */
+       eth_env_set_enetaddr("eth1addr", mac);
+
+       return 0;
+}
diff --git a/configs/helios4_defconfig b/configs/helios4_defconfig
index c78a41058c8..328e9e92727 100644
--- a/configs/helios4_defconfig
+++ b/configs/helios4_defconfig
@@ -33,6 +33,7 @@ CONFIG_USE_PREBOOT=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_MISC_INIT_R=y
 CONFIG_SPL_MAX_SIZE=0x22fd0
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_I2C=y
@@ -80,3 +81,5 @@ CONFIG_SYS_NS16550=y
 CONFIG_KIRKWOOD_SPI=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
+CONFIG_SHA256=y
+# CONFIG_SPL_SHA256 is not set

---
base-commit: 5e3b01c8466dbe45cd6a06299f8f4c7e8c1c2363
change-id: 20261011-helios4-flash-uid-mac-1f2a718cac81

Best regards,
-- 
Igor Velkov <[email protected]>


Reply via email to