From: Padmarao Begari Date: Mon, 30 Sep 2024 04:38:13 +0000 (+0530) Subject: arm64: zynqmp: Print an error for split to lock mode switch X-Git-Url: http://git.dujemihanovic.xyz/?a=commitdiff_plain;h=0ac27a62f9857837739585caa86fdd039556a31d;p=u-boot.git arm64: zynqmp: Print an error for split to lock mode switch The zynqmp tcminit crashes the U-Boot when switching from r5-mode "split" to "lockstep" instead it should throw an error. When cpu is enabled, the check_tcm_mode() function checks if the previous mode is "split", switch mode is "lockstep" then it returns the error code and the initialize_tcm() function is not updating the global control register of the RPU instead it prints the error message. When cpu is disabled, the check_tcm_mode() function returns the success code for switch split to lockstep mode. Signed-off-by: Padmarao Begari Link: https://lore.kernel.org/r/20240930043814.530181-2-padmarao.begari@amd.com Signed-off-by: Michal Simek --- diff --git a/arch/arm/mach-zynqmp/cpu.c b/arch/arm/mach-zynqmp/cpu.c index 24fd575121..5db99e2a73 100644 --- a/arch/arm/mach-zynqmp/cpu.c +++ b/arch/arm/mach-zynqmp/cpu.c @@ -115,9 +115,19 @@ u64 get_page_table_size(void) #if defined(CONFIG_SYS_MEM_RSVD_FOR_MMU) || defined(CONFIG_DEFINE_TCM_OCM_MMAP) void tcm_init(u8 mode) { - puts("WARNING: Initializing TCM overwrites TCM content\n"); - initialize_tcm(mode); - memset((void *)ZYNQMP_TCM_BASE_ADDR, 0, ZYNQMP_TCM_SIZE); + int ret; + + ret = check_tcm_mode(mode); + if (!ret) { + puts("WARNING: Initializing TCM overwrites TCM content\n"); + initialize_tcm(mode); + memset((void *)ZYNQMP_TCM_BASE_ADDR, 0, ZYNQMP_TCM_SIZE); + } + + if (ret == -EACCES) + printf("ERROR: Split to lockstep mode required reset/disable cpu\n"); + + /* Ignore if ret is -EAGAIN, trying to initialize same mode again */ } #endif diff --git a/arch/arm/mach-zynqmp/include/mach/sys_proto.h b/arch/arm/mach-zynqmp/include/mach/sys_proto.h index 15b69e7771..b3396db28f 100644 --- a/arch/arm/mach-zynqmp/include/mach/sys_proto.h +++ b/arch/arm/mach-zynqmp/include/mach/sys_proto.h @@ -48,6 +48,7 @@ enum { unsigned int zynqmp_get_silicon_version(void); +int check_tcm_mode(bool mode); void initialize_tcm(bool mode); void mem_map_fill(void); #if defined(CONFIG_SYS_MEM_RSVD_FOR_MMU) || defined(CONFIG_DEFINE_TCM_OCM_MMAP) diff --git a/arch/arm/mach-zynqmp/mp.c b/arch/arm/mach-zynqmp/mp.c index 9b46a25a1c..6e6da8008f 100644 --- a/arch/arm/mach-zynqmp/mp.c +++ b/arch/arm/mach-zynqmp/mp.c @@ -12,7 +12,9 @@ #include #include #include +#include #include +#include #include #define LOCK 0 @@ -264,6 +266,28 @@ void initialize_tcm(bool mode) } } +int check_tcm_mode(bool mode) +{ + u32 tmp, cpu_state; + bool mode_prev; + + tmp = readl(&rpu_base->rpu_glbl_ctrl); + mode_prev = FIELD_GET(ZYNQMP_RPU_GLBL_CTRL_SPLIT_LOCK_MASK, tmp); + + tmp = readl(&crlapb_base->rst_lpd_top); + cpu_state = FIELD_GET(ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK | + ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK, tmp); + cpu_state = cpu_state ? false : true; + + if ((mode_prev == SPLIT && mode == LOCK) && cpu_state) + return -EACCES; + + if (mode_prev == mode) + return -EAGAIN; + + return 0; +} + static void mark_r5_used(u32 nr, u8 mode) { u32 mask = 0;