skl-sst.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /*
  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. #include <linux/module.h>
  19. #include <linux/delay.h>
  20. #include <linux/device.h>
  21. #include "../common/sst-dsp.h"
  22. #include "../common/sst-dsp-priv.h"
  23. #include "../common/sst-ipc.h"
  24. #include "skl-sst-ipc.h"
  25. #define SKL_BASEFW_TIMEOUT 300
  26. #define SKL_INIT_TIMEOUT 1000
  27. /* Intel HD Audio SRAM Window 0*/
  28. #define SKL_ADSP_SRAM0_BASE 0x8000
  29. /* Firmware status window */
  30. #define SKL_ADSP_FW_STATUS SKL_ADSP_SRAM0_BASE
  31. #define SKL_ADSP_ERROR_CODE (SKL_ADSP_FW_STATUS + 0x4)
  32. #define SKL_INSTANCE_ID 0
  33. #define SKL_BASE_FW_MODULE_ID 0
  34. static bool skl_check_fw_status(struct sst_dsp *ctx, u32 status)
  35. {
  36. u32 cur_sts;
  37. cur_sts = sst_dsp_shim_read(ctx, SKL_ADSP_FW_STATUS) & SKL_FW_STS_MASK;
  38. return (cur_sts == status);
  39. }
  40. static int skl_transfer_firmware(struct sst_dsp *ctx,
  41. const void *basefw, u32 base_fw_size)
  42. {
  43. int ret = 0;
  44. ret = ctx->cl_dev.ops.cl_copy_to_dmabuf(ctx, basefw, base_fw_size);
  45. if (ret < 0)
  46. return ret;
  47. ret = sst_dsp_register_poll(ctx,
  48. SKL_ADSP_FW_STATUS,
  49. SKL_FW_STS_MASK,
  50. SKL_FW_RFW_START,
  51. SKL_BASEFW_TIMEOUT,
  52. "Firmware boot");
  53. ctx->cl_dev.ops.cl_stop_dma(ctx);
  54. return ret;
  55. }
  56. static int skl_load_base_firmware(struct sst_dsp *ctx)
  57. {
  58. int ret = 0, i;
  59. struct skl_sst *skl = ctx->thread_context;
  60. u32 reg;
  61. skl->boot_complete = false;
  62. init_waitqueue_head(&skl->boot_wait);
  63. if (ctx->fw == NULL) {
  64. ret = request_firmware(&ctx->fw, "dsp_fw_release.bin", ctx->dev);
  65. if (ret < 0) {
  66. dev_err(ctx->dev, "Request firmware failed %d\n", ret);
  67. skl_dsp_disable_core(ctx);
  68. return -EIO;
  69. }
  70. }
  71. ret = skl_dsp_boot(ctx);
  72. if (ret < 0) {
  73. dev_err(ctx->dev, "Boot dsp core failed ret: %d", ret);
  74. goto skl_load_base_firmware_failed;
  75. }
  76. ret = skl_cldma_prepare(ctx);
  77. if (ret < 0) {
  78. dev_err(ctx->dev, "CL dma prepare failed : %d", ret);
  79. goto skl_load_base_firmware_failed;
  80. }
  81. /* enable Interrupt */
  82. skl_ipc_int_enable(ctx);
  83. skl_ipc_op_int_enable(ctx);
  84. /* check ROM Status */
  85. for (i = SKL_INIT_TIMEOUT; i > 0; --i) {
  86. if (skl_check_fw_status(ctx, SKL_FW_INIT)) {
  87. dev_dbg(ctx->dev,
  88. "ROM loaded, we can continue with FW loading\n");
  89. break;
  90. }
  91. mdelay(1);
  92. }
  93. if (!i) {
  94. reg = sst_dsp_shim_read(ctx, SKL_ADSP_FW_STATUS);
  95. dev_err(ctx->dev,
  96. "Timeout waiting for ROM init done, reg:0x%x\n", reg);
  97. ret = -EIO;
  98. goto skl_load_base_firmware_failed;
  99. }
  100. ret = skl_transfer_firmware(ctx, ctx->fw->data, ctx->fw->size);
  101. if (ret < 0) {
  102. dev_err(ctx->dev, "Transfer firmware failed%d\n", ret);
  103. goto skl_load_base_firmware_failed;
  104. } else {
  105. ret = wait_event_timeout(skl->boot_wait, skl->boot_complete,
  106. msecs_to_jiffies(SKL_IPC_BOOT_MSECS));
  107. if (ret == 0) {
  108. dev_err(ctx->dev, "DSP boot failed, FW Ready timed-out\n");
  109. ret = -EIO;
  110. goto skl_load_base_firmware_failed;
  111. }
  112. dev_dbg(ctx->dev, "Download firmware successful%d\n", ret);
  113. skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING);
  114. }
  115. return 0;
  116. skl_load_base_firmware_failed:
  117. skl_dsp_disable_core(ctx);
  118. release_firmware(ctx->fw);
  119. ctx->fw = NULL;
  120. return ret;
  121. }
  122. static int skl_set_dsp_D0(struct sst_dsp *ctx)
  123. {
  124. int ret;
  125. ret = skl_load_base_firmware(ctx);
  126. if (ret < 0) {
  127. dev_err(ctx->dev, "unable to load firmware\n");
  128. return ret;
  129. }
  130. skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING);
  131. return ret;
  132. }
  133. static int skl_set_dsp_D3(struct sst_dsp *ctx)
  134. {
  135. int ret;
  136. struct skl_ipc_dxstate_info dx;
  137. struct skl_sst *skl = ctx->thread_context;
  138. dev_dbg(ctx->dev, "In %s:\n", __func__);
  139. mutex_lock(&ctx->mutex);
  140. if (!is_skl_dsp_running(ctx)) {
  141. mutex_unlock(&ctx->mutex);
  142. return 0;
  143. }
  144. mutex_unlock(&ctx->mutex);
  145. dx.core_mask = SKL_DSP_CORE0_MASK;
  146. dx.dx_mask = SKL_IPC_D3_MASK;
  147. ret = skl_ipc_set_dx(&skl->ipc, SKL_INSTANCE_ID, SKL_BASE_FW_MODULE_ID, &dx);
  148. if (ret < 0) {
  149. dev_err(ctx->dev, "Failed to set DSP to D3 state\n");
  150. return ret;
  151. }
  152. ret = skl_dsp_disable_core(ctx);
  153. if (ret < 0) {
  154. dev_err(ctx->dev, "disable dsp core failed ret: %d\n", ret);
  155. ret = -EIO;
  156. }
  157. skl_dsp_set_state_locked(ctx, SKL_DSP_RESET);
  158. /* disable Interrupt */
  159. ctx->cl_dev.ops.cl_cleanup_controller(ctx);
  160. skl_cldma_int_disable(ctx);
  161. skl_ipc_op_int_disable(ctx);
  162. skl_ipc_int_disable(ctx);
  163. return ret;
  164. }
  165. static unsigned int skl_get_errorcode(struct sst_dsp *ctx)
  166. {
  167. return sst_dsp_shim_read(ctx, SKL_ADSP_ERROR_CODE);
  168. }
  169. static struct skl_dsp_fw_ops skl_fw_ops = {
  170. .set_state_D0 = skl_set_dsp_D0,
  171. .set_state_D3 = skl_set_dsp_D3,
  172. .load_fw = skl_load_base_firmware,
  173. .get_fw_errcode = skl_get_errorcode,
  174. };
  175. static struct sst_ops skl_ops = {
  176. .irq_handler = skl_dsp_sst_interrupt,
  177. .write = sst_shim32_write,
  178. .read = sst_shim32_read,
  179. .ram_read = sst_memcpy_fromio_32,
  180. .ram_write = sst_memcpy_toio_32,
  181. .free = skl_dsp_free,
  182. };
  183. static struct sst_dsp_device skl_dev = {
  184. .thread = skl_dsp_irq_thread_handler,
  185. .ops = &skl_ops,
  186. };
  187. int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
  188. struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp)
  189. {
  190. struct skl_sst *skl;
  191. struct sst_dsp *sst;
  192. int ret;
  193. skl = devm_kzalloc(dev, sizeof(*skl), GFP_KERNEL);
  194. if (skl == NULL)
  195. return -ENOMEM;
  196. skl->dev = dev;
  197. skl_dev.thread_context = skl;
  198. skl->dsp = skl_dsp_ctx_init(dev, &skl_dev, irq);
  199. if (!skl->dsp) {
  200. dev_err(skl->dev, "%s: no device\n", __func__);
  201. return -ENODEV;
  202. }
  203. sst = skl->dsp;
  204. sst->addr.lpe = mmio_base;
  205. sst->addr.shim = mmio_base;
  206. sst_dsp_mailbox_init(sst, (SKL_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ),
  207. SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ);
  208. sst->dsp_ops = dsp_ops;
  209. sst->fw_ops = skl_fw_ops;
  210. ret = skl_ipc_init(dev, skl);
  211. if (ret)
  212. return ret;
  213. ret = sst->fw_ops.load_fw(sst);
  214. if (ret < 0) {
  215. dev_err(dev, "Load base fw failed : %d", ret);
  216. return ret;
  217. }
  218. if (dsp)
  219. *dsp = skl;
  220. return 0;
  221. skl_ipc_free(&skl->ipc);
  222. return ret;
  223. }
  224. EXPORT_SYMBOL_GPL(skl_sst_dsp_init);
  225. void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx)
  226. {
  227. skl_ipc_free(&ctx->ipc);
  228. ctx->dsp->cl_dev.ops.cl_cleanup_controller(ctx->dsp);
  229. ctx->dsp->ops->free(ctx->dsp);
  230. }
  231. EXPORT_SYMBOL_GPL(skl_sst_dsp_cleanup);
  232. MODULE_LICENSE("GPL v2");
  233. MODULE_DESCRIPTION("Intel Skylake IPC driver");