2 * cnl-sst-dsp.c - CNL SST library generic function
4 * Copyright (C) 2016-17, Intel Corporation.
5 * Author: Guneshwor Singh <guneshwor.o.singh@intel.com>
8 * SKL SST library generic function
9 * Copyright (C) 2014-15, Intel Corporation.
10 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as version 2, as
14 * published by the Free Software Foundation.
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
21 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 #include <linux/device.h>
24 #include "../common/sst-dsp.h"
25 #include "../common/sst-ipc.h"
26 #include "../common/sst-dsp-priv.h"
27 #include "cnl-sst-dsp.h"
29 /* various timeout values */
30 #define CNL_DSP_PU_TO 50
31 #define CNL_DSP_PD_TO 50
32 #define CNL_DSP_RESET_TO 50
35 cnl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
38 sst_dsp_shim_update_bits_unlocked(ctx,
39 CNL_ADSP_REG_ADSPCS, CNL_ADSPCS_CRST(core_mask),
40 CNL_ADSPCS_CRST(core_mask));
42 /* poll with timeout to check if operation successful */
43 return sst_dsp_register_poll(ctx,
45 CNL_ADSPCS_CRST(core_mask),
46 CNL_ADSPCS_CRST(core_mask),
52 cnl_dsp_core_unset_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
55 sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
56 CNL_ADSPCS_CRST(core_mask), 0);
58 /* poll with timeout to check if operation successful */
59 return sst_dsp_register_poll(ctx,
61 CNL_ADSPCS_CRST(core_mask),
67 static bool is_cnl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask)
72 val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPCS);
74 is_enable = (val & CNL_ADSPCS_CPA(core_mask)) &&
75 (val & CNL_ADSPCS_SPA(core_mask)) &&
76 !(val & CNL_ADSPCS_CRST(core_mask)) &&
77 !(val & CNL_ADSPCS_CSTALL(core_mask));
79 dev_dbg(ctx->dev, "DSP core(s) enabled? %d: core_mask %#x\n",
80 is_enable, core_mask);
85 static int cnl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask)
88 sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
89 CNL_ADSPCS_CSTALL(core_mask),
90 CNL_ADSPCS_CSTALL(core_mask));
93 return cnl_dsp_core_set_reset_state(ctx, core_mask);
96 static int cnl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask)
100 /* unset reset state */
101 ret = cnl_dsp_core_unset_reset_state(ctx, core_mask);
106 sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
107 CNL_ADSPCS_CSTALL(core_mask), 0);
109 if (!is_cnl_dsp_core_enable(ctx, core_mask)) {
110 cnl_dsp_reset_core(ctx, core_mask);
111 dev_err(ctx->dev, "DSP core mask %#x enable failed\n",
119 static int cnl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask)
122 sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
123 CNL_ADSPCS_SPA(core_mask),
124 CNL_ADSPCS_SPA(core_mask));
126 /* poll with timeout to check if operation successful */
127 return sst_dsp_register_poll(ctx, CNL_ADSP_REG_ADSPCS,
128 CNL_ADSPCS_CPA(core_mask),
129 CNL_ADSPCS_CPA(core_mask),
134 static int cnl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask)
137 sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
138 CNL_ADSPCS_SPA(core_mask), 0);
140 /* poll with timeout to check if operation successful */
141 return sst_dsp_register_poll(ctx,
143 CNL_ADSPCS_CPA(core_mask),
149 int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask)
154 ret = cnl_dsp_core_power_up(ctx, core_mask);
156 dev_dbg(ctx->dev, "DSP core mask %#x power up failed",
161 return cnl_dsp_start_core(ctx, core_mask);
164 int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask)
168 ret = cnl_dsp_reset_core(ctx, core_mask);
170 dev_err(ctx->dev, "DSP core mask %#x reset failed\n",
176 ret = cnl_dsp_core_power_down(ctx, core_mask);
178 dev_err(ctx->dev, "DSP core mask %#x power down failed\n",
183 if (is_cnl_dsp_core_enable(ctx, core_mask)) {
184 dev_err(ctx->dev, "DSP core mask %#x disable failed\n",
192 irqreturn_t cnl_dsp_sst_interrupt(int irq, void *dev_id)
194 struct sst_dsp *ctx = dev_id;
196 irqreturn_t ret = IRQ_NONE;
198 spin_lock(&ctx->spinlock);
200 val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS);
201 ctx->intr_status = val;
203 if (val == 0xffffffff) {
204 spin_unlock(&ctx->spinlock);
208 if (val & CNL_ADSPIS_IPC) {
209 cnl_ipc_int_disable(ctx);
210 ret = IRQ_WAKE_THREAD;
213 spin_unlock(&ctx->spinlock);
218 void cnl_dsp_free(struct sst_dsp *dsp)
220 cnl_ipc_int_disable(dsp);
222 free_irq(dsp->irq, dsp);
223 cnl_ipc_op_int_disable(dsp);
224 cnl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK);
226 EXPORT_SYMBOL_GPL(cnl_dsp_free);
228 void cnl_ipc_int_enable(struct sst_dsp *ctx)
230 sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_ADSPIC,
231 CNL_ADSPIC_IPC, CNL_ADSPIC_IPC);
234 void cnl_ipc_int_disable(struct sst_dsp *ctx)
236 sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPIC,
240 void cnl_ipc_op_int_enable(struct sst_dsp *ctx)
242 /* enable IPC DONE interrupt */
243 sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
244 CNL_ADSP_REG_HIPCCTL_DONE,
245 CNL_ADSP_REG_HIPCCTL_DONE);
247 /* enable IPC BUSY interrupt */
248 sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
249 CNL_ADSP_REG_HIPCCTL_BUSY,
250 CNL_ADSP_REG_HIPCCTL_BUSY);
253 void cnl_ipc_op_int_disable(struct sst_dsp *ctx)
255 /* disable IPC DONE interrupt */
256 sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
257 CNL_ADSP_REG_HIPCCTL_DONE, 0);
259 /* disable IPC BUSY interrupt */
260 sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
261 CNL_ADSP_REG_HIPCCTL_BUSY, 0);
264 bool cnl_ipc_int_status(struct sst_dsp *ctx)
266 return sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS) &
270 void cnl_ipc_free(struct sst_generic_ipc *ipc)
272 cnl_ipc_op_int_disable(ipc->dsp);