147d7195dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2a838dcc2SGuneshwor Singh /*
3a838dcc2SGuneshwor Singh  * cnl-sst-dsp.c - CNL SST library generic function
4a838dcc2SGuneshwor Singh  *
5a838dcc2SGuneshwor Singh  * Copyright (C) 2016-17, Intel Corporation.
6a838dcc2SGuneshwor Singh  * Author: Guneshwor Singh <guneshwor.o.singh@intel.com>
7a838dcc2SGuneshwor Singh  *
8a838dcc2SGuneshwor Singh  * Modified from:
9a838dcc2SGuneshwor Singh  *	SKL SST library generic function
10a838dcc2SGuneshwor Singh  *	Copyright (C) 2014-15, Intel Corporation.
11a838dcc2SGuneshwor Singh  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12a838dcc2SGuneshwor Singh  *
13a838dcc2SGuneshwor Singh  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
14a838dcc2SGuneshwor Singh  */
15a838dcc2SGuneshwor Singh #include <linux/device.h>
16a838dcc2SGuneshwor Singh #include "../common/sst-dsp.h"
17a838dcc2SGuneshwor Singh #include "../common/sst-ipc.h"
18a838dcc2SGuneshwor Singh #include "../common/sst-dsp-priv.h"
19a838dcc2SGuneshwor Singh #include "cnl-sst-dsp.h"
20a838dcc2SGuneshwor Singh 
21a838dcc2SGuneshwor Singh /* various timeout values */
22a838dcc2SGuneshwor Singh #define CNL_DSP_PU_TO		50
23a838dcc2SGuneshwor Singh #define CNL_DSP_PD_TO		50
24a838dcc2SGuneshwor Singh #define CNL_DSP_RESET_TO	50
25a838dcc2SGuneshwor Singh 
26a838dcc2SGuneshwor Singh static int
cnl_dsp_core_set_reset_state(struct sst_dsp * ctx,unsigned int core_mask)27a838dcc2SGuneshwor Singh cnl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
28a838dcc2SGuneshwor Singh {
29a838dcc2SGuneshwor Singh 	/* update bits */
30a838dcc2SGuneshwor Singh 	sst_dsp_shim_update_bits_unlocked(ctx,
31a838dcc2SGuneshwor Singh 			CNL_ADSP_REG_ADSPCS, CNL_ADSPCS_CRST(core_mask),
32a838dcc2SGuneshwor Singh 			CNL_ADSPCS_CRST(core_mask));
33a838dcc2SGuneshwor Singh 
34a838dcc2SGuneshwor Singh 	/* poll with timeout to check if operation successful */
35a838dcc2SGuneshwor Singh 	return sst_dsp_register_poll(ctx,
36a838dcc2SGuneshwor Singh 			CNL_ADSP_REG_ADSPCS,
37a838dcc2SGuneshwor Singh 			CNL_ADSPCS_CRST(core_mask),
38a838dcc2SGuneshwor Singh 			CNL_ADSPCS_CRST(core_mask),
39a838dcc2SGuneshwor Singh 			CNL_DSP_RESET_TO,
40a838dcc2SGuneshwor Singh 			"Set reset");
41a838dcc2SGuneshwor Singh }
42a838dcc2SGuneshwor Singh 
43a838dcc2SGuneshwor Singh static int
cnl_dsp_core_unset_reset_state(struct sst_dsp * ctx,unsigned int core_mask)44a838dcc2SGuneshwor Singh cnl_dsp_core_unset_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
45a838dcc2SGuneshwor Singh {
46a838dcc2SGuneshwor Singh 	/* update bits */
47a838dcc2SGuneshwor Singh 	sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
48a838dcc2SGuneshwor Singh 					CNL_ADSPCS_CRST(core_mask), 0);
49a838dcc2SGuneshwor Singh 
50a838dcc2SGuneshwor Singh 	/* poll with timeout to check if operation successful */
51a838dcc2SGuneshwor Singh 	return sst_dsp_register_poll(ctx,
52a838dcc2SGuneshwor Singh 			CNL_ADSP_REG_ADSPCS,
53a838dcc2SGuneshwor Singh 			CNL_ADSPCS_CRST(core_mask),
54a838dcc2SGuneshwor Singh 			0,
55a838dcc2SGuneshwor Singh 			CNL_DSP_RESET_TO,
56a838dcc2SGuneshwor Singh 			"Unset reset");
57a838dcc2SGuneshwor Singh }
58a838dcc2SGuneshwor Singh 
is_cnl_dsp_core_enable(struct sst_dsp * ctx,unsigned int core_mask)59a838dcc2SGuneshwor Singh static bool is_cnl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask)
60a838dcc2SGuneshwor Singh {
61a838dcc2SGuneshwor Singh 	int val;
62a838dcc2SGuneshwor Singh 	bool is_enable;
63a838dcc2SGuneshwor Singh 
64a838dcc2SGuneshwor Singh 	val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPCS);
65a838dcc2SGuneshwor Singh 
66a838dcc2SGuneshwor Singh 	is_enable = (val & CNL_ADSPCS_CPA(core_mask)) &&
67a838dcc2SGuneshwor Singh 			(val & CNL_ADSPCS_SPA(core_mask)) &&
68a838dcc2SGuneshwor Singh 			!(val & CNL_ADSPCS_CRST(core_mask)) &&
69a838dcc2SGuneshwor Singh 			!(val & CNL_ADSPCS_CSTALL(core_mask));
70a838dcc2SGuneshwor Singh 
71a838dcc2SGuneshwor Singh 	dev_dbg(ctx->dev, "DSP core(s) enabled? %d: core_mask %#x\n",
72a838dcc2SGuneshwor Singh 		is_enable, core_mask);
73a838dcc2SGuneshwor Singh 
74a838dcc2SGuneshwor Singh 	return is_enable;
75a838dcc2SGuneshwor Singh }
76a838dcc2SGuneshwor Singh 
cnl_dsp_reset_core(struct sst_dsp * ctx,unsigned int core_mask)77a838dcc2SGuneshwor Singh static int cnl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask)
78a838dcc2SGuneshwor Singh {
79a838dcc2SGuneshwor Singh 	/* stall core */
80a838dcc2SGuneshwor Singh 	sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
81a838dcc2SGuneshwor Singh 			CNL_ADSPCS_CSTALL(core_mask),
82a838dcc2SGuneshwor Singh 			CNL_ADSPCS_CSTALL(core_mask));
83a838dcc2SGuneshwor Singh 
84a838dcc2SGuneshwor Singh 	/* set reset state */
85a838dcc2SGuneshwor Singh 	return cnl_dsp_core_set_reset_state(ctx, core_mask);
86a838dcc2SGuneshwor Singh }
87a838dcc2SGuneshwor Singh 
cnl_dsp_start_core(struct sst_dsp * ctx,unsigned int core_mask)88a838dcc2SGuneshwor Singh static int cnl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask)
89a838dcc2SGuneshwor Singh {
90a838dcc2SGuneshwor Singh 	int ret;
91a838dcc2SGuneshwor Singh 
92a838dcc2SGuneshwor Singh 	/* unset reset state */
93a838dcc2SGuneshwor Singh 	ret = cnl_dsp_core_unset_reset_state(ctx, core_mask);
94a838dcc2SGuneshwor Singh 	if (ret < 0)
95a838dcc2SGuneshwor Singh 		return ret;
96a838dcc2SGuneshwor Singh 
97a838dcc2SGuneshwor Singh 	/* run core */
98a838dcc2SGuneshwor Singh 	sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
99a838dcc2SGuneshwor Singh 				CNL_ADSPCS_CSTALL(core_mask), 0);
100a838dcc2SGuneshwor Singh 
101a838dcc2SGuneshwor Singh 	if (!is_cnl_dsp_core_enable(ctx, core_mask)) {
102a838dcc2SGuneshwor Singh 		cnl_dsp_reset_core(ctx, core_mask);
103a838dcc2SGuneshwor Singh 		dev_err(ctx->dev, "DSP core mask %#x enable failed\n",
104a838dcc2SGuneshwor Singh 			core_mask);
105a838dcc2SGuneshwor Singh 		ret = -EIO;
106a838dcc2SGuneshwor Singh 	}
107a838dcc2SGuneshwor Singh 
108a838dcc2SGuneshwor Singh 	return ret;
109a838dcc2SGuneshwor Singh }
110a838dcc2SGuneshwor Singh 
cnl_dsp_core_power_up(struct sst_dsp * ctx,unsigned int core_mask)111a838dcc2SGuneshwor Singh static int cnl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask)
112a838dcc2SGuneshwor Singh {
113a838dcc2SGuneshwor Singh 	/* update bits */
114a838dcc2SGuneshwor Singh 	sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
115a838dcc2SGuneshwor Singh 					  CNL_ADSPCS_SPA(core_mask),
116a838dcc2SGuneshwor Singh 					  CNL_ADSPCS_SPA(core_mask));
117a838dcc2SGuneshwor Singh 
118a838dcc2SGuneshwor Singh 	/* poll with timeout to check if operation successful */
119a838dcc2SGuneshwor Singh 	return sst_dsp_register_poll(ctx, CNL_ADSP_REG_ADSPCS,
120a838dcc2SGuneshwor Singh 				    CNL_ADSPCS_CPA(core_mask),
121a838dcc2SGuneshwor Singh 				    CNL_ADSPCS_CPA(core_mask),
122a838dcc2SGuneshwor Singh 				    CNL_DSP_PU_TO,
123a838dcc2SGuneshwor Singh 				    "Power up");
124a838dcc2SGuneshwor Singh }
125a838dcc2SGuneshwor Singh 
cnl_dsp_core_power_down(struct sst_dsp * ctx,unsigned int core_mask)126a838dcc2SGuneshwor Singh static int cnl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask)
127a838dcc2SGuneshwor Singh {
128a838dcc2SGuneshwor Singh 	/* update bits */
129a838dcc2SGuneshwor Singh 	sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
130a838dcc2SGuneshwor Singh 					CNL_ADSPCS_SPA(core_mask), 0);
131a838dcc2SGuneshwor Singh 
132a838dcc2SGuneshwor Singh 	/* poll with timeout to check if operation successful */
133a838dcc2SGuneshwor Singh 	return sst_dsp_register_poll(ctx,
134a838dcc2SGuneshwor Singh 			CNL_ADSP_REG_ADSPCS,
135a838dcc2SGuneshwor Singh 			CNL_ADSPCS_CPA(core_mask),
136a838dcc2SGuneshwor Singh 			0,
137a838dcc2SGuneshwor Singh 			CNL_DSP_PD_TO,
138a838dcc2SGuneshwor Singh 			"Power down");
139a838dcc2SGuneshwor Singh }
140a838dcc2SGuneshwor Singh 
cnl_dsp_enable_core(struct sst_dsp * ctx,unsigned int core_mask)141a838dcc2SGuneshwor Singh int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask)
142a838dcc2SGuneshwor Singh {
143a838dcc2SGuneshwor Singh 	int ret;
144a838dcc2SGuneshwor Singh 
145a838dcc2SGuneshwor Singh 	/* power up */
146a838dcc2SGuneshwor Singh 	ret = cnl_dsp_core_power_up(ctx, core_mask);
147a838dcc2SGuneshwor Singh 	if (ret < 0) {
148a838dcc2SGuneshwor Singh 		dev_dbg(ctx->dev, "DSP core mask %#x power up failed",
149a838dcc2SGuneshwor Singh 			core_mask);
150a838dcc2SGuneshwor Singh 		return ret;
151a838dcc2SGuneshwor Singh 	}
152a838dcc2SGuneshwor Singh 
153a838dcc2SGuneshwor Singh 	return cnl_dsp_start_core(ctx, core_mask);
154a838dcc2SGuneshwor Singh }
155a838dcc2SGuneshwor Singh 
cnl_dsp_disable_core(struct sst_dsp * ctx,unsigned int core_mask)156a838dcc2SGuneshwor Singh int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask)
157a838dcc2SGuneshwor Singh {
158a838dcc2SGuneshwor Singh 	int ret;
159a838dcc2SGuneshwor Singh 
160a838dcc2SGuneshwor Singh 	ret = cnl_dsp_reset_core(ctx, core_mask);
161a838dcc2SGuneshwor Singh 	if (ret < 0) {
162a838dcc2SGuneshwor Singh 		dev_err(ctx->dev, "DSP core mask %#x reset failed\n",
163a838dcc2SGuneshwor Singh 			core_mask);
164a838dcc2SGuneshwor Singh 		return ret;
165a838dcc2SGuneshwor Singh 	}
166a838dcc2SGuneshwor Singh 
167a838dcc2SGuneshwor Singh 	/* power down core*/
168a838dcc2SGuneshwor Singh 	ret = cnl_dsp_core_power_down(ctx, core_mask);
169a838dcc2SGuneshwor Singh 	if (ret < 0) {
170a838dcc2SGuneshwor Singh 		dev_err(ctx->dev, "DSP core mask %#x power down failed\n",
171a838dcc2SGuneshwor Singh 			core_mask);
172a838dcc2SGuneshwor Singh 		return ret;
173a838dcc2SGuneshwor Singh 	}
174a838dcc2SGuneshwor Singh 
175a838dcc2SGuneshwor Singh 	if (is_cnl_dsp_core_enable(ctx, core_mask)) {
176a838dcc2SGuneshwor Singh 		dev_err(ctx->dev, "DSP core mask %#x disable failed\n",
177a838dcc2SGuneshwor Singh 			core_mask);
178a838dcc2SGuneshwor Singh 		ret = -EIO;
179a838dcc2SGuneshwor Singh 	}
180a838dcc2SGuneshwor Singh 
181a838dcc2SGuneshwor Singh 	return ret;
182a838dcc2SGuneshwor Singh }
183a838dcc2SGuneshwor Singh 
cnl_dsp_sst_interrupt(int irq,void * dev_id)184a838dcc2SGuneshwor Singh irqreturn_t cnl_dsp_sst_interrupt(int irq, void *dev_id)
185a838dcc2SGuneshwor Singh {
186a838dcc2SGuneshwor Singh 	struct sst_dsp *ctx = dev_id;
187a838dcc2SGuneshwor Singh 	u32 val;
188a838dcc2SGuneshwor Singh 	irqreturn_t ret = IRQ_NONE;
189a838dcc2SGuneshwor Singh 
190a838dcc2SGuneshwor Singh 	spin_lock(&ctx->spinlock);
191a838dcc2SGuneshwor Singh 
192a838dcc2SGuneshwor Singh 	val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS);
193a838dcc2SGuneshwor Singh 	ctx->intr_status = val;
194a838dcc2SGuneshwor Singh 
195a838dcc2SGuneshwor Singh 	if (val == 0xffffffff) {
196a838dcc2SGuneshwor Singh 		spin_unlock(&ctx->spinlock);
197a838dcc2SGuneshwor Singh 		return IRQ_NONE;
198a838dcc2SGuneshwor Singh 	}
199a838dcc2SGuneshwor Singh 
200a838dcc2SGuneshwor Singh 	if (val & CNL_ADSPIS_IPC) {
201a838dcc2SGuneshwor Singh 		cnl_ipc_int_disable(ctx);
202a838dcc2SGuneshwor Singh 		ret = IRQ_WAKE_THREAD;
203a838dcc2SGuneshwor Singh 	}
204a838dcc2SGuneshwor Singh 
205a838dcc2SGuneshwor Singh 	spin_unlock(&ctx->spinlock);
206a838dcc2SGuneshwor Singh 
207a838dcc2SGuneshwor Singh 	return ret;
208a838dcc2SGuneshwor Singh }
209a838dcc2SGuneshwor Singh 
cnl_dsp_free(struct sst_dsp * dsp)210a838dcc2SGuneshwor Singh void cnl_dsp_free(struct sst_dsp *dsp)
211a838dcc2SGuneshwor Singh {
212a838dcc2SGuneshwor Singh 	cnl_ipc_int_disable(dsp);
213a838dcc2SGuneshwor Singh 
214a838dcc2SGuneshwor Singh 	free_irq(dsp->irq, dsp);
215a838dcc2SGuneshwor Singh 	cnl_ipc_op_int_disable(dsp);
216a838dcc2SGuneshwor Singh 	cnl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK);
217a838dcc2SGuneshwor Singh }
218a838dcc2SGuneshwor Singh EXPORT_SYMBOL_GPL(cnl_dsp_free);
219a838dcc2SGuneshwor Singh 
cnl_ipc_int_enable(struct sst_dsp * ctx)220a838dcc2SGuneshwor Singh void cnl_ipc_int_enable(struct sst_dsp *ctx)
221a838dcc2SGuneshwor Singh {
222a838dcc2SGuneshwor Singh 	sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_ADSPIC,
223a838dcc2SGuneshwor Singh 				 CNL_ADSPIC_IPC, CNL_ADSPIC_IPC);
224a838dcc2SGuneshwor Singh }
225a838dcc2SGuneshwor Singh 
cnl_ipc_int_disable(struct sst_dsp * ctx)226a838dcc2SGuneshwor Singh void cnl_ipc_int_disable(struct sst_dsp *ctx)
227a838dcc2SGuneshwor Singh {
228a838dcc2SGuneshwor Singh 	sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPIC,
229a838dcc2SGuneshwor Singh 					  CNL_ADSPIC_IPC, 0);
230a838dcc2SGuneshwor Singh }
231a838dcc2SGuneshwor Singh 
cnl_ipc_op_int_enable(struct sst_dsp * ctx)232a838dcc2SGuneshwor Singh void cnl_ipc_op_int_enable(struct sst_dsp *ctx)
233a838dcc2SGuneshwor Singh {
234a838dcc2SGuneshwor Singh 	/* enable IPC DONE interrupt */
235a838dcc2SGuneshwor Singh 	sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
236a838dcc2SGuneshwor Singh 				 CNL_ADSP_REG_HIPCCTL_DONE,
237a838dcc2SGuneshwor Singh 				 CNL_ADSP_REG_HIPCCTL_DONE);
238a838dcc2SGuneshwor Singh 
239a838dcc2SGuneshwor Singh 	/* enable IPC BUSY interrupt */
240a838dcc2SGuneshwor Singh 	sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
241a838dcc2SGuneshwor Singh 				 CNL_ADSP_REG_HIPCCTL_BUSY,
242a838dcc2SGuneshwor Singh 				 CNL_ADSP_REG_HIPCCTL_BUSY);
243a838dcc2SGuneshwor Singh }
244a838dcc2SGuneshwor Singh 
cnl_ipc_op_int_disable(struct sst_dsp * ctx)245a838dcc2SGuneshwor Singh void cnl_ipc_op_int_disable(struct sst_dsp *ctx)
246a838dcc2SGuneshwor Singh {
247a838dcc2SGuneshwor Singh 	/* disable IPC DONE interrupt */
248a838dcc2SGuneshwor Singh 	sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
249a838dcc2SGuneshwor Singh 				 CNL_ADSP_REG_HIPCCTL_DONE, 0);
250a838dcc2SGuneshwor Singh 
251a838dcc2SGuneshwor Singh 	/* disable IPC BUSY interrupt */
252a838dcc2SGuneshwor Singh 	sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
253a838dcc2SGuneshwor Singh 				 CNL_ADSP_REG_HIPCCTL_BUSY, 0);
254a838dcc2SGuneshwor Singh }
255a838dcc2SGuneshwor Singh 
cnl_ipc_int_status(struct sst_dsp * ctx)256a838dcc2SGuneshwor Singh bool cnl_ipc_int_status(struct sst_dsp *ctx)
257a838dcc2SGuneshwor Singh {
258a838dcc2SGuneshwor Singh 	return sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS) &
259a838dcc2SGuneshwor Singh 							CNL_ADSPIS_IPC;
260a838dcc2SGuneshwor Singh }
261a838dcc2SGuneshwor Singh 
cnl_ipc_free(struct sst_generic_ipc * ipc)262a838dcc2SGuneshwor Singh void cnl_ipc_free(struct sst_generic_ipc *ipc)
263a838dcc2SGuneshwor Singh {
264a838dcc2SGuneshwor Singh 	cnl_ipc_op_int_disable(ipc->dsp);
265a838dcc2SGuneshwor Singh 	sst_ipc_fini(ipc);
266a838dcc2SGuneshwor Singh }
267