1e973e31aSSubhransu S. Prusty /* 2e973e31aSSubhransu S. Prusty * skl-sst-dsp.c - SKL SST library generic function 3e973e31aSSubhransu S. Prusty * 4e973e31aSSubhransu S. Prusty * Copyright (C) 2014-15, Intel Corporation. 5e973e31aSSubhransu S. Prusty * Author:Rafal Redzimski <rafal.f.redzimski@intel.com> 6e973e31aSSubhransu S. Prusty * Jeeja KP <jeeja.kp@intel.com> 7e973e31aSSubhransu S. Prusty * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8e973e31aSSubhransu S. Prusty * 9e973e31aSSubhransu S. Prusty * This program is free software; you can redistribute it and/or modify 10e973e31aSSubhransu S. Prusty * it under the terms of the GNU General Public License as version 2, as 11e973e31aSSubhransu S. Prusty * published by the Free Software Foundation. 12e973e31aSSubhransu S. Prusty * 13e973e31aSSubhransu S. Prusty * This program is distributed in the hope that it will be useful, but 14e973e31aSSubhransu S. Prusty * WITHOUT ANY WARRANTY; without even the implied warranty of 15e973e31aSSubhransu S. Prusty * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16e973e31aSSubhransu S. Prusty * General Public License for more details. 17e973e31aSSubhransu S. Prusty */ 18e973e31aSSubhransu S. Prusty #include <sound/pcm.h> 19e973e31aSSubhransu S. Prusty 20e973e31aSSubhransu S. Prusty #include "../common/sst-dsp.h" 21e973e31aSSubhransu S. Prusty #include "../common/sst-ipc.h" 22e973e31aSSubhransu S. Prusty #include "../common/sst-dsp-priv.h" 23e973e31aSSubhransu S. Prusty #include "skl-sst-ipc.h" 24e973e31aSSubhransu S. Prusty 25e973e31aSSubhransu S. Prusty /* various timeout values */ 26e973e31aSSubhransu S. Prusty #define SKL_DSP_PU_TO 50 27e973e31aSSubhransu S. Prusty #define SKL_DSP_PD_TO 50 28e973e31aSSubhransu S. Prusty #define SKL_DSP_RESET_TO 50 29e973e31aSSubhransu S. Prusty 30e973e31aSSubhransu S. Prusty void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state) 31e973e31aSSubhransu S. Prusty { 32e973e31aSSubhransu S. Prusty mutex_lock(&ctx->mutex); 33e973e31aSSubhransu S. Prusty ctx->sst_state = state; 34e973e31aSSubhransu S. Prusty mutex_unlock(&ctx->mutex); 35e973e31aSSubhransu S. Prusty } 36e973e31aSSubhransu S. Prusty 37052f103cSJayachandran B /* 38052f103cSJayachandran B * Initialize core power state and usage count. To be called after 39052f103cSJayachandran B * successful first boot. Hence core 0 will be running and other cores 40052f103cSJayachandran B * will be reset 41052f103cSJayachandran B */ 42052f103cSJayachandran B void skl_dsp_init_core_state(struct sst_dsp *ctx) 43052f103cSJayachandran B { 44052f103cSJayachandran B struct skl_sst *skl = ctx->thread_context; 45052f103cSJayachandran B int i; 46052f103cSJayachandran B 47052f103cSJayachandran B skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING; 48052f103cSJayachandran B skl->cores.usage_count[SKL_DSP_CORE0_ID] = 1; 49052f103cSJayachandran B 50f0a550a8SGuneshwor Singh for (i = SKL_DSP_CORE0_ID + 1; i < skl->cores.count; i++) { 51052f103cSJayachandran B skl->cores.state[i] = SKL_DSP_RESET; 52052f103cSJayachandran B skl->cores.usage_count[i] = 0; 53052f103cSJayachandran B } 54052f103cSJayachandran B } 55052f103cSJayachandran B 56052f103cSJayachandran B /* Get the mask for all enabled cores */ 57052f103cSJayachandran B unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx) 58052f103cSJayachandran B { 59052f103cSJayachandran B struct skl_sst *skl = ctx->thread_context; 60052f103cSJayachandran B unsigned int core_mask, en_cores_mask; 61052f103cSJayachandran B u32 val; 62052f103cSJayachandran B 63052f103cSJayachandran B core_mask = SKL_DSP_CORES_MASK(skl->cores.count); 64052f103cSJayachandran B 65052f103cSJayachandran B val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS); 66052f103cSJayachandran B 67052f103cSJayachandran B /* Cores having CPA bit set */ 68052f103cSJayachandran B en_cores_mask = (val & SKL_ADSPCS_CPA_MASK(core_mask)) >> 69052f103cSJayachandran B SKL_ADSPCS_CPA_SHIFT; 70052f103cSJayachandran B 71052f103cSJayachandran B /* And cores having CRST bit cleared */ 72052f103cSJayachandran B en_cores_mask &= (~val & SKL_ADSPCS_CRST_MASK(core_mask)) >> 73052f103cSJayachandran B SKL_ADSPCS_CRST_SHIFT; 74052f103cSJayachandran B 75052f103cSJayachandran B /* And cores having CSTALL bit cleared */ 76052f103cSJayachandran B en_cores_mask &= (~val & SKL_ADSPCS_CSTALL_MASK(core_mask)) >> 77052f103cSJayachandran B SKL_ADSPCS_CSTALL_SHIFT; 78052f103cSJayachandran B en_cores_mask &= core_mask; 79052f103cSJayachandran B 80052f103cSJayachandran B dev_dbg(ctx->dev, "DSP enabled cores mask = %x\n", en_cores_mask); 81052f103cSJayachandran B 82052f103cSJayachandran B return en_cores_mask; 83052f103cSJayachandran B } 84052f103cSJayachandran B 85052f103cSJayachandran B static int 86052f103cSJayachandran B skl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask) 87e973e31aSSubhransu S. Prusty { 88e973e31aSSubhransu S. Prusty int ret; 89e973e31aSSubhransu S. Prusty 90e973e31aSSubhransu S. Prusty /* update bits */ 91e973e31aSSubhransu S. Prusty sst_dsp_shim_update_bits_unlocked(ctx, 92052f103cSJayachandran B SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK(core_mask), 93052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask)); 94e973e31aSSubhransu S. Prusty 95e973e31aSSubhransu S. Prusty /* poll with timeout to check if operation successful */ 96e973e31aSSubhransu S. Prusty ret = sst_dsp_register_poll(ctx, 97e973e31aSSubhransu S. Prusty SKL_ADSP_REG_ADSPCS, 98052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask), 99052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask), 100e973e31aSSubhransu S. Prusty SKL_DSP_RESET_TO, 101e973e31aSSubhransu S. Prusty "Set reset"); 102e973e31aSSubhransu S. Prusty if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 103052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask)) != 104052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask)) { 105052f103cSJayachandran B dev_err(ctx->dev, "Set reset state failed: core_mask %x\n", 106052f103cSJayachandran B core_mask); 107e973e31aSSubhransu S. Prusty ret = -EIO; 108e973e31aSSubhransu S. Prusty } 109e973e31aSSubhransu S. Prusty 110e973e31aSSubhransu S. Prusty return ret; 111e973e31aSSubhransu S. Prusty } 112e973e31aSSubhransu S. Prusty 113052f103cSJayachandran B int skl_dsp_core_unset_reset_state( 114052f103cSJayachandran B struct sst_dsp *ctx, unsigned int core_mask) 115e973e31aSSubhransu S. Prusty { 116e973e31aSSubhransu S. Prusty int ret; 117e973e31aSSubhransu S. Prusty 118e973e31aSSubhransu S. Prusty dev_dbg(ctx->dev, "In %s\n", __func__); 119e973e31aSSubhransu S. Prusty 120e973e31aSSubhransu S. Prusty /* update bits */ 121e973e31aSSubhransu S. Prusty sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 122052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask), 0); 123e973e31aSSubhransu S. Prusty 124e973e31aSSubhransu S. Prusty /* poll with timeout to check if operation successful */ 125e973e31aSSubhransu S. Prusty ret = sst_dsp_register_poll(ctx, 126e973e31aSSubhransu S. Prusty SKL_ADSP_REG_ADSPCS, 127052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask), 128e973e31aSSubhransu S. Prusty 0, 129e973e31aSSubhransu S. Prusty SKL_DSP_RESET_TO, 130e973e31aSSubhransu S. Prusty "Unset reset"); 131e973e31aSSubhransu S. Prusty 132e973e31aSSubhransu S. Prusty if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 133052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask)) != 0) { 134052f103cSJayachandran B dev_err(ctx->dev, "Unset reset state failed: core_mask %x\n", 135052f103cSJayachandran B core_mask); 136e973e31aSSubhransu S. Prusty ret = -EIO; 137e973e31aSSubhransu S. Prusty } 138e973e31aSSubhransu S. Prusty 139e973e31aSSubhransu S. Prusty return ret; 140e973e31aSSubhransu S. Prusty } 141e973e31aSSubhransu S. Prusty 142052f103cSJayachandran B static bool 143052f103cSJayachandran B is_skl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask) 144e973e31aSSubhransu S. Prusty { 145e973e31aSSubhransu S. Prusty int val; 146e973e31aSSubhransu S. Prusty bool is_enable; 147e973e31aSSubhransu S. Prusty 148e973e31aSSubhransu S. Prusty val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS); 149e973e31aSSubhransu S. Prusty 150052f103cSJayachandran B is_enable = ((val & SKL_ADSPCS_CPA_MASK(core_mask)) && 151052f103cSJayachandran B (val & SKL_ADSPCS_SPA_MASK(core_mask)) && 152052f103cSJayachandran B !(val & SKL_ADSPCS_CRST_MASK(core_mask)) && 153052f103cSJayachandran B !(val & SKL_ADSPCS_CSTALL_MASK(core_mask))); 154e973e31aSSubhransu S. Prusty 155052f103cSJayachandran B dev_dbg(ctx->dev, "DSP core(s) enabled? %d : core_mask %x\n", 156052f103cSJayachandran B is_enable, core_mask); 157052f103cSJayachandran B 158e973e31aSSubhransu S. Prusty return is_enable; 159e973e31aSSubhransu S. Prusty } 160e973e31aSSubhransu S. Prusty 161052f103cSJayachandran B static int skl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask) 162e973e31aSSubhransu S. Prusty { 163e973e31aSSubhransu S. Prusty /* stall core */ 1642f74053bSJayachandran B sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 165052f103cSJayachandran B SKL_ADSPCS_CSTALL_MASK(core_mask), 166052f103cSJayachandran B SKL_ADSPCS_CSTALL_MASK(core_mask)); 167e973e31aSSubhransu S. Prusty 168e973e31aSSubhransu S. Prusty /* set reset state */ 169052f103cSJayachandran B return skl_dsp_core_set_reset_state(ctx, core_mask); 170e973e31aSSubhransu S. Prusty } 171e973e31aSSubhransu S. Prusty 172052f103cSJayachandran B int skl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask) 173e973e31aSSubhransu S. Prusty { 174e973e31aSSubhransu S. Prusty int ret; 175e973e31aSSubhransu S. Prusty 176e973e31aSSubhransu S. Prusty /* unset reset state */ 177052f103cSJayachandran B ret = skl_dsp_core_unset_reset_state(ctx, core_mask); 178052f103cSJayachandran B if (ret < 0) 179e973e31aSSubhransu S. Prusty return ret; 180e973e31aSSubhransu S. Prusty 181e973e31aSSubhransu S. Prusty /* run core */ 182052f103cSJayachandran B dev_dbg(ctx->dev, "unstall/run core: core_mask = %x\n", core_mask); 1832f74053bSJayachandran B sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 184052f103cSJayachandran B SKL_ADSPCS_CSTALL_MASK(core_mask), 0); 185e973e31aSSubhransu S. Prusty 186052f103cSJayachandran B if (!is_skl_dsp_core_enable(ctx, core_mask)) { 187052f103cSJayachandran B skl_dsp_reset_core(ctx, core_mask); 188052f103cSJayachandran B dev_err(ctx->dev, "DSP start core failed: core_mask %x\n", 189052f103cSJayachandran B core_mask); 190e973e31aSSubhransu S. Prusty ret = -EIO; 191e973e31aSSubhransu S. Prusty } 192e973e31aSSubhransu S. Prusty 193e973e31aSSubhransu S. Prusty return ret; 194e973e31aSSubhransu S. Prusty } 195e973e31aSSubhransu S. Prusty 196052f103cSJayachandran B int skl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask) 197e973e31aSSubhransu S. Prusty { 198e973e31aSSubhransu S. Prusty int ret; 199e973e31aSSubhransu S. Prusty 200e973e31aSSubhransu S. Prusty /* update bits */ 201e973e31aSSubhransu S. Prusty sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 202052f103cSJayachandran B SKL_ADSPCS_SPA_MASK(core_mask), 203052f103cSJayachandran B SKL_ADSPCS_SPA_MASK(core_mask)); 204e973e31aSSubhransu S. Prusty 205e973e31aSSubhransu S. Prusty /* poll with timeout to check if operation successful */ 206e973e31aSSubhransu S. Prusty ret = sst_dsp_register_poll(ctx, 207e973e31aSSubhransu S. Prusty SKL_ADSP_REG_ADSPCS, 208052f103cSJayachandran B SKL_ADSPCS_CPA_MASK(core_mask), 209052f103cSJayachandran B SKL_ADSPCS_CPA_MASK(core_mask), 210e973e31aSSubhransu S. Prusty SKL_DSP_PU_TO, 211e973e31aSSubhransu S. Prusty "Power up"); 212e973e31aSSubhransu S. Prusty 213e973e31aSSubhransu S. Prusty if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 214052f103cSJayachandran B SKL_ADSPCS_CPA_MASK(core_mask)) != 215052f103cSJayachandran B SKL_ADSPCS_CPA_MASK(core_mask)) { 216052f103cSJayachandran B dev_err(ctx->dev, "DSP core power up failed: core_mask %x\n", 217052f103cSJayachandran B core_mask); 218e973e31aSSubhransu S. Prusty ret = -EIO; 219e973e31aSSubhransu S. Prusty } 220e973e31aSSubhransu S. Prusty 221e973e31aSSubhransu S. Prusty return ret; 222e973e31aSSubhransu S. Prusty } 223e973e31aSSubhransu S. Prusty 224052f103cSJayachandran B int skl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask) 225e973e31aSSubhransu S. Prusty { 226e973e31aSSubhransu S. Prusty /* update bits */ 227e973e31aSSubhransu S. Prusty sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 228052f103cSJayachandran B SKL_ADSPCS_SPA_MASK(core_mask), 0); 229e973e31aSSubhransu S. Prusty 230e973e31aSSubhransu S. Prusty /* poll with timeout to check if operation successful */ 231e973e31aSSubhransu S. Prusty return sst_dsp_register_poll(ctx, 232e973e31aSSubhransu S. Prusty SKL_ADSP_REG_ADSPCS, 233052f103cSJayachandran B SKL_ADSPCS_CPA_MASK(core_mask), 234e973e31aSSubhransu S. Prusty 0, 235e973e31aSSubhransu S. Prusty SKL_DSP_PD_TO, 236e973e31aSSubhransu S. Prusty "Power down"); 237e973e31aSSubhransu S. Prusty } 238e973e31aSSubhransu S. Prusty 239052f103cSJayachandran B int skl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask) 240e973e31aSSubhransu S. Prusty { 241e973e31aSSubhransu S. Prusty int ret; 242e973e31aSSubhransu S. Prusty 243e973e31aSSubhransu S. Prusty /* power up */ 244052f103cSJayachandran B ret = skl_dsp_core_power_up(ctx, core_mask); 245e973e31aSSubhransu S. Prusty if (ret < 0) { 246052f103cSJayachandran B dev_err(ctx->dev, "dsp core power up failed: core_mask %x\n", 247052f103cSJayachandran B core_mask); 248e973e31aSSubhransu S. Prusty return ret; 249e973e31aSSubhransu S. Prusty } 250e973e31aSSubhransu S. Prusty 251052f103cSJayachandran B return skl_dsp_start_core(ctx, core_mask); 252e973e31aSSubhransu S. Prusty } 253e973e31aSSubhransu S. Prusty 254052f103cSJayachandran B int skl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask) 255e973e31aSSubhransu S. Prusty { 256e973e31aSSubhransu S. Prusty int ret; 257e973e31aSSubhransu S. Prusty 258052f103cSJayachandran B ret = skl_dsp_reset_core(ctx, core_mask); 259e973e31aSSubhransu S. Prusty if (ret < 0) { 260052f103cSJayachandran B dev_err(ctx->dev, "dsp core reset failed: core_mask %x\n", 261052f103cSJayachandran B core_mask); 262e973e31aSSubhransu S. Prusty return ret; 263e973e31aSSubhransu S. Prusty } 264e973e31aSSubhransu S. Prusty 265e973e31aSSubhransu S. Prusty /* power down core*/ 266052f103cSJayachandran B ret = skl_dsp_core_power_down(ctx, core_mask); 267e973e31aSSubhransu S. Prusty if (ret < 0) { 268052f103cSJayachandran B dev_err(ctx->dev, "dsp core power down fail mask %x: %d\n", 269052f103cSJayachandran B core_mask, ret); 270e973e31aSSubhransu S. Prusty return ret; 271e973e31aSSubhransu S. Prusty } 272e973e31aSSubhransu S. Prusty 273052f103cSJayachandran B if (is_skl_dsp_core_enable(ctx, core_mask)) { 274052f103cSJayachandran B dev_err(ctx->dev, "dsp core disable fail mask %x: %d\n", 275052f103cSJayachandran B core_mask, ret); 276e973e31aSSubhransu S. Prusty ret = -EIO; 277e973e31aSSubhransu S. Prusty } 278e973e31aSSubhransu S. Prusty 279e973e31aSSubhransu S. Prusty return ret; 280e973e31aSSubhransu S. Prusty } 281e973e31aSSubhransu S. Prusty 282e973e31aSSubhransu S. Prusty int skl_dsp_boot(struct sst_dsp *ctx) 283e973e31aSSubhransu S. Prusty { 284e973e31aSSubhransu S. Prusty int ret; 285e973e31aSSubhransu S. Prusty 286052f103cSJayachandran B if (is_skl_dsp_core_enable(ctx, SKL_DSP_CORE0_MASK)) { 287052f103cSJayachandran B ret = skl_dsp_reset_core(ctx, SKL_DSP_CORE0_MASK); 288e973e31aSSubhransu S. Prusty if (ret < 0) { 289052f103cSJayachandran B dev_err(ctx->dev, "dsp core0 reset fail: %d\n", ret); 290e973e31aSSubhransu S. Prusty return ret; 291e973e31aSSubhransu S. Prusty } 292e973e31aSSubhransu S. Prusty 293052f103cSJayachandran B ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK); 294e973e31aSSubhransu S. Prusty if (ret < 0) { 295052f103cSJayachandran B dev_err(ctx->dev, "dsp core0 start fail: %d\n", ret); 296e973e31aSSubhransu S. Prusty return ret; 297e973e31aSSubhransu S. Prusty } 298e973e31aSSubhransu S. Prusty } else { 299052f103cSJayachandran B ret = skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); 300e973e31aSSubhransu S. Prusty if (ret < 0) { 301052f103cSJayachandran B dev_err(ctx->dev, "dsp core0 disable fail: %d\n", ret); 302e973e31aSSubhransu S. Prusty return ret; 303e973e31aSSubhransu S. Prusty } 304052f103cSJayachandran B ret = skl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK); 305e973e31aSSubhransu S. Prusty } 306e973e31aSSubhransu S. Prusty 307e973e31aSSubhransu S. Prusty return ret; 308e973e31aSSubhransu S. Prusty } 309e973e31aSSubhransu S. Prusty 310e973e31aSSubhransu S. Prusty irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id) 311e973e31aSSubhransu S. Prusty { 312e973e31aSSubhransu S. Prusty struct sst_dsp *ctx = dev_id; 313e973e31aSSubhransu S. Prusty u32 val; 314e973e31aSSubhransu S. Prusty irqreturn_t result = IRQ_NONE; 315e973e31aSSubhransu S. Prusty 316e973e31aSSubhransu S. Prusty spin_lock(&ctx->spinlock); 317e973e31aSSubhransu S. Prusty 318e973e31aSSubhransu S. Prusty val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPIS); 319e973e31aSSubhransu S. Prusty ctx->intr_status = val; 320e973e31aSSubhransu S. Prusty 321def656feSJeeja KP if (val == 0xffffffff) { 322def656feSJeeja KP spin_unlock(&ctx->spinlock); 323def656feSJeeja KP return IRQ_NONE; 324def656feSJeeja KP } 325def656feSJeeja KP 326e973e31aSSubhransu S. Prusty if (val & SKL_ADSPIS_IPC) { 327e973e31aSSubhransu S. Prusty skl_ipc_int_disable(ctx); 328e973e31aSSubhransu S. Prusty result = IRQ_WAKE_THREAD; 329e973e31aSSubhransu S. Prusty } 330e973e31aSSubhransu S. Prusty 3316cb00333SSubhransu S. Prusty if (val & SKL_ADSPIS_CL_DMA) { 3326cb00333SSubhransu S. Prusty skl_cldma_int_disable(ctx); 3336cb00333SSubhransu S. Prusty result = IRQ_WAKE_THREAD; 3346cb00333SSubhransu S. Prusty } 3356cb00333SSubhransu S. Prusty 336e973e31aSSubhransu S. Prusty spin_unlock(&ctx->spinlock); 337e973e31aSSubhransu S. Prusty 338e973e31aSSubhransu S. Prusty return result; 339e973e31aSSubhransu S. Prusty } 340052f103cSJayachandran B /* 341052f103cSJayachandran B * skl_dsp_get_core/skl_dsp_put_core will be called inside DAPM context 342052f103cSJayachandran B * within the dapm mutex. Hence no separate lock is used. 343052f103cSJayachandran B */ 344052f103cSJayachandran B int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id) 345052f103cSJayachandran B { 346052f103cSJayachandran B struct skl_sst *skl = ctx->thread_context; 347052f103cSJayachandran B int ret = 0; 348052f103cSJayachandran B 349052f103cSJayachandran B if (core_id >= skl->cores.count) { 350052f103cSJayachandran B dev_err(ctx->dev, "invalid core id: %d\n", core_id); 351052f103cSJayachandran B return -EINVAL; 352052f103cSJayachandran B } 353052f103cSJayachandran B 354052f103cSJayachandran B if (skl->cores.state[core_id] == SKL_DSP_RESET) { 355052f103cSJayachandran B ret = ctx->fw_ops.set_state_D0(ctx, core_id); 356052f103cSJayachandran B if (ret < 0) { 357052f103cSJayachandran B dev_err(ctx->dev, "unable to get core%d\n", core_id); 3581fb344a3SJeeja KP goto out; 359052f103cSJayachandran B } 360052f103cSJayachandran B } 361052f103cSJayachandran B 362052f103cSJayachandran B skl->cores.usage_count[core_id]++; 363052f103cSJayachandran B 3641fb344a3SJeeja KP out: 365052f103cSJayachandran B dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n", 366052f103cSJayachandran B core_id, skl->cores.state[core_id], 367052f103cSJayachandran B skl->cores.usage_count[core_id]); 368052f103cSJayachandran B 369052f103cSJayachandran B return ret; 370052f103cSJayachandran B } 371052f103cSJayachandran B EXPORT_SYMBOL_GPL(skl_dsp_get_core); 372052f103cSJayachandran B 373052f103cSJayachandran B int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id) 374052f103cSJayachandran B { 375052f103cSJayachandran B struct skl_sst *skl = ctx->thread_context; 376052f103cSJayachandran B int ret = 0; 377052f103cSJayachandran B 378052f103cSJayachandran B if (core_id >= skl->cores.count) { 379052f103cSJayachandran B dev_err(ctx->dev, "invalid core id: %d\n", core_id); 380052f103cSJayachandran B return -EINVAL; 381052f103cSJayachandran B } 382052f103cSJayachandran B 3831fb344a3SJeeja KP if ((--skl->cores.usage_count[core_id] == 0) && 3841fb344a3SJeeja KP (skl->cores.state[core_id] != SKL_DSP_RESET)) { 385052f103cSJayachandran B ret = ctx->fw_ops.set_state_D3(ctx, core_id); 386052f103cSJayachandran B if (ret < 0) { 387052f103cSJayachandran B dev_err(ctx->dev, "unable to put core %d: %d\n", 388052f103cSJayachandran B core_id, ret); 389052f103cSJayachandran B skl->cores.usage_count[core_id]++; 390052f103cSJayachandran B } 391052f103cSJayachandran B } 392052f103cSJayachandran B 393052f103cSJayachandran B dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n", 394052f103cSJayachandran B core_id, skl->cores.state[core_id], 395052f103cSJayachandran B skl->cores.usage_count[core_id]); 396052f103cSJayachandran B 397052f103cSJayachandran B return ret; 398052f103cSJayachandran B } 399052f103cSJayachandran B EXPORT_SYMBOL_GPL(skl_dsp_put_core); 400e973e31aSSubhransu S. Prusty 401e973e31aSSubhransu S. Prusty int skl_dsp_wake(struct sst_dsp *ctx) 402e973e31aSSubhransu S. Prusty { 403052f103cSJayachandran B return skl_dsp_get_core(ctx, SKL_DSP_CORE0_ID); 404e973e31aSSubhransu S. Prusty } 405e973e31aSSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_dsp_wake); 406e973e31aSSubhransu S. Prusty 407e973e31aSSubhransu S. Prusty int skl_dsp_sleep(struct sst_dsp *ctx) 408e973e31aSSubhransu S. Prusty { 409052f103cSJayachandran B return skl_dsp_put_core(ctx, SKL_DSP_CORE0_ID); 410e973e31aSSubhransu S. Prusty } 411e973e31aSSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_dsp_sleep); 412e973e31aSSubhransu S. Prusty 413e973e31aSSubhransu S. Prusty struct sst_dsp *skl_dsp_ctx_init(struct device *dev, 414e973e31aSSubhransu S. Prusty struct sst_dsp_device *sst_dev, int irq) 415e973e31aSSubhransu S. Prusty { 416e973e31aSSubhransu S. Prusty int ret; 417e973e31aSSubhransu S. Prusty struct sst_dsp *sst; 418e973e31aSSubhransu S. Prusty 419e973e31aSSubhransu S. Prusty sst = devm_kzalloc(dev, sizeof(*sst), GFP_KERNEL); 420e973e31aSSubhransu S. Prusty if (sst == NULL) 421e973e31aSSubhransu S. Prusty return NULL; 422e973e31aSSubhransu S. Prusty 423e973e31aSSubhransu S. Prusty spin_lock_init(&sst->spinlock); 424e973e31aSSubhransu S. Prusty mutex_init(&sst->mutex); 425e973e31aSSubhransu S. Prusty sst->dev = dev; 426e973e31aSSubhransu S. Prusty sst->sst_dev = sst_dev; 427e973e31aSSubhransu S. Prusty sst->irq = irq; 428e973e31aSSubhransu S. Prusty sst->ops = sst_dev->ops; 429e973e31aSSubhransu S. Prusty sst->thread_context = sst_dev->thread_context; 430e973e31aSSubhransu S. Prusty 431e973e31aSSubhransu S. Prusty /* Initialise SST Audio DSP */ 432e973e31aSSubhransu S. Prusty if (sst->ops->init) { 433e973e31aSSubhransu S. Prusty ret = sst->ops->init(sst, NULL); 434e973e31aSSubhransu S. Prusty if (ret < 0) 435e973e31aSSubhransu S. Prusty return NULL; 436e973e31aSSubhransu S. Prusty } 437e973e31aSSubhransu 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); 441e973e31aSSubhransu 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 return NULL; 445e973e31aSSubhransu S. Prusty } 446e973e31aSSubhransu S. Prusty 447e973e31aSSubhransu S. Prusty return sst; 448e973e31aSSubhransu S. Prusty } 449e973e31aSSubhransu S. Prusty 450e973e31aSSubhransu S. Prusty void skl_dsp_free(struct sst_dsp *dsp) 451e973e31aSSubhransu S. Prusty { 452e973e31aSSubhransu S. Prusty skl_ipc_int_disable(dsp); 453e973e31aSSubhransu S. Prusty 454e973e31aSSubhransu S. Prusty free_irq(dsp->irq, dsp); 4553f7f8489SVinod Koul skl_ipc_op_int_disable(dsp); 456052f103cSJayachandran B skl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK); 457e973e31aSSubhransu S. Prusty } 458e973e31aSSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_dsp_free); 459e973e31aSSubhransu S. Prusty 460e973e31aSSubhransu S. Prusty bool is_skl_dsp_running(struct sst_dsp *ctx) 461e973e31aSSubhransu S. Prusty { 462e973e31aSSubhransu S. Prusty return (ctx->sst_state == SKL_DSP_RUNNING); 463e973e31aSSubhransu S. Prusty } 464e973e31aSSubhransu S. Prusty EXPORT_SYMBOL_GPL(is_skl_dsp_running); 465