From f42c6573ea62e0688f3d80590416c6c35030d908 Mon Sep 17 00:00:00 2001 From: Marcin Maka Date: Mon, 8 Oct 2018 14:18:45 +0200 Subject: [PATCH 1/2] tplg: result of the free function propagated Signed-off-by: Marcin Maka --- src/ipc/handler.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/ipc/handler.c b/src/ipc/handler.c index 0e15821a8..c723c964f 100644 --- a/src/ipc/handler.c +++ b/src/ipc/handler.c @@ -935,6 +935,7 @@ static int ipc_glb_tplg_free(uint32_t header, int (*free_func)(struct ipc *ipc, uint32_t id)) { struct sof_ipc_free *ipc_free = _ipc->comp_data; + int ret; trace_ipc("Tcf"); @@ -945,9 +946,14 @@ static int ipc_glb_tplg_free(uint32_t header, } /* free the object */ - free_func(_ipc, ipc_free->id); + ret = free_func(_ipc, ipc_free->id); - return 0; + if (ret < 0) { + trace_error(TRACE_CLASS_IPC, + "ipc-glb-tplg-free free_func failed %d", ret); + } + + return ret; } static int ipc_glb_tplg_message(uint32_t header) From 1ba7b5e0af4c7419b6ec513f264a31bf4d0e7f87 Mon Sep 17 00:00:00 2001 From: Marcin Maka Date: Tue, 2 Oct 2018 15:10:02 +0200 Subject: [PATCH 2/2] plat: apl: clock gating adjusted for dai, dma, and cores dai clocks ungated and resources allocated on the first use. dma clocks ungated and resources allocated on the first use. cores clocks gated in idle. Signed-off-by: Marcin Maka --- Makefile.am | 5 -- configure.ac | 3 - src/drivers/intel/baytrail/ssp.c | 25 +++--- src/drivers/intel/cavs/clk.c | 4 +- src/drivers/intel/cavs/dmic.c | 21 +++-- src/drivers/intel/cavs/hda-dma.c | 8 +- src/drivers/intel/cavs/ssp.c | 37 +++++---- src/drivers/intel/dw-dma.c | 7 ++ src/drivers/intel/haswell/ssp.c | 20 ++--- src/include/sof/dai.h | 18 ++-- src/include/sof/dma.h | 3 +- src/include/sof/dmic.h | 1 - src/include/sof/ssp.h | 1 - src/ipc/handler.c | 3 +- src/lib/dai.c | 51 ++++++++++-- src/lib/dma.c | 29 ++++++- .../include/platform/asm_memory_management.h | 1 + .../apollolake/include/platform/shim.h | 83 +++++++++++++------ src/platform/apollolake/power_down.S | 2 +- src/platform/intel/Makefile.am | 5 +- src/platform/intel/cavs/dai.c | 25 +++--- src/platform/intel/cavs/dma.c | 16 ++-- src/platform/intel/cavs/platform.c | 54 ++++++------ src/platform/intel/cavs/pm_runtime.c | 79 +++++++++++++++++- src/platform/intel/include/Makefile.am | 1 - .../intel/include/platform/Makefile.am | 3 - .../intel/include/platform/cavs/Makefile.am | 2 - .../intel/include/platform/cavs/pm_runtime.h | 65 --------------- 28 files changed, 333 insertions(+), 239 deletions(-) delete mode 100644 src/platform/intel/include/Makefile.am delete mode 100644 src/platform/intel/include/platform/Makefile.am delete mode 100644 src/platform/intel/include/platform/cavs/Makefile.am delete mode 100644 src/platform/intel/include/platform/cavs/pm_runtime.h diff --git a/Makefile.am b/Makefile.am index 6be7c8eae..892cc2c08 100644 --- a/Makefile.am +++ b/Makefile.am @@ -43,11 +43,6 @@ export ARCH_INCDIR PLATFORM_INCDIR = -I $(SRC_DIR)/platform/$(PLATFORM)/include -if BUILD_CAVS -PLATFORM_INCDIR += \ - -I $(SRC_DIR)/platform/intel/include -endif - if XCC PLATFORM_INCDIR += \ -I $(ROOT_DIR)/arch/include diff --git a/configure.ac b/configure.ac index 02c2579a5..9071e7239 100644 --- a/configure.ac +++ b/configure.ac @@ -566,9 +566,6 @@ AC_CONFIG_FILES([ src/platform/icelake/include/platform/Makefile src/platform/intel/Makefile src/platform/intel/cavs/Makefile - src/platform/intel/include/Makefile - src/platform/intel/include/platform/Makefile - src/platform/intel/include/platform/cavs/Makefile test/Makefile test/cmocka/Makefile ]) diff --git a/src/drivers/intel/baytrail/ssp.c b/src/drivers/intel/baytrail/ssp.c index cd67a47e3..0acbd97eb 100644 --- a/src/drivers/intel/baytrail/ssp.c +++ b/src/drivers/intel/baytrail/ssp.c @@ -57,12 +57,11 @@ static int hweight_32(uint32_t mask) /* empty SSP receive FIFO */ static void ssp_empty_rx_fifo(struct dai *dai) { - struct ssp_pdata *ssp = dai_get_drvdata(dai); uint32_t sssr; uint32_t entries; uint32_t i; - spin_lock(&ssp->lock); + spin_lock(&dai->lock); sssr = ssp_read(dai, SSSR); @@ -77,7 +76,7 @@ static void ssp_empty_rx_fifo(struct dai *dai) ssp_read(dai, SSDR); } - spin_unlock(&ssp->lock); + spin_unlock(&dai->lock); } /* save SSP context prior to entering D3 */ @@ -132,7 +131,7 @@ static inline int ssp_set_config(struct dai *dai, bool cbs = false; int ret = 0; - spin_lock(&ssp->lock); + spin_lock(&dai->lock); /* is playback/capture already running */ if (ssp->state[DAI_DIR_PLAYBACK] == COMP_STATE_ACTIVE || @@ -473,7 +472,7 @@ static inline int ssp_set_config(struct dai *dai, ssp->state[DAI_DIR_CAPTURE] = COMP_STATE_PREPARE; out: - spin_unlock(&ssp->lock); + spin_unlock(&dai->lock); return ret; } @@ -481,14 +480,12 @@ out: /* Digital Audio interface formatting */ static inline int ssp_set_loopback_mode(struct dai *dai, uint32_t lbm) { - struct ssp_pdata *ssp = dai_get_drvdata(dai); - trace_ssp("loo"); - spin_lock(&ssp->lock); + spin_lock(&dai->lock); ssp_update_bits(dai, SSCR1, SSCR1_LBM, lbm ? SSCR1_LBM : 0); - spin_unlock(&ssp->lock); + spin_unlock(&dai->lock); return 0; } @@ -498,7 +495,7 @@ static void ssp_start(struct dai *dai, int direction) { struct ssp_pdata *ssp = dai_get_drvdata(dai); - spin_lock(&ssp->lock); + spin_lock(&dai->lock); /* enable port */ ssp_update_bits(dai, SSCR0, SSCR0_SSE, SSCR0_SSE); @@ -512,7 +509,7 @@ static void ssp_start(struct dai *dai, int direction) else ssp_update_bits(dai, SSCR1, SSCR1_RSRE, SSCR1_RSRE); - spin_unlock(&ssp->lock); + spin_unlock(&dai->lock); } /* stop the SSP for either playback or capture */ @@ -520,7 +517,7 @@ static void ssp_stop(struct dai *dai, int direction) { struct ssp_pdata *ssp = dai_get_drvdata(dai); - spin_lock(&ssp->lock); + spin_lock(&dai->lock); /* stop Rx if neeed */ if (direction == DAI_DIR_CAPTURE && @@ -548,7 +545,7 @@ static void ssp_stop(struct dai *dai, int direction) trace_ssp("Ss2"); } - spin_unlock(&ssp->lock); + spin_unlock(&dai->lock); } static int ssp_trigger(struct dai *dai, int cmd, int direction) @@ -607,7 +604,7 @@ static int ssp_probe(struct dai *dai) sizeof(*ssp)); dai_set_drvdata(dai, ssp); - spinlock_init(&ssp->lock); + spinlock_init(&dai->lock); ssp->state[DAI_DIR_PLAYBACK] = COMP_STATE_READY; ssp->state[DAI_DIR_CAPTURE] = COMP_STATE_READY; diff --git a/src/drivers/intel/cavs/clk.c b/src/drivers/intel/cavs/clk.c index 785ec7e98..28b34e6f2 100644 --- a/src/drivers/intel/cavs/clk.c +++ b/src/drivers/intel/cavs/clk.c @@ -139,7 +139,7 @@ uint32_t clock_set_freq(int clock, uint32_t hz) notify_data.old_freq = clk_pdata->clk[clock].freq; notify_data.old_ticks_per_msec = clk_pdata->clk[clock].ticks_per_msec; - /* atomic context for chaning clocks */ + /* atomic context for changing clocks */ spin_lock_irq(&clk_pdata->clk[clock].lock, flags); switch (clock) { @@ -157,6 +157,8 @@ uint32_t clock_set_freq(int clock, uint32_t hz) io_reg_update_bits(SHIM_BASE + SHIM_CLKCTL, SHIM_CLKCTL_HDCS, 0); #endif + + /* TODO: should handle all cores or pass the index as arg */ io_reg_update_bits(SHIM_BASE + SHIM_CLKCTL, SHIM_CLKCTL_DPCS_MASK(0), cpu_freq[idx].enc); diff --git a/src/drivers/intel/cavs/dmic.c b/src/drivers/intel/cavs/dmic.c index 5cf88bca7..a95337210 100644 --- a/src/drivers/intel/cavs/dmic.c +++ b/src/drivers/intel/cavs/dmic.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -207,7 +208,7 @@ static uint64_t dmic_work(void *data, uint64_t delay) int i; tracev_dmic("wrk"); - spin_lock(&dmic->lock); + spin_lock(&dai->lock); /* Increment gain with logaritmic step. * Gain is Q2.30 and gain modifier is Q2.14. @@ -257,7 +258,7 @@ static uint64_t dmic_work(void *data, uint64_t delay) dmic_write(dai, base[i] + OUT_GAIN_RIGHT_B, val); } } - spin_unlock(&dmic->lock); + spin_unlock(&dai->lock); if (gval) return DMIC_UNMUTE_RAMP_US; @@ -1236,7 +1237,7 @@ static void dmic_start(struct dai *dai) int fir_b; /* enable port */ - spin_lock(&dmic->lock); + spin_lock(&dai->lock); trace_dmic("sta"); dmic->state = COMP_STATE_ACTIVE; dmic->startcount = 0; @@ -1305,7 +1306,7 @@ static void dmic_start(struct dai *dai) CIC_CONTROL_SOFT_RESET_BIT, 0); } - spin_unlock(&dmic->lock); + spin_unlock(&dai->lock); /* Currently there's no DMIC HW internal mutings and wait times * applied into this start sequence. It can be implemented here if @@ -1324,7 +1325,7 @@ static void dmic_stop(struct dai *dai) int i; trace_dmic("sto") - spin_lock(&dmic->lock); + spin_lock(&dai->lock); dmic->state = COMP_STATE_PREPARE; /* Stop FIFO packers and set FIFO initialize bits */ @@ -1352,7 +1353,7 @@ static void dmic_stop(struct dai *dai) FIR_CONTROL_B_MUTE_BIT); } - spin_unlock(&dmic->lock); + spin_unlock(&dai->lock); } /* save DMIC context prior to entering D3 */ @@ -1446,6 +1447,12 @@ static int dmic_probe(struct dai *dai) trace_dmic("pro"); + if (dai_get_drvdata(dai)) + return -EEXIST; /* already created */ + + /* Disable dynamic clock gating for dmic before touching any reg */ + pm_runtime_get_sync(DMIC_CLK, dai->index); + /* allocate private data */ dmic = rzalloc(RZONE_SYS | RZONE_FLAG_UNCACHED, SOF_MEM_CAPS_RAM, sizeof(*dmic)); @@ -1455,8 +1462,6 @@ static int dmic_probe(struct dai *dai) } dai_set_drvdata(dai, dmic); - spinlock_init(&dmic->lock); - /* Set state, note there is no playback direction support */ dmic->state = COMP_STATE_READY; diff --git a/src/drivers/intel/cavs/hda-dma.c b/src/drivers/intel/cavs/hda-dma.c index 311c70c17..6b7a048d7 100644 --- a/src/drivers/intel/cavs/hda-dma.c +++ b/src/drivers/intel/cavs/hda-dma.c @@ -612,13 +612,17 @@ static int hda_dma_probe(struct dma *dma) int i; struct hda_chan_data *chan; + trace_event(TRACE_CLASS_DMA, "hda-dma-probe %p id %d", + (uintptr_t)dma, dma->plat_data.id); + + if (dma_get_drvdata(dma)) + return -EEXIST; /* already created */ + /* allocate private data */ hda_pdata = rzalloc(RZONE_SYS | RZONE_FLAG_UNCACHED, SOF_MEM_CAPS_RAM, sizeof(*hda_pdata)); dma_set_drvdata(dma, hda_pdata); - spinlock_init(&dma->lock); - /* init channel status */ chan = hda_pdata->chan; diff --git a/src/drivers/intel/cavs/ssp.c b/src/drivers/intel/cavs/ssp.c index 081829a9e..4d39f4697 100644 --- a/src/drivers/intel/cavs/ssp.c +++ b/src/drivers/intel/cavs/ssp.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -65,10 +66,9 @@ static int hweight_32(uint32_t mask) /* empty SSP transmit FIFO */ static void ssp_empty_tx_fifo(struct dai *dai) { - struct ssp_pdata *ssp = dai_get_drvdata(dai); uint32_t sssr; - spin_lock(&ssp->lock); + spin_lock(&dai->lock); sssr = ssp_read(dai, SSSR); @@ -76,18 +76,17 @@ static void ssp_empty_tx_fifo(struct dai *dai) if (sssr & SSSR_TUR) ssp_write(dai, SSSR, sssr); - spin_unlock(&ssp->lock); + spin_unlock(&dai->lock); } /* empty SSP receive FIFO */ static void ssp_empty_rx_fifo(struct dai *dai) { - struct ssp_pdata *ssp = dai_get_drvdata(dai); uint32_t sssr; uint32_t entries; uint32_t i; - spin_lock(&ssp->lock); + spin_lock(&dai->lock); sssr = ssp_read(dai, SSSR); @@ -102,7 +101,7 @@ static void ssp_empty_rx_fifo(struct dai *dai) ssp_read(dai, SSDR); } - spin_unlock(&ssp->lock); + spin_unlock(&dai->lock); } /* save SSP context prior to entering D3 */ @@ -171,7 +170,7 @@ static inline int ssp_set_config(struct dai *dai, bool start_delay = false; int ret = 0; - spin_lock(&ssp->lock); + spin_lock(&dai->lock); /* is playback/capture already running */ if (ssp->state[DAI_DIR_PLAYBACK] == COMP_STATE_ACTIVE || @@ -733,7 +732,7 @@ static inline int ssp_set_config(struct dai *dai, ssp->state[DAI_DIR_CAPTURE] = COMP_STATE_PREPARE; out: - spin_unlock(&ssp->lock); + spin_unlock(&dai->lock); return ret; } @@ -741,14 +740,12 @@ out: /* Digital Audio interface formatting */ static inline int ssp_set_loopback_mode(struct dai *dai, uint32_t lbm) { - struct ssp_pdata *ssp = dai_get_drvdata(dai); - trace_ssp("loo"); - spin_lock(&ssp->lock); + spin_lock(&dai->lock); ssp_update_bits(dai, SSCR1, SSCR1_LBM, lbm ? SSCR1_LBM : 0); - spin_unlock(&ssp->lock); + spin_unlock(&dai->lock); return 0; } @@ -758,7 +755,7 @@ static void ssp_start(struct dai *dai, int direction) { struct ssp_pdata *ssp = dai_get_drvdata(dai); - spin_lock(&ssp->lock); + spin_lock(&dai->lock); /* enable port */ ssp_update_bits(dai, SSCR0, SSCR0_SSE, SSCR0_SSE); @@ -775,7 +772,7 @@ static void ssp_start(struct dai *dai, int direction) ssp_update_bits(dai, SSRSA, 0x1 << 8, 0x1 << 8); } - spin_unlock(&ssp->lock); + spin_unlock(&dai->lock); } /* stop the SSP for either playback or capture */ @@ -783,7 +780,7 @@ static void ssp_stop(struct dai *dai, int direction) { struct ssp_pdata *ssp = dai_get_drvdata(dai); - spin_lock(&ssp->lock); + spin_lock(&dai->lock); /* wait to get valid fifo status */ wait_delay(PLATFORM_SSP_STOP_DELAY); @@ -817,7 +814,7 @@ static void ssp_stop(struct dai *dai, int direction) trace_ssp("Ss2"); } - spin_unlock(&ssp->lock); + spin_unlock(&dai->lock); } static int ssp_trigger(struct dai *dai, int cmd, int direction) @@ -871,13 +868,17 @@ static int ssp_probe(struct dai *dai) { struct ssp_pdata *ssp; + if (dai_get_drvdata(dai)) + return -EEXIST; /* already created */ + + /* Disable dynamic clock gating before touching any register */ + pm_runtime_get_sync(SSP_CLK, dai->index); + /* allocate private data */ ssp = rzalloc(RZONE_SYS | RZONE_FLAG_UNCACHED, SOF_MEM_CAPS_RAM, sizeof(*ssp)); dai_set_drvdata(dai, ssp); - spinlock_init(&ssp->lock); - ssp->state[DAI_DIR_PLAYBACK] = COMP_STATE_READY; ssp->state[DAI_DIR_CAPTURE] = COMP_STATE_READY; diff --git a/src/drivers/intel/dw-dma.c b/src/drivers/intel/dw-dma.c index 29008f59c..1e4f25d3b 100644 --- a/src/drivers/intel/dw-dma.c +++ b/src/drivers/intel/dw-dma.c @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -1276,6 +1277,12 @@ static int dw_dma_probe(struct dma *dma) struct dma_pdata *dw_pdata; int i; + if (dma_get_drvdata(dma)) + return -EEXIST; /* already created */ + + /* disable dynamic clock gating */ + pm_runtime_get_sync(DW_DMAC_CLK, dma->plat_data.id); + /* allocate private data */ dw_pdata = rzalloc(RZONE_SYS | RZONE_FLAG_UNCACHED, SOF_MEM_CAPS_RAM, sizeof(*dw_pdata)); diff --git a/src/drivers/intel/haswell/ssp.c b/src/drivers/intel/haswell/ssp.c index 2ca95effe..3365ce970 100644 --- a/src/drivers/intel/haswell/ssp.c +++ b/src/drivers/intel/haswell/ssp.c @@ -90,7 +90,7 @@ static inline int ssp_set_config(struct dai *dai, bool inverted_frame = false; int ret = 0; - spin_lock(&ssp->lock); + spin_lock(&dai->lock); /* is playback/capture already running */ if (ssp->state[DAI_DIR_PLAYBACK] == COMP_STATE_ACTIVE || @@ -360,7 +360,7 @@ static inline int ssp_set_config(struct dai *dai, ssp_update_bits(dai, SSCR0, SSCR0_SSE, 0); out: - spin_unlock(&ssp->lock); + spin_unlock(&dai->lock); return ret; } @@ -368,14 +368,12 @@ out: /* Digital Audio interface formatting */ static inline int ssp_set_loopback_mode(struct dai *dai, uint32_t lbm) { - struct ssp_pdata *ssp = dai_get_drvdata(dai); - trace_ssp("loo"); - spin_lock(&ssp->lock); + spin_lock(&dai->lock); ssp_update_bits(dai, SSCR1, SSCR1_LBM, lbm ? SSCR1_LBM : 0); - spin_unlock(&ssp->lock); + spin_unlock(&dai->lock); return 0; } @@ -385,7 +383,7 @@ static void ssp_start(struct dai *dai, int direction) { struct ssp_pdata *ssp = dai_get_drvdata(dai); - spin_lock(&ssp->lock); + spin_lock(&dai->lock); trace_ssp("sta"); @@ -408,7 +406,7 @@ static void ssp_start(struct dai *dai, int direction) ssp->state[direction] = COMP_STATE_ACTIVE; - spin_unlock(&ssp->lock); + spin_unlock(&dai->lock); } /* stop the SSP for either playback or capture */ @@ -416,7 +414,7 @@ static void ssp_stop(struct dai *dai, int direction) { struct ssp_pdata *ssp = dai_get_drvdata(dai); - spin_lock(&ssp->lock); + spin_lock(&dai->lock); /* stop Rx if neeed */ if (direction == DAI_DIR_CAPTURE && @@ -445,7 +443,7 @@ static void ssp_stop(struct dai *dai, int direction) trace_ssp("Ss2"); } - spin_unlock(&ssp->lock); + spin_unlock(&dai->lock); } static int ssp_trigger(struct dai *dai, int cmd, int direction) @@ -504,7 +502,7 @@ static int ssp_probe(struct dai *dai) sizeof(*ssp)); dai_set_drvdata(dai, ssp); - spinlock_init(&ssp->lock); + spinlock_init(&dai->lock); ssp->state[DAI_DIR_PLAYBACK] = COMP_STATE_READY; ssp->state[DAI_DIR_CAPTURE] = COMP_STATE_READY; diff --git a/src/include/sof/dai.h b/src/include/sof/dai.h index 90434188c..c9644947e 100644 --- a/src/include/sof/dai.h +++ b/src/include/sof/dai.h @@ -88,16 +88,6 @@ struct dai_slot_map { uint32_t slot; /**< physical slot index */ }; -/** - * \brief DAI Type. - */ -enum dai_type { - DAI_TYPE_INTEL_SSP = 0, /**< Intel SSP */ - DAI_TYPE_INTEL_HDA, /**< Intel HD/A */ - DAI_TYPE_INTEL_DMIC, /**< Intel DMIC */ -}; - - struct dai_plat_fifo_data { uint32_t offset; uint32_t width; @@ -117,8 +107,10 @@ struct dai_plat_data { }; struct dai { - uint32_t type; - uint32_t index; + uint32_t type; /**< type, one of SOF_DAI_... */ + uint32_t index; /**< index */ + spinlock_t lock; + int sref; /**< simple ref counter, guarded by lock */ struct dai_plat_data plat_data; const struct dai_ops *ops; void *private; @@ -154,7 +146,7 @@ struct dai *dai_get(uint32_t type, uint32_t index); #define dai_set_drvdata(dai, data) \ dai->private = data; #define dai_get_drvdata(dai) \ - dai->private; + dai->private #define dai_base(dai) \ dai->plat_data.base #define dai_irq(dai) \ diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 491938f0f..7f8af2174 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -162,6 +162,7 @@ struct dma_plat_data { struct dma { struct dma_plat_data plat_data; spinlock_t lock; + int sref; /**< simple ref counter, guarded by lock */ const struct dma_ops *ops; atomic_t num_channels_busy; /* number of busy channels */ void *private; @@ -190,7 +191,7 @@ struct dma *dma_get(uint32_t dir, uint32_t caps, uint32_t dev, uint32_t flags); #define dma_set_drvdata(dma, data) \ dma->private = data; #define dma_get_drvdata(dma) \ - dma->private; + dma->private #define dma_base(dma) \ dma->plat_data.base #define dma_irq(dma, cpu) \ diff --git a/src/include/sof/dmic.h b/src/include/sof/dmic.h index 9bbf491ad..1027ef8da 100644 --- a/src/include/sof/dmic.h +++ b/src/include/sof/dmic.h @@ -317,7 +317,6 @@ /* DMIC private data */ struct dmic_pdata { - spinlock_t lock; /* Spinlock that's used in registers IO */ uint16_t fifo_a; uint16_t fifo_b; uint16_t enable[DMIC_HW_CONTROLLERS]; diff --git a/src/include/sof/ssp.h b/src/include/sof/ssp.h index a9defcf26..92ac4f44a 100644 --- a/src/include/sof/ssp.h +++ b/src/include/sof/ssp.h @@ -249,7 +249,6 @@ struct ssp_pdata { uint32_t sscr0; uint32_t sscr1; uint32_t psp; - spinlock_t lock; uint32_t state[2]; /* SSP_STATE_ for each direction */ completion_t drain_complete; struct sof_ipc_dai_config config; diff --git a/src/ipc/handler.c b/src/ipc/handler.c index c723c964f..58c660685 100644 --- a/src/ipc/handler.c +++ b/src/ipc/handler.c @@ -1140,7 +1140,8 @@ int ipc_queue_host_message(struct ipc *ipc, uint32_t header, void *tx_data, msg = msg_get_empty(ipc); if (msg == NULL) { - trace_ipc_error("eQb"); + trace_error(TRACE_CLASS_IPC, "eQb header 0x08x replace %d", + header, replace); ret = -EBUSY; goto out; } diff --git a/src/lib/dai.c b/src/lib/dai.c index 270e8ab38..5e43221eb 100644 --- a/src/lib/dai.c +++ b/src/lib/dai.c @@ -46,19 +46,52 @@ void dai_install(struct dai_type_info *dai_type_array, size_t num_dai_types) lib_dai.num_dai_types = num_dai_types; } -struct dai *dai_get(uint32_t type, uint32_t index) +static inline struct dai_type_info *dai_find_type(uint32_t type) { - int i; struct dai_type_info *dti; - for (dti = lib_dai.dai_type_array; dti < lib_dai.dai_type_array + lib_dai.num_dai_types; dti++) { - if (dti->type == type) { - for (i = 0; i < dti->num_dais; i++) { - if (dti->dai_array[i].index == index) - return dti->dai_array + i; - } - } + if (dti->type == type) + return dti; } return NULL; } + +struct dai *dai_get(uint32_t type, uint32_t index) +{ + int ret = 0; + struct dai_type_info *dti; + struct dai *d; + + dti = dai_find_type(type); + if (!dti) + return NULL; /* type not found */ + + for (d = dti->dai_array; d < dti->dai_array + dti->num_dais; d++) { + if (d->index != index) + continue; + /* device created? */ + spin_lock(&d->lock); + if (d->sref == 0) { + trace_event(TRACE_CLASS_DAI, + "dai-probe type %d index %d", + type, index); + + ret = dai_probe(d); + if (ret < 0) { + trace_error(TRACE_CLASS_DAI, + "probe failed %d", + ret); + } + } + if (!ret) + d->sref++; + trace_event(TRACE_CLASS_DAI, "dai-get %p sref %d", + (uintptr_t)d, d->sref); + spin_unlock(&d->lock); + return !ret ? d : NULL; + } + trace_error(TRACE_CLASS_DAI, "dai-get type %d index %d not found", + type, index); + return NULL; +} diff --git a/src/lib/dma.c b/src/lib/dma.c index 53fae9690..014c6b1c5 100644 --- a/src/lib/dma.c +++ b/src/lib/dma.c @@ -50,7 +50,7 @@ void dma_install(struct dma *dma_array, size_t num_dmas) struct dma *dma_get(uint32_t dir, uint32_t cap, uint32_t dev, uint32_t flags) { - int ch_count; + int ch_count, ret; int min_ch_count = INT32_MAX; struct dma *d = NULL, *dmin = NULL; @@ -93,9 +93,32 @@ struct dma *dma_get(uint32_t dir, uint32_t cap, uint32_t dev, uint32_t flags) /* return DMAC */ if (dmin) { - tracev_value(dmin->plat_data.id); - return dmin; + tracev_event(TRACE_CLASS_DMA, "dma-probe id %d", + dmin->plat_data.id); + /* Shared DMA controllers with multiple channels + * may be requested many times, let the probe() + * do on-first-use initialization. + */ + spin_lock(&dmin->lock); + ret = 0; + if (dmin->sref == 0) { + ret = dma_probe(dmin); + if (ret < 0) { + trace_error(TRACE_CLASS_DMA, + "dma-probe failed id %d ret %d", + dmin->plat_data.id, ret); + } + } + if (!ret) + dmin->sref++; + trace_event(TRACE_CLASS_DMA, "dma-get %p sref %d", + (uintptr_t)dmin, dmin->sref); + spin_unlock(&dmin->lock); + return !ret ? dmin : NULL; } + trace_error(TRACE_CLASS_DMA, + "dma-get dir 0x%x cap 0x%x dev 0x%x flags 0x%x not found", + dir, cap, dev, flags); return NULL; } diff --git a/src/platform/apollolake/include/platform/asm_memory_management.h b/src/platform/apollolake/include/platform/asm_memory_management.h index 7ef9cb24a..69246fb8c 100644 --- a/src/platform/apollolake/include/platform/asm_memory_management.h +++ b/src/platform/apollolake/include/platform/asm_memory_management.h @@ -40,6 +40,7 @@ #warning "ASSEMBLY macro not defined." #endif +#include #include #include diff --git a/src/platform/apollolake/include/platform/shim.h b/src/platform/apollolake/include/platform/shim.h index a121410f4..cfa10b533 100644 --- a/src/platform/apollolake/include/platform/shim.h +++ b/src/platform/apollolake/include/platform/shim.h @@ -145,37 +145,72 @@ #define SHIM_DSPWCTCS_T1A (0x1 << 1) /* Timer 1 armed */ #define SHIM_DSPWCTCS_T0A (0x1 << 0) /* Timer 0 armed */ -#define SHIM_CLKCTL 0x78 -#define SHIM_CLKSTS 0x7C - -#define SHIM_CLKCTL_RAPLLC (0x1 << 31) -#define SHIM_CLKCTL_RXOSCC (0x1 << 30) -#define SHIM_CLKCTL_RFROSCC (0x1 << 29) - +/** \brief LDO Control */ #define SHIM_LDOCTL 0xA4 -/* LP GPDMA Force Dynamic Clock Gating bits, 0--enable */ -#define SHIM_CLKCTL_LPGPDMAFDCGB(x) (0x1 << (26 + x)) -#define SHIM_CLKCTL_DMICFDCGB (0x1 << 24) -#define SHIM_CLKCTL_I2SFDCGB(x) (0x1 << (20 + x)) -#define SHIM_CLKCTL_I2SEFDCGB(x) (0x1 << (18 + x)) -#define SHIM_CLKCTL_TCPLCG(x) (0x1 << (16 + x)) +/** \brief Clock control */ +#define SHIM_CLKCTL 0x78 -/* Core clock PLL divisor */ +/** \brief Clock status */ +#define SHIM_CLKSTS 0x7C + +/** \brief Request Audio PLL Clock */ +#define SHIM_CLKCTL_RAPLLC BIT(31) + +/** \brief Request XTAL Oscillator Clock */ +#define SHIM_CLKCTL_RXOSCC BIT(30) + +/** \brief Request Fast RING Oscillator Clock */ +#define SHIM_CLKCTL_RFROSCC BIT(29) + +/** \brief LP GPDMA Force Dynamic Clock Gating bits, 0: enable */ +#define SHIM_CLKCTL_LPGPDMAFDCGB(x) BIT(26 + x) + +/** \brief DMIC Force Dynamic Clock Gating */ +#define SHIM_CLKCTL_DMICFDCGB BIT(24) + +/** \brief I2S Force Dynamic Clock Gating */ +#define SHIM_CLKCTL_I2SFDCGB(x) BIT(20 + x) + +/** \brief I2S Extension Force Dynamic Clock Gating */ +#define SHIM_CLKCTL_I2SEFDCGB(x) BIT(18 + x) + +/** \brief Tensilica Core Prevent Local Clock Gating */ +#define SHIM_CLKCTL_TCPLCG_EN(x) BIT(16 + x) +#define SHIM_CLKCTL_TCPLCG_DIS(x) 0 + +/** \brief Core clock PLL divisor */ #define SHIM_CLKCTL_DPCS_MASK(x) (0x3 << (8 + x * 2)) -/* Prevent Audio PLL Shutdown */ -#define SHIM_CLKCTL_TCPAPLLS (0x1 << 7) +#define SHIM_CLKCTL_DPCS_DIV1(x) (0x0 << (8 + x * 2)) +#define SHIM_CLKCTL_DPCS_DIV2(x) (0x1 << (8 + x * 2)) +#define SHIM_CLKCTL_DPCS_DIV4(x) (0x3 << (8 + x * 2)) -/* 0--from PLL, 1--from oscillator */ -#define SHIM_CLKCTL_LDCS (0x1 << 5) -#define SHIM_CLKCTL_HDCS (0x1 << 4) +/** \brief Tensilica Core Prevent Audio PLL Shutdown */ +#define SHIM_CLKCTL_TCPAPLLS_EN BIT(7) +#define SHIM_CLKCTL_TCPAPLLS_DIS 0 -/* Oscillator clock select select 0--XTAL, 1--Fast RING*/ -#define SHIM_CLKCTL_LDOCS (0x1 << 3) -#define SHIM_CLKCTL_HDOCS (0x1 << 2) +/** \brief LP domain clock select, 0: PLL, 1: oscillator */ +#define SHIM_CLKCTL_LDCS_XTAL BIT(5) +#define SHIM_CLKCTL_LDCS_PLL 0 -/* HP memory clock PLL divisor */ -#define SHIM_CLKCTL_HPMPCS (0x1 << 0) +/** \brief HP domain clock select */ +#define SHIM_CLKCTL_HDCS BIT(4) +#define SHIM_CLKCTL_HDCS_XTAL BIT(4) +#define SHIM_CLKCTL_HDCS_PLL 0 + +/** \brief LP domain oscillator clock select select, 0: XTAL, 1: Fast RING */ +#define SHIM_CLKCTL_LDOCS BIT(3) + +/** \brief HP domain oscillator clock select select, 0: XTAL, 1: Fast RING */ +#define SHIM_CLKCTL_HDOCS BIT(2) + +/** \brief LP memory clock PLL divisor, 0: div by 2, 1: div by 4 */ +#define SHIM_CLKCTL_LPMPCS_DIV4 BIT(1) +#define SHIM_CLKCTL_LPMPCS_DIV2 0 + +/** \brief HP memory clock PLL divisor, 0: div by 2, 1: div by 4 */ +#define SHIM_CLKCTL_HPMPCS_DIV4 BIT(0) +#define SHIM_CLKCTL_HPMPCS_DIV2 0 #define SHIM_PWRCTL 0x90 #define SHIM_PWRSTS 0x92 diff --git a/src/platform/apollolake/power_down.S b/src/platform/apollolake/power_down.S index b0c04b588..b75c7b4cf 100644 --- a/src/platform/apollolake/power_down.S +++ b/src/platform/apollolake/power_down.S @@ -115,7 +115,7 @@ _PD_SWITCH_TO_XTAL_CLOCK: // TODO: move to CLOCK hal macros movi temp_reg0, (SHIM_BASE + SHIM_CLKCTL) movi temp_reg1, ~(SHIM_CLKCTL_HDOCS | SHIM_CLKCTL_LDOCS) - movi temp_reg2, (SHIM_CLKCTL_LDCS | SHIM_CLKCTL_HDCS) + movi temp_reg2, (SHIM_CLKCTL_LDCS_XTAL | SHIM_CLKCTL_HDCS_XTAL) l32i temp_reg3, temp_reg0, 0 // Reset LDOCS & HDOCS bits to select XTAL and temp_reg3, temp_reg3, temp_reg1 diff --git a/src/platform/intel/Makefile.am b/src/platform/intel/Makefile.am index 6a966baf3..c2c6328c8 100644 --- a/src/platform/intel/Makefile.am +++ b/src/platform/intel/Makefile.am @@ -1,5 +1,4 @@ -SUBDIRS = include - +SUBDIRS = if BUILD_CAVS SUBDIRS += cavs -endif \ No newline at end of file +endif diff --git a/src/platform/intel/cavs/dai.c b/src/platform/intel/cavs/dai.c index 3ff261393..4bd2f3ef6 100644 --- a/src/platform/intel/cavs/dai.c +++ b/src/platform/intel/cavs/dai.c @@ -231,25 +231,26 @@ int dai_init(void) { int i; + /* init ssp */ + /* TODO: move all the properties initialization here */ + for (i = 0; i < ARRAY_SIZE(ssp); i++) { + /* initialize spin locks early to enable ref counting */ + spinlock_init(&ssp[i].lock); + } + /* init hd/a, note that size depends on the platform caps */ for (i = 0; i < ARRAY_SIZE(hda); i++) { hda[i].type = SOF_DAI_INTEL_HDA; hda[i].index = i; hda[i].ops = &hda_ops; + spinlock_init(&hda[i].lock); } - /* init SSP ports */ - trace_point(TRACE_BOOT_PLATFORM_SSP); - for (i = 0; i < DAI_NUM_SSP_BASE + DAI_NUM_SSP_EXT; i++) - dai_probe(ssp + i); - - /* Init DMIC. Note that the two PDM controllers and four microphones - * supported max. those are available in platform are handled by dmic0. - */ - trace_point(TRACE_BOOT_PLATFORM_DMIC); - - dai_probe(dmic + 0); - +#if defined(CONFIG_DMIC) + /* init dmic */ + for (i = 0; i < ARRAY_SIZE(dmic); i++) + spinlock_init(&dmic[i].lock); +#endif dai_install(dti, ARRAY_SIZE(dti)); return 0; } diff --git a/src/platform/intel/cavs/dma.c b/src/platform/intel/cavs/dma.c index 4a79ee1c5..36ee217da 100644 --- a/src/platform/intel/cavs/dma.c +++ b/src/platform/intel/cavs/dma.c @@ -263,18 +263,14 @@ struct dma dma[CAVS_PLATFORM_NUM_DMACS] = { /* Initialize all platform DMAC's */ int dmac_init(void) { - int i, ret; + int i; + /* no probing before first use */ - for (i = 0; i < ARRAY_SIZE(dma); i++) { - ret = dma_probe(&dma[i]); - if (ret < 0) { + /* TODO: dynamic init based on platform settings */ - /* trace failed DMAC ID */ - trace_error(TRACE_CLASS_DMA, "edi"); - trace_error_value(dma[i].plat_data.id); - return ret; - } - } + /* early lock initialization for ref counting */ + for (i = 0; i < ARRAY_SIZE(dma); i++) + spinlock_init(&dma[i].lock); /* tell the lib DMAs are ready to use */ dma_install(dma, ARRAY_SIZE(dma)); diff --git a/src/platform/intel/cavs/platform.c b/src/platform/intel/cavs/platform.c index 15b16db6b..905065e5c 100644 --- a/src/platform/intel/cavs/platform.c +++ b/src/platform/intel/cavs/platform.c @@ -321,40 +321,37 @@ int platform_init(struct sof *sof) /* init the system agent */ sa_init(sof); - /* Set CPU to default frequency for booting */ + /* Set CPU to max frequency for booting (single shim_write below) */ trace_point(TRACE_BOOT_SYS_CPU_FREQ); - clock_set_freq(CLK_CPU, CLK_MAX_CPU_HZ); - - /* set SSP clock */ - trace_point(TRACE_BOOT_PLATFORM_SSP_FREQ); - clock_set_freq(CLK_SSP, SSP_CLOCK_FREQUENCY); - - /* initialise the host IPC mechanisms */ - trace_point(TRACE_BOOT_PLATFORM_IPC); - ipc_init(sof); #if defined(CONFIG_APOLLOLAKE) - /* disable PM for boot */ - shim_write(SHIM_CLKCTL, shim_read(SHIM_CLKCTL) | - SHIM_CLKCTL_LPGPDMAFDCGB(0) | - SHIM_CLKCTL_LPGPDMAFDCGB(1) | - SHIM_CLKCTL_I2SFDCGB(3) | - SHIM_CLKCTL_I2SFDCGB(2) | - SHIM_CLKCTL_I2SFDCGB(1) | - SHIM_CLKCTL_I2SFDCGB(0) | - SHIM_CLKCTL_DMICFDCGB | - SHIM_CLKCTL_I2SEFDCGB(1) | - SHIM_CLKCTL_I2SEFDCGB(0) | - SHIM_CLKCTL_TCPAPLLS | - SHIM_CLKCTL_RAPLLC | - SHIM_CLKCTL_RXOSCC | - SHIM_CLKCTL_RFROSCC | - SHIM_CLKCTL_TCPLCG(0) | SHIM_CLKCTL_TCPLCG(1)); + /* initialize PM for boot */ + + /* TODO: there are two clk freqs CRO & CRO/4 + * Running on CRO all the time atm + */ + + /* TODO: do not do local clock gating until making sure that + * tensilica core timer is unused. + * Could not find any arch_timer_set/timer_set() direct calls + * on cavs platforms atm. + */ + shim_write(SHIM_CLKCTL, + SHIM_CLKCTL_HDCS_PLL | /* HP domain clocked by PLL */ + SHIM_CLKCTL_LDCS_PLL | /* LP domain clocked by PLL */ + SHIM_CLKCTL_DPCS_DIV1(0) | /* Core 0 clk not divided */ + SHIM_CLKCTL_DPCS_DIV1(1) | /* Core 1 clk not divided */ + SHIM_CLKCTL_HPMPCS_DIV2 | /* HP mem clock div by 2 */ + SHIM_CLKCTL_LPMPCS_DIV4 | /* LP mem clock div by 4 */ + SHIM_CLKCTL_TCPAPLLS_DIS | + SHIM_CLKCTL_TCPLCG_DIS(0) | SHIM_CLKCTL_TCPLCG_DIS(1)); shim_write(SHIM_LPSCTL, shim_read(SHIM_LPSCTL)); #elif defined(CONFIG_CANNONLAKE) || defined(CONFIG_ICELAKE) \ || defined(CONFIG_SUECREEK) + /* TODO: need to merge as for APL */ + clock_set_freq(CLK_CPU, CLK_MAX_CPU_HZ); /* prevent Core0 clock gating. */ shim_write(SHIM_CLKCTL, shim_read(SHIM_CLKCTL) | @@ -368,12 +365,17 @@ int platform_init(struct sof *sof) shim_write16(SHIM_PWRCTL, SHIM_PWRCTL_TCPDSP0PG); #endif + /* initialize the host IPC mechanisms */ + trace_point(TRACE_BOOT_PLATFORM_IPC); + ipc_init(sof); + /* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA); ret = dmac_init(); if (ret < 0) return -ENODEV; + /* init DAIs */ ret = dai_init(); if (ret < 0) return -ENODEV; diff --git a/src/platform/intel/cavs/pm_runtime.c b/src/platform/intel/cavs/pm_runtime.c index 17ad2f14c..4e77d165c 100644 --- a/src/platform/intel/cavs/pm_runtime.c +++ b/src/platform/intel/cavs/pm_runtime.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #if defined(CONFIG_APOLLOLAKE) //TODO: add support or at least stub api for Cannonlake & Icelake @@ -48,6 +48,68 @@ /** \brief Runtime power management data pointer. */ struct pm_runtime_data *_prd; +/** + * \brief Forces Host DMAs to exit L1. + */ +static inline void cavs_pm_runtime_force_host_dma_l1_exit(void) +{ + uint32_t flags; + + spin_lock_irq(&_prd->lock, flags); + + if (!(shim_read(SHIM_SVCFG) & SHIM_SVCFG_FORCE_L1_EXIT)) { + shim_write(SHIM_SVCFG, + shim_read(SHIM_SVCFG) | SHIM_SVCFG_FORCE_L1_EXIT); + + wait_delay(PLATFORM_FORCE_L1_EXIT_TIME); + + shim_write(SHIM_SVCFG, + shim_read(SHIM_SVCFG) & ~(SHIM_SVCFG_FORCE_L1_EXIT)); + } + + spin_unlock_irq(&_prd->lock, flags); +} + +static inline void cavs_pm_runtime_dis_ssp_clk_gating(uint32_t index) +{ +#if defined(CONFIG_APOLLOLAKE) + shim_write(SHIM_CLKCTL, shim_read(SHIM_CLKCTL) | + (index < DAI_NUM_SSP_BASE ? + SHIM_CLKCTL_I2SFDCGB(index) : + SHIM_CLKCTL_I2SEFDCGB(index))); + + trace_event(TRACE_CLASS_POWER, + "dis-ssp-clk-gating index %d CLKCTL %08x", + index, shim_read(SHIM_CLKCTL)); +#endif +} + +#if defined(CONFIG_DMIC) +static inline void cavs_pm_runtime_dis_dmic_clk_gating(uint32_t index) +{ +#if defined(CONFIG_APOLLOLAKE) + (void)index; + shim_write(SHIM_CLKCTL, shim_read(SHIM_CLKCTL) | SHIM_CLKCTL_DMICFDCGB); + + trace_event(TRACE_CLASS_POWER, + "dis-dmic-clk-gating index %d CLKCTL %08x", + index, shim_read(SHIM_CLKCTL)); +#endif +} +#endif + +static inline void cavs_pm_runtime_dis_dwdma_clk_gating(uint32_t index) +{ +#if defined(CONFIG_APOLLOLAKE) + shim_write(SHIM_CLKCTL, shim_read(SHIM_CLKCTL) | + SHIM_CLKCTL_LPGPDMAFDCGB(index)); + + trace_event(TRACE_CLASS_POWER, + "dis-dwdma-clk-gating index %d CLKCTL %08x", + index, shim_read(SHIM_CLKCTL)); +#endif +} + void platform_pm_runtime_init(struct pm_runtime_data *prd) { struct platform_pm_runtime_data *pprd; @@ -62,6 +124,21 @@ void platform_pm_runtime_get(enum pm_runtime_context context, uint32_t index, uint32_t flags) { /* Action based on context */ + switch (context) { + case SSP_CLK: + cavs_pm_runtime_dis_ssp_clk_gating(index); + break; +#if defined(CONFIG_DMIC) + case DMIC_CLK: + cavs_pm_runtime_dis_dmic_clk_gating(index); + break; +#endif + case DW_DMAC_CLK: + cavs_pm_runtime_dis_dwdma_clk_gating(index); + break; + default: + break; + } } void platform_pm_runtime_put(enum pm_runtime_context context, uint32_t index, diff --git a/src/platform/intel/include/Makefile.am b/src/platform/intel/include/Makefile.am deleted file mode 100644 index 912728c3a..000000000 --- a/src/platform/intel/include/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -SUBDIRS = platform diff --git a/src/platform/intel/include/platform/Makefile.am b/src/platform/intel/include/platform/Makefile.am deleted file mode 100644 index 13161e049..000000000 --- a/src/platform/intel/include/platform/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -if BUILD_CAVS -SUBDIRS = cavs -endif diff --git a/src/platform/intel/include/platform/cavs/Makefile.am b/src/platform/intel/include/platform/cavs/Makefile.am deleted file mode 100644 index 712c19764..000000000 --- a/src/platform/intel/include/platform/cavs/Makefile.am +++ /dev/null @@ -1,2 +0,0 @@ -noinst_HEADERS = \ - pm_runtime.h diff --git a/src/platform/intel/include/platform/cavs/pm_runtime.h b/src/platform/intel/include/platform/cavs/pm_runtime.h deleted file mode 100644 index e6b483deb..000000000 --- a/src/platform/intel/include/platform/cavs/pm_runtime.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2018, Intel Corporation - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the Intel Corporation nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * Author: Tomasz Lauda - */ - -/** - * \file platform/intel/platform/cavs/include/pm_runtime.h - * \brief Runtime power management header file for cAVS - * \author Tomasz Lauda - */ - -#ifndef __INCLUDE_CAVS_PM_RUNTIME__ -#define __INCLUDE_CAVS_PM_RUNTIME__ - -#include - -extern struct pm_runtime_data *_prd; - -/** - * \brief Forces Host DMAs to exit L1. - */ -static inline void cavs_pm_runtime_force_host_dma_l1_exit(void) -{ - uint32_t flags; - - spin_lock_irq(&_prd->lock, flags); - - if (!(shim_read(SHIM_SVCFG) & SHIM_SVCFG_FORCE_L1_EXIT)) { - shim_write(SHIM_SVCFG, - shim_read(SHIM_SVCFG) | SHIM_SVCFG_FORCE_L1_EXIT); - - wait_delay(PLATFORM_FORCE_L1_EXIT_TIME); - - shim_write(SHIM_SVCFG, - shim_read(SHIM_SVCFG) & ~(SHIM_SVCFG_FORCE_L1_EXIT)); - } - - spin_unlock_irq(&_prd->lock, flags); -} -#endif /* __INCLUDE_CAVS_PM_RUNTIME__ */