1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 2 // 3 // This file is provided under a dual BSD/GPLv2 license. When using or 4 // redistributing this file, you may do so under either license. 5 // 6 // Copyright(c) 2018 Intel Corporation. All rights reserved. 7 // 8 // Authors: Liam Girdwood <liam.r.girdwood@linux.intel.com> 9 // Ranjani Sridharan <ranjani.sridharan@linux.intel.com> 10 // Rander Wang <rander.wang@intel.com> 11 // Keyon Jie <yang.jie@linux.intel.com> 12 // 13 14 /* 15 * Hardware interface for generic Intel audio DSP HDA IP 16 */ 17 18 #include <sound/sof/ipc4/header.h> 19 #include <trace/events/sof_intel.h> 20 #include "../ops.h" 21 #include "hda.h" 22 23 static void hda_dsp_ipc_host_done(struct snd_sof_dev *sdev) 24 { 25 /* 26 * tell DSP cmd is done - clear busy 27 * interrupt and send reply msg to dsp 28 */ 29 snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, 30 HDA_DSP_REG_HIPCT, 31 HDA_DSP_REG_HIPCT_BUSY, 32 HDA_DSP_REG_HIPCT_BUSY); 33 34 /* unmask BUSY interrupt */ 35 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, 36 HDA_DSP_REG_HIPCCTL, 37 HDA_DSP_REG_HIPCCTL_BUSY, 38 HDA_DSP_REG_HIPCCTL_BUSY); 39 } 40 41 static void hda_dsp_ipc_dsp_done(struct snd_sof_dev *sdev) 42 { 43 /* 44 * set DONE bit - tell DSP we have received the reply msg 45 * from DSP, and processed it, don't send more reply to host 46 */ 47 snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, 48 HDA_DSP_REG_HIPCIE, 49 HDA_DSP_REG_HIPCIE_DONE, 50 HDA_DSP_REG_HIPCIE_DONE); 51 52 /* unmask Done interrupt */ 53 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, 54 HDA_DSP_REG_HIPCCTL, 55 HDA_DSP_REG_HIPCCTL_DONE, 56 HDA_DSP_REG_HIPCCTL_DONE); 57 } 58 59 int hda_dsp_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) 60 { 61 /* send IPC message to DSP */ 62 sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, 63 msg->msg_size); 64 snd_sof_dsp_write(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCI, 65 HDA_DSP_REG_HIPCI_BUSY); 66 67 return 0; 68 } 69 70 int hda_dsp_ipc4_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) 71 { 72 struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; 73 struct sof_ipc4_msg *msg_data = msg->msg_data; 74 75 if (hda_ipc4_tx_is_busy(sdev)) { 76 hdev->delayed_ipc_tx_msg = msg; 77 return 0; 78 } 79 80 hdev->delayed_ipc_tx_msg = NULL; 81 82 /* send the message via mailbox */ 83 if (msg_data->data_size) 84 sof_mailbox_write(sdev, sdev->host_box.offset, msg_data->data_ptr, 85 msg_data->data_size); 86 87 snd_sof_dsp_write(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCIE, msg_data->extension); 88 snd_sof_dsp_write(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCI, 89 msg_data->primary | HDA_DSP_REG_HIPCI_BUSY); 90 91 return 0; 92 } 93 94 void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev) 95 { 96 struct snd_sof_ipc_msg *msg = sdev->msg; 97 struct sof_ipc_reply reply; 98 struct sof_ipc_cmd_hdr *hdr; 99 100 /* 101 * Sometimes, there is unexpected reply ipc arriving. The reply 102 * ipc belongs to none of the ipcs sent from driver. 103 * In this case, the driver must ignore the ipc. 104 */ 105 if (!msg) { 106 dev_warn(sdev->dev, "unexpected ipc interrupt raised!\n"); 107 return; 108 } 109 110 hdr = msg->msg_data; 111 if (hdr->cmd == (SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_CTX_SAVE) || 112 hdr->cmd == (SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_GATE)) { 113 /* 114 * memory windows are powered off before sending IPC reply, 115 * so we can't read the mailbox for CTX_SAVE and PM_GATE 116 * replies. 117 */ 118 reply.error = 0; 119 reply.hdr.cmd = SOF_IPC_GLB_REPLY; 120 reply.hdr.size = sizeof(reply); 121 memcpy(msg->reply_data, &reply, sizeof(reply)); 122 123 msg->reply_error = 0; 124 } else { 125 snd_sof_ipc_get_reply(sdev); 126 } 127 } 128 129 irqreturn_t hda_dsp_ipc4_irq_thread(int irq, void *context) 130 { 131 struct sof_ipc4_msg notification_data = {{ 0 }}; 132 struct snd_sof_dev *sdev = context; 133 bool ack_received = false; 134 bool ipc_irq = false; 135 u32 hipcie, hipct; 136 137 hipcie = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCIE); 138 hipct = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCT); 139 140 if (hipcie & HDA_DSP_REG_HIPCIE_DONE) { 141 /* DSP received the message */ 142 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCCTL, 143 HDA_DSP_REG_HIPCCTL_DONE, 0); 144 hda_dsp_ipc_dsp_done(sdev); 145 146 ipc_irq = true; 147 ack_received = true; 148 } 149 150 if (hipct & HDA_DSP_REG_HIPCT_BUSY) { 151 /* Message from DSP (reply or notification) */ 152 u32 hipcte = snd_sof_dsp_read(sdev, HDA_DSP_BAR, 153 HDA_DSP_REG_HIPCTE); 154 u32 primary = hipct & HDA_DSP_REG_HIPCT_MSG_MASK; 155 u32 extension = hipcte & HDA_DSP_REG_HIPCTE_MSG_MASK; 156 157 /* mask BUSY interrupt */ 158 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCCTL, 159 HDA_DSP_REG_HIPCCTL_BUSY, 0); 160 161 if (primary & SOF_IPC4_MSG_DIR_MASK) { 162 /* Reply received */ 163 if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) { 164 struct sof_ipc4_msg *data = sdev->ipc->msg.reply_data; 165 166 data->primary = primary; 167 data->extension = extension; 168 169 spin_lock_irq(&sdev->ipc_lock); 170 171 snd_sof_ipc_get_reply(sdev); 172 hda_dsp_ipc_host_done(sdev); 173 snd_sof_ipc_reply(sdev, data->primary); 174 175 spin_unlock_irq(&sdev->ipc_lock); 176 } else { 177 dev_dbg_ratelimited(sdev->dev, 178 "IPC reply before FW_READY: %#x|%#x\n", 179 primary, extension); 180 } 181 } else { 182 /* Notification received */ 183 184 notification_data.primary = primary; 185 notification_data.extension = extension; 186 sdev->ipc->msg.rx_data = ¬ification_data; 187 snd_sof_ipc_msgs_rx(sdev); 188 sdev->ipc->msg.rx_data = NULL; 189 190 /* Let DSP know that we have finished processing the message */ 191 hda_dsp_ipc_host_done(sdev); 192 } 193 194 ipc_irq = true; 195 } 196 197 if (!ipc_irq) 198 /* This interrupt is not shared so no need to return IRQ_NONE. */ 199 dev_dbg_ratelimited(sdev->dev, "nothing to do in IPC IRQ thread\n"); 200 201 if (ack_received) { 202 struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; 203 204 if (hdev->delayed_ipc_tx_msg) 205 hda_dsp_ipc4_send_msg(sdev, hdev->delayed_ipc_tx_msg); 206 } 207 208 return IRQ_HANDLED; 209 } 210 211 /* IPC handler thread */ 212 irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) 213 { 214 struct snd_sof_dev *sdev = context; 215 u32 hipci; 216 u32 hipcie; 217 u32 hipct; 218 u32 hipcte; 219 u32 msg; 220 u32 msg_ext; 221 bool ipc_irq = false; 222 223 /* read IPC status */ 224 hipcie = snd_sof_dsp_read(sdev, HDA_DSP_BAR, 225 HDA_DSP_REG_HIPCIE); 226 hipct = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCT); 227 hipci = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCI); 228 hipcte = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCTE); 229 230 /* is this a reply message from the DSP */ 231 if (hipcie & HDA_DSP_REG_HIPCIE_DONE) { 232 msg = hipci & HDA_DSP_REG_HIPCI_MSG_MASK; 233 msg_ext = hipcie & HDA_DSP_REG_HIPCIE_MSG_MASK; 234 235 trace_sof_intel_ipc_firmware_response(sdev, msg, msg_ext); 236 237 /* mask Done interrupt */ 238 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, 239 HDA_DSP_REG_HIPCCTL, 240 HDA_DSP_REG_HIPCCTL_DONE, 0); 241 242 /* 243 * Make sure the interrupt thread cannot be preempted between 244 * waking up the sender and re-enabling the interrupt. Also 245 * protect against a theoretical race with sof_ipc_tx_message(): 246 * if the DSP is fast enough to receive an IPC message, reply to 247 * it, and the host interrupt processing calls this function on 248 * a different core from the one, where the sending is taking 249 * place, the message might not yet be marked as expecting a 250 * reply. 251 */ 252 if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) { 253 spin_lock_irq(&sdev->ipc_lock); 254 255 /* handle immediate reply from DSP core */ 256 hda_dsp_ipc_get_reply(sdev); 257 snd_sof_ipc_reply(sdev, msg); 258 259 /* set the done bit */ 260 hda_dsp_ipc_dsp_done(sdev); 261 262 spin_unlock_irq(&sdev->ipc_lock); 263 } else { 264 dev_dbg_ratelimited(sdev->dev, "IPC reply before FW_READY: %#x\n", 265 msg); 266 } 267 268 ipc_irq = true; 269 } 270 271 /* is this a new message from DSP */ 272 if (hipct & HDA_DSP_REG_HIPCT_BUSY) { 273 msg = hipct & HDA_DSP_REG_HIPCT_MSG_MASK; 274 msg_ext = hipcte & HDA_DSP_REG_HIPCTE_MSG_MASK; 275 276 trace_sof_intel_ipc_firmware_initiated(sdev, msg, msg_ext); 277 278 /* mask BUSY interrupt */ 279 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, 280 HDA_DSP_REG_HIPCCTL, 281 HDA_DSP_REG_HIPCCTL_BUSY, 0); 282 283 /* handle messages from DSP */ 284 if ((hipct & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) { 285 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; 286 bool non_recoverable = true; 287 288 /* 289 * This is a PANIC message! 290 * 291 * If it is arriving during firmware boot and it is not 292 * the last boot attempt then change the non_recoverable 293 * to false as the DSP might be able to boot in the next 294 * iteration(s) 295 */ 296 if (sdev->fw_state == SOF_FW_BOOT_IN_PROGRESS && 297 hda->boot_iteration < HDA_FW_BOOT_ATTEMPTS) 298 non_recoverable = false; 299 300 snd_sof_dsp_panic(sdev, HDA_DSP_PANIC_OFFSET(msg_ext), 301 non_recoverable); 302 } else { 303 /* normal message - process normally */ 304 snd_sof_ipc_msgs_rx(sdev); 305 } 306 307 hda_dsp_ipc_host_done(sdev); 308 309 ipc_irq = true; 310 } 311 312 if (!ipc_irq) { 313 /* 314 * This interrupt is not shared so no need to return IRQ_NONE. 315 */ 316 dev_dbg_ratelimited(sdev->dev, 317 "nothing to do in IPC IRQ thread\n"); 318 } 319 320 return IRQ_HANDLED; 321 } 322 323 /* Check if an IPC IRQ occurred */ 324 bool hda_dsp_check_ipc_irq(struct snd_sof_dev *sdev) 325 { 326 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; 327 bool ret = false; 328 u32 irq_status; 329 330 /* store status */ 331 irq_status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIS); 332 trace_sof_intel_hda_irq_ipc_check(sdev, irq_status); 333 334 /* invalid message ? */ 335 if (irq_status == 0xffffffff) 336 goto out; 337 338 /* IPC message ? */ 339 if (irq_status & HDA_DSP_ADSPIS_IPC) 340 ret = true; 341 342 /* CLDMA message ? */ 343 if (irq_status & HDA_DSP_ADSPIS_CL_DMA) { 344 hda->code_loading = 0; 345 wake_up(&hda->waitq); 346 ret = false; 347 } 348 349 out: 350 return ret; 351 } 352 353 int hda_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev) 354 { 355 return HDA_DSP_MBOX_UPLINK_OFFSET; 356 } 357 358 int hda_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id) 359 { 360 return SRAM_WINDOW_OFFSET(id); 361 } 362 363 int hda_ipc_msg_data(struct snd_sof_dev *sdev, 364 struct snd_pcm_substream *substream, 365 void *p, size_t sz) 366 { 367 if (!substream || !sdev->stream_box.size) { 368 sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz); 369 } else { 370 struct hdac_stream *hstream = substream->runtime->private_data; 371 struct sof_intel_hda_stream *hda_stream; 372 373 hda_stream = container_of(hstream, 374 struct sof_intel_hda_stream, 375 hext_stream.hstream); 376 377 /* The stream might already be closed */ 378 if (!hstream) 379 return -ESTRPIPE; 380 381 sof_mailbox_read(sdev, hda_stream->sof_intel_stream.posn_offset, p, sz); 382 } 383 384 return 0; 385 } 386 387 int hda_set_stream_data_offset(struct snd_sof_dev *sdev, 388 struct snd_pcm_substream *substream, 389 size_t posn_offset) 390 { 391 struct hdac_stream *hstream = substream->runtime->private_data; 392 struct sof_intel_hda_stream *hda_stream; 393 394 hda_stream = container_of(hstream, struct sof_intel_hda_stream, 395 hext_stream.hstream); 396 397 /* check for unaligned offset or overflow */ 398 if (posn_offset > sdev->stream_box.size || 399 posn_offset % sizeof(struct sof_ipc_stream_posn) != 0) 400 return -EINVAL; 401 402 hda_stream->sof_intel_stream.posn_offset = sdev->stream_box.offset + posn_offset; 403 404 dev_dbg(sdev->dev, "pcm: stream dir %d, posn mailbox offset is %zu", 405 substream->stream, hda_stream->sof_intel_stream.posn_offset); 406 407 return 0; 408 } 409