[PATCH 14/15] ddr: altera: n5x: reconfigure DDR when mem-clk handoff changes

Chen Huei Lok chen.huei.lok at altera.com
Wed Jul 8 03:12:27 CEST 2026


Trigger a DDR reconfiguration when the memory clock values in the handoff
data have changed, so that a retention restore is not attempted against a
DDR configuration that no longer matches the running mem-clk settings.

Signed-off-by: Chen Huei Lok <chen.huei.lok at altera.com>
---
 .../mach-socfpga/include/mach/handoff_soc64.h |  1 +
 arch/arm/mach-socfpga/wrap_handoff_soc64.c    |  8 ++-
 drivers/ddr/altera/sdram_n5x.c                | 59 ++++++++++++++++++-
 3 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-socfpga/include/mach/handoff_soc64.h b/arch/arm/mach-socfpga/include/mach/handoff_soc64.h
index ae5af1f0100..0fb43acc98b 100644
--- a/arch/arm/mach-socfpga/include/mach/handoff_soc64.h
+++ b/arch/arm/mach-socfpga/include/mach/handoff_soc64.h
@@ -47,6 +47,7 @@
 #define SOC64_HANDOFF_BASE		0x0007F000
 #elif IS_ENABLED(CONFIG_ARCH_SOCFPGA_N5X)
 #define SOC64_HANDOFF_BASE		0xFFE5F000
+#define SOC64_HANDOFF_DDR_CLK_HANDOFF	(SOC64_HANDOFF_BASE + 0x610)
 #define SOC64_HANDOFF_MISC		(SOC64_HANDOFF_BASE + 0x630)
 
 /* DDR handoff */
diff --git a/arch/arm/mach-socfpga/wrap_handoff_soc64.c b/arch/arm/mach-socfpga/wrap_handoff_soc64.c
index ecde90f76f4..bd1160f55bc 100644
--- a/arch/arm/mach-socfpga/wrap_handoff_soc64.c
+++ b/arch/arm/mach-socfpga/wrap_handoff_soc64.c
@@ -27,7 +27,6 @@ static enum endianness check_endianness(u32 handoff)
 	case SOC64_HANDOFF_MAGIC_IOCTL:
 	case SOC64_HANDOFF_MAGIC_FPGA:
 	case SOC64_HANDOFF_MAGIC_DELAY:
-	case SOC64_HANDOFF_MAGIC_CLOCK:
 	case SOC64_HANDOFF_MAGIC_SDRAM:
 #if IS_ENABLED(CONFIG_ARCH_SOCFPGA_AGILEX5)
 	case SOC64_HANDOFF_MAGIC_PERI:
@@ -35,6 +34,13 @@ static enum endianness check_endianness(u32 handoff)
 	case SOC64_HANDOFF_MAGIC_MISC:
 #endif
 		return BIG_ENDIAN;
+	case SOC64_HANDOFF_MAGIC_CLOCK:
+#if IS_ENABLED(CONFIG_ARCH_SOCFPGA_N5X)
+		debug("%s: mem clk  handoff data\n", __func__);
+		return LITTLE_ENDIAN;
+#else
+		return BIG_ENDIAN;
+#endif
 #if IS_ENABLED(CONFIG_ARCH_SOCFPGA_N5X)
 	case SOC64_HANDOFF_DDR_UMCTL2_MAGIC:
 		debug("%s: umctl2 handoff data\n", __func__);
diff --git a/drivers/ddr/altera/sdram_n5x.c b/drivers/ddr/altera/sdram_n5x.c
index f7a26e07cf0..bfa08f62ad6 100644
--- a/drivers/ddr/altera/sdram_n5x.c
+++ b/drivers/ddr/altera/sdram_n5x.c
@@ -38,8 +38,9 @@ DECLARE_GLOBAL_DATA_PTR;
 
 /* DDR handoff SHA384 attribute */
 #define DDR_HANDOFF_IMG_ADDR	0xFFE44000
-#define DDR_HANDOFF_IMG_LEN	0x1A000
+#define DDR_HANDOFF_IMG_LEN	0x1A200
 #define CHUNKSZ_PER_WD_RESET	(256 * 1024)
