cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

skl-sst-ipc.c (30819B)


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