aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJayachandran B <jayachandran.b@intel.com>2016-06-21 00:47:41 -0400
committerMark Brown <broonie@kernel.org>2016-06-22 11:13:12 -0400
commit052f103c89aa8ff6a72a4cadc0a5471cc8bc4c93 (patch)
treeba87d20ce1e7d7bf43d2460a4c6f63c66992c7a5
parent957427d94a82459b080a99cc7e9f4d5b8c067410 (diff)
ASoC: Intel: Skylake: Add DSP muti-core infrastructure
The DSP can have more than one cores. In that case the secondary core has to be managed by the driver. This patch adds the changes to driver infrastructure to support multiple core. A new object skl_dsp_cores is introduced to support multiple core. Helpers skl_dsp_get_core() skl_dsp_put_core() help to managed the cores. Many of the power_up/down and DSP APIs take additional argument of core_id. The primary core, 0 is always powered up first and then on demand second core. Signed-off-by: Jayachandran B <jayachandran.b@intel.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/intel/skylake/bxt-sst.c22
-rw-r--r--sound/soc/intel/skylake/skl-sst-dsp.c253
-rw-r--r--sound/soc/intel/skylake/skl-sst-dsp.h96
-rw-r--r--sound/soc/intel/skylake/skl-sst-ipc.h11
-rw-r--r--sound/soc/intel/skylake/skl-sst.c16
5 files changed, 278 insertions, 120 deletions
diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c
index 622da5d3e3b3..c6cc1cfd04c8 100644
--- a/sound/soc/intel/skylake/bxt-sst.c
+++ b/sound/soc/intel/skylake/bxt-sst.c
@@ -58,7 +58,7 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
58 ctx->dsp_ops.stream_tag = stream_tag; 58 ctx->dsp_ops.stream_tag = stream_tag;
59 memcpy(ctx->dmab.area, fwdata, fwsize); 59 memcpy(ctx->dmab.area, fwdata, fwsize);
60 60
61 ret = skl_dsp_core_power_up(ctx); 61 ret = skl_dsp_core_power_up(ctx, SKL_DSP_CORE0_MASK);
62 if (ret < 0) { 62 if (ret < 0) {
63 dev_err(ctx->dev, "Boot dsp core failed ret: %d\n", ret); 63 dev_err(ctx->dev, "Boot dsp core failed ret: %d\n", ret);
64 goto base_fw_load_failed; 64 goto base_fw_load_failed;
@@ -68,7 +68,7 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
68 sst_dsp_shim_write(ctx, SKL_ADSP_REG_HIPCI, SKL_ADSP_REG_HIPCI_BUSY | 68 sst_dsp_shim_write(ctx, SKL_ADSP_REG_HIPCI, SKL_ADSP_REG_HIPCI_BUSY |
69 (BXT_IPC_PURGE_FW | ((stream_tag - 1) << 9))); 69 (BXT_IPC_PURGE_FW | ((stream_tag - 1) << 9)));
70 70
71 ret = skl_dsp_start_core(ctx); 71 ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK);
72 if (ret < 0) { 72 if (ret < 0) {
73 dev_err(ctx->dev, "Start dsp core failed ret: %d\n", ret); 73 dev_err(ctx->dev, "Start dsp core failed ret: %d\n", ret);
74 ret = -EIO; 74 ret = -EIO;
@@ -118,7 +118,8 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
118 118
119base_fw_load_failed: 119base_fw_load_failed:
120 ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, stream_tag); 120 ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, stream_tag);
121 skl_dsp_disable_core(ctx); 121 skl_dsp_core_power_down(ctx, SKL_DSP_CORE_MASK(1));
122 skl_dsp_disable_core(ctx, SKL_DSP_CORE_MASK(1));
122 return ret; 123 return ret;
123} 124}
124 125
@@ -183,14 +184,14 @@ static int bxt_load_base_firmware(struct sst_dsp *ctx)
183 sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE), 184 sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE),
184 sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS)); 185 sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS));
185 186
186 skl_dsp_disable_core(ctx); 187 skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
187 } else { 188 } else {
188 dev_dbg(ctx->dev, "Firmware download successful\n"); 189 dev_dbg(ctx->dev, "Firmware download successful\n");
189 ret = wait_event_timeout(skl->boot_wait, skl->boot_complete, 190 ret = wait_event_timeout(skl->boot_wait, skl->boot_complete,
190 msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); 191 msecs_to_jiffies(SKL_IPC_BOOT_MSECS));
191 if (ret == 0) { 192 if (ret == 0) {
192 dev_err(ctx->dev, "DSP boot fail, FW Ready timeout\n"); 193 dev_err(ctx->dev, "DSP boot fail, FW Ready timeout\n");
193 skl_dsp_disable_core(ctx); 194 skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
194 ret = -EIO; 195 ret = -EIO;
195 } else { 196 } else {
196 skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING); 197 skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING);
@@ -204,7 +205,7 @@ sst_load_base_firmware_failed:
204 return ret; 205 return ret;
205} 206}
206 207
207static int bxt_set_dsp_D0(struct sst_dsp *ctx) 208static int bxt_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id)
208{ 209{
209 struct skl_sst *skl = ctx->thread_context; 210 struct skl_sst *skl = ctx->thread_context;
210 int ret; 211 int ret;
@@ -219,7 +220,7 @@ static int bxt_set_dsp_D0(struct sst_dsp *ctx)
219 return ret; 220 return ret;
220 } 221 }
221 222
222 ret = skl_dsp_enable_core(ctx); 223 ret = skl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK);
223 if (ret < 0) { 224 if (ret < 0) {
224 dev_err(ctx->dev, "enable dsp core failed ret: %d\n", ret); 225 dev_err(ctx->dev, "enable dsp core failed ret: %d\n", ret);
225 return ret; 226 return ret;
@@ -243,7 +244,7 @@ static int bxt_set_dsp_D0(struct sst_dsp *ctx)
243 return 0; 244 return 0;
244} 245}
245 246
246static int bxt_set_dsp_D3(struct sst_dsp *ctx) 247static int bxt_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id)
247{ 248{
248 struct skl_ipc_dxstate_info dx; 249 struct skl_ipc_dxstate_info dx;
249 struct skl_sst *skl = ctx->thread_context; 250 struct skl_sst *skl = ctx->thread_context;
@@ -262,7 +263,7 @@ static int bxt_set_dsp_D3(struct sst_dsp *ctx)
262 return ret; 263 return ret;
263 } 264 }
264 265
265 ret = skl_dsp_disable_core(ctx); 266 ret = skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
266 if (ret < 0) { 267 if (ret < 0) {
267 dev_err(ctx->dev, "disbale dsp core failed: %d\n", ret); 268 dev_err(ctx->dev, "disbale dsp core failed: %d\n", ret);
268 ret = -EIO; 269 ret = -EIO;
@@ -329,6 +330,7 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
329 if (ret) 330 if (ret)
330 return ret; 331 return ret;
331 332
333 skl->cores.count = 2;
332 skl->boot_complete = false; 334 skl->boot_complete = false;
333 init_waitqueue_head(&skl->boot_wait); 335 init_waitqueue_head(&skl->boot_wait);
334 336
@@ -338,6 +340,8 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
338 return ret; 340 return ret;
339 } 341 }
340 342
343 skl_dsp_init_core_state(sst);
344
341 if (dsp) 345 if (dsp)
342 *dsp = skl; 346 *dsp = skl;
343 347
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.c b/sound/soc/intel/skylake/skl-sst-dsp.c
index 33c45aa53532..c3deefab65d6 100644
--- a/sound/soc/intel/skylake/skl-sst-dsp.c
+++ b/sound/soc/intel/skylake/skl-sst-dsp.c
@@ -34,33 +34,84 @@ void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state)
34 mutex_unlock(&ctx->mutex); 34 mutex_unlock(&ctx->mutex);
35} 35}
36 36
37static int skl_dsp_core_set_reset_state(struct sst_dsp *ctx) 37/*
38 * Initialize core power state and usage count. To be called after
39 * successful first boot. Hence core 0 will be running and other cores
40 * will be reset
41 */
42void skl_dsp_init_core_state(struct sst_dsp *ctx)
43{
44 struct skl_sst *skl = ctx->thread_context;
45 int i;
46
47 skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING;
48 skl->cores.usage_count[SKL_DSP_CORE0_ID] = 1;
49
50 for (i = SKL_DSP_CORE0_ID + 1; i < SKL_DSP_CORES_MAX; i++) {
51 skl->cores.state[i] = SKL_DSP_RESET;
52 skl->cores.usage_count[i] = 0;
53 }
54}
55
56/* Get the mask for all enabled cores */
57unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx)
58{
59 struct skl_sst *skl = ctx->thread_context;
60 unsigned int core_mask, en_cores_mask;
61 u32 val;
62
63 core_mask = SKL_DSP_CORES_MASK(skl->cores.count);
64
65 val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS);
66
67 /* Cores having CPA bit set */
68 en_cores_mask = (val & SKL_ADSPCS_CPA_MASK(core_mask)) >>
69 SKL_ADSPCS_CPA_SHIFT;
70
71 /* And cores having CRST bit cleared */
72 en_cores_mask &= (~val & SKL_ADSPCS_CRST_MASK(core_mask)) >>
73 SKL_ADSPCS_CRST_SHIFT;
74
75 /* And cores having CSTALL bit cleared */
76 en_cores_mask &= (~val & SKL_ADSPCS_CSTALL_MASK(core_mask)) >>
77 SKL_ADSPCS_CSTALL_SHIFT;
78 en_cores_mask &= core_mask;
79
80 dev_dbg(ctx->dev, "DSP enabled cores mask = %x\n", en_cores_mask);
81
82 return en_cores_mask;
83}
84
85static int
86skl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
38{ 87{
39 int ret; 88 int ret;
40 89
41 /* update bits */ 90 /* update bits */
42 sst_dsp_shim_update_bits_unlocked(ctx, 91 sst_dsp_shim_update_bits_unlocked(ctx,
43 SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK, 92 SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK(core_mask),
44 SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)); 93 SKL_ADSPCS_CRST_MASK(core_mask));
45 94
46 /* poll with timeout to check if operation successful */ 95 /* poll with timeout to check if operation successful */
47 ret = sst_dsp_register_poll(ctx, 96 ret = sst_dsp_register_poll(ctx,
48 SKL_ADSP_REG_ADSPCS, 97 SKL_ADSP_REG_ADSPCS,
49 SKL_ADSPCS_CRST_MASK, 98 SKL_ADSPCS_CRST_MASK(core_mask),
50 SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK), 99 SKL_ADSPCS_CRST_MASK(core_mask),
51 SKL_DSP_RESET_TO, 100 SKL_DSP_RESET_TO,
52 "Set reset"); 101 "Set reset");
53 if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 102 if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
54 SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) != 103 SKL_ADSPCS_CRST_MASK(core_mask)) !=
55 SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) { 104 SKL_ADSPCS_CRST_MASK(core_mask)) {
56 dev_err(ctx->dev, "Set reset state failed\n"); 105 dev_err(ctx->dev, "Set reset state failed: core_mask %x\n",
106 core_mask);
57 ret = -EIO; 107 ret = -EIO;
58 } 108 }
59 109
60 return ret; 110 return ret;
61} 111}
62 112
63static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx) 113int skl_dsp_core_unset_reset_state(
114 struct sst_dsp *ctx, unsigned int core_mask)
64{ 115{
65 int ret; 116 int ret;
66 117
@@ -68,151 +119,160 @@ static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx)
68 119
69 /* update bits */ 120 /* update bits */
70 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 121 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
71 SKL_ADSPCS_CRST_MASK, 0); 122 SKL_ADSPCS_CRST_MASK(core_mask), 0);
72 123
73 /* poll with timeout to check if operation successful */ 124 /* poll with timeout to check if operation successful */
74 ret = sst_dsp_register_poll(ctx, 125 ret = sst_dsp_register_poll(ctx,
75 SKL_ADSP_REG_ADSPCS, 126 SKL_ADSP_REG_ADSPCS,
76 SKL_ADSPCS_CRST_MASK, 127 SKL_ADSPCS_CRST_MASK(core_mask),
77 0, 128 0,
78 SKL_DSP_RESET_TO, 129 SKL_DSP_RESET_TO,
79 "Unset reset"); 130 "Unset reset");
80 131
81 if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 132 if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
82 SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) != 0) { 133 SKL_ADSPCS_CRST_MASK(core_mask)) != 0) {
83 dev_err(ctx->dev, "Unset reset state failed\n"); 134 dev_err(ctx->dev, "Unset reset state failed: core_mask %x\n",
135 core_mask);
84 ret = -EIO; 136 ret = -EIO;
85 } 137 }
86 138
87 return ret; 139 return ret;
88} 140}
89 141
90static bool is_skl_dsp_core_enable(struct sst_dsp *ctx) 142static bool
143is_skl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask)
91{ 144{
92 int val; 145 int val;
93 bool is_enable; 146 bool is_enable;
94 147
95 val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS); 148 val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS);
96 149
97 is_enable = ((val & SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) && 150 is_enable = ((val & SKL_ADSPCS_CPA_MASK(core_mask)) &&
98 (val & SKL_ADSPCS_SPA(SKL_DSP_CORES_MASK)) && 151 (val & SKL_ADSPCS_SPA_MASK(core_mask)) &&
99 !(val & SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) && 152 !(val & SKL_ADSPCS_CRST_MASK(core_mask)) &&
100 !(val & SKL_ADSPCS_CSTALL(SKL_DSP_CORES_MASK))); 153 !(val & SKL_ADSPCS_CSTALL_MASK(core_mask)));
154
155 dev_dbg(ctx->dev, "DSP core(s) enabled? %d : core_mask %x\n",
156 is_enable, core_mask);
101 157
102 dev_dbg(ctx->dev, "DSP core is enabled=%d\n", is_enable);
103 return is_enable; 158 return is_enable;
104} 159}
105 160
106static int skl_dsp_reset_core(struct sst_dsp *ctx) 161static int skl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask)
107{ 162{
108 /* stall core */ 163 /* stall core */
109 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 164 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
110 SKL_ADSPCS_CSTALL_MASK, 165 SKL_ADSPCS_CSTALL_MASK(core_mask),
111 SKL_ADSPCS_CSTALL(SKL_DSP_CORES_MASK)); 166 SKL_ADSPCS_CSTALL_MASK(core_mask));
112 167
113 /* set reset state */ 168 /* set reset state */
114 return skl_dsp_core_set_reset_state(ctx); 169 return skl_dsp_core_set_reset_state(ctx, core_mask);
115} 170}
116 171
117int skl_dsp_start_core(struct sst_dsp *ctx) 172int skl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask)
118{ 173{
119 int ret; 174 int ret;
120 175
121 /* unset reset state */ 176 /* unset reset state */
122 ret = skl_dsp_core_unset_reset_state(ctx); 177 ret = skl_dsp_core_unset_reset_state(ctx, core_mask);
123 if (ret < 0) { 178 if (ret < 0)
124 dev_dbg(ctx->dev, "dsp unset reset fails\n");
125 return ret; 179 return ret;
126 }
127 180
128 /* run core */ 181 /* run core */
129 dev_dbg(ctx->dev, "run core...\n"); 182 dev_dbg(ctx->dev, "unstall/run core: core_mask = %x\n", core_mask);
130 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 183 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
131 SKL_ADSPCS_CSTALL_MASK, 0); 184 SKL_ADSPCS_CSTALL_MASK(core_mask), 0);
132 185
133 if (!is_skl_dsp_core_enable(ctx)) { 186 if (!is_skl_dsp_core_enable(ctx, core_mask)) {
134 skl_dsp_reset_core(ctx); 187 skl_dsp_reset_core(ctx, core_mask);
135 dev_err(ctx->dev, "DSP core enable failed\n"); 188 dev_err(ctx->dev, "DSP start core failed: core_mask %x\n",
189 core_mask);
136 ret = -EIO; 190 ret = -EIO;
137 } 191 }
138 192
139 return ret; 193 return ret;
140} 194}
141 195
142int skl_dsp_core_power_up(struct sst_dsp *ctx) 196int skl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask)
143{ 197{
144 int ret; 198 int ret;
145 199
146 /* update bits */ 200 /* update bits */
147 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 201 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
148 SKL_ADSPCS_SPA_MASK, SKL_ADSPCS_SPA(SKL_DSP_CORES_MASK)); 202 SKL_ADSPCS_SPA_MASK(core_mask),
203 SKL_ADSPCS_SPA_MASK(core_mask));
149 204
150 /* poll with timeout to check if operation successful */ 205 /* poll with timeout to check if operation successful */
151 ret = sst_dsp_register_poll(ctx, 206 ret = sst_dsp_register_poll(ctx,
152 SKL_ADSP_REG_ADSPCS, 207 SKL_ADSP_REG_ADSPCS,
153 SKL_ADSPCS_CPA_MASK, 208 SKL_ADSPCS_CPA_MASK(core_mask),
154 SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK), 209 SKL_ADSPCS_CPA_MASK(core_mask),
155 SKL_DSP_PU_TO, 210 SKL_DSP_PU_TO,
156 "Power up"); 211 "Power up");
157 212
158 if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 213 if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
159 SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) != 214 SKL_ADSPCS_CPA_MASK(core_mask)) !=
160 SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) { 215 SKL_ADSPCS_CPA_MASK(core_mask)) {
161 dev_err(ctx->dev, "DSP core power up failed\n"); 216 dev_err(ctx->dev, "DSP core power up failed: core_mask %x\n",
217 core_mask);
162 ret = -EIO; 218 ret = -EIO;
163 } 219 }
164 220
165 return ret; 221 return ret;
166} 222}
167 223
168static int skl_dsp_core_power_down(struct sst_dsp *ctx) 224int skl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask)
169{ 225{
170 /* update bits */ 226 /* update bits */
171 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 227 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
172 SKL_ADSPCS_SPA_MASK, 0); 228 SKL_ADSPCS_SPA_MASK(core_mask), 0);
173 229
174 /* poll with timeout to check if operation successful */ 230 /* poll with timeout to check if operation successful */
175 return sst_dsp_register_poll(ctx, 231 return sst_dsp_register_poll(ctx,
176 SKL_ADSP_REG_ADSPCS, 232 SKL_ADSP_REG_ADSPCS,
177 SKL_ADSPCS_CPA_MASK, 233 SKL_ADSPCS_CPA_MASK(core_mask),
178 0, 234 0,
179 SKL_DSP_PD_TO, 235 SKL_DSP_PD_TO,
180 "Power down"); 236 "Power down");
181} 237}
182 238
183int skl_dsp_enable_core(struct sst_dsp *ctx) 239int skl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask)
184{ 240{
185 int ret; 241 int ret;
186 242
187 /* power up */ 243 /* power up */
188 ret = skl_dsp_core_power_up(ctx); 244 ret = skl_dsp_core_power_up(ctx, core_mask);
189 if (ret < 0) { 245 if (ret < 0) {
190 dev_dbg(ctx->dev, "dsp core power up failed\n"); 246 dev_err(ctx->dev, "dsp core power up failed: core_mask %x\n",
247 core_mask);
191 return ret; 248 return ret;
192 } 249 }
193 250
194 return skl_dsp_start_core(ctx); 251 return skl_dsp_start_core(ctx, core_mask);
195} 252}
196 253
197int skl_dsp_disable_core(struct sst_dsp *ctx) 254int skl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask)
198{ 255{
199 int ret; 256 int ret;
200 257
201 ret = skl_dsp_reset_core(ctx); 258 ret = skl_dsp_reset_core(ctx, core_mask);
202 if (ret < 0) { 259 if (ret < 0) {
203 dev_err(ctx->dev, "dsp core reset failed\n"); 260 dev_err(ctx->dev, "dsp core reset failed: core_mask %x\n",
261 core_mask);
204 return ret; 262 return ret;
205 } 263 }
206 264
207 /* power down core*/ 265 /* power down core*/
208 ret = skl_dsp_core_power_down(ctx); 266 ret = skl_dsp_core_power_down(ctx, core_mask);
209 if (ret < 0) { 267 if (ret < 0) {
210 dev_err(ctx->dev, "dsp core power down failed\n"); 268 dev_err(ctx->dev, "dsp core power down fail mask %x: %d\n",
269 core_mask, ret);
211 return ret; 270 return ret;
212 } 271 }
213 272
214 if (is_skl_dsp_core_enable(ctx)) { 273 if (is_skl_dsp_core_enable(ctx, core_mask)) {
215 dev_err(ctx->dev, "DSP core disable failed\n"); 274 dev_err(ctx->dev, "dsp core disable fail mask %x: %d\n",
275 core_mask, ret);
216 ret = -EIO; 276 ret = -EIO;
217 } 277 }
218 278
@@ -223,28 +283,25 @@ int skl_dsp_boot(struct sst_dsp *ctx)
223{ 283{
224 int ret; 284 int ret;
225 285
226 if (is_skl_dsp_core_enable(ctx)) { 286 if (is_skl_dsp_core_enable(ctx, SKL_DSP_CORE0_MASK)) {
227 dev_dbg(ctx->dev, "dsp core is already enabled, so reset the dap core\n"); 287 ret = skl_dsp_reset_core(ctx, SKL_DSP_CORE0_MASK);
228 ret = skl_dsp_reset_core(ctx);
229 if (ret < 0) { 288 if (ret < 0) {
230 dev_err(ctx->dev, "dsp reset failed\n"); 289 dev_err(ctx->dev, "dsp core0 reset fail: %d\n", ret);
231 return ret; 290 return ret;
232 } 291 }
233 292
234 ret = skl_dsp_start_core(ctx); 293 ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK);
235 if (ret < 0) { 294 if (ret < 0) {
236 dev_err(ctx->dev, "dsp start failed\n"); 295 dev_err(ctx->dev, "dsp core0 start fail: %d\n", ret);
237 return ret; 296 return ret;
238 } 297 }
239 } else { 298 } else {
240 dev_dbg(ctx->dev, "disable and enable to make sure DSP is invalid state\n"); 299 ret = skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
241 ret = skl_dsp_disable_core(ctx);
242
243 if (ret < 0) { 300 if (ret < 0) {
244 dev_err(ctx->dev, "dsp disable core failes\n"); 301 dev_err(ctx->dev, "dsp core0 disable fail: %d\n", ret);
245 return ret; 302 return ret;
246 } 303 }
247 ret = skl_dsp_enable_core(ctx); 304 ret = skl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK);
248 } 305 }
249 306
250 return ret; 307 return ret;
@@ -280,16 +337,74 @@ irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id)
280 337
281 return result; 338 return result;
282} 339}
340/*
341 * skl_dsp_get_core/skl_dsp_put_core will be called inside DAPM context
342 * within the dapm mutex. Hence no separate lock is used.
343 */
344int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id)
345{
346 struct skl_sst *skl = ctx->thread_context;
347 int ret = 0;
348
349 if (core_id >= skl->cores.count) {
350 dev_err(ctx->dev, "invalid core id: %d\n", core_id);
351 return -EINVAL;
352 }
353
354 if (skl->cores.state[core_id] == SKL_DSP_RESET) {
355 ret = ctx->fw_ops.set_state_D0(ctx, core_id);
356 if (ret < 0) {
357 dev_err(ctx->dev, "unable to get core%d\n", core_id);
358 return ret;
359 }
360 }
361
362 skl->cores.usage_count[core_id]++;
363
364 dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n",
365 core_id, skl->cores.state[core_id],
366 skl->cores.usage_count[core_id]);
367
368 return ret;
369}
370EXPORT_SYMBOL_GPL(skl_dsp_get_core);
371
372int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id)
373{
374 struct skl_sst *skl = ctx->thread_context;
375 int ret = 0;
376
377 if (core_id >= skl->cores.count) {
378 dev_err(ctx->dev, "invalid core id: %d\n", core_id);
379 return -EINVAL;
380 }
381
382 if (--skl->cores.usage_count[core_id] == 0) {
383 ret = ctx->fw_ops.set_state_D3(ctx, core_id);
384 if (ret < 0) {
385 dev_err(ctx->dev, "unable to put core %d: %d\n",
386 core_id, ret);
387 skl->cores.usage_count[core_id]++;
388 }
389 }
390
391 dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n",
392 core_id, skl->cores.state[core_id],
393 skl->cores.usage_count[core_id]);
394
395 return ret;
396}
397EXPORT_SYMBOL_GPL(skl_dsp_put_core);
283 398
284int skl_dsp_wake(struct sst_dsp *ctx) 399int skl_dsp_wake(struct sst_dsp *ctx)
285{ 400{
286 return ctx->fw_ops.set_state_D0(ctx); 401 return skl_dsp_get_core(ctx, SKL_DSP_CORE0_ID);
287} 402}
288EXPORT_SYMBOL_GPL(skl_dsp_wake); 403EXPORT_SYMBOL_GPL(skl_dsp_wake);
289 404
290int skl_dsp_sleep(struct sst_dsp *ctx) 405int skl_dsp_sleep(struct sst_dsp *ctx)
291{ 406{
292 return ctx->fw_ops.set_state_D3(ctx); 407 return skl_dsp_put_core(ctx, SKL_DSP_CORE0_ID);
293} 408}
294EXPORT_SYMBOL_GPL(skl_dsp_sleep); 409EXPORT_SYMBOL_GPL(skl_dsp_sleep);
295 410
@@ -336,9 +451,7 @@ void skl_dsp_free(struct sst_dsp *dsp)
336 451
337 free_irq(dsp->irq, dsp); 452 free_irq(dsp->irq, dsp);
338 skl_ipc_op_int_disable(dsp); 453 skl_ipc_op_int_disable(dsp);
339 skl_ipc_int_disable(dsp); 454 skl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK);
340
341 skl_dsp_disable_core(dsp);
342} 455}
343EXPORT_SYMBOL_GPL(skl_dsp_free); 456EXPORT_SYMBOL_GPL(skl_dsp_free);
344 457
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h
index 22fbe1075cb5..0f8629ef79ac 100644
--- a/sound/soc/intel/skylake/skl-sst-dsp.h
+++ b/sound/soc/intel/skylake/skl-sst-dsp.h
@@ -77,35 +77,53 @@ struct sst_dsp_device;
77#define SKL_ADSPIC_IPC 1 77#define SKL_ADSPIC_IPC 1
78#define SKL_ADSPIS_IPC 1 78#define SKL_ADSPIS_IPC 1
79 79
80/* Core ID of core0 */
81#define SKL_DSP_CORE0_ID 0
82
83/* Mask for a given core index, c = 0.. number of supported cores - 1 */
84#define SKL_DSP_CORE_MASK(c) BIT(c)
85
86/*
87 * Core 0 mask = SKL_DSP_CORE_MASK(0); Defined separately
88 * since Core0 is primary core and it is used often
89 */
90#define SKL_DSP_CORE0_MASK BIT(0)
91
92/*
93 * Mask for a given number of cores
94 * nc = number of supported cores
95 */
96#define SKL_DSP_CORES_MASK(nc) GENMASK((nc - 1), 0)
97
80/* ADSPCS - Audio DSP Control & Status */ 98/* ADSPCS - Audio DSP Control & Status */
81#define SKL_DSP_CORES 1 99
82#define SKL_DSP_CORE0_MASK 1 100/*
83#define SKL_DSP_CORES_MASK ((1 << SKL_DSP_CORES) - 1) 101 * Core Reset - asserted high
84 102 * CRST Mask for a given core mask pattern, cm
85/* Core Reset - asserted high */ 103 */
86#define SKL_ADSPCS_CRST_SHIFT 0 104#define SKL_ADSPCS_CRST_SHIFT 0
87#define SKL_ADSPCS_CRST_MASK (SKL_DSP_CORES_MASK << SKL_ADSPCS_CRST_SHIFT) 105#define SKL_ADSPCS_CRST_MASK(cm) ((cm) << SKL_ADSPCS_CRST_SHIFT)
88#define SKL_ADSPCS_CRST(x) ((x << SKL_ADSPCS_CRST_SHIFT) & SKL_ADSPCS_CRST_MASK) 106
89 107/*
90/* Core run/stall - when set to '1' core is stalled */ 108 * Core run/stall - when set to '1' core is stalled
91#define SKL_ADSPCS_CSTALL_SHIFT 8 109 * CSTALL Mask for a given core mask pattern, cm
92#define SKL_ADSPCS_CSTALL_MASK (SKL_DSP_CORES_MASK << \ 110 */
93 SKL_ADSPCS_CSTALL_SHIFT) 111#define SKL_ADSPCS_CSTALL_SHIFT 8
94#define SKL_ADSPCS_CSTALL(x) ((x << SKL_ADSPCS_CSTALL_SHIFT) & \ 112#define SKL_ADSPCS_CSTALL_MASK(cm) ((cm) << SKL_ADSPCS_CSTALL_SHIFT)
95 SKL_ADSPCS_CSTALL_MASK) 113
96 114/*
97/* Set Power Active - when set to '1' turn cores on */ 115 * Set Power Active - when set to '1' turn cores on
98#define SKL_ADSPCS_SPA_SHIFT 16 116 * SPA Mask for a given core mask pattern, cm
99#define SKL_ADSPCS_SPA_MASK (SKL_DSP_CORES_MASK << SKL_ADSPCS_SPA_SHIFT) 117 */
100#define SKL_ADSPCS_SPA(x) ((x << SKL_ADSPCS_SPA_SHIFT) & SKL_ADSPCS_SPA_MASK) 118#define SKL_ADSPCS_SPA_SHIFT 16
101 119#define SKL_ADSPCS_SPA_MASK(cm) ((cm) << SKL_ADSPCS_SPA_SHIFT)
102/* Current Power Active - power status of cores, set by hardware */ 120
103#define SKL_ADSPCS_CPA_SHIFT 24 121/*
104#define SKL_ADSPCS_CPA_MASK (SKL_DSP_CORES_MASK << SKL_ADSPCS_CPA_SHIFT) 122 * Current Power Active - power status of cores, set by hardware
105#define SKL_ADSPCS_CPA(x) ((x << SKL_ADSPCS_CPA_SHIFT) & SKL_ADSPCS_CPA_MASK) 123 * CPA Mask for a given core mask pattern, cm
106 124 */
107#define SST_DSP_POWER_D0 0x0 /* full On */ 125#define SKL_ADSPCS_CPA_SHIFT 24
108#define SST_DSP_POWER_D3 0x3 /* Off */ 126#define SKL_ADSPCS_CPA_MASK(cm) ((cm) << SKL_ADSPCS_CPA_SHIFT)
109 127
110enum skl_dsp_states { 128enum skl_dsp_states {
111 SKL_DSP_RUNNING = 1, 129 SKL_DSP_RUNNING = 1,
@@ -116,8 +134,8 @@ struct skl_dsp_fw_ops {
116 int (*load_fw)(struct sst_dsp *ctx); 134 int (*load_fw)(struct sst_dsp *ctx);
117 /* FW module parser/loader */ 135 /* FW module parser/loader */
118 int (*parse_fw)(struct sst_dsp *ctx); 136 int (*parse_fw)(struct sst_dsp *ctx);
119 int (*set_state_D0)(struct sst_dsp *ctx); 137 int (*set_state_D0)(struct sst_dsp *ctx, unsigned int core_id);
120 int (*set_state_D3)(struct sst_dsp *ctx); 138 int (*set_state_D3)(struct sst_dsp *ctx, unsigned int core_id);
121 unsigned int (*get_fw_errcode)(struct sst_dsp *ctx); 139 unsigned int (*get_fw_errcode)(struct sst_dsp *ctx);
122 int (*load_mod)(struct sst_dsp *ctx, u16 mod_id, u8 *mod_name); 140 int (*load_mod)(struct sst_dsp *ctx, u16 mod_id, u8 *mod_name);
123 int (*unload_mod)(struct sst_dsp *ctx, u16 mod_id); 141 int (*unload_mod)(struct sst_dsp *ctx, u16 mod_id);
@@ -158,14 +176,26 @@ int skl_cldma_prepare(struct sst_dsp *ctx);
158void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state); 176void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state);
159struct sst_dsp *skl_dsp_ctx_init(struct device *dev, 177struct sst_dsp *skl_dsp_ctx_init(struct device *dev,
160 struct sst_dsp_device *sst_dev, int irq); 178 struct sst_dsp_device *sst_dev, int irq);
161int skl_dsp_enable_core(struct sst_dsp *ctx);
162int skl_dsp_disable_core(struct sst_dsp *ctx);
163bool is_skl_dsp_running(struct sst_dsp *ctx); 179bool is_skl_dsp_running(struct sst_dsp *ctx);
180
181unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx);
182void skl_dsp_init_core_state(struct sst_dsp *ctx);
183int skl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask);
184int skl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask);
185int skl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask);
186int skl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask);
187int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx,
188 unsigned int core_mask);
189int skl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask);
190
164irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id); 191irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id);
165int skl_dsp_wake(struct sst_dsp *ctx); 192int skl_dsp_wake(struct sst_dsp *ctx);
166int skl_dsp_sleep(struct sst_dsp *ctx); 193int skl_dsp_sleep(struct sst_dsp *ctx);
167void skl_dsp_free(struct sst_dsp *dsp); 194void skl_dsp_free(struct sst_dsp *dsp);
168 195
196int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id);
197int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id);
198
169int skl_dsp_boot(struct sst_dsp *ctx); 199int skl_dsp_boot(struct sst_dsp *ctx);
170int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, 200int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
171 const char *fw_name, struct skl_dsp_loader_ops dsp_ops, 201 const char *fw_name, struct skl_dsp_loader_ops dsp_ops,
@@ -182,7 +212,5 @@ int snd_skl_parse_uuids(struct sst_dsp *ctx, unsigned int offset);
182void skl_freeup_uuid_list(struct skl_sst *ctx); 212void skl_freeup_uuid_list(struct skl_sst *ctx);
183 213
184int skl_dsp_strip_extended_manifest(struct firmware *fw); 214int skl_dsp_strip_extended_manifest(struct firmware *fw);
185int skl_dsp_start_core(struct sst_dsp *ctx);
186int skl_dsp_core_power_up(struct sst_dsp *ctx);
187 215
188#endif /*__SKL_SST_DSP_H__*/ 216#endif /*__SKL_SST_DSP_H__*/
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h
index 5102c7b415fe..2e3d4e80ef97 100644
--- a/sound/soc/intel/skylake/skl-sst-ipc.h
+++ b/sound/soc/intel/skylake/skl-sst-ipc.h
@@ -45,6 +45,14 @@ struct skl_ipc_header {
45 u32 extension; 45 u32 extension;
46}; 46};
47 47
48#define SKL_DSP_CORES_MAX 2
49
50struct skl_dsp_cores {
51 unsigned int count;
52 enum skl_dsp_states state[SKL_DSP_CORES_MAX];
53 int usage_count[SKL_DSP_CORES_MAX];
54};
55
48struct skl_sst { 56struct skl_sst {
49 struct device *dev; 57 struct device *dev;
50 struct sst_dsp *dsp; 58 struct sst_dsp *dsp;
@@ -66,6 +74,9 @@ struct skl_sst {
66 74
67 /* Is firmware loaded */ 75 /* Is firmware loaded */
68 bool fw_loaded; 76 bool fw_loaded;
77
78 /* multi-core */
79 struct skl_dsp_cores cores;
69}; 80};
70 81
71struct skl_ipc_init_instance_msg { 82struct skl_ipc_init_instance_msg {
diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c
index eaf0c9d19782..ecaca94d2a96 100644
--- a/sound/soc/intel/skylake/skl-sst.c
+++ b/sound/soc/intel/skylake/skl-sst.c
@@ -84,10 +84,8 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
84 ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev); 84 ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev);
85 if (ret < 0) { 85 if (ret < 0) {
86 dev_err(ctx->dev, "Request firmware failed %d\n", ret); 86 dev_err(ctx->dev, "Request firmware failed %d\n", ret);
87 skl_dsp_disable_core(ctx);
88 return -EIO; 87 return -EIO;
89 } 88 }
90
91 } 89 }
92 90
93 ret = snd_skl_parse_uuids(ctx, SKL_ADSP_FW_BIN_HDR_OFFSET); 91 ret = snd_skl_parse_uuids(ctx, SKL_ADSP_FW_BIN_HDR_OFFSET);
@@ -95,7 +93,7 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
95 dev_err(ctx->dev, 93 dev_err(ctx->dev,
96 "UUID parsing err: %d\n", ret); 94 "UUID parsing err: %d\n", ret);
97 release_firmware(ctx->fw); 95 release_firmware(ctx->fw);
98 skl_dsp_disable_core(ctx); 96 skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
99 return ret; 97 return ret;
100 } 98 }
101 99
@@ -159,13 +157,13 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
159transfer_firmware_failed: 157transfer_firmware_failed:
160 ctx->cl_dev.ops.cl_cleanup_controller(ctx); 158 ctx->cl_dev.ops.cl_cleanup_controller(ctx);
161skl_load_base_firmware_failed: 159skl_load_base_firmware_failed:
162 skl_dsp_disable_core(ctx); 160 skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
163 release_firmware(ctx->fw); 161 release_firmware(ctx->fw);
164 ctx->fw = NULL; 162 ctx->fw = NULL;
165 return ret; 163 return ret;
166} 164}
167 165
168static int skl_set_dsp_D0(struct sst_dsp *ctx) 166static int skl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id)
169{ 167{
170 int ret; 168 int ret;
171 169
@@ -180,7 +178,7 @@ static int skl_set_dsp_D0(struct sst_dsp *ctx)
180 return ret; 178 return ret;
181} 179}
182 180
183static int skl_set_dsp_D3(struct sst_dsp *ctx) 181static int skl_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id)
184{ 182{
185 int ret; 183 int ret;
186 struct skl_ipc_dxstate_info dx; 184 struct skl_ipc_dxstate_info dx;
@@ -207,7 +205,7 @@ static int skl_set_dsp_D3(struct sst_dsp *ctx)
207 skl_ipc_op_int_disable(ctx); 205 skl_ipc_op_int_disable(ctx);
208 skl_ipc_int_disable(ctx); 206 skl_ipc_int_disable(ctx);
209 207
210 ret = skl_dsp_disable_core(ctx); 208 ret = skl_dsp_disable_core(ctx, core_id);
211 if (ret < 0) { 209 if (ret < 0) {
212 dev_err(ctx->dev, "disable dsp core failed ret: %d\n", ret); 210 dev_err(ctx->dev, "disable dsp core failed ret: %d\n", ret);
213 ret = -EIO; 211 ret = -EIO;
@@ -466,12 +464,16 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
466 if (ret) 464 if (ret)
467 return ret; 465 return ret;
468 466
467 skl->cores.count = 2;
468
469 ret = sst->fw_ops.load_fw(sst); 469 ret = sst->fw_ops.load_fw(sst);
470 if (ret < 0) { 470 if (ret < 0) {
471 dev_err(dev, "Load base fw failed : %d", ret); 471 dev_err(dev, "Load base fw failed : %d", ret);
472 goto cleanup; 472 goto cleanup;
473 } 473 }
474 474
475 skl_dsp_init_core_state(sst);
476
475 if (dsp) 477 if (dsp)
476 *dsp = skl; 478 *dsp = skl;
477 479