147d7195dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2e973e31aSSubhransu S. Prusty /*
3e973e31aSSubhransu S. Prusty * skl-sst-dsp.c - SKL SST library generic function
4e973e31aSSubhransu S. Prusty *
5e973e31aSSubhransu S. Prusty * Copyright (C) 2014-15, Intel Corporation.
6e973e31aSSubhransu S. Prusty * Author:Rafal Redzimski <rafal.f.redzimski@intel.com>
7e973e31aSSubhransu S. Prusty * Jeeja KP <jeeja.kp@intel.com>
8e973e31aSSubhransu S. Prusty * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9e973e31aSSubhransu S. Prusty */
10e973e31aSSubhransu S. Prusty #include <sound/pcm.h>
11e973e31aSSubhransu S. Prusty
12e973e31aSSubhransu S. Prusty #include "../common/sst-dsp.h"
13e973e31aSSubhransu S. Prusty #include "../common/sst-ipc.h"
14e973e31aSSubhransu S. Prusty #include "../common/sst-dsp-priv.h"
15bcc2a2dcSCezary Rojewski #include "skl.h"
16e973e31aSSubhransu S. Prusty
17e973e31aSSubhransu S. Prusty /* various timeout values */
18e973e31aSSubhransu S. Prusty #define SKL_DSP_PU_TO 50
19e973e31aSSubhransu S. Prusty #define SKL_DSP_PD_TO 50
20e973e31aSSubhransu S. Prusty #define SKL_DSP_RESET_TO 50
21e973e31aSSubhransu S. Prusty
skl_dsp_set_state_locked(struct sst_dsp * ctx,int state)22e973e31aSSubhransu S. Prusty void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state)
23e973e31aSSubhransu S. Prusty {
24e973e31aSSubhransu S. Prusty mutex_lock(&ctx->mutex);
25e973e31aSSubhransu S. Prusty ctx->sst_state = state;
26e973e31aSSubhransu S. Prusty mutex_unlock(&ctx->mutex);
27e973e31aSSubhransu S. Prusty }
28e973e31aSSubhransu S. Prusty
29052f103cSJayachandran B /*
30052f103cSJayachandran B * Initialize core power state and usage count. To be called after
31052f103cSJayachandran B * successful first boot. Hence core 0 will be running and other cores
32052f103cSJayachandran B * will be reset
33052f103cSJayachandran B */
skl_dsp_init_core_state(struct sst_dsp * ctx)34052f103cSJayachandran B void skl_dsp_init_core_state(struct sst_dsp *ctx)
35052f103cSJayachandran B {
36bcc2a2dcSCezary Rojewski struct skl_dev *skl = ctx->thread_context;
37052f103cSJayachandran B int i;
38052f103cSJayachandran B
39052f103cSJayachandran B skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING;
40052f103cSJayachandran B skl->cores.usage_count[SKL_DSP_CORE0_ID] = 1;
41052f103cSJayachandran B
42f0a550a8SGuneshwor Singh for (i = SKL_DSP_CORE0_ID + 1; i < skl->cores.count; i++) {
43052f103cSJayachandran B skl->cores.state[i] = SKL_DSP_RESET;
44052f103cSJayachandran B skl->cores.usage_count[i] = 0;
45052f103cSJayachandran B }
46052f103cSJayachandran B }
47052f103cSJayachandran B
48052f103cSJayachandran B /* Get the mask for all enabled cores */
skl_dsp_get_enabled_cores(struct sst_dsp * ctx)49052f103cSJayachandran B unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx)
50052f103cSJayachandran B {
51bcc2a2dcSCezary Rojewski struct skl_dev *skl = ctx->thread_context;
52052f103cSJayachandran B unsigned int core_mask, en_cores_mask;
53052f103cSJayachandran B u32 val;
54052f103cSJayachandran B
55052f103cSJayachandran B core_mask = SKL_DSP_CORES_MASK(skl->cores.count);
56052f103cSJayachandran B
57052f103cSJayachandran B val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS);
58052f103cSJayachandran B
59052f103cSJayachandran B /* Cores having CPA bit set */
60052f103cSJayachandran B en_cores_mask = (val & SKL_ADSPCS_CPA_MASK(core_mask)) >>
61052f103cSJayachandran B SKL_ADSPCS_CPA_SHIFT;
62052f103cSJayachandran B
63052f103cSJayachandran B /* And cores having CRST bit cleared */
64052f103cSJayachandran B en_cores_mask &= (~val & SKL_ADSPCS_CRST_MASK(core_mask)) >>
65052f103cSJayachandran B SKL_ADSPCS_CRST_SHIFT;
66052f103cSJayachandran B
67052f103cSJayachandran B /* And cores having CSTALL bit cleared */
68052f103cSJayachandran B en_cores_mask &= (~val & SKL_ADSPCS_CSTALL_MASK(core_mask)) >>
69052f103cSJayachandran B SKL_ADSPCS_CSTALL_SHIFT;
70052f103cSJayachandran B en_cores_mask &= core_mask;
71052f103cSJayachandran B
72052f103cSJayachandran B dev_dbg(ctx->dev, "DSP enabled cores mask = %x\n", en_cores_mask);
73052f103cSJayachandran B
74052f103cSJayachandran B return en_cores_mask;
75052f103cSJayachandran B }
76052f103cSJayachandran B
77052f103cSJayachandran B static int
skl_dsp_core_set_reset_state(struct sst_dsp * ctx,unsigned int core_mask)78052f103cSJayachandran B skl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
79e973e31aSSubhransu S. Prusty {
80e973e31aSSubhransu S. Prusty int ret;
81e973e31aSSubhransu S. Prusty
82e973e31aSSubhransu S. Prusty /* update bits */
83e973e31aSSubhransu S. Prusty sst_dsp_shim_update_bits_unlocked(ctx,
84052f103cSJayachandran B SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK(core_mask),
85052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask));
86e973e31aSSubhransu S. Prusty
87e973e31aSSubhransu S. Prusty /* poll with timeout to check if operation successful */
88e973e31aSSubhransu S. Prusty ret = sst_dsp_register_poll(ctx,
89e973e31aSSubhransu S. Prusty SKL_ADSP_REG_ADSPCS,
90052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask),
91052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask),
92e973e31aSSubhransu S. Prusty SKL_DSP_RESET_TO,
93e973e31aSSubhransu S. Prusty "Set reset");
94e973e31aSSubhransu S. Prusty if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
95052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask)) !=
96052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask)) {
97052f103cSJayachandran B dev_err(ctx->dev, "Set reset state failed: core_mask %x\n",
98052f103cSJayachandran B core_mask);
99e973e31aSSubhransu S. Prusty ret = -EIO;
100e973e31aSSubhransu S. Prusty }
101e973e31aSSubhransu S. Prusty
102e973e31aSSubhransu S. Prusty return ret;
103e973e31aSSubhransu S. Prusty }
104e973e31aSSubhransu S. Prusty
skl_dsp_core_unset_reset_state(struct sst_dsp * ctx,unsigned int core_mask)105052f103cSJayachandran B int skl_dsp_core_unset_reset_state(
106052f103cSJayachandran B struct sst_dsp *ctx, unsigned int core_mask)
107e973e31aSSubhransu S. Prusty {
108e973e31aSSubhransu S. Prusty int ret;
109e973e31aSSubhransu S. Prusty
110e973e31aSSubhransu S. Prusty dev_dbg(ctx->dev, "In %s\n", __func__);
111e973e31aSSubhransu S. Prusty
112e973e31aSSubhransu S. Prusty /* update bits */
113e973e31aSSubhransu S. Prusty sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
114052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask), 0);
115e973e31aSSubhransu S. Prusty
116e973e31aSSubhransu S. Prusty /* poll with timeout to check if operation successful */
117e973e31aSSubhransu S. Prusty ret = sst_dsp_register_poll(ctx,
118e973e31aSSubhransu S. Prusty SKL_ADSP_REG_ADSPCS,
119052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask),
120e973e31aSSubhransu S. Prusty 0,
121e973e31aSSubhransu S. Prusty SKL_DSP_RESET_TO,
122e973e31aSSubhransu S. Prusty "Unset reset");
123e973e31aSSubhransu S. Prusty
124e973e31aSSubhransu S. Prusty if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
125052f103cSJayachandran B SKL_ADSPCS_CRST_MASK(core_mask)) != 0) {
126052f103cSJayachandran B dev_err(ctx->dev, "Unset reset state failed: core_mask %x\n",
127052f103cSJayachandran B core_mask);
128e973e31aSSubhransu S. Prusty ret = -EIO;
129e973e31aSSubhransu S. Prusty }
130e973e31aSSubhransu S. Prusty
131e973e31aSSubhransu S. Prusty return ret;
132e973e31aSSubhransu S. Prusty }
133e973e31aSSubhransu S. Prusty
134052f103cSJayachandran B static bool
is_skl_dsp_core_enable(struct sst_dsp * ctx,unsigned int core_mask)135052f103cSJayachandran B is_skl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask)
136e973e31aSSubhransu S. Prusty {
137e973e31aSSubhransu S. Prusty int val;
138e973e31aSSubhransu S. Prusty bool is_enable;
139e973e31aSSubhransu S. Prusty
140e973e31aSSubhransu S. Prusty val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS);
141e973e31aSSubhransu S. Prusty
142052f103cSJayachandran B is_enable = ((val & SKL_ADSPCS_CPA_MASK(core_mask)) &&
143052f103cSJayachandran B (val & SKL_ADSPCS_SPA_MASK(core_mask)) &&
144052f103cSJayachandran B !(val & SKL_ADSPCS_CRST_MASK(core_mask)) &&
145052f103cSJayachandran B !(val & SKL_ADSPCS_CSTALL_MASK(core_mask)));
146e973e31aSSubhransu S. Prusty
147052f103cSJayachandran B dev_dbg(ctx->dev, "DSP core(s) enabled? %d : core_mask %x\n",
148052f103cSJayachandran B is_enable, core_mask);
149052f103cSJayachandran B
150e973e31aSSubhransu S. Prusty return is_enable;
151e973e31aSSubhransu S. Prusty }
152e973e31aSSubhransu S. Prusty
skl_dsp_reset_core(struct sst_dsp * ctx,unsigned int core_mask)153052f103cSJayachandran B static int skl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask)
154e973e31aSSubhransu S. Prusty {
155e973e31aSSubhransu S. Prusty /* stall core */
1562f74053bSJayachandran B sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
157052f103cSJayachandran B SKL_ADSPCS_CSTALL_MASK(core_mask),
158052f103cSJayachandran B SKL_ADSPCS_CSTALL_MASK(core_mask));
159e973e31aSSubhransu S. Prusty
160e973e31aSSubhransu S. Prusty /* set reset state */
161052f103cSJayachandran B return skl_dsp_core_set_reset_state(ctx, core_mask);
162e973e31aSSubhransu S. Prusty }
163e973e31aSSubhransu S. Prusty
skl_dsp_start_core(struct sst_dsp * ctx,unsigned int core_mask)164052f103cSJayachandran B int skl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask)
165e973e31aSSubhransu S. Prusty {
166e973e31aSSubhransu S. Prusty int ret;
167e973e31aSSubhransu S. Prusty
168e973e31aSSubhransu S. Prusty /* unset reset state */
169052f103cSJayachandran B ret = skl_dsp_core_unset_reset_state(ctx, core_mask);
170052f103cSJayachandran B if (ret < 0)
171e973e31aSSubhransu S. Prusty return ret;
172e973e31aSSubhransu S. Prusty
173e973e31aSSubhransu S. Prusty /* run core */
174052f103cSJayachandran B dev_dbg(ctx->dev, "unstall/run core: core_mask = %x\n", core_mask);
1752f74053bSJayachandran B sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
176052f103cSJayachandran B SKL_ADSPCS_CSTALL_MASK(core_mask), 0);
177e973e31aSSubhransu S. Prusty
178052f103cSJayachandran B if (!is_skl_dsp_core_enable(ctx, core_mask)) {
179052f103cSJayachandran B skl_dsp_reset_core(ctx, core_mask);
180052f103cSJayachandran B dev_err(ctx->dev, "DSP start core failed: core_mask %x\n",
181052f103cSJayachandran B core_mask);
182e973e31aSSubhransu S. Prusty ret = -EIO;
183e973e31aSSubhransu S. Prusty }
184e973e31aSSubhransu S. Prusty
185e973e31aSSubhransu S. Prusty return ret;
186e973e31aSSubhransu S. Prusty }
187e973e31aSSubhransu S. Prusty
skl_dsp_core_power_up(struct sst_dsp * ctx,unsigned int core_mask)188052f103cSJayachandran B int skl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask)
189e973e31aSSubhransu S. Prusty {
190e973e31aSSubhransu S. Prusty int ret;
191e973e31aSSubhransu S. Prusty
192e973e31aSSubhransu S. Prusty /* update bits */
193e973e31aSSubhransu S. Prusty sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
194052f103cSJayachandran B SKL_ADSPCS_SPA_MASK(core_mask),
195052f103cSJayachandran B SKL_ADSPCS_SPA_MASK(core_mask));
196e973e31aSSubhransu S. Prusty
197e973e31aSSubhransu S. Prusty /* poll with timeout to check if operation successful */
198e973e31aSSubhransu S. Prusty ret = sst_dsp_register_poll(ctx,
199e973e31aSSubhransu S. Prusty SKL_ADSP_REG_ADSPCS,
200052f103cSJayachandran B SKL_ADSPCS_CPA_MASK(core_mask),
201052f103cSJayachandran B SKL_ADSPCS_CPA_MASK(core_mask),
202e973e31aSSubhransu S. Prusty SKL_DSP_PU_TO,
203e973e31aSSubhransu S. Prusty "Power up");
204e973e31aSSubhransu S. Prusty
205e973e31aSSubhransu S. Prusty if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
206052f103cSJayachandran B SKL_ADSPCS_CPA_MASK(core_mask)) !=
207052f103cSJayachandran B SKL_ADSPCS_CPA_MASK(core_mask)) {
208052f103cSJayachandran B dev_err(ctx->dev, "DSP core power up failed: core_mask %x\n",
209052f103cSJayachandran B core_mask);
210e973e31aSSubhransu S. Prusty ret = -EIO;
211e973e31aSSubhransu S. Prusty }
212e973e31aSSubhransu S. Prusty
213e973e31aSSubhransu S. Prusty return ret;
214e973e31aSSubhransu S. Prusty }
215e973e31aSSubhransu S. Prusty
skl_dsp_core_power_down(struct sst_dsp * ctx,unsigned int core_mask)216052f103cSJayachandran B int skl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask)
217e973e31aSSubhransu S. Prusty {
218e973e31aSSubhransu S. Prusty /* update bits */
219e973e31aSSubhransu S. Prusty sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
220052f103cSJayachandran B SKL_ADSPCS_SPA_MASK(core_mask), 0);
221e973e31aSSubhransu S. Prusty
222e973e31aSSubhransu S. Prusty /* poll with timeout to check if operation successful */
223e973e31aSSubhransu S. Prusty return sst_dsp_register_poll(ctx,
224e973e31aSSubhransu S. Prusty SKL_ADSP_REG_ADSPCS,
225052f103cSJayachandran B SKL_ADSPCS_CPA_MASK(core_mask),
226e973e31aSSubhransu S. Prusty 0,
227e973e31aSSubhransu S. Prusty SKL_DSP_PD_TO,
228e973e31aSSubhransu S. Prusty "Power down");
229e973e31aSSubhransu S. Prusty }
230e973e31aSSubhransu S. Prusty
skl_dsp_enable_core(struct sst_dsp * ctx,unsigned int core_mask)231052f103cSJayachandran B int skl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask)
232e973e31aSSubhransu S. Prusty {
233e973e31aSSubhransu S. Prusty int ret;
234e973e31aSSubhransu S. Prusty
235e973e31aSSubhransu S. Prusty /* power up */
236052f103cSJayachandran B ret = skl_dsp_core_power_up(ctx, core_mask);
237e973e31aSSubhransu S. Prusty if (ret < 0) {
238052f103cSJayachandran B dev_err(ctx->dev, "dsp core power up failed: core_mask %x\n",
239052f103cSJayachandran B core_mask);
240e973e31aSSubhransu S. Prusty return ret;
241e973e31aSSubhransu S. Prusty }
242e973e31aSSubhransu S. Prusty
243052f103cSJayachandran B return skl_dsp_start_core(ctx, core_mask);
244e973e31aSSubhransu S. Prusty }
245e973e31aSSubhransu S. Prusty
skl_dsp_disable_core(struct sst_dsp * ctx,unsigned int core_mask)246052f103cSJayachandran B int skl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask)
247e973e31aSSubhransu S. Prusty {
248e973e31aSSubhransu S. Prusty int ret;
249e973e31aSSubhransu S. Prusty
250052f103cSJayachandran B ret = skl_dsp_reset_core(ctx, core_mask);
251e973e31aSSubhransu S. Prusty if (ret < 0) {
252052f103cSJayachandran B dev_err(ctx->dev, "dsp core reset failed: core_mask %x\n",
253052f103cSJayachandran B core_mask);
254e973e31aSSubhransu S. Prusty return ret;
255e973e31aSSubhransu S. Prusty }
256e973e31aSSubhransu S. Prusty
257e973e31aSSubhransu S. Prusty /* power down core*/
258052f103cSJayachandran B ret = skl_dsp_core_power_down(ctx, core_mask);
259e973e31aSSubhransu S. Prusty if (ret < 0) {
260052f103cSJayachandran B dev_err(ctx->dev, "dsp core power down fail mask %x: %d\n",
261052f103cSJayachandran B core_mask, ret);
262e973e31aSSubhransu S. Prusty return ret;
263e973e31aSSubhransu S. Prusty }
264e973e31aSSubhransu S. Prusty
265052f103cSJayachandran B if (is_skl_dsp_core_enable(ctx, core_mask)) {
266052f103cSJayachandran B dev_err(ctx->dev, "dsp core disable fail mask %x: %d\n",
267052f103cSJayachandran B core_mask, ret);
268e973e31aSSubhransu S. Prusty ret = -EIO;
269e973e31aSSubhransu S. Prusty }
270e973e31aSSubhransu S. Prusty
271e973e31aSSubhransu S. Prusty return ret;
272e973e31aSSubhransu S. Prusty }
273e973e31aSSubhransu S. Prusty
skl_dsp_boot(struct sst_dsp * ctx)274e973e31aSSubhransu S. Prusty int skl_dsp_boot(struct sst_dsp *ctx)
275e973e31aSSubhransu S. Prusty {
276e973e31aSSubhransu S. Prusty int ret;
277e973e31aSSubhransu S. Prusty
278052f103cSJayachandran B if (is_skl_dsp_core_enable(ctx, SKL_DSP_CORE0_MASK)) {
279052f103cSJayachandran B ret = skl_dsp_reset_core(ctx, SKL_DSP_CORE0_MASK);
280e973e31aSSubhransu S. Prusty if (ret < 0) {
281052f103cSJayachandran B dev_err(ctx->dev, "dsp core0 reset fail: %d\n", ret);
282e973e31aSSubhransu S. Prusty return ret;
283e973e31aSSubhransu S. Prusty }
284e973e31aSSubhransu S. Prusty
285052f103cSJayachandran B ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK);
286e973e31aSSubhransu S. Prusty if (ret < 0) {
287052f103cSJayachandran B dev_err(ctx->dev, "dsp core0 start fail: %d\n", ret);
288e973e31aSSubhransu S. Prusty return ret;
289e973e31aSSubhransu S. Prusty }
290e973e31aSSubhransu S. Prusty } else {
291052f103cSJayachandran B ret = skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
292e973e31aSSubhransu S. Prusty if (ret < 0) {
293052f103cSJayachandran B dev_err(ctx->dev, "dsp core0 disable fail: %d\n", ret);
294e973e31aSSubhransu S. Prusty return ret;
295e973e31aSSubhransu S. Prusty }
296052f103cSJayachandran B ret = skl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK);
297e973e31aSSubhransu S. Prusty }
298e973e31aSSubhransu S. Prusty
299e973e31aSSubhransu S. Prusty return ret;
300e973e31aSSubhransu S. Prusty }
301e973e31aSSubhransu S. Prusty
skl_dsp_sst_interrupt(int irq,void * dev_id)302e973e31aSSubhransu S. Prusty irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id)
303e973e31aSSubhransu S. Prusty {
304e973e31aSSubhransu S. Prusty struct sst_dsp *ctx = dev_id;
305e973e31aSSubhransu S. Prusty u32 val;
306e973e31aSSubhransu S. Prusty irqreturn_t result = IRQ_NONE;
307e973e31aSSubhransu S. Prusty
308e973e31aSSubhransu S. Prusty spin_lock(&ctx->spinlock);
309e973e31aSSubhransu S. Prusty
310e973e31aSSubhransu S. Prusty val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPIS);
311e973e31aSSubhransu S. Prusty ctx->intr_status = val;
312e973e31aSSubhransu S. Prusty
313def656feSJeeja KP if (val == 0xffffffff) {
314def656feSJeeja KP spin_unlock(&ctx->spinlock);
315def656feSJeeja KP return IRQ_NONE;
316def656feSJeeja KP }
317def656feSJeeja KP
318e973e31aSSubhransu S. Prusty if (val & SKL_ADSPIS_IPC) {
319e973e31aSSubhransu S. Prusty skl_ipc_int_disable(ctx);
320e973e31aSSubhransu S. Prusty result = IRQ_WAKE_THREAD;
321e973e31aSSubhransu S. Prusty }
322e973e31aSSubhransu S. Prusty
3236cb00333SSubhransu S. Prusty if (val & SKL_ADSPIS_CL_DMA) {
3246cb00333SSubhransu S. Prusty skl_cldma_int_disable(ctx);
3256cb00333SSubhransu S. Prusty result = IRQ_WAKE_THREAD;
3266cb00333SSubhransu S. Prusty }
3276cb00333SSubhransu S. Prusty
328e973e31aSSubhransu S. Prusty spin_unlock(&ctx->spinlock);
329e973e31aSSubhransu S. Prusty
330e973e31aSSubhransu S. Prusty return result;
331e973e31aSSubhransu S. Prusty }
332052f103cSJayachandran B /*
333052f103cSJayachandran B * skl_dsp_get_core/skl_dsp_put_core will be called inside DAPM context
334052f103cSJayachandran B * within the dapm mutex. Hence no separate lock is used.
335052f103cSJayachandran B */
skl_dsp_get_core(struct sst_dsp * ctx,unsigned int core_id)336052f103cSJayachandran B int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id)
337052f103cSJayachandran B {
338bcc2a2dcSCezary Rojewski struct skl_dev *skl = ctx->thread_context;
339052f103cSJayachandran B int ret = 0;
340052f103cSJayachandran B
341052f103cSJayachandran B if (core_id >= skl->cores.count) {
342052f103cSJayachandran B dev_err(ctx->dev, "invalid core id: %d\n", core_id);
343052f103cSJayachandran B return -EINVAL;
344052f103cSJayachandran B }
345052f103cSJayachandran B
3467b992c24SSubhransu S. Prusty skl->cores.usage_count[core_id]++;
3477b992c24SSubhransu S. Prusty
348052f103cSJayachandran B if (skl->cores.state[core_id] == SKL_DSP_RESET) {
349052f103cSJayachandran B ret = ctx->fw_ops.set_state_D0(ctx, core_id);
350052f103cSJayachandran B if (ret < 0) {
351052f103cSJayachandran B dev_err(ctx->dev, "unable to get core%d\n", core_id);
3521fb344a3SJeeja KP goto out;
353052f103cSJayachandran B }
354052f103cSJayachandran B }
355052f103cSJayachandran B
3561fb344a3SJeeja KP out:
357052f103cSJayachandran B dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n",
358052f103cSJayachandran B core_id, skl->cores.state[core_id],
359052f103cSJayachandran B skl->cores.usage_count[core_id]);
360052f103cSJayachandran B
361052f103cSJayachandran B return ret;
362052f103cSJayachandran B }
363052f103cSJayachandran B EXPORT_SYMBOL_GPL(skl_dsp_get_core);
364052f103cSJayachandran B
skl_dsp_put_core(struct sst_dsp * ctx,unsigned int core_id)365052f103cSJayachandran B int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id)
366052f103cSJayachandran B {
367bcc2a2dcSCezary Rojewski struct skl_dev *skl = ctx->thread_context;
368052f103cSJayachandran B int ret = 0;
369052f103cSJayachandran B
370052f103cSJayachandran B if (core_id >= skl->cores.count) {
371052f103cSJayachandran B dev_err(ctx->dev, "invalid core id: %d\n", core_id);
372052f103cSJayachandran B return -EINVAL;
373052f103cSJayachandran B }
374052f103cSJayachandran B
3751fb344a3SJeeja KP if ((--skl->cores.usage_count[core_id] == 0) &&
3761fb344a3SJeeja KP (skl->cores.state[core_id] != SKL_DSP_RESET)) {
377052f103cSJayachandran B ret = ctx->fw_ops.set_state_D3(ctx, core_id);
378052f103cSJayachandran B if (ret < 0) {
379052f103cSJayachandran B dev_err(ctx->dev, "unable to put core %d: %d\n",
380052f103cSJayachandran B core_id, ret);
381052f103cSJayachandran B skl->cores.usage_count[core_id]++;
382052f103cSJayachandran B }
383052f103cSJayachandran B }
384052f103cSJayachandran B
385052f103cSJayachandran B dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n",
386052f103cSJayachandran B core_id, skl->cores.state[core_id],
387052f103cSJayachandran B skl->cores.usage_count[core_id]);
388052f103cSJayachandran B
389052f103cSJayachandran B return ret;
390052f103cSJayachandran B }
391052f103cSJayachandran B EXPORT_SYMBOL_GPL(skl_dsp_put_core);
392e973e31aSSubhransu S. Prusty
skl_dsp_wake(struct sst_dsp * ctx)393e973e31aSSubhransu S. Prusty int skl_dsp_wake(struct sst_dsp *ctx)
394e973e31aSSubhransu S. Prusty {
395052f103cSJayachandran B return skl_dsp_get_core(ctx, SKL_DSP_CORE0_ID);
396e973e31aSSubhransu S. Prusty }
397e973e31aSSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_dsp_wake);
398e973e31aSSubhransu S. Prusty
skl_dsp_sleep(struct sst_dsp * ctx)399e973e31aSSubhransu S. Prusty int skl_dsp_sleep(struct sst_dsp *ctx)
400e973e31aSSubhransu S. Prusty {
401052f103cSJayachandran B return skl_dsp_put_core(ctx, SKL_DSP_CORE0_ID);
402e973e31aSSubhransu S. Prusty }
403e973e31aSSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_dsp_sleep);
404e973e31aSSubhransu S. Prusty
skl_dsp_ctx_init(struct device * dev,struct sst_dsp_device * sst_dev,int irq)405e973e31aSSubhransu S. Prusty struct sst_dsp *skl_dsp_ctx_init(struct device *dev,
406e973e31aSSubhransu S. Prusty struct sst_dsp_device *sst_dev, int irq)
407e973e31aSSubhransu S. Prusty {
408e973e31aSSubhransu S. Prusty int ret;
409e973e31aSSubhransu S. Prusty struct sst_dsp *sst;
410e973e31aSSubhransu S. Prusty
411e973e31aSSubhransu S. Prusty sst = devm_kzalloc(dev, sizeof(*sst), GFP_KERNEL);
412e973e31aSSubhransu S. Prusty if (sst == NULL)
413e973e31aSSubhransu S. Prusty return NULL;
414e973e31aSSubhransu S. Prusty
415e973e31aSSubhransu S. Prusty spin_lock_init(&sst->spinlock);
416e973e31aSSubhransu S. Prusty mutex_init(&sst->mutex);
417e973e31aSSubhransu S. Prusty sst->dev = dev;
418e973e31aSSubhransu S. Prusty sst->sst_dev = sst_dev;
419e973e31aSSubhransu S. Prusty sst->irq = irq;
420e973e31aSSubhransu S. Prusty sst->ops = sst_dev->ops;
421e973e31aSSubhransu S. Prusty sst->thread_context = sst_dev->thread_context;
422e973e31aSSubhransu S. Prusty
423e973e31aSSubhransu S. Prusty /* Initialise SST Audio DSP */
424e973e31aSSubhransu S. Prusty if (sst->ops->init) {
425720811f0SCezary Rojewski ret = sst->ops->init(sst);
426e973e31aSSubhransu S. Prusty if (ret < 0)
427e973e31aSSubhransu S. Prusty return NULL;
428e973e31aSSubhransu S. Prusty }
429e973e31aSSubhransu S. Prusty
4308e9d8e19SSubhransu S. Prusty return sst;
4318e9d8e19SSubhransu S. Prusty }
4328e9d8e19SSubhransu S. Prusty
skl_dsp_acquire_irq(struct sst_dsp * sst)4338e9d8e19SSubhransu S. Prusty int skl_dsp_acquire_irq(struct sst_dsp *sst)
4348e9d8e19SSubhransu S. Prusty {
4358e9d8e19SSubhransu S. Prusty struct sst_dsp_device *sst_dev = sst->sst_dev;
4368e9d8e19SSubhransu S. Prusty int ret;
4378e9d8e19SSubhransu S. Prusty
438e973e31aSSubhransu S. Prusty /* Register the ISR */
439e973e31aSSubhransu S. Prusty ret = request_threaded_irq(sst->irq, sst->ops->irq_handler,
440e973e31aSSubhransu S. Prusty sst_dev->thread, IRQF_SHARED, "AudioDSP", sst);
4418e9d8e19SSubhransu S. Prusty if (ret)
442e973e31aSSubhransu S. Prusty dev_err(sst->dev, "unable to grab threaded IRQ %d, disabling device\n",
443e973e31aSSubhransu S. Prusty sst->irq);
444e973e31aSSubhransu S. Prusty
4458e9d8e19SSubhransu S. Prusty return ret;
446e973e31aSSubhransu S. Prusty }
447e973e31aSSubhransu S. Prusty
skl_dsp_free(struct sst_dsp * dsp)448e973e31aSSubhransu S. Prusty void skl_dsp_free(struct sst_dsp *dsp)
449e973e31aSSubhransu S. Prusty {
450e973e31aSSubhransu S. Prusty skl_ipc_int_disable(dsp);
451e973e31aSSubhransu S. Prusty
452e973e31aSSubhransu S. Prusty free_irq(dsp->irq, dsp);
4533f7f8489SVinod Koul skl_ipc_op_int_disable(dsp);
454052f103cSJayachandran B skl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK);
455e973e31aSSubhransu S. Prusty }
456e973e31aSSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_dsp_free);
457e973e31aSSubhransu S. Prusty
is_skl_dsp_running(struct sst_dsp * ctx)458e973e31aSSubhransu S. Prusty bool is_skl_dsp_running(struct sst_dsp *ctx)
459e973e31aSSubhransu S. Prusty {
460e973e31aSSubhransu S. Prusty return (ctx->sst_state == SKL_DSP_RUNNING);
461e973e31aSSubhransu S. Prusty }
462e973e31aSSubhransu S. Prusty EXPORT_SYMBOL_GPL(is_skl_dsp_running);
463