]> asedeno.scripts.mit.edu Git - linux.git/blob - sound/soc/intel/skylake/bxt-sst.c
Merge branch 'work.sendmsg' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[linux.git] / sound / soc / intel / skylake / bxt-sst.c
1 /*
2  *  bxt-sst.c - DSP library functions for BXT platform
3  *
4  *  Copyright (C) 2015-16 Intel Corp
5  *  Author:Rafal Redzimski <rafal.f.redzimski@intel.com>
6  *         Jeeja KP <jeeja.kp@intel.com>
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; version 2 of the License.
11  *
12  *  This program is distributed in the hope that it will be useful, but
13  *  WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  General Public License for more details.
16  */
17
18 #include <linux/module.h>
19 #include <linux/delay.h>
20 #include <linux/firmware.h>
21 #include <linux/device.h>
22
23 #include "../common/sst-dsp.h"
24 #include "../common/sst-dsp-priv.h"
25 #include "skl-sst-ipc.h"
26
27 #define BXT_BASEFW_TIMEOUT      3000
28 #define BXT_INIT_TIMEOUT        500
29 #define BXT_IPC_PURGE_FW        0x01004000
30
31 #define BXT_ROM_INIT            0x5
32 #define BXT_ADSP_SRAM0_BASE     0x80000
33
34 /* Firmware status window */
35 #define BXT_ADSP_FW_STATUS      BXT_ADSP_SRAM0_BASE
36 #define BXT_ADSP_ERROR_CODE     (BXT_ADSP_FW_STATUS + 0x4)
37
38 #define BXT_ADSP_SRAM1_BASE     0xA0000
39
40 #define BXT_INSTANCE_ID 0
41 #define BXT_BASE_FW_MODULE_ID 0
42
43 #define BXT_ADSP_FW_BIN_HDR_OFFSET 0x2000
44
45 /* Delay before scheduling D0i3 entry */
46 #define BXT_D0I3_DELAY 5000
47
48 static unsigned int bxt_get_errorcode(struct sst_dsp *ctx)
49 {
50          return sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE);
51 }
52
53 static int
54 bxt_load_library(struct sst_dsp *ctx, struct skl_lib_info *linfo, int lib_count)
55 {
56         struct snd_dma_buffer dmab;
57         struct skl_sst *skl = ctx->thread_context;
58         const struct firmware *fw = NULL;
59         struct firmware stripped_fw;
60         int ret = 0, i, dma_id, stream_tag;
61
62         /* library indices start from 1 to N. 0 represents base FW */
63         for (i = 1; i < lib_count; i++) {
64                 ret = request_firmware(&fw, linfo[i].name, ctx->dev);
65                 if (ret < 0) {
66                         dev_err(ctx->dev, "Request lib %s failed:%d\n",
67                                         linfo[i].name, ret);
68                         return ret;
69                 }
70
71                 if (skl->is_first_boot) {
72                         ret = snd_skl_parse_uuids(ctx, fw,
73                                         BXT_ADSP_FW_BIN_HDR_OFFSET, i);
74                         if (ret < 0)
75                                 goto load_library_failed;
76                 }
77
78                 stripped_fw.data = fw->data;
79                 stripped_fw.size = fw->size;
80                 skl_dsp_strip_extended_manifest(&stripped_fw);
81
82                 stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40,
83                                         stripped_fw.size, &dmab);
84                 if (stream_tag <= 0) {
85                         dev_err(ctx->dev, "Lib prepare DMA err: %x\n",
86                                         stream_tag);
87                         ret = stream_tag;
88                         goto load_library_failed;
89                 }
90
91                 dma_id = stream_tag - 1;
92                 memcpy(dmab.area, stripped_fw.data, stripped_fw.size);
93
94                 ctx->dsp_ops.trigger(ctx->dev, true, stream_tag);
95                 ret = skl_sst_ipc_load_library(&skl->ipc, dma_id, i);
96                 if (ret < 0)
97                         dev_err(ctx->dev, "IPC Load Lib for %s fail: %d\n",
98                                         linfo[i].name, ret);
99
100                 ctx->dsp_ops.trigger(ctx->dev, false, stream_tag);
101                 ctx->dsp_ops.cleanup(ctx->dev, &dmab, stream_tag);
102                 release_firmware(fw);
103                 fw = NULL;
104         }
105
106         return ret;
107
108 load_library_failed:
109         release_firmware(fw);
110         return ret;
111 }
112
113 /*
114  * First boot sequence has some extra steps. Core 0 waits for power
115  * status on core 1, so power up core 1 also momentarily, keep it in
116  * reset/stall and then turn it off
117  */
118 static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
119                         const void *fwdata, u32 fwsize)
120 {
121         int stream_tag, ret;
122
123         stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, fwsize, &ctx->dmab);
124         if (stream_tag <= 0) {
125                 dev_err(ctx->dev, "Failed to prepare DMA FW loading err: %x\n",
126                                 stream_tag);
127                 return stream_tag;
128         }
129
130         ctx->dsp_ops.stream_tag = stream_tag;
131         memcpy(ctx->dmab.area, fwdata, fwsize);
132
133         /* Step 1: Power up core 0 and core1 */
134         ret = skl_dsp_core_power_up(ctx, SKL_DSP_CORE0_MASK |
135                                 SKL_DSP_CORE_MASK(1));
136         if (ret < 0) {
137                 dev_err(ctx->dev, "dsp core0/1 power up failed\n");
138                 goto base_fw_load_failed;
139         }
140
141         /* Step 2: Purge FW request */
142         sst_dsp_shim_write(ctx, SKL_ADSP_REG_HIPCI, SKL_ADSP_REG_HIPCI_BUSY |
143                                 (BXT_IPC_PURGE_FW | ((stream_tag - 1) << 9)));
144
145         /* Step 3: Unset core0 reset state & unstall/run core0 */
146         ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK);
147         if (ret < 0) {
148                 dev_err(ctx->dev, "Start dsp core failed ret: %d\n", ret);
149                 ret = -EIO;
150                 goto base_fw_load_failed;
151         }
152
153         /* Step 4: Wait for DONE Bit */
154         ret = sst_dsp_register_poll(ctx, SKL_ADSP_REG_HIPCIE,
155                                         SKL_ADSP_REG_HIPCIE_DONE,
156                                         SKL_ADSP_REG_HIPCIE_DONE,
157                                         BXT_INIT_TIMEOUT, "HIPCIE Done");
158         if (ret < 0) {
159                 dev_err(ctx->dev, "Timout for Purge Request%d\n", ret);
160                 goto base_fw_load_failed;
161         }
162
163         /* Step 5: power down core1 */
164         ret = skl_dsp_core_power_down(ctx, SKL_DSP_CORE_MASK(1));
165         if (ret < 0) {
166                 dev_err(ctx->dev, "dsp core1 power down failed\n");
167                 goto base_fw_load_failed;
168         }
169
170         /* Step 6: Enable Interrupt */
171         skl_ipc_int_enable(ctx);
172         skl_ipc_op_int_enable(ctx);
173
174         /* Step 7: Wait for ROM init */
175         ret = sst_dsp_register_poll(ctx, BXT_ADSP_FW_STATUS, SKL_FW_STS_MASK,
176                         SKL_FW_INIT, BXT_INIT_TIMEOUT, "ROM Load");
177         if (ret < 0) {
178                 dev_err(ctx->dev, "Timeout for ROM init, ret:%d\n", ret);
179                 goto base_fw_load_failed;
180         }
181
182         return ret;
183
184 base_fw_load_failed:
185         ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, stream_tag);
186         skl_dsp_core_power_down(ctx, SKL_DSP_CORE_MASK(1));
187         skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
188         return ret;
189 }
190
191 static int sst_transfer_fw_host_dma(struct sst_dsp *ctx)
192 {
193         int ret;
194
195         ctx->dsp_ops.trigger(ctx->dev, true, ctx->dsp_ops.stream_tag);
196         ret = sst_dsp_register_poll(ctx, BXT_ADSP_FW_STATUS, SKL_FW_STS_MASK,
197                         BXT_ROM_INIT, BXT_BASEFW_TIMEOUT, "Firmware boot");
198
199         ctx->dsp_ops.trigger(ctx->dev, false, ctx->dsp_ops.stream_tag);
200         ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, ctx->dsp_ops.stream_tag);
201
202         return ret;
203 }
204
205 static int bxt_load_base_firmware(struct sst_dsp *ctx)
206 {
207         struct firmware stripped_fw;
208         struct skl_sst *skl = ctx->thread_context;
209         int ret;
210
211         ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev);
212         if (ret < 0) {
213                 dev_err(ctx->dev, "Request firmware failed %d\n", ret);
214                 goto sst_load_base_firmware_failed;
215         }
216
217         /* check for extended manifest */
218         if (ctx->fw == NULL)
219                 goto sst_load_base_firmware_failed;
220
221         /* prase uuids on first boot */
222         if (skl->is_first_boot) {
223                 ret = snd_skl_parse_uuids(ctx, ctx->fw, BXT_ADSP_FW_BIN_HDR_OFFSET, 0);
224                 if (ret < 0)
225                         goto sst_load_base_firmware_failed;
226         }
227
228         stripped_fw.data = ctx->fw->data;
229         stripped_fw.size = ctx->fw->size;
230         skl_dsp_strip_extended_manifest(&stripped_fw);
231
232         ret = sst_bxt_prepare_fw(ctx, stripped_fw.data, stripped_fw.size);
233         /* Retry Enabling core and ROM load. Retry seemed to help */
234         if (ret < 0) {
235                 ret = sst_bxt_prepare_fw(ctx, stripped_fw.data, stripped_fw.size);
236                 if (ret < 0) {
237                         dev_err(ctx->dev, "Error code=0x%x: FW status=0x%x\n",
238                         sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE),
239                         sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS));
240
241                         dev_err(ctx->dev, "Core En/ROM load fail:%d\n", ret);
242                         goto sst_load_base_firmware_failed;
243                 }
244         }
245
246         ret = sst_transfer_fw_host_dma(ctx);
247         if (ret < 0) {
248                 dev_err(ctx->dev, "Transfer firmware failed %d\n", ret);
249                 dev_info(ctx->dev, "Error code=0x%x: FW status=0x%x\n",
250                         sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE),
251                         sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS));
252
253                 skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
254         } else {
255                 dev_dbg(ctx->dev, "Firmware download successful\n");
256                 ret = wait_event_timeout(skl->boot_wait, skl->boot_complete,
257                                         msecs_to_jiffies(SKL_IPC_BOOT_MSECS));
258                 if (ret == 0) {
259                         dev_err(ctx->dev, "DSP boot fail, FW Ready timeout\n");
260                         skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
261                         ret = -EIO;
262                 } else {
263                         ret = 0;
264                         skl->fw_loaded = true;
265                 }
266         }
267
268 sst_load_base_firmware_failed:
269         release_firmware(ctx->fw);
270         return ret;
271 }
272
273 /*
274  * Decide the D0i3 state that can be targeted based on the usecase
275  * ref counts and DSP state
276  *
277  * Decision Matrix:  (X= dont care; state = target state)
278  *
279  * DSP state != SKL_DSP_RUNNING ; state = no d0i3
280  *
281  * DSP state == SKL_DSP_RUNNING , the following matrix applies
282  * non_d0i3 >0; streaming =X; non_streaming =X; state = no d0i3
283  * non_d0i3 =X; streaming =0; non_streaming =0; state = no d0i3
284  * non_d0i3 =0; streaming >0; non_streaming =X; state = streaming d0i3
285  * non_d0i3 =0; streaming =0; non_streaming =X; state = non-streaming d0i3
286  */
287 static int bxt_d0i3_target_state(struct sst_dsp *ctx)
288 {
289         struct skl_sst *skl = ctx->thread_context;
290         struct skl_d0i3_data *d0i3 = &skl->d0i3;
291
292         if (skl->cores.state[SKL_DSP_CORE0_ID] != SKL_DSP_RUNNING)
293                 return SKL_DSP_D0I3_NONE;
294
295         if (d0i3->non_d0i3)
296                 return SKL_DSP_D0I3_NONE;
297         else if (d0i3->streaming)
298                 return SKL_DSP_D0I3_STREAMING;
299         else if (d0i3->non_streaming)
300                 return SKL_DSP_D0I3_NON_STREAMING;
301         else
302                 return SKL_DSP_D0I3_NONE;
303 }
304
305 static void bxt_set_dsp_D0i3(struct work_struct *work)
306 {
307         int ret;
308         struct skl_ipc_d0ix_msg msg;
309         struct skl_sst *skl = container_of(work,
310                         struct skl_sst, d0i3.work.work);
311         struct sst_dsp *ctx = skl->dsp;
312         struct skl_d0i3_data *d0i3 = &skl->d0i3;
313         int target_state;
314
315         dev_dbg(ctx->dev, "In %s:\n", __func__);
316
317         /* D0i3 entry allowed only if core 0 alone is running */
318         if (skl_dsp_get_enabled_cores(ctx) !=  SKL_DSP_CORE0_MASK) {
319                 dev_warn(ctx->dev,
320                                 "D0i3 allowed when only core0 running:Exit\n");
321                 return;
322         }
323
324         target_state = bxt_d0i3_target_state(ctx);
325         if (target_state == SKL_DSP_D0I3_NONE)
326                 return;
327
328         msg.instance_id = 0;
329         msg.module_id = 0;
330         msg.wake = 1;
331         msg.streaming = 0;
332         if (target_state == SKL_DSP_D0I3_STREAMING)
333                 msg.streaming = 1;
334
335         ret =  skl_ipc_set_d0ix(&skl->ipc, &msg);
336
337         if (ret < 0) {
338                 dev_err(ctx->dev, "Failed to set DSP to D0i3 state\n");
339                 return;
340         }
341
342         /* Set Vendor specific register D0I3C.I3 to enable D0i3*/
343         if (skl->update_d0i3c)
344                 skl->update_d0i3c(skl->dev, true);
345
346         d0i3->state = target_state;
347         skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING_D0I3;
348 }
349
350 static int bxt_schedule_dsp_D0i3(struct sst_dsp *ctx)
351 {
352         struct skl_sst *skl = ctx->thread_context;
353         struct skl_d0i3_data *d0i3 = &skl->d0i3;
354
355         /* Schedule D0i3 only if the usecase ref counts are appropriate */
356         if (bxt_d0i3_target_state(ctx) != SKL_DSP_D0I3_NONE) {
357
358                 dev_dbg(ctx->dev, "%s: Schedule D0i3\n", __func__);
359
360                 schedule_delayed_work(&d0i3->work,
361                                 msecs_to_jiffies(BXT_D0I3_DELAY));
362         }
363
364         return 0;
365 }
366
367 static int bxt_set_dsp_D0i0(struct sst_dsp *ctx)
368 {
369         int ret;
370         struct skl_ipc_d0ix_msg msg;
371         struct skl_sst *skl = ctx->thread_context;
372
373         dev_dbg(ctx->dev, "In %s:\n", __func__);
374
375         /* First Cancel any pending attempt to put DSP to D0i3 */
376         cancel_delayed_work_sync(&skl->d0i3.work);
377
378         /* If DSP is currently in D0i3, bring it to D0i0 */
379         if (skl->cores.state[SKL_DSP_CORE0_ID] != SKL_DSP_RUNNING_D0I3)
380                 return 0;
381
382         dev_dbg(ctx->dev, "Set DSP to D0i0\n");
383
384         msg.instance_id = 0;
385         msg.module_id = 0;
386         msg.streaming = 0;
387         msg.wake = 0;
388
389         if (skl->d0i3.state == SKL_DSP_D0I3_STREAMING)
390                 msg.streaming = 1;
391
392         /* Clear Vendor specific register D0I3C.I3 to disable D0i3*/
393         if (skl->update_d0i3c)
394                 skl->update_d0i3c(skl->dev, false);
395
396         ret =  skl_ipc_set_d0ix(&skl->ipc, &msg);
397         if (ret < 0) {
398                 dev_err(ctx->dev, "Failed to set DSP to D0i0\n");
399                 return ret;
400         }
401
402         skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING;
403         skl->d0i3.state = SKL_DSP_D0I3_NONE;
404
405         return 0;
406 }
407
408 static int bxt_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id)
409 {
410         struct skl_sst *skl = ctx->thread_context;
411         int ret;
412         struct skl_ipc_dxstate_info dx;
413         unsigned int core_mask = SKL_DSP_CORE_MASK(core_id);
414
415         if (skl->fw_loaded == false) {
416                 skl->boot_complete = false;
417                 ret = bxt_load_base_firmware(ctx);
418                 if (ret < 0) {
419                         dev_err(ctx->dev, "reload fw failed: %d\n", ret);
420                         return ret;
421                 }
422
423                 if (skl->lib_count > 1) {
424                         ret = bxt_load_library(ctx, skl->lib_info,
425                                                 skl->lib_count);
426                         if (ret < 0) {
427                                 dev_err(ctx->dev, "reload libs failed: %d\n", ret);
428                                 return ret;
429                         }
430                 }
431                 return ret;
432         }
433
434         /* If core 0 is being turned on, turn on core 1 as well */
435         if (core_id == SKL_DSP_CORE0_ID)
436                 ret = skl_dsp_core_power_up(ctx, core_mask |
437                                 SKL_DSP_CORE_MASK(1));
438         else
439                 ret = skl_dsp_core_power_up(ctx, core_mask);
440
441         if (ret < 0)
442                 goto err;
443
444         if (core_id == SKL_DSP_CORE0_ID) {
445
446                 /*
447                  * Enable interrupt after SPA is set and before
448                  * DSP is unstalled
449                  */
450                 skl_ipc_int_enable(ctx);
451                 skl_ipc_op_int_enable(ctx);
452                 skl->boot_complete = false;
453         }
454
455         ret = skl_dsp_start_core(ctx, core_mask);
456         if (ret < 0)
457                 goto err;
458
459         if (core_id == SKL_DSP_CORE0_ID) {
460                 ret = wait_event_timeout(skl->boot_wait,
461                                 skl->boot_complete,
462                                 msecs_to_jiffies(SKL_IPC_BOOT_MSECS));
463
464         /* If core 1 was turned on for booting core 0, turn it off */
465                 skl_dsp_core_power_down(ctx, SKL_DSP_CORE_MASK(1));
466                 if (ret == 0) {
467                         dev_err(ctx->dev, "%s: DSP boot timeout\n", __func__);
468                         dev_err(ctx->dev, "Error code=0x%x: FW status=0x%x\n",
469                                 sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE),
470                                 sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS));
471                         dev_err(ctx->dev, "Failed to set core0 to D0 state\n");
472                         ret = -EIO;
473                         goto err;
474                 }
475         }
476
477         /* Tell FW if additional core in now On */
478
479         if (core_id != SKL_DSP_CORE0_ID) {
480                 dx.core_mask = core_mask;
481                 dx.dx_mask = core_mask;
482
483                 ret = skl_ipc_set_dx(&skl->ipc, BXT_INSTANCE_ID,
484                                         BXT_BASE_FW_MODULE_ID, &dx);
485                 if (ret < 0) {
486                         dev_err(ctx->dev, "IPC set_dx for core %d fail: %d\n",
487                                                                 core_id, ret);
488                         goto err;
489                 }
490         }
491
492         skl->cores.state[core_id] = SKL_DSP_RUNNING;
493         return 0;
494 err:
495         if (core_id == SKL_DSP_CORE0_ID)
496                 core_mask |= SKL_DSP_CORE_MASK(1);
497         skl_dsp_disable_core(ctx, core_mask);
498
499         return ret;
500 }
501
502 static int bxt_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id)
503 {
504         int ret;
505         struct skl_ipc_dxstate_info dx;
506         struct skl_sst *skl = ctx->thread_context;
507         unsigned int core_mask = SKL_DSP_CORE_MASK(core_id);
508
509         dx.core_mask = core_mask;
510         dx.dx_mask = SKL_IPC_D3_MASK;
511
512         dev_dbg(ctx->dev, "core mask=%x dx_mask=%x\n",
513                         dx.core_mask, dx.dx_mask);
514
515         ret = skl_ipc_set_dx(&skl->ipc, BXT_INSTANCE_ID,
516                                 BXT_BASE_FW_MODULE_ID, &dx);
517         if (ret < 0)
518                 dev_err(ctx->dev,
519                 "Failed to set DSP to D3:core id = %d;Continue reset\n",
520                 core_id);
521
522         ret = skl_dsp_disable_core(ctx, core_mask);
523         if (ret < 0) {
524                 dev_err(ctx->dev, "Failed to disable core %d\n", ret);
525                 return ret;
526         }
527         skl->cores.state[core_id] = SKL_DSP_RESET;
528         return 0;
529 }
530
531 static struct skl_dsp_fw_ops bxt_fw_ops = {
532         .set_state_D0 = bxt_set_dsp_D0,
533         .set_state_D3 = bxt_set_dsp_D3,
534         .set_state_D0i3 = bxt_schedule_dsp_D0i3,
535         .set_state_D0i0 = bxt_set_dsp_D0i0,
536         .load_fw = bxt_load_base_firmware,
537         .get_fw_errcode = bxt_get_errorcode,
538         .load_library = bxt_load_library,
539 };
540
541 static struct sst_ops skl_ops = {
542         .irq_handler = skl_dsp_sst_interrupt,
543         .write = sst_shim32_write,
544         .read = sst_shim32_read,
545         .ram_read = sst_memcpy_fromio_32,
546         .ram_write = sst_memcpy_toio_32,
547         .free = skl_dsp_free,
548 };
549
550 static struct sst_dsp_device skl_dev = {
551         .thread = skl_dsp_irq_thread_handler,
552         .ops = &skl_ops,
553 };
554
555 int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
556                         const char *fw_name, struct skl_dsp_loader_ops dsp_ops,
557                         struct skl_sst **dsp)
558 {
559         struct skl_sst *skl;
560         struct sst_dsp *sst;
561         int ret;
562
563         skl = devm_kzalloc(dev, sizeof(*skl), GFP_KERNEL);
564         if (skl == NULL)
565                 return -ENOMEM;
566
567         skl->dev = dev;
568         skl_dev.thread_context = skl;
569         INIT_LIST_HEAD(&skl->uuid_list);
570
571         skl->dsp = skl_dsp_ctx_init(dev, &skl_dev, irq);
572         if (!skl->dsp) {
573                 dev_err(skl->dev, "skl_dsp_ctx_init failed\n");
574                 return -ENODEV;
575         }
576
577         sst = skl->dsp;
578         sst->fw_name = fw_name;
579         sst->dsp_ops = dsp_ops;
580         sst->fw_ops = bxt_fw_ops;
581         sst->addr.lpe = mmio_base;
582         sst->addr.shim = mmio_base;
583
584         sst_dsp_mailbox_init(sst, (BXT_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ),
585                         SKL_ADSP_W0_UP_SZ, BXT_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ);
586
587         INIT_LIST_HEAD(&sst->module_list);
588         ret = skl_ipc_init(dev, skl);
589         if (ret)
590                 return ret;
591
592         /* set the D0i3 check */
593         skl->ipc.ops.check_dsp_lp_on = skl_ipc_check_D0i0;
594
595         skl->cores.count = 2;
596         skl->boot_complete = false;
597         init_waitqueue_head(&skl->boot_wait);
598         skl->is_first_boot = true;
599         INIT_DELAYED_WORK(&skl->d0i3.work, bxt_set_dsp_D0i3);
600         skl->d0i3.state = SKL_DSP_D0I3_NONE;
601
602         if (dsp)
603                 *dsp = skl;
604
605         return 0;
606 }
607 EXPORT_SYMBOL_GPL(bxt_sst_dsp_init);
608
609 int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx)
610 {
611         int ret;
612         struct sst_dsp *sst = ctx->dsp;
613
614         ret = sst->fw_ops.load_fw(sst);
615         if (ret < 0) {
616                 dev_err(dev, "Load base fw failed: %x\n", ret);
617                 return ret;
618         }
619
620         skl_dsp_init_core_state(sst);
621
622         if (ctx->lib_count > 1) {
623                 ret = sst->fw_ops.load_library(sst, ctx->lib_info,
624                                                 ctx->lib_count);
625                 if (ret < 0) {
626                         dev_err(dev, "Load Library failed : %x\n", ret);
627                         return ret;
628                 }
629         }
630         ctx->is_first_boot = false;
631
632         return 0;
633 }
634 EXPORT_SYMBOL_GPL(bxt_sst_init_fw);
635
636 void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx)
637 {
638         skl_freeup_uuid_list(ctx);
639         skl_ipc_free(&ctx->ipc);
640         ctx->dsp->cl_dev.ops.cl_cleanup_controller(ctx->dsp);
641
642         if (ctx->dsp->addr.lpe)
643                 iounmap(ctx->dsp->addr.lpe);
644
645         ctx->dsp->ops->free(ctx->dsp);
646 }
647 EXPORT_SYMBOL_GPL(bxt_sst_dsp_cleanup);
648
649 MODULE_LICENSE("GPL v2");
650 MODULE_DESCRIPTION("Intel Broxton IPC driver");