xref: /OK3568_Linux_fs/kernel/sound/soc/intel/skylake/skl-sst-dsp.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * skl-sst-dsp.c - SKL SST library generic function
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2014-15, Intel Corporation.
6*4882a593Smuzhiyun  * Author:Rafal Redzimski <rafal.f.redzimski@intel.com>
7*4882a593Smuzhiyun  *	Jeeja KP <jeeja.kp@intel.com>
8*4882a593Smuzhiyun  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun #include <sound/pcm.h>
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include "../common/sst-dsp.h"
13*4882a593Smuzhiyun #include "../common/sst-ipc.h"
14*4882a593Smuzhiyun #include "../common/sst-dsp-priv.h"
15*4882a593Smuzhiyun #include "skl.h"
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun /* various timeout values */
18*4882a593Smuzhiyun #define SKL_DSP_PU_TO		50
19*4882a593Smuzhiyun #define SKL_DSP_PD_TO		50
20*4882a593Smuzhiyun #define SKL_DSP_RESET_TO	50
21*4882a593Smuzhiyun 
skl_dsp_set_state_locked(struct sst_dsp * ctx,int state)22*4882a593Smuzhiyun void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state)
23*4882a593Smuzhiyun {
24*4882a593Smuzhiyun 	mutex_lock(&ctx->mutex);
25*4882a593Smuzhiyun 	ctx->sst_state = state;
26*4882a593Smuzhiyun 	mutex_unlock(&ctx->mutex);
27*4882a593Smuzhiyun }
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun /*
30*4882a593Smuzhiyun  * Initialize core power state and usage count. To be called after
31*4882a593Smuzhiyun  * successful first boot. Hence core 0 will be running and other cores
32*4882a593Smuzhiyun  * will be reset
33*4882a593Smuzhiyun  */
skl_dsp_init_core_state(struct sst_dsp * ctx)34*4882a593Smuzhiyun void skl_dsp_init_core_state(struct sst_dsp *ctx)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun 	struct skl_dev *skl = ctx->thread_context;
37*4882a593Smuzhiyun 	int i;
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 	skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING;
40*4882a593Smuzhiyun 	skl->cores.usage_count[SKL_DSP_CORE0_ID] = 1;
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 	for (i = SKL_DSP_CORE0_ID + 1; i < skl->cores.count; i++) {
43*4882a593Smuzhiyun 		skl->cores.state[i] = SKL_DSP_RESET;
44*4882a593Smuzhiyun 		skl->cores.usage_count[i] = 0;
45*4882a593Smuzhiyun 	}
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun /* Get the mask for all enabled cores */
skl_dsp_get_enabled_cores(struct sst_dsp * ctx)49*4882a593Smuzhiyun unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun 	struct skl_dev *skl = ctx->thread_context;
52*4882a593Smuzhiyun 	unsigned int core_mask, en_cores_mask;
53*4882a593Smuzhiyun 	u32 val;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	core_mask = SKL_DSP_CORES_MASK(skl->cores.count);
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS);
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	/* Cores having CPA bit set */
60*4882a593Smuzhiyun 	en_cores_mask = (val & SKL_ADSPCS_CPA_MASK(core_mask)) >>
61*4882a593Smuzhiyun 			SKL_ADSPCS_CPA_SHIFT;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	/* And cores having CRST bit cleared */
64*4882a593Smuzhiyun 	en_cores_mask &= (~val & SKL_ADSPCS_CRST_MASK(core_mask)) >>
65*4882a593Smuzhiyun 			SKL_ADSPCS_CRST_SHIFT;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	/* And cores having CSTALL bit cleared */
68*4882a593Smuzhiyun 	en_cores_mask &= (~val & SKL_ADSPCS_CSTALL_MASK(core_mask)) >>
69*4882a593Smuzhiyun 			SKL_ADSPCS_CSTALL_SHIFT;
70*4882a593Smuzhiyun 	en_cores_mask &= core_mask;
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	dev_dbg(ctx->dev, "DSP enabled cores mask = %x\n", en_cores_mask);
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 	return en_cores_mask;
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun static int
skl_dsp_core_set_reset_state(struct sst_dsp * ctx,unsigned int core_mask)78*4882a593Smuzhiyun skl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun 	int ret;
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	/* update bits */
83*4882a593Smuzhiyun 	sst_dsp_shim_update_bits_unlocked(ctx,
84*4882a593Smuzhiyun 			SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK(core_mask),
85*4882a593Smuzhiyun 			SKL_ADSPCS_CRST_MASK(core_mask));
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	/* poll with timeout to check if operation successful */
88*4882a593Smuzhiyun 	ret = sst_dsp_register_poll(ctx,
89*4882a593Smuzhiyun 			SKL_ADSP_REG_ADSPCS,
90*4882a593Smuzhiyun 			SKL_ADSPCS_CRST_MASK(core_mask),
91*4882a593Smuzhiyun 			SKL_ADSPCS_CRST_MASK(core_mask),
92*4882a593Smuzhiyun 			SKL_DSP_RESET_TO,
93*4882a593Smuzhiyun 			"Set reset");
94*4882a593Smuzhiyun 	if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
95*4882a593Smuzhiyun 				SKL_ADSPCS_CRST_MASK(core_mask)) !=
96*4882a593Smuzhiyun 				SKL_ADSPCS_CRST_MASK(core_mask)) {
97*4882a593Smuzhiyun 		dev_err(ctx->dev, "Set reset state failed: core_mask %x\n",
98*4882a593Smuzhiyun 							core_mask);
99*4882a593Smuzhiyun 		ret = -EIO;
100*4882a593Smuzhiyun 	}
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	return ret;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun 
skl_dsp_core_unset_reset_state(struct sst_dsp * ctx,unsigned int core_mask)105*4882a593Smuzhiyun int skl_dsp_core_unset_reset_state(
106*4882a593Smuzhiyun 		struct sst_dsp *ctx, unsigned int core_mask)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun 	int ret;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	dev_dbg(ctx->dev, "In %s\n", __func__);
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	/* update bits */
113*4882a593Smuzhiyun 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
114*4882a593Smuzhiyun 				SKL_ADSPCS_CRST_MASK(core_mask), 0);
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	/* poll with timeout to check if operation successful */
117*4882a593Smuzhiyun 	ret = sst_dsp_register_poll(ctx,
118*4882a593Smuzhiyun 			SKL_ADSP_REG_ADSPCS,
119*4882a593Smuzhiyun 			SKL_ADSPCS_CRST_MASK(core_mask),
120*4882a593Smuzhiyun 			0,
121*4882a593Smuzhiyun 			SKL_DSP_RESET_TO,
122*4882a593Smuzhiyun 			"Unset reset");
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
125*4882a593Smuzhiyun 				SKL_ADSPCS_CRST_MASK(core_mask)) != 0) {
126*4882a593Smuzhiyun 		dev_err(ctx->dev, "Unset reset state failed: core_mask %x\n",
127*4882a593Smuzhiyun 				core_mask);
128*4882a593Smuzhiyun 		ret = -EIO;
129*4882a593Smuzhiyun 	}
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	return ret;
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun static bool
is_skl_dsp_core_enable(struct sst_dsp * ctx,unsigned int core_mask)135*4882a593Smuzhiyun is_skl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun 	int val;
138*4882a593Smuzhiyun 	bool is_enable;
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 	val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS);
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	is_enable = ((val & SKL_ADSPCS_CPA_MASK(core_mask)) &&
143*4882a593Smuzhiyun 			(val & SKL_ADSPCS_SPA_MASK(core_mask)) &&
144*4882a593Smuzhiyun 			!(val & SKL_ADSPCS_CRST_MASK(core_mask)) &&
145*4882a593Smuzhiyun 			!(val & SKL_ADSPCS_CSTALL_MASK(core_mask)));
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	dev_dbg(ctx->dev, "DSP core(s) enabled? %d : core_mask %x\n",
148*4882a593Smuzhiyun 						is_enable, core_mask);
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	return is_enable;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun 
skl_dsp_reset_core(struct sst_dsp * ctx,unsigned int core_mask)153*4882a593Smuzhiyun static int skl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun 	/* stall core */
156*4882a593Smuzhiyun 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
157*4882a593Smuzhiyun 			SKL_ADSPCS_CSTALL_MASK(core_mask),
158*4882a593Smuzhiyun 			SKL_ADSPCS_CSTALL_MASK(core_mask));
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	/* set reset state */
161*4882a593Smuzhiyun 	return skl_dsp_core_set_reset_state(ctx, core_mask);
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
skl_dsp_start_core(struct sst_dsp * ctx,unsigned int core_mask)164*4882a593Smuzhiyun int skl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun 	int ret;
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	/* unset reset state */
169*4882a593Smuzhiyun 	ret = skl_dsp_core_unset_reset_state(ctx, core_mask);
170*4882a593Smuzhiyun 	if (ret < 0)
171*4882a593Smuzhiyun 		return ret;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	/* run core */
174*4882a593Smuzhiyun 	dev_dbg(ctx->dev, "unstall/run core: core_mask = %x\n", core_mask);
175*4882a593Smuzhiyun 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
176*4882a593Smuzhiyun 			SKL_ADSPCS_CSTALL_MASK(core_mask), 0);
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	if (!is_skl_dsp_core_enable(ctx, core_mask)) {
179*4882a593Smuzhiyun 		skl_dsp_reset_core(ctx, core_mask);
180*4882a593Smuzhiyun 		dev_err(ctx->dev, "DSP start core failed: core_mask %x\n",
181*4882a593Smuzhiyun 							core_mask);
182*4882a593Smuzhiyun 		ret = -EIO;
183*4882a593Smuzhiyun 	}
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	return ret;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun 
skl_dsp_core_power_up(struct sst_dsp * ctx,unsigned int core_mask)188*4882a593Smuzhiyun int skl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun 	int ret;
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	/* update bits */
193*4882a593Smuzhiyun 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
194*4882a593Smuzhiyun 			SKL_ADSPCS_SPA_MASK(core_mask),
195*4882a593Smuzhiyun 			SKL_ADSPCS_SPA_MASK(core_mask));
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	/* poll with timeout to check if operation successful */
198*4882a593Smuzhiyun 	ret = sst_dsp_register_poll(ctx,
199*4882a593Smuzhiyun 			SKL_ADSP_REG_ADSPCS,
200*4882a593Smuzhiyun 			SKL_ADSPCS_CPA_MASK(core_mask),
201*4882a593Smuzhiyun 			SKL_ADSPCS_CPA_MASK(core_mask),
202*4882a593Smuzhiyun 			SKL_DSP_PU_TO,
203*4882a593Smuzhiyun 			"Power up");
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
206*4882a593Smuzhiyun 			SKL_ADSPCS_CPA_MASK(core_mask)) !=
207*4882a593Smuzhiyun 			SKL_ADSPCS_CPA_MASK(core_mask)) {
208*4882a593Smuzhiyun 		dev_err(ctx->dev, "DSP core power up failed: core_mask %x\n",
209*4882a593Smuzhiyun 				core_mask);
210*4882a593Smuzhiyun 		ret = -EIO;
211*4882a593Smuzhiyun 	}
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	return ret;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun 
skl_dsp_core_power_down(struct sst_dsp * ctx,unsigned int core_mask)216*4882a593Smuzhiyun int skl_dsp_core_power_down(struct sst_dsp  *ctx, unsigned int core_mask)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun 	/* update bits */
219*4882a593Smuzhiyun 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
220*4882a593Smuzhiyun 				SKL_ADSPCS_SPA_MASK(core_mask), 0);
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	/* poll with timeout to check if operation successful */
223*4882a593Smuzhiyun 	return sst_dsp_register_poll(ctx,
224*4882a593Smuzhiyun 			SKL_ADSP_REG_ADSPCS,
225*4882a593Smuzhiyun 			SKL_ADSPCS_CPA_MASK(core_mask),
226*4882a593Smuzhiyun 			0,
227*4882a593Smuzhiyun 			SKL_DSP_PD_TO,
228*4882a593Smuzhiyun 			"Power down");
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun 
skl_dsp_enable_core(struct sst_dsp * ctx,unsigned int core_mask)231*4882a593Smuzhiyun int skl_dsp_enable_core(struct sst_dsp  *ctx, unsigned int core_mask)
232*4882a593Smuzhiyun {
233*4882a593Smuzhiyun 	int ret;
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	/* power up */
236*4882a593Smuzhiyun 	ret = skl_dsp_core_power_up(ctx, core_mask);
237*4882a593Smuzhiyun 	if (ret < 0) {
238*4882a593Smuzhiyun 		dev_err(ctx->dev, "dsp core power up failed: core_mask %x\n",
239*4882a593Smuzhiyun 							core_mask);
240*4882a593Smuzhiyun 		return ret;
241*4882a593Smuzhiyun 	}
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	return skl_dsp_start_core(ctx, core_mask);
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun 
skl_dsp_disable_core(struct sst_dsp * ctx,unsigned int core_mask)246*4882a593Smuzhiyun int skl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask)
247*4882a593Smuzhiyun {
248*4882a593Smuzhiyun 	int ret;
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	ret = skl_dsp_reset_core(ctx, core_mask);
251*4882a593Smuzhiyun 	if (ret < 0) {
252*4882a593Smuzhiyun 		dev_err(ctx->dev, "dsp core reset failed: core_mask %x\n",
253*4882a593Smuzhiyun 							core_mask);
254*4882a593Smuzhiyun 		return ret;
255*4882a593Smuzhiyun 	}
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	/* power down core*/
258*4882a593Smuzhiyun 	ret = skl_dsp_core_power_down(ctx, core_mask);
259*4882a593Smuzhiyun 	if (ret < 0) {
260*4882a593Smuzhiyun 		dev_err(ctx->dev, "dsp core power down fail mask %x: %d\n",
261*4882a593Smuzhiyun 							core_mask, ret);
262*4882a593Smuzhiyun 		return ret;
263*4882a593Smuzhiyun 	}
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	if (is_skl_dsp_core_enable(ctx, core_mask)) {
266*4882a593Smuzhiyun 		dev_err(ctx->dev, "dsp core disable fail mask %x: %d\n",
267*4882a593Smuzhiyun 							core_mask, ret);
268*4882a593Smuzhiyun 		ret = -EIO;
269*4882a593Smuzhiyun 	}
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	return ret;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun 
skl_dsp_boot(struct sst_dsp * ctx)274*4882a593Smuzhiyun int skl_dsp_boot(struct sst_dsp *ctx)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun 	int ret;
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	if (is_skl_dsp_core_enable(ctx, SKL_DSP_CORE0_MASK)) {
279*4882a593Smuzhiyun 		ret = skl_dsp_reset_core(ctx, SKL_DSP_CORE0_MASK);
280*4882a593Smuzhiyun 		if (ret < 0) {
281*4882a593Smuzhiyun 			dev_err(ctx->dev, "dsp core0 reset fail: %d\n", ret);
282*4882a593Smuzhiyun 			return ret;
283*4882a593Smuzhiyun 		}
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 		ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK);
286*4882a593Smuzhiyun 		if (ret < 0) {
287*4882a593Smuzhiyun 			dev_err(ctx->dev, "dsp core0 start fail: %d\n", ret);
288*4882a593Smuzhiyun 			return ret;
289*4882a593Smuzhiyun 		}
290*4882a593Smuzhiyun 	} else {
291*4882a593Smuzhiyun 		ret = skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
292*4882a593Smuzhiyun 		if (ret < 0) {
293*4882a593Smuzhiyun 			dev_err(ctx->dev, "dsp core0 disable fail: %d\n", ret);
294*4882a593Smuzhiyun 			return ret;
295*4882a593Smuzhiyun 		}
296*4882a593Smuzhiyun 		ret = skl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK);
297*4882a593Smuzhiyun 	}
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	return ret;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun 
skl_dsp_sst_interrupt(int irq,void * dev_id)302*4882a593Smuzhiyun irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun 	struct sst_dsp *ctx = dev_id;
305*4882a593Smuzhiyun 	u32 val;
306*4882a593Smuzhiyun 	irqreturn_t result = IRQ_NONE;
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	spin_lock(&ctx->spinlock);
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPIS);
311*4882a593Smuzhiyun 	ctx->intr_status = val;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	if (val == 0xffffffff) {
314*4882a593Smuzhiyun 		spin_unlock(&ctx->spinlock);
315*4882a593Smuzhiyun 		return IRQ_NONE;
316*4882a593Smuzhiyun 	}
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	if (val & SKL_ADSPIS_IPC) {
319*4882a593Smuzhiyun 		skl_ipc_int_disable(ctx);
320*4882a593Smuzhiyun 		result = IRQ_WAKE_THREAD;
321*4882a593Smuzhiyun 	}
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 	if (val & SKL_ADSPIS_CL_DMA) {
324*4882a593Smuzhiyun 		skl_cldma_int_disable(ctx);
325*4882a593Smuzhiyun 		result = IRQ_WAKE_THREAD;
326*4882a593Smuzhiyun 	}
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	spin_unlock(&ctx->spinlock);
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	return result;
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun /*
333*4882a593Smuzhiyun  * skl_dsp_get_core/skl_dsp_put_core will be called inside DAPM context
334*4882a593Smuzhiyun  * within the dapm mutex. Hence no separate lock is used.
335*4882a593Smuzhiyun  */
skl_dsp_get_core(struct sst_dsp * ctx,unsigned int core_id)336*4882a593Smuzhiyun int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id)
337*4882a593Smuzhiyun {
338*4882a593Smuzhiyun 	struct skl_dev *skl = ctx->thread_context;
339*4882a593Smuzhiyun 	int ret = 0;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	if (core_id >= skl->cores.count) {
342*4882a593Smuzhiyun 		dev_err(ctx->dev, "invalid core id: %d\n", core_id);
343*4882a593Smuzhiyun 		return -EINVAL;
344*4882a593Smuzhiyun 	}
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 	skl->cores.usage_count[core_id]++;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	if (skl->cores.state[core_id] == SKL_DSP_RESET) {
349*4882a593Smuzhiyun 		ret = ctx->fw_ops.set_state_D0(ctx, core_id);
350*4882a593Smuzhiyun 		if (ret < 0) {
351*4882a593Smuzhiyun 			dev_err(ctx->dev, "unable to get core%d\n", core_id);
352*4882a593Smuzhiyun 			goto out;
353*4882a593Smuzhiyun 		}
354*4882a593Smuzhiyun 	}
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun out:
357*4882a593Smuzhiyun 	dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n",
358*4882a593Smuzhiyun 			core_id, skl->cores.state[core_id],
359*4882a593Smuzhiyun 			skl->cores.usage_count[core_id]);
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	return ret;
362*4882a593Smuzhiyun }
363*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(skl_dsp_get_core);
364*4882a593Smuzhiyun 
skl_dsp_put_core(struct sst_dsp * ctx,unsigned int core_id)365*4882a593Smuzhiyun int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id)
366*4882a593Smuzhiyun {
367*4882a593Smuzhiyun 	struct skl_dev *skl = ctx->thread_context;
368*4882a593Smuzhiyun 	int ret = 0;
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 	if (core_id >= skl->cores.count) {
371*4882a593Smuzhiyun 		dev_err(ctx->dev, "invalid core id: %d\n", core_id);
372*4882a593Smuzhiyun 		return -EINVAL;
373*4882a593Smuzhiyun 	}
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	if ((--skl->cores.usage_count[core_id] == 0) &&
376*4882a593Smuzhiyun 		(skl->cores.state[core_id] != SKL_DSP_RESET)) {
377*4882a593Smuzhiyun 		ret = ctx->fw_ops.set_state_D3(ctx, core_id);
378*4882a593Smuzhiyun 		if (ret < 0) {
379*4882a593Smuzhiyun 			dev_err(ctx->dev, "unable to put core %d: %d\n",
380*4882a593Smuzhiyun 					core_id, ret);
381*4882a593Smuzhiyun 			skl->cores.usage_count[core_id]++;
382*4882a593Smuzhiyun 		}
383*4882a593Smuzhiyun 	}
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n",
386*4882a593Smuzhiyun 			core_id, skl->cores.state[core_id],
387*4882a593Smuzhiyun 			skl->cores.usage_count[core_id]);
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	return ret;
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(skl_dsp_put_core);
392*4882a593Smuzhiyun 
skl_dsp_wake(struct sst_dsp * ctx)393*4882a593Smuzhiyun int skl_dsp_wake(struct sst_dsp *ctx)
394*4882a593Smuzhiyun {
395*4882a593Smuzhiyun 	return skl_dsp_get_core(ctx, SKL_DSP_CORE0_ID);
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(skl_dsp_wake);
398*4882a593Smuzhiyun 
skl_dsp_sleep(struct sst_dsp * ctx)399*4882a593Smuzhiyun int skl_dsp_sleep(struct sst_dsp *ctx)
400*4882a593Smuzhiyun {
401*4882a593Smuzhiyun 	return skl_dsp_put_core(ctx, SKL_DSP_CORE0_ID);
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(skl_dsp_sleep);
404*4882a593Smuzhiyun 
skl_dsp_ctx_init(struct device * dev,struct sst_dsp_device * sst_dev,int irq)405*4882a593Smuzhiyun struct sst_dsp *skl_dsp_ctx_init(struct device *dev,
406*4882a593Smuzhiyun 		struct sst_dsp_device *sst_dev, int irq)
407*4882a593Smuzhiyun {
408*4882a593Smuzhiyun 	int ret;
409*4882a593Smuzhiyun 	struct sst_dsp *sst;
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	sst = devm_kzalloc(dev, sizeof(*sst), GFP_KERNEL);
412*4882a593Smuzhiyun 	if (sst == NULL)
413*4882a593Smuzhiyun 		return NULL;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 	spin_lock_init(&sst->spinlock);
416*4882a593Smuzhiyun 	mutex_init(&sst->mutex);
417*4882a593Smuzhiyun 	sst->dev = dev;
418*4882a593Smuzhiyun 	sst->sst_dev = sst_dev;
419*4882a593Smuzhiyun 	sst->irq = irq;
420*4882a593Smuzhiyun 	sst->ops = sst_dev->ops;
421*4882a593Smuzhiyun 	sst->thread_context = sst_dev->thread_context;
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	/* Initialise SST Audio DSP */
424*4882a593Smuzhiyun 	if (sst->ops->init) {
425*4882a593Smuzhiyun 		ret = sst->ops->init(sst);
426*4882a593Smuzhiyun 		if (ret < 0)
427*4882a593Smuzhiyun 			return NULL;
428*4882a593Smuzhiyun 	}
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 	return sst;
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun 
skl_dsp_acquire_irq(struct sst_dsp * sst)433*4882a593Smuzhiyun int skl_dsp_acquire_irq(struct sst_dsp *sst)
434*4882a593Smuzhiyun {
435*4882a593Smuzhiyun 	struct sst_dsp_device *sst_dev = sst->sst_dev;
436*4882a593Smuzhiyun 	int ret;
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 	/* Register the ISR */
439*4882a593Smuzhiyun 	ret = request_threaded_irq(sst->irq, sst->ops->irq_handler,
440*4882a593Smuzhiyun 		sst_dev->thread, IRQF_SHARED, "AudioDSP", sst);
441*4882a593Smuzhiyun 	if (ret)
442*4882a593Smuzhiyun 		dev_err(sst->dev, "unable to grab threaded IRQ %d, disabling device\n",
443*4882a593Smuzhiyun 			       sst->irq);
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun 	return ret;
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun 
skl_dsp_free(struct sst_dsp * dsp)448*4882a593Smuzhiyun void skl_dsp_free(struct sst_dsp *dsp)
449*4882a593Smuzhiyun {
450*4882a593Smuzhiyun 	skl_ipc_int_disable(dsp);
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	free_irq(dsp->irq, dsp);
453*4882a593Smuzhiyun 	skl_ipc_op_int_disable(dsp);
454*4882a593Smuzhiyun 	skl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK);
455*4882a593Smuzhiyun }
456*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(skl_dsp_free);
457*4882a593Smuzhiyun 
is_skl_dsp_running(struct sst_dsp * ctx)458*4882a593Smuzhiyun bool is_skl_dsp_running(struct sst_dsp *ctx)
459*4882a593Smuzhiyun {
460*4882a593Smuzhiyun 	return (ctx->sst_state == SKL_DSP_RUNNING);
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(is_skl_dsp_running);
463