2 * skl-sst.c - HDA DSP library functions for SKL platform
4 * Copyright (C) 2014-15, Intel Corporation.
5 * Author:Rafal Redzimski <rafal.f.redzimski@intel.com>
6 * Jeeja KP <jeeja.kp@intel.com>
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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.
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.
19 #include <linux/module.h>
20 #include <linux/delay.h>
21 #include <linux/device.h>
22 #include "../common/sst-dsp.h"
23 #include "../common/sst-dsp-priv.h"
24 #include "../common/sst-ipc.h"
25 #include "skl-sst-ipc.h"
27 #define SKL_BASEFW_TIMEOUT 300
28 #define SKL_INIT_TIMEOUT 1000
30 /* Intel HD Audio SRAM Window 0*/
31 #define SKL_ADSP_SRAM0_BASE 0x8000
33 /* Firmware status window */
34 #define SKL_ADSP_FW_STATUS SKL_ADSP_SRAM0_BASE
35 #define SKL_ADSP_ERROR_CODE (SKL_ADSP_FW_STATUS + 0x4)
37 #define SKL_INSTANCE_ID 0
38 #define SKL_BASE_FW_MODULE_ID 0
40 static bool skl_check_fw_status(struct sst_dsp
*ctx
, u32 status
)
44 cur_sts
= sst_dsp_shim_read(ctx
, SKL_ADSP_FW_STATUS
) & SKL_FW_STS_MASK
;
46 return (cur_sts
== status
);
49 static int skl_transfer_firmware(struct sst_dsp
*ctx
,
50 const void *basefw
, u32 base_fw_size
)
54 ret
= ctx
->cl_dev
.ops
.cl_copy_to_dmabuf(ctx
, basefw
, base_fw_size
);
58 ret
= sst_dsp_register_poll(ctx
,
65 ctx
->cl_dev
.ops
.cl_stop_dma(ctx
);
70 static int skl_load_base_firmware(struct sst_dsp
*ctx
)
73 const struct firmware
*fw
= NULL
;
74 struct skl_sst
*skl
= ctx
->thread_context
;
77 ret
= request_firmware(&fw
, "dsp_fw_release.bin", ctx
->dev
);
79 dev_err(ctx
->dev
, "Request firmware failed %d\n", ret
);
80 skl_dsp_disable_core(ctx
);
84 /* enable Interrupt */
85 skl_ipc_int_enable(ctx
);
86 skl_ipc_op_int_enable(ctx
);
88 /* check ROM Status */
89 for (i
= SKL_INIT_TIMEOUT
; i
> 0; --i
) {
90 if (skl_check_fw_status(ctx
, SKL_FW_INIT
)) {
92 "ROM loaded, we can continue with FW loading\n");
98 reg
= sst_dsp_shim_read(ctx
, SKL_ADSP_FW_STATUS
);
100 "Timeout waiting for ROM init done, reg:0x%x\n", reg
);
102 goto skl_load_base_firmware_failed
;
105 ret
= skl_transfer_firmware(ctx
, fw
->data
, fw
->size
);
107 dev_err(ctx
->dev
, "Transfer firmware failed%d\n", ret
);
108 goto skl_load_base_firmware_failed
;
110 ret
= wait_event_timeout(skl
->boot_wait
, skl
->boot_complete
,
111 msecs_to_jiffies(SKL_IPC_BOOT_MSECS
));
113 dev_err(ctx
->dev
, "DSP boot failed, FW Ready timed-out\n");
115 goto skl_load_base_firmware_failed
;
118 dev_dbg(ctx
->dev
, "Download firmware successful%d\n", ret
);
119 skl_dsp_set_state_locked(ctx
, SKL_DSP_RUNNING
);
121 release_firmware(fw
);
125 skl_load_base_firmware_failed
:
126 skl_dsp_disable_core(ctx
);
127 release_firmware(fw
);
131 static int skl_set_dsp_D0(struct sst_dsp
*ctx
)
135 ret
= skl_load_base_firmware(ctx
);
137 dev_err(ctx
->dev
, "unable to load firmware\n");
141 skl_dsp_set_state_locked(ctx
, SKL_DSP_RUNNING
);
146 static int skl_set_dsp_D3(struct sst_dsp
*ctx
)
149 struct skl_ipc_dxstate_info dx
;
150 struct skl_sst
*skl
= ctx
->thread_context
;
152 dev_dbg(ctx
->dev
, "In %s:\n", __func__
);
153 mutex_lock(&ctx
->mutex
);
154 if (!is_skl_dsp_running(ctx
)) {
155 mutex_unlock(&ctx
->mutex
);
158 mutex_unlock(&ctx
->mutex
);
160 dx
.core_mask
= SKL_DSP_CORE0_MASK
;
161 dx
.dx_mask
= SKL_IPC_D3_MASK
;
162 ret
= skl_ipc_set_dx(&skl
->ipc
, SKL_INSTANCE_ID
, SKL_BASE_FW_MODULE_ID
, &dx
);
164 dev_err(ctx
->dev
, "Failed to set DSP to D3 state\n");
168 ret
= skl_dsp_disable_core(ctx
);
170 dev_err(ctx
->dev
, "disable dsp core failed ret: %d\n", ret
);
173 skl_dsp_set_state_locked(ctx
, SKL_DSP_RESET
);
178 static unsigned int skl_get_errorcode(struct sst_dsp
*ctx
)
180 return sst_dsp_shim_read(ctx
, SKL_ADSP_ERROR_CODE
);
183 static struct skl_dsp_fw_ops skl_fw_ops
= {
184 .set_state_D0
= skl_set_dsp_D0
,
185 .set_state_D3
= skl_set_dsp_D3
,
186 .load_fw
= skl_load_base_firmware
,
187 .get_fw_errcode
= skl_get_errorcode
,
190 static struct sst_ops skl_ops
= {
191 .irq_handler
= skl_dsp_sst_interrupt
,
192 .write
= sst_shim32_write
,
193 .read
= sst_shim32_read
,
194 .ram_read
= sst_memcpy_fromio_32
,
195 .ram_write
= sst_memcpy_toio_32
,
196 .free
= skl_dsp_free
,
199 static struct sst_dsp_device skl_dev
= {
200 .thread
= skl_dsp_irq_thread_handler
,
204 int skl_sst_dsp_init(struct device
*dev
, void __iomem
*mmio_base
, int irq
,
205 struct skl_dsp_loader_ops dsp_ops
, struct skl_sst
**dsp
)
211 skl
= devm_kzalloc(dev
, sizeof(*skl
), GFP_KERNEL
);
216 skl_dev
.thread_context
= skl
;
218 skl
->dsp
= skl_dsp_ctx_init(dev
, &skl_dev
, irq
);
220 dev_err(skl
->dev
, "%s: no device\n", __func__
);
226 sst
->addr
.lpe
= mmio_base
;
227 sst
->addr
.shim
= mmio_base
;
228 sst_dsp_mailbox_init(sst
, (SKL_ADSP_SRAM0_BASE
+ SKL_ADSP_W0_STAT_SZ
),
229 SKL_ADSP_W0_UP_SZ
, SKL_ADSP_SRAM1_BASE
, SKL_ADSP_W1_SZ
);
231 sst
->dsp_ops
= dsp_ops
;
232 sst
->fw_ops
= skl_fw_ops
;
234 ret
= skl_ipc_init(dev
, skl
);
238 skl
->boot_complete
= false;
239 init_waitqueue_head(&skl
->boot_wait
);
241 ret
= skl_dsp_boot(sst
);
243 dev_err(skl
->dev
, "Boot dsp core failed ret: %d", ret
);
247 ret
= skl_cldma_prepare(sst
);
249 dev_err(dev
, "CL dma prepare failed : %d", ret
);
254 ret
= sst
->fw_ops
.load_fw(sst
);
256 dev_err(dev
, "Load base fw failed : %d", ret
);
266 skl_ipc_free(&skl
->ipc
);
269 EXPORT_SYMBOL_GPL(skl_sst_dsp_init
);
271 void skl_sst_dsp_cleanup(struct device
*dev
, struct skl_sst
*ctx
)
273 skl_ipc_free(&ctx
->ipc
);
274 ctx
->dsp
->cl_dev
.ops
.cl_cleanup_controller(ctx
->dsp
);
275 ctx
->dsp
->ops
->free(ctx
->dsp
);
277 EXPORT_SYMBOL_GPL(skl_sst_dsp_cleanup
);
279 MODULE_LICENSE("GPL v2");
280 MODULE_DESCRIPTION("Intel Skylake IPC driver");