Skip to content

Commit

Permalink
soc: intel_adsp/ace: use functions to do CPU power control
Browse files Browse the repository at this point in the history
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.

Signed-off-by: Daniel Leung <[email protected]>
  • Loading branch information
dcpleung committed Jun 28, 2023
1 parent 14573fc commit 8a3a2b7
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 6 deletions.
46 changes: 46 additions & 0 deletions soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm/adsp_power.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
* SPDX-License-Identifier: Apache-2.0
*/

#include <stdint.h>
#include <zephyr/toolchain.h>
#include <zephyr/sys/util_macro.h>
#include <adsp_shim.h>

#ifndef ZEPHYR_SOC_INTEL_ADSP_POWER_H_
Expand Down Expand Up @@ -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_ */
46 changes: 46 additions & 0 deletions soc/xtensa/intel_adsp/ace/include/intel_ace20_lnl/adsp_power.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
#ifndef ZEPHYR_SOC_INTEL_ADSP_POWER_H_
#define ZEPHYR_SOC_INTEL_ADSP_POWER_H_

#include <stdint.h>
#include <zephyr/toolchain.h>
#include <zephyr/sys/util_macro.h>

/* Value used as delay when waiting for hw register state change. */
#define HW_STATE_CHECK_DELAY 64

Expand Down Expand Up @@ -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_ */
6 changes: 3 additions & 3 deletions soc/xtensa/intel_adsp/ace/multiprocessing.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,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);
}

Expand Down Expand Up @@ -194,7 +194,7 @@ int soc_adsp_halt_cpu(int id)
return -EINVAL;
}

ACE_PWRCTL->wpdsphpxpg &= ~BIT(id);
soc_cpu_power_down(id);
return 0;
}
#endif
6 changes: 3 additions & 3 deletions soc/xtensa/intel_adsp/ace/power.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,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);

Expand Down Expand Up @@ -337,9 +337,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);
}

Expand Down

0 comments on commit 8a3a2b7

Please sign in to comment.