From d75bc8c31011d802106a3724310a193cfbdce39b Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Thu, 5 Aug 2021 11:48:11 -0700 Subject: [PATCH] soc/intel_adsp: Fix MP startup for cAVS 2.5 This hardware works a little differently. The cores will start up immediately on receipt of an IDC interrupt (they don't need the host to be involved), but they don't have a ROM. They start executing at the start of the LP-SRAM block always. Copy over a tiny trampoline for them that jumps to the existing multiprocessor startup path. Also set the PS WOE bit to enable register windows in the startup path. This isn't the hardware default, and where the ROM would do that for us before here we need to make sure it's on. Signed-off-by: Andy Ross --- soc/xtensa/intel_adsp/common/soc_mp.c | 37 ++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/soc/xtensa/intel_adsp/common/soc_mp.c b/soc/xtensa/intel_adsp/common/soc_mp.c index ee5b20f6e13..2580a545ec0 100644 --- a/soc/xtensa/intel_adsp/common/soc_mp.c +++ b/soc/xtensa/intel_adsp/common/soc_mp.c @@ -103,7 +103,8 @@ void z_soc_mp_asm_entry(void); __asm__(".align 4 \n\t" ".global z_soc_mp_asm_entry \n\t" "z_soc_mp_asm_entry: \n\t" - " rsil a0, 5 \n\t" /* 5 == XCHAL_EXCM_LEVEL */ + " movi a0, 0x40025 \n\t" /* WOE | UM | INTLEVEL(5) */ + " wsr a0, PS \n\t" " movi a0, 0 \n\t" " wsr a0, WINDOWBASE \n\t" " movi a0, 1 \n\t" @@ -187,9 +188,39 @@ void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz, uint32_t vecbase; uint32_t idc_reg; - __ASSERT(cpu_num == 1, "Only supports only two CPUs!"); +#ifdef CONFIG_SOC_SERIES_INTEL_CAVS_V25 + /* On cAVS v2.5, MP startup works differently. The core has + * no ROM, and starts running immediately upon receipt of an + * IDC interrupt at the start of LPSRAM at 0xbe800000. Note + * that means we don't need to bother constructing a "message" + * below, it will be ignored. But it's left in place for + * simplicity and compatibility. + * + * All we need to do is place a single jump at that address to + * our existing MP entry point. Unfortunately Xtensa makes + * this difficult, as the region is beyond the range of a + * relative jump instruction, so we need an immediate, which + * can only be backwards-referenced. So we hand-assemble a + * tiny trampoline here ("jump over the immediate address, + * load it, jump to it"). + * + * Long term we want to have this in linkable LP-SRAM memory + * such that the standard system bootstrap out of IMR can + * place it there. But this is fine for now. + */ + void **lpsram = z_soc_uncached_ptr((void *)LP_SRAM_BASE); + uint8_t tramp[] = { + 0x06, 0x01, 0x00, /* J (jump to L32R) */ + 0, /* (padding to align entry_addr) */ + 0, 0, 0, 0, /* (entry_addr goes here) */ + 0x01, 0xff, 0xff, /* L32R a0, */ + 0xa0, 0x00, 0x00, /* JX a0 */ + }; + + memcpy(lpsram, tramp, ARRAY_SIZE(tramp)); + lpsram[1] = z_soc_mp_asm_entry; +#endif - /* Setup data to boot core #1 */ __asm__ volatile("rsr.VECBASE %0\n\t" : "=r"(vecbase)); start_rec.cpu = cpu_num;