Skip to content

Commit

Permalink
intel_adsp: power: clock gating in idle
Browse files Browse the repository at this point in the history
This patch add implementation of the dynamic clock gating for ACE
platforms. If clock gating is not desired, an application or other
subsystem can prevent it via clock gating lock get/put API.

If ADSP_DYNAMIC_CLOCK_GATING option is not selected clock gating will be
enabled in HW only during power gating.

Signed-off-by: Tomasz Leman <[email protected]>
  • Loading branch information
tmleman committed Dec 7, 2023
1 parent ed61040 commit f27bbfa
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 5 deletions.
7 changes: 7 additions & 0 deletions soc/xtensa/intel_adsp/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,11 @@ config XTENSA_WAITI_BUG
platforms which prefixes a WAITI entry with 128 NOP
instructions followed by an ISYNC and EXTW.

config ADSP_DYNAMIC_CLOCK_GATING
bool "DSP clock gating in Idle"
help
When true, FW will enable clock gating before core enter WAITI state
(wait for interrupt) during idle. Clock gating will be disabled when
there is a dependency on the CCOUNT value or DSP clock interrupt.

endif # SOC_FAMILY_INTEL_ADSP
10 changes: 7 additions & 3 deletions soc/xtensa/intel_adsp/ace/multiprocessing.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,13 @@ void soc_mp_startup(uint32_t cpu)
/* Must have this enabled always */
z_xtensa_irq_enable(ACE_INTC_IRQ);

/* Prevent idle from powering us off */
DSPCS.bootctl[cpu].bctl |=
DSPBR_BCTL_WAITIPCG | DSPBR_BCTL_WAITIPPG;
#if CONFIG_ADSP_DYNAMIC_CLOCK_GATING
/* Disable idle power gating */
DSPCS.bootctl[cpu].bctl |= DSPBR_BCTL_WAITIPPG;
#else
/* Disable idle power and clock gating */
DSPCS.bootctl[cpu].bctl |= DSPBR_BCTL_WAITIPCG | DSPBR_BCTL_WAITIPPG;
#endif
}

void arch_sched_ipi(void)
Expand Down
47 changes: 45 additions & 2 deletions soc/xtensa/intel_adsp/ace/power.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,13 @@

__imr void power_init(void)
{
#if CONFIG_ADSP_DYNAMIC_CLOCK_GATING
/* Disable idle power gating */
DSPCS.bootctl[0].bctl |= DSPBR_BCTL_WAITIPPG;
#else
/* Disable idle power and clock gating */
DSPCS.bootctl[0].bctl |= DSPBR_BCTL_WAITIPCG | DSPBR_BCTL_WAITIPPG;
#endif
}

#ifdef CONFIG_PM
Expand Down Expand Up @@ -358,8 +363,15 @@ void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
k_panic();
}

DSPCS.bootctl[cpu].bctl |=
DSPBR_BCTL_WAITIPCG | DSPBR_BCTL_WAITIPPG;
#if CONFIG_ADSP_DYNAMIC_CLOCK_GATING
/* If dynamic clock gating feature is enabled we can safely assume that clock
* gating was not prevented in this power flow. DSP cannot go into power gating
* without clock gating.
*/
DSPCS.bootctl[cpu].bctl |= DSPBR_BCTL_WAITIPPG;
#else
DSPCS.bootctl[cpu].bctl |= DSPBR_BCTL_WAITIPCG | DSPBR_BCTL_WAITIPPG;
#endif
if (cpu == 0) {
DSPCS.bootctl[cpu].battr &= (~LPSCTL_BATTR_MASK);
}
Expand All @@ -373,4 +385,35 @@ void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
z_xt_ints_on(core_desc[cpu].intenable);
}

#if CONFIG_ADSP_DYNAMIC_CLOCK_GATING

atomic_t clock_gating_lock;

void adsp_clock_gating_lock_get(void)
{
if (atomic_get(&clock_gating_lock) == 0)
DSPCS.bootctl[arch_proc_id()].bctl |= DSPBR_BCTL_WAITIPCG;

atomic_inc(&clock_gating_lock);
}

void adsp_clock_gating_lock_put(void)
{
atomic_t cnt = atomic_dec(&clock_gating_lock);

ARG_UNUSED(cnt);

__ASSERT(cnt >= 1, "Unbalanced clock gating lock get/put");

if (atomic_get(&clock_gating_lock) == 0)
DSPCS.bootctl[arch_proc_id()].bctl &= ~DSPBR_BCTL_WAITIPCG;
}

bool adsp_clock_gating_lock_is_active(void)
{
return (atomic_get(&clock_gating_lock) != 0);
}

#endif /* CONFIG_ADSP_DYNAMIC_CLOCK_GATING */

#endif
25 changes: 25 additions & 0 deletions soc/xtensa/intel_adsp/common/include/adsp_clk.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,29 @@ bool adsp_clock_source_is_supported(int source);
*/
uint32_t adsp_clock_source_frequency(int source);

#if CONFIG_ADSP_DYNAMIC_CLOCK_GATING

/**
* @brief Increase a power gating lock counter.
*
* @note It is the user's responsibility to ensure that the GET and PUT
* function calls are balanced.
*/
void adsp_clock_gating_lock_get(void);

/**
* @brief Decrease a power gating lock counter.
*/
void adsp_clock_gating_lock_put(void);

/**
* @brief Check if a power gating lock is active (not allowed).
*
* @return true if power gating lock is active.
* @return false if power gating lock is not active.
*/
bool adsp_clock_gating_lock_is_active(void);

#endif /* CONFIG_ADSP_DYNAMIC_CLOCK_GATING */

#endif /* ZEPHYR_SOC_INTEL_ADSP_CAVS_CLK_H_ */

0 comments on commit f27bbfa

Please sign in to comment.