skl-sst-dsp.c (11038B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * skl-sst-dsp.c - SKL SST library generic function 4 * 5 * Copyright (C) 2014-15, Intel Corporation. 6 * Author:Rafal Redzimski <rafal.f.redzimski@intel.com> 7 * Jeeja KP <jeeja.kp@intel.com> 8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9 */ 10#include <sound/pcm.h> 11 12#include "../common/sst-dsp.h" 13#include "../common/sst-ipc.h" 14#include "../common/sst-dsp-priv.h" 15#include "skl.h" 16 17/* various timeout values */ 18#define SKL_DSP_PU_TO 50 19#define SKL_DSP_PD_TO 50 20#define SKL_DSP_RESET_TO 50 21 22void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state) 23{ 24 mutex_lock(&ctx->mutex); 25 ctx->sst_state = state; 26 mutex_unlock(&ctx->mutex); 27} 28 29/* 30 * Initialize core power state and usage count. To be called after 31 * successful first boot. Hence core 0 will be running and other cores 32 * will be reset 33 */ 34void skl_dsp_init_core_state(struct sst_dsp *ctx) 35{ 36 struct skl_dev *skl = ctx->thread_context; 37 int i; 38 39 skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING; 40 skl->cores.usage_count[SKL_DSP_CORE0_ID] = 1; 41 42 for (i = SKL_DSP_CORE0_ID + 1; i < skl->cores.count; i++) { 43 skl->cores.state[i] = SKL_DSP_RESET; 44 skl->cores.usage_count[i] = 0; 45 } 46} 47 48/* Get the mask for all enabled cores */ 49unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx) 50{ 51 struct skl_dev *skl = ctx->thread_context; 52 unsigned int core_mask, en_cores_mask; 53 u32 val; 54 55 core_mask = SKL_DSP_CORES_MASK(skl->cores.count); 56 57 val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS); 58 59 /* Cores having CPA bit set */ 60 en_cores_mask = (val & SKL_ADSPCS_CPA_MASK(core_mask)) >> 61 SKL_ADSPCS_CPA_SHIFT; 62 63 /* And cores having CRST bit cleared */ 64 en_cores_mask &= (~val & SKL_ADSPCS_CRST_MASK(core_mask)) >> 65 SKL_ADSPCS_CRST_SHIFT; 66 67 /* And cores having CSTALL bit cleared */ 68 en_cores_mask &= (~val & SKL_ADSPCS_CSTALL_MASK(core_mask)) >> 69 SKL_ADSPCS_CSTALL_SHIFT; 70 en_cores_mask &= core_mask; 71 72 dev_dbg(ctx->dev, "DSP enabled cores mask = %x\n", en_cores_mask); 73 74 return en_cores_mask; 75} 76 77static int 78skl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask) 79{ 80 int ret; 81 82 /* update bits */ 83 sst_dsp_shim_update_bits_unlocked(ctx, 84 SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK(core_mask), 85 SKL_ADSPCS_CRST_MASK(core_mask)); 86 87 /* poll with timeout to check if operation successful */ 88 ret = sst_dsp_register_poll(ctx, 89 SKL_ADSP_REG_ADSPCS, 90 SKL_ADSPCS_CRST_MASK(core_mask), 91 SKL_ADSPCS_CRST_MASK(core_mask), 92 SKL_DSP_RESET_TO, 93 "Set reset"); 94 if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 95 SKL_ADSPCS_CRST_MASK(core_mask)) != 96 SKL_ADSPCS_CRST_MASK(core_mask)) { 97 dev_err(ctx->dev, "Set reset state failed: core_mask %x\n", 98 core_mask); 99 ret = -EIO; 100 } 101 102 return ret; 103} 104 105int skl_dsp_core_unset_reset_state( 106 struct sst_dsp *ctx, unsigned int core_mask) 107{ 108 int ret; 109 110 dev_dbg(ctx->dev, "In %s\n", __func__); 111 112 /* update bits */ 113 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 114 SKL_ADSPCS_CRST_MASK(core_mask), 0); 115 116 /* poll with timeout to check if operation successful */ 117 ret = sst_dsp_register_poll(ctx, 118 SKL_ADSP_REG_ADSPCS, 119 SKL_ADSPCS_CRST_MASK(core_mask), 120 0, 121 SKL_DSP_RESET_TO, 122 "Unset reset"); 123 124 if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 125 SKL_ADSPCS_CRST_MASK(core_mask)) != 0) { 126 dev_err(ctx->dev, "Unset reset state failed: core_mask %x\n", 127 core_mask); 128 ret = -EIO; 129 } 130 131 return ret; 132} 133 134static bool 135is_skl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask) 136{ 137 int val; 138 bool is_enable; 139 140 val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS); 141 142 is_enable = ((val & SKL_ADSPCS_CPA_MASK(core_mask)) && 143 (val & SKL_ADSPCS_SPA_MASK(core_mask)) && 144 !(val & SKL_ADSPCS_CRST_MASK(core_mask)) && 145 !(val & SKL_ADSPCS_CSTALL_MASK(core_mask))); 146 147 dev_dbg(ctx->dev, "DSP core(s) enabled? %d : core_mask %x\n", 148 is_enable, core_mask); 149 150 return is_enable; 151} 152 153static int skl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask) 154{ 155 /* stall core */ 156 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 157 SKL_ADSPCS_CSTALL_MASK(core_mask), 158 SKL_ADSPCS_CSTALL_MASK(core_mask)); 159 160 /* set reset state */ 161 return skl_dsp_core_set_reset_state(ctx, core_mask); 162} 163 164int skl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask) 165{ 166 int ret; 167 168 /* unset reset state */ 169 ret = skl_dsp_core_unset_reset_state(ctx, core_mask); 170 if (ret < 0) 171 return ret; 172 173 /* run core */ 174 dev_dbg(ctx->dev, "unstall/run core: core_mask = %x\n", core_mask); 175 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 176 SKL_ADSPCS_CSTALL_MASK(core_mask), 0); 177 178 if (!is_skl_dsp_core_enable(ctx, core_mask)) { 179 skl_dsp_reset_core(ctx, core_mask); 180 dev_err(ctx->dev, "DSP start core failed: core_mask %x\n", 181 core_mask); 182 ret = -EIO; 183 } 184 185 return ret; 186} 187 188int skl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask) 189{ 190 int ret; 191 192 /* update bits */ 193 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 194 SKL_ADSPCS_SPA_MASK(core_mask), 195 SKL_ADSPCS_SPA_MASK(core_mask)); 196 197 /* poll with timeout to check if operation successful */ 198 ret = sst_dsp_register_poll(ctx, 199 SKL_ADSP_REG_ADSPCS, 200 SKL_ADSPCS_CPA_MASK(core_mask), 201 SKL_ADSPCS_CPA_MASK(core_mask), 202 SKL_DSP_PU_TO, 203 "Power up"); 204 205 if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 206 SKL_ADSPCS_CPA_MASK(core_mask)) != 207 SKL_ADSPCS_CPA_MASK(core_mask)) { 208 dev_err(ctx->dev, "DSP core power up failed: core_mask %x\n", 209 core_mask); 210 ret = -EIO; 211 } 212 213 return ret; 214} 215 216int skl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask) 217{ 218 /* update bits */ 219 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 220 SKL_ADSPCS_SPA_MASK(core_mask), 0); 221 222 /* poll with timeout to check if operation successful */ 223 return sst_dsp_register_poll(ctx, 224 SKL_ADSP_REG_ADSPCS, 225 SKL_ADSPCS_CPA_MASK(core_mask), 226 0, 227 SKL_DSP_PD_TO, 228 "Power down"); 229} 230 231int skl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask) 232{ 233 int ret; 234 235 /* power up */ 236 ret = skl_dsp_core_power_up(ctx, core_mask); 237 if (ret < 0) { 238 dev_err(ctx->dev, "dsp core power up failed: core_mask %x\n", 239 core_mask); 240 return ret; 241 } 242 243 return skl_dsp_start_core(ctx, core_mask); 244} 245 246int skl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask) 247{ 248 int ret; 249 250 ret = skl_dsp_reset_core(ctx, core_mask); 251 if (ret < 0) { 252 dev_err(ctx->dev, "dsp core reset failed: core_mask %x\n", 253 core_mask); 254 return ret; 255 } 256 257 /* power down core*/ 258 ret = skl_dsp_core_power_down(ctx, core_mask); 259 if (ret < 0) { 260 dev_err(ctx->dev, "dsp core power down fail mask %x: %d\n", 261 core_mask, ret); 262 return ret; 263 } 264 265 if (is_skl_dsp_core_enable(ctx, core_mask)) { 266 dev_err(ctx->dev, "dsp core disable fail mask %x: %d\n", 267 core_mask, ret); 268 ret = -EIO; 269 } 270 271 return ret; 272} 273 274int skl_dsp_boot(struct sst_dsp *ctx) 275{ 276 int ret; 277 278 if (is_skl_dsp_core_enable(ctx, SKL_DSP_CORE0_MASK)) { 279 ret = skl_dsp_reset_core(ctx, SKL_DSP_CORE0_MASK); 280 if (ret < 0) { 281 dev_err(ctx->dev, "dsp core0 reset fail: %d\n", ret); 282 return ret; 283 } 284 285 ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK); 286 if (ret < 0) { 287 dev_err(ctx->dev, "dsp core0 start fail: %d\n", ret); 288 return ret; 289 } 290 } else { 291 ret = skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); 292 if (ret < 0) { 293 dev_err(ctx->dev, "dsp core0 disable fail: %d\n", ret); 294 return ret; 295 } 296 ret = skl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK); 297 } 298 299 return ret; 300} 301 302irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id) 303{ 304 struct sst_dsp *ctx = dev_id; 305 u32 val; 306 irqreturn_t result = IRQ_NONE; 307 308 spin_lock(&ctx->spinlock); 309 310 val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPIS); 311 ctx->intr_status = val; 312 313 if (val == 0xffffffff) { 314 spin_unlock(&ctx->spinlock); 315 return IRQ_NONE; 316 } 317 318 if (val & SKL_ADSPIS_IPC) { 319 skl_ipc_int_disable(ctx); 320 result = IRQ_WAKE_THREAD; 321 } 322 323 if (val & SKL_ADSPIS_CL_DMA) { 324 skl_cldma_int_disable(ctx); 325 result = IRQ_WAKE_THREAD; 326 } 327 328 spin_unlock(&ctx->spinlock); 329 330 return result; 331} 332/* 333 * skl_dsp_get_core/skl_dsp_put_core will be called inside DAPM context 334 * within the dapm mutex. Hence no separate lock is used. 335 */ 336int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id) 337{ 338 struct skl_dev *skl = ctx->thread_context; 339 int ret = 0; 340 341 if (core_id >= skl->cores.count) { 342 dev_err(ctx->dev, "invalid core id: %d\n", core_id); 343 return -EINVAL; 344 } 345 346 skl->cores.usage_count[core_id]++; 347 348 if (skl->cores.state[core_id] == SKL_DSP_RESET) { 349 ret = ctx->fw_ops.set_state_D0(ctx, core_id); 350 if (ret < 0) { 351 dev_err(ctx->dev, "unable to get core%d\n", core_id); 352 goto out; 353 } 354 } 355 356out: 357 dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n", 358 core_id, skl->cores.state[core_id], 359 skl->cores.usage_count[core_id]); 360 361 return ret; 362} 363EXPORT_SYMBOL_GPL(skl_dsp_get_core); 364 365int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id) 366{ 367 struct skl_dev *skl = ctx->thread_context; 368 int ret = 0; 369 370 if (core_id >= skl->cores.count) { 371 dev_err(ctx->dev, "invalid core id: %d\n", core_id); 372 return -EINVAL; 373 } 374 375 if ((--skl->cores.usage_count[core_id] == 0) && 376 (skl->cores.state[core_id] != SKL_DSP_RESET)) { 377 ret = ctx->fw_ops.set_state_D3(ctx, core_id); 378 if (ret < 0) { 379 dev_err(ctx->dev, "unable to put core %d: %d\n", 380 core_id, ret); 381 skl->cores.usage_count[core_id]++; 382 } 383 } 384 385 dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n", 386 core_id, skl->cores.state[core_id], 387 skl->cores.usage_count[core_id]); 388 389 return ret; 390} 391EXPORT_SYMBOL_GPL(skl_dsp_put_core); 392 393int skl_dsp_wake(struct sst_dsp *ctx) 394{ 395 return skl_dsp_get_core(ctx, SKL_DSP_CORE0_ID); 396} 397EXPORT_SYMBOL_GPL(skl_dsp_wake); 398 399int skl_dsp_sleep(struct sst_dsp *ctx) 400{ 401 return skl_dsp_put_core(ctx, SKL_DSP_CORE0_ID); 402} 403EXPORT_SYMBOL_GPL(skl_dsp_sleep); 404 405struct sst_dsp *skl_dsp_ctx_init(struct device *dev, 406 struct sst_dsp_device *sst_dev, int irq) 407{ 408 int ret; 409 struct sst_dsp *sst; 410 411 sst = devm_kzalloc(dev, sizeof(*sst), GFP_KERNEL); 412 if (sst == NULL) 413 return NULL; 414 415 spin_lock_init(&sst->spinlock); 416 mutex_init(&sst->mutex); 417 sst->dev = dev; 418 sst->sst_dev = sst_dev; 419 sst->irq = irq; 420 sst->ops = sst_dev->ops; 421 sst->thread_context = sst_dev->thread_context; 422 423 /* Initialise SST Audio DSP */ 424 if (sst->ops->init) { 425 ret = sst->ops->init(sst); 426 if (ret < 0) 427 return NULL; 428 } 429 430 return sst; 431} 432 433int skl_dsp_acquire_irq(struct sst_dsp *sst) 434{ 435 struct sst_dsp_device *sst_dev = sst->sst_dev; 436 int ret; 437 438 /* Register the ISR */ 439 ret = request_threaded_irq(sst->irq, sst->ops->irq_handler, 440 sst_dev->thread, IRQF_SHARED, "AudioDSP", sst); 441 if (ret) 442 dev_err(sst->dev, "unable to grab threaded IRQ %d, disabling device\n", 443 sst->irq); 444 445 return ret; 446} 447 448void skl_dsp_free(struct sst_dsp *dsp) 449{ 450 skl_ipc_int_disable(dsp); 451 452 free_irq(dsp->irq, dsp); 453 skl_ipc_op_int_disable(dsp); 454 skl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK); 455} 456EXPORT_SYMBOL_GPL(skl_dsp_free); 457 458bool is_skl_dsp_running(struct sst_dsp *ctx) 459{ 460 return (ctx->sst_state == SKL_DSP_RUNNING); 461} 462EXPORT_SYMBOL_GPL(is_skl_dsp_running);