root/sound/soc/intel/skylake/skl-sst-dsp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. skl_dsp_set_state_locked
  2. skl_dsp_init_core_state
  3. skl_dsp_get_enabled_cores
  4. skl_dsp_core_set_reset_state
  5. skl_dsp_core_unset_reset_state
  6. is_skl_dsp_core_enable
  7. skl_dsp_reset_core
  8. skl_dsp_start_core
  9. skl_dsp_core_power_up
  10. skl_dsp_core_power_down
  11. skl_dsp_enable_core
  12. skl_dsp_disable_core
  13. skl_dsp_boot
  14. skl_dsp_sst_interrupt
  15. skl_dsp_get_core
  16. skl_dsp_put_core
  17. skl_dsp_wake
  18. skl_dsp_sleep
  19. skl_dsp_ctx_init
  20. skl_dsp_acquire_irq
  21. skl_dsp_free
  22. is_skl_dsp_running

   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 
  22 void 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  */
  34 void 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 */
  49 unsigned 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 
  77 static int
  78 skl_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 
 105 int 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 
 134 static bool
 135 is_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 
 153 static 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 
 164 int 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 
 188 int 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 
 216 int 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 
 231 int 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 
 246 int 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 
 274 int 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 
 302 irqreturn_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  */
 336 int 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 
 356 out:
 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 }
 363 EXPORT_SYMBOL_GPL(skl_dsp_get_core);
 364 
 365 int 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 }
 391 EXPORT_SYMBOL_GPL(skl_dsp_put_core);
 392 
 393 int skl_dsp_wake(struct sst_dsp *ctx)
 394 {
 395         return skl_dsp_get_core(ctx, SKL_DSP_CORE0_ID);
 396 }
 397 EXPORT_SYMBOL_GPL(skl_dsp_wake);
 398 
 399 int skl_dsp_sleep(struct sst_dsp *ctx)
 400 {
 401         return skl_dsp_put_core(ctx, SKL_DSP_CORE0_ID);
 402 }
 403 EXPORT_SYMBOL_GPL(skl_dsp_sleep);
 404 
 405 struct 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, NULL);
 426                 if (ret < 0)
 427                         return NULL;
 428         }
 429 
 430         return sst;
 431 }
 432 
 433 int 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 
 448 void 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 }
 456 EXPORT_SYMBOL_GPL(skl_dsp_free);
 457 
 458 bool is_skl_dsp_running(struct sst_dsp *ctx)
 459 {
 460         return (ctx->sst_state == SKL_DSP_RUNNING);
 461 }
 462 EXPORT_SYMBOL_GPL(is_skl_dsp_running);

/* [<][>][^][v][top][bottom][index][help] */