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