147d7195dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2e973e31aSSubhransu S. Prusty /* 3e973e31aSSubhransu S. Prusty * skl-sst-dsp.c - SKL SST library generic function 4e973e31aSSubhransu S. Prusty * 5e973e31aSSubhransu S. Prusty * Copyright (C) 2014-15, Intel Corporation. 6e973e31aSSubhransu S. Prusty * Author:Rafal Redzimski <rafal.f.redzimski@intel.com> 7e973e31aSSubhransu S. Prusty * Jeeja KP <jeeja.kp@intel.com> 8e973e31aSSubhransu S. Prusty * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9e973e31aSSubhransu S. Prusty */ 10e973e31aSSubhransu S. Prusty #include <sound/pcm.h> 11e973e31aSSubhransu S. Prusty 12e973e31aSSubhransu S. Prusty #include "../common/sst-dsp.h" 13e973e31aSSubhransu S. Prusty #include "../common/sst-ipc.h" 14e973e31aSSubhransu S. Prusty #include "../common/sst-dsp-priv.h" 15e973e31aSSubhransu S. Prusty #include "skl-sst-ipc.h" 16e973e31aSSubhransu S. Prusty 17e973e31aSSubhransu S. Prusty /* various timeout values */ 18e973e31aSSubhransu S. Prusty #define SKL_DSP_PU_TO 50 19e973e31aSSubhransu S. Prusty #define SKL_DSP_PD_TO 50 20e973e31aSSubhransu S. Prusty #define SKL_DSP_RESET_TO 50 21e973e31aSSubhransu S. Prusty 22e973e31aSSubhransu S. Prusty void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state) 23e973e31aSSubhransu S. Prusty { 24e973e31aSSubhransu S. Prusty mutex_lock(&ctx->mutex); 25e973e31aSSubhransu S. Prusty ctx->sst_state = state; 26e973e31aSSubhransu S. Prusty mutex_unlock(&ctx->mutex); 27e973e31aSSubhransu S. Prusty } 28e973e31aSSubhransu S. Prusty 29052f103cSJayachandran B /* 30052f103cSJayachandran B * Initialize core power state and usage count. To be called after 31052f103cSJayachandran B * successful first boot. Hence core 0 will be running and other cores 32052f103cSJayachandran B * will be reset 33052f103cSJayachandran B */ 34052f103cSJayachandran B void skl_dsp_init_core_state(struct sst_dsp *ctx) 35052f103cSJayachandran B { 36052f103cSJayachandran B struct skl_sst *skl = ctx->thread_context; 37052f103cSJayachandran B int i; 38052f103cSJayachandran B 39052f103cSJayachandran B skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING; 40052f103cSJayachandran B skl->cores.usage_count[SKL_DSP_CORE0_ID] = 1; 41052f103cSJayachandran B 42f0a550a8SGuneshwor Singh for (i = SKL_DSP_CORE0_ID + 1; i < skl->cores.count; i++) { 43052f103cSJayachandran B skl->cores.state[i] = SKL_DSP_RESET; 44052f103cSJayachandran B skl->cores.usage_count[i] = 0; 45052f103cSJayachandran B } 46052f103cSJayachandran B } 47052f103cSJayachandran B 48052f103cSJayachandran B /* Get the mask for all enabled cores */ 49052f103cSJayachandran B unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx) 50052f103cSJayachandran B { 51052f103cSJayachandran B struct skl_sst *skl = ctx->thread_context; 52052f103cSJayachandran B unsigned int core_mask, en_cores_mask; 53052f103cSJayachandran B u32 val; 54052f103cSJayachandran B 55052f103cSJayachandran B core_mask = SKL_DSP_CORES_MASK(skl->cores.count); 56052f103cSJayachandran B 57052f103cSJayachandran B val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS); 58052f103cSJayachandran B 59052f103cSJayachandran B /* Cores having CPA bit set */ 60052f103cSJayachandran B en_cores_mask = (val & SKL_ADSPCS_CPA_MASK(core_mask)) >> 61052f103cSJayachandran B SKL_ADSPCS_CPA_SHIFT; 62052f103cSJayachandran B 63052f103cSJayachandran B /* And cores having CRST bit cleared */ 64052f103cSJayachandran B en_cores_mask &= (~val & SKL_ADSPCS_CRST_MASK(core_mask)) >> 65052f103cSJayachandran B SKL_ADSPCS_CRST_SHIFT; 66052f103cSJayachandran B 67052f103cSJayachandran B /* And cores having CSTALL bit cleared */ 68052f103cSJayachandran B en_cores_mask &= (~val & SKL_ADSPCS_CSTALL_MASK(core_mask)) >> 69052f103cSJayachandran B SKL_ADSPCS_CSTALL_SHIFT; 70052f103cSJayachandran B en_cores_mask &= core_mask; 71052f103cSJayachandran B 72052f103cSJayachandran B dev_dbg(ctx->dev, "DSP enabled cores mask = %x\n", en_cores_mask); 73052f103cSJayachandran B 74052f103cSJayachandran B return en_cores_mask; 75052f103cSJayachandran B } 76052f103cSJayachandran B 77052f103cSJayachandran B static int 78052f103cSJayachandran B skl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask) 79e973e31aSSubhransu S. Prusty { 80e973e31aSSubhransu S. Prusty int ret; 81e973e31aSSubhransu S. Prusty 82e973e31aSSubhransu S. Prusty /* update bits */ 83e973e31aSSubhransu S. Prusty sst_dsp_shim_update_bits_unlocked(ctx, 84052f103cSJayachandran B SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK(core_mask), 85052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask)); 86e973e31aSSubhransu S. Prusty 87e973e31aSSubhransu S. Prusty /* poll with timeout to check if operation successful */ 88e973e31aSSubhransu S. Prusty ret = sst_dsp_register_poll(ctx, 89e973e31aSSubhransu S. Prusty SKL_ADSP_REG_ADSPCS, 90052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask), 91052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask), 92e973e31aSSubhransu S. Prusty SKL_DSP_RESET_TO, 93e973e31aSSubhransu S. Prusty "Set reset"); 94e973e31aSSubhransu S. Prusty if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 95052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask)) != 96052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask)) { 97052f103cSJayachandran B dev_err(ctx->dev, "Set reset state failed: core_mask %x\n", 98052f103cSJayachandran B core_mask); 99e973e31aSSubhransu S. Prusty ret = -EIO; 100e973e31aSSubhransu S. Prusty } 101e973e31aSSubhransu S. Prusty 102e973e31aSSubhransu S. Prusty return ret; 103e973e31aSSubhransu S. Prusty } 104e973e31aSSubhransu S. Prusty 105052f103cSJayachandran B int skl_dsp_core_unset_reset_state( 106052f103cSJayachandran B struct sst_dsp *ctx, unsigned int core_mask) 107e973e31aSSubhransu S. Prusty { 108e973e31aSSubhransu S. Prusty int ret; 109e973e31aSSubhransu S. Prusty 110e973e31aSSubhransu S. Prusty dev_dbg(ctx->dev, "In %s\n", __func__); 111e973e31aSSubhransu S. Prusty 112e973e31aSSubhransu S. Prusty /* update bits */ 113e973e31aSSubhransu S. Prusty sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 114052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask), 0); 115e973e31aSSubhransu S. Prusty 116e973e31aSSubhransu S. Prusty /* poll with timeout to check if operation successful */ 117e973e31aSSubhransu S. Prusty ret = sst_dsp_register_poll(ctx, 118e973e31aSSubhransu S. Prusty SKL_ADSP_REG_ADSPCS, 119052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask), 120e973e31aSSubhransu S. Prusty 0, 121e973e31aSSubhransu S. Prusty SKL_DSP_RESET_TO, 122e973e31aSSubhransu S. Prusty "Unset reset"); 123e973e31aSSubhransu S. Prusty 124e973e31aSSubhransu S. Prusty if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 125052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask)) != 0) { 126052f103cSJayachandran B dev_err(ctx->dev, "Unset reset state failed: core_mask %x\n", 127052f103cSJayachandran B core_mask); 128e973e31aSSubhransu S. Prusty ret = -EIO; 129e973e31aSSubhransu S. Prusty } 130e973e31aSSubhransu S. Prusty 131e973e31aSSubhransu S. Prusty return ret; 132e973e31aSSubhransu S. Prusty } 133e973e31aSSubhransu S. Prusty 134052f103cSJayachandran B static bool 135052f103cSJayachandran B is_skl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask) 136e973e31aSSubhransu S. Prusty { 137e973e31aSSubhransu S. Prusty int val; 138e973e31aSSubhransu S. Prusty bool is_enable; 139e973e31aSSubhransu S. Prusty 140e973e31aSSubhransu S. Prusty val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS); 141e973e31aSSubhransu S. Prusty 142052f103cSJayachandran B is_enable = ((val & SKL_ADSPCS_CPA_MASK(core_mask)) && 143052f103cSJayachandran B (val & SKL_ADSPCS_SPA_MASK(core_mask)) && 144052f103cSJayachandran B !(val & SKL_ADSPCS_CRST_MASK(core_mask)) && 145052f103cSJayachandran B !(val & SKL_ADSPCS_CSTALL_MASK(core_mask))); 146e973e31aSSubhransu S. Prusty 147052f103cSJayachandran B dev_dbg(ctx->dev, "DSP core(s) enabled? %d : core_mask %x\n", 148052f103cSJayachandran B is_enable, core_mask); 149052f103cSJayachandran B 150e973e31aSSubhransu S. Prusty return is_enable; 151e973e31aSSubhransu S. Prusty } 152e973e31aSSubhransu S. Prusty 153052f103cSJayachandran B static int skl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask) 154e973e31aSSubhransu S. Prusty { 155e973e31aSSubhransu S. Prusty /* stall core */ 1562f74053bSJayachandran B sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 157052f103cSJayachandran B SKL_ADSPCS_CSTALL_MASK(core_mask), 158052f103cSJayachandran B SKL_ADSPCS_CSTALL_MASK(core_mask)); 159e973e31aSSubhransu S. Prusty 160e973e31aSSubhransu S. Prusty /* set reset state */ 161052f103cSJayachandran B return skl_dsp_core_set_reset_state(ctx, core_mask); 162e973e31aSSubhransu S. Prusty } 163e973e31aSSubhransu S. Prusty 164052f103cSJayachandran B int skl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask) 165e973e31aSSubhransu S. Prusty { 166e973e31aSSubhransu S. Prusty int ret; 167e973e31aSSubhransu S. Prusty 168e973e31aSSubhransu S. Prusty /* unset reset state */ 169052f103cSJayachandran B ret = skl_dsp_core_unset_reset_state(ctx, core_mask); 170052f103cSJayachandran B if (ret < 0) 171e973e31aSSubhransu S. Prusty return ret; 172e973e31aSSubhransu S. Prusty 173e973e31aSSubhransu S. Prusty /* run core */ 174052f103cSJayachandran B dev_dbg(ctx->dev, "unstall/run core: core_mask = %x\n", core_mask); 1752f74053bSJayachandran B sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 176052f103cSJayachandran B SKL_ADSPCS_CSTALL_MASK(core_mask), 0); 177e973e31aSSubhransu S. Prusty 178052f103cSJayachandran B if (!is_skl_dsp_core_enable(ctx, core_mask)) { 179052f103cSJayachandran B skl_dsp_reset_core(ctx, core_mask); 180052f103cSJayachandran B dev_err(ctx->dev, "DSP start core failed: core_mask %x\n", 181052f103cSJayachandran B core_mask); 182e973e31aSSubhransu S. Prusty ret = -EIO; 183e973e31aSSubhransu S. Prusty } 184e973e31aSSubhransu S. Prusty 185e973e31aSSubhransu S. Prusty return ret; 186e973e31aSSubhransu S. Prusty } 187e973e31aSSubhransu S. Prusty 188052f103cSJayachandran B int skl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask) 189e973e31aSSubhransu S. Prusty { 190e973e31aSSubhransu S. Prusty int ret; 191e973e31aSSubhransu S. Prusty 192e973e31aSSubhransu S. Prusty /* update bits */ 193e973e31aSSubhransu S. Prusty sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 194052f103cSJayachandran B SKL_ADSPCS_SPA_MASK(core_mask), 195052f103cSJayachandran B SKL_ADSPCS_SPA_MASK(core_mask)); 196e973e31aSSubhransu S. Prusty 197e973e31aSSubhransu S. Prusty /* poll with timeout to check if operation successful */ 198e973e31aSSubhransu S. Prusty ret = sst_dsp_register_poll(ctx, 199e973e31aSSubhransu S. Prusty SKL_ADSP_REG_ADSPCS, 200052f103cSJayachandran B SKL_ADSPCS_CPA_MASK(core_mask), 201052f103cSJayachandran B SKL_ADSPCS_CPA_MASK(core_mask), 202e973e31aSSubhransu S. Prusty SKL_DSP_PU_TO, 203e973e31aSSubhransu S. Prusty "Power up"); 204e973e31aSSubhransu S. Prusty 205e973e31aSSubhransu S. Prusty if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 206052f103cSJayachandran B SKL_ADSPCS_CPA_MASK(core_mask)) != 207052f103cSJayachandran B SKL_ADSPCS_CPA_MASK(core_mask)) { 208052f103cSJayachandran B dev_err(ctx->dev, "DSP core power up failed: core_mask %x\n", 209052f103cSJayachandran B core_mask); 210e973e31aSSubhransu S. Prusty ret = -EIO; 211e973e31aSSubhransu S. Prusty } 212e973e31aSSubhransu S. Prusty 213e973e31aSSubhransu S. Prusty return ret; 214e973e31aSSubhransu S. Prusty } 215e973e31aSSubhransu S. Prusty 216052f103cSJayachandran B int skl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask) 217e973e31aSSubhransu S. Prusty { 218e973e31aSSubhransu S. Prusty /* update bits */ 219e973e31aSSubhransu S. Prusty sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 220052f103cSJayachandran B SKL_ADSPCS_SPA_MASK(core_mask), 0); 221e973e31aSSubhransu S. Prusty 222e973e31aSSubhransu S. Prusty /* poll with timeout to check if operation successful */ 223e973e31aSSubhransu S. Prusty return sst_dsp_register_poll(ctx, 224e973e31aSSubhransu S. Prusty SKL_ADSP_REG_ADSPCS, 225052f103cSJayachandran B SKL_ADSPCS_CPA_MASK(core_mask), 226e973e31aSSubhransu S. Prusty 0, 227e973e31aSSubhransu S. Prusty SKL_DSP_PD_TO, 228e973e31aSSubhransu S. Prusty "Power down"); 229e973e31aSSubhransu S. Prusty } 230e973e31aSSubhransu S. Prusty 231052f103cSJayachandran B int skl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask) 232e973e31aSSubhransu S. Prusty { 233e973e31aSSubhransu S. Prusty int ret; 234e973e31aSSubhransu S. Prusty 235e973e31aSSubhransu S. Prusty /* power up */ 236052f103cSJayachandran B ret = skl_dsp_core_power_up(ctx, core_mask); 237e973e31aSSubhransu S. Prusty if (ret < 0) { 238052f103cSJayachandran B dev_err(ctx->dev, "dsp core power up failed: core_mask %x\n", 239052f103cSJayachandran B core_mask); 240e973e31aSSubhransu S. Prusty return ret; 241e973e31aSSubhransu S. Prusty } 242e973e31aSSubhransu S. Prusty 243052f103cSJayachandran B return skl_dsp_start_core(ctx, core_mask); 244e973e31aSSubhransu S. Prusty } 245e973e31aSSubhransu S. Prusty 246052f103cSJayachandran B int skl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask) 247e973e31aSSubhransu S. Prusty { 248e973e31aSSubhransu S. Prusty int ret; 249e973e31aSSubhransu S. Prusty 250052f103cSJayachandran B ret = skl_dsp_reset_core(ctx, core_mask); 251e973e31aSSubhransu S. Prusty if (ret < 0) { 252052f103cSJayachandran B dev_err(ctx->dev, "dsp core reset failed: core_mask %x\n", 253052f103cSJayachandran B core_mask); 254e973e31aSSubhransu S. Prusty return ret; 255e973e31aSSubhransu S. Prusty } 256e973e31aSSubhransu S. Prusty 257e973e31aSSubhransu S. Prusty /* power down core*/ 258052f103cSJayachandran B ret = skl_dsp_core_power_down(ctx, core_mask); 259e973e31aSSubhransu S. Prusty if (ret < 0) { 260052f103cSJayachandran B dev_err(ctx->dev, "dsp core power down fail mask %x: %d\n", 261052f103cSJayachandran B core_mask, ret); 262e973e31aSSubhransu S. Prusty return ret; 263e973e31aSSubhransu S. Prusty } 264e973e31aSSubhransu S. Prusty 265052f103cSJayachandran B if (is_skl_dsp_core_enable(ctx, core_mask)) { 266052f103cSJayachandran B dev_err(ctx->dev, "dsp core disable fail mask %x: %d\n", 267052f103cSJayachandran B core_mask, ret); 268e973e31aSSubhransu S. Prusty ret = -EIO; 269e973e31aSSubhransu S. Prusty } 270e973e31aSSubhransu S. Prusty 271e973e31aSSubhransu S. Prusty return ret; 272e973e31aSSubhransu S. Prusty } 273e973e31aSSubhransu S. Prusty 274e973e31aSSubhransu S. Prusty int skl_dsp_boot(struct sst_dsp *ctx) 275e973e31aSSubhransu S. Prusty { 276e973e31aSSubhransu S. Prusty int ret; 277e973e31aSSubhransu S. Prusty 278052f103cSJayachandran B if (is_skl_dsp_core_enable(ctx, SKL_DSP_CORE0_MASK)) { 279052f103cSJayachandran B ret = skl_dsp_reset_core(ctx, SKL_DSP_CORE0_MASK); 280e973e31aSSubhransu S. Prusty if (ret < 0) { 281052f103cSJayachandran B dev_err(ctx->dev, "dsp core0 reset fail: %d\n", ret); 282e973e31aSSubhransu S. Prusty return ret; 283e973e31aSSubhransu S. Prusty } 284e973e31aSSubhransu S. Prusty 285052f103cSJayachandran B ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK); 286e973e31aSSubhransu S. Prusty if (ret < 0) { 287052f103cSJayachandran B dev_err(ctx->dev, "dsp core0 start fail: %d\n", ret); 288e973e31aSSubhransu S. Prusty return ret; 289e973e31aSSubhransu S. Prusty } 290e973e31aSSubhransu S. Prusty } else { 291052f103cSJayachandran B ret = skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); 292e973e31aSSubhransu S. Prusty if (ret < 0) { 293052f103cSJayachandran B dev_err(ctx->dev, "dsp core0 disable fail: %d\n", ret); 294e973e31aSSubhransu S. Prusty return ret; 295e973e31aSSubhransu S. Prusty } 296052f103cSJayachandran B ret = skl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK); 297e973e31aSSubhransu S. Prusty } 298e973e31aSSubhransu S. Prusty 299e973e31aSSubhransu S. Prusty return ret; 300e973e31aSSubhransu S. Prusty } 301e973e31aSSubhransu S. Prusty 302e973e31aSSubhransu S. Prusty irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id) 303e973e31aSSubhransu S. Prusty { 304e973e31aSSubhransu S. Prusty struct sst_dsp *ctx = dev_id; 305e973e31aSSubhransu S. Prusty u32 val; 306e973e31aSSubhransu S. Prusty irqreturn_t result = IRQ_NONE; 307e973e31aSSubhransu S. Prusty 308e973e31aSSubhransu S. Prusty spin_lock(&ctx->spinlock); 309e973e31aSSubhransu S. Prusty 310e973e31aSSubhransu S. Prusty val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPIS); 311e973e31aSSubhransu S. Prusty ctx->intr_status = val; 312e973e31aSSubhransu S. Prusty 313def656feSJeeja KP if (val == 0xffffffff) { 314def656feSJeeja KP spin_unlock(&ctx->spinlock); 315def656feSJeeja KP return IRQ_NONE; 316def656feSJeeja KP } 317def656feSJeeja KP 318e973e31aSSubhransu S. Prusty if (val & SKL_ADSPIS_IPC) { 319e973e31aSSubhransu S. Prusty skl_ipc_int_disable(ctx); 320e973e31aSSubhransu S. Prusty result = IRQ_WAKE_THREAD; 321e973e31aSSubhransu S. Prusty } 322e973e31aSSubhransu S. Prusty 3236cb00333SSubhransu S. Prusty if (val & SKL_ADSPIS_CL_DMA) { 3246cb00333SSubhransu S. Prusty skl_cldma_int_disable(ctx); 3256cb00333SSubhransu S. Prusty result = IRQ_WAKE_THREAD; 3266cb00333SSubhransu S. Prusty } 3276cb00333SSubhransu S. Prusty 328e973e31aSSubhransu S. Prusty spin_unlock(&ctx->spinlock); 329e973e31aSSubhransu S. Prusty 330e973e31aSSubhransu S. Prusty return result; 331e973e31aSSubhransu S. Prusty } 332052f103cSJayachandran B /* 333052f103cSJayachandran B * skl_dsp_get_core/skl_dsp_put_core will be called inside DAPM context 334052f103cSJayachandran B * within the dapm mutex. Hence no separate lock is used. 335052f103cSJayachandran B */ 336052f103cSJayachandran B int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id) 337052f103cSJayachandran B { 338052f103cSJayachandran B struct skl_sst *skl = ctx->thread_context; 339052f103cSJayachandran B int ret = 0; 340052f103cSJayachandran B 341052f103cSJayachandran B if (core_id >= skl->cores.count) { 342052f103cSJayachandran B dev_err(ctx->dev, "invalid core id: %d\n", core_id); 343052f103cSJayachandran B return -EINVAL; 344052f103cSJayachandran B } 345052f103cSJayachandran B 3467b992c24SSubhransu S. Prusty skl->cores.usage_count[core_id]++; 3477b992c24SSubhransu S. Prusty 348052f103cSJayachandran B if (skl->cores.state[core_id] == SKL_DSP_RESET) { 349052f103cSJayachandran B ret = ctx->fw_ops.set_state_D0(ctx, core_id); 350052f103cSJayachandran B if (ret < 0) { 351052f103cSJayachandran B dev_err(ctx->dev, "unable to get core%d\n", core_id); 3521fb344a3SJeeja KP goto out; 353052f103cSJayachandran B } 354052f103cSJayachandran B } 355052f103cSJayachandran B 3561fb344a3SJeeja KP out: 357052f103cSJayachandran B dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n", 358052f103cSJayachandran B core_id, skl->cores.state[core_id], 359052f103cSJayachandran B skl->cores.usage_count[core_id]); 360052f103cSJayachandran B 361052f103cSJayachandran B return ret; 362052f103cSJayachandran B } 363052f103cSJayachandran B EXPORT_SYMBOL_GPL(skl_dsp_get_core); 364052f103cSJayachandran B 365052f103cSJayachandran B int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id) 366052f103cSJayachandran B { 367052f103cSJayachandran B struct skl_sst *skl = ctx->thread_context; 368052f103cSJayachandran B int ret = 0; 369052f103cSJayachandran B 370052f103cSJayachandran B if (core_id >= skl->cores.count) { 371052f103cSJayachandran B dev_err(ctx->dev, "invalid core id: %d\n", core_id); 372052f103cSJayachandran B return -EINVAL; 373052f103cSJayachandran B } 374052f103cSJayachandran B 3751fb344a3SJeeja KP if ((--skl->cores.usage_count[core_id] == 0) && 3761fb344a3SJeeja KP (skl->cores.state[core_id] != SKL_DSP_RESET)) { 377052f103cSJayachandran B ret = ctx->fw_ops.set_state_D3(ctx, core_id); 378052f103cSJayachandran B if (ret < 0) { 379052f103cSJayachandran B dev_err(ctx->dev, "unable to put core %d: %d\n", 380052f103cSJayachandran B core_id, ret); 381052f103cSJayachandran B skl->cores.usage_count[core_id]++; 382052f103cSJayachandran B } 383052f103cSJayachandran B } 384052f103cSJayachandran B 385052f103cSJayachandran B dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n", 386052f103cSJayachandran B core_id, skl->cores.state[core_id], 387052f103cSJayachandran B skl->cores.usage_count[core_id]); 388052f103cSJayachandran B 389052f103cSJayachandran B return ret; 390052f103cSJayachandran B } 391052f103cSJayachandran B EXPORT_SYMBOL_GPL(skl_dsp_put_core); 392e973e31aSSubhransu S. Prusty 393e973e31aSSubhransu S. Prusty int skl_dsp_wake(struct sst_dsp *ctx) 394e973e31aSSubhransu S. Prusty { 395052f103cSJayachandran B return skl_dsp_get_core(ctx, SKL_DSP_CORE0_ID); 396e973e31aSSubhransu S. Prusty } 397e973e31aSSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_dsp_wake); 398e973e31aSSubhransu S. Prusty 399e973e31aSSubhransu S. Prusty int skl_dsp_sleep(struct sst_dsp *ctx) 400e973e31aSSubhransu S. Prusty { 401052f103cSJayachandran B return skl_dsp_put_core(ctx, SKL_DSP_CORE0_ID); 402e973e31aSSubhransu S. Prusty } 403e973e31aSSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_dsp_sleep); 404e973e31aSSubhransu S. Prusty 405e973e31aSSubhransu S. Prusty struct sst_dsp *skl_dsp_ctx_init(struct device *dev, 406e973e31aSSubhransu S. Prusty struct sst_dsp_device *sst_dev, int irq) 407e973e31aSSubhransu S. Prusty { 408e973e31aSSubhransu S. Prusty int ret; 409e973e31aSSubhransu S. Prusty struct sst_dsp *sst; 410e973e31aSSubhransu S. Prusty 411e973e31aSSubhransu S. Prusty sst = devm_kzalloc(dev, sizeof(*sst), GFP_KERNEL); 412e973e31aSSubhransu S. Prusty if (sst == NULL) 413e973e31aSSubhransu S. Prusty return NULL; 414e973e31aSSubhransu S. Prusty 415e973e31aSSubhransu S. Prusty spin_lock_init(&sst->spinlock); 416e973e31aSSubhransu S. Prusty mutex_init(&sst->mutex); 417e973e31aSSubhransu S. Prusty sst->dev = dev; 418e973e31aSSubhransu S. Prusty sst->sst_dev = sst_dev; 419e973e31aSSubhransu S. Prusty sst->irq = irq; 420e973e31aSSubhransu S. Prusty sst->ops = sst_dev->ops; 421e973e31aSSubhransu S. Prusty sst->thread_context = sst_dev->thread_context; 422e973e31aSSubhransu S. Prusty 423e973e31aSSubhransu S. Prusty /* Initialise SST Audio DSP */ 424e973e31aSSubhransu S. Prusty if (sst->ops->init) { 425e973e31aSSubhransu S. Prusty ret = sst->ops->init(sst, NULL); 426e973e31aSSubhransu S. Prusty if (ret < 0) 427e973e31aSSubhransu S. Prusty return NULL; 428e973e31aSSubhransu S. Prusty } 429e973e31aSSubhransu S. Prusty 4308e9d8e19SSubhransu S. Prusty return sst; 4318e9d8e19SSubhransu S. Prusty } 4328e9d8e19SSubhransu S. Prusty 4338e9d8e19SSubhransu S. Prusty int skl_dsp_acquire_irq(struct sst_dsp *sst) 4348e9d8e19SSubhransu S. Prusty { 4358e9d8e19SSubhransu S. Prusty struct sst_dsp_device *sst_dev = sst->sst_dev; 4368e9d8e19SSubhransu S. Prusty int ret; 4378e9d8e19SSubhransu S. Prusty 438e973e31aSSubhransu S. Prusty /* Register the ISR */ 439e973e31aSSubhransu S. Prusty ret = request_threaded_irq(sst->irq, sst->ops->irq_handler, 440e973e31aSSubhransu S. Prusty sst_dev->thread, IRQF_SHARED, "AudioDSP", sst); 4418e9d8e19SSubhransu S. Prusty if (ret) 442e973e31aSSubhransu S. Prusty dev_err(sst->dev, "unable to grab threaded IRQ %d, disabling device\n", 443e973e31aSSubhransu S. Prusty sst->irq); 444e973e31aSSubhransu S. Prusty 4458e9d8e19SSubhransu S. Prusty return ret; 446e973e31aSSubhransu S. Prusty } 447e973e31aSSubhransu S. Prusty 448e973e31aSSubhransu S. Prusty void skl_dsp_free(struct sst_dsp *dsp) 449e973e31aSSubhransu S. Prusty { 450e973e31aSSubhransu S. Prusty skl_ipc_int_disable(dsp); 451e973e31aSSubhransu S. Prusty 452e973e31aSSubhransu S. Prusty free_irq(dsp->irq, dsp); 4533f7f8489SVinod Koul skl_ipc_op_int_disable(dsp); 454052f103cSJayachandran B skl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK); 455e973e31aSSubhransu S. Prusty } 456e973e31aSSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_dsp_free); 457e973e31aSSubhransu S. Prusty 458e973e31aSSubhransu S. Prusty bool is_skl_dsp_running(struct sst_dsp *ctx) 459e973e31aSSubhransu S. Prusty { 460e973e31aSSubhransu S. Prusty return (ctx->sst_state == SKL_DSP_RUNNING); 461e973e31aSSubhransu S. Prusty } 462e973e31aSSubhransu S. Prusty EXPORT_SYMBOL_GPL(is_skl_dsp_running); 463