cnl-sst-dsp.c 6.6 KB

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