1 // SPDX-License-Identifier: GPL-2.0-only
3 * cnl-sst-dsp.c - CNL SST library generic function
5 * Copyright (C) 2016-17, Intel Corporation.
6 * Author: Guneshwor Singh <guneshwor.o.singh@intel.com>
9 * SKL SST library generic function
10 * Copyright (C) 2014-15, Intel Corporation.
11 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
15 #include <linux/device.h>
16 #include "../common/sst-dsp.h"
17 #include "../common/sst-ipc.h"
18 #include "../common/sst-dsp-priv.h"
19 #include "cnl-sst-dsp.h"
21 /* various timeout values */
22 #define CNL_DSP_PU_TO 50
23 #define CNL_DSP_PD_TO 50
24 #define CNL_DSP_RESET_TO 50
27 cnl_dsp_core_set_reset_state(struct sst_dsp
*ctx
, unsigned int core_mask
)
30 sst_dsp_shim_update_bits_unlocked(ctx
,
31 CNL_ADSP_REG_ADSPCS
, CNL_ADSPCS_CRST(core_mask
),
32 CNL_ADSPCS_CRST(core_mask
));
34 /* poll with timeout to check if operation successful */
35 return sst_dsp_register_poll(ctx
,
37 CNL_ADSPCS_CRST(core_mask
),
38 CNL_ADSPCS_CRST(core_mask
),
44 cnl_dsp_core_unset_reset_state(struct sst_dsp
*ctx
, unsigned int core_mask
)
47 sst_dsp_shim_update_bits_unlocked(ctx
, CNL_ADSP_REG_ADSPCS
,
48 CNL_ADSPCS_CRST(core_mask
), 0);
50 /* poll with timeout to check if operation successful */
51 return sst_dsp_register_poll(ctx
,
53 CNL_ADSPCS_CRST(core_mask
),
59 static bool is_cnl_dsp_core_enable(struct sst_dsp
*ctx
, unsigned int core_mask
)
64 val
= sst_dsp_shim_read_unlocked(ctx
, CNL_ADSP_REG_ADSPCS
);
66 is_enable
= (val
& CNL_ADSPCS_CPA(core_mask
)) &&
67 (val
& CNL_ADSPCS_SPA(core_mask
)) &&
68 !(val
& CNL_ADSPCS_CRST(core_mask
)) &&
69 !(val
& CNL_ADSPCS_CSTALL(core_mask
));
71 dev_dbg(ctx
->dev
, "DSP core(s) enabled? %d: core_mask %#x\n",
72 is_enable
, core_mask
);
77 static int cnl_dsp_reset_core(struct sst_dsp
*ctx
, unsigned int core_mask
)
80 sst_dsp_shim_update_bits_unlocked(ctx
, CNL_ADSP_REG_ADSPCS
,
81 CNL_ADSPCS_CSTALL(core_mask
),
82 CNL_ADSPCS_CSTALL(core_mask
));
85 return cnl_dsp_core_set_reset_state(ctx
, core_mask
);
88 static int cnl_dsp_start_core(struct sst_dsp
*ctx
, unsigned int core_mask
)
92 /* unset reset state */
93 ret
= cnl_dsp_core_unset_reset_state(ctx
, core_mask
);
98 sst_dsp_shim_update_bits_unlocked(ctx
, CNL_ADSP_REG_ADSPCS
,
99 CNL_ADSPCS_CSTALL(core_mask
), 0);
101 if (!is_cnl_dsp_core_enable(ctx
, core_mask
)) {
102 cnl_dsp_reset_core(ctx
, core_mask
);
103 dev_err(ctx
->dev
, "DSP core mask %#x enable failed\n",
111 static int cnl_dsp_core_power_up(struct sst_dsp
*ctx
, unsigned int core_mask
)
114 sst_dsp_shim_update_bits_unlocked(ctx
, CNL_ADSP_REG_ADSPCS
,
115 CNL_ADSPCS_SPA(core_mask
),
116 CNL_ADSPCS_SPA(core_mask
));
118 /* poll with timeout to check if operation successful */
119 return sst_dsp_register_poll(ctx
, CNL_ADSP_REG_ADSPCS
,
120 CNL_ADSPCS_CPA(core_mask
),
121 CNL_ADSPCS_CPA(core_mask
),
126 static int cnl_dsp_core_power_down(struct sst_dsp
*ctx
, unsigned int core_mask
)
129 sst_dsp_shim_update_bits_unlocked(ctx
, CNL_ADSP_REG_ADSPCS
,
130 CNL_ADSPCS_SPA(core_mask
), 0);
132 /* poll with timeout to check if operation successful */
133 return sst_dsp_register_poll(ctx
,
135 CNL_ADSPCS_CPA(core_mask
),
141 int cnl_dsp_enable_core(struct sst_dsp
*ctx
, unsigned int core_mask
)
146 ret
= cnl_dsp_core_power_up(ctx
, core_mask
);
148 dev_dbg(ctx
->dev
, "DSP core mask %#x power up failed",
153 return cnl_dsp_start_core(ctx
, core_mask
);
156 int cnl_dsp_disable_core(struct sst_dsp
*ctx
, unsigned int core_mask
)
160 ret
= cnl_dsp_reset_core(ctx
, core_mask
);
162 dev_err(ctx
->dev
, "DSP core mask %#x reset failed\n",
168 ret
= cnl_dsp_core_power_down(ctx
, core_mask
);
170 dev_err(ctx
->dev
, "DSP core mask %#x power down failed\n",
175 if (is_cnl_dsp_core_enable(ctx
, core_mask
)) {
176 dev_err(ctx
->dev
, "DSP core mask %#x disable failed\n",
184 irqreturn_t
cnl_dsp_sst_interrupt(int irq
, void *dev_id
)
186 struct sst_dsp
*ctx
= dev_id
;
188 irqreturn_t ret
= IRQ_NONE
;
190 spin_lock(&ctx
->spinlock
);
192 val
= sst_dsp_shim_read_unlocked(ctx
, CNL_ADSP_REG_ADSPIS
);
193 ctx
->intr_status
= val
;
195 if (val
== 0xffffffff) {
196 spin_unlock(&ctx
->spinlock
);
200 if (val
& CNL_ADSPIS_IPC
) {
201 cnl_ipc_int_disable(ctx
);
202 ret
= IRQ_WAKE_THREAD
;
205 spin_unlock(&ctx
->spinlock
);
210 void cnl_dsp_free(struct sst_dsp
*dsp
)
212 cnl_ipc_int_disable(dsp
);
214 free_irq(dsp
->irq
, dsp
);
215 cnl_ipc_op_int_disable(dsp
);
216 cnl_dsp_disable_core(dsp
, SKL_DSP_CORE0_MASK
);
218 EXPORT_SYMBOL_GPL(cnl_dsp_free
);
220 void cnl_ipc_int_enable(struct sst_dsp
*ctx
)
222 sst_dsp_shim_update_bits(ctx
, CNL_ADSP_REG_ADSPIC
,
223 CNL_ADSPIC_IPC
, CNL_ADSPIC_IPC
);
226 void cnl_ipc_int_disable(struct sst_dsp
*ctx
)
228 sst_dsp_shim_update_bits_unlocked(ctx
, CNL_ADSP_REG_ADSPIC
,
232 void cnl_ipc_op_int_enable(struct sst_dsp
*ctx
)
234 /* enable IPC DONE interrupt */
235 sst_dsp_shim_update_bits(ctx
, CNL_ADSP_REG_HIPCCTL
,
236 CNL_ADSP_REG_HIPCCTL_DONE
,
237 CNL_ADSP_REG_HIPCCTL_DONE
);
239 /* enable IPC BUSY interrupt */
240 sst_dsp_shim_update_bits(ctx
, CNL_ADSP_REG_HIPCCTL
,
241 CNL_ADSP_REG_HIPCCTL_BUSY
,
242 CNL_ADSP_REG_HIPCCTL_BUSY
);
245 void cnl_ipc_op_int_disable(struct sst_dsp
*ctx
)
247 /* disable IPC DONE interrupt */
248 sst_dsp_shim_update_bits(ctx
, CNL_ADSP_REG_HIPCCTL
,
249 CNL_ADSP_REG_HIPCCTL_DONE
, 0);
251 /* disable IPC BUSY interrupt */
252 sst_dsp_shim_update_bits(ctx
, CNL_ADSP_REG_HIPCCTL
,
253 CNL_ADSP_REG_HIPCCTL_BUSY
, 0);
256 bool cnl_ipc_int_status(struct sst_dsp
*ctx
)
258 return sst_dsp_shim_read_unlocked(ctx
, CNL_ADSP_REG_ADSPIS
) &
262 void cnl_ipc_free(struct sst_generic_ipc
*ipc
)
264 cnl_ipc_op_int_disable(ipc
->dsp
);