arm64: zynqmp: Fix split mode reset functionality
authorNeal Frager <neal.frager@amd.com>
Wed, 4 May 2022 07:12:26 +0000 (09:12 +0200)
committerMichal Simek <michal.simek@amd.com>
Wed, 18 May 2022 11:17:18 +0000 (13:17 +0200)
This patch fixes two issues in the set_r5_reset function.

1. When in split mode, the lpd_amba_rst bit should only be set when
both r5 cpu cores are in reset. Otherwise, if one r5 core is still
running, setting the lpd_amba_rst bit will cause an error for the
running core. The set_r5_reset function has been modified to check
if the other r5 core is still running before setting the lpd_amba_rst
bit.

2. The cpu_disable function was always assuming that the r5 cores
are in split mode when resetting either core 4 or 5. This is
incorrect for lockstep functionality. This patch adds a function
check_r5_mode to handle the cpu_disable function correctly for
the r5 cores by checking the mode and handling the reset appropriately.

Signed-off-by: Neal Frager <neal.frager@amd.com>
Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/d99cbd7f2394ac055ef27457298f554ff0747ba7.1651648344.git.michal.simek@amd.com
arch/arm/mach-zynqmp/mp.c

index 704520e..4f1ed44 100644 (file)
@@ -102,13 +102,21 @@ static void set_r5_reset(u32 nr, u8 mode)
        u32 tmp;
 
        tmp = readl(&crlapb_base->rst_lpd_top);
-       if (mode == LOCK || nr == ZYNQMP_CORE_RPU0)
-               tmp |= (ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK |
-                       ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK);
-
-       if (mode == LOCK || nr == ZYNQMP_CORE_RPU1)
+       if (mode == LOCK) {
                tmp |= (ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK |
+                       ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK |
                        ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK);
+       } else {
+               if (nr == ZYNQMP_CORE_RPU0) {
+                       tmp |= ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK;
+                       if (tmp & ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK)
+                               tmp |= ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK;
+               } else {
+                       tmp |= ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK;
+                       if (tmp & ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK)
+                               tmp |= ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK;
+               }
+       }
 
        writel(tmp, &crlapb_base->rst_lpd_top);
 }
@@ -142,6 +150,17 @@ static void enable_clock_r5(void)
        udelay(0x500);
 }
 
+static int check_r5_mode(void)
+{
+       u32 tmp;
+
+       tmp = readl(&rpu_base->rpu_glbl_ctrl);
+       if (tmp & ZYNQMP_RPU_GLBL_CTRL_SPLIT_LOCK_MASK)
+               return SPLIT;
+
+       return LOCK;
+}
+
 int cpu_disable(u32 nr)
 {
        if (nr >= ZYNQMP_CORE_APU0 && nr <= ZYNQMP_CORE_APU3) {
@@ -149,7 +168,7 @@ int cpu_disable(u32 nr)
                val |= 1 << nr;
                writel(val, &crfapb_base->rst_fpd_apu);
        } else {
-               set_r5_reset(nr, SPLIT);
+               set_r5_reset(nr, check_r5_mode());
        }
 
        return 0;