147d7195dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2b81fd263SSubhransu S. Prusty /*
3b81fd263SSubhransu S. Prusty * skl-sst-ipc.c - Intel skl IPC Support
4b81fd263SSubhransu S. Prusty *
5b81fd263SSubhransu S. Prusty * Copyright (C) 2014-15, Intel Corporation.
6b81fd263SSubhransu S. Prusty */
7b81fd263SSubhransu S. Prusty #include <linux/device.h>
8b81fd263SSubhransu S. Prusty
9b81fd263SSubhransu S. Prusty #include "../common/sst-dsp.h"
10b81fd263SSubhransu S. Prusty #include "../common/sst-dsp-priv.h"
11721c3e36SDharageswari.R #include "skl.h"
12b81fd263SSubhransu S. Prusty #include "skl-sst-dsp.h"
13b81fd263SSubhransu S. Prusty #include "skl-sst-ipc.h"
14721c3e36SDharageswari.R #include "sound/hdaudio_ext.h"
15b81fd263SSubhransu S. Prusty
16b81fd263SSubhransu S. Prusty
17b81fd263SSubhransu S. Prusty #define IPC_IXC_STATUS_BITS 24
18b81fd263SSubhransu S. Prusty
19b81fd263SSubhransu S. Prusty /* Global Message - Generic */
20b81fd263SSubhransu S. Prusty #define IPC_GLB_TYPE_SHIFT 24
21b81fd263SSubhransu S. Prusty #define IPC_GLB_TYPE_MASK (0xf << IPC_GLB_TYPE_SHIFT)
22b81fd263SSubhransu S. Prusty #define IPC_GLB_TYPE(x) ((x) << IPC_GLB_TYPE_SHIFT)
23b81fd263SSubhransu S. Prusty
24b81fd263SSubhransu S. Prusty /* Global Message - Reply */
25b81fd263SSubhransu S. Prusty #define IPC_GLB_REPLY_STATUS_SHIFT 24
26b81fd263SSubhransu S. Prusty #define IPC_GLB_REPLY_STATUS_MASK ((0x1 << IPC_GLB_REPLY_STATUS_SHIFT) - 1)
27b81fd263SSubhransu S. Prusty #define IPC_GLB_REPLY_STATUS(x) ((x) << IPC_GLB_REPLY_STATUS_SHIFT)
28b81fd263SSubhransu S. Prusty
29b7d0254cSJeeja KP #define IPC_GLB_REPLY_TYPE_SHIFT 29
30b7d0254cSJeeja KP #define IPC_GLB_REPLY_TYPE_MASK 0x1F
31b7d0254cSJeeja KP #define IPC_GLB_REPLY_TYPE(x) (((x) >> IPC_GLB_REPLY_TYPE_SHIFT) \
32b7d0254cSJeeja KP & IPC_GLB_RPLY_TYPE_MASK)
33b7d0254cSJeeja KP
34b81fd263SSubhransu S. Prusty #define IPC_TIMEOUT_MSECS 3000
35b81fd263SSubhransu S. Prusty
36b81fd263SSubhransu S. Prusty #define IPC_EMPTY_LIST_SIZE 8
37b81fd263SSubhransu S. Prusty
38b81fd263SSubhransu S. Prusty #define IPC_MSG_TARGET_SHIFT 30
39b81fd263SSubhransu S. Prusty #define IPC_MSG_TARGET_MASK 0x1
40b81fd263SSubhransu S. Prusty #define IPC_MSG_TARGET(x) (((x) & IPC_MSG_TARGET_MASK) \
41b81fd263SSubhransu S. Prusty << IPC_MSG_TARGET_SHIFT)
42b81fd263SSubhransu S. Prusty
43b81fd263SSubhransu S. Prusty #define IPC_MSG_DIR_SHIFT 29
44b81fd263SSubhransu S. Prusty #define IPC_MSG_DIR_MASK 0x1
45b81fd263SSubhransu S. Prusty #define IPC_MSG_DIR(x) (((x) & IPC_MSG_DIR_MASK) \
46b81fd263SSubhransu S. Prusty << IPC_MSG_DIR_SHIFT)
47b81fd263SSubhransu S. Prusty /* Global Notification Message */
48b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_TYPE_SHIFT 16
49b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_TYPE_MASK 0xFF
50b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_TYPE(x) (((x) >> IPC_GLB_NOTIFY_TYPE_SHIFT) \
51b81fd263SSubhransu S. Prusty & IPC_GLB_NOTIFY_TYPE_MASK)
52b81fd263SSubhransu S. Prusty
53b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_MSG_TYPE_SHIFT 24
54b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_MSG_TYPE_MASK 0x1F
55b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_MSG_TYPE(x) (((x) >> IPC_GLB_NOTIFY_MSG_TYPE_SHIFT) \
56b81fd263SSubhransu S. Prusty & IPC_GLB_NOTIFY_MSG_TYPE_MASK)
57b81fd263SSubhransu S. Prusty
58b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_RSP_SHIFT 29
59b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_RSP_MASK 0x1
60b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_RSP_TYPE(x) (((x) >> IPC_GLB_NOTIFY_RSP_SHIFT) \
61b81fd263SSubhransu S. Prusty & IPC_GLB_NOTIFY_RSP_MASK)
62b81fd263SSubhransu S. Prusty
63b81fd263SSubhransu S. Prusty /* Pipeline operations */
64b81fd263SSubhransu S. Prusty
65b81fd263SSubhransu S. Prusty /* Create pipeline message */
66b81fd263SSubhransu S. Prusty #define IPC_PPL_MEM_SIZE_SHIFT 0
67b81fd263SSubhransu S. Prusty #define IPC_PPL_MEM_SIZE_MASK 0x7FF
68b81fd263SSubhransu S. Prusty #define IPC_PPL_MEM_SIZE(x) (((x) & IPC_PPL_MEM_SIZE_MASK) \
69b81fd263SSubhransu S. Prusty << IPC_PPL_MEM_SIZE_SHIFT)
70b81fd263SSubhransu S. Prusty
71b81fd263SSubhransu S. Prusty #define IPC_PPL_TYPE_SHIFT 11
72b81fd263SSubhransu S. Prusty #define IPC_PPL_TYPE_MASK 0x1F
73b81fd263SSubhransu S. Prusty #define IPC_PPL_TYPE(x) (((x) & IPC_PPL_TYPE_MASK) \
74b81fd263SSubhransu S. Prusty << IPC_PPL_TYPE_SHIFT)
75b81fd263SSubhransu S. Prusty
76b81fd263SSubhransu S. Prusty #define IPC_INSTANCE_ID_SHIFT 16
77b81fd263SSubhransu S. Prusty #define IPC_INSTANCE_ID_MASK 0xFF
78b81fd263SSubhransu S. Prusty #define IPC_INSTANCE_ID(x) (((x) & IPC_INSTANCE_ID_MASK) \
79b81fd263SSubhransu S. Prusty << IPC_INSTANCE_ID_SHIFT)
80b81fd263SSubhransu S. Prusty
818a0cb236SVinod Koul #define IPC_PPL_LP_MODE_SHIFT 0
828a0cb236SVinod Koul #define IPC_PPL_LP_MODE_MASK 0x1
838a0cb236SVinod Koul #define IPC_PPL_LP_MODE(x) (((x) & IPC_PPL_LP_MODE_MASK) \
848a0cb236SVinod Koul << IPC_PPL_LP_MODE_SHIFT)
858a0cb236SVinod Koul
86b81fd263SSubhransu S. Prusty /* Set pipeline state message */
87b81fd263SSubhransu S. Prusty #define IPC_PPL_STATE_SHIFT 0
88b81fd263SSubhransu S. Prusty #define IPC_PPL_STATE_MASK 0x1F
89b81fd263SSubhransu S. Prusty #define IPC_PPL_STATE(x) (((x) & IPC_PPL_STATE_MASK) \
90b81fd263SSubhransu S. Prusty << IPC_PPL_STATE_SHIFT)
91b81fd263SSubhransu S. Prusty
92b81fd263SSubhransu S. Prusty /* Module operations primary register */
93b81fd263SSubhransu S. Prusty #define IPC_MOD_ID_SHIFT 0
94b81fd263SSubhransu S. Prusty #define IPC_MOD_ID_MASK 0xFFFF
95b81fd263SSubhransu S. Prusty #define IPC_MOD_ID(x) (((x) & IPC_MOD_ID_MASK) \
96b81fd263SSubhransu S. Prusty << IPC_MOD_ID_SHIFT)
97b81fd263SSubhransu S. Prusty
98b81fd263SSubhransu S. Prusty #define IPC_MOD_INSTANCE_ID_SHIFT 16
99b81fd263SSubhransu S. Prusty #define IPC_MOD_INSTANCE_ID_MASK 0xFF
100b81fd263SSubhransu S. Prusty #define IPC_MOD_INSTANCE_ID(x) (((x) & IPC_MOD_INSTANCE_ID_MASK) \
101b81fd263SSubhransu S. Prusty << IPC_MOD_INSTANCE_ID_SHIFT)
102b81fd263SSubhransu S. Prusty
103b81fd263SSubhransu S. Prusty /* Init instance message extension register */
104b81fd263SSubhransu S. Prusty #define IPC_PARAM_BLOCK_SIZE_SHIFT 0
105b81fd263SSubhransu S. Prusty #define IPC_PARAM_BLOCK_SIZE_MASK 0xFFFF
106b81fd263SSubhransu S. Prusty #define IPC_PARAM_BLOCK_SIZE(x) (((x) & IPC_PARAM_BLOCK_SIZE_MASK) \
107b81fd263SSubhransu S. Prusty << IPC_PARAM_BLOCK_SIZE_SHIFT)
108b81fd263SSubhransu S. Prusty
109b81fd263SSubhransu S. Prusty #define IPC_PPL_INSTANCE_ID_SHIFT 16
110b81fd263SSubhransu S. Prusty #define IPC_PPL_INSTANCE_ID_MASK 0xFF
111b81fd263SSubhransu S. Prusty #define IPC_PPL_INSTANCE_ID(x) (((x) & IPC_PPL_INSTANCE_ID_MASK) \
112b81fd263SSubhransu S. Prusty << IPC_PPL_INSTANCE_ID_SHIFT)
113b81fd263SSubhransu S. Prusty
114b81fd263SSubhransu S. Prusty #define IPC_CORE_ID_SHIFT 24
115b81fd263SSubhransu S. Prusty #define IPC_CORE_ID_MASK 0x1F
116b81fd263SSubhransu S. Prusty #define IPC_CORE_ID(x) (((x) & IPC_CORE_ID_MASK) \
117b81fd263SSubhransu S. Prusty << IPC_CORE_ID_SHIFT)
118b81fd263SSubhransu S. Prusty
1193d4006cdSSenthilnathan Veppur #define IPC_DOMAIN_SHIFT 28
1203d4006cdSSenthilnathan Veppur #define IPC_DOMAIN_MASK 0x1
1213d4006cdSSenthilnathan Veppur #define IPC_DOMAIN(x) (((x) & IPC_DOMAIN_MASK) \
1223d4006cdSSenthilnathan Veppur << IPC_DOMAIN_SHIFT)
1233d4006cdSSenthilnathan Veppur
124b81fd263SSubhransu S. Prusty /* Bind/Unbind message extension register */
125b81fd263SSubhransu S. Prusty #define IPC_DST_MOD_ID_SHIFT 0
126b81fd263SSubhransu S. Prusty #define IPC_DST_MOD_ID(x) (((x) & IPC_MOD_ID_MASK) \
127b81fd263SSubhransu S. Prusty << IPC_DST_MOD_ID_SHIFT)
128b81fd263SSubhransu S. Prusty
129b81fd263SSubhransu S. Prusty #define IPC_DST_MOD_INSTANCE_ID_SHIFT 16
130b81fd263SSubhransu S. Prusty #define IPC_DST_MOD_INSTANCE_ID(x) (((x) & IPC_MOD_INSTANCE_ID_MASK) \
131b81fd263SSubhransu S. Prusty << IPC_DST_MOD_INSTANCE_ID_SHIFT)
132b81fd263SSubhransu S. Prusty
133b81fd263SSubhransu S. Prusty #define IPC_DST_QUEUE_SHIFT 24
134b81fd263SSubhransu S. Prusty #define IPC_DST_QUEUE_MASK 0x7
135b81fd263SSubhransu S. Prusty #define IPC_DST_QUEUE(x) (((x) & IPC_DST_QUEUE_MASK) \
136b81fd263SSubhransu S. Prusty << IPC_DST_QUEUE_SHIFT)
137b81fd263SSubhransu S. Prusty
138b81fd263SSubhransu S. Prusty #define IPC_SRC_QUEUE_SHIFT 27
139b81fd263SSubhransu S. Prusty #define IPC_SRC_QUEUE_MASK 0x7
140b81fd263SSubhransu S. Prusty #define IPC_SRC_QUEUE(x) (((x) & IPC_SRC_QUEUE_MASK) \
141b81fd263SSubhransu S. Prusty << IPC_SRC_QUEUE_SHIFT)
1426c5768b3SDharageswari R /* Load Module count */
1436c5768b3SDharageswari R #define IPC_LOAD_MODULE_SHIFT 0
1446c5768b3SDharageswari R #define IPC_LOAD_MODULE_MASK 0xFF
1456c5768b3SDharageswari R #define IPC_LOAD_MODULE_CNT(x) (((x) & IPC_LOAD_MODULE_MASK) \
1466c5768b3SDharageswari R << IPC_LOAD_MODULE_SHIFT)
147b81fd263SSubhransu S. Prusty
148b81fd263SSubhransu S. Prusty /* Save pipeline messgae extension register */
149b81fd263SSubhransu S. Prusty #define IPC_DMA_ID_SHIFT 0
150b81fd263SSubhransu S. Prusty #define IPC_DMA_ID_MASK 0x1F
151b81fd263SSubhransu S. Prusty #define IPC_DMA_ID(x) (((x) & IPC_DMA_ID_MASK) \
152b81fd263SSubhransu S. Prusty << IPC_DMA_ID_SHIFT)
153b81fd263SSubhransu S. Prusty /* Large Config message extension register */
154b81fd263SSubhransu S. Prusty #define IPC_DATA_OFFSET_SZ_SHIFT 0
155b81fd263SSubhransu S. Prusty #define IPC_DATA_OFFSET_SZ_MASK 0xFFFFF
156b81fd263SSubhransu S. Prusty #define IPC_DATA_OFFSET_SZ(x) (((x) & IPC_DATA_OFFSET_SZ_MASK) \
157b81fd263SSubhransu S. Prusty << IPC_DATA_OFFSET_SZ_SHIFT)
158b81fd263SSubhransu S. Prusty #define IPC_DATA_OFFSET_SZ_CLEAR ~(IPC_DATA_OFFSET_SZ_MASK \
159b81fd263SSubhransu S. Prusty << IPC_DATA_OFFSET_SZ_SHIFT)
160b81fd263SSubhransu S. Prusty
161b81fd263SSubhransu S. Prusty #define IPC_LARGE_PARAM_ID_SHIFT 20
162b81fd263SSubhransu S. Prusty #define IPC_LARGE_PARAM_ID_MASK 0xFF
163b81fd263SSubhransu S. Prusty #define IPC_LARGE_PARAM_ID(x) (((x) & IPC_LARGE_PARAM_ID_MASK) \
164b81fd263SSubhransu S. Prusty << IPC_LARGE_PARAM_ID_SHIFT)
165b81fd263SSubhransu S. Prusty
166b81fd263SSubhransu S. Prusty #define IPC_FINAL_BLOCK_SHIFT 28
167b81fd263SSubhransu S. Prusty #define IPC_FINAL_BLOCK_MASK 0x1
168b81fd263SSubhransu S. Prusty #define IPC_FINAL_BLOCK(x) (((x) & IPC_FINAL_BLOCK_MASK) \
169b81fd263SSubhransu S. Prusty << IPC_FINAL_BLOCK_SHIFT)
170b81fd263SSubhransu S. Prusty
171b81fd263SSubhransu S. Prusty #define IPC_INITIAL_BLOCK_SHIFT 29
172b81fd263SSubhransu S. Prusty #define IPC_INITIAL_BLOCK_MASK 0x1
173b81fd263SSubhransu S. Prusty #define IPC_INITIAL_BLOCK(x) (((x) & IPC_INITIAL_BLOCK_MASK) \
174b81fd263SSubhransu S. Prusty << IPC_INITIAL_BLOCK_SHIFT)
175b81fd263SSubhransu S. Prusty #define IPC_INITIAL_BLOCK_CLEAR ~(IPC_INITIAL_BLOCK_MASK \
176b81fd263SSubhransu S. Prusty << IPC_INITIAL_BLOCK_SHIFT)
17741b7523fSPardha Saradhi K /* Set D0ix IPC extension register */
17841b7523fSPardha Saradhi K #define IPC_D0IX_WAKE_SHIFT 0
17941b7523fSPardha Saradhi K #define IPC_D0IX_WAKE_MASK 0x1
18041b7523fSPardha Saradhi K #define IPC_D0IX_WAKE(x) (((x) & IPC_D0IX_WAKE_MASK) \
18141b7523fSPardha Saradhi K << IPC_D0IX_WAKE_SHIFT)
18241b7523fSPardha Saradhi K
18341b7523fSPardha Saradhi K #define IPC_D0IX_STREAMING_SHIFT 1
18441b7523fSPardha Saradhi K #define IPC_D0IX_STREAMING_MASK 0x1
18541b7523fSPardha Saradhi K #define IPC_D0IX_STREAMING(x) (((x) & IPC_D0IX_STREAMING_MASK) \
18641b7523fSPardha Saradhi K << IPC_D0IX_STREAMING_SHIFT)
18741b7523fSPardha Saradhi K
188b81fd263SSubhransu S. Prusty
189b81fd263SSubhransu S. Prusty enum skl_ipc_msg_target {
190b81fd263SSubhransu S. Prusty IPC_FW_GEN_MSG = 0,
191b81fd263SSubhransu S. Prusty IPC_MOD_MSG = 1
192b81fd263SSubhransu S. Prusty };
193b81fd263SSubhransu S. Prusty
194b81fd263SSubhransu S. Prusty enum skl_ipc_msg_direction {
195b81fd263SSubhransu S. Prusty IPC_MSG_REQUEST = 0,
196b81fd263SSubhransu S. Prusty IPC_MSG_REPLY = 1
197b81fd263SSubhransu S. Prusty };
198b81fd263SSubhransu S. Prusty
199b81fd263SSubhransu S. Prusty /* Global Message Types */
200b81fd263SSubhransu S. Prusty enum skl_ipc_glb_type {
201b81fd263SSubhransu S. Prusty IPC_GLB_GET_FW_VERSION = 0, /* Retrieves firmware version */
202b81fd263SSubhransu S. Prusty IPC_GLB_LOAD_MULTIPLE_MODS = 15,
203b81fd263SSubhransu S. Prusty IPC_GLB_UNLOAD_MULTIPLE_MODS = 16,
204b81fd263SSubhransu S. Prusty IPC_GLB_CREATE_PPL = 17,
205b81fd263SSubhransu S. Prusty IPC_GLB_DELETE_PPL = 18,
206b81fd263SSubhransu S. Prusty IPC_GLB_SET_PPL_STATE = 19,
207b81fd263SSubhransu S. Prusty IPC_GLB_GET_PPL_STATE = 20,
208b81fd263SSubhransu S. Prusty IPC_GLB_GET_PPL_CONTEXT_SIZE = 21,
209b81fd263SSubhransu S. Prusty IPC_GLB_SAVE_PPL = 22,
210b81fd263SSubhransu S. Prusty IPC_GLB_RESTORE_PPL = 23,
21120fb2fbdSRamesh Babu IPC_GLB_LOAD_LIBRARY = 24,
212b81fd263SSubhransu S. Prusty IPC_GLB_NOTIFY = 26,
213b81fd263SSubhransu S. Prusty IPC_GLB_MAX_IPC_MSG_NUMBER = 31 /* Maximum message number */
214b81fd263SSubhransu S. Prusty };
215b81fd263SSubhransu S. Prusty
216b81fd263SSubhransu S. Prusty enum skl_ipc_glb_reply {
217b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_SUCCESS = 0,
218b81fd263SSubhransu S. Prusty
219b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_UNKNOWN_MSG_TYPE = 1,
220b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_ERROR_INVALID_PARAM = 2,
221b81fd263SSubhransu S. Prusty
222b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_BUSY = 3,
223b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_PENDING = 4,
224b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_FAILURE = 5,
225b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_INVALID_REQUEST = 6,
226b81fd263SSubhransu S. Prusty
227b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_OUT_OF_MEMORY = 7,
228b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_OUT_OF_MIPS = 8,
229b81fd263SSubhransu S. Prusty
230b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_INVALID_RESOURCE_ID = 9,
231b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_INVALID_RESOURCE_STATE = 10,
232b81fd263SSubhransu S. Prusty
233b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_MOD_MGMT_ERROR = 100,
234b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_MOD_LOAD_CL_FAILED = 101,
235b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_MOD_LOAD_INVALID_HASH = 102,
236b81fd263SSubhransu S. Prusty
237b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_MOD_UNLOAD_INST_EXIST = 103,
238b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_MOD_NOT_INITIALIZED = 104,
239b81fd263SSubhransu S. Prusty
240b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_INVALID_CONFIG_PARAM_ID = 120,
241b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_INVALID_CONFIG_DATA_LEN = 121,
242b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_GATEWAY_NOT_INITIALIZED = 140,
243b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_GATEWAY_NOT_EXIST = 141,
24461f94ee4SSubhransu S. Prusty IPC_GLB_REPLY_SCLK_ALREADY_RUNNING = 150,
24561f94ee4SSubhransu S. Prusty IPC_GLB_REPLY_MCLK_ALREADY_RUNNING = 151,
246b81fd263SSubhransu S. Prusty
247b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_PPL_NOT_INITIALIZED = 160,
248b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_PPL_NOT_EXIST = 161,
249b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_PPL_SAVE_FAILED = 162,
250b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_PPL_RESTORE_FAILED = 163,
251b81fd263SSubhransu S. Prusty
252b81fd263SSubhransu S. Prusty IPC_MAX_STATUS = ((1<<IPC_IXC_STATUS_BITS)-1)
253b81fd263SSubhransu S. Prusty };
254b81fd263SSubhransu S. Prusty
255b81fd263SSubhransu S. Prusty enum skl_ipc_notification_type {
256b81fd263SSubhransu S. Prusty IPC_GLB_NOTIFY_GLITCH = 0,
257b81fd263SSubhransu S. Prusty IPC_GLB_NOTIFY_OVERRUN = 1,
258b81fd263SSubhransu S. Prusty IPC_GLB_NOTIFY_UNDERRUN = 2,
259b81fd263SSubhransu S. Prusty IPC_GLB_NOTIFY_END_STREAM = 3,
260b81fd263SSubhransu S. Prusty IPC_GLB_NOTIFY_PHRASE_DETECTED = 4,
261b81fd263SSubhransu S. Prusty IPC_GLB_NOTIFY_RESOURCE_EVENT = 5,
262b81fd263SSubhransu S. Prusty IPC_GLB_NOTIFY_LOG_BUFFER_STATUS = 6,
263b81fd263SSubhransu S. Prusty IPC_GLB_NOTIFY_TIMESTAMP_CAPTURED = 7,
264b81fd263SSubhransu S. Prusty IPC_GLB_NOTIFY_FW_READY = 8
265b81fd263SSubhransu S. Prusty };
266b81fd263SSubhransu S. Prusty
267b81fd263SSubhransu S. Prusty /* Module Message Types */
268b81fd263SSubhransu S. Prusty enum skl_ipc_module_msg {
269b81fd263SSubhransu S. Prusty IPC_MOD_INIT_INSTANCE = 0,
270b81fd263SSubhransu S. Prusty IPC_MOD_CONFIG_GET = 1,
271b81fd263SSubhransu S. Prusty IPC_MOD_CONFIG_SET = 2,
272b81fd263SSubhransu S. Prusty IPC_MOD_LARGE_CONFIG_GET = 3,
273b81fd263SSubhransu S. Prusty IPC_MOD_LARGE_CONFIG_SET = 4,
274b81fd263SSubhransu S. Prusty IPC_MOD_BIND = 5,
275b81fd263SSubhransu S. Prusty IPC_MOD_UNBIND = 6,
27641b7523fSPardha Saradhi K IPC_MOD_SET_DX = 7,
27741b7523fSPardha Saradhi K IPC_MOD_SET_D0IX = 8
278b81fd263SSubhransu S. Prusty };
279b81fd263SSubhransu S. Prusty
skl_ipc_tx_data_copy(struct ipc_message * msg,char * tx_data,size_t tx_size)2804bdb04f0SGuneshwor Singh void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data,
281b81fd263SSubhransu S. Prusty size_t tx_size)
282b81fd263SSubhransu S. Prusty {
283b81fd263SSubhransu S. Prusty if (tx_size)
284abf31feeSCezary Rojewski memcpy(msg->tx.data, tx_data, tx_size);
285b81fd263SSubhransu S. Prusty }
286b81fd263SSubhransu S. Prusty
skl_ipc_is_dsp_busy(struct sst_dsp * dsp)287b81fd263SSubhransu S. Prusty static bool skl_ipc_is_dsp_busy(struct sst_dsp *dsp)
288b81fd263SSubhransu S. Prusty {
289b81fd263SSubhransu S. Prusty u32 hipci;
290b81fd263SSubhransu S. Prusty
291b81fd263SSubhransu S. Prusty hipci = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCI);
292b81fd263SSubhransu S. Prusty return (hipci & SKL_ADSP_REG_HIPCI_BUSY);
293b81fd263SSubhransu S. Prusty }
294b81fd263SSubhransu S. Prusty
295b81fd263SSubhransu S. Prusty /* Lock to be held by caller */
skl_ipc_tx_msg(struct sst_generic_ipc * ipc,struct ipc_message * msg)296b81fd263SSubhransu S. Prusty static void skl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg)
297b81fd263SSubhransu S. Prusty {
298abf31feeSCezary Rojewski struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->tx.header);
299b81fd263SSubhransu S. Prusty
300abf31feeSCezary Rojewski if (msg->tx.size)
301abf31feeSCezary Rojewski sst_dsp_outbox_write(ipc->dsp, msg->tx.data, msg->tx.size);
302b81fd263SSubhransu S. Prusty sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCIE,
303b81fd263SSubhransu S. Prusty header->extension);
304b81fd263SSubhransu S. Prusty sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCI,
305b81fd263SSubhransu S. Prusty header->primary | SKL_ADSP_REG_HIPCI_BUSY);
306b81fd263SSubhransu S. Prusty }
307b81fd263SSubhransu S. Prusty
skl_ipc_check_D0i0(struct sst_dsp * dsp,bool state)308a83e3b4cSVinod Koul int skl_ipc_check_D0i0(struct sst_dsp *dsp, bool state)
309a83e3b4cSVinod Koul {
310a83e3b4cSVinod Koul int ret;
311a83e3b4cSVinod Koul
312a83e3b4cSVinod Koul /* check D0i3 support */
313a83e3b4cSVinod Koul if (!dsp->fw_ops.set_state_D0i0)
314a83e3b4cSVinod Koul return 0;
315a83e3b4cSVinod Koul
316a83e3b4cSVinod Koul /* Attempt D0i0 or D0i3 based on state */
317a83e3b4cSVinod Koul if (state)
318a83e3b4cSVinod Koul ret = dsp->fw_ops.set_state_D0i0(dsp);
319a83e3b4cSVinod Koul else
320a83e3b4cSVinod Koul ret = dsp->fw_ops.set_state_D0i3(dsp);
321a83e3b4cSVinod Koul
322a83e3b4cSVinod Koul return ret;
323a83e3b4cSVinod Koul }
324a83e3b4cSVinod Koul
skl_ipc_reply_get_msg(struct sst_generic_ipc * ipc,u64 ipc_header)325b81fd263SSubhransu S. Prusty static struct ipc_message *skl_ipc_reply_get_msg(struct sst_generic_ipc *ipc,
326b81fd263SSubhransu S. Prusty u64 ipc_header)
327b81fd263SSubhransu S. Prusty {
328b81fd263SSubhransu S. Prusty struct ipc_message *msg = NULL;
329b81fd263SSubhransu S. Prusty struct skl_ipc_header *header = (struct skl_ipc_header *)(&ipc_header);
330b81fd263SSubhransu S. Prusty
331b81fd263SSubhransu S. Prusty if (list_empty(&ipc->rx_list)) {
332b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "ipc: rx list is empty but received 0x%x\n",
333b81fd263SSubhransu S. Prusty header->primary);
334b81fd263SSubhransu S. Prusty goto out;
335b81fd263SSubhransu S. Prusty }
336b81fd263SSubhransu S. Prusty
337b81fd263SSubhransu S. Prusty msg = list_first_entry(&ipc->rx_list, struct ipc_message, list);
338b81fd263SSubhransu S. Prusty
33926ae2049SGustaw Lewandowski list_del(&msg->list);
340b81fd263SSubhransu S. Prusty out:
341b81fd263SSubhransu S. Prusty return msg;
342b81fd263SSubhransu S. Prusty
343b81fd263SSubhransu S. Prusty }
344b81fd263SSubhransu S. Prusty
skl_ipc_process_notification(struct sst_generic_ipc * ipc,struct skl_ipc_header header)3454bdb04f0SGuneshwor Singh int skl_ipc_process_notification(struct sst_generic_ipc *ipc,
346b81fd263SSubhransu S. Prusty struct skl_ipc_header header)
347b81fd263SSubhransu S. Prusty {
348bcc2a2dcSCezary Rojewski struct skl_dev *skl = container_of(ipc, struct skl_dev, ipc);
349b81fd263SSubhransu S. Prusty
350b81fd263SSubhransu S. Prusty if (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) {
351b81fd263SSubhransu S. Prusty switch (IPC_GLB_NOTIFY_TYPE(header.primary)) {
352b81fd263SSubhransu S. Prusty
353b81fd263SSubhransu S. Prusty case IPC_GLB_NOTIFY_UNDERRUN:
354b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "FW Underrun %x\n", header.primary);
355b81fd263SSubhransu S. Prusty break;
356b81fd263SSubhransu S. Prusty
357b81fd263SSubhransu S. Prusty case IPC_GLB_NOTIFY_RESOURCE_EVENT:
358b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "MCPS Budget Violation: %x\n",
359b81fd263SSubhransu S. Prusty header.primary);
360b81fd263SSubhransu S. Prusty break;
361b81fd263SSubhransu S. Prusty
362b81fd263SSubhransu S. Prusty case IPC_GLB_NOTIFY_FW_READY:
363b81fd263SSubhransu S. Prusty skl->boot_complete = true;
364b81fd263SSubhransu S. Prusty wake_up(&skl->boot_wait);
365b81fd263SSubhransu S. Prusty break;
366b81fd263SSubhransu S. Prusty
367721c3e36SDharageswari.R case IPC_GLB_NOTIFY_PHRASE_DETECTED:
368721c3e36SDharageswari.R dev_dbg(ipc->dev, "***** Phrase Detected **********\n");
369721c3e36SDharageswari.R
370721c3e36SDharageswari.R /*
371721c3e36SDharageswari.R * Per HW recomendation, After phrase detection,
372721c3e36SDharageswari.R * clear the CGCTL.MISCBDCGE.
373721c3e36SDharageswari.R *
374721c3e36SDharageswari.R * This will be set back on stream closure
375721c3e36SDharageswari.R */
376721c3e36SDharageswari.R skl->enable_miscbdcge(ipc->dev, false);
377721c3e36SDharageswari.R skl->miscbdcg_disabled = true;
378721c3e36SDharageswari.R break;
379721c3e36SDharageswari.R
380b81fd263SSubhransu S. Prusty default:
381ecd286a9SColin Ian King dev_err(ipc->dev, "ipc: Unhandled error msg=%x\n",
382b81fd263SSubhransu S. Prusty header.primary);
383b81fd263SSubhransu S. Prusty break;
384b81fd263SSubhransu S. Prusty }
385b81fd263SSubhransu S. Prusty }
386b81fd263SSubhransu S. Prusty
387b81fd263SSubhransu S. Prusty return 0;
388b81fd263SSubhransu S. Prusty }
389b81fd263SSubhransu S. Prusty
390aa15679bSSubhransu S. Prusty struct skl_ipc_err_map {
391aa15679bSSubhransu S. Prusty const char *msg;
392aa15679bSSubhransu S. Prusty enum skl_ipc_glb_reply reply;
393aa15679bSSubhransu S. Prusty int err;
394aa15679bSSubhransu S. Prusty };
395aa15679bSSubhransu S. Prusty
396aa15679bSSubhransu S. Prusty static struct skl_ipc_err_map skl_err_map[] = {
397aa15679bSSubhransu S. Prusty {"DSP out of memory", IPC_GLB_REPLY_OUT_OF_MEMORY, -ENOMEM},
398aa15679bSSubhransu S. Prusty {"DSP busy", IPC_GLB_REPLY_BUSY, -EBUSY},
39961f94ee4SSubhransu S. Prusty {"SCLK already running", IPC_GLB_REPLY_SCLK_ALREADY_RUNNING,
40061f94ee4SSubhransu S. Prusty IPC_GLB_REPLY_SCLK_ALREADY_RUNNING},
40161f94ee4SSubhransu S. Prusty {"MCLK already running", IPC_GLB_REPLY_MCLK_ALREADY_RUNNING,
40261f94ee4SSubhransu S. Prusty IPC_GLB_REPLY_MCLK_ALREADY_RUNNING},
403aa15679bSSubhransu S. Prusty };
404aa15679bSSubhransu S. Prusty
skl_ipc_set_reply_error_code(struct sst_generic_ipc * ipc,u32 reply)405aa15679bSSubhransu S. Prusty static int skl_ipc_set_reply_error_code(struct sst_generic_ipc *ipc, u32 reply)
406b7d0254cSJeeja KP {
407aa15679bSSubhransu S. Prusty int i;
408b7d0254cSJeeja KP
409aa15679bSSubhransu S. Prusty for (i = 0; i < ARRAY_SIZE(skl_err_map); i++) {
410aa15679bSSubhransu S. Prusty if (skl_err_map[i].reply == reply)
411aa15679bSSubhransu S. Prusty break;
412aa15679bSSubhransu S. Prusty }
413b7d0254cSJeeja KP
414aa15679bSSubhransu S. Prusty if (i == ARRAY_SIZE(skl_err_map)) {
415aa15679bSSubhransu S. Prusty dev_err(ipc->dev, "ipc FW reply: %d FW Error Code: %u\n",
416aa15679bSSubhransu S. Prusty reply,
417aa15679bSSubhransu S. Prusty ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp));
418b7d0254cSJeeja KP return -EINVAL;
419b7d0254cSJeeja KP }
420aa15679bSSubhransu S. Prusty
421aa15679bSSubhransu S. Prusty if (skl_err_map[i].err < 0)
422aa15679bSSubhransu S. Prusty dev_err(ipc->dev, "ipc FW reply: %s FW Error Code: %u\n",
423aa15679bSSubhransu S. Prusty skl_err_map[i].msg,
424aa15679bSSubhransu S. Prusty ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp));
425aa15679bSSubhransu S. Prusty else
426aa15679bSSubhransu S. Prusty dev_info(ipc->dev, "ipc FW reply: %s FW Error Code: %u\n",
427aa15679bSSubhransu S. Prusty skl_err_map[i].msg,
428aa15679bSSubhransu S. Prusty ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp));
429aa15679bSSubhransu S. Prusty
430aa15679bSSubhransu S. Prusty return skl_err_map[i].err;
431b7d0254cSJeeja KP }
432b7d0254cSJeeja KP
skl_ipc_process_reply(struct sst_generic_ipc * ipc,struct skl_ipc_header header)4334bdb04f0SGuneshwor Singh void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
434b81fd263SSubhransu S. Prusty struct skl_ipc_header header)
435b81fd263SSubhransu S. Prusty {
436b81fd263SSubhransu S. Prusty struct ipc_message *msg;
437b81fd263SSubhransu S. Prusty u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK;
438b81fd263SSubhransu S. Prusty u64 *ipc_header = (u64 *)(&header);
439bcc2a2dcSCezary Rojewski struct skl_dev *skl = container_of(ipc, struct skl_dev, ipc);
4405cd1f5c3SPardha Saradhi K unsigned long flags;
441b81fd263SSubhransu S. Prusty
4425cd1f5c3SPardha Saradhi K spin_lock_irqsave(&ipc->dsp->spinlock, flags);
443b81fd263SSubhransu S. Prusty msg = skl_ipc_reply_get_msg(ipc, *ipc_header);
4445cd1f5c3SPardha Saradhi K spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
445b81fd263SSubhransu S. Prusty if (msg == NULL) {
446b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "ipc: rx list is empty\n");
447b81fd263SSubhransu S. Prusty return;
448b81fd263SSubhransu S. Prusty }
449b81fd263SSubhransu S. Prusty
450abf31feeSCezary Rojewski msg->rx.header = *ipc_header;
451b81fd263SSubhransu S. Prusty /* first process the header */
452b7d0254cSJeeja KP if (reply == IPC_GLB_REPLY_SUCCESS) {
45391c18325SVedang Patel dev_dbg(ipc->dev, "ipc FW reply %x: success\n", header.primary);
454cce1c7f3SMousami Jana /* copy the rx data from the mailbox */
455abf31feeSCezary Rojewski sst_dsp_inbox_read(ipc->dsp, msg->rx.data, msg->rx.size);
456b7d0254cSJeeja KP switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) {
457b7d0254cSJeeja KP case IPC_GLB_LOAD_MULTIPLE_MODS:
458b6726009SSodhi, VunnyX case IPC_GLB_LOAD_LIBRARY:
459b7d0254cSJeeja KP skl->mod_load_complete = true;
460b7d0254cSJeeja KP skl->mod_load_status = true;
461b7d0254cSJeeja KP wake_up(&skl->mod_load_wait);
462b81fd263SSubhransu S. Prusty break;
463b81fd263SSubhransu S. Prusty
464b81fd263SSubhransu S. Prusty default:
465b81fd263SSubhransu S. Prusty break;
466b81fd263SSubhransu S. Prusty
467b7d0254cSJeeja KP }
468b7d0254cSJeeja KP } else {
469aa15679bSSubhransu S. Prusty msg->errno = skl_ipc_set_reply_error_code(ipc, reply);
470b7d0254cSJeeja KP switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) {
471b7d0254cSJeeja KP case IPC_GLB_LOAD_MULTIPLE_MODS:
472b6726009SSodhi, VunnyX case IPC_GLB_LOAD_LIBRARY:
473b7d0254cSJeeja KP skl->mod_load_complete = true;
474b7d0254cSJeeja KP skl->mod_load_status = false;
475b7d0254cSJeeja KP wake_up(&skl->mod_load_wait);
476b7d0254cSJeeja KP break;
477b7d0254cSJeeja KP
478b7d0254cSJeeja KP default:
479b7d0254cSJeeja KP break;
480b7d0254cSJeeja KP
481b7d0254cSJeeja KP }
48228f3b6f1SOmair M Abdullah }
48328f3b6f1SOmair M Abdullah
4845cd1f5c3SPardha Saradhi K spin_lock_irqsave(&ipc->dsp->spinlock, flags);
485b81fd263SSubhransu S. Prusty sst_ipc_tx_msg_reply_complete(ipc, msg);
4865cd1f5c3SPardha Saradhi K spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
487b81fd263SSubhransu S. Prusty }
488b81fd263SSubhransu S. Prusty
skl_dsp_irq_thread_handler(int irq,void * context)489b81fd263SSubhransu S. Prusty irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context)
490b81fd263SSubhransu S. Prusty {
491b81fd263SSubhransu S. Prusty struct sst_dsp *dsp = context;
492eb062e47SCezary Rojewski struct skl_dev *skl = dsp->thread_context;
493b81fd263SSubhransu S. Prusty struct sst_generic_ipc *ipc = &skl->ipc;
494b81fd263SSubhransu S. Prusty struct skl_ipc_header header = {0};
495b81fd263SSubhransu S. Prusty u32 hipcie, hipct, hipcte;
496b81fd263SSubhransu S. Prusty int ipc_irq = 0;
497b81fd263SSubhransu S. Prusty
4986cb00333SSubhransu S. Prusty if (dsp->intr_status & SKL_ADSPIS_CL_DMA)
4996cb00333SSubhransu S. Prusty skl_cldma_process_intr(dsp);
5006cb00333SSubhransu S. Prusty
501b81fd263SSubhransu S. Prusty /* Here we handle IPC interrupts only */
502b81fd263SSubhransu S. Prusty if (!(dsp->intr_status & SKL_ADSPIS_IPC))
503b81fd263SSubhransu S. Prusty return IRQ_NONE;
504b81fd263SSubhransu S. Prusty
505b81fd263SSubhransu S. Prusty hipcie = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCIE);
506b81fd263SSubhransu S. Prusty hipct = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCT);
50707875939SCezary Rojewski hipcte = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCTE);
508b81fd263SSubhransu S. Prusty
509b81fd263SSubhransu S. Prusty /* reply message from DSP */
510b81fd263SSubhransu S. Prusty if (hipcie & SKL_ADSP_REG_HIPCIE_DONE) {
511b81fd263SSubhransu S. Prusty sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL,
512b81fd263SSubhransu S. Prusty SKL_ADSP_REG_HIPCCTL_DONE, 0);
513b81fd263SSubhransu S. Prusty
514b81fd263SSubhransu S. Prusty /* clear DONE bit - tell DSP we have completed the operation */
515b81fd263SSubhransu S. Prusty sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCIE,
516b81fd263SSubhransu S. Prusty SKL_ADSP_REG_HIPCIE_DONE, SKL_ADSP_REG_HIPCIE_DONE);
517b81fd263SSubhransu S. Prusty
518b81fd263SSubhransu S. Prusty ipc_irq = 1;
519b81fd263SSubhransu S. Prusty
520b81fd263SSubhransu S. Prusty /* unmask Done interrupt */
521b81fd263SSubhransu S. Prusty sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL,
522b81fd263SSubhransu S. Prusty SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE);
523b81fd263SSubhransu S. Prusty }
524b81fd263SSubhransu S. Prusty
525b81fd263SSubhransu S. Prusty /* New message from DSP */
526b81fd263SSubhransu S. Prusty if (hipct & SKL_ADSP_REG_HIPCT_BUSY) {
527b81fd263SSubhransu S. Prusty header.primary = hipct;
528b81fd263SSubhransu S. Prusty header.extension = hipcte;
529ecd286a9SColin Ian King dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x\n",
530b81fd263SSubhransu S. Prusty header.primary);
531ecd286a9SColin Ian King dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x\n",
532b81fd263SSubhransu S. Prusty header.extension);
533b81fd263SSubhransu S. Prusty
534b81fd263SSubhransu S. Prusty if (IPC_GLB_NOTIFY_RSP_TYPE(header.primary)) {
535b81fd263SSubhransu S. Prusty /* Handle Immediate reply from DSP Core */
536b81fd263SSubhransu S. Prusty skl_ipc_process_reply(ipc, header);
537b81fd263SSubhransu S. Prusty } else {
538b81fd263SSubhransu S. Prusty dev_dbg(dsp->dev, "IPC irq: Notification from firmware\n");
539b81fd263SSubhransu S. Prusty skl_ipc_process_notification(ipc, header);
540b81fd263SSubhransu S. Prusty }
541b81fd263SSubhransu S. Prusty /* clear busy interrupt */
542b81fd263SSubhransu S. Prusty sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCT,
543b81fd263SSubhransu S. Prusty SKL_ADSP_REG_HIPCT_BUSY, SKL_ADSP_REG_HIPCT_BUSY);
544b81fd263SSubhransu S. Prusty ipc_irq = 1;
545b81fd263SSubhransu S. Prusty }
546b81fd263SSubhransu S. Prusty
547b81fd263SSubhransu S. Prusty if (ipc_irq == 0)
548b81fd263SSubhransu S. Prusty return IRQ_NONE;
549b81fd263SSubhransu S. Prusty
550b81fd263SSubhransu S. Prusty skl_ipc_int_enable(dsp);
551b81fd263SSubhransu S. Prusty
552b81fd263SSubhransu S. Prusty /* continue to send any remaining messages... */
553786e1c37STakashi Iwai schedule_work(&ipc->kwork);
554b81fd263SSubhransu S. Prusty
555b81fd263SSubhransu S. Prusty return IRQ_HANDLED;
556b81fd263SSubhransu S. Prusty }
557b81fd263SSubhransu S. Prusty
skl_ipc_int_enable(struct sst_dsp * ctx)558b81fd263SSubhransu S. Prusty void skl_ipc_int_enable(struct sst_dsp *ctx)
559b81fd263SSubhransu S. Prusty {
560b81fd263SSubhransu S. Prusty sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_ADSPIC,
561b81fd263SSubhransu S. Prusty SKL_ADSPIC_IPC, SKL_ADSPIC_IPC);
562b81fd263SSubhransu S. Prusty }
563b81fd263SSubhransu S. Prusty
skl_ipc_int_disable(struct sst_dsp * ctx)564b81fd263SSubhransu S. Prusty void skl_ipc_int_disable(struct sst_dsp *ctx)
565b81fd263SSubhransu S. Prusty {
566b81fd263SSubhransu S. Prusty sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPIC,
567b81fd263SSubhransu S. Prusty SKL_ADSPIC_IPC, 0);
568b81fd263SSubhransu S. Prusty }
569b81fd263SSubhransu S. Prusty
skl_ipc_op_int_enable(struct sst_dsp * ctx)570b81fd263SSubhransu S. Prusty void skl_ipc_op_int_enable(struct sst_dsp *ctx)
571b81fd263SSubhransu S. Prusty {
572b81fd263SSubhransu S. Prusty /* enable IPC DONE interrupt */
573b81fd263SSubhransu S. Prusty sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL,
574b81fd263SSubhransu S. Prusty SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE);
575b81fd263SSubhransu S. Prusty
576b81fd263SSubhransu S. Prusty /* Enable IPC BUSY interrupt */
577b81fd263SSubhransu S. Prusty sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL,
578b81fd263SSubhransu S. Prusty SKL_ADSP_REG_HIPCCTL_BUSY, SKL_ADSP_REG_HIPCCTL_BUSY);
579b81fd263SSubhransu S. Prusty }
580b81fd263SSubhransu S. Prusty
skl_ipc_op_int_disable(struct sst_dsp * ctx)58184c9e283SJeeja KP void skl_ipc_op_int_disable(struct sst_dsp *ctx)
58284c9e283SJeeja KP {
58384c9e283SJeeja KP /* disable IPC DONE interrupt */
58484c9e283SJeeja KP sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
58584c9e283SJeeja KP SKL_ADSP_REG_HIPCCTL_DONE, 0);
58684c9e283SJeeja KP
58784c9e283SJeeja KP /* Disable IPC BUSY interrupt */
58884c9e283SJeeja KP sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
58984c9e283SJeeja KP SKL_ADSP_REG_HIPCCTL_BUSY, 0);
59084c9e283SJeeja KP
59184c9e283SJeeja KP }
59284c9e283SJeeja KP
skl_ipc_int_status(struct sst_dsp * ctx)593b81fd263SSubhransu S. Prusty bool skl_ipc_int_status(struct sst_dsp *ctx)
594b81fd263SSubhransu S. Prusty {
595b81fd263SSubhransu S. Prusty return sst_dsp_shim_read_unlocked(ctx,
596b81fd263SSubhransu S. Prusty SKL_ADSP_REG_ADSPIS) & SKL_ADSPIS_IPC;
597b81fd263SSubhransu S. Prusty }
598b81fd263SSubhransu S. Prusty
skl_ipc_init(struct device * dev,struct skl_dev * skl)599bcc2a2dcSCezary Rojewski int skl_ipc_init(struct device *dev, struct skl_dev *skl)
600b81fd263SSubhransu S. Prusty {
601b81fd263SSubhransu S. Prusty struct sst_generic_ipc *ipc;
602b81fd263SSubhransu S. Prusty int err;
603b81fd263SSubhransu S. Prusty
604b81fd263SSubhransu S. Prusty ipc = &skl->ipc;
605b81fd263SSubhransu S. Prusty ipc->dsp = skl->dsp;
606b81fd263SSubhransu S. Prusty ipc->dev = dev;
607b81fd263SSubhransu S. Prusty
608b81fd263SSubhransu S. Prusty ipc->tx_data_max_size = SKL_ADSP_W1_SZ;
609b81fd263SSubhransu S. Prusty ipc->rx_data_max_size = SKL_ADSP_W0_UP_SZ;
610b81fd263SSubhransu S. Prusty
611b81fd263SSubhransu S. Prusty err = sst_ipc_init(ipc);
612b81fd263SSubhransu S. Prusty if (err)
613b81fd263SSubhransu S. Prusty return err;
614b81fd263SSubhransu S. Prusty
615b81fd263SSubhransu S. Prusty ipc->ops.tx_msg = skl_ipc_tx_msg;
616b81fd263SSubhransu S. Prusty ipc->ops.tx_data_copy = skl_ipc_tx_data_copy;
617b81fd263SSubhransu S. Prusty ipc->ops.is_dsp_busy = skl_ipc_is_dsp_busy;
618b81fd263SSubhransu S. Prusty
619b81fd263SSubhransu S. Prusty return 0;
620b81fd263SSubhransu S. Prusty }
621b81fd263SSubhransu S. Prusty
skl_ipc_free(struct sst_generic_ipc * ipc)622b81fd263SSubhransu S. Prusty void skl_ipc_free(struct sst_generic_ipc *ipc)
623b81fd263SSubhransu S. Prusty {
624b81fd263SSubhransu S. Prusty /* Disable IPC DONE interrupt */
625b81fd263SSubhransu S. Prusty sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL,
626b81fd263SSubhransu S. Prusty SKL_ADSP_REG_HIPCCTL_DONE, 0);
627b81fd263SSubhransu S. Prusty
628b81fd263SSubhransu S. Prusty /* Disable IPC BUSY interrupt */
629b81fd263SSubhransu S. Prusty sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL,
630b81fd263SSubhransu S. Prusty SKL_ADSP_REG_HIPCCTL_BUSY, 0);
631a750ba5fSSubhransu S. Prusty
632a750ba5fSSubhransu S. Prusty sst_ipc_fini(ipc);
633b81fd263SSubhransu S. Prusty }
634b81fd263SSubhransu S. Prusty
skl_ipc_create_pipeline(struct sst_generic_ipc * ipc,u16 ppl_mem_size,u8 ppl_type,u8 instance_id,u8 lp_mode)635b81fd263SSubhransu S. Prusty int skl_ipc_create_pipeline(struct sst_generic_ipc *ipc,
6368a0cb236SVinod Koul u16 ppl_mem_size, u8 ppl_type, u8 instance_id, u8 lp_mode)
637b81fd263SSubhransu S. Prusty {
638b81fd263SSubhransu S. Prusty struct skl_ipc_header header = {0};
639abf31feeSCezary Rojewski struct sst_ipc_message request = {0};
640b81fd263SSubhransu S. Prusty int ret;
641b81fd263SSubhransu S. Prusty
642b81fd263SSubhransu S. Prusty header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
643b81fd263SSubhransu S. Prusty header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
644b81fd263SSubhransu S. Prusty header.primary |= IPC_GLB_TYPE(IPC_GLB_CREATE_PPL);
645b81fd263SSubhransu S. Prusty header.primary |= IPC_INSTANCE_ID(instance_id);
646b81fd263SSubhransu S. Prusty header.primary |= IPC_PPL_TYPE(ppl_type);
647b81fd263SSubhransu S. Prusty header.primary |= IPC_PPL_MEM_SIZE(ppl_mem_size);
648b81fd263SSubhransu S. Prusty
6498a0cb236SVinod Koul header.extension = IPC_PPL_LP_MODE(lp_mode);
650abf31feeSCezary Rojewski request.header = *(u64 *)(&header);
6518a0cb236SVinod Koul
652b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
653abf31feeSCezary Rojewski ret = sst_ipc_tx_message_wait(ipc, request, NULL);
654b81fd263SSubhransu S. Prusty if (ret < 0) {
655b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "ipc: create pipeline fail, err: %d\n", ret);
656b81fd263SSubhransu S. Prusty return ret;
657b81fd263SSubhransu S. Prusty }
658b81fd263SSubhransu S. Prusty
659b81fd263SSubhransu S. Prusty return ret;
660b81fd263SSubhransu S. Prusty }
661b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_create_pipeline);
662b81fd263SSubhransu S. Prusty
skl_ipc_delete_pipeline(struct sst_generic_ipc * ipc,u8 instance_id)663b81fd263SSubhransu S. Prusty int skl_ipc_delete_pipeline(struct sst_generic_ipc *ipc, u8 instance_id)
664b81fd263SSubhransu S. Prusty {
665b81fd263SSubhransu S. Prusty struct skl_ipc_header header = {0};
666abf31feeSCezary Rojewski struct sst_ipc_message request = {0};
667b81fd263SSubhransu S. Prusty int ret;
668b81fd263SSubhransu S. Prusty
669b81fd263SSubhransu S. Prusty header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
670b81fd263SSubhransu S. Prusty header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
671b81fd263SSubhransu S. Prusty header.primary |= IPC_GLB_TYPE(IPC_GLB_DELETE_PPL);
672b81fd263SSubhransu S. Prusty header.primary |= IPC_INSTANCE_ID(instance_id);
673abf31feeSCezary Rojewski request.header = *(u64 *)(&header);
674b81fd263SSubhransu S. Prusty
675b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
676abf31feeSCezary Rojewski ret = sst_ipc_tx_message_wait(ipc, request, NULL);
677b81fd263SSubhransu S. Prusty if (ret < 0) {
678b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "ipc: delete pipeline failed, err %d\n", ret);
679b81fd263SSubhransu S. Prusty return ret;
680b81fd263SSubhransu S. Prusty }
681b81fd263SSubhransu S. Prusty
682b81fd263SSubhransu S. Prusty return 0;
683b81fd263SSubhransu S. Prusty }
684b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_delete_pipeline);
685b81fd263SSubhransu S. Prusty
skl_ipc_set_pipeline_state(struct sst_generic_ipc * ipc,u8 instance_id,enum skl_ipc_pipeline_state state)686b81fd263SSubhransu S. Prusty int skl_ipc_set_pipeline_state(struct sst_generic_ipc *ipc,
687b81fd263SSubhransu S. Prusty u8 instance_id, enum skl_ipc_pipeline_state state)
688b81fd263SSubhransu S. Prusty {
689b81fd263SSubhransu S. Prusty struct skl_ipc_header header = {0};
690abf31feeSCezary Rojewski struct sst_ipc_message request = {0};
691b81fd263SSubhransu S. Prusty int ret;
692b81fd263SSubhransu S. Prusty
693b81fd263SSubhransu S. Prusty header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
694b81fd263SSubhransu S. Prusty header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
695b81fd263SSubhransu S. Prusty header.primary |= IPC_GLB_TYPE(IPC_GLB_SET_PPL_STATE);
696b81fd263SSubhransu S. Prusty header.primary |= IPC_INSTANCE_ID(instance_id);
697b81fd263SSubhransu S. Prusty header.primary |= IPC_PPL_STATE(state);
698abf31feeSCezary Rojewski request.header = *(u64 *)(&header);
699b81fd263SSubhransu S. Prusty
700b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
701abf31feeSCezary Rojewski ret = sst_ipc_tx_message_wait(ipc, request, NULL);
702b81fd263SSubhransu S. Prusty if (ret < 0) {
703b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "ipc: set pipeline state failed, err: %d\n", ret);
704b81fd263SSubhransu S. Prusty return ret;
705b81fd263SSubhransu S. Prusty }
706b81fd263SSubhransu S. Prusty return ret;
707b81fd263SSubhransu S. Prusty }
708b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_set_pipeline_state);
709b81fd263SSubhransu S. Prusty
710b81fd263SSubhransu S. Prusty int
skl_ipc_save_pipeline(struct sst_generic_ipc * ipc,u8 instance_id,int dma_id)711b81fd263SSubhransu S. Prusty skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, u8 instance_id, int dma_id)
712b81fd263SSubhransu S. Prusty {
713b81fd263SSubhransu S. Prusty struct skl_ipc_header header = {0};
714abf31feeSCezary Rojewski struct sst_ipc_message request = {0};
715b81fd263SSubhransu S. Prusty int ret;
716b81fd263SSubhransu S. Prusty
717b81fd263SSubhransu S. Prusty header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
718b81fd263SSubhransu S. Prusty header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
719b81fd263SSubhransu S. Prusty header.primary |= IPC_GLB_TYPE(IPC_GLB_SAVE_PPL);
720b81fd263SSubhransu S. Prusty header.primary |= IPC_INSTANCE_ID(instance_id);
721b81fd263SSubhransu S. Prusty
722b81fd263SSubhransu S. Prusty header.extension = IPC_DMA_ID(dma_id);
723abf31feeSCezary Rojewski request.header = *(u64 *)(&header);
724abf31feeSCezary Rojewski
725b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
726abf31feeSCezary Rojewski ret = sst_ipc_tx_message_wait(ipc, request, NULL);
727b81fd263SSubhransu S. Prusty if (ret < 0) {
728b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "ipc: save pipeline failed, err: %d\n", ret);
729b81fd263SSubhransu S. Prusty return ret;
730b81fd263SSubhransu S. Prusty }
731b81fd263SSubhransu S. Prusty
732b81fd263SSubhransu S. Prusty return ret;
733b81fd263SSubhransu S. Prusty }
734b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_save_pipeline);
735b81fd263SSubhransu S. Prusty
skl_ipc_restore_pipeline(struct sst_generic_ipc * ipc,u8 instance_id)736b81fd263SSubhransu S. Prusty int skl_ipc_restore_pipeline(struct sst_generic_ipc *ipc, u8 instance_id)
737b81fd263SSubhransu S. Prusty {
738b81fd263SSubhransu S. Prusty struct skl_ipc_header header = {0};
739abf31feeSCezary Rojewski struct sst_ipc_message request = {0};
740b81fd263SSubhransu S. Prusty int ret;
741b81fd263SSubhransu S. Prusty
742b81fd263SSubhransu S. Prusty header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
743b81fd263SSubhransu S. Prusty header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
744b81fd263SSubhransu S. Prusty header.primary |= IPC_GLB_TYPE(IPC_GLB_RESTORE_PPL);
745b81fd263SSubhransu S. Prusty header.primary |= IPC_INSTANCE_ID(instance_id);
746abf31feeSCezary Rojewski request.header = *(u64 *)(&header);
747b81fd263SSubhransu S. Prusty
748b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
749abf31feeSCezary Rojewski ret = sst_ipc_tx_message_wait(ipc, request, NULL);
750b81fd263SSubhransu S. Prusty if (ret < 0) {
751b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "ipc: restore pipeline failed, err: %d\n", ret);
752b81fd263SSubhransu S. Prusty return ret;
753b81fd263SSubhransu S. Prusty }
754b81fd263SSubhransu S. Prusty
755b81fd263SSubhransu S. Prusty return ret;
756b81fd263SSubhransu S. Prusty }
757b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_restore_pipeline);
758b81fd263SSubhransu S. Prusty
skl_ipc_set_dx(struct sst_generic_ipc * ipc,u8 instance_id,u16 module_id,struct skl_ipc_dxstate_info * dx)759b81fd263SSubhransu S. Prusty int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id,
760b81fd263SSubhransu S. Prusty u16 module_id, struct skl_ipc_dxstate_info *dx)
761b81fd263SSubhransu S. Prusty {
762b81fd263SSubhransu S. Prusty struct skl_ipc_header header = {0};
763abf31feeSCezary Rojewski struct sst_ipc_message request;
764b81fd263SSubhransu S. Prusty int ret;
765b81fd263SSubhransu S. Prusty
766b81fd263SSubhransu S. Prusty header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
767b81fd263SSubhransu S. Prusty header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
768b81fd263SSubhransu S. Prusty header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_DX);
769b81fd263SSubhransu S. Prusty header.primary |= IPC_MOD_INSTANCE_ID(instance_id);
770b81fd263SSubhransu S. Prusty header.primary |= IPC_MOD_ID(module_id);
771b81fd263SSubhransu S. Prusty
772abf31feeSCezary Rojewski request.header = *(u64 *)(&header);
773abf31feeSCezary Rojewski request.data = dx;
774abf31feeSCezary Rojewski request.size = sizeof(*dx);
775abf31feeSCezary Rojewski
776b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__,
777b81fd263SSubhransu S. Prusty header.primary, header.extension);
778abf31feeSCezary Rojewski ret = sst_ipc_tx_message_wait(ipc, request, NULL);
779b81fd263SSubhransu S. Prusty if (ret < 0) {
780b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "ipc: set dx failed, err %d\n", ret);
781b81fd263SSubhransu S. Prusty return ret;
782b81fd263SSubhransu S. Prusty }
783b81fd263SSubhransu S. Prusty
784b81fd263SSubhransu S. Prusty return ret;
785b81fd263SSubhransu S. Prusty }
786b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_set_dx);
787b81fd263SSubhransu S. Prusty
skl_ipc_init_instance(struct sst_generic_ipc * ipc,struct skl_ipc_init_instance_msg * msg,void * param_data)788b81fd263SSubhransu S. Prusty int skl_ipc_init_instance(struct sst_generic_ipc *ipc,
789b81fd263SSubhransu S. Prusty struct skl_ipc_init_instance_msg *msg, void *param_data)
790b81fd263SSubhransu S. Prusty {
791b81fd263SSubhransu S. Prusty struct skl_ipc_header header = {0};
792abf31feeSCezary Rojewski struct sst_ipc_message request;
793b81fd263SSubhransu S. Prusty int ret;
794b81fd263SSubhransu S. Prusty u32 *buffer = (u32 *)param_data;
795b81fd263SSubhransu S. Prusty /* param_block_size must be in dwords */
796b81fd263SSubhransu S. Prusty u16 param_block_size = msg->param_data_size / sizeof(u32);
797b81fd263SSubhransu S. Prusty
79896bd6033SVedang Patel print_hex_dump_debug("Param data:", DUMP_PREFIX_NONE,
799b81fd263SSubhransu S. Prusty 16, 4, buffer, param_block_size, false);
800b81fd263SSubhransu S. Prusty
801b81fd263SSubhransu S. Prusty header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
802b81fd263SSubhransu S. Prusty header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
803b81fd263SSubhransu S. Prusty header.primary |= IPC_GLB_TYPE(IPC_MOD_INIT_INSTANCE);
804b81fd263SSubhransu S. Prusty header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
805b81fd263SSubhransu S. Prusty header.primary |= IPC_MOD_ID(msg->module_id);
806b81fd263SSubhransu S. Prusty
807b81fd263SSubhransu S. Prusty header.extension = IPC_CORE_ID(msg->core_id);
808b81fd263SSubhransu S. Prusty header.extension |= IPC_PPL_INSTANCE_ID(msg->ppl_instance_id);
809b81fd263SSubhransu S. Prusty header.extension |= IPC_PARAM_BLOCK_SIZE(param_block_size);
8103d4006cdSSenthilnathan Veppur header.extension |= IPC_DOMAIN(msg->domain);
811b81fd263SSubhransu S. Prusty
812abf31feeSCezary Rojewski request.header = *(u64 *)(&header);
813abf31feeSCezary Rojewski request.data = param_data;
814abf31feeSCezary Rojewski request.size = msg->param_data_size;
815abf31feeSCezary Rojewski
816b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__,
817b81fd263SSubhransu S. Prusty header.primary, header.extension);
818abf31feeSCezary Rojewski ret = sst_ipc_tx_message_wait(ipc, request, NULL);
819b81fd263SSubhransu S. Prusty
820b81fd263SSubhransu S. Prusty if (ret < 0) {
821b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "ipc: init instance failed\n");
822b81fd263SSubhransu S. Prusty return ret;
823b81fd263SSubhransu S. Prusty }
824b81fd263SSubhransu S. Prusty
825b81fd263SSubhransu S. Prusty return ret;
826b81fd263SSubhransu S. Prusty }
827b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_init_instance);
828b81fd263SSubhransu S. Prusty
skl_ipc_bind_unbind(struct sst_generic_ipc * ipc,struct skl_ipc_bind_unbind_msg * msg)829b81fd263SSubhransu S. Prusty int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc,
830b81fd263SSubhransu S. Prusty struct skl_ipc_bind_unbind_msg *msg)
831b81fd263SSubhransu S. Prusty {
832b81fd263SSubhransu S. Prusty struct skl_ipc_header header = {0};
833abf31feeSCezary Rojewski struct sst_ipc_message request = {0};
834b81fd263SSubhransu S. Prusty u8 bind_unbind = msg->bind ? IPC_MOD_BIND : IPC_MOD_UNBIND;
835b81fd263SSubhransu S. Prusty int ret;
836b81fd263SSubhransu S. Prusty
837b81fd263SSubhransu S. Prusty header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
838b81fd263SSubhransu S. Prusty header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
839b81fd263SSubhransu S. Prusty header.primary |= IPC_GLB_TYPE(bind_unbind);
840b81fd263SSubhransu S. Prusty header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
841b81fd263SSubhransu S. Prusty header.primary |= IPC_MOD_ID(msg->module_id);
842b81fd263SSubhransu S. Prusty
843b81fd263SSubhransu S. Prusty header.extension = IPC_DST_MOD_ID(msg->dst_module_id);
844b81fd263SSubhransu S. Prusty header.extension |= IPC_DST_MOD_INSTANCE_ID(msg->dst_instance_id);
845b81fd263SSubhransu S. Prusty header.extension |= IPC_DST_QUEUE(msg->dst_queue);
846b81fd263SSubhransu S. Prusty header.extension |= IPC_SRC_QUEUE(msg->src_queue);
847abf31feeSCezary Rojewski request.header = *(u64 *)(&header);
848b81fd263SSubhransu S. Prusty
849b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "In %s hdr=%x ext=%x\n", __func__, header.primary,
850b81fd263SSubhransu S. Prusty header.extension);
851abf31feeSCezary Rojewski ret = sst_ipc_tx_message_wait(ipc, request, NULL);
852b81fd263SSubhransu S. Prusty if (ret < 0) {
853ecd286a9SColin Ian King dev_err(ipc->dev, "ipc: bind/unbind failed\n");
854b81fd263SSubhransu S. Prusty return ret;
855b81fd263SSubhransu S. Prusty }
856b81fd263SSubhransu S. Prusty
857b81fd263SSubhransu S. Prusty return ret;
858b81fd263SSubhransu S. Prusty }
859b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_bind_unbind);
860b81fd263SSubhransu S. Prusty
8616c5768b3SDharageswari R /*
8626c5768b3SDharageswari R * In order to load a module we need to send IPC to initiate that. DMA will
8636c5768b3SDharageswari R * performed to load the module memory. The FW supports multiple module load
8646c5768b3SDharageswari R * at single shot, so we can send IPC with N modules represented by
8656c5768b3SDharageswari R * module_cnt
8666c5768b3SDharageswari R */
skl_ipc_load_modules(struct sst_generic_ipc * ipc,u8 module_cnt,void * data)8676c5768b3SDharageswari R int skl_ipc_load_modules(struct sst_generic_ipc *ipc,
8686c5768b3SDharageswari R u8 module_cnt, void *data)
8696c5768b3SDharageswari R {
8706c5768b3SDharageswari R struct skl_ipc_header header = {0};
871abf31feeSCezary Rojewski struct sst_ipc_message request;
8726c5768b3SDharageswari R int ret;
8736c5768b3SDharageswari R
8746c5768b3SDharageswari R header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
8756c5768b3SDharageswari R header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
8766c5768b3SDharageswari R header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_MULTIPLE_MODS);
8776c5768b3SDharageswari R header.primary |= IPC_LOAD_MODULE_CNT(module_cnt);
8786c5768b3SDharageswari R
879abf31feeSCezary Rojewski request.header = *(u64 *)(&header);
880abf31feeSCezary Rojewski request.data = data;
881abf31feeSCezary Rojewski request.size = sizeof(u16) * module_cnt;
882abf31feeSCezary Rojewski
883abf31feeSCezary Rojewski ret = sst_ipc_tx_message_nowait(ipc, request);
8846c5768b3SDharageswari R if (ret < 0)
8856c5768b3SDharageswari R dev_err(ipc->dev, "ipc: load modules failed :%d\n", ret);
8866c5768b3SDharageswari R
8876c5768b3SDharageswari R return ret;
8886c5768b3SDharageswari R }
8896c5768b3SDharageswari R EXPORT_SYMBOL_GPL(skl_ipc_load_modules);
8906c5768b3SDharageswari R
skl_ipc_unload_modules(struct sst_generic_ipc * ipc,u8 module_cnt,void * data)8916c5768b3SDharageswari R int skl_ipc_unload_modules(struct sst_generic_ipc *ipc, u8 module_cnt,
8926c5768b3SDharageswari R void *data)
8936c5768b3SDharageswari R {
8946c5768b3SDharageswari R struct skl_ipc_header header = {0};
895abf31feeSCezary Rojewski struct sst_ipc_message request;
8966c5768b3SDharageswari R int ret;
8976c5768b3SDharageswari R
8986c5768b3SDharageswari R header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
8996c5768b3SDharageswari R header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
9006c5768b3SDharageswari R header.primary |= IPC_GLB_TYPE(IPC_GLB_UNLOAD_MULTIPLE_MODS);
9016c5768b3SDharageswari R header.primary |= IPC_LOAD_MODULE_CNT(module_cnt);
9026c5768b3SDharageswari R
903abf31feeSCezary Rojewski request.header = *(u64 *)(&header);
904abf31feeSCezary Rojewski request.data = data;
905abf31feeSCezary Rojewski request.size = sizeof(u16) * module_cnt;
906abf31feeSCezary Rojewski
907abf31feeSCezary Rojewski ret = sst_ipc_tx_message_wait(ipc, request, NULL);
9086c5768b3SDharageswari R if (ret < 0)
9096c5768b3SDharageswari R dev_err(ipc->dev, "ipc: unload modules failed :%d\n", ret);
9106c5768b3SDharageswari R
9116c5768b3SDharageswari R return ret;
9126c5768b3SDharageswari R }
9136c5768b3SDharageswari R EXPORT_SYMBOL_GPL(skl_ipc_unload_modules);
9146c5768b3SDharageswari R
skl_ipc_set_large_config(struct sst_generic_ipc * ipc,struct skl_ipc_large_config_msg * msg,u32 * param)915b81fd263SSubhransu S. Prusty int skl_ipc_set_large_config(struct sst_generic_ipc *ipc,
916b81fd263SSubhransu S. Prusty struct skl_ipc_large_config_msg *msg, u32 *param)
917b81fd263SSubhransu S. Prusty {
918b81fd263SSubhransu S. Prusty struct skl_ipc_header header = {0};
919abf31feeSCezary Rojewski struct sst_ipc_message request;
920b81fd263SSubhransu S. Prusty int ret = 0;
921b81fd263SSubhransu S. Prusty size_t sz_remaining, tx_size, data_offset;
922b81fd263SSubhransu S. Prusty
923b81fd263SSubhransu S. Prusty header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
924b81fd263SSubhransu S. Prusty header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
925b81fd263SSubhransu S. Prusty header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_SET);
926b81fd263SSubhransu S. Prusty header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
927b81fd263SSubhransu S. Prusty header.primary |= IPC_MOD_ID(msg->module_id);
928b81fd263SSubhransu S. Prusty
929b81fd263SSubhransu S. Prusty header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size);
930b81fd263SSubhransu S. Prusty header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id);
931b81fd263SSubhransu S. Prusty header.extension |= IPC_FINAL_BLOCK(0);
932b81fd263SSubhransu S. Prusty header.extension |= IPC_INITIAL_BLOCK(1);
933b81fd263SSubhransu S. Prusty
934b81fd263SSubhransu S. Prusty sz_remaining = msg->param_data_size;
935b81fd263SSubhransu S. Prusty data_offset = 0;
936b81fd263SSubhransu S. Prusty while (sz_remaining != 0) {
937b81fd263SSubhransu S. Prusty tx_size = sz_remaining > SKL_ADSP_W1_SZ
938b81fd263SSubhransu S. Prusty ? SKL_ADSP_W1_SZ : sz_remaining;
939b81fd263SSubhransu S. Prusty if (tx_size == sz_remaining)
940b81fd263SSubhransu S. Prusty header.extension |= IPC_FINAL_BLOCK(1);
941b81fd263SSubhransu S. Prusty
942b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "In %s primary=%#x ext=%#x\n", __func__,
943b81fd263SSubhransu S. Prusty header.primary, header.extension);
944b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "transmitting offset: %#x, size: %#x\n",
945b81fd263SSubhransu S. Prusty (unsigned)data_offset, (unsigned)tx_size);
946abf31feeSCezary Rojewski
947abf31feeSCezary Rojewski request.header = *(u64 *)(&header);
948abf31feeSCezary Rojewski request.data = ((char *)param) + data_offset;
949abf31feeSCezary Rojewski request.size = tx_size;
950abf31feeSCezary Rojewski ret = sst_ipc_tx_message_wait(ipc, request, NULL);
951b81fd263SSubhransu S. Prusty if (ret < 0) {
952b81fd263SSubhransu S. Prusty dev_err(ipc->dev,
953b81fd263SSubhransu S. Prusty "ipc: set large config fail, err: %d\n", ret);
954b81fd263SSubhransu S. Prusty return ret;
955b81fd263SSubhransu S. Prusty }
956b81fd263SSubhransu S. Prusty sz_remaining -= tx_size;
957b81fd263SSubhransu S. Prusty data_offset = msg->param_data_size - sz_remaining;
958b81fd263SSubhransu S. Prusty
959b81fd263SSubhransu S. Prusty /* clear the fields */
960b81fd263SSubhransu S. Prusty header.extension &= IPC_INITIAL_BLOCK_CLEAR;
961b81fd263SSubhransu S. Prusty header.extension &= IPC_DATA_OFFSET_SZ_CLEAR;
962b81fd263SSubhransu S. Prusty /* fill the fields */
963b81fd263SSubhransu S. Prusty header.extension |= IPC_INITIAL_BLOCK(0);
964b81fd263SSubhransu S. Prusty header.extension |= IPC_DATA_OFFSET_SZ(data_offset);
965b81fd263SSubhransu S. Prusty }
966b81fd263SSubhransu S. Prusty
967b81fd263SSubhransu S. Prusty return ret;
968b81fd263SSubhransu S. Prusty }
969b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_set_large_config);
970cce1c7f3SMousami Jana
skl_ipc_get_large_config(struct sst_generic_ipc * ipc,struct skl_ipc_large_config_msg * msg,u32 ** payload,size_t * bytes)971cce1c7f3SMousami Jana int skl_ipc_get_large_config(struct sst_generic_ipc *ipc,
97236004c42SCezary Rojewski struct skl_ipc_large_config_msg *msg,
97336004c42SCezary Rojewski u32 **payload, size_t *bytes)
974cce1c7f3SMousami Jana {
975cce1c7f3SMousami Jana struct skl_ipc_header header = {0};
97636004c42SCezary Rojewski struct sst_ipc_message request, reply = {0};
97736004c42SCezary Rojewski unsigned int *buf;
97863e45324SCezary Rojewski int ret;
979cce1c7f3SMousami Jana
98036004c42SCezary Rojewski reply.data = kzalloc(SKL_ADSP_W1_SZ, GFP_KERNEL);
98136004c42SCezary Rojewski if (!reply.data)
98236004c42SCezary Rojewski return -ENOMEM;
98336004c42SCezary Rojewski
984cce1c7f3SMousami Jana header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
985cce1c7f3SMousami Jana header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
986cce1c7f3SMousami Jana header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_GET);
987cce1c7f3SMousami Jana header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
988cce1c7f3SMousami Jana header.primary |= IPC_MOD_ID(msg->module_id);
989cce1c7f3SMousami Jana
990cce1c7f3SMousami Jana header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size);
991cce1c7f3SMousami Jana header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id);
992cce1c7f3SMousami Jana header.extension |= IPC_FINAL_BLOCK(1);
993cce1c7f3SMousami Jana header.extension |= IPC_INITIAL_BLOCK(1);
994cce1c7f3SMousami Jana
99536004c42SCezary Rojewski request.header = *(u64 *)&header;
99636004c42SCezary Rojewski request.data = *payload;
99736004c42SCezary Rojewski request.size = *bytes;
99836004c42SCezary Rojewski reply.size = SKL_ADSP_W1_SZ;
99936004c42SCezary Rojewski
1000abf31feeSCezary Rojewski ret = sst_ipc_tx_message_wait(ipc, request, &reply);
100163e45324SCezary Rojewski if (ret < 0)
100263e45324SCezary Rojewski dev_err(ipc->dev, "ipc: get large config fail, err: %d\n", ret);
1003cce1c7f3SMousami Jana
100436004c42SCezary Rojewski reply.size = (reply.header >> 32) & IPC_DATA_OFFSET_SZ_MASK;
100536004c42SCezary Rojewski buf = krealloc(reply.data, reply.size, GFP_KERNEL);
1006*07c7fd07SKamil Duljas if (!buf) {
1007*07c7fd07SKamil Duljas kfree(reply.data);
100836004c42SCezary Rojewski return -ENOMEM;
1009*07c7fd07SKamil Duljas }
101036004c42SCezary Rojewski *payload = buf;
101136004c42SCezary Rojewski *bytes = reply.size;
101236004c42SCezary Rojewski
1013cce1c7f3SMousami Jana return ret;
1014cce1c7f3SMousami Jana }
1015cce1c7f3SMousami Jana EXPORT_SYMBOL_GPL(skl_ipc_get_large_config);
101620fb2fbdSRamesh Babu
skl_sst_ipc_load_library(struct sst_generic_ipc * ipc,u8 dma_id,u8 table_id,bool wait)101720fb2fbdSRamesh Babu int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc,
1018100e7f39SSubhransu S. Prusty u8 dma_id, u8 table_id, bool wait)
101920fb2fbdSRamesh Babu {
102020fb2fbdSRamesh Babu struct skl_ipc_header header = {0};
1021abf31feeSCezary Rojewski struct sst_ipc_message request = {0};
102220fb2fbdSRamesh Babu int ret = 0;
102320fb2fbdSRamesh Babu
102420fb2fbdSRamesh Babu header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
102520fb2fbdSRamesh Babu header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
102620fb2fbdSRamesh Babu header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_LIBRARY);
102720fb2fbdSRamesh Babu header.primary |= IPC_MOD_INSTANCE_ID(table_id);
102820fb2fbdSRamesh Babu header.primary |= IPC_MOD_ID(dma_id);
1029abf31feeSCezary Rojewski request.header = *(u64 *)(&header);
103020fb2fbdSRamesh Babu
1031100e7f39SSubhransu S. Prusty if (wait)
1032abf31feeSCezary Rojewski ret = sst_ipc_tx_message_wait(ipc, request, NULL);
1033100e7f39SSubhransu S. Prusty else
1034abf31feeSCezary Rojewski ret = sst_ipc_tx_message_nowait(ipc, request);
103520fb2fbdSRamesh Babu
103620fb2fbdSRamesh Babu if (ret < 0)
103720fb2fbdSRamesh Babu dev_err(ipc->dev, "ipc: load lib failed\n");
103820fb2fbdSRamesh Babu
103920fb2fbdSRamesh Babu return ret;
104020fb2fbdSRamesh Babu }
104120fb2fbdSRamesh Babu EXPORT_SYMBOL_GPL(skl_sst_ipc_load_library);
104241b7523fSPardha Saradhi K
skl_ipc_set_d0ix(struct sst_generic_ipc * ipc,struct skl_ipc_d0ix_msg * msg)104341b7523fSPardha Saradhi K int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, struct skl_ipc_d0ix_msg *msg)
104441b7523fSPardha Saradhi K {
104541b7523fSPardha Saradhi K struct skl_ipc_header header = {0};
1046abf31feeSCezary Rojewski struct sst_ipc_message request = {0};
104741b7523fSPardha Saradhi K int ret;
104841b7523fSPardha Saradhi K
104941b7523fSPardha Saradhi K header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
105041b7523fSPardha Saradhi K header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
105141b7523fSPardha Saradhi K header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_D0IX);
105241b7523fSPardha Saradhi K header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
105341b7523fSPardha Saradhi K header.primary |= IPC_MOD_ID(msg->module_id);
105441b7523fSPardha Saradhi K
105541b7523fSPardha Saradhi K header.extension = IPC_D0IX_WAKE(msg->wake);
105641b7523fSPardha Saradhi K header.extension |= IPC_D0IX_STREAMING(msg->streaming);
1057abf31feeSCezary Rojewski request.header = *(u64 *)(&header);
105841b7523fSPardha Saradhi K
105941b7523fSPardha Saradhi K dev_dbg(ipc->dev, "In %s primary=%x ext=%x\n", __func__,
106041b7523fSPardha Saradhi K header.primary, header.extension);
106141b7523fSPardha Saradhi K
106241b7523fSPardha Saradhi K /*
106341b7523fSPardha Saradhi K * Use the nopm IPC here as we dont want it checking for D0iX
106441b7523fSPardha Saradhi K */
1065abf31feeSCezary Rojewski ret = sst_ipc_tx_message_nopm(ipc, request, NULL);
106641b7523fSPardha Saradhi K if (ret < 0)
106741b7523fSPardha Saradhi K dev_err(ipc->dev, "ipc: set d0ix failed, err %d\n", ret);
106841b7523fSPardha Saradhi K
106941b7523fSPardha Saradhi K return ret;
107041b7523fSPardha Saradhi K }
107141b7523fSPardha Saradhi K EXPORT_SYMBOL_GPL(skl_ipc_set_d0ix);
1072