162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * skl-sst-dsp.c - SKL SST library generic function 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2014-15, Intel Corporation. 662306a36Sopenharmony_ci * Author:Rafal Redzimski <rafal.f.redzimski@intel.com> 762306a36Sopenharmony_ci * Jeeja KP <jeeja.kp@intel.com> 862306a36Sopenharmony_ci * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci#include <sound/pcm.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "../common/sst-dsp.h" 1362306a36Sopenharmony_ci#include "../common/sst-ipc.h" 1462306a36Sopenharmony_ci#include "../common/sst-dsp-priv.h" 1562306a36Sopenharmony_ci#include "skl.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/* various timeout values */ 1862306a36Sopenharmony_ci#define SKL_DSP_PU_TO 50 1962306a36Sopenharmony_ci#define SKL_DSP_PD_TO 50 2062306a36Sopenharmony_ci#define SKL_DSP_RESET_TO 50 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_civoid skl_dsp_set_state_locked(struct sst_dsp *ctx, int state) 2362306a36Sopenharmony_ci{ 2462306a36Sopenharmony_ci mutex_lock(&ctx->mutex); 2562306a36Sopenharmony_ci ctx->sst_state = state; 2662306a36Sopenharmony_ci mutex_unlock(&ctx->mutex); 2762306a36Sopenharmony_ci} 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/* 3062306a36Sopenharmony_ci * Initialize core power state and usage count. To be called after 3162306a36Sopenharmony_ci * successful first boot. Hence core 0 will be running and other cores 3262306a36Sopenharmony_ci * will be reset 3362306a36Sopenharmony_ci */ 3462306a36Sopenharmony_civoid skl_dsp_init_core_state(struct sst_dsp *ctx) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci struct skl_dev *skl = ctx->thread_context; 3762306a36Sopenharmony_ci int i; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING; 4062306a36Sopenharmony_ci skl->cores.usage_count[SKL_DSP_CORE0_ID] = 1; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci for (i = SKL_DSP_CORE0_ID + 1; i < skl->cores.count; i++) { 4362306a36Sopenharmony_ci skl->cores.state[i] = SKL_DSP_RESET; 4462306a36Sopenharmony_ci skl->cores.usage_count[i] = 0; 4562306a36Sopenharmony_ci } 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/* Get the mask for all enabled cores */ 4962306a36Sopenharmony_ciunsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci struct skl_dev *skl = ctx->thread_context; 5262306a36Sopenharmony_ci unsigned int core_mask, en_cores_mask; 5362306a36Sopenharmony_ci u32 val; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci core_mask = SKL_DSP_CORES_MASK(skl->cores.count); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci /* Cores having CPA bit set */ 6062306a36Sopenharmony_ci en_cores_mask = (val & SKL_ADSPCS_CPA_MASK(core_mask)) >> 6162306a36Sopenharmony_ci SKL_ADSPCS_CPA_SHIFT; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci /* And cores having CRST bit cleared */ 6462306a36Sopenharmony_ci en_cores_mask &= (~val & SKL_ADSPCS_CRST_MASK(core_mask)) >> 6562306a36Sopenharmony_ci SKL_ADSPCS_CRST_SHIFT; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci /* And cores having CSTALL bit cleared */ 6862306a36Sopenharmony_ci en_cores_mask &= (~val & SKL_ADSPCS_CSTALL_MASK(core_mask)) >> 6962306a36Sopenharmony_ci SKL_ADSPCS_CSTALL_SHIFT; 7062306a36Sopenharmony_ci en_cores_mask &= core_mask; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci dev_dbg(ctx->dev, "DSP enabled cores mask = %x\n", en_cores_mask); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci return en_cores_mask; 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic int 7862306a36Sopenharmony_ciskl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci int ret; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci /* update bits */ 8362306a36Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, 8462306a36Sopenharmony_ci SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK(core_mask), 8562306a36Sopenharmony_ci SKL_ADSPCS_CRST_MASK(core_mask)); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci /* poll with timeout to check if operation successful */ 8862306a36Sopenharmony_ci ret = sst_dsp_register_poll(ctx, 8962306a36Sopenharmony_ci SKL_ADSP_REG_ADSPCS, 9062306a36Sopenharmony_ci SKL_ADSPCS_CRST_MASK(core_mask), 9162306a36Sopenharmony_ci SKL_ADSPCS_CRST_MASK(core_mask), 9262306a36Sopenharmony_ci SKL_DSP_RESET_TO, 9362306a36Sopenharmony_ci "Set reset"); 9462306a36Sopenharmony_ci if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 9562306a36Sopenharmony_ci SKL_ADSPCS_CRST_MASK(core_mask)) != 9662306a36Sopenharmony_ci SKL_ADSPCS_CRST_MASK(core_mask)) { 9762306a36Sopenharmony_ci dev_err(ctx->dev, "Set reset state failed: core_mask %x\n", 9862306a36Sopenharmony_ci core_mask); 9962306a36Sopenharmony_ci ret = -EIO; 10062306a36Sopenharmony_ci } 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci return ret; 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ciint skl_dsp_core_unset_reset_state( 10662306a36Sopenharmony_ci struct sst_dsp *ctx, unsigned int core_mask) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci int ret; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci dev_dbg(ctx->dev, "In %s\n", __func__); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci /* update bits */ 11362306a36Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 11462306a36Sopenharmony_ci SKL_ADSPCS_CRST_MASK(core_mask), 0); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci /* poll with timeout to check if operation successful */ 11762306a36Sopenharmony_ci ret = sst_dsp_register_poll(ctx, 11862306a36Sopenharmony_ci SKL_ADSP_REG_ADSPCS, 11962306a36Sopenharmony_ci SKL_ADSPCS_CRST_MASK(core_mask), 12062306a36Sopenharmony_ci 0, 12162306a36Sopenharmony_ci SKL_DSP_RESET_TO, 12262306a36Sopenharmony_ci "Unset reset"); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 12562306a36Sopenharmony_ci SKL_ADSPCS_CRST_MASK(core_mask)) != 0) { 12662306a36Sopenharmony_ci dev_err(ctx->dev, "Unset reset state failed: core_mask %x\n", 12762306a36Sopenharmony_ci core_mask); 12862306a36Sopenharmony_ci ret = -EIO; 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci return ret; 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistatic bool 13562306a36Sopenharmony_ciis_skl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci int val; 13862306a36Sopenharmony_ci bool is_enable; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci is_enable = ((val & SKL_ADSPCS_CPA_MASK(core_mask)) && 14362306a36Sopenharmony_ci (val & SKL_ADSPCS_SPA_MASK(core_mask)) && 14462306a36Sopenharmony_ci !(val & SKL_ADSPCS_CRST_MASK(core_mask)) && 14562306a36Sopenharmony_ci !(val & SKL_ADSPCS_CSTALL_MASK(core_mask))); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci dev_dbg(ctx->dev, "DSP core(s) enabled? %d : core_mask %x\n", 14862306a36Sopenharmony_ci is_enable, core_mask); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci return is_enable; 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_cistatic int skl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask) 15462306a36Sopenharmony_ci{ 15562306a36Sopenharmony_ci /* stall core */ 15662306a36Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 15762306a36Sopenharmony_ci SKL_ADSPCS_CSTALL_MASK(core_mask), 15862306a36Sopenharmony_ci SKL_ADSPCS_CSTALL_MASK(core_mask)); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci /* set reset state */ 16162306a36Sopenharmony_ci return skl_dsp_core_set_reset_state(ctx, core_mask); 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ciint skl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask) 16562306a36Sopenharmony_ci{ 16662306a36Sopenharmony_ci int ret; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci /* unset reset state */ 16962306a36Sopenharmony_ci ret = skl_dsp_core_unset_reset_state(ctx, core_mask); 17062306a36Sopenharmony_ci if (ret < 0) 17162306a36Sopenharmony_ci return ret; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci /* run core */ 17462306a36Sopenharmony_ci dev_dbg(ctx->dev, "unstall/run core: core_mask = %x\n", core_mask); 17562306a36Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 17662306a36Sopenharmony_ci SKL_ADSPCS_CSTALL_MASK(core_mask), 0); 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci if (!is_skl_dsp_core_enable(ctx, core_mask)) { 17962306a36Sopenharmony_ci skl_dsp_reset_core(ctx, core_mask); 18062306a36Sopenharmony_ci dev_err(ctx->dev, "DSP start core failed: core_mask %x\n", 18162306a36Sopenharmony_ci core_mask); 18262306a36Sopenharmony_ci ret = -EIO; 18362306a36Sopenharmony_ci } 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci return ret; 18662306a36Sopenharmony_ci} 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ciint skl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci int ret; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci /* update bits */ 19362306a36Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 19462306a36Sopenharmony_ci SKL_ADSPCS_SPA_MASK(core_mask), 19562306a36Sopenharmony_ci SKL_ADSPCS_SPA_MASK(core_mask)); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci /* poll with timeout to check if operation successful */ 19862306a36Sopenharmony_ci ret = sst_dsp_register_poll(ctx, 19962306a36Sopenharmony_ci SKL_ADSP_REG_ADSPCS, 20062306a36Sopenharmony_ci SKL_ADSPCS_CPA_MASK(core_mask), 20162306a36Sopenharmony_ci SKL_ADSPCS_CPA_MASK(core_mask), 20262306a36Sopenharmony_ci SKL_DSP_PU_TO, 20362306a36Sopenharmony_ci "Power up"); 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 20662306a36Sopenharmony_ci SKL_ADSPCS_CPA_MASK(core_mask)) != 20762306a36Sopenharmony_ci SKL_ADSPCS_CPA_MASK(core_mask)) { 20862306a36Sopenharmony_ci dev_err(ctx->dev, "DSP core power up failed: core_mask %x\n", 20962306a36Sopenharmony_ci core_mask); 21062306a36Sopenharmony_ci ret = -EIO; 21162306a36Sopenharmony_ci } 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci return ret; 21462306a36Sopenharmony_ci} 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ciint skl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci /* update bits */ 21962306a36Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 22062306a36Sopenharmony_ci SKL_ADSPCS_SPA_MASK(core_mask), 0); 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci /* poll with timeout to check if operation successful */ 22362306a36Sopenharmony_ci return sst_dsp_register_poll(ctx, 22462306a36Sopenharmony_ci SKL_ADSP_REG_ADSPCS, 22562306a36Sopenharmony_ci SKL_ADSPCS_CPA_MASK(core_mask), 22662306a36Sopenharmony_ci 0, 22762306a36Sopenharmony_ci SKL_DSP_PD_TO, 22862306a36Sopenharmony_ci "Power down"); 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ciint skl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci int ret; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci /* power up */ 23662306a36Sopenharmony_ci ret = skl_dsp_core_power_up(ctx, core_mask); 23762306a36Sopenharmony_ci if (ret < 0) { 23862306a36Sopenharmony_ci dev_err(ctx->dev, "dsp core power up failed: core_mask %x\n", 23962306a36Sopenharmony_ci core_mask); 24062306a36Sopenharmony_ci return ret; 24162306a36Sopenharmony_ci } 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci return skl_dsp_start_core(ctx, core_mask); 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ciint skl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask) 24762306a36Sopenharmony_ci{ 24862306a36Sopenharmony_ci int ret; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci ret = skl_dsp_reset_core(ctx, core_mask); 25162306a36Sopenharmony_ci if (ret < 0) { 25262306a36Sopenharmony_ci dev_err(ctx->dev, "dsp core reset failed: core_mask %x\n", 25362306a36Sopenharmony_ci core_mask); 25462306a36Sopenharmony_ci return ret; 25562306a36Sopenharmony_ci } 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci /* power down core*/ 25862306a36Sopenharmony_ci ret = skl_dsp_core_power_down(ctx, core_mask); 25962306a36Sopenharmony_ci if (ret < 0) { 26062306a36Sopenharmony_ci dev_err(ctx->dev, "dsp core power down fail mask %x: %d\n", 26162306a36Sopenharmony_ci core_mask, ret); 26262306a36Sopenharmony_ci return ret; 26362306a36Sopenharmony_ci } 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci if (is_skl_dsp_core_enable(ctx, core_mask)) { 26662306a36Sopenharmony_ci dev_err(ctx->dev, "dsp core disable fail mask %x: %d\n", 26762306a36Sopenharmony_ci core_mask, ret); 26862306a36Sopenharmony_ci ret = -EIO; 26962306a36Sopenharmony_ci } 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci return ret; 27262306a36Sopenharmony_ci} 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ciint skl_dsp_boot(struct sst_dsp *ctx) 27562306a36Sopenharmony_ci{ 27662306a36Sopenharmony_ci int ret; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci if (is_skl_dsp_core_enable(ctx, SKL_DSP_CORE0_MASK)) { 27962306a36Sopenharmony_ci ret = skl_dsp_reset_core(ctx, SKL_DSP_CORE0_MASK); 28062306a36Sopenharmony_ci if (ret < 0) { 28162306a36Sopenharmony_ci dev_err(ctx->dev, "dsp core0 reset fail: %d\n", ret); 28262306a36Sopenharmony_ci return ret; 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK); 28662306a36Sopenharmony_ci if (ret < 0) { 28762306a36Sopenharmony_ci dev_err(ctx->dev, "dsp core0 start fail: %d\n", ret); 28862306a36Sopenharmony_ci return ret; 28962306a36Sopenharmony_ci } 29062306a36Sopenharmony_ci } else { 29162306a36Sopenharmony_ci ret = skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); 29262306a36Sopenharmony_ci if (ret < 0) { 29362306a36Sopenharmony_ci dev_err(ctx->dev, "dsp core0 disable fail: %d\n", ret); 29462306a36Sopenharmony_ci return ret; 29562306a36Sopenharmony_ci } 29662306a36Sopenharmony_ci ret = skl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK); 29762306a36Sopenharmony_ci } 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci return ret; 30062306a36Sopenharmony_ci} 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ciirqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id) 30362306a36Sopenharmony_ci{ 30462306a36Sopenharmony_ci struct sst_dsp *ctx = dev_id; 30562306a36Sopenharmony_ci u32 val; 30662306a36Sopenharmony_ci irqreturn_t result = IRQ_NONE; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci spin_lock(&ctx->spinlock); 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPIS); 31162306a36Sopenharmony_ci ctx->intr_status = val; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci if (val == 0xffffffff) { 31462306a36Sopenharmony_ci spin_unlock(&ctx->spinlock); 31562306a36Sopenharmony_ci return IRQ_NONE; 31662306a36Sopenharmony_ci } 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci if (val & SKL_ADSPIS_IPC) { 31962306a36Sopenharmony_ci skl_ipc_int_disable(ctx); 32062306a36Sopenharmony_ci result = IRQ_WAKE_THREAD; 32162306a36Sopenharmony_ci } 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci if (val & SKL_ADSPIS_CL_DMA) { 32462306a36Sopenharmony_ci skl_cldma_int_disable(ctx); 32562306a36Sopenharmony_ci result = IRQ_WAKE_THREAD; 32662306a36Sopenharmony_ci } 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci spin_unlock(&ctx->spinlock); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci return result; 33162306a36Sopenharmony_ci} 33262306a36Sopenharmony_ci/* 33362306a36Sopenharmony_ci * skl_dsp_get_core/skl_dsp_put_core will be called inside DAPM context 33462306a36Sopenharmony_ci * within the dapm mutex. Hence no separate lock is used. 33562306a36Sopenharmony_ci */ 33662306a36Sopenharmony_ciint skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id) 33762306a36Sopenharmony_ci{ 33862306a36Sopenharmony_ci struct skl_dev *skl = ctx->thread_context; 33962306a36Sopenharmony_ci int ret = 0; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci if (core_id >= skl->cores.count) { 34262306a36Sopenharmony_ci dev_err(ctx->dev, "invalid core id: %d\n", core_id); 34362306a36Sopenharmony_ci return -EINVAL; 34462306a36Sopenharmony_ci } 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci skl->cores.usage_count[core_id]++; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci if (skl->cores.state[core_id] == SKL_DSP_RESET) { 34962306a36Sopenharmony_ci ret = ctx->fw_ops.set_state_D0(ctx, core_id); 35062306a36Sopenharmony_ci if (ret < 0) { 35162306a36Sopenharmony_ci dev_err(ctx->dev, "unable to get core%d\n", core_id); 35262306a36Sopenharmony_ci goto out; 35362306a36Sopenharmony_ci } 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ciout: 35762306a36Sopenharmony_ci dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n", 35862306a36Sopenharmony_ci core_id, skl->cores.state[core_id], 35962306a36Sopenharmony_ci skl->cores.usage_count[core_id]); 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci return ret; 36262306a36Sopenharmony_ci} 36362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(skl_dsp_get_core); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ciint skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id) 36662306a36Sopenharmony_ci{ 36762306a36Sopenharmony_ci struct skl_dev *skl = ctx->thread_context; 36862306a36Sopenharmony_ci int ret = 0; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci if (core_id >= skl->cores.count) { 37162306a36Sopenharmony_ci dev_err(ctx->dev, "invalid core id: %d\n", core_id); 37262306a36Sopenharmony_ci return -EINVAL; 37362306a36Sopenharmony_ci } 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci if ((--skl->cores.usage_count[core_id] == 0) && 37662306a36Sopenharmony_ci (skl->cores.state[core_id] != SKL_DSP_RESET)) { 37762306a36Sopenharmony_ci ret = ctx->fw_ops.set_state_D3(ctx, core_id); 37862306a36Sopenharmony_ci if (ret < 0) { 37962306a36Sopenharmony_ci dev_err(ctx->dev, "unable to put core %d: %d\n", 38062306a36Sopenharmony_ci core_id, ret); 38162306a36Sopenharmony_ci skl->cores.usage_count[core_id]++; 38262306a36Sopenharmony_ci } 38362306a36Sopenharmony_ci } 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n", 38662306a36Sopenharmony_ci core_id, skl->cores.state[core_id], 38762306a36Sopenharmony_ci skl->cores.usage_count[core_id]); 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci return ret; 39062306a36Sopenharmony_ci} 39162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(skl_dsp_put_core); 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ciint skl_dsp_wake(struct sst_dsp *ctx) 39462306a36Sopenharmony_ci{ 39562306a36Sopenharmony_ci return skl_dsp_get_core(ctx, SKL_DSP_CORE0_ID); 39662306a36Sopenharmony_ci} 39762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(skl_dsp_wake); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ciint skl_dsp_sleep(struct sst_dsp *ctx) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci return skl_dsp_put_core(ctx, SKL_DSP_CORE0_ID); 40262306a36Sopenharmony_ci} 40362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(skl_dsp_sleep); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_cistruct sst_dsp *skl_dsp_ctx_init(struct device *dev, 40662306a36Sopenharmony_ci struct sst_dsp_device *sst_dev, int irq) 40762306a36Sopenharmony_ci{ 40862306a36Sopenharmony_ci int ret; 40962306a36Sopenharmony_ci struct sst_dsp *sst; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci sst = devm_kzalloc(dev, sizeof(*sst), GFP_KERNEL); 41262306a36Sopenharmony_ci if (sst == NULL) 41362306a36Sopenharmony_ci return NULL; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci spin_lock_init(&sst->spinlock); 41662306a36Sopenharmony_ci mutex_init(&sst->mutex); 41762306a36Sopenharmony_ci sst->dev = dev; 41862306a36Sopenharmony_ci sst->sst_dev = sst_dev; 41962306a36Sopenharmony_ci sst->irq = irq; 42062306a36Sopenharmony_ci sst->ops = sst_dev->ops; 42162306a36Sopenharmony_ci sst->thread_context = sst_dev->thread_context; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci /* Initialise SST Audio DSP */ 42462306a36Sopenharmony_ci if (sst->ops->init) { 42562306a36Sopenharmony_ci ret = sst->ops->init(sst); 42662306a36Sopenharmony_ci if (ret < 0) 42762306a36Sopenharmony_ci return NULL; 42862306a36Sopenharmony_ci } 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci return sst; 43162306a36Sopenharmony_ci} 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ciint skl_dsp_acquire_irq(struct sst_dsp *sst) 43462306a36Sopenharmony_ci{ 43562306a36Sopenharmony_ci struct sst_dsp_device *sst_dev = sst->sst_dev; 43662306a36Sopenharmony_ci int ret; 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci /* Register the ISR */ 43962306a36Sopenharmony_ci ret = request_threaded_irq(sst->irq, sst->ops->irq_handler, 44062306a36Sopenharmony_ci sst_dev->thread, IRQF_SHARED, "AudioDSP", sst); 44162306a36Sopenharmony_ci if (ret) 44262306a36Sopenharmony_ci dev_err(sst->dev, "unable to grab threaded IRQ %d, disabling device\n", 44362306a36Sopenharmony_ci sst->irq); 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci return ret; 44662306a36Sopenharmony_ci} 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_civoid skl_dsp_free(struct sst_dsp *dsp) 44962306a36Sopenharmony_ci{ 45062306a36Sopenharmony_ci skl_ipc_int_disable(dsp); 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci free_irq(dsp->irq, dsp); 45362306a36Sopenharmony_ci skl_ipc_op_int_disable(dsp); 45462306a36Sopenharmony_ci skl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK); 45562306a36Sopenharmony_ci} 45662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(skl_dsp_free); 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_cibool is_skl_dsp_running(struct sst_dsp *ctx) 45962306a36Sopenharmony_ci{ 46062306a36Sopenharmony_ci return (ctx->sst_state == SKL_DSP_RUNNING); 46162306a36Sopenharmony_ci} 46262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(is_skl_dsp_running); 463