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