1 /* 2 * skl-sst-dsp.c - SKL SST library generic function 3 * 4 * Copyright (C) 2014-15, Intel Corporation. 5 * Author:Rafal Redzimski <rafal.f.redzimski@intel.com> 6 * Jeeja KP <jeeja.kp@intel.com> 7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as version 2, as 11 * published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 */ 18 #include <sound/pcm.h> 19 20 #include "../common/sst-dsp.h" 21 #include "../common/sst-ipc.h" 22 #include "../common/sst-dsp-priv.h" 23 #include "skl-sst-ipc.h" 24 25 /* various timeout values */ 26 #define SKL_DSP_PU_TO 50 27 #define SKL_DSP_PD_TO 50 28 #define SKL_DSP_RESET_TO 50 29 30 void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state) 31 { 32 mutex_lock(&ctx->mutex); 33 ctx->sst_state = state; 34 mutex_unlock(&ctx->mutex); 35 } 36 37 static int skl_dsp_core_set_reset_state(struct sst_dsp *ctx) 38 { 39 int ret; 40 41 /* update bits */ 42 sst_dsp_shim_update_bits_unlocked(ctx, 43 SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK, 44 SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)); 45 46 /* poll with timeout to check if operation successful */ 47 ret = sst_dsp_register_poll(ctx, 48 SKL_ADSP_REG_ADSPCS, 49 SKL_ADSPCS_CRST_MASK, 50 SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK), 51 SKL_DSP_RESET_TO, 52 "Set reset"); 53 if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 54 SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) != 55 SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) { 56 dev_err(ctx->dev, "Set reset state failed\n"); 57 ret = -EIO; 58 } 59 60 return ret; 61 } 62 63 static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx) 64 { 65 int ret; 66 67 dev_dbg(ctx->dev, "In %s\n", __func__); 68 69 /* update bits */ 70 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 71 SKL_ADSPCS_CRST_MASK, 0); 72 73 /* poll with timeout to check if operation successful */ 74 ret = sst_dsp_register_poll(ctx, 75 SKL_ADSP_REG_ADSPCS, 76 SKL_ADSPCS_CRST_MASK, 77 0, 78 SKL_DSP_RESET_TO, 79 "Unset reset"); 80 81 if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 82 SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) != 0) { 83 dev_err(ctx->dev, "Unset reset state failed\n"); 84 ret = -EIO; 85 } 86 87 return ret; 88 } 89 90 static bool is_skl_dsp_core_enable(struct sst_dsp *ctx) 91 { 92 int val; 93 bool is_enable; 94 95 val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS); 96 97 is_enable = ((val & SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) && 98 (val & SKL_ADSPCS_SPA(SKL_DSP_CORES_MASK)) && 99 !(val & SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) && 100 !(val & SKL_ADSPCS_CSTALL(SKL_DSP_CORES_MASK))); 101 102 dev_dbg(ctx->dev, "DSP core is enabled=%d\n", is_enable); 103 return is_enable; 104 } 105 106 static int skl_dsp_reset_core(struct sst_dsp *ctx) 107 { 108 /* stall core */ 109 sst_dsp_shim_write_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 110 sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 111 SKL_ADSPCS_CSTALL(SKL_DSP_CORES_MASK)); 112 113 /* set reset state */ 114 return skl_dsp_core_set_reset_state(ctx); 115 } 116 117 static int skl_dsp_start_core(struct sst_dsp *ctx) 118 { 119 int ret; 120 121 /* unset reset state */ 122 ret = skl_dsp_core_unset_reset_state(ctx); 123 if (ret < 0) { 124 dev_dbg(ctx->dev, "dsp unset reset fails\n"); 125 return ret; 126 } 127 128 /* run core */ 129 dev_dbg(ctx->dev, "run core...\n"); 130 sst_dsp_shim_write_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 131 sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 132 ~SKL_ADSPCS_CSTALL(SKL_DSP_CORES_MASK)); 133 134 if (!is_skl_dsp_core_enable(ctx)) { 135 skl_dsp_reset_core(ctx); 136 dev_err(ctx->dev, "DSP core enable failed\n"); 137 ret = -EIO; 138 } 139 140 return ret; 141 } 142 143 static int skl_dsp_core_power_up(struct sst_dsp *ctx) 144 { 145 int ret; 146 147 /* update bits */ 148 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 149 SKL_ADSPCS_SPA_MASK, SKL_ADSPCS_SPA(SKL_DSP_CORES_MASK)); 150 151 /* poll with timeout to check if operation successful */ 152 ret = sst_dsp_register_poll(ctx, 153 SKL_ADSP_REG_ADSPCS, 154 SKL_ADSPCS_CPA_MASK, 155 SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK), 156 SKL_DSP_PU_TO, 157 "Power up"); 158 159 if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 160 SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) != 161 SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) { 162 dev_err(ctx->dev, "DSP core power up failed\n"); 163 ret = -EIO; 164 } 165 166 return ret; 167 } 168 169 static int skl_dsp_core_power_down(struct sst_dsp *ctx) 170 { 171 /* update bits */ 172 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 173 SKL_ADSPCS_SPA_MASK, 0); 174 175 /* poll with timeout to check if operation successful */ 176 return sst_dsp_register_poll(ctx, 177 SKL_ADSP_REG_ADSPCS, 178 SKL_ADSPCS_CPA_MASK, 179 0, 180 SKL_DSP_PD_TO, 181 "Power down"); 182 } 183 184 static int skl_dsp_enable_core(struct sst_dsp *ctx) 185 { 186 int ret; 187 188 /* power up */ 189 ret = skl_dsp_core_power_up(ctx); 190 if (ret < 0) { 191 dev_dbg(ctx->dev, "dsp core power up failed\n"); 192 return ret; 193 } 194 195 return skl_dsp_start_core(ctx); 196 } 197 198 int skl_dsp_disable_core(struct sst_dsp *ctx) 199 { 200 int ret; 201 202 ret = skl_dsp_reset_core(ctx); 203 if (ret < 0) { 204 dev_err(ctx->dev, "dsp core reset failed\n"); 205 return ret; 206 } 207 208 /* power down core*/ 209 ret = skl_dsp_core_power_down(ctx); 210 if (ret < 0) { 211 dev_err(ctx->dev, "dsp core power down failed\n"); 212 return ret; 213 } 214 215 if (is_skl_dsp_core_enable(ctx)) { 216 dev_err(ctx->dev, "DSP core disable failed\n"); 217 ret = -EIO; 218 } 219 220 return ret; 221 } 222 223 int skl_dsp_boot(struct sst_dsp *ctx) 224 { 225 int ret; 226 227 if (is_skl_dsp_core_enable(ctx)) { 228 dev_dbg(ctx->dev, "dsp core is already enabled, so reset the dap core\n"); 229 ret = skl_dsp_reset_core(ctx); 230 if (ret < 0) { 231 dev_err(ctx->dev, "dsp reset failed\n"); 232 return ret; 233 } 234 235 ret = skl_dsp_start_core(ctx); 236 if (ret < 0) { 237 dev_err(ctx->dev, "dsp start failed\n"); 238 return ret; 239 } 240 } else { 241 dev_dbg(ctx->dev, "disable and enable to make sure DSP is invalid state\n"); 242 ret = skl_dsp_disable_core(ctx); 243 244 if (ret < 0) { 245 dev_err(ctx->dev, "dsp disable core failes\n"); 246 return ret; 247 } 248 ret = skl_dsp_enable_core(ctx); 249 } 250 251 return ret; 252 } 253 254 irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id) 255 { 256 struct sst_dsp *ctx = dev_id; 257 u32 val; 258 irqreturn_t result = IRQ_NONE; 259 260 spin_lock(&ctx->spinlock); 261 262 val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPIS); 263 ctx->intr_status = val; 264 265 if (val == 0xffffffff) { 266 spin_unlock(&ctx->spinlock); 267 return IRQ_NONE; 268 } 269 270 if (val & SKL_ADSPIS_IPC) { 271 skl_ipc_int_disable(ctx); 272 result = IRQ_WAKE_THREAD; 273 } 274 275 if (val & SKL_ADSPIS_CL_DMA) { 276 skl_cldma_int_disable(ctx); 277 result = IRQ_WAKE_THREAD; 278 } 279 280 spin_unlock(&ctx->spinlock); 281 282 return result; 283 } 284 285 int skl_dsp_wake(struct sst_dsp *ctx) 286 { 287 return ctx->fw_ops.set_state_D0(ctx); 288 } 289 EXPORT_SYMBOL_GPL(skl_dsp_wake); 290 291 int skl_dsp_sleep(struct sst_dsp *ctx) 292 { 293 return ctx->fw_ops.set_state_D3(ctx); 294 } 295 EXPORT_SYMBOL_GPL(skl_dsp_sleep); 296 297 struct sst_dsp *skl_dsp_ctx_init(struct device *dev, 298 struct sst_dsp_device *sst_dev, int irq) 299 { 300 int ret; 301 struct sst_dsp *sst; 302 303 sst = devm_kzalloc(dev, sizeof(*sst), GFP_KERNEL); 304 if (sst == NULL) 305 return NULL; 306 307 spin_lock_init(&sst->spinlock); 308 mutex_init(&sst->mutex); 309 sst->dev = dev; 310 sst->sst_dev = sst_dev; 311 sst->irq = irq; 312 sst->ops = sst_dev->ops; 313 sst->thread_context = sst_dev->thread_context; 314 315 /* Initialise SST Audio DSP */ 316 if (sst->ops->init) { 317 ret = sst->ops->init(sst, NULL); 318 if (ret < 0) 319 return NULL; 320 } 321 322 /* Register the ISR */ 323 ret = request_threaded_irq(sst->irq, sst->ops->irq_handler, 324 sst_dev->thread, IRQF_SHARED, "AudioDSP", sst); 325 if (ret) { 326 dev_err(sst->dev, "unable to grab threaded IRQ %d, disabling device\n", 327 sst->irq); 328 return NULL; 329 } 330 331 return sst; 332 } 333 334 void skl_dsp_free(struct sst_dsp *dsp) 335 { 336 skl_ipc_int_disable(dsp); 337 338 free_irq(dsp->irq, dsp); 339 skl_dsp_disable_core(dsp); 340 } 341 EXPORT_SYMBOL_GPL(skl_dsp_free); 342 343 bool is_skl_dsp_running(struct sst_dsp *ctx) 344 { 345 return (ctx->sst_state == SKL_DSP_RUNNING); 346 } 347 EXPORT_SYMBOL_GPL(is_skl_dsp_running); 348