1e973e31aSSubhransu S. Prusty /*
2e973e31aSSubhransu S. Prusty  * skl-sst-dsp.c - SKL SST library generic function
3e973e31aSSubhransu S. Prusty  *
4e973e31aSSubhransu S. Prusty  * Copyright (C) 2014-15, Intel Corporation.
5e973e31aSSubhransu S. Prusty  * Author:Rafal Redzimski <rafal.f.redzimski@intel.com>
6e973e31aSSubhransu S. Prusty  *	Jeeja KP <jeeja.kp@intel.com>
7e973e31aSSubhransu S. Prusty  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8e973e31aSSubhransu S. Prusty  *
9e973e31aSSubhransu S. Prusty  * This program is free software; you can redistribute it and/or modify
10e973e31aSSubhransu S. Prusty  * it under the terms of the GNU General Public License as version 2, as
11e973e31aSSubhransu S. Prusty  * published by the Free Software Foundation.
12e973e31aSSubhransu S. Prusty  *
13e973e31aSSubhransu S. Prusty  * This program is distributed in the hope that it will be useful, but
14e973e31aSSubhransu S. Prusty  * WITHOUT ANY WARRANTY; without even the implied warranty of
15e973e31aSSubhransu S. Prusty  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16e973e31aSSubhransu S. Prusty  * General Public License for more details.
17e973e31aSSubhransu S. Prusty  */
18e973e31aSSubhransu S. Prusty #include <sound/pcm.h>
19e973e31aSSubhransu S. Prusty 
20e973e31aSSubhransu S. Prusty #include "../common/sst-dsp.h"
21e973e31aSSubhransu S. Prusty #include "../common/sst-ipc.h"
22e973e31aSSubhransu S. Prusty #include "../common/sst-dsp-priv.h"
23e973e31aSSubhransu S. Prusty #include "skl-sst-ipc.h"
24e973e31aSSubhransu S. Prusty 
25e973e31aSSubhransu S. Prusty /* various timeout values */
26e973e31aSSubhransu S. Prusty #define SKL_DSP_PU_TO		50
27e973e31aSSubhransu S. Prusty #define SKL_DSP_PD_TO		50
28e973e31aSSubhransu S. Prusty #define SKL_DSP_RESET_TO	50
29e973e31aSSubhransu S. Prusty 
30e973e31aSSubhransu S. Prusty void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state)
31e973e31aSSubhransu S. Prusty {
32e973e31aSSubhransu S. Prusty 	mutex_lock(&ctx->mutex);
33e973e31aSSubhransu S. Prusty 	ctx->sst_state = state;
34e973e31aSSubhransu S. Prusty 	mutex_unlock(&ctx->mutex);
35e973e31aSSubhransu S. Prusty }
36e973e31aSSubhransu S. Prusty 
37052f103cSJayachandran B /*
38052f103cSJayachandran B  * Initialize core power state and usage count. To be called after
39052f103cSJayachandran B  * successful first boot. Hence core 0 will be running and other cores
40052f103cSJayachandran B  * will be reset
41052f103cSJayachandran B  */
42052f103cSJayachandran B void skl_dsp_init_core_state(struct sst_dsp *ctx)
43052f103cSJayachandran B {
44052f103cSJayachandran B 	struct skl_sst *skl = ctx->thread_context;
45052f103cSJayachandran B 	int i;
46052f103cSJayachandran B 
47052f103cSJayachandran B 	skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING;
48052f103cSJayachandran B 	skl->cores.usage_count[SKL_DSP_CORE0_ID] = 1;
49052f103cSJayachandran B 
50f0a550a8SGuneshwor Singh 	for (i = SKL_DSP_CORE0_ID + 1; i < skl->cores.count; i++) {
51052f103cSJayachandran B 		skl->cores.state[i] = SKL_DSP_RESET;
52052f103cSJayachandran B 		skl->cores.usage_count[i] = 0;
53052f103cSJayachandran B 	}
54052f103cSJayachandran B }
55052f103cSJayachandran B 
56052f103cSJayachandran B /* Get the mask for all enabled cores */
57052f103cSJayachandran B unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx)
58052f103cSJayachandran B {
59052f103cSJayachandran B 	struct skl_sst *skl = ctx->thread_context;
60052f103cSJayachandran B 	unsigned int core_mask, en_cores_mask;
61052f103cSJayachandran B 	u32 val;
62052f103cSJayachandran B 
63052f103cSJayachandran B 	core_mask = SKL_DSP_CORES_MASK(skl->cores.count);
64052f103cSJayachandran B 
65052f103cSJayachandran B 	val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS);
66052f103cSJayachandran B 
67052f103cSJayachandran B 	/* Cores having CPA bit set */
68052f103cSJayachandran B 	en_cores_mask = (val & SKL_ADSPCS_CPA_MASK(core_mask)) >>
69052f103cSJayachandran B 			SKL_ADSPCS_CPA_SHIFT;
70052f103cSJayachandran B 
71052f103cSJayachandran B 	/* And cores having CRST bit cleared */
72052f103cSJayachandran B 	en_cores_mask &= (~val & SKL_ADSPCS_CRST_MASK(core_mask)) >>
73052f103cSJayachandran B 			SKL_ADSPCS_CRST_SHIFT;
74052f103cSJayachandran B 
75052f103cSJayachandran B 	/* And cores having CSTALL bit cleared */
76052f103cSJayachandran B 	en_cores_mask &= (~val & SKL_ADSPCS_CSTALL_MASK(core_mask)) >>
77052f103cSJayachandran B 			SKL_ADSPCS_CSTALL_SHIFT;
78052f103cSJayachandran B 	en_cores_mask &= core_mask;
79052f103cSJayachandran B 
80052f103cSJayachandran B 	dev_dbg(ctx->dev, "DSP enabled cores mask = %x\n", en_cores_mask);
81052f103cSJayachandran B 
82052f103cSJayachandran B 	return en_cores_mask;
83052f103cSJayachandran B }
84052f103cSJayachandran B 
85052f103cSJayachandran B static int
86052f103cSJayachandran B skl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
87e973e31aSSubhransu S. Prusty {
88e973e31aSSubhransu S. Prusty 	int ret;
89e973e31aSSubhransu S. Prusty 
90e973e31aSSubhransu S. Prusty 	/* update bits */
91e973e31aSSubhransu S. Prusty 	sst_dsp_shim_update_bits_unlocked(ctx,
92052f103cSJayachandran B 			SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK(core_mask),
93052f103cSJayachandran B 			SKL_ADSPCS_CRST_MASK(core_mask));
94e973e31aSSubhransu S. Prusty 
95e973e31aSSubhransu S. Prusty 	/* poll with timeout to check if operation successful */
96e973e31aSSubhransu S. Prusty 	ret = sst_dsp_register_poll(ctx,
97e973e31aSSubhransu S. Prusty 			SKL_ADSP_REG_ADSPCS,
98052f103cSJayachandran B 			SKL_ADSPCS_CRST_MASK(core_mask),
99052f103cSJayachandran B 			SKL_ADSPCS_CRST_MASK(core_mask),
100e973e31aSSubhransu S. Prusty 			SKL_DSP_RESET_TO,
101e973e31aSSubhransu S. Prusty 			"Set reset");
102e973e31aSSubhransu S. Prusty 	if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
103052f103cSJayachandran B 				SKL_ADSPCS_CRST_MASK(core_mask)) !=
104052f103cSJayachandran B 				SKL_ADSPCS_CRST_MASK(core_mask)) {
105052f103cSJayachandran B 		dev_err(ctx->dev, "Set reset state failed: core_mask %x\n",
106052f103cSJayachandran B 							core_mask);
107e973e31aSSubhransu S. Prusty 		ret = -EIO;
108e973e31aSSubhransu S. Prusty 	}
109e973e31aSSubhransu S. Prusty 
110e973e31aSSubhransu S. Prusty 	return ret;
111e973e31aSSubhransu S. Prusty }
112e973e31aSSubhransu S. Prusty 
113052f103cSJayachandran B int skl_dsp_core_unset_reset_state(
114052f103cSJayachandran B 		struct sst_dsp *ctx, unsigned int core_mask)
115e973e31aSSubhransu S. Prusty {
116e973e31aSSubhransu S. Prusty 	int ret;
117e973e31aSSubhransu S. Prusty 
118e973e31aSSubhransu S. Prusty 	dev_dbg(ctx->dev, "In %s\n", __func__);
119e973e31aSSubhransu S. Prusty 
120e973e31aSSubhransu S. Prusty 	/* update bits */
121e973e31aSSubhransu S. Prusty 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
122052f103cSJayachandran B 				SKL_ADSPCS_CRST_MASK(core_mask), 0);
123e973e31aSSubhransu S. Prusty 
124e973e31aSSubhransu S. Prusty 	/* poll with timeout to check if operation successful */
125e973e31aSSubhransu S. Prusty 	ret = sst_dsp_register_poll(ctx,
126e973e31aSSubhransu S. Prusty 			SKL_ADSP_REG_ADSPCS,
127052f103cSJayachandran B 			SKL_ADSPCS_CRST_MASK(core_mask),
128e973e31aSSubhransu S. Prusty 			0,
129e973e31aSSubhransu S. Prusty 			SKL_DSP_RESET_TO,
130e973e31aSSubhransu S. Prusty 			"Unset reset");
131e973e31aSSubhransu S. Prusty 
132e973e31aSSubhransu S. Prusty 	if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
133052f103cSJayachandran B 				SKL_ADSPCS_CRST_MASK(core_mask)) != 0) {
134052f103cSJayachandran B 		dev_err(ctx->dev, "Unset reset state failed: core_mask %x\n",
135052f103cSJayachandran B 				core_mask);
136e973e31aSSubhransu S. Prusty 		ret = -EIO;
137e973e31aSSubhransu S. Prusty 	}
138e973e31aSSubhransu S. Prusty 
139e973e31aSSubhransu S. Prusty 	return ret;
140e973e31aSSubhransu S. Prusty }
141e973e31aSSubhransu S. Prusty 
142052f103cSJayachandran B static bool
143052f103cSJayachandran B is_skl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask)
144e973e31aSSubhransu S. Prusty {
145e973e31aSSubhransu S. Prusty 	int val;
146e973e31aSSubhransu S. Prusty 	bool is_enable;
147e973e31aSSubhransu S. Prusty 
148e973e31aSSubhransu S. Prusty 	val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS);
149e973e31aSSubhransu S. Prusty 
150052f103cSJayachandran B 	is_enable = ((val & SKL_ADSPCS_CPA_MASK(core_mask)) &&
151052f103cSJayachandran B 			(val & SKL_ADSPCS_SPA_MASK(core_mask)) &&
152052f103cSJayachandran B 			!(val & SKL_ADSPCS_CRST_MASK(core_mask)) &&
153052f103cSJayachandran B 			!(val & SKL_ADSPCS_CSTALL_MASK(core_mask)));
154e973e31aSSubhransu S. Prusty 
155052f103cSJayachandran B 	dev_dbg(ctx->dev, "DSP core(s) enabled? %d : core_mask %x\n",
156052f103cSJayachandran B 						is_enable, core_mask);
157052f103cSJayachandran B 
158e973e31aSSubhransu S. Prusty 	return is_enable;
159e973e31aSSubhransu S. Prusty }
160e973e31aSSubhransu S. Prusty 
161052f103cSJayachandran B static int skl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask)
162e973e31aSSubhransu S. Prusty {
163e973e31aSSubhransu S. Prusty 	/* stall core */
1642f74053bSJayachandran B 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
165052f103cSJayachandran B 			SKL_ADSPCS_CSTALL_MASK(core_mask),
166052f103cSJayachandran B 			SKL_ADSPCS_CSTALL_MASK(core_mask));
167e973e31aSSubhransu S. Prusty 
168e973e31aSSubhransu S. Prusty 	/* set reset state */
169052f103cSJayachandran B 	return skl_dsp_core_set_reset_state(ctx, core_mask);
170e973e31aSSubhransu S. Prusty }
171e973e31aSSubhransu S. Prusty 
172052f103cSJayachandran B int skl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask)
173e973e31aSSubhransu S. Prusty {
174e973e31aSSubhransu S. Prusty 	int ret;
175e973e31aSSubhransu S. Prusty 
176e973e31aSSubhransu S. Prusty 	/* unset reset state */
177052f103cSJayachandran B 	ret = skl_dsp_core_unset_reset_state(ctx, core_mask);
178052f103cSJayachandran B 	if (ret < 0)
179e973e31aSSubhransu S. Prusty 		return ret;
180e973e31aSSubhransu S. Prusty 
181e973e31aSSubhransu S. Prusty 	/* run core */
182052f103cSJayachandran B 	dev_dbg(ctx->dev, "unstall/run core: core_mask = %x\n", core_mask);
1832f74053bSJayachandran B 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
184052f103cSJayachandran B 			SKL_ADSPCS_CSTALL_MASK(core_mask), 0);
185e973e31aSSubhransu S. Prusty 
186052f103cSJayachandran B 	if (!is_skl_dsp_core_enable(ctx, core_mask)) {
187052f103cSJayachandran B 		skl_dsp_reset_core(ctx, core_mask);
188052f103cSJayachandran B 		dev_err(ctx->dev, "DSP start core failed: core_mask %x\n",
189052f103cSJayachandran B 							core_mask);
190e973e31aSSubhransu S. Prusty 		ret = -EIO;
191e973e31aSSubhransu S. Prusty 	}
192e973e31aSSubhransu S. Prusty 
193e973e31aSSubhransu S. Prusty 	return ret;
194e973e31aSSubhransu S. Prusty }
195e973e31aSSubhransu S. Prusty 
196052f103cSJayachandran B int skl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask)
197e973e31aSSubhransu S. Prusty {
198e973e31aSSubhransu S. Prusty 	int ret;
199e973e31aSSubhransu S. Prusty 
200e973e31aSSubhransu S. Prusty 	/* update bits */
201e973e31aSSubhransu S. Prusty 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
202052f103cSJayachandran B 			SKL_ADSPCS_SPA_MASK(core_mask),
203052f103cSJayachandran B 			SKL_ADSPCS_SPA_MASK(core_mask));
204e973e31aSSubhransu S. Prusty 
205e973e31aSSubhransu S. Prusty 	/* poll with timeout to check if operation successful */
206e973e31aSSubhransu S. Prusty 	ret = sst_dsp_register_poll(ctx,
207e973e31aSSubhransu S. Prusty 			SKL_ADSP_REG_ADSPCS,
208052f103cSJayachandran B 			SKL_ADSPCS_CPA_MASK(core_mask),
209052f103cSJayachandran B 			SKL_ADSPCS_CPA_MASK(core_mask),
210e973e31aSSubhransu S. Prusty 			SKL_DSP_PU_TO,
211e973e31aSSubhransu S. Prusty 			"Power up");
212e973e31aSSubhransu S. Prusty 
213e973e31aSSubhransu S. Prusty 	if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
214052f103cSJayachandran B 			SKL_ADSPCS_CPA_MASK(core_mask)) !=
215052f103cSJayachandran B 			SKL_ADSPCS_CPA_MASK(core_mask)) {
216052f103cSJayachandran B 		dev_err(ctx->dev, "DSP core power up failed: core_mask %x\n",
217052f103cSJayachandran B 				core_mask);
218e973e31aSSubhransu S. Prusty 		ret = -EIO;
219e973e31aSSubhransu S. Prusty 	}
220e973e31aSSubhransu S. Prusty 
221e973e31aSSubhransu S. Prusty 	return ret;
222e973e31aSSubhransu S. Prusty }
223e973e31aSSubhransu S. Prusty 
224052f103cSJayachandran B int skl_dsp_core_power_down(struct sst_dsp  *ctx, unsigned int core_mask)
225e973e31aSSubhransu S. Prusty {
226e973e31aSSubhransu S. Prusty 	/* update bits */
227e973e31aSSubhransu S. Prusty 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
228052f103cSJayachandran B 				SKL_ADSPCS_SPA_MASK(core_mask), 0);
229e973e31aSSubhransu S. Prusty 
230e973e31aSSubhransu S. Prusty 	/* poll with timeout to check if operation successful */
231e973e31aSSubhransu S. Prusty 	return sst_dsp_register_poll(ctx,
232e973e31aSSubhransu S. Prusty 			SKL_ADSP_REG_ADSPCS,
233052f103cSJayachandran B 			SKL_ADSPCS_CPA_MASK(core_mask),
234e973e31aSSubhransu S. Prusty 			0,
235e973e31aSSubhransu S. Prusty 			SKL_DSP_PD_TO,
236e973e31aSSubhransu S. Prusty 			"Power down");
237e973e31aSSubhransu S. Prusty }
238e973e31aSSubhransu S. Prusty 
239052f103cSJayachandran B int skl_dsp_enable_core(struct sst_dsp  *ctx, unsigned int core_mask)
240e973e31aSSubhransu S. Prusty {
241e973e31aSSubhransu S. Prusty 	int ret;
242e973e31aSSubhransu S. Prusty 
243e973e31aSSubhransu S. Prusty 	/* power up */
244052f103cSJayachandran B 	ret = skl_dsp_core_power_up(ctx, core_mask);
245e973e31aSSubhransu S. Prusty 	if (ret < 0) {
246052f103cSJayachandran B 		dev_err(ctx->dev, "dsp core power up failed: core_mask %x\n",
247052f103cSJayachandran B 							core_mask);
248e973e31aSSubhransu S. Prusty 		return ret;
249e973e31aSSubhransu S. Prusty 	}
250e973e31aSSubhransu S. Prusty 
251052f103cSJayachandran B 	return skl_dsp_start_core(ctx, core_mask);
252e973e31aSSubhransu S. Prusty }
253e973e31aSSubhransu S. Prusty 
254052f103cSJayachandran B int skl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask)
255e973e31aSSubhransu S. Prusty {
256e973e31aSSubhransu S. Prusty 	int ret;
257e973e31aSSubhransu S. Prusty 
258052f103cSJayachandran B 	ret = skl_dsp_reset_core(ctx, core_mask);
259e973e31aSSubhransu S. Prusty 	if (ret < 0) {
260052f103cSJayachandran B 		dev_err(ctx->dev, "dsp core reset failed: core_mask %x\n",
261052f103cSJayachandran B 							core_mask);
262e973e31aSSubhransu S. Prusty 		return ret;
263e973e31aSSubhransu S. Prusty 	}
264e973e31aSSubhransu S. Prusty 
265e973e31aSSubhransu S. Prusty 	/* power down core*/
266052f103cSJayachandran B 	ret = skl_dsp_core_power_down(ctx, core_mask);
267e973e31aSSubhransu S. Prusty 	if (ret < 0) {
268052f103cSJayachandran B 		dev_err(ctx->dev, "dsp core power down fail mask %x: %d\n",
269052f103cSJayachandran B 							core_mask, ret);
270e973e31aSSubhransu S. Prusty 		return ret;
271e973e31aSSubhransu S. Prusty 	}
272e973e31aSSubhransu S. Prusty 
273052f103cSJayachandran B 	if (is_skl_dsp_core_enable(ctx, core_mask)) {
274052f103cSJayachandran B 		dev_err(ctx->dev, "dsp core disable fail mask %x: %d\n",
275052f103cSJayachandran B 							core_mask, ret);
276e973e31aSSubhransu S. Prusty 		ret = -EIO;
277e973e31aSSubhransu S. Prusty 	}
278e973e31aSSubhransu S. Prusty 
279e973e31aSSubhransu S. Prusty 	return ret;
280e973e31aSSubhransu S. Prusty }
281e973e31aSSubhransu S. Prusty 
282e973e31aSSubhransu S. Prusty int skl_dsp_boot(struct sst_dsp *ctx)
283e973e31aSSubhransu S. Prusty {
284e973e31aSSubhransu S. Prusty 	int ret;
285e973e31aSSubhransu S. Prusty 
286052f103cSJayachandran B 	if (is_skl_dsp_core_enable(ctx, SKL_DSP_CORE0_MASK)) {
287052f103cSJayachandran B 		ret = skl_dsp_reset_core(ctx, SKL_DSP_CORE0_MASK);
288e973e31aSSubhransu S. Prusty 		if (ret < 0) {
289052f103cSJayachandran B 			dev_err(ctx->dev, "dsp core0 reset fail: %d\n", ret);
290e973e31aSSubhransu S. Prusty 			return ret;
291e973e31aSSubhransu S. Prusty 		}
292e973e31aSSubhransu S. Prusty 
293052f103cSJayachandran B 		ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK);
294e973e31aSSubhransu S. Prusty 		if (ret < 0) {
295052f103cSJayachandran B 			dev_err(ctx->dev, "dsp core0 start fail: %d\n", ret);
296e973e31aSSubhransu S. Prusty 			return ret;
297e973e31aSSubhransu S. Prusty 		}
298e973e31aSSubhransu S. Prusty 	} else {
299052f103cSJayachandran B 		ret = skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
300e973e31aSSubhransu S. Prusty 		if (ret < 0) {
301052f103cSJayachandran B 			dev_err(ctx->dev, "dsp core0 disable fail: %d\n", ret);
302e973e31aSSubhransu S. Prusty 			return ret;
303e973e31aSSubhransu S. Prusty 		}
304052f103cSJayachandran B 		ret = skl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK);
305e973e31aSSubhransu S. Prusty 	}
306e973e31aSSubhransu S. Prusty 
307e973e31aSSubhransu S. Prusty 	return ret;
308e973e31aSSubhransu S. Prusty }
309e973e31aSSubhransu S. Prusty 
310e973e31aSSubhransu S. Prusty irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id)
311e973e31aSSubhransu S. Prusty {
312e973e31aSSubhransu S. Prusty 	struct sst_dsp *ctx = dev_id;
313e973e31aSSubhransu S. Prusty 	u32 val;
314e973e31aSSubhransu S. Prusty 	irqreturn_t result = IRQ_NONE;
315e973e31aSSubhransu S. Prusty 
316e973e31aSSubhransu S. Prusty 	spin_lock(&ctx->spinlock);
317e973e31aSSubhransu S. Prusty 
318e973e31aSSubhransu S. Prusty 	val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPIS);
319e973e31aSSubhransu S. Prusty 	ctx->intr_status = val;
320e973e31aSSubhransu S. Prusty 
321def656feSJeeja KP 	if (val == 0xffffffff) {
322def656feSJeeja KP 		spin_unlock(&ctx->spinlock);
323def656feSJeeja KP 		return IRQ_NONE;
324def656feSJeeja KP 	}
325def656feSJeeja KP 
326e973e31aSSubhransu S. Prusty 	if (val & SKL_ADSPIS_IPC) {
327e973e31aSSubhransu S. Prusty 		skl_ipc_int_disable(ctx);
328e973e31aSSubhransu S. Prusty 		result = IRQ_WAKE_THREAD;
329e973e31aSSubhransu S. Prusty 	}
330e973e31aSSubhransu S. Prusty 
3316cb00333SSubhransu S. Prusty 	if (val & SKL_ADSPIS_CL_DMA) {
3326cb00333SSubhransu S. Prusty 		skl_cldma_int_disable(ctx);
3336cb00333SSubhransu S. Prusty 		result = IRQ_WAKE_THREAD;
3346cb00333SSubhransu S. Prusty 	}
3356cb00333SSubhransu S. Prusty 
336e973e31aSSubhransu S. Prusty 	spin_unlock(&ctx->spinlock);
337e973e31aSSubhransu S. Prusty 
338e973e31aSSubhransu S. Prusty 	return result;
339e973e31aSSubhransu S. Prusty }
340052f103cSJayachandran B /*
341052f103cSJayachandran B  * skl_dsp_get_core/skl_dsp_put_core will be called inside DAPM context
342052f103cSJayachandran B  * within the dapm mutex. Hence no separate lock is used.
343052f103cSJayachandran B  */
344052f103cSJayachandran B int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id)
345052f103cSJayachandran B {
346052f103cSJayachandran B 	struct skl_sst *skl = ctx->thread_context;
347052f103cSJayachandran B 	int ret = 0;
348052f103cSJayachandran B 
349052f103cSJayachandran B 	if (core_id >= skl->cores.count) {
350052f103cSJayachandran B 		dev_err(ctx->dev, "invalid core id: %d\n", core_id);
351052f103cSJayachandran B 		return -EINVAL;
352052f103cSJayachandran B 	}
353052f103cSJayachandran B 
3547b992c24SSubhransu S. Prusty 	skl->cores.usage_count[core_id]++;
3557b992c24SSubhransu S. Prusty 
356052f103cSJayachandran B 	if (skl->cores.state[core_id] == SKL_DSP_RESET) {
357052f103cSJayachandran B 		ret = ctx->fw_ops.set_state_D0(ctx, core_id);
358052f103cSJayachandran B 		if (ret < 0) {
359052f103cSJayachandran B 			dev_err(ctx->dev, "unable to get core%d\n", core_id);
3601fb344a3SJeeja KP 			goto out;
361052f103cSJayachandran B 		}
362052f103cSJayachandran B 	}
363052f103cSJayachandran B 
3641fb344a3SJeeja KP out:
365052f103cSJayachandran B 	dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n",
366052f103cSJayachandran B 			core_id, skl->cores.state[core_id],
367052f103cSJayachandran B 			skl->cores.usage_count[core_id]);
368052f103cSJayachandran B 
369052f103cSJayachandran B 	return ret;
370052f103cSJayachandran B }
371052f103cSJayachandran B EXPORT_SYMBOL_GPL(skl_dsp_get_core);
372052f103cSJayachandran B 
373052f103cSJayachandran B int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id)
374052f103cSJayachandran B {
375052f103cSJayachandran B 	struct skl_sst *skl = ctx->thread_context;
376052f103cSJayachandran B 	int ret = 0;
377052f103cSJayachandran B 
378052f103cSJayachandran B 	if (core_id >= skl->cores.count) {
379052f103cSJayachandran B 		dev_err(ctx->dev, "invalid core id: %d\n", core_id);
380052f103cSJayachandran B 		return -EINVAL;
381052f103cSJayachandran B 	}
382052f103cSJayachandran B 
3831fb344a3SJeeja KP 	if ((--skl->cores.usage_count[core_id] == 0) &&
3841fb344a3SJeeja KP 		(skl->cores.state[core_id] != SKL_DSP_RESET)) {
385052f103cSJayachandran B 		ret = ctx->fw_ops.set_state_D3(ctx, core_id);
386052f103cSJayachandran B 		if (ret < 0) {
387052f103cSJayachandran B 			dev_err(ctx->dev, "unable to put core %d: %d\n",
388052f103cSJayachandran B 					core_id, ret);
389052f103cSJayachandran B 			skl->cores.usage_count[core_id]++;
390052f103cSJayachandran B 		}
391052f103cSJayachandran B 	}
392052f103cSJayachandran B 
393052f103cSJayachandran B 	dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n",
394052f103cSJayachandran B 			core_id, skl->cores.state[core_id],
395052f103cSJayachandran B 			skl->cores.usage_count[core_id]);
396052f103cSJayachandran B 
397052f103cSJayachandran B 	return ret;
398052f103cSJayachandran B }
399052f103cSJayachandran B EXPORT_SYMBOL_GPL(skl_dsp_put_core);
400e973e31aSSubhransu S. Prusty 
401e973e31aSSubhransu S. Prusty int skl_dsp_wake(struct sst_dsp *ctx)
402e973e31aSSubhransu S. Prusty {
403052f103cSJayachandran B 	return skl_dsp_get_core(ctx, SKL_DSP_CORE0_ID);
404e973e31aSSubhransu S. Prusty }
405e973e31aSSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_dsp_wake);
406e973e31aSSubhransu S. Prusty 
407e973e31aSSubhransu S. Prusty int skl_dsp_sleep(struct sst_dsp *ctx)
408e973e31aSSubhransu S. Prusty {
409052f103cSJayachandran B 	return skl_dsp_put_core(ctx, SKL_DSP_CORE0_ID);
410e973e31aSSubhransu S. Prusty }
411e973e31aSSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_dsp_sleep);
412e973e31aSSubhransu S. Prusty 
413e973e31aSSubhransu S. Prusty struct sst_dsp *skl_dsp_ctx_init(struct device *dev,
414e973e31aSSubhransu S. Prusty 		struct sst_dsp_device *sst_dev, int irq)
415e973e31aSSubhransu S. Prusty {
416e973e31aSSubhransu S. Prusty 	int ret;
417e973e31aSSubhransu S. Prusty 	struct sst_dsp *sst;
418e973e31aSSubhransu S. Prusty 
419e973e31aSSubhransu S. Prusty 	sst = devm_kzalloc(dev, sizeof(*sst), GFP_KERNEL);
420e973e31aSSubhransu S. Prusty 	if (sst == NULL)
421e973e31aSSubhransu S. Prusty 		return NULL;
422e973e31aSSubhransu S. Prusty 
423e973e31aSSubhransu S. Prusty 	spin_lock_init(&sst->spinlock);
424e973e31aSSubhransu S. Prusty 	mutex_init(&sst->mutex);
425e973e31aSSubhransu S. Prusty 	sst->dev = dev;
426e973e31aSSubhransu S. Prusty 	sst->sst_dev = sst_dev;
427e973e31aSSubhransu S. Prusty 	sst->irq = irq;
428e973e31aSSubhransu S. Prusty 	sst->ops = sst_dev->ops;
429e973e31aSSubhransu S. Prusty 	sst->thread_context = sst_dev->thread_context;
430e973e31aSSubhransu S. Prusty 
431e973e31aSSubhransu S. Prusty 	/* Initialise SST Audio DSP */
432e973e31aSSubhransu S. Prusty 	if (sst->ops->init) {
433e973e31aSSubhransu S. Prusty 		ret = sst->ops->init(sst, NULL);
434e973e31aSSubhransu S. Prusty 		if (ret < 0)
435e973e31aSSubhransu S. Prusty 			return NULL;
436e973e31aSSubhransu S. Prusty 	}
437e973e31aSSubhransu S. Prusty 
4388e9d8e19SSubhransu S. Prusty 	return sst;
4398e9d8e19SSubhransu S. Prusty }
4408e9d8e19SSubhransu S. Prusty 
4418e9d8e19SSubhransu S. Prusty int skl_dsp_acquire_irq(struct sst_dsp *sst)
4428e9d8e19SSubhransu S. Prusty {
4438e9d8e19SSubhransu S. Prusty 	struct sst_dsp_device *sst_dev = sst->sst_dev;
4448e9d8e19SSubhransu S. Prusty 	int ret;
4458e9d8e19SSubhransu S. Prusty 
446e973e31aSSubhransu S. Prusty 	/* Register the ISR */
447e973e31aSSubhransu S. Prusty 	ret = request_threaded_irq(sst->irq, sst->ops->irq_handler,
448e973e31aSSubhransu S. Prusty 		sst_dev->thread, IRQF_SHARED, "AudioDSP", sst);
4498e9d8e19SSubhransu S. Prusty 	if (ret)
450e973e31aSSubhransu S. Prusty 		dev_err(sst->dev, "unable to grab threaded IRQ %d, disabling device\n",
451e973e31aSSubhransu S. Prusty 			       sst->irq);
452e973e31aSSubhransu S. Prusty 
4538e9d8e19SSubhransu S. Prusty 	return ret;
454e973e31aSSubhransu S. Prusty }
455e973e31aSSubhransu S. Prusty 
456e973e31aSSubhransu S. Prusty void skl_dsp_free(struct sst_dsp *dsp)
457e973e31aSSubhransu S. Prusty {
458e973e31aSSubhransu S. Prusty 	skl_ipc_int_disable(dsp);
459e973e31aSSubhransu S. Prusty 
460e973e31aSSubhransu S. Prusty 	free_irq(dsp->irq, dsp);
4613f7f8489SVinod Koul 	skl_ipc_op_int_disable(dsp);
462052f103cSJayachandran B 	skl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK);
463e973e31aSSubhransu S. Prusty }
464e973e31aSSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_dsp_free);
465e973e31aSSubhransu S. Prusty 
466e973e31aSSubhransu S. Prusty bool is_skl_dsp_running(struct sst_dsp *ctx)
467e973e31aSSubhransu S. Prusty {
468e973e31aSSubhransu S. Prusty 	return (ctx->sst_state == SKL_DSP_RUNNING);
469e973e31aSSubhransu S. Prusty }
470e973e31aSSubhransu S. Prusty EXPORT_SYMBOL_GPL(is_skl_dsp_running);
471