1 /*
2  * skl-sst-dsp.c - SKL SST library generic function
3  *
4  * Copyright (C) 2014-15, Intel Corporation.
5  * Author:Rafal Redzimski <rafal.f.redzimski@intel.com>
6  *	Jeeja KP <jeeja.kp@intel.com>
7  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as version 2, as
11  * published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  */
18 #include <sound/pcm.h>
19 
20 #include "../common/sst-dsp.h"
21 #include "../common/sst-ipc.h"
22 #include "../common/sst-dsp-priv.h"
23 #include "skl-sst-ipc.h"
24 
25 /* various timeout values */
26 #define SKL_DSP_PU_TO		50
27 #define SKL_DSP_PD_TO		50
28 #define SKL_DSP_RESET_TO	50
29 
30 void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state)
31 {
32 	mutex_lock(&ctx->mutex);
33 	ctx->sst_state = state;
34 	mutex_unlock(&ctx->mutex);
35 }
36 
37 static int skl_dsp_core_set_reset_state(struct sst_dsp *ctx)
38 {
39 	int ret;
40 
41 	/* update bits */
42 	sst_dsp_shim_update_bits_unlocked(ctx,
43 			SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK,
44 			SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK));
45 
46 	/* poll with timeout to check if operation successful */
47 	ret = sst_dsp_register_poll(ctx,
48 			SKL_ADSP_REG_ADSPCS,
49 			SKL_ADSPCS_CRST_MASK,
50 			SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK),
51 			SKL_DSP_RESET_TO,
52 			"Set reset");
53 	if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
54 				SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) !=
55 				SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) {
56 		dev_err(ctx->dev, "Set reset state failed\n");
57 		ret = -EIO;
58 	}
59 
60 	return ret;
61 }
62 
63 static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx)
64 {
65 	int ret;
66 
67 	dev_dbg(ctx->dev, "In %s\n", __func__);
68 
69 	/* update bits */
70 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
71 					SKL_ADSPCS_CRST_MASK, 0);
72 
73 	/* poll with timeout to check if operation successful */
74 	ret = sst_dsp_register_poll(ctx,
75 			SKL_ADSP_REG_ADSPCS,
76 			SKL_ADSPCS_CRST_MASK,
77 			0,
78 			SKL_DSP_RESET_TO,
79 			"Unset reset");
80 
81 	if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
82 				 SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) != 0) {
83 		dev_err(ctx->dev, "Unset reset state failed\n");
84 		ret = -EIO;
85 	}
86 
87 	return ret;
88 }
89 
90 static bool is_skl_dsp_core_enable(struct sst_dsp *ctx)
91 {
92 	int val;
93 	bool is_enable;
94 
95 	val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS);
96 
97 	is_enable = ((val & SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) &&
98 			(val & SKL_ADSPCS_SPA(SKL_DSP_CORES_MASK)) &&
99 			!(val & SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) &&
100 			!(val & SKL_ADSPCS_CSTALL(SKL_DSP_CORES_MASK)));
101 
102 	dev_dbg(ctx->dev, "DSP core is enabled=%d\n", is_enable);
103 	return is_enable;
104 }
105 
106 static int skl_dsp_reset_core(struct sst_dsp *ctx)
107 {
108 	/* stall core */
109 	sst_dsp_shim_write_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
110 			 sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
111 				SKL_ADSPCS_CSTALL(SKL_DSP_CORES_MASK));
112 
113 	/* set reset state */
114 	return skl_dsp_core_set_reset_state(ctx);
115 }
116 
117 static int skl_dsp_start_core(struct sst_dsp *ctx)
118 {
119 	int ret;
120 
121 	/* unset reset state */
122 	ret = skl_dsp_core_unset_reset_state(ctx);
123 	if (ret < 0) {
124 		dev_dbg(ctx->dev, "dsp unset reset fails\n");
125 		return ret;
126 	}
127 
128 	/* run core */
129 	dev_dbg(ctx->dev, "run core...\n");
130 	sst_dsp_shim_write_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
131 			 sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
132 				~SKL_ADSPCS_CSTALL(SKL_DSP_CORES_MASK));
133 
134 	if (!is_skl_dsp_core_enable(ctx)) {
135 		skl_dsp_reset_core(ctx);
136 		dev_err(ctx->dev, "DSP core enable failed\n");
137 		ret = -EIO;
138 	}
139 
140 	return ret;
141 }
142 
143 static int skl_dsp_core_power_up(struct sst_dsp *ctx)
144 {
145 	int ret;
146 
147 	/* update bits */
148 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
149 			SKL_ADSPCS_SPA_MASK, SKL_ADSPCS_SPA(SKL_DSP_CORES_MASK));
150 
151 	/* poll with timeout to check if operation successful */
152 	ret = sst_dsp_register_poll(ctx,
153 			SKL_ADSP_REG_ADSPCS,
154 			SKL_ADSPCS_CPA_MASK,
155 			SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK),
156 			SKL_DSP_PU_TO,
157 			"Power up");
158 
159 	if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
160 			SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) !=
161 			SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) {
162 		dev_err(ctx->dev, "DSP core power up failed\n");
163 		ret = -EIO;
164 	}
165 
166 	return ret;
167 }
168 
169 static int skl_dsp_core_power_down(struct sst_dsp *ctx)
170 {
171 	/* update bits */
172 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
173 					SKL_ADSPCS_SPA_MASK, 0);
174 
175 	/* poll with timeout to check if operation successful */
176 	return sst_dsp_register_poll(ctx,
177 			SKL_ADSP_REG_ADSPCS,
178 			SKL_ADSPCS_CPA_MASK,
179 			0,
180 			SKL_DSP_PD_TO,
181 			"Power down");
182 }
183 
184 int skl_dsp_enable_core(struct sst_dsp *ctx)
185 {
186 	int ret;
187 
188 	/* power up */
189 	ret = skl_dsp_core_power_up(ctx);
190 	if (ret < 0) {
191 		dev_dbg(ctx->dev, "dsp core power up failed\n");
192 		return ret;
193 	}
194 
195 	return skl_dsp_start_core(ctx);
196 }
197 
198 int skl_dsp_disable_core(struct sst_dsp *ctx)
199 {
200 	int ret;
201 
202 	ret = skl_dsp_reset_core(ctx);
203 	if (ret < 0) {
204 		dev_err(ctx->dev, "dsp core reset failed\n");
205 		return ret;
206 	}
207 
208 	/* power down core*/
209 	ret = skl_dsp_core_power_down(ctx);
210 	if (ret < 0) {
211 		dev_err(ctx->dev, "dsp core power down failed\n");
212 		return ret;
213 	}
214 
215 	if (is_skl_dsp_core_enable(ctx)) {
216 		dev_err(ctx->dev, "DSP core disable failed\n");
217 		ret = -EIO;
218 	}
219 
220 	return ret;
221 }
222 
223 int skl_dsp_boot(struct sst_dsp *ctx)
224 {
225 	int ret;
226 
227 	if (is_skl_dsp_core_enable(ctx)) {
228 		dev_dbg(ctx->dev, "dsp core is already enabled, so reset the dap core\n");
229 		ret = skl_dsp_reset_core(ctx);
230 		if (ret < 0) {
231 			dev_err(ctx->dev, "dsp reset failed\n");
232 			return ret;
233 		}
234 
235 		ret = skl_dsp_start_core(ctx);
236 		if (ret < 0) {
237 			dev_err(ctx->dev, "dsp start failed\n");
238 			return ret;
239 		}
240 	} else {
241 		dev_dbg(ctx->dev, "disable and enable to make sure DSP is invalid state\n");
242 		ret = skl_dsp_disable_core(ctx);
243 
244 		if (ret < 0) {
245 			dev_err(ctx->dev, "dsp disable core failes\n");
246 			return ret;
247 		}
248 		ret = skl_dsp_enable_core(ctx);
249 	}
250 
251 	return ret;
252 }
253 
254 irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id)
255 {
256 	struct sst_dsp *ctx = dev_id;
257 	u32 val;
258 	irqreturn_t result = IRQ_NONE;
259 
260 	spin_lock(&ctx->spinlock);
261 
262 	val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPIS);
263 	ctx->intr_status = val;
264 
265 	if (val == 0xffffffff) {
266 		spin_unlock(&ctx->spinlock);
267 		return IRQ_NONE;
268 	}
269 
270 	if (val & SKL_ADSPIS_IPC) {
271 		skl_ipc_int_disable(ctx);
272 		result = IRQ_WAKE_THREAD;
273 	}
274 
275 	if (val & SKL_ADSPIS_CL_DMA) {
276 		skl_cldma_int_disable(ctx);
277 		result = IRQ_WAKE_THREAD;
278 	}
279 
280 	spin_unlock(&ctx->spinlock);
281 
282 	return result;
283 }
284 
285 int skl_dsp_wake(struct sst_dsp *ctx)
286 {
287 	return ctx->fw_ops.set_state_D0(ctx);
288 }
289 EXPORT_SYMBOL_GPL(skl_dsp_wake);
290 
291 int skl_dsp_sleep(struct sst_dsp *ctx)
292 {
293 	return ctx->fw_ops.set_state_D3(ctx);
294 }
295 EXPORT_SYMBOL_GPL(skl_dsp_sleep);
296 
297 struct sst_dsp *skl_dsp_ctx_init(struct device *dev,
298 		struct sst_dsp_device *sst_dev, int irq)
299 {
300 	int ret;
301 	struct sst_dsp *sst;
302 
303 	sst = devm_kzalloc(dev, sizeof(*sst), GFP_KERNEL);
304 	if (sst == NULL)
305 		return NULL;
306 
307 	spin_lock_init(&sst->spinlock);
308 	mutex_init(&sst->mutex);
309 	sst->dev = dev;
310 	sst->sst_dev = sst_dev;
311 	sst->irq = irq;
312 	sst->ops = sst_dev->ops;
313 	sst->thread_context = sst_dev->thread_context;
314 
315 	/* Initialise SST Audio DSP */
316 	if (sst->ops->init) {
317 		ret = sst->ops->init(sst, NULL);
318 		if (ret < 0)
319 			return NULL;
320 	}
321 
322 	/* Register the ISR */
323 	ret = request_threaded_irq(sst->irq, sst->ops->irq_handler,
324 		sst_dev->thread, IRQF_SHARED, "AudioDSP", sst);
325 	if (ret) {
326 		dev_err(sst->dev, "unable to grab threaded IRQ %d, disabling device\n",
327 			       sst->irq);
328 		return NULL;
329 	}
330 
331 	return sst;
332 }
333 
334 void skl_dsp_free(struct sst_dsp *dsp)
335 {
336 	skl_ipc_int_disable(dsp);
337 
338 	free_irq(dsp->irq, dsp);
339 	skl_ipc_op_int_disable(dsp);
340 	skl_ipc_int_disable(dsp);
341 
342 	skl_dsp_disable_core(dsp);
343 }
344 EXPORT_SYMBOL_GPL(skl_dsp_free);
345 
346 bool is_skl_dsp_running(struct sst_dsp *ctx)
347 {
348 	return (ctx->sst_state == SKL_DSP_RUNNING);
349 }
350 EXPORT_SYMBOL_GPL(is_skl_dsp_running);
351