From 1c2243240c94794381ba87342d0dda473d8022af Mon Sep 17 00:00:00 2001 From: Tomasz Leman Date: Wed, 13 Dec 2023 20:39:16 +0100 Subject: [PATCH 1/2] intel_adsp: ace: power: prevent hst domain power gating This commit introduces a mechanism to prevent the power gating of the HST (Host) power domain when the primary core of the audio DSP is active. The power gating prevention is crucial for maintaining the functionality of the HST domain while the primary DSP core is performing critical tasks. Signed-off-by: Tomasz Leman --- .../ace/include/intel_ace15_mtpm/adsp_power.h | 9 +++++++++ .../ace/include/intel_ace20_lnl/adsp_power.h | 10 ++++++++++ soc/xtensa/intel_adsp/ace/multiprocessing.c | 5 +++++ soc/xtensa/intel_adsp/ace/power.c | 14 ++++++++++++++ 4 files changed, 38 insertions(+) diff --git a/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm/adsp_power.h b/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm/adsp_power.h index 6efcde4a491300..594fc414bbc734 100644 --- a/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm/adsp_power.h +++ b/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm/adsp_power.h @@ -88,5 +88,14 @@ static ALWAYS_INLINE bool soc_cpu_is_powered(int cpu_num) return (ACE_PWRSTS->dsphpxpgs & BIT(cpu_num)) == BIT(cpu_num); } +/** + * @brief Retrieve node identifier for Intel ADSP HOST power domain. + */ +#define INTEL_ADSP_HST_DOMAIN_DTNODE DT_NODELABEL(hst_domain) + +/** + * @brief Intel ADSP HOST power domain pointer. + */ +#define INTEL_ADSP_HST_DOMAIN_DEV DEVICE_DT_GET(INTEL_ADSP_HST_DOMAIN_DTNODE) #endif /* ZEPHYR_SOC_INTEL_ADSP_POWER_H_ */ diff --git a/soc/xtensa/intel_adsp/ace/include/intel_ace20_lnl/adsp_power.h b/soc/xtensa/intel_adsp/ace/include/intel_ace20_lnl/adsp_power.h index 60631945da30cc..5d12c79fdcb1aa 100644 --- a/soc/xtensa/intel_adsp/ace/include/intel_ace20_lnl/adsp_power.h +++ b/soc/xtensa/intel_adsp/ace/include/intel_ace20_lnl/adsp_power.h @@ -88,4 +88,14 @@ static ALWAYS_INLINE bool soc_cpu_is_powered(int cpu_num) return (ACE_PWRSTS->dsphpxpgs & BIT(cpu_num)) == BIT(cpu_num); } +/** + * @brief Retrieve node identifier for Intel ADSP HOST power domain. + */ +#define INTEL_ADSP_HST_DOMAIN_DTNODE DT_NODELABEL(hst_domain) + +/** + * @brief Intel ADSP HOST power domain pointer. + */ +#define INTEL_ADSP_HST_DOMAIN_DEV DEVICE_DT_GET(INTEL_ADSP_HST_DOMAIN_DTNODE) + #endif /* ZEPHYR_SOC_INTEL_ADSP_POWER_H_ */ diff --git a/soc/xtensa/intel_adsp/ace/multiprocessing.c b/soc/xtensa/intel_adsp/ace/multiprocessing.c index e762245e669ecb..c6f691a10b6996 100644 --- a/soc/xtensa/intel_adsp/ace/multiprocessing.c +++ b/soc/xtensa/intel_adsp/ace/multiprocessing.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -79,6 +80,10 @@ void soc_mp_init(void) IDC[i].agents[0].ipc.ctl = BIT(0); /* IPCTBIE */ } + int ret = pm_device_runtime_get(INTEL_ADSP_HST_DOMAIN_DEV); + ARG_UNUSED(ret); + __ASSERT(ret == 0, "HST power domain resume operation failed."); + /* Set the core 0 active */ soc_cpus_active[0] = true; } diff --git a/soc/xtensa/intel_adsp/ace/power.c b/soc/xtensa/intel_adsp/ace/power.c index ace2b27d802199..93b4c67f2f4d79 100644 --- a/soc/xtensa/intel_adsp/ace/power.c +++ b/soc/xtensa/intel_adsp/ace/power.c @@ -5,6 +5,7 @@ */ #include #include +#include #include #include #include @@ -235,6 +236,8 @@ void pm_state_set(enum pm_state state, uint8_t substate_id) { ARG_UNUSED(substate_id); uint32_t cpu = arch_proc_id(); + int ret = 0; + ARG_UNUSED(ret); /* save interrupt state and turn off all interrupts */ core_desc[cpu].intenable = XTENSA_RSR("INTENABLE"); @@ -297,6 +300,8 @@ void pm_state_set(enum pm_state state, uint8_t substate_id) hpsram_mask = (1 << ebb_banks) - 1; #endif /* CONFIG_ADSP_POWER_DOWN_HPSRAM */ /* do power down - this function won't return */ + ret = pm_device_runtime_put(INTEL_ADSP_HST_DOMAIN_DEV); + __ASSERT(ret == 0, "HST power domain suspend operation failed."); power_down(true, uncache_to_cache(&hpsram_mask), true); } else { @@ -312,6 +317,9 @@ void pm_state_set(enum pm_state state, uint8_t substate_id) battr |= (DSPBR_BATTR_LPSCTL_RESTORE_BOOT & LPSCTL_BATTR_MASK); DSPCS.bootctl[cpu].battr = battr; } + + ret = pm_device_runtime_put(INTEL_ADSP_HST_DOMAIN_DEV); + __ASSERT(ret == 0, "HST power domain suspend operation failed."); power_gate_entry(cpu); } else { __ASSERT(false, "invalid argument - unsupported power state"); @@ -324,6 +332,12 @@ void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) ARG_UNUSED(substate_id); uint32_t cpu = arch_proc_id(); + if (cpu == 0) { + int ret = pm_device_runtime_get(INTEL_ADSP_HST_DOMAIN_DEV); + ARG_UNUSED(ret); + __ASSERT(ret == 0, "HST power domain resume operation failed."); + } + if (state == PM_STATE_SOFT_OFF) { /* restore clock gating state */ DSPCS.bootctl[cpu].bctl |= From 980f757c8fde4a555d461a44e12a2ba92d4f5a46 Mon Sep 17 00:00:00 2001 From: Tomasz Leman Date: Wed, 13 Dec 2023 22:21:55 +0100 Subject: [PATCH 2/2] intel_adsp: mtl: extra step for hst domain This step for an HST power domain is only required on the ACE 1.5 generation platform. Signed-off-by: Tomasz Leman --- drivers/power_domain/power_domain_intel_adsp.c | 14 ++++++++++++++ .../ace/include/intel_ace15_mtpm/adsp_power.h | 6 ++++++ soc/xtensa/intel_adsp/ace/multiprocessing.c | 9 +++++++++ 3 files changed, 29 insertions(+) diff --git a/drivers/power_domain/power_domain_intel_adsp.c b/drivers/power_domain/power_domain_intel_adsp.c index 47828d6c744e6d..b8b3da7ddd631e 100644 --- a/drivers/power_domain/power_domain_intel_adsp.c +++ b/drivers/power_domain/power_domain_intel_adsp.c @@ -9,6 +9,10 @@ #include #include +#if CONFIG_ACE_VERSION_1_5 +#include +#endif /* CONFIG_ACE_VERSION_1_5 */ + #include LOG_MODULE_REGISTER(power_domain_intel_adsp, LOG_LEVEL_INF); @@ -31,6 +35,16 @@ static int pd_intel_adsp_set_power_enable(struct pg_bits *bits, bool power_enabl return -1; } } else { +#if CONFIG_ACE_VERSION_1_5 + extern uint32_t g_key_read_holder; + + if (bits->SPA_bit == INTEL_ADSP_HST_DOMAIN_BIT) { + volatile uint32_t* key_read_ptr = SRAM_TO_SRAM_ALIAS(&g_key_read_holder); + uint32_t key_value = *key_read_ptr; + if (key_value != INTEL_ADSP_ACE15_MAGIC_KEY) + return -1; + } +#endif sys_write16(sys_read16((mem_addr_t)&ACE_DfPMCCU.dfpwrctl) & ~(SPA_bit_mask), (mem_addr_t)&ACE_DfPMCCU.dfpwrctl); } diff --git a/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm/adsp_power.h b/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm/adsp_power.h index 594fc414bbc734..382b64f1679316 100644 --- a/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm/adsp_power.h +++ b/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm/adsp_power.h @@ -98,4 +98,10 @@ static ALWAYS_INLINE bool soc_cpu_is_powered(int cpu_num) */ #define INTEL_ADSP_HST_DOMAIN_DEV DEVICE_DT_GET(INTEL_ADSP_HST_DOMAIN_DTNODE) +#define INTEL_ADSP_HST_DOMAIN_BIT DT_PROP(INTEL_ADSP_HST_DOMAIN_DTNODE, bit_position) + +#define INTEL_ADSP_ACE15_MAGIC_KEY 0xFFFACE15 + +#define SRAM_TO_SRAM_ALIAS(address) ((__typeof__(address))((((uint32_t)(address)) & 0x1FFFFFFF) | 0x40000000)) + #endif /* ZEPHYR_SOC_INTEL_ADSP_POWER_H_ */ diff --git a/soc/xtensa/intel_adsp/ace/multiprocessing.c b/soc/xtensa/intel_adsp/ace/multiprocessing.c index c6f691a10b6996..caa8ea7fec71cd 100644 --- a/soc/xtensa/intel_adsp/ace/multiprocessing.c +++ b/soc/xtensa/intel_adsp/ace/multiprocessing.c @@ -26,6 +26,11 @@ #define ACE_INTC_IRQ DT_IRQN(DT_NODELABEL(ace_intc)) +#if CONFIG_ACE_VERSION_1_5 +__attribute__((__aligned__(CONFIG_DCACHE_LINE_SIZE))) uint32_t g_key_read_holder; +__attribute__((__aligned__(CONFIG_DCACHE_LINE_SIZE))) unsigned alignment_dummy[0]; +#endif /* CONFIG_ACE_VERSION_1_5 */ + static void ipc_isr(void *arg) { uint32_t cpu_id = arch_proc_id(); @@ -86,6 +91,10 @@ void soc_mp_init(void) /* Set the core 0 active */ soc_cpus_active[0] = true; +#if CONFIG_ACE_VERSION_1_5 + g_key_read_holder = INTEL_ADSP_ACE15_MAGIC_KEY; + sys_cache_data_flush_range(&g_key_read_holder, sizeof(g_key_read_holder)); +#endif /* CONFIG_ACE_VERSION_1_5 */ } #ifdef CONFIG_ADSP_IMR_CONTEXT_SAVE