aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Funke2022-10-28 14:15:47 +0200
committerMichal Simek2022-12-05 08:55:54 +0100
commitd9efdc7d424ddfdc2aafeee4268435f9f46dd1db (patch)
tree826900f0e798a9abac7a00c724585dfebc1c814f
parentf3558be91e5086f1673d47ba8c430e7640b32e71 (diff)
arm64: zynqmp: dynamically mark r5 cores as used
When Linux boot takes over control of the pmu (by signaling PM_INIT_FINALIZE via ipi), pmu will switch off 'unused' rpu cores. The Xilinx zynqmp fsbl prevents switching off those cores by marking rpu cores as 'used' when loading code partitions to those cores. The current u-boot SPL is missing this behaviour, which results in halting rpu cores during Linux boot. This commit mimics the xilinx zynqmp fsbl behavior by marking r5 cores as used when they are released during boot. Signed-off-by: Lukas Funke <lukas.funke@weidmueller.com> Signed-off-by: Lukas Funke <lukas.funke-oss@weidmueller.com> Link: https://lore.kernel.org/r/20221028121547.26464-2-lukas.funke-oss@weidmueller.com Signed-off-by: Michal Simek <michal.simek@amd.com>
-rw-r--r--arch/arm/mach-zynqmp/include/mach/hardware.h4
-rw-r--r--arch/arm/mach-zynqmp/mp.c26
2 files changed, 29 insertions, 1 deletions
diff --git a/arch/arm/mach-zynqmp/include/mach/hardware.h b/arch/arm/mach-zynqmp/include/mach/hardware.h
index a70d6d611b8..70221e03057 100644
--- a/arch/arm/mach-zynqmp/include/mach/hardware.h
+++ b/arch/arm/mach-zynqmp/include/mach/hardware.h
@@ -175,7 +175,9 @@ struct csu_regs {
#define ZYNQMP_PMU_BASEADDR 0xFFD80000
struct pmu_regs {
- u32 reserved[18];
+ u32 reserved0[16];
+ u32 gen_storage4; /* 0x40 */
+ u32 reserved1[1];
u32 gen_storage6; /* 0x48 */
};
diff --git a/arch/arm/mach-zynqmp/mp.c b/arch/arm/mach-zynqmp/mp.c
index 949456d5309..2891878973e 100644
--- a/arch/arm/mach-zynqmp/mp.c
+++ b/arch/arm/mach-zynqmp/mp.c
@@ -42,6 +42,9 @@
#define ZYNQMP_MAX_CORES 6
+#define ZYNQMP_RPU0_USE_MASK BIT(1)
+#define ZYNQMP_RPU1_USE_MASK BIT(2)
+
int is_core_valid(unsigned int core)
{
if (core < ZYNQMP_MAX_CORES)
@@ -250,6 +253,27 @@ void initialize_tcm(bool mode)
}
}
+static void mark_r5_used(u32 nr, u8 mode)
+{
+ u32 mask = 0;
+
+ if (mode == LOCK) {
+ mask = ZYNQMP_RPU0_USE_MASK | ZYNQMP_RPU1_USE_MASK;
+ } else {
+ switch (nr) {
+ case ZYNQMP_CORE_RPU0:
+ mask = ZYNQMP_RPU0_USE_MASK;
+ break;
+ case ZYNQMP_CORE_RPU1:
+ mask = ZYNQMP_RPU1_USE_MASK;
+ break;
+ default:
+ return;
+ }
+ }
+ zynqmp_mmio_write((ulong)&pmu_base->gen_storage4, mask, mask);
+}
+
int cpu_release(u32 nr, int argc, char *const argv[])
{
if (nr <= ZYNQMP_CORE_APU3) {
@@ -305,6 +329,7 @@ int cpu_release(u32 nr, int argc, char *const argv[])
write_tcm_boot_trampoline(boot_addr_uniq);
dcache_enable();
set_r5_halt_mode(nr, RELEASE, LOCK);
+ mark_r5_used(nr, LOCK);
} else if (!strncmp(argv[1], "split", 5)) {
printf("R5 split mode\n");
set_r5_reset(nr, SPLIT);
@@ -317,6 +342,7 @@ int cpu_release(u32 nr, int argc, char *const argv[])
write_tcm_boot_trampoline(boot_addr_uniq);
dcache_enable();
set_r5_halt_mode(nr, RELEASE, SPLIT);
+ mark_r5_used(nr, SPLIT);
} else {
printf("Unsupported mode\n");
return 1;