skl-sst-ipc.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  1. /*
  2. * skl-sst-ipc.c - Intel skl IPC Support
  3. *
  4. * Copyright (C) 2014-15, Intel Corporation.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as version 2, as
  8. * published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. */
  15. #include <linux/device.h>
  16. #include "../common/sst-dsp.h"
  17. #include "../common/sst-dsp-priv.h"
  18. #include "skl-sst-dsp.h"
  19. #include "skl-sst-ipc.h"
  20. #define IPC_IXC_STATUS_BITS 24
  21. /* Global Message - Generic */
  22. #define IPC_GLB_TYPE_SHIFT 24
  23. #define IPC_GLB_TYPE_MASK (0xf << IPC_GLB_TYPE_SHIFT)
  24. #define IPC_GLB_TYPE(x) ((x) << IPC_GLB_TYPE_SHIFT)
  25. /* Global Message - Reply */
  26. #define IPC_GLB_REPLY_STATUS_SHIFT 24
  27. #define IPC_GLB_REPLY_STATUS_MASK ((0x1 << IPC_GLB_REPLY_STATUS_SHIFT) - 1)
  28. #define IPC_GLB_REPLY_STATUS(x) ((x) << IPC_GLB_REPLY_STATUS_SHIFT)
  29. #define IPC_TIMEOUT_MSECS 3000
  30. #define IPC_EMPTY_LIST_SIZE 8
  31. #define IPC_MSG_TARGET_SHIFT 30
  32. #define IPC_MSG_TARGET_MASK 0x1
  33. #define IPC_MSG_TARGET(x) (((x) & IPC_MSG_TARGET_MASK) \
  34. << IPC_MSG_TARGET_SHIFT)
  35. #define IPC_MSG_DIR_SHIFT 29
  36. #define IPC_MSG_DIR_MASK 0x1
  37. #define IPC_MSG_DIR(x) (((x) & IPC_MSG_DIR_MASK) \
  38. << IPC_MSG_DIR_SHIFT)
  39. /* Global Notification Message */
  40. #define IPC_GLB_NOTIFY_TYPE_SHIFT 16
  41. #define IPC_GLB_NOTIFY_TYPE_MASK 0xFF
  42. #define IPC_GLB_NOTIFY_TYPE(x) (((x) >> IPC_GLB_NOTIFY_TYPE_SHIFT) \
  43. & IPC_GLB_NOTIFY_TYPE_MASK)
  44. #define IPC_GLB_NOTIFY_MSG_TYPE_SHIFT 24
  45. #define IPC_GLB_NOTIFY_MSG_TYPE_MASK 0x1F
  46. #define IPC_GLB_NOTIFY_MSG_TYPE(x) (((x) >> IPC_GLB_NOTIFY_MSG_TYPE_SHIFT) \
  47. & IPC_GLB_NOTIFY_MSG_TYPE_MASK)
  48. #define IPC_GLB_NOTIFY_RSP_SHIFT 29
  49. #define IPC_GLB_NOTIFY_RSP_MASK 0x1
  50. #define IPC_GLB_NOTIFY_RSP_TYPE(x) (((x) >> IPC_GLB_NOTIFY_RSP_SHIFT) \
  51. & IPC_GLB_NOTIFY_RSP_MASK)
  52. /* Pipeline operations */
  53. /* Create pipeline message */
  54. #define IPC_PPL_MEM_SIZE_SHIFT 0
  55. #define IPC_PPL_MEM_SIZE_MASK 0x7FF
  56. #define IPC_PPL_MEM_SIZE(x) (((x) & IPC_PPL_MEM_SIZE_MASK) \
  57. << IPC_PPL_MEM_SIZE_SHIFT)
  58. #define IPC_PPL_TYPE_SHIFT 11
  59. #define IPC_PPL_TYPE_MASK 0x1F
  60. #define IPC_PPL_TYPE(x) (((x) & IPC_PPL_TYPE_MASK) \
  61. << IPC_PPL_TYPE_SHIFT)
  62. #define IPC_INSTANCE_ID_SHIFT 16
  63. #define IPC_INSTANCE_ID_MASK 0xFF
  64. #define IPC_INSTANCE_ID(x) (((x) & IPC_INSTANCE_ID_MASK) \
  65. << IPC_INSTANCE_ID_SHIFT)
  66. /* Set pipeline state message */
  67. #define IPC_PPL_STATE_SHIFT 0
  68. #define IPC_PPL_STATE_MASK 0x1F
  69. #define IPC_PPL_STATE(x) (((x) & IPC_PPL_STATE_MASK) \
  70. << IPC_PPL_STATE_SHIFT)
  71. /* Module operations primary register */
  72. #define IPC_MOD_ID_SHIFT 0
  73. #define IPC_MOD_ID_MASK 0xFFFF
  74. #define IPC_MOD_ID(x) (((x) & IPC_MOD_ID_MASK) \
  75. << IPC_MOD_ID_SHIFT)
  76. #define IPC_MOD_INSTANCE_ID_SHIFT 16
  77. #define IPC_MOD_INSTANCE_ID_MASK 0xFF
  78. #define IPC_MOD_INSTANCE_ID(x) (((x) & IPC_MOD_INSTANCE_ID_MASK) \
  79. << IPC_MOD_INSTANCE_ID_SHIFT)
  80. /* Init instance message extension register */
  81. #define IPC_PARAM_BLOCK_SIZE_SHIFT 0
  82. #define IPC_PARAM_BLOCK_SIZE_MASK 0xFFFF
  83. #define IPC_PARAM_BLOCK_SIZE(x) (((x) & IPC_PARAM_BLOCK_SIZE_MASK) \
  84. << IPC_PARAM_BLOCK_SIZE_SHIFT)
  85. #define IPC_PPL_INSTANCE_ID_SHIFT 16
  86. #define IPC_PPL_INSTANCE_ID_MASK 0xFF
  87. #define IPC_PPL_INSTANCE_ID(x) (((x) & IPC_PPL_INSTANCE_ID_MASK) \
  88. << IPC_PPL_INSTANCE_ID_SHIFT)
  89. #define IPC_CORE_ID_SHIFT 24
  90. #define IPC_CORE_ID_MASK 0x1F
  91. #define IPC_CORE_ID(x) (((x) & IPC_CORE_ID_MASK) \
  92. << IPC_CORE_ID_SHIFT)
  93. /* Bind/Unbind message extension register */
  94. #define IPC_DST_MOD_ID_SHIFT 0
  95. #define IPC_DST_MOD_ID(x) (((x) & IPC_MOD_ID_MASK) \
  96. << IPC_DST_MOD_ID_SHIFT)
  97. #define IPC_DST_MOD_INSTANCE_ID_SHIFT 16
  98. #define IPC_DST_MOD_INSTANCE_ID(x) (((x) & IPC_MOD_INSTANCE_ID_MASK) \
  99. << IPC_DST_MOD_INSTANCE_ID_SHIFT)
  100. #define IPC_DST_QUEUE_SHIFT 24
  101. #define IPC_DST_QUEUE_MASK 0x7
  102. #define IPC_DST_QUEUE(x) (((x) & IPC_DST_QUEUE_MASK) \
  103. << IPC_DST_QUEUE_SHIFT)
  104. #define IPC_SRC_QUEUE_SHIFT 27
  105. #define IPC_SRC_QUEUE_MASK 0x7
  106. #define IPC_SRC_QUEUE(x) (((x) & IPC_SRC_QUEUE_MASK) \
  107. << IPC_SRC_QUEUE_SHIFT)
  108. /* Save pipeline messgae extension register */
  109. #define IPC_DMA_ID_SHIFT 0
  110. #define IPC_DMA_ID_MASK 0x1F
  111. #define IPC_DMA_ID(x) (((x) & IPC_DMA_ID_MASK) \
  112. << IPC_DMA_ID_SHIFT)
  113. /* Large Config message extension register */
  114. #define IPC_DATA_OFFSET_SZ_SHIFT 0
  115. #define IPC_DATA_OFFSET_SZ_MASK 0xFFFFF
  116. #define IPC_DATA_OFFSET_SZ(x) (((x) & IPC_DATA_OFFSET_SZ_MASK) \
  117. << IPC_DATA_OFFSET_SZ_SHIFT)
  118. #define IPC_DATA_OFFSET_SZ_CLEAR ~(IPC_DATA_OFFSET_SZ_MASK \
  119. << IPC_DATA_OFFSET_SZ_SHIFT)
  120. #define IPC_LARGE_PARAM_ID_SHIFT 20
  121. #define IPC_LARGE_PARAM_ID_MASK 0xFF
  122. #define IPC_LARGE_PARAM_ID(x) (((x) & IPC_LARGE_PARAM_ID_MASK) \
  123. << IPC_LARGE_PARAM_ID_SHIFT)
  124. #define IPC_FINAL_BLOCK_SHIFT 28
  125. #define IPC_FINAL_BLOCK_MASK 0x1
  126. #define IPC_FINAL_BLOCK(x) (((x) & IPC_FINAL_BLOCK_MASK) \
  127. << IPC_FINAL_BLOCK_SHIFT)
  128. #define IPC_INITIAL_BLOCK_SHIFT 29
  129. #define IPC_INITIAL_BLOCK_MASK 0x1
  130. #define IPC_INITIAL_BLOCK(x) (((x) & IPC_INITIAL_BLOCK_MASK) \
  131. << IPC_INITIAL_BLOCK_SHIFT)
  132. #define IPC_INITIAL_BLOCK_CLEAR ~(IPC_INITIAL_BLOCK_MASK \
  133. << IPC_INITIAL_BLOCK_SHIFT)
  134. enum skl_ipc_msg_target {
  135. IPC_FW_GEN_MSG = 0,
  136. IPC_MOD_MSG = 1
  137. };
  138. enum skl_ipc_msg_direction {
  139. IPC_MSG_REQUEST = 0,
  140. IPC_MSG_REPLY = 1
  141. };
  142. /* Global Message Types */
  143. enum skl_ipc_glb_type {
  144. IPC_GLB_GET_FW_VERSION = 0, /* Retrieves firmware version */
  145. IPC_GLB_LOAD_MULTIPLE_MODS = 15,
  146. IPC_GLB_UNLOAD_MULTIPLE_MODS = 16,
  147. IPC_GLB_CREATE_PPL = 17,
  148. IPC_GLB_DELETE_PPL = 18,
  149. IPC_GLB_SET_PPL_STATE = 19,
  150. IPC_GLB_GET_PPL_STATE = 20,
  151. IPC_GLB_GET_PPL_CONTEXT_SIZE = 21,
  152. IPC_GLB_SAVE_PPL = 22,
  153. IPC_GLB_RESTORE_PPL = 23,
  154. IPC_GLB_NOTIFY = 26,
  155. IPC_GLB_MAX_IPC_MSG_NUMBER = 31 /* Maximum message number */
  156. };
  157. enum skl_ipc_glb_reply {
  158. IPC_GLB_REPLY_SUCCESS = 0,
  159. IPC_GLB_REPLY_UNKNOWN_MSG_TYPE = 1,
  160. IPC_GLB_REPLY_ERROR_INVALID_PARAM = 2,
  161. IPC_GLB_REPLY_BUSY = 3,
  162. IPC_GLB_REPLY_PENDING = 4,
  163. IPC_GLB_REPLY_FAILURE = 5,
  164. IPC_GLB_REPLY_INVALID_REQUEST = 6,
  165. IPC_GLB_REPLY_OUT_OF_MEMORY = 7,
  166. IPC_GLB_REPLY_OUT_OF_MIPS = 8,
  167. IPC_GLB_REPLY_INVALID_RESOURCE_ID = 9,
  168. IPC_GLB_REPLY_INVALID_RESOURCE_STATE = 10,
  169. IPC_GLB_REPLY_MOD_MGMT_ERROR = 100,
  170. IPC_GLB_REPLY_MOD_LOAD_CL_FAILED = 101,
  171. IPC_GLB_REPLY_MOD_LOAD_INVALID_HASH = 102,
  172. IPC_GLB_REPLY_MOD_UNLOAD_INST_EXIST = 103,
  173. IPC_GLB_REPLY_MOD_NOT_INITIALIZED = 104,
  174. IPC_GLB_REPLY_INVALID_CONFIG_PARAM_ID = 120,
  175. IPC_GLB_REPLY_INVALID_CONFIG_DATA_LEN = 121,
  176. IPC_GLB_REPLY_GATEWAY_NOT_INITIALIZED = 140,
  177. IPC_GLB_REPLY_GATEWAY_NOT_EXIST = 141,
  178. IPC_GLB_REPLY_PPL_NOT_INITIALIZED = 160,
  179. IPC_GLB_REPLY_PPL_NOT_EXIST = 161,
  180. IPC_GLB_REPLY_PPL_SAVE_FAILED = 162,
  181. IPC_GLB_REPLY_PPL_RESTORE_FAILED = 163,
  182. IPC_MAX_STATUS = ((1<<IPC_IXC_STATUS_BITS)-1)
  183. };
  184. enum skl_ipc_notification_type {
  185. IPC_GLB_NOTIFY_GLITCH = 0,
  186. IPC_GLB_NOTIFY_OVERRUN = 1,
  187. IPC_GLB_NOTIFY_UNDERRUN = 2,
  188. IPC_GLB_NOTIFY_END_STREAM = 3,
  189. IPC_GLB_NOTIFY_PHRASE_DETECTED = 4,
  190. IPC_GLB_NOTIFY_RESOURCE_EVENT = 5,
  191. IPC_GLB_NOTIFY_LOG_BUFFER_STATUS = 6,
  192. IPC_GLB_NOTIFY_TIMESTAMP_CAPTURED = 7,
  193. IPC_GLB_NOTIFY_FW_READY = 8
  194. };
  195. /* Module Message Types */
  196. enum skl_ipc_module_msg {
  197. IPC_MOD_INIT_INSTANCE = 0,
  198. IPC_MOD_CONFIG_GET = 1,
  199. IPC_MOD_CONFIG_SET = 2,
  200. IPC_MOD_LARGE_CONFIG_GET = 3,
  201. IPC_MOD_LARGE_CONFIG_SET = 4,
  202. IPC_MOD_BIND = 5,
  203. IPC_MOD_UNBIND = 6,
  204. IPC_MOD_SET_DX = 7
  205. };
  206. static void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data,
  207. size_t tx_size)
  208. {
  209. if (tx_size)
  210. memcpy(msg->tx_data, tx_data, tx_size);
  211. }
  212. static bool skl_ipc_is_dsp_busy(struct sst_dsp *dsp)
  213. {
  214. u32 hipci;
  215. hipci = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCI);
  216. return (hipci & SKL_ADSP_REG_HIPCI_BUSY);
  217. }
  218. /* Lock to be held by caller */
  219. static void skl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg)
  220. {
  221. struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->header);
  222. if (msg->tx_size)
  223. sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size);
  224. sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCIE,
  225. header->extension);
  226. sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCI,
  227. header->primary | SKL_ADSP_REG_HIPCI_BUSY);
  228. }
  229. static struct ipc_message *skl_ipc_reply_get_msg(struct sst_generic_ipc *ipc,
  230. u64 ipc_header)
  231. {
  232. struct ipc_message *msg = NULL;
  233. struct skl_ipc_header *header = (struct skl_ipc_header *)(&ipc_header);
  234. if (list_empty(&ipc->rx_list)) {
  235. dev_err(ipc->dev, "ipc: rx list is empty but received 0x%x\n",
  236. header->primary);
  237. goto out;
  238. }
  239. msg = list_first_entry(&ipc->rx_list, struct ipc_message, list);
  240. out:
  241. return msg;
  242. }
  243. static int skl_ipc_process_notification(struct sst_generic_ipc *ipc,
  244. struct skl_ipc_header header)
  245. {
  246. struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc);
  247. if (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) {
  248. switch (IPC_GLB_NOTIFY_TYPE(header.primary)) {
  249. case IPC_GLB_NOTIFY_UNDERRUN:
  250. dev_err(ipc->dev, "FW Underrun %x\n", header.primary);
  251. break;
  252. case IPC_GLB_NOTIFY_RESOURCE_EVENT:
  253. dev_err(ipc->dev, "MCPS Budget Violation: %x\n",
  254. header.primary);
  255. break;
  256. case IPC_GLB_NOTIFY_FW_READY:
  257. skl->boot_complete = true;
  258. wake_up(&skl->boot_wait);
  259. break;
  260. default:
  261. dev_err(ipc->dev, "ipc: Unhandled error msg=%x",
  262. header.primary);
  263. break;
  264. }
  265. }
  266. return 0;
  267. }
  268. static void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
  269. struct skl_ipc_header header)
  270. {
  271. struct ipc_message *msg;
  272. u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK;
  273. u64 *ipc_header = (u64 *)(&header);
  274. msg = skl_ipc_reply_get_msg(ipc, *ipc_header);
  275. if (msg == NULL) {
  276. dev_dbg(ipc->dev, "ipc: rx list is empty\n");
  277. return;
  278. }
  279. /* first process the header */
  280. switch (reply) {
  281. case IPC_GLB_REPLY_SUCCESS:
  282. dev_info(ipc->dev, "ipc FW reply %x: success\n", header.primary);
  283. break;
  284. case IPC_GLB_REPLY_OUT_OF_MEMORY:
  285. dev_err(ipc->dev, "ipc fw reply: %x: no memory\n", header.primary);
  286. msg->errno = -ENOMEM;
  287. break;
  288. case IPC_GLB_REPLY_BUSY:
  289. dev_err(ipc->dev, "ipc fw reply: %x: Busy\n", header.primary);
  290. msg->errno = -EBUSY;
  291. break;
  292. default:
  293. dev_err(ipc->dev, "Unknown ipc reply: 0x%x", reply);
  294. msg->errno = -EINVAL;
  295. break;
  296. }
  297. if (reply != IPC_GLB_REPLY_SUCCESS) {
  298. dev_err(ipc->dev, "ipc FW reply: reply=%d", reply);
  299. dev_err(ipc->dev, "FW Error Code: %u\n",
  300. ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp));
  301. }
  302. list_del(&msg->list);
  303. sst_ipc_tx_msg_reply_complete(ipc, msg);
  304. }
  305. irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context)
  306. {
  307. struct sst_dsp *dsp = context;
  308. struct skl_sst *skl = sst_dsp_get_thread_context(dsp);
  309. struct sst_generic_ipc *ipc = &skl->ipc;
  310. struct skl_ipc_header header = {0};
  311. u32 hipcie, hipct, hipcte;
  312. int ipc_irq = 0;
  313. if (dsp->intr_status & SKL_ADSPIS_CL_DMA)
  314. skl_cldma_process_intr(dsp);
  315. /* Here we handle IPC interrupts only */
  316. if (!(dsp->intr_status & SKL_ADSPIS_IPC))
  317. return IRQ_NONE;
  318. hipcie = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCIE);
  319. hipct = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCT);
  320. /* reply message from DSP */
  321. if (hipcie & SKL_ADSP_REG_HIPCIE_DONE) {
  322. sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL,
  323. SKL_ADSP_REG_HIPCCTL_DONE, 0);
  324. /* clear DONE bit - tell DSP we have completed the operation */
  325. sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCIE,
  326. SKL_ADSP_REG_HIPCIE_DONE, SKL_ADSP_REG_HIPCIE_DONE);
  327. ipc_irq = 1;
  328. /* unmask Done interrupt */
  329. sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL,
  330. SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE);
  331. }
  332. /* New message from DSP */
  333. if (hipct & SKL_ADSP_REG_HIPCT_BUSY) {
  334. hipcte = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCTE);
  335. header.primary = hipct;
  336. header.extension = hipcte;
  337. dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x",
  338. header.primary);
  339. dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x",
  340. header.extension);
  341. if (IPC_GLB_NOTIFY_RSP_TYPE(header.primary)) {
  342. /* Handle Immediate reply from DSP Core */
  343. skl_ipc_process_reply(ipc, header);
  344. } else {
  345. dev_dbg(dsp->dev, "IPC irq: Notification from firmware\n");
  346. skl_ipc_process_notification(ipc, header);
  347. }
  348. /* clear busy interrupt */
  349. sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCT,
  350. SKL_ADSP_REG_HIPCT_BUSY, SKL_ADSP_REG_HIPCT_BUSY);
  351. ipc_irq = 1;
  352. }
  353. if (ipc_irq == 0)
  354. return IRQ_NONE;
  355. skl_ipc_int_enable(dsp);
  356. /* continue to send any remaining messages... */
  357. queue_kthread_work(&ipc->kworker, &ipc->kwork);
  358. return IRQ_HANDLED;
  359. }
  360. void skl_ipc_int_enable(struct sst_dsp *ctx)
  361. {
  362. sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_ADSPIC,
  363. SKL_ADSPIC_IPC, SKL_ADSPIC_IPC);
  364. }
  365. void skl_ipc_int_disable(struct sst_dsp *ctx)
  366. {
  367. sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPIC,
  368. SKL_ADSPIC_IPC, 0);
  369. }
  370. void skl_ipc_op_int_enable(struct sst_dsp *ctx)
  371. {
  372. /* enable IPC DONE interrupt */
  373. sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL,
  374. SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE);
  375. /* Enable IPC BUSY interrupt */
  376. sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL,
  377. SKL_ADSP_REG_HIPCCTL_BUSY, SKL_ADSP_REG_HIPCCTL_BUSY);
  378. }
  379. void skl_ipc_op_int_disable(struct sst_dsp *ctx)
  380. {
  381. /* disable IPC DONE interrupt */
  382. sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
  383. SKL_ADSP_REG_HIPCCTL_DONE, 0);
  384. /* Disable IPC BUSY interrupt */
  385. sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
  386. SKL_ADSP_REG_HIPCCTL_BUSY, 0);
  387. }
  388. bool skl_ipc_int_status(struct sst_dsp *ctx)
  389. {
  390. return sst_dsp_shim_read_unlocked(ctx,
  391. SKL_ADSP_REG_ADSPIS) & SKL_ADSPIS_IPC;
  392. }
  393. int skl_ipc_init(struct device *dev, struct skl_sst *skl)
  394. {
  395. struct sst_generic_ipc *ipc;
  396. int err;
  397. ipc = &skl->ipc;
  398. ipc->dsp = skl->dsp;
  399. ipc->dev = dev;
  400. ipc->tx_data_max_size = SKL_ADSP_W1_SZ;
  401. ipc->rx_data_max_size = SKL_ADSP_W0_UP_SZ;
  402. err = sst_ipc_init(ipc);
  403. if (err)
  404. return err;
  405. ipc->ops.tx_msg = skl_ipc_tx_msg;
  406. ipc->ops.tx_data_copy = skl_ipc_tx_data_copy;
  407. ipc->ops.is_dsp_busy = skl_ipc_is_dsp_busy;
  408. return 0;
  409. }
  410. void skl_ipc_free(struct sst_generic_ipc *ipc)
  411. {
  412. /* Disable IPC DONE interrupt */
  413. sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL,
  414. SKL_ADSP_REG_HIPCCTL_DONE, 0);
  415. /* Disable IPC BUSY interrupt */
  416. sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL,
  417. SKL_ADSP_REG_HIPCCTL_BUSY, 0);
  418. sst_ipc_fini(ipc);
  419. }
  420. int skl_ipc_create_pipeline(struct sst_generic_ipc *ipc,
  421. u16 ppl_mem_size, u8 ppl_type, u8 instance_id)
  422. {
  423. struct skl_ipc_header header = {0};
  424. u64 *ipc_header = (u64 *)(&header);
  425. int ret;
  426. header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
  427. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  428. header.primary |= IPC_GLB_TYPE(IPC_GLB_CREATE_PPL);
  429. header.primary |= IPC_INSTANCE_ID(instance_id);
  430. header.primary |= IPC_PPL_TYPE(ppl_type);
  431. header.primary |= IPC_PPL_MEM_SIZE(ppl_mem_size);
  432. dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
  433. ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
  434. if (ret < 0) {
  435. dev_err(ipc->dev, "ipc: create pipeline fail, err: %d\n", ret);
  436. return ret;
  437. }
  438. return ret;
  439. }
  440. EXPORT_SYMBOL_GPL(skl_ipc_create_pipeline);
  441. int skl_ipc_delete_pipeline(struct sst_generic_ipc *ipc, u8 instance_id)
  442. {
  443. struct skl_ipc_header header = {0};
  444. u64 *ipc_header = (u64 *)(&header);
  445. int ret;
  446. header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
  447. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  448. header.primary |= IPC_GLB_TYPE(IPC_GLB_DELETE_PPL);
  449. header.primary |= IPC_INSTANCE_ID(instance_id);
  450. dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
  451. ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
  452. if (ret < 0) {
  453. dev_err(ipc->dev, "ipc: delete pipeline failed, err %d\n", ret);
  454. return ret;
  455. }
  456. return 0;
  457. }
  458. EXPORT_SYMBOL_GPL(skl_ipc_delete_pipeline);
  459. int skl_ipc_set_pipeline_state(struct sst_generic_ipc *ipc,
  460. u8 instance_id, enum skl_ipc_pipeline_state state)
  461. {
  462. struct skl_ipc_header header = {0};
  463. u64 *ipc_header = (u64 *)(&header);
  464. int ret;
  465. header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
  466. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  467. header.primary |= IPC_GLB_TYPE(IPC_GLB_SET_PPL_STATE);
  468. header.primary |= IPC_INSTANCE_ID(instance_id);
  469. header.primary |= IPC_PPL_STATE(state);
  470. dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
  471. ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
  472. if (ret < 0) {
  473. dev_err(ipc->dev, "ipc: set pipeline state failed, err: %d\n", ret);
  474. return ret;
  475. }
  476. return ret;
  477. }
  478. EXPORT_SYMBOL_GPL(skl_ipc_set_pipeline_state);
  479. int
  480. skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, u8 instance_id, int dma_id)
  481. {
  482. struct skl_ipc_header header = {0};
  483. u64 *ipc_header = (u64 *)(&header);
  484. int ret;
  485. header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
  486. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  487. header.primary |= IPC_GLB_TYPE(IPC_GLB_SAVE_PPL);
  488. header.primary |= IPC_INSTANCE_ID(instance_id);
  489. header.extension = IPC_DMA_ID(dma_id);
  490. dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
  491. ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
  492. if (ret < 0) {
  493. dev_err(ipc->dev, "ipc: save pipeline failed, err: %d\n", ret);
  494. return ret;
  495. }
  496. return ret;
  497. }
  498. EXPORT_SYMBOL_GPL(skl_ipc_save_pipeline);
  499. int skl_ipc_restore_pipeline(struct sst_generic_ipc *ipc, u8 instance_id)
  500. {
  501. struct skl_ipc_header header = {0};
  502. u64 *ipc_header = (u64 *)(&header);
  503. int ret;
  504. header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
  505. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  506. header.primary |= IPC_GLB_TYPE(IPC_GLB_RESTORE_PPL);
  507. header.primary |= IPC_INSTANCE_ID(instance_id);
  508. dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
  509. ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
  510. if (ret < 0) {
  511. dev_err(ipc->dev, "ipc: restore pipeline failed, err: %d\n", ret);
  512. return ret;
  513. }
  514. return ret;
  515. }
  516. EXPORT_SYMBOL_GPL(skl_ipc_restore_pipeline);
  517. int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id,
  518. u16 module_id, struct skl_ipc_dxstate_info *dx)
  519. {
  520. struct skl_ipc_header header = {0};
  521. u64 *ipc_header = (u64 *)(&header);
  522. int ret;
  523. header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
  524. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  525. header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_DX);
  526. header.primary |= IPC_MOD_INSTANCE_ID(instance_id);
  527. header.primary |= IPC_MOD_ID(module_id);
  528. dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__,
  529. header.primary, header.extension);
  530. ret = sst_ipc_tx_message_wait(ipc, *ipc_header,
  531. dx, sizeof(dx), NULL, 0);
  532. if (ret < 0) {
  533. dev_err(ipc->dev, "ipc: set dx failed, err %d\n", ret);
  534. return ret;
  535. }
  536. return ret;
  537. }
  538. EXPORT_SYMBOL_GPL(skl_ipc_set_dx);
  539. int skl_ipc_init_instance(struct sst_generic_ipc *ipc,
  540. struct skl_ipc_init_instance_msg *msg, void *param_data)
  541. {
  542. struct skl_ipc_header header = {0};
  543. u64 *ipc_header = (u64 *)(&header);
  544. int ret;
  545. u32 *buffer = (u32 *)param_data;
  546. /* param_block_size must be in dwords */
  547. u16 param_block_size = msg->param_data_size / sizeof(u32);
  548. print_hex_dump(KERN_DEBUG, NULL, DUMP_PREFIX_NONE,
  549. 16, 4, buffer, param_block_size, false);
  550. header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
  551. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  552. header.primary |= IPC_GLB_TYPE(IPC_MOD_INIT_INSTANCE);
  553. header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
  554. header.primary |= IPC_MOD_ID(msg->module_id);
  555. header.extension = IPC_CORE_ID(msg->core_id);
  556. header.extension |= IPC_PPL_INSTANCE_ID(msg->ppl_instance_id);
  557. header.extension |= IPC_PARAM_BLOCK_SIZE(param_block_size);
  558. dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__,
  559. header.primary, header.extension);
  560. ret = sst_ipc_tx_message_wait(ipc, *ipc_header, param_data,
  561. msg->param_data_size, NULL, 0);
  562. if (ret < 0) {
  563. dev_err(ipc->dev, "ipc: init instance failed\n");
  564. return ret;
  565. }
  566. return ret;
  567. }
  568. EXPORT_SYMBOL_GPL(skl_ipc_init_instance);
  569. int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc,
  570. struct skl_ipc_bind_unbind_msg *msg)
  571. {
  572. struct skl_ipc_header header = {0};
  573. u64 *ipc_header = (u64 *)(&header);
  574. u8 bind_unbind = msg->bind ? IPC_MOD_BIND : IPC_MOD_UNBIND;
  575. int ret;
  576. header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
  577. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  578. header.primary |= IPC_GLB_TYPE(bind_unbind);
  579. header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
  580. header.primary |= IPC_MOD_ID(msg->module_id);
  581. header.extension = IPC_DST_MOD_ID(msg->dst_module_id);
  582. header.extension |= IPC_DST_MOD_INSTANCE_ID(msg->dst_instance_id);
  583. header.extension |= IPC_DST_QUEUE(msg->dst_queue);
  584. header.extension |= IPC_SRC_QUEUE(msg->src_queue);
  585. dev_dbg(ipc->dev, "In %s hdr=%x ext=%x\n", __func__, header.primary,
  586. header.extension);
  587. ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
  588. if (ret < 0) {
  589. dev_err(ipc->dev, "ipc: bind/unbind faileden");
  590. return ret;
  591. }
  592. return ret;
  593. }
  594. EXPORT_SYMBOL_GPL(skl_ipc_bind_unbind);
  595. int skl_ipc_set_large_config(struct sst_generic_ipc *ipc,
  596. struct skl_ipc_large_config_msg *msg, u32 *param)
  597. {
  598. struct skl_ipc_header header = {0};
  599. u64 *ipc_header = (u64 *)(&header);
  600. int ret = 0;
  601. size_t sz_remaining, tx_size, data_offset;
  602. header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
  603. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  604. header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_SET);
  605. header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
  606. header.primary |= IPC_MOD_ID(msg->module_id);
  607. header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size);
  608. header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id);
  609. header.extension |= IPC_FINAL_BLOCK(0);
  610. header.extension |= IPC_INITIAL_BLOCK(1);
  611. sz_remaining = msg->param_data_size;
  612. data_offset = 0;
  613. while (sz_remaining != 0) {
  614. tx_size = sz_remaining > SKL_ADSP_W1_SZ
  615. ? SKL_ADSP_W1_SZ : sz_remaining;
  616. if (tx_size == sz_remaining)
  617. header.extension |= IPC_FINAL_BLOCK(1);
  618. dev_dbg(ipc->dev, "In %s primary=%#x ext=%#x\n", __func__,
  619. header.primary, header.extension);
  620. dev_dbg(ipc->dev, "transmitting offset: %#x, size: %#x\n",
  621. (unsigned)data_offset, (unsigned)tx_size);
  622. ret = sst_ipc_tx_message_wait(ipc, *ipc_header,
  623. ((char *)param) + data_offset,
  624. tx_size, NULL, 0);
  625. if (ret < 0) {
  626. dev_err(ipc->dev,
  627. "ipc: set large config fail, err: %d\n", ret);
  628. return ret;
  629. }
  630. sz_remaining -= tx_size;
  631. data_offset = msg->param_data_size - sz_remaining;
  632. /* clear the fields */
  633. header.extension &= IPC_INITIAL_BLOCK_CLEAR;
  634. header.extension &= IPC_DATA_OFFSET_SZ_CLEAR;
  635. /* fill the fields */
  636. header.extension |= IPC_INITIAL_BLOCK(0);
  637. header.extension |= IPC_DATA_OFFSET_SZ(data_offset);
  638. }
  639. return ret;
  640. }
  641. EXPORT_SYMBOL_GPL(skl_ipc_set_large_config);