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

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

Version: ~ [ linux-5.1-rc5 ] ~ [ linux-5.0.7 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.34 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.111 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.168 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.178 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.138 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.65 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp