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); }