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

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

DEFINITIONS

This source file includes following definitions.
  1. cnl_dsp_core_set_reset_state
  2. cnl_dsp_core_unset_reset_state
  3. is_cnl_dsp_core_enable
  4. cnl_dsp_reset_core
  5. cnl_dsp_start_core
  6. cnl_dsp_core_power_up
  7. cnl_dsp_core_power_down
  8. cnl_dsp_enable_core
  9. cnl_dsp_disable_core
  10. cnl_dsp_sst_interrupt
  11. cnl_dsp_free
  12. cnl_ipc_int_enable
  13. cnl_ipc_int_disable
  14. cnl_ipc_op_int_enable
  15. cnl_ipc_op_int_disable
  16. cnl_ipc_int_status
  17. cnl_ipc_free

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * cnl-sst-dsp.c - CNL SST library generic function
   4  *
   5  * Copyright (C) 2016-17, Intel Corporation.
   6  * Author: Guneshwor Singh <guneshwor.o.singh@intel.com>
   7  *
   8  * Modified from:
   9  *      SKL SST library generic function
  10  *      Copyright (C) 2014-15, Intel Corporation.
  11  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  12  *
  13  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  14  */
  15 #include <linux/device.h>
  16 #include "../common/sst-dsp.h"
  17 #include "../common/sst-ipc.h"
  18 #include "../common/sst-dsp-priv.h"
  19 #include "cnl-sst-dsp.h"
  20 
  21 /* various timeout values */
  22 #define CNL_DSP_PU_TO           50
  23 #define CNL_DSP_PD_TO           50
  24 #define CNL_DSP_RESET_TO        50
  25 
  26 static int
  27 cnl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
  28 {
  29         /* update bits */
  30         sst_dsp_shim_update_bits_unlocked(ctx,
  31                         CNL_ADSP_REG_ADSPCS, CNL_ADSPCS_CRST(core_mask),
  32                         CNL_ADSPCS_CRST(core_mask));
  33 
  34         /* poll with timeout to check if operation successful */
  35         return sst_dsp_register_poll(ctx,
  36                         CNL_ADSP_REG_ADSPCS,
  37                         CNL_ADSPCS_CRST(core_mask),
  38                         CNL_ADSPCS_CRST(core_mask),
  39                         CNL_DSP_RESET_TO,
  40                         "Set reset");
  41 }
  42 
  43 static int
  44 cnl_dsp_core_unset_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
  45 {
  46         /* update bits */
  47         sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
  48                                         CNL_ADSPCS_CRST(core_mask), 0);
  49 
  50         /* poll with timeout to check if operation successful */
  51         return sst_dsp_register_poll(ctx,
  52                         CNL_ADSP_REG_ADSPCS,
  53                         CNL_ADSPCS_CRST(core_mask),
  54                         0,
  55                         CNL_DSP_RESET_TO,
  56                         "Unset reset");
  57 }
  58 
  59 static bool is_cnl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask)
  60 {
  61         int val;
  62         bool is_enable;
  63 
  64         val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPCS);
  65 
  66         is_enable = (val & CNL_ADSPCS_CPA(core_mask)) &&
  67                         (val & CNL_ADSPCS_SPA(core_mask)) &&
  68                         !(val & CNL_ADSPCS_CRST(core_mask)) &&
  69                         !(val & CNL_ADSPCS_CSTALL(core_mask));
  70 
  71         dev_dbg(ctx->dev, "DSP core(s) enabled? %d: core_mask %#x\n",
  72                 is_enable, core_mask);
  73 
  74         return is_enable;
  75 }
  76 
  77 static int cnl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask)
  78 {
  79         /* stall core */
  80         sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
  81                         CNL_ADSPCS_CSTALL(core_mask),
  82                         CNL_ADSPCS_CSTALL(core_mask));
  83 
  84         /* set reset state */
  85         return cnl_dsp_core_set_reset_state(ctx, core_mask);
  86 }
  87 
  88 static int cnl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask)
  89 {
  90         int ret;
  91 
  92         /* unset reset state */
  93         ret = cnl_dsp_core_unset_reset_state(ctx, core_mask);
  94         if (ret < 0)
  95                 return ret;
  96 
  97         /* run core */
  98         sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
  99                                 CNL_ADSPCS_CSTALL(core_mask), 0);
 100 
 101         if (!is_cnl_dsp_core_enable(ctx, core_mask)) {
 102                 cnl_dsp_reset_core(ctx, core_mask);
 103                 dev_err(ctx->dev, "DSP core mask %#x enable failed\n",
 104                         core_mask);
 105                 ret = -EIO;
 106         }
 107 
 108         return ret;
 109 }
 110 
 111 static int cnl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask)
 112 {
 113         /* update bits */
 114         sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
 115                                           CNL_ADSPCS_SPA(core_mask),
 116                                           CNL_ADSPCS_SPA(core_mask));
 117 
 118         /* poll with timeout to check if operation successful */
 119         return sst_dsp_register_poll(ctx, CNL_ADSP_REG_ADSPCS,
 120                                     CNL_ADSPCS_CPA(core_mask),
 121                                     CNL_ADSPCS_CPA(core_mask),
 122                                     CNL_DSP_PU_TO,
 123                                     "Power up");
 124 }
 125 
 126 static int cnl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask)
 127 {
 128         /* update bits */
 129         sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
 130                                         CNL_ADSPCS_SPA(core_mask), 0);
 131 
 132         /* poll with timeout to check if operation successful */
 133         return sst_dsp_register_poll(ctx,
 134                         CNL_ADSP_REG_ADSPCS,
 135                         CNL_ADSPCS_CPA(core_mask),
 136                         0,
 137                         CNL_DSP_PD_TO,
 138                         "Power down");
 139 }
 140 
 141 int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask)
 142 {
 143         int ret;
 144 
 145         /* power up */
 146         ret = cnl_dsp_core_power_up(ctx, core_mask);
 147         if (ret < 0) {
 148                 dev_dbg(ctx->dev, "DSP core mask %#x power up failed",
 149                         core_mask);
 150                 return ret;
 151         }
 152 
 153         return cnl_dsp_start_core(ctx, core_mask);
 154 }
 155 
 156 int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask)
 157 {
 158         int ret;
 159 
 160         ret = cnl_dsp_reset_core(ctx, core_mask);
 161         if (ret < 0) {
 162                 dev_err(ctx->dev, "DSP core mask %#x reset failed\n",
 163                         core_mask);
 164                 return ret;
 165         }
 166 
 167         /* power down core*/
 168         ret = cnl_dsp_core_power_down(ctx, core_mask);
 169         if (ret < 0) {
 170                 dev_err(ctx->dev, "DSP core mask %#x power down failed\n",
 171                         core_mask);
 172                 return ret;
 173         }
 174 
 175         if (is_cnl_dsp_core_enable(ctx, core_mask)) {
 176                 dev_err(ctx->dev, "DSP core mask %#x disable failed\n",
 177                         core_mask);
 178                 ret = -EIO;
 179         }
 180 
 181         return ret;
 182 }
 183 
 184 irqreturn_t cnl_dsp_sst_interrupt(int irq, void *dev_id)
 185 {
 186         struct sst_dsp *ctx = dev_id;
 187         u32 val;
 188         irqreturn_t ret = IRQ_NONE;
 189 
 190         spin_lock(&ctx->spinlock);
 191 
 192         val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS);
 193         ctx->intr_status = val;
 194 
 195         if (val == 0xffffffff) {
 196                 spin_unlock(&ctx->spinlock);
 197                 return IRQ_NONE;
 198         }
 199 
 200         if (val & CNL_ADSPIS_IPC) {
 201                 cnl_ipc_int_disable(ctx);
 202                 ret = IRQ_WAKE_THREAD;
 203         }
 204 
 205         spin_unlock(&ctx->spinlock);
 206 
 207         return ret;
 208 }
 209 
 210 void cnl_dsp_free(struct sst_dsp *dsp)
 211 {
 212         cnl_ipc_int_disable(dsp);
 213 
 214         free_irq(dsp->irq, dsp);
 215         cnl_ipc_op_int_disable(dsp);
 216         cnl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK);
 217 }
 218 EXPORT_SYMBOL_GPL(cnl_dsp_free);
 219 
 220 void cnl_ipc_int_enable(struct sst_dsp *ctx)
 221 {
 222         sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_ADSPIC,
 223                                  CNL_ADSPIC_IPC, CNL_ADSPIC_IPC);
 224 }
 225 
 226 void cnl_ipc_int_disable(struct sst_dsp *ctx)
 227 {
 228         sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPIC,
 229                                           CNL_ADSPIC_IPC, 0);
 230 }
 231 
 232 void cnl_ipc_op_int_enable(struct sst_dsp *ctx)
 233 {
 234         /* enable IPC DONE interrupt */
 235         sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
 236                                  CNL_ADSP_REG_HIPCCTL_DONE,
 237                                  CNL_ADSP_REG_HIPCCTL_DONE);
 238 
 239         /* enable IPC BUSY interrupt */
 240         sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
 241                                  CNL_ADSP_REG_HIPCCTL_BUSY,
 242                                  CNL_ADSP_REG_HIPCCTL_BUSY);
 243 }
 244 
 245 void cnl_ipc_op_int_disable(struct sst_dsp *ctx)
 246 {
 247         /* disable IPC DONE interrupt */
 248         sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
 249                                  CNL_ADSP_REG_HIPCCTL_DONE, 0);
 250 
 251         /* disable IPC BUSY interrupt */
 252         sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
 253                                  CNL_ADSP_REG_HIPCCTL_BUSY, 0);
 254 }
 255 
 256 bool cnl_ipc_int_status(struct sst_dsp *ctx)
 257 {
 258         return sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS) &
 259                                                         CNL_ADSPIS_IPC;
 260 }
 261 
 262 void cnl_ipc_free(struct sst_generic_ipc *ipc)
 263 {
 264         cnl_ipc_op_int_disable(ipc->dsp);
 265         sst_ipc_fini(ipc);
 266 }

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