mirror of https://github.com/thesofproject/sof.git
Merge pull request #452 from mmaka1/clk-gating
plat: apl: clock gating adjusted for dai, dma, and cores
This commit is contained in:
commit
b180af8ba7
|
@ -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
|
||||
|
|
|
@ -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
|
||||
])
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <sof/stream.h>
|
||||
#include <sof/dmic.h>
|
||||
#include <sof/interrupt.h>
|
||||
#include <sof/pm_runtime.h>
|
||||
#include <sof/math/numbers.h>
|
||||
#include <sof/audio/format.h>
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <sof/ssp.h>
|
||||
#include <sof/alloc.h>
|
||||
#include <sof/interrupt.h>
|
||||
#include <sof/pm_runtime.h>
|
||||
#include <sof/math/numbers.h>
|
||||
#include <config.h>
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include <sof/lock.h>
|
||||
#include <sof/trace.h>
|
||||
#include <sof/wait.h>
|
||||
#include <sof/pm_runtime.h>
|
||||
#include <sof/audio/component.h>
|
||||
#include <sof/cpu.h>
|
||||
#include <platform/dma.h>
|
||||
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
@ -1134,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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#warning "ASSEMBLY macro not defined."
|
||||
#endif
|
||||
|
||||
#include <sof/bit.h>
|
||||
#include <platform/shim.h>
|
||||
#include <platform/platcfg.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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
SUBDIRS = include
|
||||
|
||||
SUBDIRS =
|
||||
if BUILD_CAVS
|
||||
SUBDIRS += cavs
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#include <sof/alloc.h>
|
||||
#include <platform/platform.h>
|
||||
#include <platform/pm_runtime.h>
|
||||
#include <platform/cavs/pm_runtime.h>
|
||||
#include <platform/dai.h>
|
||||
|
||||
#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,
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
SUBDIRS = platform
|
|
@ -1,3 +0,0 @@
|
|||
if BUILD_CAVS
|
||||
SUBDIRS = cavs
|
||||
endif
|
|
@ -1,2 +0,0 @@
|
|||
noinst_HEADERS = \
|
||||
pm_runtime.h
|
|
@ -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 <tomasz.lauda@linux.intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file platform/intel/platform/cavs/include/pm_runtime.h
|
||||
* \brief Runtime power management header file for cAVS
|
||||
* \author Tomasz Lauda <tomasz.lauda@linux.intel.com>
|
||||
*/
|
||||
|
||||
#ifndef __INCLUDE_CAVS_PM_RUNTIME__
|
||||
#define __INCLUDE_CAVS_PM_RUNTIME__
|
||||
|
||||
#include <platform/pm_runtime.h>
|
||||
|
||||
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__ */
|
Loading…
Reference in New Issue