From cf5b1f817ece48b0df2204f819669be74f088a38 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Fri, 3 Nov 2023 14:13:37 +0800 Subject: [PATCH] soc: intel_adsp/cavs: add arch_cpu_idle support Cavs platforms starts from Apllolake to Raptorlake. Some of them need some workaround for arch_cpu_idle so create a bespoken one. Each workaround is configured by kconfig setting. Signed-off-by: Rander Wang --- soc/xtensa/intel_adsp/cavs/power.c | 46 ++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/soc/xtensa/intel_adsp/cavs/power.c b/soc/xtensa/intel_adsp/cavs/power.c index bc955b3cb90e214..f2dcfb3565125f7 100644 --- a/soc/xtensa/intel_adsp/cavs/power.c +++ b/soc/xtensa/intel_adsp/cavs/power.c @@ -180,6 +180,52 @@ void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) } #endif /* CONFIG_PM */ +#ifdef CONFIG_ARCH_CPU_IDLE_CUSTOM +/* xt-clang removes any NOPs more than 8. So we need to set + * no optimization to avoid those NOPs from being removed. + * + * This function is simply enough and full of hand written + * assembly that optimization is not really meaningful + * anyway. So we can skip optimization unconditionally. + * Re-evalulate its use and add #ifdef if this assumption + * is no longer valid. + */ + +__no_optimization +void arch_cpu_idle(void) +{ + sys_trace_idle(); + + /* Just spin forever with interrupts unmasked, for platforms + * where WAITI can't be used or where its behavior is + * complicated (Intel DSPs will power gate on idle entry under + * some circumstances) + */ + if (IS_ENABLED(CONFIG_XTENSA_CPU_IDLE_SPIN)) { + __asm__ volatile("rsil a0, 0"); + __asm__ volatile("loop_forever: j loop_forever"); + return; + } + + /* Cribbed from SOF: workaround for a bug in some versions of + * the LX6 IP. Preprocessor ugliness avoids the need to + * figure out how to get the compiler to unroll a loop. + */ + if (IS_ENABLED(CONFIG_XTENSA_WAITI_BUG)) { +#define NOP4 __asm__ volatile("nop; nop; nop; nop"); +#define NOP32 NOP4 NOP4 NOP4 NOP4 NOP4 NOP4 NOP4 NOP4 +#define NOP128() NOP32 NOP32 NOP32 NOP32 + NOP128(); +#undef NOP128 +#undef NOP32 +#undef NOP4 + __asm__ volatile("isync; extw"); + } + +__asm__ volatile ("waiti 0"); +} +#endif + __imr void power_init(void) { /* Request HP ring oscillator and