1 /*
2  * skl-sst-ipc.c - Intel skl IPC Support
3  *
4  * Copyright (C) 2014-15, Intel Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as version 2, as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  */
15 #include <linux/device.h>
16 
17 #include "../common/sst-dsp.h"
18 #include "../common/sst-dsp-priv.h"
19 #include "skl.h"
20 #include "skl-sst-dsp.h"
21 #include "skl-sst-ipc.h"
22 #include "sound/hdaudio_ext.h"
23 
24 
25 #define IPC_IXC_STATUS_BITS		24
26 
27 /* Global Message - Generic */
28 #define IPC_GLB_TYPE_SHIFT		24
29 #define IPC_GLB_TYPE_MASK		(0xf << IPC_GLB_TYPE_SHIFT)
30 #define IPC_GLB_TYPE(x)			((x) << IPC_GLB_TYPE_SHIFT)
31 
32 /* Global Message - Reply */
33 #define IPC_GLB_REPLY_STATUS_SHIFT	24
34 #define IPC_GLB_REPLY_STATUS_MASK	((0x1 << IPC_GLB_REPLY_STATUS_SHIFT) - 1)
35 #define IPC_GLB_REPLY_STATUS(x)		((x) << IPC_GLB_REPLY_STATUS_SHIFT)
36 
37 #define IPC_TIMEOUT_MSECS		3000
38 
39 #define IPC_EMPTY_LIST_SIZE		8
40 
41 #define IPC_MSG_TARGET_SHIFT		30
42 #define IPC_MSG_TARGET_MASK		0x1
43 #define IPC_MSG_TARGET(x)		(((x) & IPC_MSG_TARGET_MASK) \
44 					<< IPC_MSG_TARGET_SHIFT)
45 
46 #define IPC_MSG_DIR_SHIFT		29
47 #define IPC_MSG_DIR_MASK		0x1
48 #define IPC_MSG_DIR(x)			(((x) & IPC_MSG_DIR_MASK) \
49 					<< IPC_MSG_DIR_SHIFT)
50 /* Global Notification Message */
51 #define IPC_GLB_NOTIFY_TYPE_SHIFT	16
52 #define IPC_GLB_NOTIFY_TYPE_MASK	0xFF
53 #define IPC_GLB_NOTIFY_TYPE(x)		(((x) >> IPC_GLB_NOTIFY_TYPE_SHIFT) \
54 					& IPC_GLB_NOTIFY_TYPE_MASK)
55 
56 #define IPC_GLB_NOTIFY_MSG_TYPE_SHIFT	24
57 #define IPC_GLB_NOTIFY_MSG_TYPE_MASK	0x1F
58 #define IPC_GLB_NOTIFY_MSG_TYPE(x)	(((x) >> IPC_GLB_NOTIFY_MSG_TYPE_SHIFT)	\
59 						& IPC_GLB_NOTIFY_MSG_TYPE_MASK)
60 
61 #define IPC_GLB_NOTIFY_RSP_SHIFT	29
62 #define IPC_GLB_NOTIFY_RSP_MASK		0x1
63 #define IPC_GLB_NOTIFY_RSP_TYPE(x)	(((x) >> IPC_GLB_NOTIFY_RSP_SHIFT) \
64 					& IPC_GLB_NOTIFY_RSP_MASK)
65 
66 /* Pipeline operations */
67 
68 /* Create pipeline message */
69 #define IPC_PPL_MEM_SIZE_SHIFT		0
70 #define IPC_PPL_MEM_SIZE_MASK		0x7FF
71 #define IPC_PPL_MEM_SIZE(x)		(((x) & IPC_PPL_MEM_SIZE_MASK) \
72 					<< IPC_PPL_MEM_SIZE_SHIFT)
73 
74 #define IPC_PPL_TYPE_SHIFT		11
75 #define IPC_PPL_TYPE_MASK		0x1F
76 #define IPC_PPL_TYPE(x)			(((x) & IPC_PPL_TYPE_MASK) \
77 					<< IPC_PPL_TYPE_SHIFT)
78 
79 #define IPC_INSTANCE_ID_SHIFT		16
80 #define IPC_INSTANCE_ID_MASK		0xFF
81 #define IPC_INSTANCE_ID(x)		(((x) & IPC_INSTANCE_ID_MASK) \
82 					<< IPC_INSTANCE_ID_SHIFT)
83 
84 /* Set pipeline state message */
85 #define IPC_PPL_STATE_SHIFT		0
86 #define IPC_PPL_STATE_MASK		0x1F
87 #define IPC_PPL_STATE(x)		(((x) & IPC_PPL_STATE_MASK) \
88 					<< IPC_PPL_STATE_SHIFT)
89 
90 /* Module operations primary register */
91 #define IPC_MOD_ID_SHIFT		0
92 #define IPC_MOD_ID_MASK		0xFFFF
93 #define IPC_MOD_ID(x)		(((x) & IPC_MOD_ID_MASK) \
94 					<< IPC_MOD_ID_SHIFT)
95 
96 #define IPC_MOD_INSTANCE_ID_SHIFT	16
97 #define IPC_MOD_INSTANCE_ID_MASK	0xFF
98 #define IPC_MOD_INSTANCE_ID(x)	(((x) & IPC_MOD_INSTANCE_ID_MASK) \
99 					<< IPC_MOD_INSTANCE_ID_SHIFT)
100 
101 /* Init instance message extension register */
102 #define IPC_PARAM_BLOCK_SIZE_SHIFT	0
103 #define IPC_PARAM_BLOCK_SIZE_MASK	0xFFFF
104 #define IPC_PARAM_BLOCK_SIZE(x)		(((x) & IPC_PARAM_BLOCK_SIZE_MASK) \
105 					<< IPC_PARAM_BLOCK_SIZE_SHIFT)
106 
107 #define IPC_PPL_INSTANCE_ID_SHIFT	16
108 #define IPC_PPL_INSTANCE_ID_MASK	0xFF
109 #define IPC_PPL_INSTANCE_ID(x)		(((x) & IPC_PPL_INSTANCE_ID_MASK) \
110 					<< IPC_PPL_INSTANCE_ID_SHIFT)
111 
112 #define IPC_CORE_ID_SHIFT		24
113 #define IPC_CORE_ID_MASK		0x1F
114 #define IPC_CORE_ID(x)			(((x) & IPC_CORE_ID_MASK) \
115 					<< IPC_CORE_ID_SHIFT)
116 
117 /* Bind/Unbind message extension register */
118 #define IPC_DST_MOD_ID_SHIFT		0
119 #define IPC_DST_MOD_ID(x)		(((x) & IPC_MOD_ID_MASK) \
120 					<< IPC_DST_MOD_ID_SHIFT)
121 
122 #define IPC_DST_MOD_INSTANCE_ID_SHIFT 16
123 #define IPC_DST_MOD_INSTANCE_ID(x)	(((x) & IPC_MOD_INSTANCE_ID_MASK) \
124 					<< IPC_DST_MOD_INSTANCE_ID_SHIFT)
125 
126 #define IPC_DST_QUEUE_SHIFT		24
127 #define IPC_DST_QUEUE_MASK		0x7
128 #define IPC_DST_QUEUE(x)		(((x) & IPC_DST_QUEUE_MASK) \
129 					<< IPC_DST_QUEUE_SHIFT)
130 
131 #define IPC_SRC_QUEUE_SHIFT		27
132 #define IPC_SRC_QUEUE_MASK		0x7
133 #define IPC_SRC_QUEUE(x)		(((x) & IPC_SRC_QUEUE_MASK) \
134 					<< IPC_SRC_QUEUE_SHIFT)
135 /* Load Module count */
136 #define IPC_LOAD_MODULE_SHIFT		0
137 #define IPC_LOAD_MODULE_MASK		0xFF
138 #define IPC_LOAD_MODULE_CNT(x)		(((x) & IPC_LOAD_MODULE_MASK) \
139 					<< IPC_LOAD_MODULE_SHIFT)
140 
141 /* Save pipeline messgae extension register */
142 #define IPC_DMA_ID_SHIFT		0
143 #define IPC_DMA_ID_MASK			0x1F
144 #define IPC_DMA_ID(x)			(((x) & IPC_DMA_ID_MASK) \
145 					<< IPC_DMA_ID_SHIFT)
146 /* Large Config message extension register */
147 #define IPC_DATA_OFFSET_SZ_SHIFT	0
148 #define IPC_DATA_OFFSET_SZ_MASK		0xFFFFF
149 #define IPC_DATA_OFFSET_SZ(x)		(((x) & IPC_DATA_OFFSET_SZ_MASK) \
150 					<< IPC_DATA_OFFSET_SZ_SHIFT)
151 #define IPC_DATA_OFFSET_SZ_CLEAR	~(IPC_DATA_OFFSET_SZ_MASK \
152 					  << IPC_DATA_OFFSET_SZ_SHIFT)
153 
154 #define IPC_LARGE_PARAM_ID_SHIFT	20
155 #define IPC_LARGE_PARAM_ID_MASK		0xFF
156 #define IPC_LARGE_PARAM_ID(x)		(((x) & IPC_LARGE_PARAM_ID_MASK) \
157 					<< IPC_LARGE_PARAM_ID_SHIFT)
158 
159 #define IPC_FINAL_BLOCK_SHIFT		28
160 #define IPC_FINAL_BLOCK_MASK		0x1
161 #define IPC_FINAL_BLOCK(x)		(((x) & IPC_FINAL_BLOCK_MASK) \
162 					<< IPC_FINAL_BLOCK_SHIFT)
163 
164 #define IPC_INITIAL_BLOCK_SHIFT		29
165 #define IPC_INITIAL_BLOCK_MASK		0x1
166 #define IPC_INITIAL_BLOCK(x)		(((x) & IPC_INITIAL_BLOCK_MASK) \
167 					<< IPC_INITIAL_BLOCK_SHIFT)
168 #define IPC_INITIAL_BLOCK_CLEAR		~(IPC_INITIAL_BLOCK_MASK \
169 					  << IPC_INITIAL_BLOCK_SHIFT)
170 
171 enum skl_ipc_msg_target {
172 	IPC_FW_GEN_MSG = 0,
173 	IPC_MOD_MSG = 1
174 };
175 
176 enum skl_ipc_msg_direction {
177 	IPC_MSG_REQUEST = 0,
178 	IPC_MSG_REPLY = 1
179 };
180 
181 /* Global Message Types */
182 enum skl_ipc_glb_type {
183 	IPC_GLB_GET_FW_VERSION = 0, /* Retrieves firmware version */
184 	IPC_GLB_LOAD_MULTIPLE_MODS = 15,
185 	IPC_GLB_UNLOAD_MULTIPLE_MODS = 16,
186 	IPC_GLB_CREATE_PPL = 17,
187 	IPC_GLB_DELETE_PPL = 18,
188 	IPC_GLB_SET_PPL_STATE = 19,
189 	IPC_GLB_GET_PPL_STATE = 20,
190 	IPC_GLB_GET_PPL_CONTEXT_SIZE = 21,
191 	IPC_GLB_SAVE_PPL = 22,
192 	IPC_GLB_RESTORE_PPL = 23,
193 	IPC_GLB_NOTIFY = 26,
194 	IPC_GLB_MAX_IPC_MSG_NUMBER = 31 /* Maximum message number */
195 };
196 
197 enum skl_ipc_glb_reply {
198 	IPC_GLB_REPLY_SUCCESS = 0,
199 
200 	IPC_GLB_REPLY_UNKNOWN_MSG_TYPE = 1,
201 	IPC_GLB_REPLY_ERROR_INVALID_PARAM = 2,
202 
203 	IPC_GLB_REPLY_BUSY = 3,
204 	IPC_GLB_REPLY_PENDING = 4,
205 	IPC_GLB_REPLY_FAILURE = 5,
206 	IPC_GLB_REPLY_INVALID_REQUEST = 6,
207 
208 	IPC_GLB_REPLY_OUT_OF_MEMORY = 7,
209 	IPC_GLB_REPLY_OUT_OF_MIPS = 8,
210 
211 	IPC_GLB_REPLY_INVALID_RESOURCE_ID = 9,
212 	IPC_GLB_REPLY_INVALID_RESOURCE_STATE = 10,
213 
214 	IPC_GLB_REPLY_MOD_MGMT_ERROR = 100,
215 	IPC_GLB_REPLY_MOD_LOAD_CL_FAILED = 101,
216 	IPC_GLB_REPLY_MOD_LOAD_INVALID_HASH = 102,
217 
218 	IPC_GLB_REPLY_MOD_UNLOAD_INST_EXIST = 103,
219 	IPC_GLB_REPLY_MOD_NOT_INITIALIZED = 104,
220 
221 	IPC_GLB_REPLY_INVALID_CONFIG_PARAM_ID = 120,
222 	IPC_GLB_REPLY_INVALID_CONFIG_DATA_LEN = 121,
223 	IPC_GLB_REPLY_GATEWAY_NOT_INITIALIZED = 140,
224 	IPC_GLB_REPLY_GATEWAY_NOT_EXIST = 141,
225 
226 	IPC_GLB_REPLY_PPL_NOT_INITIALIZED = 160,
227 	IPC_GLB_REPLY_PPL_NOT_EXIST = 161,
228 	IPC_GLB_REPLY_PPL_SAVE_FAILED = 162,
229 	IPC_GLB_REPLY_PPL_RESTORE_FAILED = 163,
230 
231 	IPC_MAX_STATUS = ((1<<IPC_IXC_STATUS_BITS)-1)
232 };
233 
234 enum skl_ipc_notification_type {
235 	IPC_GLB_NOTIFY_GLITCH = 0,
236 	IPC_GLB_NOTIFY_OVERRUN = 1,
237 	IPC_GLB_NOTIFY_UNDERRUN = 2,
238 	IPC_GLB_NOTIFY_END_STREAM = 3,
239 	IPC_GLB_NOTIFY_PHRASE_DETECTED = 4,
240 	IPC_GLB_NOTIFY_RESOURCE_EVENT = 5,
241 	IPC_GLB_NOTIFY_LOG_BUFFER_STATUS = 6,
242 	IPC_GLB_NOTIFY_TIMESTAMP_CAPTURED = 7,
243 	IPC_GLB_NOTIFY_FW_READY = 8
244 };
245 
246 /* Module Message Types */
247 enum skl_ipc_module_msg {
248 	IPC_MOD_INIT_INSTANCE = 0,
249 	IPC_MOD_CONFIG_GET = 1,
250 	IPC_MOD_CONFIG_SET = 2,
251 	IPC_MOD_LARGE_CONFIG_GET = 3,
252 	IPC_MOD_LARGE_CONFIG_SET = 4,
253 	IPC_MOD_BIND = 5,
254 	IPC_MOD_UNBIND = 6,
255 	IPC_MOD_SET_DX = 7
256 };
257 
258 static void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data,
259 		size_t tx_size)
260 {
261 	if (tx_size)
262 		memcpy(msg->tx_data, tx_data, tx_size);
263 }
264 
265 static bool skl_ipc_is_dsp_busy(struct sst_dsp *dsp)
266 {
267 	u32 hipci;
268 
269 	hipci = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCI);
270 	return (hipci & SKL_ADSP_REG_HIPCI_BUSY);
271 }
272 
273 /* Lock to be held by caller */
274 static void skl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg)
275 {
276 	struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->header);
277 
278 	if (msg->tx_size)
279 		sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size);
280 	sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCIE,
281 						header->extension);
282 	sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCI,
283 		header->primary | SKL_ADSP_REG_HIPCI_BUSY);
284 }
285 
286 static struct ipc_message *skl_ipc_reply_get_msg(struct sst_generic_ipc *ipc,
287 				u64 ipc_header)
288 {
289 	struct ipc_message *msg =  NULL;
290 	struct skl_ipc_header *header = (struct skl_ipc_header *)(&ipc_header);
291 
292 	if (list_empty(&ipc->rx_list)) {
293 		dev_err(ipc->dev, "ipc: rx list is empty but received 0x%x\n",
294 			header->primary);
295 		goto out;
296 	}
297 
298 	msg = list_first_entry(&ipc->rx_list, struct ipc_message, list);
299 
300 out:
301 	return msg;
302 
303 }
304 
305 static int skl_ipc_process_notification(struct sst_generic_ipc *ipc,
306 		struct skl_ipc_header header)
307 {
308 	struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc);
309 
310 	if (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) {
311 		switch (IPC_GLB_NOTIFY_TYPE(header.primary)) {
312 
313 		case IPC_GLB_NOTIFY_UNDERRUN:
314 			dev_err(ipc->dev, "FW Underrun %x\n", header.primary);
315 			break;
316 
317 		case IPC_GLB_NOTIFY_RESOURCE_EVENT:
318 			dev_err(ipc->dev, "MCPS Budget Violation: %x\n",
319 						header.primary);
320 			break;
321 
322 		case IPC_GLB_NOTIFY_FW_READY:
323 			skl->boot_complete = true;
324 			wake_up(&skl->boot_wait);
325 			break;
326 
327 		case IPC_GLB_NOTIFY_PHRASE_DETECTED:
328 			dev_dbg(ipc->dev, "***** Phrase Detected **********\n");
329 
330 			/*
331 			 * Per HW recomendation, After phrase detection,
332 			 * clear the CGCTL.MISCBDCGE.
333 			 *
334 			 * This will be set back on stream closure
335 			 */
336 			skl->enable_miscbdcge(ipc->dev, false);
337 			skl->miscbdcg_disabled = true;
338 			break;
339 
340 		default:
341 			dev_err(ipc->dev, "ipc: Unhandled error msg=%x",
342 						header.primary);
343 			break;
344 		}
345 	}
346 
347 	return 0;
348 }
349 
350 static void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
351 		struct skl_ipc_header header)
352 {
353 	struct ipc_message *msg;
354 	u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK;
355 	u64 *ipc_header = (u64 *)(&header);
356 
357 	msg = skl_ipc_reply_get_msg(ipc, *ipc_header);
358 	if (msg == NULL) {
359 		dev_dbg(ipc->dev, "ipc: rx list is empty\n");
360 		return;
361 	}
362 
363 	/* first process the header */
364 	switch (reply) {
365 	case IPC_GLB_REPLY_SUCCESS:
366 		dev_dbg(ipc->dev, "ipc FW reply %x: success\n", header.primary);
367 		/* copy the rx data from the mailbox */
368 		sst_dsp_inbox_read(ipc->dsp, msg->rx_data, msg->rx_size);
369 		break;
370 
371 	case IPC_GLB_REPLY_OUT_OF_MEMORY:
372 		dev_err(ipc->dev, "ipc fw reply: %x: no memory\n", header.primary);
373 		msg->errno = -ENOMEM;
374 		break;
375 
376 	case IPC_GLB_REPLY_BUSY:
377 		dev_err(ipc->dev, "ipc fw reply: %x: Busy\n", header.primary);
378 		msg->errno = -EBUSY;
379 		break;
380 
381 	default:
382 		dev_err(ipc->dev, "Unknown ipc reply: 0x%x", reply);
383 		msg->errno = -EINVAL;
384 		break;
385 	}
386 
387 	if (reply != IPC_GLB_REPLY_SUCCESS) {
388 		dev_err(ipc->dev, "ipc FW reply: reply=%d", reply);
389 		dev_err(ipc->dev, "FW Error Code: %u\n",
390 			ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp));
391 	}
392 
393 	list_del(&msg->list);
394 	sst_ipc_tx_msg_reply_complete(ipc, msg);
395 }
396 
397 irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context)
398 {
399 	struct sst_dsp *dsp = context;
400 	struct skl_sst *skl = sst_dsp_get_thread_context(dsp);
401 	struct sst_generic_ipc *ipc = &skl->ipc;
402 	struct skl_ipc_header header = {0};
403 	u32 hipcie, hipct, hipcte;
404 	int ipc_irq = 0;
405 
406 	if (dsp->intr_status & SKL_ADSPIS_CL_DMA)
407 		skl_cldma_process_intr(dsp);
408 
409 	/* Here we handle IPC interrupts only */
410 	if (!(dsp->intr_status & SKL_ADSPIS_IPC))
411 		return IRQ_NONE;
412 
413 	hipcie = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCIE);
414 	hipct = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCT);
415 
416 	/* reply message from DSP */
417 	if (hipcie & SKL_ADSP_REG_HIPCIE_DONE) {
418 		sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL,
419 			SKL_ADSP_REG_HIPCCTL_DONE, 0);
420 
421 		/* clear DONE bit - tell DSP we have completed the operation */
422 		sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCIE,
423 			SKL_ADSP_REG_HIPCIE_DONE, SKL_ADSP_REG_HIPCIE_DONE);
424 
425 		ipc_irq = 1;
426 
427 		/* unmask Done interrupt */
428 		sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL,
429 			SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE);
430 	}
431 
432 	/* New message from DSP */
433 	if (hipct & SKL_ADSP_REG_HIPCT_BUSY) {
434 		hipcte = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCTE);
435 		header.primary = hipct;
436 		header.extension = hipcte;
437 		dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x",
438 						header.primary);
439 		dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x",
440 						header.extension);
441 
442 		if (IPC_GLB_NOTIFY_RSP_TYPE(header.primary)) {
443 			/* Handle Immediate reply from DSP Core */
444 			skl_ipc_process_reply(ipc, header);
445 		} else {
446 			dev_dbg(dsp->dev, "IPC irq: Notification from firmware\n");
447 			skl_ipc_process_notification(ipc, header);
448 		}
449 		/* clear  busy interrupt */
450 		sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCT,
451 			SKL_ADSP_REG_HIPCT_BUSY, SKL_ADSP_REG_HIPCT_BUSY);
452 		ipc_irq = 1;
453 	}
454 
455 	if (ipc_irq == 0)
456 		return IRQ_NONE;
457 
458 	skl_ipc_int_enable(dsp);
459 
460 	/* continue to send any remaining messages... */
461 	queue_kthread_work(&ipc->kworker, &ipc->kwork);
462 
463 	return IRQ_HANDLED;
464 }
465 
466 void skl_ipc_int_enable(struct sst_dsp *ctx)
467 {
468 	sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_ADSPIC,
469 			SKL_ADSPIC_IPC, SKL_ADSPIC_IPC);
470 }
471 
472 void skl_ipc_int_disable(struct sst_dsp *ctx)
473 {
474 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPIC,
475 			SKL_ADSPIC_IPC, 0);
476 }
477 
478 void skl_ipc_op_int_enable(struct sst_dsp *ctx)
479 {
480 	/* enable IPC DONE interrupt */
481 	sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL,
482 		SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE);
483 
484 	/* Enable IPC BUSY interrupt */
485 	sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL,
486 		SKL_ADSP_REG_HIPCCTL_BUSY, SKL_ADSP_REG_HIPCCTL_BUSY);
487 }
488 
489 void skl_ipc_op_int_disable(struct sst_dsp *ctx)
490 {
491 	/* disable IPC DONE interrupt */
492 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
493 					SKL_ADSP_REG_HIPCCTL_DONE, 0);
494 
495 	/* Disable IPC BUSY interrupt */
496 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
497 					SKL_ADSP_REG_HIPCCTL_BUSY, 0);
498 
499 }
500 
501 bool skl_ipc_int_status(struct sst_dsp *ctx)
502 {
503 	return sst_dsp_shim_read_unlocked(ctx,
504 			SKL_ADSP_REG_ADSPIS) & SKL_ADSPIS_IPC;
505 }
506 
507 int skl_ipc_init(struct device *dev, struct skl_sst *skl)
508 {
509 	struct sst_generic_ipc *ipc;
510 	int err;
511 
512 	ipc = &skl->ipc;
513 	ipc->dsp = skl->dsp;
514 	ipc->dev = dev;
515 
516 	ipc->tx_data_max_size = SKL_ADSP_W1_SZ;
517 	ipc->rx_data_max_size = SKL_ADSP_W0_UP_SZ;
518 
519 	err = sst_ipc_init(ipc);
520 	if (err)
521 		return err;
522 
523 	ipc->ops.tx_msg = skl_ipc_tx_msg;
524 	ipc->ops.tx_data_copy = skl_ipc_tx_data_copy;
525 	ipc->ops.is_dsp_busy = skl_ipc_is_dsp_busy;
526 
527 	return 0;
528 }
529 
530 void skl_ipc_free(struct sst_generic_ipc *ipc)
531 {
532 	/* Disable IPC DONE interrupt */
533 	sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL,
534 		SKL_ADSP_REG_HIPCCTL_DONE, 0);
535 
536 	/* Disable IPC BUSY interrupt */
537 	sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL,
538 		SKL_ADSP_REG_HIPCCTL_BUSY, 0);
539 
540 	sst_ipc_fini(ipc);
541 }
542 
543 int skl_ipc_create_pipeline(struct sst_generic_ipc *ipc,
544 		u16 ppl_mem_size, u8 ppl_type, u8 instance_id)
545 {
546 	struct skl_ipc_header header = {0};
547 	u64 *ipc_header = (u64 *)(&header);
548 	int ret;
549 
550 	header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
551 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
552 	header.primary |= IPC_GLB_TYPE(IPC_GLB_CREATE_PPL);
553 	header.primary |= IPC_INSTANCE_ID(instance_id);
554 	header.primary |= IPC_PPL_TYPE(ppl_type);
555 	header.primary |= IPC_PPL_MEM_SIZE(ppl_mem_size);
556 
557 	dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
558 	ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
559 	if (ret < 0) {
560 		dev_err(ipc->dev, "ipc: create pipeline fail, err: %d\n", ret);
561 		return ret;
562 	}
563 
564 	return ret;
565 }
566 EXPORT_SYMBOL_GPL(skl_ipc_create_pipeline);
567 
568 int skl_ipc_delete_pipeline(struct sst_generic_ipc *ipc, u8 instance_id)
569 {
570 	struct skl_ipc_header header = {0};
571 	u64 *ipc_header = (u64 *)(&header);
572 	int ret;
573 
574 	header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
575 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
576 	header.primary |= IPC_GLB_TYPE(IPC_GLB_DELETE_PPL);
577 	header.primary |= IPC_INSTANCE_ID(instance_id);
578 
579 	dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
580 	ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
581 	if (ret < 0) {
582 		dev_err(ipc->dev, "ipc: delete pipeline failed, err %d\n", ret);
583 		return ret;
584 	}
585 
586 	return 0;
587 }
588 EXPORT_SYMBOL_GPL(skl_ipc_delete_pipeline);
589 
590 int skl_ipc_set_pipeline_state(struct sst_generic_ipc *ipc,
591 		u8 instance_id, enum skl_ipc_pipeline_state state)
592 {
593 	struct skl_ipc_header header = {0};
594 	u64 *ipc_header = (u64 *)(&header);
595 	int ret;
596 
597 	header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
598 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
599 	header.primary |= IPC_GLB_TYPE(IPC_GLB_SET_PPL_STATE);
600 	header.primary |= IPC_INSTANCE_ID(instance_id);
601 	header.primary |= IPC_PPL_STATE(state);
602 
603 	dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
604 	ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
605 	if (ret < 0) {
606 		dev_err(ipc->dev, "ipc: set pipeline state failed, err: %d\n", ret);
607 		return ret;
608 	}
609 	return ret;
610 }
611 EXPORT_SYMBOL_GPL(skl_ipc_set_pipeline_state);
612 
613 int
614 skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, u8 instance_id, int dma_id)
615 {
616 	struct skl_ipc_header header = {0};
617 	u64 *ipc_header = (u64 *)(&header);
618 	int ret;
619 
620 	header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
621 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
622 	header.primary |= IPC_GLB_TYPE(IPC_GLB_SAVE_PPL);
623 	header.primary |= IPC_INSTANCE_ID(instance_id);
624 
625 	header.extension = IPC_DMA_ID(dma_id);
626 	dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
627 	ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
628 	if (ret < 0) {
629 		dev_err(ipc->dev, "ipc: save pipeline failed, err: %d\n", ret);
630 		return ret;
631 	}
632 
633 	return ret;
634 }
635 EXPORT_SYMBOL_GPL(skl_ipc_save_pipeline);
636 
637 int skl_ipc_restore_pipeline(struct sst_generic_ipc *ipc, u8 instance_id)
638 {
639 	struct skl_ipc_header header = {0};
640 	u64 *ipc_header = (u64 *)(&header);
641 	int ret;
642 
643 	header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
644 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
645 	header.primary |= IPC_GLB_TYPE(IPC_GLB_RESTORE_PPL);
646 	header.primary |= IPC_INSTANCE_ID(instance_id);
647 
648 	dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
649 	ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
650 	if (ret < 0) {
651 		dev_err(ipc->dev, "ipc: restore  pipeline failed, err: %d\n", ret);
652 		return ret;
653 	}
654 
655 	return ret;
656 }
657 EXPORT_SYMBOL_GPL(skl_ipc_restore_pipeline);
658 
659 int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id,
660 		u16 module_id, struct skl_ipc_dxstate_info *dx)
661 {
662 	struct skl_ipc_header header = {0};
663 	u64 *ipc_header = (u64 *)(&header);
664 	int ret;
665 
666 	header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
667 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
668 	header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_DX);
669 	header.primary |= IPC_MOD_INSTANCE_ID(instance_id);
670 	header.primary |= IPC_MOD_ID(module_id);
671 
672 	dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__,
673 			 header.primary, header.extension);
674 	ret = sst_ipc_tx_message_wait(ipc, *ipc_header,
675 				dx, sizeof(*dx), NULL, 0);
676 	if (ret < 0) {
677 		dev_err(ipc->dev, "ipc: set dx failed, err %d\n", ret);
678 		return ret;
679 	}
680 
681 	return ret;
682 }
683 EXPORT_SYMBOL_GPL(skl_ipc_set_dx);
684 
685 int skl_ipc_init_instance(struct sst_generic_ipc *ipc,
686 		struct skl_ipc_init_instance_msg *msg, void *param_data)
687 {
688 	struct skl_ipc_header header = {0};
689 	u64 *ipc_header = (u64 *)(&header);
690 	int ret;
691 	u32 *buffer = (u32 *)param_data;
692 	 /* param_block_size must be in dwords */
693 	u16 param_block_size = msg->param_data_size / sizeof(u32);
694 
695 	print_hex_dump_debug("Param data:", DUMP_PREFIX_NONE,
696 		16, 4, buffer, param_block_size, false);
697 
698 	header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
699 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
700 	header.primary |= IPC_GLB_TYPE(IPC_MOD_INIT_INSTANCE);
701 	header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
702 	header.primary |= IPC_MOD_ID(msg->module_id);
703 
704 	header.extension = IPC_CORE_ID(msg->core_id);
705 	header.extension |= IPC_PPL_INSTANCE_ID(msg->ppl_instance_id);
706 	header.extension |= IPC_PARAM_BLOCK_SIZE(param_block_size);
707 
708 	dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__,
709 			 header.primary, header.extension);
710 	ret = sst_ipc_tx_message_wait(ipc, *ipc_header, param_data,
711 			msg->param_data_size, NULL, 0);
712 
713 	if (ret < 0) {
714 		dev_err(ipc->dev, "ipc: init instance failed\n");
715 		return ret;
716 	}
717 
718 	return ret;
719 }
720 EXPORT_SYMBOL_GPL(skl_ipc_init_instance);
721 
722 int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc,
723 		struct skl_ipc_bind_unbind_msg *msg)
724 {
725 	struct skl_ipc_header header = {0};
726 	u64 *ipc_header = (u64 *)(&header);
727 	u8 bind_unbind = msg->bind ? IPC_MOD_BIND : IPC_MOD_UNBIND;
728 	int ret;
729 
730 	header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
731 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
732 	header.primary |= IPC_GLB_TYPE(bind_unbind);
733 	header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
734 	header.primary |= IPC_MOD_ID(msg->module_id);
735 
736 	header.extension = IPC_DST_MOD_ID(msg->dst_module_id);
737 	header.extension |= IPC_DST_MOD_INSTANCE_ID(msg->dst_instance_id);
738 	header.extension |= IPC_DST_QUEUE(msg->dst_queue);
739 	header.extension |= IPC_SRC_QUEUE(msg->src_queue);
740 
741 	dev_dbg(ipc->dev, "In %s hdr=%x ext=%x\n", __func__, header.primary,
742 			 header.extension);
743 	ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
744 	if (ret < 0) {
745 		dev_err(ipc->dev, "ipc: bind/unbind faileden");
746 		return ret;
747 	}
748 
749 	return ret;
750 }
751 EXPORT_SYMBOL_GPL(skl_ipc_bind_unbind);
752 
753 /*
754  * In order to load a module we need to send IPC to initiate that. DMA will
755  * performed to load the module memory. The FW supports multiple module load
756  * at single shot, so we can send IPC with N modules represented by
757  * module_cnt
758  */
759 int skl_ipc_load_modules(struct sst_generic_ipc *ipc,
760 				u8 module_cnt, void *data)
761 {
762 	struct skl_ipc_header header = {0};
763 	u64 *ipc_header = (u64 *)(&header);
764 	int ret;
765 
766 	header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
767 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
768 	header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_MULTIPLE_MODS);
769 	header.primary |= IPC_LOAD_MODULE_CNT(module_cnt);
770 
771 	ret = sst_ipc_tx_message_wait(ipc, *ipc_header, data,
772 				(sizeof(u16) * module_cnt), NULL, 0);
773 	if (ret < 0)
774 		dev_err(ipc->dev, "ipc: load modules failed :%d\n", ret);
775 
776 	return ret;
777 }
778 EXPORT_SYMBOL_GPL(skl_ipc_load_modules);
779 
780 int skl_ipc_unload_modules(struct sst_generic_ipc *ipc, u8 module_cnt,
781 							void *data)
782 {
783 	struct skl_ipc_header header = {0};
784 	u64 *ipc_header = (u64 *)(&header);
785 	int ret;
786 
787 	header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
788 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
789 	header.primary |= IPC_GLB_TYPE(IPC_GLB_UNLOAD_MULTIPLE_MODS);
790 	header.primary |= IPC_LOAD_MODULE_CNT(module_cnt);
791 
792 	ret = sst_ipc_tx_message_wait(ipc, *ipc_header, data,
793 				(sizeof(u16) * module_cnt), NULL, 0);
794 	if (ret < 0)
795 		dev_err(ipc->dev, "ipc: unload modules failed :%d\n", ret);
796 
797 	return ret;
798 }
799 EXPORT_SYMBOL_GPL(skl_ipc_unload_modules);
800 
801 int skl_ipc_set_large_config(struct sst_generic_ipc *ipc,
802 		struct skl_ipc_large_config_msg *msg, u32 *param)
803 {
804 	struct skl_ipc_header header = {0};
805 	u64 *ipc_header = (u64 *)(&header);
806 	int ret = 0;
807 	size_t sz_remaining, tx_size, data_offset;
808 
809 	header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
810 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
811 	header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_SET);
812 	header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
813 	header.primary |= IPC_MOD_ID(msg->module_id);
814 
815 	header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size);
816 	header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id);
817 	header.extension |= IPC_FINAL_BLOCK(0);
818 	header.extension |= IPC_INITIAL_BLOCK(1);
819 
820 	sz_remaining = msg->param_data_size;
821 	data_offset = 0;
822 	while (sz_remaining != 0) {
823 		tx_size = sz_remaining > SKL_ADSP_W1_SZ
824 				? SKL_ADSP_W1_SZ : sz_remaining;
825 		if (tx_size == sz_remaining)
826 			header.extension |= IPC_FINAL_BLOCK(1);
827 
828 		dev_dbg(ipc->dev, "In %s primary=%#x ext=%#x\n", __func__,
829 			header.primary, header.extension);
830 		dev_dbg(ipc->dev, "transmitting offset: %#x, size: %#x\n",
831 			(unsigned)data_offset, (unsigned)tx_size);
832 		ret = sst_ipc_tx_message_wait(ipc, *ipc_header,
833 					  ((char *)param) + data_offset,
834 					  tx_size, NULL, 0);
835 		if (ret < 0) {
836 			dev_err(ipc->dev,
837 				"ipc: set large config fail, err: %d\n", ret);
838 			return ret;
839 		}
840 		sz_remaining -= tx_size;
841 		data_offset = msg->param_data_size - sz_remaining;
842 
843 		/* clear the fields */
844 		header.extension &= IPC_INITIAL_BLOCK_CLEAR;
845 		header.extension &= IPC_DATA_OFFSET_SZ_CLEAR;
846 		/* fill the fields */
847 		header.extension |= IPC_INITIAL_BLOCK(0);
848 		header.extension |= IPC_DATA_OFFSET_SZ(data_offset);
849 	}
850 
851 	return ret;
852 }
853 EXPORT_SYMBOL_GPL(skl_ipc_set_large_config);
854 
855 int skl_ipc_get_large_config(struct sst_generic_ipc *ipc,
856 		struct skl_ipc_large_config_msg *msg, u32 *param)
857 {
858 	struct skl_ipc_header header = {0};
859 	u64 *ipc_header = (u64 *)(&header);
860 	int ret = 0;
861 	size_t sz_remaining, rx_size, data_offset;
862 
863 	header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
864 	header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
865 	header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_GET);
866 	header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
867 	header.primary |= IPC_MOD_ID(msg->module_id);
868 
869 	header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size);
870 	header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id);
871 	header.extension |= IPC_FINAL_BLOCK(1);
872 	header.extension |= IPC_INITIAL_BLOCK(1);
873 
874 	sz_remaining = msg->param_data_size;
875 	data_offset = 0;
876 
877 	while (sz_remaining != 0) {
878 		rx_size = sz_remaining > SKL_ADSP_W1_SZ
879 				? SKL_ADSP_W1_SZ : sz_remaining;
880 		if (rx_size == sz_remaining)
881 			header.extension |= IPC_FINAL_BLOCK(1);
882 
883 		ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0,
884 					      ((char *)param) + data_offset,
885 					      msg->param_data_size);
886 		if (ret < 0) {
887 			dev_err(ipc->dev,
888 				"ipc: get large config fail, err: %d\n", ret);
889 			return ret;
890 		}
891 		sz_remaining -= rx_size;
892 		data_offset = msg->param_data_size - sz_remaining;
893 
894 		/* clear the fields */
895 		header.extension &= IPC_INITIAL_BLOCK_CLEAR;
896 		header.extension &= IPC_DATA_OFFSET_SZ_CLEAR;
897 		/* fill the fields */
898 		header.extension |= IPC_INITIAL_BLOCK(1);
899 		header.extension |= IPC_DATA_OFFSET_SZ(data_offset);
900 	}
901 
902 	return ret;
903 }
904 EXPORT_SYMBOL_GPL(skl_ipc_get_large_config);
905