+#define MEMCLK_HANDOFF_SIZE 0x2C
 
 /* MPFE NOC registers */
 #define FPGA2SDRAM_MGR_MAIN_SIDEBANDMGR_FLAGOUTSET0	0xF8024050
@@ -1106,6 +1107,28 @@ static void phy_ocram(phys_addr_t phy_base, phys_addr_t phy_offset,
 	}
 }
 
+static int populate_memclk_handoff(void *handoff_base, u32 *mclk_table, u32 size)
+{
+	u32 length = MEMCLK_HANDOFF_SIZE - 4;
+	u32 offset = length - 8;
+	u32 handoff_table[length];
+	u32 i;
+	int ret = 0;
+
+	ret = socfpga_handoff_read((void *)handoff_base, handoff_table, length);
+	if (ret) {
+		debug("%s: handoff read failed. ret: %d\n", __func__, ret);
+		return ret;
+	}
+
+	for (i = 0; i < size; i++) {
+		mclk_table[i] = handoff_table[offset + i];
+		debug("mclk_table[%d]: 0x%x\n", i, mclk_table[i]);
+	}
+
+	return ret;
+}
+
 static int cal_data_ocram(phys_addr_t phy_base, u32 addr,
 			  enum data_process proc)
 {
@@ -1391,6 +1414,11 @@ static int cal_data_ocram(phys_addr_t phy_base, u32 addr,
 	size_t phybak_num;
 	const u32 *phybak_p = phybak;
 	u16 *data;
+	u32 memclk_table[4];
+	u32 size = ARRAY_SIZE(memclk_table);
+	u8 *memclk_hash_offset = (u8 *)(SOC64_OCRAM_PHY_BACKUP_BASE - SZ_1K);
+	int ret = 0;
+
 	struct bac_cal_data_t *cal = (struct bac_cal_data_t *)
 					((uintptr_t)addr);
 
@@ -1425,6 +1453,17 @@ static int cal_data_ocram(phys_addr_t phy_base, u32 addr,
 	};
 
 	if (proc == STORE) {
+		ret = populate_memclk_handoff((void *)SOC64_HANDOFF_CLOCK,
+					      memclk_table, size);
+		if (ret) {
+			debug("%s: Memclks config Magic Number miss match. ret :%d\n",
+			      __func__, ret);
+			return -EFAULT;
+		}
+
+		sha384_csum_wd((u8 *)memclk_table, 4 * size,
+			       memclk_hash_offset, CHUNKSZ_PER_WD_RESET);
+
 		/* Creating header */
 		/* Generate HASH384 from the DDR config */
 		sha384_csum_wd((u8 *)DDR_HANDOFF_IMG_ADDR,
@@ -1455,10 +1494,28 @@ static bool is_ddrconfig_hash_match(const void *buffer)
 {
 	int ret;
 	u8 hash[SHA384_SUM_LEN];
+	u32 memclk_table[4];
+	u32 size = ARRAY_SIZE(memclk_table);
 
 	/* Magic symbol in first 4 bytes of header */
 	struct cal_header_t *header = (struct cal_header_t *)buffer;
 
+	/*
+	 * Read and generate the hash for the Mem clk values and store before
+	 * calcuting the HASH384 generation before Image.
+	 */
+	ret = populate_memclk_handoff((void *)SOC64_HANDOFF_CLOCK,
+				      memclk_table, size);
+	if (ret) {
+		debug("%s: Memclks config Magic Number miss match. ret : %d\n",
+		      __func__, ret);
+		return -EFAULT;
+	}
+
+	sha384_csum_wd((u8 *)memclk_table, (4 * sizeof(u32)),
+		       (u8 *)DDR_HANDOFF_IMG_ADDR + DDR_HANDOFF_IMG_LEN - SZ_512,
+		       CHUNKSZ_PER_WD_RESET);
+
 	/* Generate HASH384 from the image */
 	sha384_csum_wd((u8 *)DDR_HANDOFF_IMG_ADDR, DDR_HANDOFF_IMG_LEN,
 		       hash, CHUNKSZ_PER_WD_RESET);
-- 
2.43.7



More information about the U-Boot mailing list