[PATCH 1/2] arm64: zynqmp: Print an error for split to lock mode switch
Padmarao Begari
padmarao.begari at amd.com
Fri Sep 27 15:59:25 CEST 2024
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 <padmarao.begari at amd.com>
---
arch/arm/mach-zynqmp/cpu.c | 16 ++++++++++---
arch/arm/mach-zynqmp/include/mach/sys_proto.h | 1 +
arch/arm/mach-zynqmp/mp.c | 24 +++++++++++++++++++
3 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-zynqmp/cpu.c b/arch/arm/mach-zynqmp/cpu.c
index 07668c9468..b24c163147 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 <asm/arch/hardware.h>
#include <asm/arch/sys_proto.h>
#include <asm/io.h>
+#include <linux/bitfield.h>
#include <linux/delay.h>
+#include <linux/errno.h>
#include <linux/string.h>
#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;
--
2.25.1
More information about the U-Boot
mailing list