[PATCH] lib: utils/hsm: spacemit: wait for the PMU to take a wakeup request

Ahmed Fardi ahmedfardi93 at gmail.com
Wed Nov 4 08:09:37 PST 2026


The PMU clears a hart's wakeup bit about 17 us after it is written. A
second write before that replaces the pending request, so harts started
back to back may never wake up (on a BPI-F3, harts 4-6 stayed off).

Poll for the bit to clear, with a 1 ms timeout.

Signed-off-by: Ahmed Fardi <ahmedfardi93 at gmail.com>
---
Tested on a Banana Pi BPI-F3 (K1) with OP-TEE starting harts 1-7 back to
back: 5 of 8 harts came up before, 8 of 8 with this change. That test ran
on OpenSBI 1.8; this patch is the same change applied to current master.

 lib/utils/hsm/fdt_hsm_spacemit.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/lib/utils/hsm/fdt_hsm_spacemit.c b/lib/utils/hsm/fdt_hsm_spacemit.c
index 4f76b99e..3ccb17db 100644
--- a/lib/utils/hsm/fdt_hsm_spacemit.c
+++ b/lib/utils/hsm/fdt_hsm_spacemit.c
@@ -11,6 +11,7 @@
 #include <sbi/riscv_io.h>
 #include <sbi/sbi_error.h>
 #include <sbi/sbi_hsm.h>
+#include <sbi/sbi_timer.h>
 #include <spacemit/common.h>
 #include <spacemit/k1.h>
 #include <spacemit/k3.h>
@@ -53,15 +54,27 @@ static inline void spacemit_k1_set_cpu_power(u32 hartid, bool enable)
 	writel(value, cpu_idle_base);
 }
 
-static void spacemit_k1_wakeup_cpu(u32 mpidr)
+#define SPACEMIT_K1_WAKEUP_TIMEOUT_US	1000
+
+static int spacemit_k1_wakeup_cpu(u32 mpidr)
 {
 	unsigned int *cpu_reset_base;
 	unsigned int cur_hartid = current_hartid();
+	unsigned int us;
 
 	cpu_reset_base =
 		(unsigned int *)(unsigned long)k1_cpu_wakeup_reg[cur_hartid];
 
 	writel(1 << mpidr, cpu_reset_base);
+
+	/* Wait for the PMU to take the request: a new write would replace it */
+	for (us = 0; us < SPACEMIT_K1_WAKEUP_TIMEOUT_US; us++) {
+		if (!(readl(cpu_reset_base) & (1 << mpidr)))
+			return 0;
+		sbi_timer_udelay(1);
+	}
+
+	return SBI_ETIMEDOUT;
 }
 
 static void spacemit_k1_assert_cpu(void)
@@ -78,9 +91,8 @@ static void spacemit_k1_deassert_cpu(unsigned int hartid)
 static int spacemit_k1_hart_start(unsigned int hartid, unsigned long saddr)
 {
 	spacemit_k1_deassert_cpu(hartid);
-	spacemit_k1_wakeup_cpu(hartid);
 
-	return 0;
+	return spacemit_k1_wakeup_cpu(hartid);
 }
 
 /*
-- 
2.53.0




More information about the opensbi mailing list