
From: Rick Chen rick@andestech.com
It will work fine due to hart 0 always will be main hart coincidentally. When develop SPL flow, I try to force other harts to be main hart. And it will go wrong in sending IPI flow. So fix it.
Having this fix, any hart can be main hart in U-Boot SPL theoretically, but it still fail somewhere. After dig in and found there is an assumption that hart 0 shall be main hart in OpenSbi.
After some work-arounds, it can pass the verifications that any hart can be main hart and boots U-Boot SPL -> OpenSbi -> U-Boot proper -> Linux Kernel successfully.
Signed-off-by: Rick Chen rick@andestech.com Cc: KC Lin kclin@andestech.com Cc: Alan Kao alankao@andestech.com --- arch/riscv/lib/andes_plic.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/arch/riscv/lib/andes_plic.c b/arch/riscv/lib/andes_plic.c index 28568e4..42394b9 100644 --- a/arch/riscv/lib/andes_plic.c +++ b/arch/riscv/lib/andes_plic.c @@ -19,7 +19,7 @@ #include <cpu.h>
/* pending register */ -#define PENDING_REG(base, hart) ((ulong)(base) + 0x1000 + (hart) * 8) +#define PENDING_REG(base, hart) ((ulong)(base) + 0x1000 + ((hart) / 4) * 4) /* enable register */ #define ENABLE_REG(base, hart) ((ulong)(base) + 0x2000 + (hart) * 0x80) /* claim register */ @@ -46,7 +46,7 @@ static int init_plic(void);
static int enable_ipi(int hart) { - int en; + unsigned int en;
en = ENABLE_HART_IPI >> hart; writel(en, (void __iomem *)ENABLE_REG(gd->arch.plic, hart)); @@ -94,10 +94,13 @@ static int init_plic(void)
int riscv_send_ipi(int hart) { + unsigned int ipi; + PLIC_BASE_GET();
- writel(SEND_IPI_TO_HART(hart), - (void __iomem *)PENDING_REG(gd->arch.plic, gd->arch.boot_hart)); + ipi = (SEND_IPI_TO_HART(hart) << (8 * gd->arch.boot_hart)); + writel(ipi, (void __iomem *)PENDING_REG(gd->arch.plic, + gd->arch.boot_hart));
return 0; }