Skip to content

Commit

Permalink
intel_adsp: power: dynamic clock switching
Browse files Browse the repository at this point in the history
This patch adds functionality of a dynamic clock switching by the DSP
during idle.

Signed-off-by: Tomasz Leman <[email protected]>
  • Loading branch information
tmleman authored and abonislawski committed Nov 15, 2023
1 parent e7a093e commit 3a1da41
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 2 deletions.
7 changes: 7 additions & 0 deletions soc/xtensa/intel_adsp/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,11 @@ config ADSP_CPU_DYNAMIC_CLOCK_GATING
(wait for interrupt) during idle. Clock gating will be disabled in which
there is dependence on dependency to CCOUNT value or DSP clock interrupt.

config ADSP_CPU_DYNAMIC_CLOCK_SWITCHING
bool "DSP clock switching in Idle"
help
When true, FW will switch clock if all cores are in idle state. The dynamic
clock change is intended to reduce energy consumption when the DSP is waiting
for interrupt.

endif # SOC_FAMILY_INTEL_ADSP
23 changes: 21 additions & 2 deletions soc/xtensa/intel_adsp/ace/power.c
Original file line number Diff line number Diff line change
Expand Up @@ -381,9 +381,23 @@ void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)

#ifdef CONFIG_ARCH_CPU_IDLE_CUSTOM

extern void adsp_clock_idle_entry(void);
extern void adsp_clock_idle_exit(void);

void arch_cpu_idle(void)
{
sys_trace_idle();
#if CONFIG_ADSP_CPU_DYNAMIC_CLOCK_SWITCHING
/* NOTE: Decreasing a power state lock counter before entering idle. Primary core is
* increasing/decreasing lock counter each time secondary core is powerup/shutdown.
* This way state lock is active for non-idle cores.
*/
pm_policy_state_lock_put(PM_STATE_ACTIVE, 2);

if (pm_policy_state_lock_is_active(PM_STATE_ACTIVE, 2)) {
adsp_clock_idle_entry();
}
#endif /* CONFIG_ADSP_CPU_DYNAMIC_CLOCK_SWITCHING */

#if CONFIG_ADSP_CPU_DYNAMIC_CLOCK_GATING
/* TODO: Add enum for substates (1 -> clock gating) */
Expand All @@ -392,9 +406,14 @@ void arch_cpu_idle(void)
} else {
DSPCS.bootctl[arch_proc_id()].bctl &= ~DSPBR_BCTL_WAITIPCG;
}
#endif
#endif /* CONFIG_ADSP_CPU_DYNAMIC_CLOCK_GATING */

wait_for_interrupt(0);
#if CONFIG_ADSP_CPU_DYNAMIC_CLOCK_SWITCHING
pm_policy_state_lock_get(PM_STATE_ACTIVE, 2);
adsp_clock_idle_exit();
#endif /* CONFIG_ADSP_CPU_DYNAMIC_CLOCK_SWITCHING */
}
#endif
#endif /* CONFIG_ARCH_CPU_IDLE_CUSTOM */

#endif
49 changes: 49 additions & 0 deletions soc/xtensa/intel_adsp/common/clk.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,52 @@ uint32_t adsp_clock_source_frequency(int source)

return adsp_clk_src_info[source].frequency;
}

#ifdef CONFIG_ADSP_CPU_DYNAMIC_CLOCK_SWITCHING
/**
* @brief Clock change counter.
*
* A atomic variable that counts how many times the clock has been tried to be lowered.
*/
atomic_t clock_change_count;

/**
* @brief Clock switch on idle entry.
*
* This function should be called in Idle thread. Intel ADSP can change clock according to
* its needs. But in idle, when core is waiting for interrupt, clock can be change to
* lower frequanze.
*
* @see adsp_clock_idle_exit()
*/
void adsp_clock_idle_entry(void)
{
/* we are already at the lowest clock, there is no need to do anything */
if (platform_cpu_clocks[0].current_freq != platform_cpu_clocks[0].lowest_freq) {
select_cpu_clock_hw(platform_cpu_clocks[0].lowest_freq);
(void)atomic_inc(&clock_change_count);
}
}

/**
* @brief Clock restore on idle exit.
*
* This function must be called when exiting the idle state. During idle entry core could switch
* clock to the lowest frequency and we need to restore previous settings.
*
* @see adsp_clock_idle_entry()
*/
void adsp_clock_idle_exit(void)
{
/* clock has not been changed */
if (!atomic_get(&clock_change_count))
return;

/* If the DSP should run at a higher clock than the lowest, restore this setting */
if (platform_cpu_clocks[0].current_freq != platform_cpu_clocks[0].lowest_freq) {
select_cpu_clock_hw(platform_cpu_clocks[0].current_freq);
(void)atomic_clear(&clock_change_count);
}
}

#endif /* CONFIG_ADSP_CPU_DYNAMIC_CLOCK_SWITCHING */

0 comments on commit 3a1da41

Please sign in to comment.