cnl-sst-dsp.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * cnl-sst-dsp.c - CNL SST library generic function
  4. *
  5. * Copyright (C) 2016-17, Intel Corporation.
  6. * Author: Guneshwor Singh <[email protected]>
  7. *
  8. * Modified from:
  9. * SKL SST library generic function
  10. * Copyright (C) 2014-15, Intel Corporation.
  11. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  12. *
  13. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  14. */
  15. #include <linux/device.h>
  16. #include "../common/sst-dsp.h"
  17. #include "../common/sst-ipc.h"
  18. #include "../common/sst-dsp-priv.h"
  19. #include "cnl-sst-dsp.h"
  20. /* various timeout values */
  21. #define CNL_DSP_PU_TO 50
  22. #define CNL_DSP_PD_TO 50
  23. #define CNL_DSP_RESET_TO 50
  24. static int
  25. cnl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
  26. {
  27. /* update bits */
  28. sst_dsp_shim_update_bits_unlocked(ctx,
  29. CNL_ADSP_REG_ADSPCS, CNL_ADSPCS_CRST(core_mask),
  30. CNL_ADSPCS_CRST(core_mask));
  31. /* poll with timeout to check if operation successful */
  32. return sst_dsp_register_poll(ctx,
  33. CNL_ADSP_REG_ADSPCS,
  34. CNL_ADSPCS_CRST(core_mask),
  35. CNL_ADSPCS_CRST(core_mask),
  36. CNL_DSP_RESET_TO,
  37. "Set reset");
  38. }
  39. static int
  40. cnl_dsp_core_unset_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
  41. {
  42. /* update bits */
  43. sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
  44. CNL_ADSPCS_CRST(core_mask), 0);
  45. /* poll with timeout to check if operation successful */
  46. return sst_dsp_register_poll(ctx,
  47. CNL_ADSP_REG_ADSPCS,
  48. CNL_ADSPCS_CRST(core_mask),
  49. 0,
  50. CNL_DSP_RESET_TO,
  51. "Unset reset");
  52. }
  53. static bool is_cnl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask)
  54. {
  55. int val;
  56. bool is_enable;
  57. val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPCS);
  58. is_enable = (val & CNL_ADSPCS_CPA(core_mask)) &&
  59. (val & CNL_ADSPCS_SPA(core_mask)) &&
  60. !(val & CNL_ADSPCS_CRST(core_mask)) &&
  61. !(val & CNL_ADSPCS_CSTALL(core_mask));
  62. dev_dbg(ctx->dev, "DSP core(s) enabled? %d: core_mask %#x\n",
  63. is_enable, core_mask);
  64. return is_enable;
  65. }
  66. static int cnl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask)
  67. {
  68. /* stall core */
  69. sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
  70. CNL_ADSPCS_CSTALL(core_mask),
  71. CNL_ADSPCS_CSTALL(core_mask));
  72. /* set reset state */
  73. return cnl_dsp_core_set_reset_state(ctx, core_mask);
  74. }
  75. static int cnl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask)
  76. {
  77. int ret;
  78. /* unset reset state */
  79. ret = cnl_dsp_core_unset_reset_state(ctx, core_mask);
  80. if (ret < 0)
  81. return ret;
  82. /* run core */
  83. sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
  84. CNL_ADSPCS_CSTALL(core_mask), 0);
  85. if (!is_cnl_dsp_core_enable(ctx, core_mask)) {
  86. cnl_dsp_reset_core(ctx, core_mask);
  87. dev_err(ctx->dev, "DSP core mask %#x enable failed\n",
  88. core_mask);
  89. ret = -EIO;
  90. }
  91. return ret;
  92. }
  93. static int cnl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask)
  94. {
  95. /* update bits */
  96. sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
  97. CNL_ADSPCS_SPA(core_mask),
  98. CNL_ADSPCS_SPA(core_mask));
  99. /* poll with timeout to check if operation successful */
  100. return sst_dsp_register_poll(ctx, CNL_ADSP_REG_ADSPCS,
  101. CNL_ADSPCS_CPA(core_mask),
  102. CNL_ADSPCS_CPA(core_mask),
  103. CNL_DSP_PU_TO,
  104. "Power up");
  105. }
  106. static int cnl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask)
  107. {
  108. /* update bits */
  109. sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
  110. CNL_ADSPCS_SPA(core_mask), 0);
  111. /* poll with timeout to check if operation successful */
  112. return sst_dsp_register_poll(ctx,
  113. CNL_ADSP_REG_ADSPCS,
  114. CNL_ADSPCS_CPA(core_mask),
  115. 0,
  116. CNL_DSP_PD_TO,
  117. "Power down");
  118. }
  119. int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask)
  120. {
  121. int ret;
  122. /* power up */
  123. ret = cnl_dsp_core_power_up(ctx, core_mask);
  124. if (ret < 0) {
  125. dev_dbg(ctx->dev, "DSP core mask %#x power up failed",
  126. core_mask);
  127. return ret;
  128. }
  129. return cnl_dsp_start_core(ctx, core_mask);
  130. }
  131. int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask)
  132. {
  133. int ret;
  134. ret = cnl_dsp_reset_core(ctx, core_mask);
  135. if (ret < 0) {
  136. dev_err(ctx->dev, "DSP core mask %#x reset failed\n",
  137. core_mask);
  138. return ret;
  139. }
  140. /* power down core*/
  141. ret = cnl_dsp_core_power_down(ctx, core_mask);
  142. if (ret < 0) {
  143. dev_err(ctx->dev, "DSP core mask %#x power down failed\n",
  144. core_mask);
  145. return ret;
  146. }
  147. if (is_cnl_dsp_core_enable(ctx, core_mask)) {
  148. dev_err(ctx->dev, "DSP core mask %#x disable failed\n",
  149. core_mask);
  150. ret = -EIO;
  151. }
  152. return ret;
  153. }
  154. irqreturn_t cnl_dsp_sst_interrupt(int irq, void *dev_id)
  155. {
  156. struct sst_dsp *ctx = dev_id;
  157. u32 val;
  158. irqreturn_t ret = IRQ_NONE;
  159. spin_lock(&ctx->spinlock);
  160. val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS);
  161. ctx->intr_status = val;
  162. if (val == 0xffffffff) {
  163. spin_unlock(&ctx->spinlock);
  164. return IRQ_NONE;
  165. }
  166. if (val & CNL_ADSPIS_IPC) {
  167. cnl_ipc_int_disable(ctx);
  168. ret = IRQ_WAKE_THREAD;
  169. }
  170. spin_unlock(&ctx->spinlock);
  171. return ret;
  172. }
  173. void cnl_dsp_free(struct sst_dsp *dsp)
  174. {
  175. cnl_ipc_int_disable(dsp);
  176. free_irq(dsp->irq, dsp);
  177. cnl_ipc_op_int_disable(dsp);
  178. cnl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK);
  179. }
  180. EXPORT_SYMBOL_GPL(cnl_dsp_free);
  181. void cnl_ipc_int_enable(struct sst_dsp *ctx)
  182. {
  183. sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_ADSPIC,
  184. CNL_ADSPIC_IPC, CNL_ADSPIC_IPC);
  185. }
  186. void cnl_ipc_int_disable(struct sst_dsp *ctx)
  187. {
  188. sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPIC,
  189. CNL_ADSPIC_IPC, 0);
  190. }
  191. void cnl_ipc_op_int_enable(struct sst_dsp *ctx)
  192. {
  193. /* enable IPC DONE interrupt */
  194. sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
  195. CNL_ADSP_REG_HIPCCTL_DONE,
  196. CNL_ADSP_REG_HIPCCTL_DONE);
  197. /* enable IPC BUSY interrupt */
  198. sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
  199. CNL_ADSP_REG_HIPCCTL_BUSY,
  200. CNL_ADSP_REG_HIPCCTL_BUSY);
  201. }
  202. void cnl_ipc_op_int_disable(struct sst_dsp *ctx)
  203. {
  204. /* disable IPC DONE interrupt */
  205. sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
  206. CNL_ADSP_REG_HIPCCTL_DONE, 0);
  207. /* disable IPC BUSY interrupt */
  208. sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
  209. CNL_ADSP_REG_HIPCCTL_BUSY, 0);
  210. }
  211. bool cnl_ipc_int_status(struct sst_dsp *ctx)
  212. {
  213. return sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS) &
  214. CNL_ADSPIS_IPC;
  215. }
  216. void cnl_ipc_free(struct sst_generic_ipc *ipc)
  217. {
  218. cnl_ipc_op_int_disable(ipc->dsp);
  219. sst_ipc_fini(ipc);
  220. }