~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/intel/skylake/cnl-sst-dsp.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php