1 // SPDX-License-Identifier: GPL-2.0-only 2 // 3 // Copyright(c) 2021-2022 Intel Corporation. All rights reserved. 4 // 5 // Authors: Cezary Rojewski <cezary.rojewski@intel.com> 6 // Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com> 7 // 8 9 #include <linux/slab.h> 10 #include <sound/hdaudio_ext.h> 11 #include "avs.h" 12 #include "messages.h" 13 #include "registers.h" 14 15 #define AVS_IPC_TIMEOUT_MS 300 16 17 static void avs_dsp_receive_rx(struct avs_dev *adev, u64 header) 18 { 19 struct avs_ipc *ipc = adev->ipc; 20 union avs_reply_msg msg = AVS_MSG(header); 21 22 ipc->rx.header = header; 23 /* Abort copying payload if request processing was unsuccessful. */ 24 if (!msg.status) { 25 /* update size in case of LARGE_CONFIG_GET */ 26 if (msg.msg_target == AVS_MOD_MSG && 27 msg.global_msg_type == AVS_MOD_LARGE_CONFIG_GET) 28 ipc->rx.size = msg.ext.large_config.data_off_size; 29 30 memcpy_fromio(ipc->rx.data, avs_uplink_addr(adev), ipc->rx.size); 31 } 32 } 33 34 static void avs_dsp_process_notification(struct avs_dev *adev, u64 header) 35 { 36 struct avs_notify_mod_data mod_data; 37 union avs_notify_msg msg = AVS_MSG(header); 38 size_t data_size = 0; 39 void *data = NULL; 40 41 /* Ignore spurious notifications until handshake is established. */ 42 if (!adev->ipc->ready && msg.notify_msg_type != AVS_NOTIFY_FW_READY) { 43 dev_dbg(adev->dev, "FW not ready, skip notification: 0x%08x\n", msg.primary); 44 return; 45 } 46 47 /* Calculate notification payload size. */ 48 switch (msg.notify_msg_type) { 49 case AVS_NOTIFY_FW_READY: 50 break; 51 52 case AVS_NOTIFY_PHRASE_DETECTED: 53 data_size = sizeof(struct avs_notify_voice_data); 54 break; 55 56 case AVS_NOTIFY_RESOURCE_EVENT: 57 data_size = sizeof(struct avs_notify_res_data); 58 break; 59 60 case AVS_NOTIFY_MODULE_EVENT: 61 /* To know the total payload size, header needs to be read first. */ 62 memcpy_fromio(&mod_data, avs_uplink_addr(adev), sizeof(mod_data)); 63 data_size = sizeof(mod_data) + mod_data.data_size; 64 break; 65 66 default: 67 dev_info(adev->dev, "unknown notification: 0x%08x\n", msg.primary); 68 break; 69 } 70 71 if (data_size) { 72 data = kmalloc(data_size, GFP_KERNEL); 73 if (!data) 74 return; 75 76 memcpy_fromio(data, avs_uplink_addr(adev), data_size); 77 } 78 79 /* Perform notification-specific operations. */ 80 switch (msg.notify_msg_type) { 81 case AVS_NOTIFY_FW_READY: 82 dev_dbg(adev->dev, "FW READY 0x%08x\n", msg.primary); 83 adev->ipc->ready = true; 84 complete(&adev->fw_ready); 85 break; 86 87 default: 88 break; 89 } 90 91 kfree(data); 92 } 93 94 void avs_dsp_process_response(struct avs_dev *adev, u64 header) 95 { 96 struct avs_ipc *ipc = adev->ipc; 97 98 /* 99 * Response may either be solicited - a reply for a request that has 100 * been sent beforehand - or unsolicited (notification). 101 */ 102 if (avs_msg_is_reply(header)) { 103 /* Response processing is invoked from IRQ thread. */ 104 spin_lock_irq(&ipc->rx_lock); 105 avs_dsp_receive_rx(adev, header); 106 ipc->rx_completed = true; 107 spin_unlock_irq(&ipc->rx_lock); 108 } else { 109 avs_dsp_process_notification(adev, header); 110 } 111 112 complete(&ipc->busy_completion); 113 } 114 115 irqreturn_t avs_dsp_irq_handler(int irq, void *dev_id) 116 { 117 struct avs_dev *adev = dev_id; 118 struct avs_ipc *ipc = adev->ipc; 119 u32 adspis, hipc_rsp, hipc_ack; 120 irqreturn_t ret = IRQ_NONE; 121 122 adspis = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPIS); 123 if (adspis == UINT_MAX || !(adspis & AVS_ADSP_ADSPIS_IPC)) 124 return ret; 125 126 hipc_ack = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCIE); 127 hipc_rsp = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCT); 128 129 /* DSP acked host's request */ 130 if (hipc_ack & SKL_ADSP_HIPCIE_DONE) { 131 /* 132 * As an extra precaution, mask done interrupt. Code executed 133 * due to complete() found below does not assume any masking. 134 */ 135 snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL, 136 AVS_ADSP_HIPCCTL_DONE, 0); 137 138 complete(&ipc->done_completion); 139 140 /* tell DSP it has our attention */ 141 snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCIE, 142 SKL_ADSP_HIPCIE_DONE, 143 SKL_ADSP_HIPCIE_DONE); 144 /* unmask done interrupt */ 145 snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL, 146 AVS_ADSP_HIPCCTL_DONE, 147 AVS_ADSP_HIPCCTL_DONE); 148 ret = IRQ_HANDLED; 149 } 150 151 /* DSP sent new response to process */ 152 if (hipc_rsp & SKL_ADSP_HIPCT_BUSY) { 153 /* mask busy interrupt */ 154 snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL, 155 AVS_ADSP_HIPCCTL_BUSY, 0); 156 157 ret = IRQ_WAKE_THREAD; 158 } 159 160 return ret; 161 } 162 163 irqreturn_t avs_dsp_irq_thread(int irq, void *dev_id) 164 { 165 struct avs_dev *adev = dev_id; 166 union avs_reply_msg msg; 167 u32 hipct, hipcte; 168 169 hipct = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCT); 170 hipcte = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCTE); 171 172 /* ensure DSP sent new response to process */ 173 if (!(hipct & SKL_ADSP_HIPCT_BUSY)) 174 return IRQ_NONE; 175 176 msg.primary = hipct; 177 msg.ext.val = hipcte; 178 avs_dsp_process_response(adev, msg.val); 179 180 /* tell DSP we accepted its message */ 181 snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCT, 182 SKL_ADSP_HIPCT_BUSY, SKL_ADSP_HIPCT_BUSY); 183 /* unmask busy interrupt */ 184 snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL, 185 AVS_ADSP_HIPCCTL_BUSY, AVS_ADSP_HIPCCTL_BUSY); 186 187 return IRQ_HANDLED; 188 } 189 190 static bool avs_ipc_is_busy(struct avs_ipc *ipc) 191 { 192 struct avs_dev *adev = to_avs_dev(ipc->dev); 193 u32 hipc_rsp; 194 195 hipc_rsp = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCT); 196 return hipc_rsp & SKL_ADSP_HIPCT_BUSY; 197 } 198 199 static int avs_ipc_wait_busy_completion(struct avs_ipc *ipc, int timeout) 200 { 201 u32 repeats_left = 128; /* to avoid infinite looping */ 202 int ret; 203 204 again: 205 ret = wait_for_completion_timeout(&ipc->busy_completion, msecs_to_jiffies(timeout)); 206 207 /* DSP could be unresponsive at this point. */ 208 if (!ipc->ready) 209 return -EPERM; 210 211 if (!ret) { 212 if (!avs_ipc_is_busy(ipc)) 213 return -ETIMEDOUT; 214 /* 215 * Firmware did its job, either notification or reply 216 * has been received - now wait until it's processed. 217 */ 218 wait_for_completion_killable(&ipc->busy_completion); 219 } 220 221 /* Ongoing notification's bottom-half may cause early wakeup */ 222 spin_lock(&ipc->rx_lock); 223 if (!ipc->rx_completed) { 224 if (repeats_left) { 225 /* Reply delayed due to notification. */ 226 repeats_left--; 227 reinit_completion(&ipc->busy_completion); 228 spin_unlock(&ipc->rx_lock); 229 goto again; 230 } 231 232 spin_unlock(&ipc->rx_lock); 233 return -ETIMEDOUT; 234 } 235 236 spin_unlock(&ipc->rx_lock); 237 return 0; 238 } 239 240 static void avs_ipc_msg_init(struct avs_ipc *ipc, struct avs_ipc_msg *reply) 241 { 242 lockdep_assert_held(&ipc->rx_lock); 243 244 ipc->rx.header = 0; 245 ipc->rx.size = reply ? reply->size : 0; 246 ipc->rx_completed = false; 247 248 reinit_completion(&ipc->done_completion); 249 reinit_completion(&ipc->busy_completion); 250 } 251 252 static void avs_dsp_send_tx(struct avs_dev *adev, struct avs_ipc_msg *tx) 253 { 254 tx->header |= SKL_ADSP_HIPCI_BUSY; 255 256 if (tx->size) 257 memcpy_toio(avs_downlink_addr(adev), tx->data, tx->size); 258 snd_hdac_adsp_writel(adev, SKL_ADSP_REG_HIPCIE, tx->header >> 32); 259 snd_hdac_adsp_writel(adev, SKL_ADSP_REG_HIPCI, tx->header & UINT_MAX); 260 } 261 262 static int avs_dsp_do_send_msg(struct avs_dev *adev, struct avs_ipc_msg *request, 263 struct avs_ipc_msg *reply, int timeout) 264 { 265 struct avs_ipc *ipc = adev->ipc; 266 int ret; 267 268 if (!ipc->ready) 269 return -EPERM; 270 271 mutex_lock(&ipc->msg_mutex); 272 273 spin_lock(&ipc->rx_lock); 274 avs_ipc_msg_init(ipc, reply); 275 avs_dsp_send_tx(adev, request); 276 spin_unlock(&ipc->rx_lock); 277 278 ret = avs_ipc_wait_busy_completion(ipc, timeout); 279 if (ret) { 280 if (ret == -ETIMEDOUT) { 281 dev_crit(adev->dev, "communication severed: %d, rebooting dsp..\n", ret); 282 283 avs_ipc_block(ipc); 284 } 285 goto exit; 286 } 287 288 ret = ipc->rx.rsp.status; 289 if (reply) { 290 reply->header = ipc->rx.header; 291 if (reply->data && ipc->rx.size) 292 memcpy(reply->data, ipc->rx.data, reply->size); 293 } 294 295 exit: 296 mutex_unlock(&ipc->msg_mutex); 297 return ret; 298 } 299 300 int avs_dsp_send_msg_timeout(struct avs_dev *adev, struct avs_ipc_msg *request, 301 struct avs_ipc_msg *reply, int timeout) 302 { 303 return avs_dsp_do_send_msg(adev, request, reply, timeout); 304 } 305 306 int avs_dsp_send_msg(struct avs_dev *adev, struct avs_ipc_msg *request, 307 struct avs_ipc_msg *reply) 308 { 309 return avs_dsp_send_msg_timeout(adev, request, reply, adev->ipc->default_timeout_ms); 310 } 311 312 static int avs_dsp_do_send_rom_msg(struct avs_dev *adev, struct avs_ipc_msg *request, int timeout) 313 { 314 struct avs_ipc *ipc = adev->ipc; 315 int ret; 316 317 mutex_lock(&ipc->msg_mutex); 318 319 spin_lock(&ipc->rx_lock); 320 avs_ipc_msg_init(ipc, NULL); 321 avs_dsp_send_tx(adev, request); 322 spin_unlock(&ipc->rx_lock); 323 324 /* ROM messages must be sent before main core is unstalled */ 325 ret = avs_dsp_op(adev, stall, AVS_MAIN_CORE_MASK, false); 326 if (!ret) { 327 ret = wait_for_completion_timeout(&ipc->done_completion, msecs_to_jiffies(timeout)); 328 ret = ret ? 0 : -ETIMEDOUT; 329 } 330 331 mutex_unlock(&ipc->msg_mutex); 332 333 return ret; 334 } 335 336 int avs_dsp_send_rom_msg_timeout(struct avs_dev *adev, struct avs_ipc_msg *request, int timeout) 337 { 338 return avs_dsp_do_send_rom_msg(adev, request, timeout); 339 } 340 341 int avs_dsp_send_rom_msg(struct avs_dev *adev, struct avs_ipc_msg *request) 342 { 343 return avs_dsp_send_rom_msg_timeout(adev, request, adev->ipc->default_timeout_ms); 344 } 345 346 void avs_dsp_interrupt_control(struct avs_dev *adev, bool enable) 347 { 348 u32 value, mask; 349 350 /* 351 * No particular bit setting order. All of these are required 352 * to have a functional SW <-> FW communication. 353 */ 354 value = enable ? AVS_ADSP_ADSPIC_IPC : 0; 355 snd_hdac_adsp_updatel(adev, AVS_ADSP_REG_ADSPIC, AVS_ADSP_ADSPIC_IPC, value); 356 357 mask = AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY; 358 value = enable ? mask : 0; 359 snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL, mask, value); 360 } 361 362 int avs_ipc_init(struct avs_ipc *ipc, struct device *dev) 363 { 364 ipc->rx.data = devm_kzalloc(dev, AVS_MAILBOX_SIZE, GFP_KERNEL); 365 if (!ipc->rx.data) 366 return -ENOMEM; 367 368 ipc->dev = dev; 369 ipc->ready = false; 370 ipc->default_timeout_ms = AVS_IPC_TIMEOUT_MS; 371 init_completion(&ipc->done_completion); 372 init_completion(&ipc->busy_completion); 373 spin_lock_init(&ipc->rx_lock); 374 mutex_init(&ipc->msg_mutex); 375 376 return 0; 377 } 378 379 void avs_ipc_block(struct avs_ipc *ipc) 380 { 381 ipc->ready = false; 382 } 383