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
skl_dsp_set_state_locked(struct sst_dsp * ctx,int state)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 */
skl_dsp_init_core_state(struct sst_dsp * ctx)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 */
skl_dsp_get_enabled_cores(struct sst_dsp * ctx)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
skl_dsp_core_set_reset_state(struct sst_dsp * ctx,unsigned int core_mask)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
skl_dsp_core_unset_reset_state(struct sst_dsp * ctx,unsigned int core_mask)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
is_skl_dsp_core_enable(struct sst_dsp * ctx,unsigned int core_mask)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
skl_dsp_reset_core(struct sst_dsp * ctx,unsigned int core_mask)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
skl_dsp_start_core(struct sst_dsp * ctx,unsigned int core_mask)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
skl_dsp_core_power_up(struct sst_dsp * ctx,unsigned int core_mask)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
skl_dsp_core_power_down(struct sst_dsp * ctx,unsigned int core_mask)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
skl_dsp_enable_core(struct sst_dsp * ctx,unsigned int core_mask)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
skl_dsp_disable_core(struct sst_dsp * ctx,unsigned int core_mask)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
skl_dsp_boot(struct sst_dsp * ctx)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
skl_dsp_sst_interrupt(int irq,void * dev_id)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 */
skl_dsp_get_core(struct sst_dsp * ctx,unsigned int core_id)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
skl_dsp_put_core(struct sst_dsp * ctx,unsigned int core_id)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
skl_dsp_wake(struct sst_dsp * ctx)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
skl_dsp_sleep(struct sst_dsp * ctx)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
skl_dsp_ctx_init(struct device * dev,struct sst_dsp_device * sst_dev,int irq)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
skl_dsp_acquire_irq(struct sst_dsp * sst)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
skl_dsp_free(struct sst_dsp * dsp)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
is_skl_dsp_running(struct sst_dsp * ctx)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);
463