blob: 20968e5ec86d9f90a0962e6911803b3b4b9058e3 [file] [log] [blame]
Subhransu S. Prustya750ba52015-07-10 22:18:44 +05301/*
2 * skl-sst.c - HDA DSP library functions for SKL platform
3 *
4 * Copyright (C) 2014-15, Intel Corporation.
5 * Author:Rafal Redzimski <rafal.f.redzimski@intel.com>
6 * Jeeja KP <jeeja.kp@intel.com>
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as version 2, as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 */
18
19#include <linux/module.h>
20#include <linux/delay.h>
21#include <linux/device.h>
Jeeja KP53afce22015-11-13 19:22:09 +053022#include <linux/err.h>
Shreyas NC09305da2016-04-21 11:45:22 +053023#include <linux/uuid.h>
Subhransu S. Prustya750ba52015-07-10 22:18:44 +053024#include "../common/sst-dsp.h"
25#include "../common/sst-dsp-priv.h"
26#include "../common/sst-ipc.h"
27#include "skl-sst-ipc.h"
28
29#define SKL_BASEFW_TIMEOUT 300
30#define SKL_INIT_TIMEOUT 1000
31
32/* Intel HD Audio SRAM Window 0*/
33#define SKL_ADSP_SRAM0_BASE 0x8000
34
35/* Firmware status window */
36#define SKL_ADSP_FW_STATUS SKL_ADSP_SRAM0_BASE
37#define SKL_ADSP_ERROR_CODE (SKL_ADSP_FW_STATUS + 0x4)
38
Dharageswari R6c5768b2015-12-03 23:29:50 +053039#define SKL_NUM_MODULES 1
40
Subhransu S. Prustya750ba52015-07-10 22:18:44 +053041static bool skl_check_fw_status(struct sst_dsp *ctx, u32 status)
42{
43 u32 cur_sts;
44
45 cur_sts = sst_dsp_shim_read(ctx, SKL_ADSP_FW_STATUS) & SKL_FW_STS_MASK;
46
47 return (cur_sts == status);
48}
49
50static int skl_transfer_firmware(struct sst_dsp *ctx,
51 const void *basefw, u32 base_fw_size)
52{
53 int ret = 0;
54
Jeeja KPb7d0254c52017-03-13 22:11:31 +053055 ret = ctx->cl_dev.ops.cl_copy_to_dmabuf(ctx, basefw, base_fw_size,
56 true);
Subhransu S. Prustya750ba52015-07-10 22:18:44 +053057 if (ret < 0)
58 return ret;
59
60 ret = sst_dsp_register_poll(ctx,
61 SKL_ADSP_FW_STATUS,
62 SKL_FW_STS_MASK,
63 SKL_FW_RFW_START,
64 SKL_BASEFW_TIMEOUT,
65 "Firmware boot");
66
67 ctx->cl_dev.ops.cl_stop_dma(ctx);
68
69 return ret;
70}
71
Vinod Koul06711052016-05-30 17:43:00 +053072#define SKL_ADSP_FW_BIN_HDR_OFFSET 0x284
73
Subhransu S. Prustya750ba52015-07-10 22:18:44 +053074static int skl_load_base_firmware(struct sst_dsp *ctx)
75{
76 int ret = 0, i;
Subhransu S. Prustya750ba52015-07-10 22:18:44 +053077 struct skl_sst *skl = ctx->thread_context;
Vinod Koulcd636552016-05-30 17:42:57 +053078 struct firmware stripped_fw;
Subhransu S. Prustya750ba52015-07-10 22:18:44 +053079 u32 reg;
80
Jeeja KP84c9e282015-10-09 09:01:50 +010081 skl->boot_complete = false;
82 init_waitqueue_head(&skl->boot_wait);
83
84 if (ctx->fw == NULL) {
Vinod Koulaecf6fd2015-11-05 21:34:15 +053085 ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev);
Jeeja KP84c9e282015-10-09 09:01:50 +010086 if (ret < 0) {
87 dev_err(ctx->dev, "Request firmware failed %d\n", ret);
Jeeja KP84c9e282015-10-09 09:01:50 +010088 return -EIO;
89 }
Vinod Koul06711052016-05-30 17:43:00 +053090 }
91
Vinod Koule2808232016-07-26 18:06:45 +053092 /* prase uuids on first boot */
93 if (skl->is_first_boot) {
94 ret = snd_skl_parse_uuids(ctx, ctx->fw, SKL_ADSP_FW_BIN_HDR_OFFSET, 0);
95 if (ret < 0) {
96 dev_err(ctx->dev, "UUID parsing err: %d\n", ret);
97 release_firmware(ctx->fw);
98 skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
99 return ret;
100 }
Jeeja KP84c9e282015-10-09 09:01:50 +0100101 }
102
Vinod Koulcd636552016-05-30 17:42:57 +0530103 /* check for extended manifest */
104 stripped_fw.data = ctx->fw->data;
105 stripped_fw.size = ctx->fw->size;
106
107 skl_dsp_strip_extended_manifest(&stripped_fw);
108
Jeeja KP84c9e282015-10-09 09:01:50 +0100109 ret = skl_dsp_boot(ctx);
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530110 if (ret < 0) {
Colin Ian Kingecd286a2016-09-16 18:51:21 +0100111 dev_err(ctx->dev, "Boot dsp core failed ret: %d\n", ret);
Jeeja KP84c9e282015-10-09 09:01:50 +0100112 goto skl_load_base_firmware_failed;
113 }
114
115 ret = skl_cldma_prepare(ctx);
116 if (ret < 0) {
Colin Ian Kingecd286a2016-09-16 18:51:21 +0100117 dev_err(ctx->dev, "CL dma prepare failed : %d\n", ret);
Jeeja KP84c9e282015-10-09 09:01:50 +0100118 goto skl_load_base_firmware_failed;
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530119 }
120
121 /* enable Interrupt */
122 skl_ipc_int_enable(ctx);
123 skl_ipc_op_int_enable(ctx);
124
125 /* check ROM Status */
126 for (i = SKL_INIT_TIMEOUT; i > 0; --i) {
127 if (skl_check_fw_status(ctx, SKL_FW_INIT)) {
128 dev_dbg(ctx->dev,
129 "ROM loaded, we can continue with FW loading\n");
130 break;
131 }
132 mdelay(1);
133 }
134 if (!i) {
135 reg = sst_dsp_shim_read(ctx, SKL_ADSP_FW_STATUS);
136 dev_err(ctx->dev,
137 "Timeout waiting for ROM init done, reg:0x%x\n", reg);
138 ret = -EIO;
Jeeja KPae395932015-11-13 19:22:08 +0530139 goto transfer_firmware_failed;
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530140 }
141
Vinod Koulcd636552016-05-30 17:42:57 +0530142 ret = skl_transfer_firmware(ctx, stripped_fw.data, stripped_fw.size);
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530143 if (ret < 0) {
144 dev_err(ctx->dev, "Transfer firmware failed%d\n", ret);
Jeeja KPae395932015-11-13 19:22:08 +0530145 goto transfer_firmware_failed;
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530146 } else {
147 ret = wait_event_timeout(skl->boot_wait, skl->boot_complete,
148 msecs_to_jiffies(SKL_IPC_BOOT_MSECS));
149 if (ret == 0) {
150 dev_err(ctx->dev, "DSP boot failed, FW Ready timed-out\n");
151 ret = -EIO;
Jeeja KPae395932015-11-13 19:22:08 +0530152 goto transfer_firmware_failed;
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530153 }
154
155 dev_dbg(ctx->dev, "Download firmware successful%d\n", ret);
Jayachandran B1665c172016-06-13 17:59:01 +0530156 skl->fw_loaded = true;
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530157 }
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530158 return 0;
Jeeja KPae395932015-11-13 19:22:08 +0530159transfer_firmware_failed:
160 ctx->cl_dev.ops.cl_cleanup_controller(ctx);
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530161skl_load_base_firmware_failed:
Jayachandran B052f1032016-06-21 10:17:41 +0530162 skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
Jeeja KP84c9e282015-10-09 09:01:50 +0100163 release_firmware(ctx->fw);
164 ctx->fw = NULL;
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530165 return ret;
166}
167
Jayachandran B052f1032016-06-21 10:17:41 +0530168static int skl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id)
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530169{
170 int ret;
Jayachandran B40a16602016-06-21 10:17:42 +0530171 struct skl_ipc_dxstate_info dx;
172 struct skl_sst *skl = ctx->thread_context;
173 unsigned int core_mask = SKL_DSP_CORE_MASK(core_id);
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530174
Jayachandran B40a16602016-06-21 10:17:42 +0530175 /* If core0 is being turned on, we need to load the FW */
176 if (core_id == SKL_DSP_CORE0_ID) {
177 ret = skl_load_base_firmware(ctx);
178 if (ret < 0) {
179 dev_err(ctx->dev, "unable to load firmware\n");
180 return ret;
181 }
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530182 }
183
Jayachandran B40a16602016-06-21 10:17:42 +0530184 /*
185 * If any core other than core 0 is being moved to D0, enable the
186 * core and send the set dx IPC for the core.
187 */
188 if (core_id != SKL_DSP_CORE0_ID) {
189 ret = skl_dsp_enable_core(ctx, core_mask);
190 if (ret < 0)
191 return ret;
192
193 dx.core_mask = core_mask;
194 dx.dx_mask = core_mask;
195
196 ret = skl_ipc_set_dx(&skl->ipc, SKL_INSTANCE_ID,
197 SKL_BASE_FW_MODULE_ID, &dx);
198 if (ret < 0) {
199 dev_err(ctx->dev, "Failed to set dsp to D0:core id= %d\n",
200 core_id);
201 skl_dsp_disable_core(ctx, core_mask);
202 }
203 }
204
205 skl->cores.state[core_id] = SKL_DSP_RUNNING;
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530206
207 return ret;
208}
209
Jayachandran B052f1032016-06-21 10:17:41 +0530210static int skl_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id)
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530211{
212 int ret;
213 struct skl_ipc_dxstate_info dx;
214 struct skl_sst *skl = ctx->thread_context;
Jayachandran B40a16602016-06-21 10:17:42 +0530215 unsigned int core_mask = SKL_DSP_CORE_MASK(core_id);
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530216
Jayachandran B40a16602016-06-21 10:17:42 +0530217 dx.core_mask = core_mask;
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530218 dx.dx_mask = SKL_IPC_D3_MASK;
Jayachandran B40a16602016-06-21 10:17:42 +0530219
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530220 ret = skl_ipc_set_dx(&skl->ipc, SKL_INSTANCE_ID, SKL_BASE_FW_MODULE_ID, &dx);
Jeeja KP53afce22015-11-13 19:22:09 +0530221 if (ret < 0)
Jayachandran B40a16602016-06-21 10:17:42 +0530222 dev_err(ctx->dev, "set Dx core %d fail: %d\n", core_id, ret);
Jeeja KP53afce22015-11-13 19:22:09 +0530223
Jayachandran B40a16602016-06-21 10:17:42 +0530224 if (core_id == SKL_DSP_CORE0_ID) {
225 /* disable Interrupt */
226 ctx->cl_dev.ops.cl_cleanup_controller(ctx);
227 skl_cldma_int_disable(ctx);
228 skl_ipc_op_int_disable(ctx);
229 skl_ipc_int_disable(ctx);
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530230 }
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530231
Jayachandran B40a16602016-06-21 10:17:42 +0530232 ret = skl_dsp_disable_core(ctx, core_mask);
233 if (ret < 0)
234 return ret;
235
236 skl->cores.state[core_id] = SKL_DSP_RESET;
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530237 return ret;
238}
239
240static unsigned int skl_get_errorcode(struct sst_dsp *ctx)
241{
242 return sst_dsp_shim_read(ctx, SKL_ADSP_ERROR_CODE);
243}
244
Dharageswari R6c5768b2015-12-03 23:29:50 +0530245/*
246 * since get/set_module are called from DAPM context,
247 * we don't need lock for usage count
248 */
Dan Carpenterdb4e5612015-12-15 12:20:14 +0300249static int skl_get_module(struct sst_dsp *ctx, u16 mod_id)
Dharageswari R6c5768b2015-12-03 23:29:50 +0530250{
251 struct skl_module_table *module;
252
253 list_for_each_entry(module, &ctx->module_list, list) {
254 if (module->mod_info->mod_id == mod_id)
255 return ++module->usage_cnt;
256 }
257
258 return -EINVAL;
259}
260
Dan Carpenterdb4e5612015-12-15 12:20:14 +0300261static int skl_put_module(struct sst_dsp *ctx, u16 mod_id)
Dharageswari R6c5768b2015-12-03 23:29:50 +0530262{
263 struct skl_module_table *module;
264
265 list_for_each_entry(module, &ctx->module_list, list) {
266 if (module->mod_info->mod_id == mod_id)
267 return --module->usage_cnt;
268 }
269
270 return -EINVAL;
271}
272
273static struct skl_module_table *skl_fill_module_table(struct sst_dsp *ctx,
274 char *mod_name, int mod_id)
275{
276 const struct firmware *fw;
277 struct skl_module_table *skl_module;
278 unsigned int size;
279 int ret;
280
281 ret = request_firmware(&fw, mod_name, ctx->dev);
282 if (ret < 0) {
283 dev_err(ctx->dev, "Request Module %s failed :%d\n",
284 mod_name, ret);
285 return NULL;
286 }
287
288 skl_module = devm_kzalloc(ctx->dev, sizeof(*skl_module), GFP_KERNEL);
289 if (skl_module == NULL) {
290 release_firmware(fw);
291 return NULL;
292 }
293
294 size = sizeof(*skl_module->mod_info);
295 skl_module->mod_info = devm_kzalloc(ctx->dev, size, GFP_KERNEL);
296 if (skl_module->mod_info == NULL) {
297 release_firmware(fw);
298 return NULL;
299 }
300
301 skl_module->mod_info->mod_id = mod_id;
302 skl_module->mod_info->fw = fw;
303 list_add(&skl_module->list, &ctx->module_list);
304
305 return skl_module;
306}
307
308/* get a module from it's unique ID */
309static struct skl_module_table *skl_module_get_from_id(
310 struct sst_dsp *ctx, u16 mod_id)
311{
312 struct skl_module_table *module;
313
314 if (list_empty(&ctx->module_list)) {
315 dev_err(ctx->dev, "Module list is empty\n");
316 return NULL;
317 }
318
319 list_for_each_entry(module, &ctx->module_list, list) {
320 if (module->mod_info->mod_id == mod_id)
321 return module;
322 }
323
324 return NULL;
325}
326
Jeeja KPb7d0254c52017-03-13 22:11:31 +0530327static int skl_transfer_module(struct sst_dsp *ctx, const void *data,
G Kranthi4e0277d2017-04-25 12:18:21 +0530328 u32 size, u16 mod_id, u8 table_id, bool is_module)
Dharageswari R6c5768b2015-12-03 23:29:50 +0530329{
Jeeja KPb7d0254c52017-03-13 22:11:31 +0530330 int ret, bytes_left, curr_pos;
Dharageswari R6c5768b2015-12-03 23:29:50 +0530331 struct skl_sst *skl = ctx->thread_context;
Jeeja KPb7d0254c52017-03-13 22:11:31 +0530332 skl->mod_load_complete = false;
Dharageswari R6c5768b2015-12-03 23:29:50 +0530333
Jeeja KPb7d0254c52017-03-13 22:11:31 +0530334 bytes_left = ctx->cl_dev.ops.cl_copy_to_dmabuf(ctx, data, size, false);
335 if (bytes_left < 0)
336 return bytes_left;
Dharageswari R6c5768b2015-12-03 23:29:50 +0530337
G Kranthi4e0277d2017-04-25 12:18:21 +0530338 if (is_module) { /* load module */
339 ret = skl_ipc_load_modules(&skl->ipc, SKL_NUM_MODULES, &mod_id);
340 if (ret < 0) {
341 dev_err(ctx->dev, "Failed to Load module: %d\n", ret);
342 goto out;
343 }
Jeeja KPb7d0254c52017-03-13 22:11:31 +0530344 }
Dharageswari R6c5768b2015-12-03 23:29:50 +0530345
Jeeja KPb7d0254c52017-03-13 22:11:31 +0530346 /*
347 * if bytes_left > 0 then wait for BDL complete interrupt and
348 * copy the next chunk till bytes_left is 0. if bytes_left is
349 * is zero, then wait for load module IPC reply
350 */
351 while (bytes_left > 0) {
352 curr_pos = size - bytes_left;
353
354 ret = skl_cldma_wait_interruptible(ctx);
355 if (ret < 0)
356 goto out;
357
358 bytes_left = ctx->cl_dev.ops.cl_copy_to_dmabuf(ctx,
359 data + curr_pos,
360 bytes_left, false);
361 }
362
363 ret = wait_event_timeout(skl->mod_load_wait, skl->mod_load_complete,
364 msecs_to_jiffies(SKL_IPC_BOOT_MSECS));
365 if (ret == 0 || !skl->mod_load_status) {
366 dev_err(ctx->dev, "Module Load failed\n");
367 ret = -EIO;
368 }
369
370out:
Dharageswari R6c5768b2015-12-03 23:29:50 +0530371 ctx->cl_dev.ops.cl_stop_dma(ctx);
372
373 return ret;
374}
375
Shreyas NC09305da2016-04-21 11:45:22 +0530376static int skl_load_module(struct sst_dsp *ctx, u16 mod_id, u8 *guid)
Dharageswari R6c5768b2015-12-03 23:29:50 +0530377{
378 struct skl_module_table *module_entry = NULL;
379 int ret = 0;
380 char mod_name[64]; /* guid str = 32 chars + 4 hyphens */
Shreyas NC09305da2016-04-21 11:45:22 +0530381 uuid_le *uuid_mod;
Dharageswari R6c5768b2015-12-03 23:29:50 +0530382
Shreyas NC09305da2016-04-21 11:45:22 +0530383 uuid_mod = (uuid_le *)guid;
384 snprintf(mod_name, sizeof(mod_name), "%s%pUL%s",
385 "intel/dsp_fw_", uuid_mod, ".bin");
Dharageswari R6c5768b2015-12-03 23:29:50 +0530386
387 module_entry = skl_module_get_from_id(ctx, mod_id);
388 if (module_entry == NULL) {
389 module_entry = skl_fill_module_table(ctx, mod_name, mod_id);
390 if (module_entry == NULL) {
391 dev_err(ctx->dev, "Failed to Load module\n");
392 return -EINVAL;
393 }
394 }
395
396 if (!module_entry->usage_cnt) {
Jeeja KPb7d0254c52017-03-13 22:11:31 +0530397 ret = skl_transfer_module(ctx, module_entry->mod_info->fw->data,
G Kranthi4e0277d2017-04-25 12:18:21 +0530398 module_entry->mod_info->fw->size,
399 mod_id, 0, true);
Dharageswari R6c5768b2015-12-03 23:29:50 +0530400 if (ret < 0) {
401 dev_err(ctx->dev, "Failed to Load module\n");
402 return ret;
403 }
404 }
405
406 ret = skl_get_module(ctx, mod_id);
407
408 return ret;
409}
410
411static int skl_unload_module(struct sst_dsp *ctx, u16 mod_id)
412{
Dan Carpenterdb4e5612015-12-15 12:20:14 +0300413 int usage_cnt;
Dharageswari R6c5768b2015-12-03 23:29:50 +0530414 struct skl_sst *skl = ctx->thread_context;
415 int ret = 0;
416
417 usage_cnt = skl_put_module(ctx, mod_id);
418 if (usage_cnt < 0) {
419 dev_err(ctx->dev, "Module bad usage cnt!:%d\n", usage_cnt);
420 return -EIO;
421 }
Vinod Koulf7ea7772017-03-24 23:10:28 +0530422
423 /* if module is used by others return, no need to unload */
424 if (usage_cnt > 0)
425 return 0;
426
Dharageswari R6c5768b2015-12-03 23:29:50 +0530427 ret = skl_ipc_unload_modules(&skl->ipc,
428 SKL_NUM_MODULES, &mod_id);
429 if (ret < 0) {
430 dev_err(ctx->dev, "Failed to UnLoad module\n");
431 skl_get_module(ctx, mod_id);
432 return ret;
433 }
434
435 return ret;
436}
437
Dharageswari Rfe3f4442016-06-03 18:29:39 +0530438void skl_clear_module_cnt(struct sst_dsp *ctx)
439{
440 struct skl_module_table *module;
441
Vinod Koula35aeae2016-06-14 21:33:45 +0530442 if (list_empty(&ctx->module_list))
443 return;
444
Dharageswari Rfe3f4442016-06-03 18:29:39 +0530445 list_for_each_entry(module, &ctx->module_list, list) {
446 module->usage_cnt = 0;
447 }
448}
449EXPORT_SYMBOL_GPL(skl_clear_module_cnt);
450
Dharageswari R6c5768b2015-12-03 23:29:50 +0530451static void skl_clear_module_table(struct sst_dsp *ctx)
452{
453 struct skl_module_table *module, *tmp;
454
455 if (list_empty(&ctx->module_list))
456 return;
457
458 list_for_each_entry_safe(module, tmp, &ctx->module_list, list) {
459 list_del(&module->list);
460 release_firmware(module->mod_info->fw);
461 }
462}
463
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530464static struct skl_dsp_fw_ops skl_fw_ops = {
465 .set_state_D0 = skl_set_dsp_D0,
466 .set_state_D3 = skl_set_dsp_D3,
467 .load_fw = skl_load_base_firmware,
468 .get_fw_errcode = skl_get_errorcode,
Dharageswari R6c5768b2015-12-03 23:29:50 +0530469 .load_mod = skl_load_module,
470 .unload_mod = skl_unload_module,
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530471};
472
Subhransu S. Prusty89b0d8a2017-04-25 12:18:22 +0530473static struct skl_dsp_fw_ops kbl_fw_ops = {
474 .set_state_D0 = skl_set_dsp_D0,
475 .set_state_D3 = skl_set_dsp_D3,
476 .load_fw = skl_load_base_firmware,
477 .get_fw_errcode = skl_get_errorcode,
478 .load_mod = skl_load_module,
479 .unload_mod = skl_unload_module,
480};
481
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530482static struct sst_ops skl_ops = {
483 .irq_handler = skl_dsp_sst_interrupt,
484 .write = sst_shim32_write,
485 .read = sst_shim32_read,
486 .ram_read = sst_memcpy_fromio_32,
487 .ram_write = sst_memcpy_toio_32,
488 .free = skl_dsp_free,
489};
490
491static struct sst_dsp_device skl_dev = {
492 .thread = skl_dsp_irq_thread_handler,
493 .ops = &skl_ops,
494};
495
496int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
Vinod Koulaecf6fd2015-11-05 21:34:15 +0530497 const char *fw_name, struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp)
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530498{
499 struct skl_sst *skl;
500 struct sst_dsp *sst;
501 int ret;
502
G Kranthi9fe9c712017-04-25 12:18:19 +0530503 ret = skl_sst_ctx_init(dev, irq, fw_name, dsp_ops, dsp, &skl_dev);
504 if (ret < 0) {
505 dev_err(dev, "%s: no device\n", __func__);
506 return ret;
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530507 }
508
G Kranthi9fe9c712017-04-25 12:18:19 +0530509 skl = *dsp;
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530510 sst = skl->dsp;
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530511 sst->addr.lpe = mmio_base;
512 sst->addr.shim = mmio_base;
513 sst_dsp_mailbox_init(sst, (SKL_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ),
514 SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ);
515
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530516 sst->fw_ops = skl_fw_ops;
517
Jayachandran B052f1032016-06-21 10:17:41 +0530518 skl->cores.count = 2;
Jayachandran B052f1032016-06-21 10:17:41 +0530519
G Kranthi9fe9c712017-04-25 12:18:19 +0530520 return 0;
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530521}
522EXPORT_SYMBOL_GPL(skl_sst_dsp_init);
523
Subhransu S. Prusty89b0d8a2017-04-25 12:18:22 +0530524int kbl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
525 const char *fw_name, struct skl_dsp_loader_ops dsp_ops,
526 struct skl_sst **dsp)
527{
528 struct sst_dsp *sst;
529 int ret;
530
531 ret = skl_sst_dsp_init(dev, mmio_base, irq, fw_name, dsp_ops, dsp);
532 if (ret < 0) {
533 dev_err(dev, "%s: Init failed %d\n", __func__, ret);
534 return ret;
535 }
536
537 sst = (*dsp)->dsp;
538 sst->fw_ops = kbl_fw_ops;
539
540 return 0;
541
542}
543EXPORT_SYMBOL_GPL(kbl_sst_dsp_init);
544
Vinod Koul78cdbbd2016-07-26 18:06:42 +0530545int skl_sst_init_fw(struct device *dev, struct skl_sst *ctx)
546{
547 int ret;
548 struct sst_dsp *sst = ctx->dsp;
549
550 ret = sst->fw_ops.load_fw(sst);
551 if (ret < 0) {
Colin Ian Kingecd286a2016-09-16 18:51:21 +0100552 dev_err(dev, "Load base fw failed : %d\n", ret);
Vinod Koul78cdbbd2016-07-26 18:06:42 +0530553 return ret;
554 }
555
556 skl_dsp_init_core_state(sst);
557 ctx->is_first_boot = false;
558
559 return 0;
560}
561EXPORT_SYMBOL_GPL(skl_sst_init_fw);
562
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530563void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx)
564{
Jeeja KPbc65a322017-01-02 09:50:05 +0530565
566 if (ctx->dsp->fw)
567 release_firmware(ctx->dsp->fw);
Dharageswari R6c5768b2015-12-03 23:29:50 +0530568 skl_clear_module_table(ctx->dsp);
Vinod Koul06711052016-05-30 17:43:00 +0530569 skl_freeup_uuid_list(ctx);
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530570 skl_ipc_free(&ctx->ipc);
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530571 ctx->dsp->ops->free(ctx->dsp);
Dharageswari.R95536d82016-04-28 18:45:25 +0530572 if (ctx->boot_complete) {
573 ctx->dsp->cl_dev.ops.cl_cleanup_controller(ctx->dsp);
574 skl_cldma_int_disable(ctx->dsp);
575 }
Subhransu S. Prustya750ba52015-07-10 22:18:44 +0530576}
577EXPORT_SYMBOL_GPL(skl_sst_dsp_cleanup);
578
579MODULE_LICENSE("GPL v2");
580MODULE_DESCRIPTION("Intel Skylake IPC driver");