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