From 778b72a507e57bf954f054dd9a6359ff8dee9830 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 3 Jul 2020 16:35:14 +0800 Subject: [PATCH 01/15] host-dma: only do DMA L1 exit at post copy Only set DMA L1 Exit at post copy to reduce the power consumption, this will benefit the KWD scenario as doing the HDA host DMA L1 Exit even no real data is being copied will stop the system to enter s0ix low power stage. Signed-off-by: Keyon Jie --- src/drivers/intel/hda/hda-dma.c | 88 ++------------------------------- 1 file changed, 3 insertions(+), 85 deletions(-) diff --git a/src/drivers/intel/hda/hda-dma.c b/src/drivers/intel/hda/hda-dma.c index 0a3ad0797dea..a35fc8e27fb3 100644 --- a/src/drivers/intel/hda/hda-dma.c +++ b/src/drivers/intel/hda/hda-dma.c @@ -221,18 +221,6 @@ static void hda_dma_get_dbg_vals(struct dma_chan_data *chan, #define hda_dma_ptr_trace(...) #endif -static void hda_dma_l1_entry_notify(void *arg, enum notify_id type, void *data) -{ - /* Notify about Host DMA usage */ - pm_runtime_get(PM_RUNTIME_HOST_DMA_L1, 0); -} - -static void hda_dma_l1_exit_notify(void *arg, enum notify_id type, void *data) -{ - /* Force Host DMA to exit L1 */ - pm_runtime_put(PM_RUNTIME_HOST_DMA_L1, 0); -} - static inline int hda_dma_is_buffer_full(struct dma_chan_data *chan) { return dma_chan_reg_read(chan, DGCS) & DGCS_BF; @@ -293,7 +281,6 @@ static int hda_dma_wait_for_buffer_empty(struct dma_chan_data *chan) static void hda_dma_post_copy(struct dma_chan_data *chan, int bytes) { - struct hda_chan_data *hda_chan = dma_chan_get_data(chan); struct dma_cb_data next = { .channel = chan, .elem = { .size = bytes }, @@ -309,9 +296,8 @@ static void hda_dma_post_copy(struct dma_chan_data *chan, int bytes) */ hda_dma_inc_fp(chan, bytes); - /* Force Host DMA to exit L1 if scheduled on DMA */ - if (!hda_chan->irq_disabled) - pm_runtime_put(PM_RUNTIME_HOST_DMA_L1, 0); + /* Force Host DMA to exit L1 */ + pm_runtime_put(PM_RUNTIME_HOST_DMA_L1, 0); } else { /* * set BFPI to let link gateway know we have read size, @@ -336,60 +322,10 @@ static int hda_dma_link_copy_ch(struct dma_chan_data *chan, int bytes) return 0; } -static int hda_dma_host_start(struct dma_chan_data *channel) -{ - struct hda_chan_data *hda_chan = dma_chan_get_data(channel); - int ret = 0; - - /* Force Host DMA to exit L1 only on start*/ - if (!(hda_chan->state & HDA_STATE_RELEASE)) - pm_runtime_put(PM_RUNTIME_HOST_DMA_L1, 0); - - if (!hda_chan->irq_disabled) - return ret; - - /* Inform about Host DMA usage */ - ret = notifier_register(NULL, scheduler_get_data(SOF_SCHEDULE_LL_TIMER), - NOTIFIER_ID_LL_PRE_RUN, hda_dma_l1_entry_notify, - NOTIFIER_FLAG_AGGREGATE); - if (ret < 0) - tr_err(&hdma_tr, "hda-dmac: %d channel %d, cannot register notification %d", - channel->dma->plat_data.id, channel->index, - ret); - - /* Register common L1 exit for all channels */ - ret = notifier_register(NULL, scheduler_get_data(SOF_SCHEDULE_LL_TIMER), - NOTIFIER_ID_LL_POST_RUN, hda_dma_l1_exit_notify, - NOTIFIER_FLAG_AGGREGATE); - if (ret < 0) - tr_err(&hdma_tr, "hda-dmac: %d channel %d, cannot register notification %d", - channel->dma->plat_data.id, channel->index, - ret); - - return ret; -} - -static void hda_dma_host_stop(struct dma_chan_data *channel) -{ - struct hda_chan_data *hda_chan = dma_chan_get_data(channel); - - if (!hda_chan->irq_disabled) - return; - - /* Unregister L1 entry */ - notifier_unregister(NULL, scheduler_get_data(SOF_SCHEDULE_LL_TIMER), - NOTIFIER_ID_LL_PRE_RUN); - - /* Unregister L1 exit */ - notifier_unregister(NULL, scheduler_get_data(SOF_SCHEDULE_LL_TIMER), - NOTIFIER_ID_LL_POST_RUN); -} - /* lock should be held by caller */ static int hda_dma_enable_unlock(struct dma_chan_data *channel) { struct hda_chan_data *hda_chan; - int ret; tr_info(&hdma_tr, "hda-dmac: %d channel %d -> enable", channel->dma->plat_data.id, channel->index); @@ -404,14 +340,6 @@ static int hda_dma_enable_unlock(struct dma_chan_data *channel) hda_chan = dma_chan_get_data(channel); hda_chan->desc_avail = channel->desc_count; - if (channel->direction == DMA_DIR_HMEM_TO_LMEM || - channel->direction == DMA_DIR_LMEM_TO_HMEM) { - pm_runtime_get(PM_RUNTIME_HOST_DMA_L1, 0); - ret = hda_dma_host_start(channel); - if (ret < 0) - return ret; - } - /* start link output transfer now */ if (channel->direction == DMA_DIR_MEM_TO_DEV && !(hda_chan->state & HDA_STATE_RELEASE)) @@ -436,7 +364,6 @@ static int hda_dma_link_copy(struct dma_chan_data *channel, int bytes, static int hda_dma_host_copy(struct dma_chan_data *channel, int bytes, uint32_t flags) { - struct hda_chan_data *hda_chan = dma_chan_get_data(channel); int ret; tr_dbg(&hdma_tr, "hda-dmac: %d channel %d -> copy 0x%x bytes", @@ -445,8 +372,7 @@ static int hda_dma_host_copy(struct dma_chan_data *channel, int bytes, hda_dma_get_dbg_vals(channel, HDA_DBG_PRE, HDA_DBG_HOST); /* Register Host DMA usage */ - if (!hda_chan->irq_disabled) - pm_runtime_get(PM_RUNTIME_HOST_DMA_L1, 0); + pm_runtime_get(PM_RUNTIME_HOST_DMA_L1, 0); /* blocking mode copy */ if (flags & DMA_COPY_BLOCKING) { @@ -580,10 +506,6 @@ static int hda_dma_release(struct dma_chan_data *channel) */ hda_chan->state |= HDA_STATE_RELEASE; - if (channel->direction == DMA_DIR_HMEM_TO_LMEM || - channel->direction == DMA_DIR_LMEM_TO_HMEM) - ret = hda_dma_host_start(channel); - irq_local_enable(flags); return ret; } @@ -622,10 +544,6 @@ static int hda_dma_stop(struct dma_chan_data *channel) tr_info(&hdma_tr, "hda-dmac: %d channel %d -> stop", channel->dma->plat_data.id, channel->index); - if (channel->direction == DMA_DIR_HMEM_TO_LMEM || - channel->direction == DMA_DIR_LMEM_TO_HMEM) - hda_dma_host_stop(channel); - /* disable the channel */ dma_chan_reg_update_bits(channel, DGCS, DGCS_GEN | DGCS_FIFORDY, 0); channel->status = COMP_STATE_PREPARE; From 27bb843fba9bd9f00b55f171c29b56f46ea1e898 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Tue, 30 Jun 2020 17:07:30 +0800 Subject: [PATCH 02/15] detect_test: refine the activation threshold to fix trigger issue Refine to use the consistent activation threshold for different formats, use a unified coefficient 0.05, and update the threshold at .params(). These refinement will fix the KWD trigger volume inconsistent for different sample format issue. Signed-off-by: Keyon Jie --- src/audio/detect_test.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/audio/detect_test.c b/src/audio/detect_test.c index 6dd9684a5b68..9e2031988e23 100644 --- a/src/audio/detect_test.c +++ b/src/audio/detect_test.c @@ -33,15 +33,14 @@ #include #define ACTIVATION_DEFAULT_SHIFT 3 -#define ACTIVATION_DEFAULT_DIVIDER_S16 0.5 -#define ACTIVATION_DEFAULT_DIVIDER_S24 0.05 +#define ACTIVATION_DEFAULT_COEF 0.05 #define ACTIVATION_DEFAULT_THRESHOLD_S16 \ - ((int16_t)((INT16_MAX) * (ACTIVATION_DEFAULT_DIVIDER_S16))) + Q_CONVERT_FLOAT(ACTIVATION_DEFAULT_COEF, 15) /* Q1.15 */ #define ACTIVATION_DEFAULT_THRESHOLD_S24 \ - ((int32_t)((INT24_MAXVALUE) * (ACTIVATION_DEFAULT_DIVIDER_S24))) + Q_CONVERT_FLOAT(ACTIVATION_DEFAULT_COEF, 23) /* Q1.23 */ #define ACTIVATION_DEFAULT_THRESHOLD_S32 \ - ACTIVATION_DEFAULT_THRESHOLD_S24 + Q_CONVERT_FLOAT(ACTIVATION_DEFAULT_COEF, 31) /* Q1.31 */ #define INITIAL_MODEL_DATA_SIZE 64 @@ -384,6 +383,9 @@ static int test_keyword_params(struct comp_dev *dev, cd->keyphrase_samples = KEYPHRASE_DEFAULT_PREAMBLE_LENGTH; } + cd->config.activation_threshold = + test_keyword_get_threshold(dev, params->sample_valid_bytes * 8); + return 0; } From a13c8d05ce5d55181ee215791e9dac6aeab839b9 Mon Sep 17 00:00:00 2001 From: Janusz Jankowski Date: Tue, 7 Jul 2020 11:43:13 +0200 Subject: [PATCH 03/15] chrome: tgl: disable system agent Current implementation doesn't fit processing restrictions, so we need to disable system agent in order to avoid FW hang. Signed-off-by: Janusz Jankowski --- src/arch/xtensa/configs/override/tigerlake_chrome.config | 1 + 1 file changed, 1 insertion(+) diff --git a/src/arch/xtensa/configs/override/tigerlake_chrome.config b/src/arch/xtensa/configs/override/tigerlake_chrome.config index fedf5820299d..02bc1031fc1d 100644 --- a/src/arch/xtensa/configs/override/tigerlake_chrome.config +++ b/src/arch/xtensa/configs/override/tigerlake_chrome.config @@ -1,3 +1,4 @@ CONFIG_CAVS_LPS=y CONFIG_CAVS_LPRO=y CONFIG_PROBE=y +CONFIG_HAVE_AGENT=n From 7dffd9ffeb3a479ec139c68ea39291fbee557e42 Mon Sep 17 00:00:00 2001 From: Marcin Rajwa Date: Fri, 3 Jul 2020 22:11:36 +0200 Subject: [PATCH 04/15] scheduler: make sure we don't get negative number of clients. [WIP] It looks like under certain circumstances the number of clients of scheduler can go negative. Signed-off-by: Marcin Rajwa --- src/schedule/ll_schedule.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/schedule/ll_schedule.c b/src/schedule/ll_schedule.c index 6d2db4219d66..e46dac371ff3 100644 --- a/src/schedule/ll_schedule.c +++ b/src/schedule/ll_schedule.c @@ -172,9 +172,11 @@ static void schedule_ll_tasks_run(void *data) /* TODO: no need for atomic operations, * already protected by spin_lock */ - num_clients = atomic_sub(&sch->domain->num_clients, 1); - if (!num_clients) - domain_clear(sch->domain); + if (atomic_read(&sch->domain->num_clients)) { + num_clients = atomic_sub(&sch->domain->num_clients, 1); + if (!num_clients) + domain_clear(sch->domain); + } platform_shared_commit(sch->domain, sizeof(*sch->domain)); From 8b98addee616164141cdc1792ae0cbd0c041a5e9 Mon Sep 17 00:00:00 2001 From: Marcin Rajwa Date: Tue, 7 Jul 2020 12:37:11 +0200 Subject: [PATCH 05/15] topology: fix two playback pipelines to be timer driven This patch fixes two SSP pipelines to be scheduled in timer domain. Signed-off-by: Marcin Rajwa --- tools/topology/sof-tgl-max98357a-rt5682.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/topology/sof-tgl-max98357a-rt5682.m4 b/tools/topology/sof-tgl-max98357a-rt5682.m4 index 77b48288c576..4f7036e350c0 100644 --- a/tools/topology/sof-tgl-max98357a-rt5682.m4 +++ b/tools/topology/sof-tgl-max98357a-rt5682.m4 @@ -192,14 +192,14 @@ SectionGraph."PIPE_CAP_VIRT" { DAI_ADD(sof/pipe-dai-playback.m4, 2, SSP, 0, SSP0-Codec, PIPELINE_SOURCE_2, 2, s24le, - 1000, 0, 0) + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) # capture DAI is SSP0 using 2 periods # Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 DAI_ADD(sof/pipe-dai-capture.m4, 3, SSP, 0, SSP0-Codec, PIPELINE_SINK_3, 2, s24le, - 1000, 0, 0) + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) # playback DAI is iDisp1 using 2 periods # Buffers use s32le format, with 48 frame per 1000us on core 0 with priority 0 From 321c78923e88e97483136e2d290e0fcacfd1fab4 Mon Sep 17 00:00:00 2001 From: Marcin Rajwa Date: Tue, 7 Jul 2020 12:46:20 +0200 Subject: [PATCH 06/15] dai: do not limit the amount of copy_bytes This patch removes the constrain to copy at most one period of data one each copy-period. This will help to compensate copy delays introduced by LPRO Signed-off-by: Marcin Rajwa --- src/audio/dai.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/audio/dai.c b/src/audio/dai.c index b2a7e9419704..108b40368844 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -689,12 +689,6 @@ static int dai_copy(struct comp_dev *dev) src_samples = avail_bytes / get_sample_bytes(dd->frame_fmt); sink_samples = audio_stream_get_free_samples(&buf->stream); samples = MIN(src_samples, sink_samples); - - /* limit bytes per copy to one period for the whole pipeline - * in order to avoid high load spike - */ - samples = MIN(samples, dd->period_bytes / - get_sample_bytes(dd->frame_fmt)); } copy_bytes = samples * get_sample_bytes(dd->frame_fmt); From e92e9bc659ea7f530802f15a7cb3b934362eb782 Mon Sep 17 00:00:00 2001 From: Marcin Rajwa Date: Thu, 2 Jul 2020 11:11:58 +0200 Subject: [PATCH 07/15] traces: fix trace messages related to delay reports This patch fixes trace messages related to delays so they print correct number of ticks Signed-off-by: Marcin Rajwa --- src/lib/agent.c | 2 +- src/schedule/timer_domain.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/agent.c b/src/lib/agent.c index e13eae2e396d..2c1125c4f03e 100644 --- a/src/lib/agent.c +++ b/src/lib/agent.c @@ -66,7 +66,7 @@ static enum task_state validate(void *data) /* warning timeout */ if (delta > sa->warn_timeout) tr_warn(&sa_tr, "validate(), ll drift detected, delta = %u", - delta); + (uint32_t)delta); /* update last_check to current */ sa->last_check = current; diff --git a/src/schedule/timer_domain.c b/src/schedule/timer_domain.c index fe74fa2d9e04..edb71d388134 100644 --- a/src/schedule/timer_domain.c +++ b/src/schedule/timer_domain.c @@ -31,8 +31,8 @@ static inline void timer_report_delay(int id, uint64_t delay) uint32_t ll_delay_us = (delay * 1000) / clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1); - tr_err(&ll_tr, "timer_report_delay(): timer %d delayed by %d uS %d ticks", - id, ll_delay_us, delay); + tr_err(&ll_tr, "timer_report_delay(): timer %d delayed by %d uS %u ticks", + id, ll_delay_us, (uint32_t)delay); /* Fix compile error when traces are disabled */ (void)ll_delay_us; From 33cfa90e72868ba1b5247c712e634d7c2603e178 Mon Sep 17 00:00:00 2001 From: Marcin Rajwa Date: Tue, 7 Jul 2020 17:32:39 +0200 Subject: [PATCH 08/15] config: disable LPS from TGL chrome defconfig This patch disables LPS from chrome defconfig Signed-off-by: Marcin Rajwa --- src/arch/xtensa/configs/override/tigerlake_chrome.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/xtensa/configs/override/tigerlake_chrome.config b/src/arch/xtensa/configs/override/tigerlake_chrome.config index 02bc1031fc1d..149415970c69 100644 --- a/src/arch/xtensa/configs/override/tigerlake_chrome.config +++ b/src/arch/xtensa/configs/override/tigerlake_chrome.config @@ -1,4 +1,4 @@ -CONFIG_CAVS_LPS=y +CONFIG_CAVS_LPS=n CONFIG_CAVS_LPRO=y CONFIG_PROBE=y CONFIG_HAVE_AGENT=n From 5793b17634357ff51177688db748b19bf3940c69 Mon Sep 17 00:00:00 2001 From: Bartosz Kokoszko Date: Tue, 7 Jul 2020 11:58:45 +0200 Subject: [PATCH 09/15] smart_amp: fix smart amplifier tplg This commit changes SSP bclk rate from 9600000 to 12288000 in order to fix glitch issue. Signed-off-by: Bartosz Kokoszko --- tools/topology/sof-smart-amplifier.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/topology/sof-smart-amplifier.m4 b/tools/topology/sof-smart-amplifier.m4 index 593b5afa2a37..07aa8b56837c 100644 --- a/tools/topology/sof-smart-amplifier.m4 +++ b/tools/topology/sof-smart-amplifier.m4 @@ -222,7 +222,7 @@ DAI_CONFIG(ALH, eval(SMART_ALH_INDEX + 1), eval(SMART_BE_ID + 1), SMART_ALH_CAPT #SSP SSP_INDEX (ID: SMART_BE_ID) DAI_CONFIG(SSP, SMART_SSP_INDEX, SMART_BE_ID, SMART_SSP_NAME, SSP_CONFIG(DSP_B, SSP_CLOCK(mclk, SSP_MCLK, codec_mclk_in), - SSP_CLOCK(bclk, 9600000, codec_slave), + SSP_CLOCK(bclk, 12288000, codec_slave), SSP_CLOCK(fsync, 48000, codec_slave), SSP_TDM(8, 25, 15, 255), SSP_CONFIG_DATA(SSP, SMART_SSP_INDEX, 24, 0, SMART_SSP_QUIRK))) From aa5216200757d617d9e86df319c09fae00654726 Mon Sep 17 00:00:00 2001 From: Adrian Bonislawski Date: Mon, 29 Jun 2020 12:24:22 +0200 Subject: [PATCH 10/15] tgl: iccmax use pm_runtime_en_dsp_pg power up instead of full core init This patch will introduce additional client override flag to pm_runtime_get Extra flag is not necessary but if used it will prevent from powering down a core without the same flag This will save a lot of time if quick changes are needed eg. in dynamic hpro-lpro switching which on TGL will also require to power up core 3 Signed-off-by: Adrian Bonislawski --- src/arch/xtensa/lib/cpu.c | 9 +++------ .../intel/cavs/include/cavs/lib/pm_runtime.h | 9 +++++++++ src/platform/intel/cavs/lib/clk.c | 5 +++-- src/platform/intel/cavs/lib/pm_runtime.c | 18 ++++++++++++++++-- src/platform/intel/cavs/platform.c | 2 +- 5 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/arch/xtensa/lib/cpu.c b/src/arch/xtensa/lib/cpu.c index d6e0cfc65782..7f8e5e721361 100644 --- a/src/arch/xtensa/lib/cpu.c +++ b/src/arch/xtensa/lib/cpu.c @@ -32,7 +32,6 @@ extern struct core_context *core_ctx_ptr[PLATFORM_CORE_COUNT]; extern struct xtos_core_data *core_data_ptr[PLATFORM_CORE_COUNT]; static uint32_t active_cores_mask; -static int dsp_sref[PLATFORM_CORE_COUNT]; /**< simple ref counter */ #if CONFIG_NO_SLAVE_CORE_ROM extern void *shared_vecbase_ptr; @@ -82,7 +81,7 @@ int arch_cpu_enable_core(int id) pm_runtime_get(CORE_MEMORY_POW, id); /* Power up slave core */ - pm_runtime_get(PM_RUNTIME_DSP, id); + pm_runtime_get(PM_RUNTIME_DSP, PWRD_BY_TPLG | id); /* allocate resources for core */ cpu_alloc_core_context(id); @@ -104,7 +103,6 @@ int arch_cpu_enable_core(int id) active_cores_mask |= (1 << id); } - ++dsp_sref[id]; return 0; } @@ -114,8 +112,7 @@ void arch_cpu_disable_core(int id) struct idc_msg power_down = { IDC_MSG_POWER_DOWN, IDC_MSG_POWER_DOWN_EXT, id }; - --dsp_sref[id]; - if (arch_cpu_is_core_enabled(id) && dsp_sref[id] == 0) { + if (arch_cpu_is_core_enabled(id)) { idc_send_msg(&power_down, IDC_NON_BLOCKING); active_cores_mask ^= (1 << id); @@ -177,7 +174,7 @@ void cpu_power_down_core(void) /* Turn off stack memory for core */ pm_runtime_put(CORE_MEMORY_POW, cpu_get_id()); - pm_runtime_put(PM_RUNTIME_DSP, cpu_get_id()); + pm_runtime_put(PM_RUNTIME_DSP, PWRD_BY_TPLG | cpu_get_id()); /* arch_wait_for_interrupt() not used, because it will cause panic. * This code is executed on irq lvl > 0, which is expected. diff --git a/src/platform/intel/cavs/include/cavs/lib/pm_runtime.h b/src/platform/intel/cavs/include/cavs/lib/pm_runtime.h index 94e590c83271..d9db3743907e 100644 --- a/src/platform/intel/cavs/include/cavs/lib/pm_runtime.h +++ b/src/platform/intel/cavs/include/cavs/lib/pm_runtime.h @@ -16,12 +16,21 @@ #ifndef __CAVS_LIB_PM_RUNTIME_H__ #define __CAVS_LIB_PM_RUNTIME_H__ +/** + * \brief extra pwr flag to power up a core with a specific reason + * it can be powered down only with the same reason (flag) + */ +#define PWRD_MASK MASK(31, 30) +#define PWRD_BY_HPRO BIT(31) /**< requested by HPRO */ +#define PWRD_BY_TPLG BIT(30) /**< typical power up */ + struct pm_runtime_data; /** \brief cAVS specific runtime power management data. */ struct cavs_pm_runtime_data { int dsp_d0_sref; /**< simple ref counter, accessed by core 0 only */ int host_dma_l1_sref; /**< ref counter for Host DMA accesses */ + int dsp_client_bitmap[PLATFORM_CORE_COUNT]; /**< simple pwr override */ }; #endif diff --git a/src/platform/intel/cavs/lib/clk.c b/src/platform/intel/cavs/lib/clk.c index f2e4433b0348..272148325543 100644 --- a/src/platform/intel/cavs/lib/clk.c +++ b/src/platform/intel/cavs/lib/clk.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -32,7 +33,7 @@ static inline void select_cpu_clock(int freq_idx, bool release_unused) #if CONFIG_TIGERLAKE if (freq_idx == CPU_HPRO_FREQ_IDX) - cpu_enable_core(PLATFORM_CORE_COUNT - 1); + pm_runtime_get(PM_RUNTIME_DSP, PWRD_BY_HPRO | (PLATFORM_CORE_COUNT - 1)); #endif /* request clock */ @@ -55,7 +56,7 @@ static inline void select_cpu_clock(int freq_idx, bool release_unused) ~SHIM_CLKCTL_OSC_REQUEST_MASK) | enc); #if CONFIG_TIGERLAKE if (freq_idx != CPU_HPRO_FREQ_IDX) - cpu_disable_core(PLATFORM_CORE_COUNT - 1); + pm_runtime_put(PM_RUNTIME_DSP, PWRD_BY_HPRO | (PLATFORM_CORE_COUNT - 1)); #endif } } diff --git a/src/platform/intel/cavs/lib/pm_runtime.c b/src/platform/intel/cavs/lib/pm_runtime.c index ea56e4722ff9..165595135d51 100644 --- a/src/platform/intel/cavs/lib/pm_runtime.c +++ b/src/platform/intel/cavs/lib/pm_runtime.c @@ -340,7 +340,12 @@ static inline void cavs_pm_runtime_core_en_memory(uint32_t index) static inline void cavs_pm_runtime_dis_dsp_pg(uint32_t index) { #if CAVS_VERSION >= CAVS_VERSION_1_8 + struct pm_runtime_data *prd = pm_runtime_data_get(); + struct cavs_pm_runtime_data *pprd = prd->platform_data; uint32_t lps_ctl, tries = PLATFORM_PM_RUNTIME_DSP_TRIES; + uint32_t flag = PWRD_MASK & index; + + index &= ~(PWRD_MASK); if (index == PLATFORM_MASTER_CORE_ID) { lps_ctl = shim_read(SHIM_LPSCTL); @@ -368,6 +373,7 @@ static inline void cavs_pm_runtime_dis_dsp_pg(uint32_t index) if (tries == 0) tr_err(&power_tr, "cavs_pm_runtime_dis_dsp_pg(): failed to power up core %d", index); + pprd->dsp_client_bitmap[index] |= flag; } #endif } @@ -375,7 +381,12 @@ static inline void cavs_pm_runtime_dis_dsp_pg(uint32_t index) static inline void cavs_pm_runtime_en_dsp_pg(uint32_t index) { #if CAVS_VERSION >= CAVS_VERSION_1_8 + struct pm_runtime_data *prd = pm_runtime_data_get(); + struct cavs_pm_runtime_data *pprd = prd->platform_data; uint32_t lps_ctl; + uint32_t flag = PWRD_MASK & index; + + index &= ~(PWRD_MASK); if (index == PLATFORM_MASTER_CORE_ID) { lps_ctl = shim_read(SHIM_LPSCTL); @@ -389,8 +400,11 @@ static inline void cavs_pm_runtime_en_dsp_pg(uint32_t index) lps_ctl &= ~SHIM_LPSCTL_FDSPRUN; shim_write(SHIM_LPSCTL, lps_ctl); } else { - shim_write16(SHIM_PWRCTL, shim_read16(SHIM_PWRCTL) & - ~SHIM_PWRCTL_TCPDSPPG(index)); + pprd->dsp_client_bitmap[index] &= ~(flag); + + if (pprd->dsp_client_bitmap[index] == 0) + shim_write16(SHIM_PWRCTL, shim_read16(SHIM_PWRCTL) & + ~SHIM_PWRCTL_TCPDSPPG(index)); } #endif } diff --git a/src/platform/intel/cavs/platform.c b/src/platform/intel/cavs/platform.c index 14afc8b3ff51..c0e9da62eec3 100644 --- a/src/platform/intel/cavs/platform.c +++ b/src/platform/intel/cavs/platform.c @@ -297,7 +297,7 @@ int platform_boot_complete(uint32_t boot_message) uint32_t mb_offset = 0; #if CONFIG_TIGERLAKE && !CONFIG_CAVS_LPRO - cpu_enable_core(PLATFORM_CORE_COUNT - 1); + pm_runtime_get(PM_RUNTIME_DSP, PWRD_BY_HPRO | (PLATFORM_CORE_COUNT - 1)); #endif mailbox_dspbox_write(mb_offset, &ready, sizeof(ready)); From f0b5b453ac9f5c2dc5e04f483fbc3595bcc76845 Mon Sep 17 00:00:00 2001 From: Adrian Bonislawski Date: Wed, 1 Jul 2020 16:09:48 +0200 Subject: [PATCH 11/15] tgl: align with HW recommended flow at platform init This patch will align with HW recommended flow while clock switching at platform init Signed-off-by: Adrian Bonislawski --- src/platform/intel/cavs/platform.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/platform/intel/cavs/platform.c b/src/platform/intel/cavs/platform.c index c0e9da62eec3..9e8bd5aa57e2 100644 --- a/src/platform/intel/cavs/platform.c +++ b/src/platform/intel/cavs/platform.c @@ -296,10 +296,6 @@ int platform_boot_complete(uint32_t boot_message) { uint32_t mb_offset = 0; -#if CONFIG_TIGERLAKE && !CONFIG_CAVS_LPRO - pm_runtime_get(PM_RUNTIME_DSP, PWRD_BY_HPRO | (PLATFORM_CORE_COUNT - 1)); -#endif - mailbox_dspbox_write(mb_offset, &ready, sizeof(ready)); mb_offset = mb_offset + sizeof(ready); @@ -432,7 +428,9 @@ int platform_init(struct sof *sof) #elif CONFIG_CANNONLAKE || CONFIG_ICELAKE || CONFIG_TIGERLAKE /* initialize PM for boot */ - +#if CONFIG_TIGERLAKE + pm_runtime_get(PM_RUNTIME_DSP, PWRD_BY_HPRO | (PLATFORM_CORE_COUNT - 1)); +#endif /* request configured ring oscillator and wait for status ready */ shim_write(SHIM_CLKCTL, shim_read(SHIM_CLKCTL) | CAVS_DEFAULT_RO); while (!(shim_read(SHIM_CLKSTS) & CAVS_DEFAULT_RO)) @@ -453,7 +451,9 @@ int platform_init(struct sof *sof) /* prevent DSP Common power gating */ pm_runtime_get(PM_RUNTIME_DSP, PLATFORM_MASTER_CORE_ID); - +#if CONFIG_TIGERLAKE && CONFIG_CAVS_LPRO + pm_runtime_put(PM_RUNTIME_DSP, PWRD_BY_HPRO | (PLATFORM_CORE_COUNT - 1)); +#endif #elif CONFIG_SUECREEK /* TODO: need to merge as for APL */ clock_set_freq(CLK_CPU(cpu_get_id()), CLK_MAX_CPU_HZ); From 9f9c31acfb576584291842a64ed407c75b97d40e Mon Sep 17 00:00:00 2001 From: Slawomir Blauciak Date: Mon, 22 Jun 2020 14:32:10 +0200 Subject: [PATCH 12/15] clk: switch between lpro and hpro on pm gate This change utilizes the PM gate requests to switch between low power and high performance ring oscillator clocks as needed. This allows for the DSP to properly enter D0ix modes, even if normally operated using the high performance clock. Signed-off-by: Slawomir Blauciak --- src/ipc/handler.c | 7 ++++++ .../intel/cavs/include/cavs/lib/clk.h | 5 +++- src/platform/intel/cavs/lib/clk.c | 24 ++++++++++++------- src/platform/intel/cavs/platform.c | 3 +-- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/ipc/handler.c b/src/ipc/handler.c index 9f91f8b38fdb..fbec1711c125 100644 --- a/src/ipc/handler.c +++ b/src/ipc/handler.c @@ -677,6 +677,13 @@ static int ipc_pm_gate(uint32_t header) else pm_runtime_enable(PM_RUNTIME_DSP, PLATFORM_MASTER_CORE_ID); +#if !CONFIG_CAVS_LPRO + if (pm_runtime_is_active(PM_RUNTIME_DSP, PLATFORM_MASTER_CORE_ID)) + platform_set_active_clock(CPU_HPRO_FREQ_IDX); + else + platform_set_active_clock(CPU_LPRO_FREQ_IDX); +#endif + /* resume dma trace if needed */ if (!(pm_gate.flags & SOF_PM_NO_TRACE)) trace_on(); diff --git a/src/platform/intel/cavs/include/cavs/lib/clk.h b/src/platform/intel/cavs/include/cavs/lib/clk.h index 459d84847b11..af8e1f3d102a 100644 --- a/src/platform/intel/cavs/include/cavs/lib/clk.h +++ b/src/platform/intel/cavs/include/cavs/lib/clk.h @@ -43,11 +43,14 @@ extern const uint32_t cpu_freq_status_mask[]; void platform_clock_init(struct sof *sof); -#if CONFIG_CAVS_USE_LPRO_IN_WAITI void platform_clock_on_waiti(void); + +#if CONFIG_CAVS_USE_LPRO_IN_WAITI void platform_clock_on_wakeup(void); #endif +void platform_set_active_clock(int index); + #endif /* __CAVS_LIB_CLK_H__ */ #else diff --git a/src/platform/intel/cavs/lib/clk.c b/src/platform/intel/cavs/lib/clk.c index 272148325543..97b2489b575a 100644 --- a/src/platform/intel/cavs/lib/clk.c +++ b/src/platform/intel/cavs/lib/clk.c @@ -68,10 +68,7 @@ static int clock_platform_set_cpu_freq(int clock, int freq_idx) return 0; } -#if CONFIG_CAVS_USE_LPRO_IN_WAITI -/* Store clock source that was active before going to waiti, - * so it can be restored on wake up. - */ +/* Clock source to be used when not waiting for an interrupt. */ static SHARED_DATA int active_freq_idx = CPU_DEFAULT_IDX; static inline int get_cpu_current_freq_idx(void) @@ -93,6 +90,7 @@ static inline void set_cpu_current_freq_idx(int freq_idx) sizeof(*clk_info) * PLATFORM_CORE_COUNT); } +#if CONFIG_CAVS_USE_LPRO_IN_WAITI void platform_clock_on_wakeup(void) { int freq_idx = *cache_to_uncache(&active_freq_idx); @@ -102,24 +100,34 @@ void platform_clock_on_wakeup(void) set_cpu_current_freq_idx(freq_idx); } } +#endif void platform_clock_on_waiti(void) { int freq_idx = get_cpu_current_freq_idx(); +#if CONFIG_CAVS_USE_LPRO_IN_WAITI + int target_idx = CPU_LPRO_FREQ_IDX; *cache_to_uncache(&active_freq_idx) = freq_idx; +#else + int target_idx = *cache_to_uncache(&active_freq_idx); +#endif - if (freq_idx != CPU_LPRO_FREQ_IDX) { + if (freq_idx != target_idx) { /* LPRO requests are fast, but requests for other ROs * can take a lot of time. That's why it's better to * not release active clock just for waiti, * so they can be switched without delay on wake up. */ - select_cpu_clock(CPU_LPRO_FREQ_IDX, false); - set_cpu_current_freq_idx(CPU_LPRO_FREQ_IDX); + select_cpu_clock(target_idx, false); + set_cpu_current_freq_idx(target_idx); } } -#endif + +void platform_set_active_clock(int index) +{ + *cache_to_uncache(&active_freq_idx) = index; +} void platform_clock_init(struct sof *sof) { diff --git a/src/platform/intel/cavs/platform.c b/src/platform/intel/cavs/platform.c index 9e8bd5aa57e2..f922cf8e5246 100644 --- a/src/platform/intel/cavs/platform.c +++ b/src/platform/intel/cavs/platform.c @@ -530,9 +530,8 @@ int platform_init(struct sof *sof) void platform_wait_for_interrupt(int level) { -#if CONFIG_CAVS_USE_LPRO_IN_WAITI platform_clock_on_waiti(); -#endif + #if (CONFIG_CAVS_LPS) if (pm_runtime_is_active(PM_RUNTIME_DSP, PLATFORM_MASTER_CORE_ID)) arch_wait_for_interrupt(level); From 250ce25635f8606fc205419b3507233c72b4e99d Mon Sep 17 00:00:00 2001 From: Janusz Jankowski Date: Tue, 23 Jun 2020 10:03:17 +0200 Subject: [PATCH 13/15] chrome: change default clock to HPRO Set HPRO as default clock, so firmware can dynamically switch between LPRO and HPRO, instead of having it constantly set to LPRO. Signed-off-by: Janusz Jankowski --- src/arch/xtensa/configs/override/tigerlake_chrome.config | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/arch/xtensa/configs/override/tigerlake_chrome.config b/src/arch/xtensa/configs/override/tigerlake_chrome.config index 149415970c69..d8eec7d1433d 100644 --- a/src/arch/xtensa/configs/override/tigerlake_chrome.config +++ b/src/arch/xtensa/configs/override/tigerlake_chrome.config @@ -1,4 +1,3 @@ -CONFIG_CAVS_LPS=n -CONFIG_CAVS_LPRO=y +CONFIG_CAVS_LPS=y CONFIG_PROBE=y CONFIG_HAVE_AGENT=n From 677938ab6b2c628be682b234d158cd3fbf40f217 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Wed, 8 Jul 2020 17:06:52 +0800 Subject: [PATCH 14/15] cavs: platform: enable both LP and HP Oscillators at init We need to enable both LP and HP oscillators at platform init, and switch them dynamically. Signed-off-by: Keyon Jie --- src/platform/intel/cavs/platform.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/platform/intel/cavs/platform.c b/src/platform/intel/cavs/platform.c index f922cf8e5246..f1680b830e5c 100644 --- a/src/platform/intel/cavs/platform.c +++ b/src/platform/intel/cavs/platform.c @@ -146,13 +146,8 @@ EXT_MAN_PORT( #endif #if CONFIG_CANNONLAKE || CONFIG_ICELAKE || CONFIG_TIGERLAKE -#if CONFIG_CAVS_LPRO -#define CAVS_DEFAULT_RO SHIM_CLKCTL_RLROSCC -#define CAVS_DEFAULT_RO_FOR_MEM SHIM_CLKCTL_OCS_LP_RING -#else -#define CAVS_DEFAULT_RO SHIM_CLKCTL_RHROSCC -#define CAVS_DEFAULT_RO_FOR_MEM SHIM_CLKCTL_OCS_HP_RING -#endif +#define CAVS_ROS (SHIM_CLKCTL_RHROSCC | SHIM_CLKCTL_RLROSCC) +#define CAVS_ROS_FOR_MEM (SHIM_CLKCTL_OCS_HP_RING | SHIM_CLKCTL_OCS_LP_RING) #endif #if CONFIG_DW_GPIO @@ -432,15 +427,15 @@ int platform_init(struct sof *sof) pm_runtime_get(PM_RUNTIME_DSP, PWRD_BY_HPRO | (PLATFORM_CORE_COUNT - 1)); #endif /* request configured ring oscillator and wait for status ready */ - shim_write(SHIM_CLKCTL, shim_read(SHIM_CLKCTL) | CAVS_DEFAULT_RO); - while (!(shim_read(SHIM_CLKSTS) & CAVS_DEFAULT_RO)) + shim_write(SHIM_CLKCTL, shim_read(SHIM_CLKCTL) | CAVS_ROS); + while (!((shim_read(SHIM_CLKSTS) & CAVS_ROS) == CAVS_ROS)) idelay(16); shim_write(SHIM_CLKCTL, - CAVS_DEFAULT_RO | /* Request configured RING Osc */ - CAVS_DEFAULT_RO_FOR_MEM | /* Select configured - * RING Oscillator Clk for memory - */ + CAVS_ROS | /* Request configured RING Osc */ + CAVS_ROS_FOR_MEM | /* Select configured + * RING Oscillator Clk for memory + */ SHIM_CLKCTL_HMCS_DIV2 | /* HP mem clock div by 2 */ SHIM_CLKCTL_LMCS_DIV4 | /* LP mem clock div by 4 */ SHIM_CLKCTL_TCPLCG_DIS_ALL); /* Allow Local Clk Gating */ From c847315dfbe27274e1aceb4a0a1c1c5a88aa0bdc Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Wed, 8 Jul 2020 17:13:22 +0800 Subject: [PATCH 15/15] cavs: discard CAVS_LPRO and set CAVS_USE_LPRO_IN_WAITI by default With dynamic clock switching applied, we don't need to configure CAVS_LPRO explicitly, instead, we will use HPRO by default, and switch to use LPRO in low power scenarios (e.g. WFI, D0I3 with KWD). Switching to use LPRO in waiti or not is configured by CAVS_USE_LPRO_IN_WAITI item, and use LPRO in waiti by default for power saving. The commit also refine the clock switching logic as below: 1. use the active_freq_idx to save the active (non-WFI) clock index. 2. refine helper platform_set_active_clock() to switch the active clock and update the active_freq_idx together. 3. for WFI related clock switching, don't update the active_freq_idx, but just do the real switching and switching back. 4. implement platform_clock_waiti_entry() and platform_clock_waiti_exit() for the clock switching, and update the active clock before each WFI entry. This is verified works on TGL platforms, we also need testing on JSL with it. Signed-off-by: Keyon Jie --- .../configs/override/cannonlake_chrome.config | 2 +- .../configs/override/jasperlake_chrome.config | 2 +- src/ipc/handler.c | 7 --- src/platform/Kconfig | 10 +---- .../cannonlake/include/platform/lib/clk.h | 4 -- .../intel/cavs/include/cavs/lib/clk.h | 3 +- src/platform/intel/cavs/lib/clk.c | 44 +++++++++++++++++-- src/platform/intel/cavs/platform.c | 4 +- 8 files changed, 48 insertions(+), 28 deletions(-) diff --git a/src/arch/xtensa/configs/override/cannonlake_chrome.config b/src/arch/xtensa/configs/override/cannonlake_chrome.config index 3ac57df516da..039ec36fdcc2 100644 --- a/src/arch/xtensa/configs/override/cannonlake_chrome.config +++ b/src/arch/xtensa/configs/override/cannonlake_chrome.config @@ -1,2 +1,2 @@ CONFIG_CAVS_LPS=y -CONFIG_CAVS_LPRO=y +CONFIG_CAVS_USE_LPRO_IN_WAITI=y diff --git a/src/arch/xtensa/configs/override/jasperlake_chrome.config b/src/arch/xtensa/configs/override/jasperlake_chrome.config index 3ac57df516da..039ec36fdcc2 100644 --- a/src/arch/xtensa/configs/override/jasperlake_chrome.config +++ b/src/arch/xtensa/configs/override/jasperlake_chrome.config @@ -1,2 +1,2 @@ CONFIG_CAVS_LPS=y -CONFIG_CAVS_LPRO=y +CONFIG_CAVS_USE_LPRO_IN_WAITI=y diff --git a/src/ipc/handler.c b/src/ipc/handler.c index fbec1711c125..9f91f8b38fdb 100644 --- a/src/ipc/handler.c +++ b/src/ipc/handler.c @@ -677,13 +677,6 @@ static int ipc_pm_gate(uint32_t header) else pm_runtime_enable(PM_RUNTIME_DSP, PLATFORM_MASTER_CORE_ID); -#if !CONFIG_CAVS_LPRO - if (pm_runtime_is_active(PM_RUNTIME_DSP, PLATFORM_MASTER_CORE_ID)) - platform_set_active_clock(CPU_HPRO_FREQ_IDX); - else - platform_set_active_clock(CPU_LPRO_FREQ_IDX); -#endif - /* resume dma trace if needed */ if (!(pm_gate.flags & SOF_PM_NO_TRACE)) trace_on(); diff --git a/src/platform/Kconfig b/src/platform/Kconfig index 940610717c2d..c27506ac5ffa 100644 --- a/src/platform/Kconfig +++ b/src/platform/Kconfig @@ -296,17 +296,9 @@ config CAVS_LPS This option is required to support S0ix/D0ix mode on cAVS platforms. -config CAVS_LPRO - bool "Enable low power ring oscillator as the default clock" - default n - depends on CAVS && !CAVS_VERSION_1_5 - help - Select if you want to use 120MHz LPRO as the DSP clock source. - This option is required to support S0ix/D0ix mode. - config CAVS_USE_LPRO_IN_WAITI bool - default n + default y depends on CAVS select WAKEUP_HOOK help diff --git a/src/platform/cannonlake/include/platform/lib/clk.h b/src/platform/cannonlake/include/platform/lib/clk.h index 61fbbd53fa55..eb39bb31f549 100644 --- a/src/platform/cannonlake/include/platform/lib/clk.h +++ b/src/platform/cannonlake/include/platform/lib/clk.h @@ -20,11 +20,7 @@ #define CPU_HPRO_FREQ_IDX 1 -#if CONFIG_CAVS_LPRO -#define CPU_DEFAULT_IDX CPU_LPRO_FREQ_IDX -#else #define CPU_DEFAULT_IDX CPU_HPRO_FREQ_IDX -#endif #define SSP_DEFAULT_IDX 0 diff --git a/src/platform/intel/cavs/include/cavs/lib/clk.h b/src/platform/intel/cavs/include/cavs/lib/clk.h index af8e1f3d102a..ec83f09fc221 100644 --- a/src/platform/intel/cavs/include/cavs/lib/clk.h +++ b/src/platform/intel/cavs/include/cavs/lib/clk.h @@ -43,7 +43,8 @@ extern const uint32_t cpu_freq_status_mask[]; void platform_clock_init(struct sof *sof); -void platform_clock_on_waiti(void); +void platform_clock_waiti_entry(void); +void platform_clock_waiti_exit(void); #if CONFIG_CAVS_USE_LPRO_IN_WAITI void platform_clock_on_wakeup(void); diff --git a/src/platform/intel/cavs/lib/clk.c b/src/platform/intel/cavs/lib/clk.c index 97b2489b575a..6fc07ed98d8b 100644 --- a/src/platform/intel/cavs/lib/clk.c +++ b/src/platform/intel/cavs/lib/clk.c @@ -102,15 +102,28 @@ void platform_clock_on_wakeup(void) } #endif -void platform_clock_on_waiti(void) +void platform_clock_waiti_entry(void) { - int freq_idx = get_cpu_current_freq_idx(); + int freq_idx; + int target_idx; + + /* update the active clock according to the pm runtime state */ + if (*cache_to_uncache(&active_freq_idx) != CPU_LPRO_FREQ_IDX && + !pm_runtime_is_active(PM_RUNTIME_DSP, PLATFORM_MASTER_CORE_ID)) + platform_set_active_clock(CPU_LPRO_FREQ_IDX); + else if (*cache_to_uncache(&active_freq_idx) != CPU_HPRO_FREQ_IDX && + pm_runtime_is_active(PM_RUNTIME_DSP, PLATFORM_MASTER_CORE_ID)) + platform_set_active_clock(CPU_HPRO_FREQ_IDX); + + freq_idx = get_cpu_current_freq_idx(); + #if CONFIG_CAVS_USE_LPRO_IN_WAITI - int target_idx = CPU_LPRO_FREQ_IDX; + target_idx = CPU_LPRO_FREQ_IDX; + /* store the cpu freq_idx */ *cache_to_uncache(&active_freq_idx) = freq_idx; #else - int target_idx = *cache_to_uncache(&active_freq_idx); + target_idx = *cache_to_uncache(&active_freq_idx); #endif if (freq_idx != target_idx) { @@ -124,8 +137,31 @@ void platform_clock_on_waiti(void) } } +void platform_clock_waiti_exit(void) +{ + int current_idx = get_cpu_current_freq_idx(); + int target_idx = *cache_to_uncache(&active_freq_idx); + + /* restore the active cpu freq_idx */ + if (current_idx != target_idx) { + /* LPRO requests are fast, but requests for other ROs + * can take a lot of time. That's why it's better to + * not release active clock just for waiti, + * so they can be switched without delay on wake up. + */ + select_cpu_clock(target_idx, false); + set_cpu_current_freq_idx(target_idx); + } +} + void platform_set_active_clock(int index) { + if (*cache_to_uncache(&active_freq_idx) == index) + return; + + select_cpu_clock(index, true); + set_cpu_current_freq_idx(index); + *cache_to_uncache(&active_freq_idx) = index; } diff --git a/src/platform/intel/cavs/platform.c b/src/platform/intel/cavs/platform.c index f1680b830e5c..08cc0693f3fd 100644 --- a/src/platform/intel/cavs/platform.c +++ b/src/platform/intel/cavs/platform.c @@ -525,7 +525,7 @@ int platform_init(struct sof *sof) void platform_wait_for_interrupt(int level) { - platform_clock_on_waiti(); + platform_clock_waiti_entry(); #if (CONFIG_CAVS_LPS) if (pm_runtime_is_active(PM_RUNTIME_DSP, PLATFORM_MASTER_CORE_ID)) @@ -535,4 +535,6 @@ void platform_wait_for_interrupt(int level) #else arch_wait_for_interrupt(level); #endif + + platform_clock_waiti_exit(); }