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 <[email protected]> --- .../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

