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