From 25c6553edde5faab3565165c27d9c1da94a081f9 Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Mon, 26 Jun 2023 10:26:48 -0700 Subject: [PATCH] soc: intel_adsp/ace: use functions to do CPU power control Instead of relying on direct memory access via structs to control CPU power and status, using inline functions instead to hide the details. This makes reading the common code a bit cleaner. The function names are generic and not architecture or platform specific, in an attempt to ease future arch or platform additions with code reuse. Or else we would need to rename these. Signed-off-by: Daniel Leung --- .../ace/include/intel_ace15_mtpm/adsp_power.h | 46 +++++++++++++++++++ .../ace/include/intel_ace20_lnl/adsp_power.h | 46 +++++++++++++++++++ soc/xtensa/intel_adsp/ace/multiprocessing.c | 6 +-- soc/xtensa/intel_adsp/ace/power.c | 6 +-- 4 files changed, 98 insertions(+), 6 deletions(-) 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 b16d64bb653e97..6efcde4a491300 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 @@ -3,6 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include #include #ifndef ZEPHYR_SOC_INTEL_ADSP_POWER_H_ @@ -43,4 +46,47 @@ struct ace_pwrsts { #define ACE_PWRSTS ((volatile struct ace_pwrsts *) &ACE_DfPMCCU.dfpwrsts) +/** + * @brief Power up a specific CPU. + * + * This sets the "not power gating" bit in the power control + * register to disable power gating to CPU, thus powering up + * the CPU. + * + * @param cpu_num CPU to be powered up. + */ +static ALWAYS_INLINE void soc_cpu_power_up(int cpu_num) +{ + ACE_PWRCTL->wpdsphpxpg |= BIT(cpu_num); +} + +/** + * @brief Power down a specific CPU. + * + * This clears the "not power gating" bit in the power control + * register to enable power gating to CPU, thus powering down + * the CPU. + * + * @param cpu_num CPU to be powered down. + */ +static ALWAYS_INLINE void soc_cpu_power_down(int cpu_num) +{ + ACE_PWRCTL->wpdsphpxpg &= ~BIT(cpu_num); +} + +/** + * @brief Test if a CPU is currently powered. + * + * This queries the power status register to see if the CPU + * is currently powered. + * + * @param cpu_num CPU to be queried. + * @return True if CPU is powered, false if now. + */ +static ALWAYS_INLINE bool soc_cpu_is_powered(int cpu_num) +{ + return (ACE_PWRSTS->dsphpxpgs & BIT(cpu_num)) == BIT(cpu_num); +} + + #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 9210a0a7f835b6..60631945da30cc 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 @@ -6,6 +6,10 @@ #ifndef ZEPHYR_SOC_INTEL_ADSP_POWER_H_ #define ZEPHYR_SOC_INTEL_ADSP_POWER_H_ +#include +#include +#include + /* Value used as delay when waiting for hw register state change. */ #define HW_STATE_CHECK_DELAY 64 @@ -42,4 +46,46 @@ struct ace_pwrsts { #define ACE_PWRSTS ((volatile struct ace_pwrsts *)PWRSTS_REG) +/** + * @brief Power up a specific CPU. + * + * This sets the "not power gating" bit in the power control + * register to disable power gating to CPU, thus powering up + * the CPU. + * + * @param cpu_num CPU to be powered up. + */ +static ALWAYS_INLINE void soc_cpu_power_up(int cpu_num) +{ + ACE_PWRCTL->wpdsphpxpg |= BIT(cpu_num); +} + +/** + * @brief Power down a specific CPU. + * + * This clears the "not power gating" bit in the power control + * register to enable power gating to CPU, thus powering down + * the CPU. + * + * @param cpu_num CPU to be powered down. + */ +static ALWAYS_INLINE void soc_cpu_power_down(int cpu_num) +{ + ACE_PWRCTL->wpdsphpxpg &= ~BIT(cpu_num); +} + +/** + * @brief Test if a CPU is currently powered. + * + * This queries the power status register to see if the CPU + * is currently powered. + * + * @param cpu_num CPU to be queried. + * @return True if CPU is powered, false if now. + */ +static ALWAYS_INLINE bool soc_cpu_is_powered(int cpu_num) +{ + return (ACE_PWRSTS->dsphpxpgs & BIT(cpu_num)) == BIT(cpu_num); +} + #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 51901d3d9c80a7..94558c2ca755b5 100644 --- a/soc/xtensa/intel_adsp/ace/multiprocessing.c +++ b/soc/xtensa/intel_adsp/ace/multiprocessing.c @@ -115,9 +115,9 @@ void soc_start_core(int cpu_num) #endif sys_cache_data_flush_range(rom_jump_vector, sizeof(*rom_jump_vector)); - ACE_PWRCTL->wpdsphpxpg |= BIT(cpu_num); + soc_cpu_power_up(cpu_num); - while ((ACE_PWRSTS->dsphpxpgs & BIT(cpu_num)) == 0) { + while (!soc_cpu_is_powered(cpu_num)) { k_busy_wait(HW_STATE_CHECK_DELAY); } @@ -205,7 +205,7 @@ int soc_adsp_halt_cpu(int id) return -EINVAL; } - ACE_PWRCTL->wpdsphpxpg &= ~BIT(id); + soc_cpu_power_down(id); return 0; } #endif diff --git a/soc/xtensa/intel_adsp/ace/power.c b/soc/xtensa/intel_adsp/ace/power.c index 9ac30bfc4cc686..518e0808d3c3a5 100644 --- a/soc/xtensa/intel_adsp/ace/power.c +++ b/soc/xtensa/intel_adsp/ace/power.c @@ -294,7 +294,7 @@ __weak void pm_state_set(enum pm_state state, uint8_t substate_id) } else if (state == PM_STATE_RUNTIME_IDLE) { DSPCS.bootctl[cpu].bctl &= ~DSPBR_BCTL_WAITIPPG; DSPCS.bootctl[cpu].bctl &= ~DSPBR_BCTL_WAITIPCG; - ACE_PWRCTL->wpdsphpxpg &= ~BIT(cpu); + soc_cpu_power_down(cpu); if (cpu == 0) { uint32_t battr = DSPCS.bootctl[cpu].battr & (~LPSCTL_BATTR_MASK); @@ -346,9 +346,9 @@ __weak void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) return; } - ACE_PWRCTL->wpdsphpxpg |= BIT(cpu); + soc_cpu_power_up(cpu); - while ((ACE_PWRSTS->dsphpxpgs & BIT(cpu)) == 0) { + while (!soc_cpu_is_powered(cpu)) { k_busy_wait(HW_STATE_CHECK_DELAY); }