1b81fd263SSubhransu S. Prusty /*
2b81fd263SSubhransu S. Prusty  * skl-sst-ipc.c - Intel skl IPC Support
3b81fd263SSubhransu S. Prusty  *
4b81fd263SSubhransu S. Prusty  * Copyright (C) 2014-15, Intel Corporation.
5b81fd263SSubhransu S. Prusty  *
6b81fd263SSubhransu S. Prusty  * This program is free software; you can redistribute it and/or modify
7b81fd263SSubhransu S. Prusty  * it under the terms of the GNU General Public License as version 2, as
8b81fd263SSubhransu S. Prusty  * published by the Free Software Foundation.
9b81fd263SSubhransu S. Prusty  *
10b81fd263SSubhransu S. Prusty  * This program is distributed in the hope that it will be useful, but
11b81fd263SSubhransu S. Prusty  * WITHOUT ANY WARRANTY; without even the implied warranty of
12b81fd263SSubhransu S. Prusty  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13b81fd263SSubhransu S. Prusty  * General Public License for more details.
14b81fd263SSubhransu S. Prusty  */
15b81fd263SSubhransu S. Prusty #include <linux/device.h>
16b81fd263SSubhransu S. Prusty 
17b81fd263SSubhransu S. Prusty #include "../common/sst-dsp.h"
18b81fd263SSubhransu S. Prusty #include "../common/sst-dsp-priv.h"
19721c3e36SDharageswari.R #include "skl.h"
20b81fd263SSubhransu S. Prusty #include "skl-sst-dsp.h"
21b81fd263SSubhransu S. Prusty #include "skl-sst-ipc.h"
22721c3e36SDharageswari.R #include "sound/hdaudio_ext.h"
23b81fd263SSubhransu S. Prusty 
24b81fd263SSubhransu S. Prusty 
25b81fd263SSubhransu S. Prusty #define IPC_IXC_STATUS_BITS		24
26b81fd263SSubhransu S. Prusty 
27b81fd263SSubhransu S. Prusty /* Global Message - Generic */
28b81fd263SSubhransu S. Prusty #define IPC_GLB_TYPE_SHIFT		24
29b81fd263SSubhransu S. Prusty #define IPC_GLB_TYPE_MASK		(0xf << IPC_GLB_TYPE_SHIFT)
30b81fd263SSubhransu S. Prusty #define IPC_GLB_TYPE(x)			((x) << IPC_GLB_TYPE_SHIFT)
31b81fd263SSubhransu S. Prusty 
32b81fd263SSubhransu S. Prusty /* Global Message - Reply */
33b81fd263SSubhransu S. Prusty #define IPC_GLB_REPLY_STATUS_SHIFT	24
34b81fd263SSubhransu S. Prusty #define IPC_GLB_REPLY_STATUS_MASK	((0x1 << IPC_GLB_REPLY_STATUS_SHIFT) - 1)
35b81fd263SSubhransu S. Prusty #define IPC_GLB_REPLY_STATUS(x)		((x) << IPC_GLB_REPLY_STATUS_SHIFT)
36b81fd263SSubhransu S. Prusty 
37b81fd263SSubhransu S. Prusty #define IPC_TIMEOUT_MSECS		3000
38b81fd263SSubhransu S. Prusty 
39b81fd263SSubhransu S. Prusty #define IPC_EMPTY_LIST_SIZE		8
40b81fd263SSubhransu S. Prusty 
41b81fd263SSubhransu S. Prusty #define IPC_MSG_TARGET_SHIFT		30
42b81fd263SSubhransu S. Prusty #define IPC_MSG_TARGET_MASK		0x1
43b81fd263SSubhransu S. Prusty #define IPC_MSG_TARGET(x)		(((x) & IPC_MSG_TARGET_MASK) \
44b81fd263SSubhransu S. Prusty 					<< IPC_MSG_TARGET_SHIFT)
45b81fd263SSubhransu S. Prusty 
46b81fd263SSubhransu S. Prusty #define IPC_MSG_DIR_SHIFT		29
47b81fd263SSubhransu S. Prusty #define IPC_MSG_DIR_MASK		0x1
48b81fd263SSubhransu S. Prusty #define IPC_MSG_DIR(x)			(((x) & IPC_MSG_DIR_MASK) \
49b81fd263SSubhransu S. Prusty 					<< IPC_MSG_DIR_SHIFT)
50b81fd263SSubhransu S. Prusty /* Global Notification Message */
51b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_TYPE_SHIFT	16
52b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_TYPE_MASK	0xFF
53b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_TYPE(x)		(((x) >> IPC_GLB_NOTIFY_TYPE_SHIFT) \
54b81fd263SSubhransu S. Prusty 					& IPC_GLB_NOTIFY_TYPE_MASK)
55b81fd263SSubhransu S. Prusty 
56b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_MSG_TYPE_SHIFT	24
57b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_MSG_TYPE_MASK	0x1F
58b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_MSG_TYPE(x)	(((x) >> IPC_GLB_NOTIFY_MSG_TYPE_SHIFT)	\
59b81fd263SSubhransu S. Prusty 						& IPC_GLB_NOTIFY_MSG_TYPE_MASK)
60b81fd263SSubhransu S. Prusty 
61b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_RSP_SHIFT	29
62b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_RSP_MASK		0x1
63b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_RSP_TYPE(x)	(((x) >> IPC_GLB_NOTIFY_RSP_SHIFT) \
64b81fd263SSubhransu S. Prusty 					& IPC_GLB_NOTIFY_RSP_MASK)
65b81fd263SSubhransu S. Prusty 
66b81fd263SSubhransu S. Prusty /* Pipeline operations */
67b81fd263SSubhransu S. Prusty 
68b81fd263SSubhransu S. Prusty /* Create pipeline message */
69b81fd263SSubhransu S. Prusty #define IPC_PPL_MEM_SIZE_SHIFT		0
70b81fd263SSubhransu S. Prusty #define IPC_PPL_MEM_SIZE_MASK		0x7FF
71b81fd263SSubhransu S. Prusty #define IPC_PPL_MEM_SIZE(x)		(((x) & IPC_PPL_MEM_SIZE_MASK) \
72b81fd263SSubhransu S. Prusty 					<< IPC_PPL_MEM_SIZE_SHIFT)
73b81fd263SSubhransu S. Prusty 
74b81fd263SSubhransu S. Prusty #define IPC_PPL_TYPE_SHIFT		11
75b81fd263SSubhransu S. Prusty #define IPC_PPL_TYPE_MASK		0x1F
76b81fd263SSubhransu S. Prusty #define IPC_PPL_TYPE(x)			(((x) & IPC_PPL_TYPE_MASK) \
77b81fd263SSubhransu S. Prusty 					<< IPC_PPL_TYPE_SHIFT)
78b81fd263SSubhransu S. Prusty 
79b81fd263SSubhransu S. Prusty #define IPC_INSTANCE_ID_SHIFT		16
80b81fd263SSubhransu S. Prusty #define IPC_INSTANCE_ID_MASK		0xFF
81b81fd263SSubhransu S. Prusty #define IPC_INSTANCE_ID(x)		(((x) & IPC_INSTANCE_ID_MASK) \
82b81fd263SSubhransu S. Prusty 					<< IPC_INSTANCE_ID_SHIFT)
83b81fd263SSubhransu S. Prusty 
848a0cb236SVinod Koul #define IPC_PPL_LP_MODE_SHIFT           0
858a0cb236SVinod Koul #define IPC_PPL_LP_MODE_MASK            0x1
868a0cb236SVinod Koul #define IPC_PPL_LP_MODE(x)              (((x) & IPC_PPL_LP_MODE_MASK) \
878a0cb236SVinod Koul 					<< IPC_PPL_LP_MODE_SHIFT)
888a0cb236SVinod Koul 
89b81fd263SSubhransu S. Prusty /* Set pipeline state message */
90b81fd263SSubhransu S. Prusty #define IPC_PPL_STATE_SHIFT		0
91b81fd263SSubhransu S. Prusty #define IPC_PPL_STATE_MASK		0x1F
92b81fd263SSubhransu S. Prusty #define IPC_PPL_STATE(x)		(((x) & IPC_PPL_STATE_MASK) \
93b81fd263SSubhransu S. Prusty 					<< IPC_PPL_STATE_SHIFT)
94b81fd263SSubhransu S. Prusty 
95b81fd263SSubhransu S. Prusty /* Module operations primary register */
96b81fd263SSubhransu S. Prusty #define IPC_MOD_ID_SHIFT		0
97b81fd263SSubhransu S. Prusty #define IPC_MOD_ID_MASK		0xFFFF
98b81fd263SSubhransu S. Prusty #define IPC_MOD_ID(x)		(((x) & IPC_MOD_ID_MASK) \
99b81fd263SSubhransu S. Prusty 					<< IPC_MOD_ID_SHIFT)
100b81fd263SSubhransu S. Prusty 
101b81fd263SSubhransu S. Prusty #define IPC_MOD_INSTANCE_ID_SHIFT	16
102b81fd263SSubhransu S. Prusty #define IPC_MOD_INSTANCE_ID_MASK	0xFF
103b81fd263SSubhransu S. Prusty #define IPC_MOD_INSTANCE_ID(x)	(((x) & IPC_MOD_INSTANCE_ID_MASK) \
104b81fd263SSubhransu S. Prusty 					<< IPC_MOD_INSTANCE_ID_SHIFT)
105b81fd263SSubhransu S. Prusty 
106b81fd263SSubhransu S. Prusty /* Init instance message extension register */
107b81fd263SSubhransu S. Prusty #define IPC_PARAM_BLOCK_SIZE_SHIFT	0
108b81fd263SSubhransu S. Prusty #define IPC_PARAM_BLOCK_SIZE_MASK	0xFFFF
109b81fd263SSubhransu S. Prusty #define IPC_PARAM_BLOCK_SIZE(x)		(((x) & IPC_PARAM_BLOCK_SIZE_MASK) \
110b81fd263SSubhransu S. Prusty 					<< IPC_PARAM_BLOCK_SIZE_SHIFT)
111b81fd263SSubhransu S. Prusty 
112b81fd263SSubhransu S. Prusty #define IPC_PPL_INSTANCE_ID_SHIFT	16
113b81fd263SSubhransu S. Prusty #define IPC_PPL_INSTANCE_ID_MASK	0xFF
114b81fd263SSubhransu S. Prusty #define IPC_PPL_INSTANCE_ID(x)		(((x) & IPC_PPL_INSTANCE_ID_MASK) \
115b81fd263SSubhransu S. Prusty 					<< IPC_PPL_INSTANCE_ID_SHIFT)
116b81fd263SSubhransu S. Prusty 
117b81fd263SSubhransu S. Prusty #define IPC_CORE_ID_SHIFT		24
118b81fd263SSubhransu S. Prusty #define IPC_CORE_ID_MASK		0x1F
119b81fd263SSubhransu S. Prusty #define IPC_CORE_ID(x)			(((x) & IPC_CORE_ID_MASK) \
120b81fd263SSubhransu S. Prusty 					<< IPC_CORE_ID_SHIFT)
121b81fd263SSubhransu S. Prusty 
1223d4006cdSSenthilnathan Veppur #define IPC_DOMAIN_SHIFT                28
1233d4006cdSSenthilnathan Veppur #define IPC_DOMAIN_MASK                 0x1
1243d4006cdSSenthilnathan Veppur #define IPC_DOMAIN(x)                   (((x) & IPC_DOMAIN_MASK) \
1253d4006cdSSenthilnathan Veppur 					<< IPC_DOMAIN_SHIFT)
1263d4006cdSSenthilnathan Veppur 
127b81fd263SSubhransu S. Prusty /* Bind/Unbind message extension register */
128b81fd263SSubhransu S. Prusty #define IPC_DST_MOD_ID_SHIFT		0
129b81fd263SSubhransu S. Prusty #define IPC_DST_MOD_ID(x)		(((x) & IPC_MOD_ID_MASK) \
130b81fd263SSubhransu S. Prusty 					<< IPC_DST_MOD_ID_SHIFT)
131b81fd263SSubhransu S. Prusty 
132b81fd263SSubhransu S. Prusty #define IPC_DST_MOD_INSTANCE_ID_SHIFT 16
133b81fd263SSubhransu S. Prusty #define IPC_DST_MOD_INSTANCE_ID(x)	(((x) & IPC_MOD_INSTANCE_ID_MASK) \
134b81fd263SSubhransu S. Prusty 					<< IPC_DST_MOD_INSTANCE_ID_SHIFT)
135b81fd263SSubhransu S. Prusty 
136b81fd263SSubhransu S. Prusty #define IPC_DST_QUEUE_SHIFT		24
137b81fd263SSubhransu S. Prusty #define IPC_DST_QUEUE_MASK		0x7
138b81fd263SSubhransu S. Prusty #define IPC_DST_QUEUE(x)		(((x) & IPC_DST_QUEUE_MASK) \
139b81fd263SSubhransu S. Prusty 					<< IPC_DST_QUEUE_SHIFT)
140b81fd263SSubhransu S. Prusty 
141b81fd263SSubhransu S. Prusty #define IPC_SRC_QUEUE_SHIFT		27
142b81fd263SSubhransu S. Prusty #define IPC_SRC_QUEUE_MASK		0x7
143b81fd263SSubhransu S. Prusty #define IPC_SRC_QUEUE(x)		(((x) & IPC_SRC_QUEUE_MASK) \
144b81fd263SSubhransu S. Prusty 					<< IPC_SRC_QUEUE_SHIFT)
1456c5768b3SDharageswari R /* Load Module count */
1466c5768b3SDharageswari R #define IPC_LOAD_MODULE_SHIFT		0
1476c5768b3SDharageswari R #define IPC_LOAD_MODULE_MASK		0xFF
1486c5768b3SDharageswari R #define IPC_LOAD_MODULE_CNT(x)		(((x) & IPC_LOAD_MODULE_MASK) \
1496c5768b3SDharageswari R 					<< IPC_LOAD_MODULE_SHIFT)
150b81fd263SSubhransu S. Prusty 
151b81fd263SSubhransu S. Prusty /* Save pipeline messgae extension register */
152b81fd263SSubhransu S. Prusty #define IPC_DMA_ID_SHIFT		0
153b81fd263SSubhransu S. Prusty #define IPC_DMA_ID_MASK			0x1F
154b81fd263SSubhransu S. Prusty #define IPC_DMA_ID(x)			(((x) & IPC_DMA_ID_MASK) \
155b81fd263SSubhransu S. Prusty 					<< IPC_DMA_ID_SHIFT)
156b81fd263SSubhransu S. Prusty /* Large Config message extension register */
157b81fd263SSubhransu S. Prusty #define IPC_DATA_OFFSET_SZ_SHIFT	0
158b81fd263SSubhransu S. Prusty #define IPC_DATA_OFFSET_SZ_MASK		0xFFFFF
159b81fd263SSubhransu S. Prusty #define IPC_DATA_OFFSET_SZ(x)		(((x) & IPC_DATA_OFFSET_SZ_MASK) \
160b81fd263SSubhransu S. Prusty 					<< IPC_DATA_OFFSET_SZ_SHIFT)
161b81fd263SSubhransu S. Prusty #define IPC_DATA_OFFSET_SZ_CLEAR	~(IPC_DATA_OFFSET_SZ_MASK \
162b81fd263SSubhransu S. Prusty 					  << IPC_DATA_OFFSET_SZ_SHIFT)
163b81fd263SSubhransu S. Prusty 
164b81fd263SSubhransu S. Prusty #define IPC_LARGE_PARAM_ID_SHIFT	20
165b81fd263SSubhransu S. Prusty #define IPC_LARGE_PARAM_ID_MASK		0xFF
166b81fd263SSubhransu S. Prusty #define IPC_LARGE_PARAM_ID(x)		(((x) & IPC_LARGE_PARAM_ID_MASK) \
167b81fd263SSubhransu S. Prusty 					<< IPC_LARGE_PARAM_ID_SHIFT)
168b81fd263SSubhransu S. Prusty 
169b81fd263SSubhransu S. Prusty #define IPC_FINAL_BLOCK_SHIFT		28
170b81fd263SSubhransu S. Prusty #define IPC_FINAL_BLOCK_MASK		0x1
171b81fd263SSubhransu S. Prusty #define IPC_FINAL_BLOCK(x)		(((x) & IPC_FINAL_BLOCK_MASK) \
172b81fd263SSubhransu S. Prusty 					<< IPC_FINAL_BLOCK_SHIFT)
173b81fd263SSubhransu S. Prusty 
174b81fd263SSubhransu S. Prusty #define IPC_INITIAL_BLOCK_SHIFT		29
175b81fd263SSubhransu S. Prusty #define IPC_INITIAL_BLOCK_MASK		0x1
176b81fd263SSubhransu S. Prusty #define IPC_INITIAL_BLOCK(x)		(((x) & IPC_INITIAL_BLOCK_MASK) \
177b81fd263SSubhransu S. Prusty 					<< IPC_INITIAL_BLOCK_SHIFT)
178b81fd263SSubhransu S. Prusty #define IPC_INITIAL_BLOCK_CLEAR		~(IPC_INITIAL_BLOCK_MASK \
179b81fd263SSubhransu S. Prusty 					  << IPC_INITIAL_BLOCK_SHIFT)
18041b7523fSPardha Saradhi K /* Set D0ix IPC extension register */
18141b7523fSPardha Saradhi K #define IPC_D0IX_WAKE_SHIFT		0
18241b7523fSPardha Saradhi K #define IPC_D0IX_WAKE_MASK		0x1
18341b7523fSPardha Saradhi K #define IPC_D0IX_WAKE(x)		(((x) & IPC_D0IX_WAKE_MASK) \
18441b7523fSPardha Saradhi K 					<< IPC_D0IX_WAKE_SHIFT)
18541b7523fSPardha Saradhi K 
18641b7523fSPardha Saradhi K #define IPC_D0IX_STREAMING_SHIFT	1
18741b7523fSPardha Saradhi K #define IPC_D0IX_STREAMING_MASK		0x1
18841b7523fSPardha Saradhi K #define IPC_D0IX_STREAMING(x)		(((x) & IPC_D0IX_STREAMING_MASK) \
18941b7523fSPardha Saradhi K 					<< IPC_D0IX_STREAMING_SHIFT)
19041b7523fSPardha Saradhi K 
191b81fd263SSubhransu S. Prusty 
192b81fd263SSubhransu S. Prusty enum skl_ipc_msg_target {
193b81fd263SSubhransu S. Prusty 	IPC_FW_GEN_MSG = 0,
194b81fd263SSubhransu S. Prusty 	IPC_MOD_MSG = 1
195b81fd263SSubhransu S. Prusty };
196b81fd263SSubhransu S. Prusty 
197b81fd263SSubhransu S. Prusty enum skl_ipc_msg_direction {
198b81fd263SSubhransu S. Prusty 	IPC_MSG_REQUEST = 0,
199b81fd263SSubhransu S. Prusty 	IPC_MSG_REPLY = 1
200b81fd263SSubhransu S. Prusty };
201b81fd263SSubhransu S. Prusty 
202b81fd263SSubhransu S. Prusty /* Global Message Types */
203b81fd263SSubhransu S. Prusty enum skl_ipc_glb_type {
204b81fd263SSubhransu S. Prusty 	IPC_GLB_GET_FW_VERSION = 0, /* Retrieves firmware version */
205b81fd263SSubhransu S. Prusty 	IPC_GLB_LOAD_MULTIPLE_MODS = 15,
206b81fd263SSubhransu S. Prusty 	IPC_GLB_UNLOAD_MULTIPLE_MODS = 16,
207b81fd263SSubhransu S. Prusty 	IPC_GLB_CREATE_PPL = 17,
208b81fd263SSubhransu S. Prusty 	IPC_GLB_DELETE_PPL = 18,
209b81fd263SSubhransu S. Prusty 	IPC_GLB_SET_PPL_STATE = 19,
210b81fd263SSubhransu S. Prusty 	IPC_GLB_GET_PPL_STATE = 20,
211b81fd263SSubhransu S. Prusty 	IPC_GLB_GET_PPL_CONTEXT_SIZE = 21,
212b81fd263SSubhransu S. Prusty 	IPC_GLB_SAVE_PPL = 22,
213b81fd263SSubhransu S. Prusty 	IPC_GLB_RESTORE_PPL = 23,
21420fb2fbdSRamesh Babu 	IPC_GLB_LOAD_LIBRARY = 24,
215b81fd263SSubhransu S. Prusty 	IPC_GLB_NOTIFY = 26,
216b81fd263SSubhransu S. Prusty 	IPC_GLB_MAX_IPC_MSG_NUMBER = 31 /* Maximum message number */
217b81fd263SSubhransu S. Prusty };
218b81fd263SSubhransu S. Prusty 
219b81fd263SSubhransu S. Prusty enum skl_ipc_glb_reply {
220b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_SUCCESS = 0,
221b81fd263SSubhransu S. Prusty 
222b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_UNKNOWN_MSG_TYPE = 1,
223b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_ERROR_INVALID_PARAM = 2,
224b81fd263SSubhransu S. Prusty 
225b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_BUSY = 3,
226b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_PENDING = 4,
227b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_FAILURE = 5,
228b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_INVALID_REQUEST = 6,
229b81fd263SSubhransu S. Prusty 
230b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_OUT_OF_MEMORY = 7,
231b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_OUT_OF_MIPS = 8,
232b81fd263SSubhransu S. Prusty 
233b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_INVALID_RESOURCE_ID = 9,
234b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_INVALID_RESOURCE_STATE = 10,
235b81fd263SSubhransu S. Prusty 
236b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_MOD_MGMT_ERROR = 100,
237b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_MOD_LOAD_CL_FAILED = 101,
238b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_MOD_LOAD_INVALID_HASH = 102,
239b81fd263SSubhransu S. Prusty 
240b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_MOD_UNLOAD_INST_EXIST = 103,
241b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_MOD_NOT_INITIALIZED = 104,
242b81fd263SSubhransu S. Prusty 
243b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_INVALID_CONFIG_PARAM_ID = 120,
244b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_INVALID_CONFIG_DATA_LEN = 121,
245b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_GATEWAY_NOT_INITIALIZED = 140,
246b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_GATEWAY_NOT_EXIST = 141,
247b81fd263SSubhransu S. Prusty 
248b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_PPL_NOT_INITIALIZED = 160,
249b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_PPL_NOT_EXIST = 161,
250b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_PPL_SAVE_FAILED = 162,
251b81fd263SSubhransu S. Prusty 	IPC_GLB_REPLY_PPL_RESTORE_FAILED = 163,
252b81fd263SSubhransu S. Prusty 
253b81fd263SSubhransu S. Prusty 	IPC_MAX_STATUS = ((1<<IPC_IXC_STATUS_BITS)-1)
254b81fd263SSubhransu S. Prusty };
255b81fd263SSubhransu S. Prusty 
256b81fd263SSubhransu S. Prusty enum skl_ipc_notification_type {
257b81fd263SSubhransu S. Prusty 	IPC_GLB_NOTIFY_GLITCH = 0,
258b81fd263SSubhransu S. Prusty 	IPC_GLB_NOTIFY_OVERRUN = 1,
259b81fd263SSubhransu S. Prusty 	IPC_GLB_NOTIFY_UNDERRUN = 2,
260b81fd263SSubhransu S. Prusty 	IPC_GLB_NOTIFY_END_STREAM = 3,
261b81fd263SSubhransu S. Prusty 	IPC_GLB_NOTIFY_PHRASE_DETECTED = 4,
262b81fd263SSubhransu S. Prusty 	IPC_GLB_NOTIFY_RESOURCE_EVENT = 5,
263b81fd263SSubhransu S. Prusty 	IPC_GLB_NOTIFY_LOG_BUFFER_STATUS = 6,
264b81fd263SSubhransu S. Prusty 	IPC_GLB_NOTIFY_TIMESTAMP_CAPTURED = 7,
265b81fd263SSubhransu S. Prusty 	IPC_GLB_NOTIFY_FW_READY = 8
266b81fd263SSubhransu S. Prusty };
267b81fd263SSubhransu S. Prusty 
268b81fd263SSubhransu S. Prusty /* Module Message Types */
269b81fd263SSubhransu S. Prusty enum skl_ipc_module_msg {
270b81fd263SSubhransu S. Prusty 	IPC_MOD_INIT_INSTANCE = 0,
271b81fd263SSubhransu S. Prusty 	IPC_MOD_CONFIG_GET = 1,
272b81fd263SSubhransu S. Prusty 	IPC_MOD_CONFIG_SET = 2,
273b81fd263SSubhransu S. Prusty 	IPC_MOD_LARGE_CONFIG_GET = 3,
274b81fd263SSubhransu S. Prusty 	IPC_MOD_LARGE_CONFIG_SET = 4,
275b81fd263SSubhransu S. Prusty 	IPC_MOD_BIND = 5,
276b81fd263SSubhransu S. Prusty 	IPC_MOD_UNBIND = 6,
27741b7523fSPardha Saradhi K 	IPC_MOD_SET_DX = 7,
27841b7523fSPardha Saradhi K 	IPC_MOD_SET_D0IX = 8
279b81fd263SSubhransu S. Prusty };
280b81fd263SSubhransu S. Prusty 
281b81fd263SSubhransu S. Prusty static void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data,
282b81fd263SSubhransu S. Prusty 		size_t tx_size)
283b81fd263SSubhransu S. Prusty {
284b81fd263SSubhransu S. Prusty 	if (tx_size)
285b81fd263SSubhransu S. Prusty 		memcpy(msg->tx_data, tx_data, tx_size);
286b81fd263SSubhransu S. Prusty }
287b81fd263SSubhransu S. Prusty 
288b81fd263SSubhransu S. Prusty static bool skl_ipc_is_dsp_busy(struct sst_dsp *dsp)
289b81fd263SSubhransu S. Prusty {
290b81fd263SSubhransu S. Prusty 	u32 hipci;
291b81fd263SSubhransu S. Prusty 
292b81fd263SSubhransu S. Prusty 	hipci = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCI);
293b81fd263SSubhransu S. Prusty 	return (hipci & SKL_ADSP_REG_HIPCI_BUSY);
294b81fd263SSubhransu S. Prusty }
295b81fd263SSubhransu S. Prusty 
296b81fd263SSubhransu S. Prusty /* Lock to be held by caller */
297b81fd263SSubhransu S. Prusty static void skl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg)
298b81fd263SSubhransu S. Prusty {
299b81fd263SSubhransu S. Prusty 	struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->header);
300b81fd263SSubhransu S. Prusty 
301b81fd263SSubhransu S. Prusty 	if (msg->tx_size)
302b81fd263SSubhransu S. Prusty 		sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size);
303b81fd263SSubhransu S. Prusty 	sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCIE,
304b81fd263SSubhransu S. Prusty 						header->extension);
305b81fd263SSubhransu S. Prusty 	sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCI,
306b81fd263SSubhransu S. Prusty 		header->primary | SKL_ADSP_REG_HIPCI_BUSY);
307b81fd263SSubhransu S. Prusty }
308b81fd263SSubhransu S. Prusty 
309a83e3b4cSVinod Koul int skl_ipc_check_D0i0(struct sst_dsp *dsp, bool state)
310a83e3b4cSVinod Koul {
311a83e3b4cSVinod Koul 	int ret;
312a83e3b4cSVinod Koul 
313a83e3b4cSVinod Koul 	/* check D0i3 support */
314a83e3b4cSVinod Koul 	if (!dsp->fw_ops.set_state_D0i0)
315a83e3b4cSVinod Koul 		return 0;
316a83e3b4cSVinod Koul 
317a83e3b4cSVinod Koul 	/* Attempt D0i0 or D0i3 based on state */
318a83e3b4cSVinod Koul 	if (state)
319a83e3b4cSVinod Koul 		ret = dsp->fw_ops.set_state_D0i0(dsp);
320a83e3b4cSVinod Koul 	else
321a83e3b4cSVinod Koul 		ret = dsp->fw_ops.set_state_D0i3(dsp);
322a83e3b4cSVinod Koul 
323a83e3b4cSVinod Koul 	return ret;
324a83e3b4cSVinod Koul }
325a83e3b4cSVinod Koul 
326b81fd263SSubhransu S. Prusty static struct ipc_message *skl_ipc_reply_get_msg(struct sst_generic_ipc *ipc,
327b81fd263SSubhransu S. Prusty 				u64 ipc_header)
328b81fd263SSubhransu S. Prusty {
329b81fd263SSubhransu S. Prusty 	struct ipc_message *msg =  NULL;
330b81fd263SSubhransu S. Prusty 	struct skl_ipc_header *header = (struct skl_ipc_header *)(&ipc_header);
331b81fd263SSubhransu S. Prusty 
332b81fd263SSubhransu S. Prusty 	if (list_empty(&ipc->rx_list)) {
333b81fd263SSubhransu S. Prusty 		dev_err(ipc->dev, "ipc: rx list is empty but received 0x%x\n",
334b81fd263SSubhransu S. Prusty 			header->primary);
335b81fd263SSubhransu S. Prusty 		goto out;
336b81fd263SSubhransu S. Prusty 	}
337b81fd263SSubhransu S. Prusty 
338b81fd263SSubhransu S. Prusty 	msg = list_first_entry(&ipc->rx_list, struct ipc_message, list);
339b81fd263SSubhransu S. Prusty 
340b81fd263SSubhransu S. Prusty out:
341b81fd263SSubhransu S. Prusty 	return msg;
342b81fd263SSubhransu S. Prusty 
343b81fd263SSubhransu S. Prusty }
344b81fd263SSubhransu S. Prusty 
345b81fd263SSubhransu S. Prusty static int skl_ipc_process_notification(struct sst_generic_ipc *ipc,
346b81fd263SSubhransu S. Prusty 		struct skl_ipc_header header)
347b81fd263SSubhransu S. Prusty {
348b81fd263SSubhransu S. Prusty 	struct skl_sst *skl = container_of(ipc, struct skl_sst, 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 
390b81fd263SSubhransu S. Prusty static void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
391b81fd263SSubhransu S. Prusty 		struct skl_ipc_header header)
392b81fd263SSubhransu S. Prusty {
393b81fd263SSubhransu S. Prusty 	struct ipc_message *msg;
394b81fd263SSubhransu S. Prusty 	u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK;
395b81fd263SSubhransu S. Prusty 	u64 *ipc_header = (u64 *)(&header);
396b81fd263SSubhransu S. Prusty 
397b81fd263SSubhransu S. Prusty 	msg = skl_ipc_reply_get_msg(ipc, *ipc_header);
398b81fd263SSubhransu S. Prusty 	if (msg == NULL) {
399b81fd263SSubhransu S. Prusty 		dev_dbg(ipc->dev, "ipc: rx list is empty\n");
400b81fd263SSubhransu S. Prusty 		return;
401b81fd263SSubhransu S. Prusty 	}
402b81fd263SSubhransu S. Prusty 
403b81fd263SSubhransu S. Prusty 	/* first process the header */
404b81fd263SSubhransu S. Prusty 	switch (reply) {
405b81fd263SSubhransu S. Prusty 	case IPC_GLB_REPLY_SUCCESS:
40691c18325SVedang Patel 		dev_dbg(ipc->dev, "ipc FW reply %x: success\n", header.primary);
407cce1c7f3SMousami Jana 		/* copy the rx data from the mailbox */
408cce1c7f3SMousami Jana 		sst_dsp_inbox_read(ipc->dsp, msg->rx_data, msg->rx_size);
409b81fd263SSubhransu S. Prusty 		break;
410b81fd263SSubhransu S. Prusty 
411b81fd263SSubhransu S. Prusty 	case IPC_GLB_REPLY_OUT_OF_MEMORY:
412b81fd263SSubhransu S. Prusty 		dev_err(ipc->dev, "ipc fw reply: %x: no memory\n", header.primary);
413b81fd263SSubhransu S. Prusty 		msg->errno = -ENOMEM;
414b81fd263SSubhransu S. Prusty 		break;
415b81fd263SSubhransu S. Prusty 
416b81fd263SSubhransu S. Prusty 	case IPC_GLB_REPLY_BUSY:
417b81fd263SSubhransu S. Prusty 		dev_err(ipc->dev, "ipc fw reply: %x: Busy\n", header.primary);
418b81fd263SSubhransu S. Prusty 		msg->errno = -EBUSY;
419b81fd263SSubhransu S. Prusty 		break;
420b81fd263SSubhransu S. Prusty 
421b81fd263SSubhransu S. Prusty 	default:
422ecd286a9SColin Ian King 		dev_err(ipc->dev, "Unknown ipc reply: 0x%x\n", reply);
423b81fd263SSubhransu S. Prusty 		msg->errno = -EINVAL;
424b81fd263SSubhransu S. Prusty 		break;
425b81fd263SSubhransu S. Prusty 	}
426b81fd263SSubhransu S. Prusty 
42728f3b6f1SOmair M Abdullah 	if (reply != IPC_GLB_REPLY_SUCCESS) {
428ecd286a9SColin Ian King 		dev_err(ipc->dev, "ipc FW reply: reply=%d\n", reply);
42928f3b6f1SOmair M Abdullah 		dev_err(ipc->dev, "FW Error Code: %u\n",
43028f3b6f1SOmair M Abdullah 			ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp));
43128f3b6f1SOmair M Abdullah 	}
43228f3b6f1SOmair M Abdullah 
433b81fd263SSubhransu S. Prusty 	list_del(&msg->list);
434b81fd263SSubhransu S. Prusty 	sst_ipc_tx_msg_reply_complete(ipc, msg);
435b81fd263SSubhransu S. Prusty }
436b81fd263SSubhransu S. Prusty 
437b81fd263SSubhransu S. Prusty irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context)
438b81fd263SSubhransu S. Prusty {
439b81fd263SSubhransu S. Prusty 	struct sst_dsp *dsp = context;
440b81fd263SSubhransu S. Prusty 	struct skl_sst *skl = sst_dsp_get_thread_context(dsp);
441b81fd263SSubhransu S. Prusty 	struct sst_generic_ipc *ipc = &skl->ipc;
442b81fd263SSubhransu S. Prusty 	struct skl_ipc_header header = {0};
443b81fd263SSubhransu S. Prusty 	u32 hipcie, hipct, hipcte;
444b81fd263SSubhransu S. Prusty 	int ipc_irq = 0;
445b81fd263SSubhransu S. Prusty 
4466cb00333SSubhransu S. Prusty 	if (dsp->intr_status & SKL_ADSPIS_CL_DMA)
4476cb00333SSubhransu S. Prusty 		skl_cldma_process_intr(dsp);
4486cb00333SSubhransu S. Prusty 
449b81fd263SSubhransu S. Prusty 	/* Here we handle IPC interrupts only */
450b81fd263SSubhransu S. Prusty 	if (!(dsp->intr_status & SKL_ADSPIS_IPC))
451b81fd263SSubhransu S. Prusty 		return IRQ_NONE;
452b81fd263SSubhransu S. Prusty 
453b81fd263SSubhransu S. Prusty 	hipcie = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCIE);
454b81fd263SSubhransu S. Prusty 	hipct = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCT);
455b81fd263SSubhransu S. Prusty 
456b81fd263SSubhransu S. Prusty 	/* reply message from DSP */
457b81fd263SSubhransu S. Prusty 	if (hipcie & SKL_ADSP_REG_HIPCIE_DONE) {
458b81fd263SSubhransu S. Prusty 		sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL,
459b81fd263SSubhransu S. Prusty 			SKL_ADSP_REG_HIPCCTL_DONE, 0);
460b81fd263SSubhransu S. Prusty 
461b81fd263SSubhransu S. Prusty 		/* clear DONE bit - tell DSP we have completed the operation */
462b81fd263SSubhransu S. Prusty 		sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCIE,
463b81fd263SSubhransu S. Prusty 			SKL_ADSP_REG_HIPCIE_DONE, SKL_ADSP_REG_HIPCIE_DONE);
464b81fd263SSubhransu S. Prusty 
465b81fd263SSubhransu S. Prusty 		ipc_irq = 1;
466b81fd263SSubhransu S. Prusty 
467b81fd263SSubhransu S. Prusty 		/* unmask Done interrupt */
468b81fd263SSubhransu S. Prusty 		sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL,
469b81fd263SSubhransu S. Prusty 			SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE);
470b81fd263SSubhransu S. Prusty 	}
471b81fd263SSubhransu S. Prusty 
472b81fd263SSubhransu S. Prusty 	/* New message from DSP */
473b81fd263SSubhransu S. Prusty 	if (hipct & SKL_ADSP_REG_HIPCT_BUSY) {
474b81fd263SSubhransu S. Prusty 		hipcte = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCTE);
475b81fd263SSubhransu S. Prusty 		header.primary = hipct;
476b81fd263SSubhransu S. Prusty 		header.extension = hipcte;
477ecd286a9SColin Ian King 		dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x\n",
478b81fd263SSubhransu S. Prusty 						header.primary);
479ecd286a9SColin Ian King 		dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x\n",
480b81fd263SSubhransu S. Prusty 						header.extension);
481b81fd263SSubhransu S. Prusty 
482b81fd263SSubhransu S. Prusty 		if (IPC_GLB_NOTIFY_RSP_TYPE(header.primary)) {
483b81fd263SSubhransu S. Prusty 			/* Handle Immediate reply from DSP Core */
484b81fd263SSubhransu S. Prusty 			skl_ipc_process_reply(ipc, header);
485b81fd263SSubhransu S. Prusty 		} else {
486b81fd263SSubhransu S. Prusty 			dev_dbg(dsp->dev, "IPC irq: Notification from firmware\n");
487b81fd263SSubhransu S. Prusty 			skl_ipc_process_notification(ipc, header);
488b81fd263SSubhransu S. Prusty 		}
489b81fd263SSubhransu S. Prusty 		/* clear  busy interrupt */
490b81fd263SSubhransu S. Prusty 		sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCT,
491b81fd263SSubhransu S. Prusty 			SKL_ADSP_REG_HIPCT_BUSY, SKL_ADSP_REG_HIPCT_BUSY);
492b81fd263SSubhransu S. Prusty 		ipc_irq = 1;
493b81fd263SSubhransu S. Prusty 	}
494b81fd263SSubhransu S. Prusty 
495b81fd263SSubhransu S. Prusty 	if (ipc_irq == 0)
496b81fd263SSubhransu S. Prusty 		return IRQ_NONE;
497b81fd263SSubhransu S. Prusty 
498b81fd263SSubhransu S. Prusty 	skl_ipc_int_enable(dsp);
499b81fd263SSubhransu S. Prusty 
500b81fd263SSubhransu S. Prusty 	/* continue to send any remaining messages... */
5013989144fSPetr Mladek 	kthread_queue_work(&ipc->kworker, &ipc->kwork);
502b81fd263SSubhransu S. Prusty 
503b81fd263SSubhransu S. Prusty 	return IRQ_HANDLED;
504b81fd263SSubhransu S. Prusty }
505b81fd263SSubhransu S. Prusty 
506b81fd263SSubhransu S. Prusty void skl_ipc_int_enable(struct sst_dsp *ctx)
507b81fd263SSubhransu S. Prusty {
508b81fd263SSubhransu S. Prusty 	sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_ADSPIC,
509b81fd263SSubhransu S. Prusty 			SKL_ADSPIC_IPC, SKL_ADSPIC_IPC);
510b81fd263SSubhransu S. Prusty }
511b81fd263SSubhransu S. Prusty 
512b81fd263SSubhransu S. Prusty void skl_ipc_int_disable(struct sst_dsp *ctx)
513b81fd263SSubhransu S. Prusty {
514b81fd263SSubhransu S. Prusty 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPIC,
515b81fd263SSubhransu S. Prusty 			SKL_ADSPIC_IPC, 0);
516b81fd263SSubhransu S. Prusty }
517b81fd263SSubhransu S. Prusty 
518b81fd263SSubhransu S. Prusty void skl_ipc_op_int_enable(struct sst_dsp *ctx)
519b81fd263SSubhransu S. Prusty {
520b81fd263SSubhransu S. Prusty 	/* enable IPC DONE interrupt */
521b81fd263SSubhransu S. Prusty 	sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL,
522b81fd263SSubhransu S. Prusty 		SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE);
523b81fd263SSubhransu S. Prusty 
524b81fd263SSubhransu S. Prusty 	/* Enable IPC BUSY interrupt */
525b81fd263SSubhransu S. Prusty 	sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL,
526b81fd263SSubhransu S. Prusty 		SKL_ADSP_REG_HIPCCTL_BUSY, SKL_ADSP_REG_HIPCCTL_BUSY);
527b81fd263SSubhransu S. Prusty }
528b81fd263SSubhransu S. Prusty 
52984c9e283SJeeja KP void skl_ipc_op_int_disable(struct sst_dsp *ctx)
53084c9e283SJeeja KP {
53184c9e283SJeeja KP 	/* disable IPC DONE interrupt */
53284c9e283SJeeja KP 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
53384c9e283SJeeja KP 					SKL_ADSP_REG_HIPCCTL_DONE, 0);
53484c9e283SJeeja KP 
53584c9e283SJeeja KP 	/* Disable IPC BUSY interrupt */
53684c9e283SJeeja KP 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
53784c9e283SJeeja KP 					SKL_ADSP_REG_HIPCCTL_BUSY, 0);
53884c9e283SJeeja KP 
53984c9e283SJeeja KP }
54084c9e283SJeeja KP 
541b81fd263SSubhransu S. Prusty bool skl_ipc_int_status(struct sst_dsp *ctx)
542b81fd263SSubhransu S. Prusty {
543b81fd263SSubhransu S. Prusty 	return sst_dsp_shim_read_unlocked(ctx,
544b81fd263SSubhransu S. Prusty 			SKL_ADSP_REG_ADSPIS) & SKL_ADSPIS_IPC;
545b81fd263SSubhransu S. Prusty }
546b81fd263SSubhransu S. Prusty 
547b81fd263SSubhransu S. Prusty int skl_ipc_init(struct device *dev, struct skl_sst *skl)
548b81fd263SSubhransu S. Prusty {
549b81fd263SSubhransu S. Prusty 	struct sst_generic_ipc *ipc;
550b81fd263SSubhransu S. Prusty 	int err;
551b81fd263SSubhransu S. Prusty 
552b81fd263SSubhransu S. Prusty 	ipc = &skl->ipc;
553b81fd263SSubhransu S. Prusty 	ipc->dsp = skl->dsp;
554b81fd263SSubhransu S. Prusty 	ipc->dev = dev;
555b81fd263SSubhransu S. Prusty 
556b81fd263SSubhransu S. Prusty 	ipc->tx_data_max_size = SKL_ADSP_W1_SZ;
557b81fd263SSubhransu S. Prusty 	ipc->rx_data_max_size = SKL_ADSP_W0_UP_SZ;
558b81fd263SSubhransu S. Prusty 
559b81fd263SSubhransu S. Prusty 	err = sst_ipc_init(ipc);
560b81fd263SSubhransu S. Prusty 	if (err)
561b81fd263SSubhransu S. Prusty 		return err;
562b81fd263SSubhransu S. Prusty 
563b81fd263SSubhransu S. Prusty 	ipc->ops.tx_msg = skl_ipc_tx_msg;
564b81fd263SSubhransu S. Prusty 	ipc->ops.tx_data_copy = skl_ipc_tx_data_copy;
565b81fd263SSubhransu S. Prusty 	ipc->ops.is_dsp_busy = skl_ipc_is_dsp_busy;
566b81fd263SSubhransu S. Prusty 
567b81fd263SSubhransu S. Prusty 	return 0;
568b81fd263SSubhransu S. Prusty }
569b81fd263SSubhransu S. Prusty 
570b81fd263SSubhransu S. Prusty void skl_ipc_free(struct sst_generic_ipc *ipc)
571b81fd263SSubhransu S. Prusty {
572b81fd263SSubhransu S. Prusty 	/* Disable IPC DONE interrupt */
573b81fd263SSubhransu S. Prusty 	sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL,
574b81fd263SSubhransu S. Prusty 		SKL_ADSP_REG_HIPCCTL_DONE, 0);
575b81fd263SSubhransu S. Prusty 
576b81fd263SSubhransu S. Prusty 	/* Disable IPC BUSY interrupt */
577b81fd263SSubhransu S. Prusty 	sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL,
578b81fd263SSubhransu S. Prusty 		SKL_ADSP_REG_HIPCCTL_BUSY, 0);
579a750ba5fSSubhransu S. Prusty 
580a750ba5fSSubhransu S. Prusty 	sst_ipc_fini(ipc);
581b81fd263SSubhransu S. Prusty }
582b81fd263SSubhransu S. Prusty 
583b81fd263SSubhransu S. Prusty int skl_ipc_create_pipeline(struct sst_generic_ipc *ipc,
5848a0cb236SVinod Koul 		u16 ppl_mem_size, u8 ppl_type, u8 instance_id, u8 lp_mode)
585b81fd263SSubhransu S. Prusty {
586b81fd263SSubhransu S. Prusty 	struct skl_ipc_header header = {0};
587b81fd263SSubhransu S. Prusty 	u64 *ipc_header = (u64 *)(&header);
588b81fd263SSubhransu S. Prusty 	int ret;
589b81fd263SSubhransu S. Prusty 
590b81fd263SSubhransu S. Prusty 	header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
591b81fd263SSubhransu S. Prusty 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
592b81fd263SSubhransu S. Prusty 	header.primary |= IPC_GLB_TYPE(IPC_GLB_CREATE_PPL);
593b81fd263SSubhransu S. Prusty 	header.primary |= IPC_INSTANCE_ID(instance_id);
594b81fd263SSubhransu S. Prusty 	header.primary |= IPC_PPL_TYPE(ppl_type);
595b81fd263SSubhransu S. Prusty 	header.primary |= IPC_PPL_MEM_SIZE(ppl_mem_size);
596b81fd263SSubhransu S. Prusty 
5978a0cb236SVinod Koul 	header.extension = IPC_PPL_LP_MODE(lp_mode);
5988a0cb236SVinod Koul 
599b81fd263SSubhransu S. Prusty 	dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
600b81fd263SSubhransu S. Prusty 	ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
601b81fd263SSubhransu S. Prusty 	if (ret < 0) {
602b81fd263SSubhransu S. Prusty 		dev_err(ipc->dev, "ipc: create pipeline fail, err: %d\n", ret);
603b81fd263SSubhransu S. Prusty 		return ret;
604b81fd263SSubhransu S. Prusty 	}
605b81fd263SSubhransu S. Prusty 
606b81fd263SSubhransu S. Prusty 	return ret;
607b81fd263SSubhransu S. Prusty }
608b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_create_pipeline);
609b81fd263SSubhransu S. Prusty 
610b81fd263SSubhransu S. Prusty int skl_ipc_delete_pipeline(struct sst_generic_ipc *ipc, u8 instance_id)
611b81fd263SSubhransu S. Prusty {
612b81fd263SSubhransu S. Prusty 	struct skl_ipc_header header = {0};
613b81fd263SSubhransu S. Prusty 	u64 *ipc_header = (u64 *)(&header);
614b81fd263SSubhransu S. Prusty 	int ret;
615b81fd263SSubhransu S. Prusty 
616b81fd263SSubhransu S. Prusty 	header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
617b81fd263SSubhransu S. Prusty 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
618b81fd263SSubhransu S. Prusty 	header.primary |= IPC_GLB_TYPE(IPC_GLB_DELETE_PPL);
619b81fd263SSubhransu S. Prusty 	header.primary |= IPC_INSTANCE_ID(instance_id);
620b81fd263SSubhransu S. Prusty 
621b81fd263SSubhransu S. Prusty 	dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
622b81fd263SSubhransu S. Prusty 	ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
623b81fd263SSubhransu S. Prusty 	if (ret < 0) {
624b81fd263SSubhransu S. Prusty 		dev_err(ipc->dev, "ipc: delete pipeline failed, err %d\n", ret);
625b81fd263SSubhransu S. Prusty 		return ret;
626b81fd263SSubhransu S. Prusty 	}
627b81fd263SSubhransu S. Prusty 
628b81fd263SSubhransu S. Prusty 	return 0;
629b81fd263SSubhransu S. Prusty }
630b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_delete_pipeline);
631b81fd263SSubhransu S. Prusty 
632b81fd263SSubhransu S. Prusty int skl_ipc_set_pipeline_state(struct sst_generic_ipc *ipc,
633b81fd263SSubhransu S. Prusty 		u8 instance_id, enum skl_ipc_pipeline_state state)
634b81fd263SSubhransu S. Prusty {
635b81fd263SSubhransu S. Prusty 	struct skl_ipc_header header = {0};
636b81fd263SSubhransu S. Prusty 	u64 *ipc_header = (u64 *)(&header);
637b81fd263SSubhransu S. Prusty 	int ret;
638b81fd263SSubhransu S. Prusty 
639b81fd263SSubhransu S. Prusty 	header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
640b81fd263SSubhransu S. Prusty 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
641b81fd263SSubhransu S. Prusty 	header.primary |= IPC_GLB_TYPE(IPC_GLB_SET_PPL_STATE);
642b81fd263SSubhransu S. Prusty 	header.primary |= IPC_INSTANCE_ID(instance_id);
643b81fd263SSubhransu S. Prusty 	header.primary |= IPC_PPL_STATE(state);
644b81fd263SSubhransu S. Prusty 
645b81fd263SSubhransu S. Prusty 	dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
646b81fd263SSubhransu S. Prusty 	ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
647b81fd263SSubhransu S. Prusty 	if (ret < 0) {
648b81fd263SSubhransu S. Prusty 		dev_err(ipc->dev, "ipc: set pipeline state failed, err: %d\n", ret);
649b81fd263SSubhransu S. Prusty 		return ret;
650b81fd263SSubhransu S. Prusty 	}
651b81fd263SSubhransu S. Prusty 	return ret;
652b81fd263SSubhransu S. Prusty }
653b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_set_pipeline_state);
654b81fd263SSubhransu S. Prusty 
655b81fd263SSubhransu S. Prusty int
656b81fd263SSubhransu S. Prusty skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, u8 instance_id, int dma_id)
657b81fd263SSubhransu S. Prusty {
658b81fd263SSubhransu S. Prusty 	struct skl_ipc_header header = {0};
659b81fd263SSubhransu S. Prusty 	u64 *ipc_header = (u64 *)(&header);
660b81fd263SSubhransu S. Prusty 	int ret;
661b81fd263SSubhransu S. Prusty 
662b81fd263SSubhransu S. Prusty 	header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
663b81fd263SSubhransu S. Prusty 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
664b81fd263SSubhransu S. Prusty 	header.primary |= IPC_GLB_TYPE(IPC_GLB_SAVE_PPL);
665b81fd263SSubhransu S. Prusty 	header.primary |= IPC_INSTANCE_ID(instance_id);
666b81fd263SSubhransu S. Prusty 
667b81fd263SSubhransu S. Prusty 	header.extension = IPC_DMA_ID(dma_id);
668b81fd263SSubhransu S. Prusty 	dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
669b81fd263SSubhransu S. Prusty 	ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
670b81fd263SSubhransu S. Prusty 	if (ret < 0) {
671b81fd263SSubhransu S. Prusty 		dev_err(ipc->dev, "ipc: save pipeline failed, err: %d\n", ret);
672b81fd263SSubhransu S. Prusty 		return ret;
673b81fd263SSubhransu S. Prusty 	}
674b81fd263SSubhransu S. Prusty 
675b81fd263SSubhransu S. Prusty 	return ret;
676b81fd263SSubhransu S. Prusty }
677b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_save_pipeline);
678b81fd263SSubhransu S. Prusty 
679b81fd263SSubhransu S. Prusty int skl_ipc_restore_pipeline(struct sst_generic_ipc *ipc, u8 instance_id)
680b81fd263SSubhransu S. Prusty {
681b81fd263SSubhransu S. Prusty 	struct skl_ipc_header header = {0};
682b81fd263SSubhransu S. Prusty 	u64 *ipc_header = (u64 *)(&header);
683b81fd263SSubhransu S. Prusty 	int ret;
684b81fd263SSubhransu S. Prusty 
685b81fd263SSubhransu S. Prusty 	header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
686b81fd263SSubhransu S. Prusty 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
687b81fd263SSubhransu S. Prusty 	header.primary |= IPC_GLB_TYPE(IPC_GLB_RESTORE_PPL);
688b81fd263SSubhransu S. Prusty 	header.primary |= IPC_INSTANCE_ID(instance_id);
689b81fd263SSubhransu S. Prusty 
690b81fd263SSubhransu S. Prusty 	dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
691b81fd263SSubhransu S. Prusty 	ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
692b81fd263SSubhransu S. Prusty 	if (ret < 0) {
693b81fd263SSubhransu S. Prusty 		dev_err(ipc->dev, "ipc: restore  pipeline failed, err: %d\n", ret);
694b81fd263SSubhransu S. Prusty 		return ret;
695b81fd263SSubhransu S. Prusty 	}
696b81fd263SSubhransu S. Prusty 
697b81fd263SSubhransu S. Prusty 	return ret;
698b81fd263SSubhransu S. Prusty }
699b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_restore_pipeline);
700b81fd263SSubhransu S. Prusty 
701b81fd263SSubhransu S. Prusty int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id,
702b81fd263SSubhransu S. Prusty 		u16 module_id, struct skl_ipc_dxstate_info *dx)
703b81fd263SSubhransu S. Prusty {
704b81fd263SSubhransu S. Prusty 	struct skl_ipc_header header = {0};
705b81fd263SSubhransu S. Prusty 	u64 *ipc_header = (u64 *)(&header);
706b81fd263SSubhransu S. Prusty 	int ret;
707b81fd263SSubhransu S. Prusty 
708b81fd263SSubhransu S. Prusty 	header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
709b81fd263SSubhransu S. Prusty 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
710b81fd263SSubhransu S. Prusty 	header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_DX);
711b81fd263SSubhransu S. Prusty 	header.primary |= IPC_MOD_INSTANCE_ID(instance_id);
712b81fd263SSubhransu S. Prusty 	header.primary |= IPC_MOD_ID(module_id);
713b81fd263SSubhransu S. Prusty 
714b81fd263SSubhransu S. Prusty 	dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__,
715b81fd263SSubhransu S. Prusty 			 header.primary, header.extension);
716b81fd263SSubhransu S. Prusty 	ret = sst_ipc_tx_message_wait(ipc, *ipc_header,
717aaec7e9fSVincent Stehlé 				dx, sizeof(*dx), NULL, 0);
718b81fd263SSubhransu S. Prusty 	if (ret < 0) {
719b81fd263SSubhransu S. Prusty 		dev_err(ipc->dev, "ipc: set dx failed, err %d\n", ret);
720b81fd263SSubhransu S. Prusty 		return ret;
721b81fd263SSubhransu S. Prusty 	}
722b81fd263SSubhransu S. Prusty 
723b81fd263SSubhransu S. Prusty 	return ret;
724b81fd263SSubhransu S. Prusty }
725b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_set_dx);
726b81fd263SSubhransu S. Prusty 
727b81fd263SSubhransu S. Prusty int skl_ipc_init_instance(struct sst_generic_ipc *ipc,
728b81fd263SSubhransu S. Prusty 		struct skl_ipc_init_instance_msg *msg, void *param_data)
729b81fd263SSubhransu S. Prusty {
730b81fd263SSubhransu S. Prusty 	struct skl_ipc_header header = {0};
731b81fd263SSubhransu S. Prusty 	u64 *ipc_header = (u64 *)(&header);
732b81fd263SSubhransu S. Prusty 	int ret;
733b81fd263SSubhransu S. Prusty 	u32 *buffer = (u32 *)param_data;
734b81fd263SSubhransu S. Prusty 	 /* param_block_size must be in dwords */
735b81fd263SSubhransu S. Prusty 	u16 param_block_size = msg->param_data_size / sizeof(u32);
736b81fd263SSubhransu S. Prusty 
73796bd6033SVedang Patel 	print_hex_dump_debug("Param data:", DUMP_PREFIX_NONE,
738b81fd263SSubhransu S. Prusty 		16, 4, buffer, param_block_size, false);
739b81fd263SSubhransu S. Prusty 
740b81fd263SSubhransu S. Prusty 	header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
741b81fd263SSubhransu S. Prusty 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
742b81fd263SSubhransu S. Prusty 	header.primary |= IPC_GLB_TYPE(IPC_MOD_INIT_INSTANCE);
743b81fd263SSubhransu S. Prusty 	header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
744b81fd263SSubhransu S. Prusty 	header.primary |= IPC_MOD_ID(msg->module_id);
745b81fd263SSubhransu S. Prusty 
746b81fd263SSubhransu S. Prusty 	header.extension = IPC_CORE_ID(msg->core_id);
747b81fd263SSubhransu S. Prusty 	header.extension |= IPC_PPL_INSTANCE_ID(msg->ppl_instance_id);
748b81fd263SSubhransu S. Prusty 	header.extension |= IPC_PARAM_BLOCK_SIZE(param_block_size);
7493d4006cdSSenthilnathan Veppur 	header.extension |= IPC_DOMAIN(msg->domain);
750b81fd263SSubhransu S. Prusty 
751b81fd263SSubhransu S. Prusty 	dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__,
752b81fd263SSubhransu S. Prusty 			 header.primary, header.extension);
753b81fd263SSubhransu S. Prusty 	ret = sst_ipc_tx_message_wait(ipc, *ipc_header, param_data,
754b81fd263SSubhransu S. Prusty 			msg->param_data_size, NULL, 0);
755b81fd263SSubhransu S. Prusty 
756b81fd263SSubhransu S. Prusty 	if (ret < 0) {
757b81fd263SSubhransu S. Prusty 		dev_err(ipc->dev, "ipc: init instance failed\n");
758b81fd263SSubhransu S. Prusty 		return ret;
759b81fd263SSubhransu S. Prusty 	}
760b81fd263SSubhransu S. Prusty 
761b81fd263SSubhransu S. Prusty 	return ret;
762b81fd263SSubhransu S. Prusty }
763b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_init_instance);
764b81fd263SSubhransu S. Prusty 
765b81fd263SSubhransu S. Prusty int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc,
766b81fd263SSubhransu S. Prusty 		struct skl_ipc_bind_unbind_msg *msg)
767b81fd263SSubhransu S. Prusty {
768b81fd263SSubhransu S. Prusty 	struct skl_ipc_header header = {0};
769b81fd263SSubhransu S. Prusty 	u64 *ipc_header = (u64 *)(&header);
770b81fd263SSubhransu S. Prusty 	u8 bind_unbind = msg->bind ? IPC_MOD_BIND : IPC_MOD_UNBIND;
771b81fd263SSubhransu S. Prusty 	int ret;
772b81fd263SSubhransu S. Prusty 
773b81fd263SSubhransu S. Prusty 	header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
774b81fd263SSubhransu S. Prusty 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
775b81fd263SSubhransu S. Prusty 	header.primary |= IPC_GLB_TYPE(bind_unbind);
776b81fd263SSubhransu S. Prusty 	header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
777b81fd263SSubhransu S. Prusty 	header.primary |= IPC_MOD_ID(msg->module_id);
778b81fd263SSubhransu S. Prusty 
779b81fd263SSubhransu S. Prusty 	header.extension = IPC_DST_MOD_ID(msg->dst_module_id);
780b81fd263SSubhransu S. Prusty 	header.extension |= IPC_DST_MOD_INSTANCE_ID(msg->dst_instance_id);
781b81fd263SSubhransu S. Prusty 	header.extension |= IPC_DST_QUEUE(msg->dst_queue);
782b81fd263SSubhransu S. Prusty 	header.extension |= IPC_SRC_QUEUE(msg->src_queue);
783b81fd263SSubhransu S. Prusty 
784b81fd263SSubhransu S. Prusty 	dev_dbg(ipc->dev, "In %s hdr=%x ext=%x\n", __func__, header.primary,
785b81fd263SSubhransu S. Prusty 			 header.extension);
786b81fd263SSubhransu S. Prusty 	ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
787b81fd263SSubhransu S. Prusty 	if (ret < 0) {
788ecd286a9SColin Ian King 		dev_err(ipc->dev, "ipc: bind/unbind failed\n");
789b81fd263SSubhransu S. Prusty 		return ret;
790b81fd263SSubhransu S. Prusty 	}
791b81fd263SSubhransu S. Prusty 
792b81fd263SSubhransu S. Prusty 	return ret;
793b81fd263SSubhransu S. Prusty }
794b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_bind_unbind);
795b81fd263SSubhransu S. Prusty 
7966c5768b3SDharageswari R /*
7976c5768b3SDharageswari R  * In order to load a module we need to send IPC to initiate that. DMA will
7986c5768b3SDharageswari R  * performed to load the module memory. The FW supports multiple module load
7996c5768b3SDharageswari R  * at single shot, so we can send IPC with N modules represented by
8006c5768b3SDharageswari R  * module_cnt
8016c5768b3SDharageswari R  */
8026c5768b3SDharageswari R int skl_ipc_load_modules(struct sst_generic_ipc *ipc,
8036c5768b3SDharageswari R 				u8 module_cnt, void *data)
8046c5768b3SDharageswari R {
8056c5768b3SDharageswari R 	struct skl_ipc_header header = {0};
8066c5768b3SDharageswari R 	u64 *ipc_header = (u64 *)(&header);
8076c5768b3SDharageswari R 	int ret;
8086c5768b3SDharageswari R 
8096c5768b3SDharageswari R 	header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
8106c5768b3SDharageswari R 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
8116c5768b3SDharageswari R 	header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_MULTIPLE_MODS);
8126c5768b3SDharageswari R 	header.primary |= IPC_LOAD_MODULE_CNT(module_cnt);
8136c5768b3SDharageswari R 
8146c5768b3SDharageswari R 	ret = sst_ipc_tx_message_wait(ipc, *ipc_header, data,
8156c5768b3SDharageswari R 				(sizeof(u16) * module_cnt), NULL, 0);
8166c5768b3SDharageswari R 	if (ret < 0)
8176c5768b3SDharageswari R 		dev_err(ipc->dev, "ipc: load modules failed :%d\n", ret);
8186c5768b3SDharageswari R 
8196c5768b3SDharageswari R 	return ret;
8206c5768b3SDharageswari R }
8216c5768b3SDharageswari R EXPORT_SYMBOL_GPL(skl_ipc_load_modules);
8226c5768b3SDharageswari R 
8236c5768b3SDharageswari R int skl_ipc_unload_modules(struct sst_generic_ipc *ipc, u8 module_cnt,
8246c5768b3SDharageswari R 							void *data)
8256c5768b3SDharageswari R {
8266c5768b3SDharageswari R 	struct skl_ipc_header header = {0};
8276c5768b3SDharageswari R 	u64 *ipc_header = (u64 *)(&header);
8286c5768b3SDharageswari R 	int ret;
8296c5768b3SDharageswari R 
8306c5768b3SDharageswari R 	header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
8316c5768b3SDharageswari R 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
8326c5768b3SDharageswari R 	header.primary |= IPC_GLB_TYPE(IPC_GLB_UNLOAD_MULTIPLE_MODS);
8336c5768b3SDharageswari R 	header.primary |= IPC_LOAD_MODULE_CNT(module_cnt);
8346c5768b3SDharageswari R 
8356c5768b3SDharageswari R 	ret = sst_ipc_tx_message_wait(ipc, *ipc_header, data,
8366c5768b3SDharageswari R 				(sizeof(u16) * module_cnt), NULL, 0);
8376c5768b3SDharageswari R 	if (ret < 0)
8386c5768b3SDharageswari R 		dev_err(ipc->dev, "ipc: unload modules failed :%d\n", ret);
8396c5768b3SDharageswari R 
8406c5768b3SDharageswari R 	return ret;
8416c5768b3SDharageswari R }
8426c5768b3SDharageswari R EXPORT_SYMBOL_GPL(skl_ipc_unload_modules);
8436c5768b3SDharageswari R 
844b81fd263SSubhransu S. Prusty int skl_ipc_set_large_config(struct sst_generic_ipc *ipc,
845b81fd263SSubhransu S. Prusty 		struct skl_ipc_large_config_msg *msg, u32 *param)
846b81fd263SSubhransu S. Prusty {
847b81fd263SSubhransu S. Prusty 	struct skl_ipc_header header = {0};
848b81fd263SSubhransu S. Prusty 	u64 *ipc_header = (u64 *)(&header);
849b81fd263SSubhransu S. Prusty 	int ret = 0;
850b81fd263SSubhransu S. Prusty 	size_t sz_remaining, tx_size, data_offset;
851b81fd263SSubhransu S. Prusty 
852b81fd263SSubhransu S. Prusty 	header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
853b81fd263SSubhransu S. Prusty 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
854b81fd263SSubhransu S. Prusty 	header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_SET);
855b81fd263SSubhransu S. Prusty 	header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
856b81fd263SSubhransu S. Prusty 	header.primary |= IPC_MOD_ID(msg->module_id);
857b81fd263SSubhransu S. Prusty 
858b81fd263SSubhransu S. Prusty 	header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size);
859b81fd263SSubhransu S. Prusty 	header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id);
860b81fd263SSubhransu S. Prusty 	header.extension |= IPC_FINAL_BLOCK(0);
861b81fd263SSubhransu S. Prusty 	header.extension |= IPC_INITIAL_BLOCK(1);
862b81fd263SSubhransu S. Prusty 
863b81fd263SSubhransu S. Prusty 	sz_remaining = msg->param_data_size;
864b81fd263SSubhransu S. Prusty 	data_offset = 0;
865b81fd263SSubhransu S. Prusty 	while (sz_remaining != 0) {
866b81fd263SSubhransu S. Prusty 		tx_size = sz_remaining > SKL_ADSP_W1_SZ
867b81fd263SSubhransu S. Prusty 				? SKL_ADSP_W1_SZ : sz_remaining;
868b81fd263SSubhransu S. Prusty 		if (tx_size == sz_remaining)
869b81fd263SSubhransu S. Prusty 			header.extension |= IPC_FINAL_BLOCK(1);
870b81fd263SSubhransu S. Prusty 
871b81fd263SSubhransu S. Prusty 		dev_dbg(ipc->dev, "In %s primary=%#x ext=%#x\n", __func__,
872b81fd263SSubhransu S. Prusty 			header.primary, header.extension);
873b81fd263SSubhransu S. Prusty 		dev_dbg(ipc->dev, "transmitting offset: %#x, size: %#x\n",
874b81fd263SSubhransu S. Prusty 			(unsigned)data_offset, (unsigned)tx_size);
875b81fd263SSubhransu S. Prusty 		ret = sst_ipc_tx_message_wait(ipc, *ipc_header,
876b81fd263SSubhransu S. Prusty 					  ((char *)param) + data_offset,
877b81fd263SSubhransu S. Prusty 					  tx_size, NULL, 0);
878b81fd263SSubhransu S. Prusty 		if (ret < 0) {
879b81fd263SSubhransu S. Prusty 			dev_err(ipc->dev,
880b81fd263SSubhransu S. Prusty 				"ipc: set large config fail, err: %d\n", ret);
881b81fd263SSubhransu S. Prusty 			return ret;
882b81fd263SSubhransu S. Prusty 		}
883b81fd263SSubhransu S. Prusty 		sz_remaining -= tx_size;
884b81fd263SSubhransu S. Prusty 		data_offset = msg->param_data_size - sz_remaining;
885b81fd263SSubhransu S. Prusty 
886b81fd263SSubhransu S. Prusty 		/* clear the fields */
887b81fd263SSubhransu S. Prusty 		header.extension &= IPC_INITIAL_BLOCK_CLEAR;
888b81fd263SSubhransu S. Prusty 		header.extension &= IPC_DATA_OFFSET_SZ_CLEAR;
889b81fd263SSubhransu S. Prusty 		/* fill the fields */
890b81fd263SSubhransu S. Prusty 		header.extension |= IPC_INITIAL_BLOCK(0);
891b81fd263SSubhransu S. Prusty 		header.extension |= IPC_DATA_OFFSET_SZ(data_offset);
892b81fd263SSubhransu S. Prusty 	}
893b81fd263SSubhransu S. Prusty 
894b81fd263SSubhransu S. Prusty 	return ret;
895b81fd263SSubhransu S. Prusty }
896b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_set_large_config);
897cce1c7f3SMousami Jana 
898cce1c7f3SMousami Jana int skl_ipc_get_large_config(struct sst_generic_ipc *ipc,
899cce1c7f3SMousami Jana 		struct skl_ipc_large_config_msg *msg, u32 *param)
900cce1c7f3SMousami Jana {
901cce1c7f3SMousami Jana 	struct skl_ipc_header header = {0};
902cce1c7f3SMousami Jana 	u64 *ipc_header = (u64 *)(&header);
903cce1c7f3SMousami Jana 	int ret = 0;
904cce1c7f3SMousami Jana 	size_t sz_remaining, rx_size, data_offset;
905cce1c7f3SMousami Jana 
906cce1c7f3SMousami Jana 	header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
907cce1c7f3SMousami Jana 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
908cce1c7f3SMousami Jana 	header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_GET);
909cce1c7f3SMousami Jana 	header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
910cce1c7f3SMousami Jana 	header.primary |= IPC_MOD_ID(msg->module_id);
911cce1c7f3SMousami Jana 
912cce1c7f3SMousami Jana 	header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size);
913cce1c7f3SMousami Jana 	header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id);
914cce1c7f3SMousami Jana 	header.extension |= IPC_FINAL_BLOCK(1);
915cce1c7f3SMousami Jana 	header.extension |= IPC_INITIAL_BLOCK(1);
916cce1c7f3SMousami Jana 
917cce1c7f3SMousami Jana 	sz_remaining = msg->param_data_size;
918cce1c7f3SMousami Jana 	data_offset = 0;
919cce1c7f3SMousami Jana 
920cce1c7f3SMousami Jana 	while (sz_remaining != 0) {
921cce1c7f3SMousami Jana 		rx_size = sz_remaining > SKL_ADSP_W1_SZ
922cce1c7f3SMousami Jana 				? SKL_ADSP_W1_SZ : sz_remaining;
923cce1c7f3SMousami Jana 		if (rx_size == sz_remaining)
924cce1c7f3SMousami Jana 			header.extension |= IPC_FINAL_BLOCK(1);
925cce1c7f3SMousami Jana 
926cce1c7f3SMousami Jana 		ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0,
927cce1c7f3SMousami Jana 					      ((char *)param) + data_offset,
928cce1c7f3SMousami Jana 					      msg->param_data_size);
929cce1c7f3SMousami Jana 		if (ret < 0) {
930cce1c7f3SMousami Jana 			dev_err(ipc->dev,
931cce1c7f3SMousami Jana 				"ipc: get large config fail, err: %d\n", ret);
932cce1c7f3SMousami Jana 			return ret;
933cce1c7f3SMousami Jana 		}
934cce1c7f3SMousami Jana 		sz_remaining -= rx_size;
935cce1c7f3SMousami Jana 		data_offset = msg->param_data_size - sz_remaining;
936cce1c7f3SMousami Jana 
937cce1c7f3SMousami Jana 		/* clear the fields */
938cce1c7f3SMousami Jana 		header.extension &= IPC_INITIAL_BLOCK_CLEAR;
939cce1c7f3SMousami Jana 		header.extension &= IPC_DATA_OFFSET_SZ_CLEAR;
940cce1c7f3SMousami Jana 		/* fill the fields */
941cce1c7f3SMousami Jana 		header.extension |= IPC_INITIAL_BLOCK(1);
942cce1c7f3SMousami Jana 		header.extension |= IPC_DATA_OFFSET_SZ(data_offset);
943cce1c7f3SMousami Jana 	}
944cce1c7f3SMousami Jana 
945cce1c7f3SMousami Jana 	return ret;
946cce1c7f3SMousami Jana }
947cce1c7f3SMousami Jana EXPORT_SYMBOL_GPL(skl_ipc_get_large_config);
94820fb2fbdSRamesh Babu 
94920fb2fbdSRamesh Babu int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc,
95020fb2fbdSRamesh Babu 				u8 dma_id, u8 table_id)
95120fb2fbdSRamesh Babu {
95220fb2fbdSRamesh Babu 	struct skl_ipc_header header = {0};
95320fb2fbdSRamesh Babu 	u64 *ipc_header = (u64 *)(&header);
95420fb2fbdSRamesh Babu 	int ret = 0;
95520fb2fbdSRamesh Babu 
95620fb2fbdSRamesh Babu 	header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
95720fb2fbdSRamesh Babu 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
95820fb2fbdSRamesh Babu 	header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_LIBRARY);
95920fb2fbdSRamesh Babu 	header.primary |= IPC_MOD_INSTANCE_ID(table_id);
96020fb2fbdSRamesh Babu 	header.primary |= IPC_MOD_ID(dma_id);
96120fb2fbdSRamesh Babu 
96220fb2fbdSRamesh Babu 	ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
96320fb2fbdSRamesh Babu 
96420fb2fbdSRamesh Babu 	if (ret < 0)
96520fb2fbdSRamesh Babu 		dev_err(ipc->dev, "ipc: load lib failed\n");
96620fb2fbdSRamesh Babu 
96720fb2fbdSRamesh Babu 	return ret;
96820fb2fbdSRamesh Babu }
96920fb2fbdSRamesh Babu EXPORT_SYMBOL_GPL(skl_sst_ipc_load_library);
97041b7523fSPardha Saradhi K 
97141b7523fSPardha Saradhi K int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, struct skl_ipc_d0ix_msg *msg)
97241b7523fSPardha Saradhi K {
97341b7523fSPardha Saradhi K 	struct skl_ipc_header header = {0};
97441b7523fSPardha Saradhi K 	u64 *ipc_header = (u64 *)(&header);
97541b7523fSPardha Saradhi K 	int ret;
97641b7523fSPardha Saradhi K 
97741b7523fSPardha Saradhi K 	header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
97841b7523fSPardha Saradhi K 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
97941b7523fSPardha Saradhi K 	header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_D0IX);
98041b7523fSPardha Saradhi K 	header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
98141b7523fSPardha Saradhi K 	header.primary |= IPC_MOD_ID(msg->module_id);
98241b7523fSPardha Saradhi K 
98341b7523fSPardha Saradhi K 	header.extension = IPC_D0IX_WAKE(msg->wake);
98441b7523fSPardha Saradhi K 	header.extension |= IPC_D0IX_STREAMING(msg->streaming);
98541b7523fSPardha Saradhi K 
98641b7523fSPardha Saradhi K 	dev_dbg(ipc->dev, "In %s primary=%x ext=%x\n", __func__,
98741b7523fSPardha Saradhi K 			header.primary,	header.extension);
98841b7523fSPardha Saradhi K 
98941b7523fSPardha Saradhi K 	/*
99041b7523fSPardha Saradhi K 	 * Use the nopm IPC here as we dont want it checking for D0iX
99141b7523fSPardha Saradhi K 	 */
99241b7523fSPardha Saradhi K 	ret = sst_ipc_tx_message_nopm(ipc, *ipc_header, NULL, 0, NULL, 0);
99341b7523fSPardha Saradhi K 	if (ret < 0)
99441b7523fSPardha Saradhi K 		dev_err(ipc->dev, "ipc: set d0ix failed, err %d\n", ret);
99541b7523fSPardha Saradhi K 
99641b7523fSPardha Saradhi K 	return ret;
99741b7523fSPardha Saradhi K }
99841b7523fSPardha Saradhi K EXPORT_SYMBOL_GPL(skl_ipc_set_d0ix);
999