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