diff --git a/sound/soc/sof/amd/acp-dsp-offset.h b/sound/soc/sof/amd/acp-dsp-offset.h index 63f13c111b241..40fbf11facba5 100644 --- a/sound/soc/sof/amd/acp-dsp-offset.h +++ b/sound/soc/sof/amd/acp-dsp-offset.h @@ -61,6 +61,7 @@ #define ACP_DSP_SW_INTR_STAT 0x1818 #define ACP_SW_INTR_TRIG 0x181C #define ACP_ERROR_STATUS 0x18C4 +#define ACP_AXI2DAGB_SEM_0 0x1880 /* Registers from ACP_SHA block */ #define ACP_SHA_DSP_FW_QUALIFIER 0x1C70 diff --git a/sound/soc/sof/amd/acp-ipc.c b/sound/soc/sof/amd/acp-ipc.c index cd5af3d850023..9fcd2535fd3b1 100644 --- a/sound/soc/sof/amd/acp-ipc.c +++ b/sound/soc/sof/amd/acp-ipc.c @@ -62,12 +62,26 @@ int acp_sof_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) { struct acp_dev_data *adata = sdev->pdata->hw_pdata; unsigned int offset = offsetof(struct scratch_ipc_conf, sof_in_box); + unsigned int count = ACP_HW_SEM_RETRY_COUNT; + + while (snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_AXI2DAGB_SEM_0)) { + /* Wait until acquired HW Semaphore Lock or timeout*/ + count--; + if (!count) { + dev_err(sdev->dev, "%s: Failed to acquire HW lock\n", __func__); + return -EINVAL; + } + }; acp_mailbox_write(sdev, offset, msg->msg_data, msg->msg_size); acp_ipc_host_msg_set(sdev); /* Trigger host to dsp interrupt for the msg */ acpbus_trigger_host_to_dsp_swintr(adata); + + /* Unlock or Release HW Semaphore */ + snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_AXI2DAGB_SEM_0, 0x0); + return 0; } EXPORT_SYMBOL_NS(acp_sof_ipc_send_msg, SND_SOC_SOF_AMD_COMMON); diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c index fe9b7dc5bc866..ba8b6427b59f1 100644 --- a/sound/soc/sof/amd/acp.c +++ b/sound/soc/sof/amd/acp.c @@ -273,7 +273,7 @@ static int acp_memory_init(struct snd_sof_dev *sdev) static irqreturn_t acp_irq_thread(int irq, void *context) { struct snd_sof_dev *sdev = context; - unsigned int val; + unsigned int val, count = ACP_HW_SEM_RETRY_COUNT; val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_EXTERNAL_INTR_STAT); if (val & ACP_SHA_STAT) { @@ -284,9 +284,22 @@ static irqreturn_t acp_irq_thread(int irq, void *context) val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_DSP_SW_INTR_STAT); if (val & ACP_DSP_TO_HOST_IRQ) { + while (snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_AXI2DAGB_SEM_0)) { + /* Wait until acquired HW Semaphore lock or timeout */ + count--; + if (!count) { + dev_err(sdev->dev, "%s: Failed to acquire HW lock\n", __func__); + return IRQ_NONE; + } + }; + sof_ops(sdev)->irq_thread(irq, sdev); val |= ACP_DSP_TO_HOST_IRQ; snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_DSP_SW_INTR_STAT, val); + + /* Unlock or Release HW Semaphore */ + snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_AXI2DAGB_SEM_0, 0x0); + return IRQ_HANDLED; } diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h index 8ed4e338467f7..db1030d36811d 100644 --- a/sound/soc/sof/amd/acp.h +++ b/sound/soc/sof/amd/acp.h @@ -17,6 +17,7 @@ #define ACP_DSP_BAR 0 +#define ACP_HW_SEM_RETRY_COUNT 10 #define ACP_REG_POLL_INTERVAL 500 #define ACP_REG_POLL_TIMEOUT_US 2000 #define ACP_DMA_COMPLETE_TIMEOUT_US 5000