Commit 3d2e5c48 authored by Keyon Jie's avatar Keyon Jie Committed by Mark Brown

ASoC: SOF: Intel: BYT: harden IPC initialization and handling

On probe and reset, we should not touch the SHIM_IMRD register since
it is configured by firmware.

The driver only configures SHIM_IMRX with the BUSY interrupt enabled
by default and DONE interrupt disabled. When sending an IPC message,
the DONE interrupt is enabled until the DSP response is provided.

This sequence hardens the IPC communication and avoid
interrupt-related issues when adding/removing modules or during system
suspend-resume transitions.
Signed-off-by: default avatarKeyon Jie <yang.jie@linux.intel.com>
Signed-off-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Tested-by: default avatarEnric Balletbo i Serra <enric.balletbo@collabora.com>
Reviewed-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Link: https://lore.kernel.org/r/20200526203640.25980-9-pierre-louis.bossart@linux.intel.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 3d3d1fb9
...@@ -236,6 +236,10 @@ static irqreturn_t byt_irq_thread(int irq, void *context) ...@@ -236,6 +236,10 @@ static irqreturn_t byt_irq_thread(int irq, void *context)
static int byt_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) static int byt_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
{ {
/* unmask and prepare to receive Done interrupt */
snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX,
SHIM_IMRX_DONE, 0);
/* send the message */ /* send the message */
sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
msg->msg_size); msg->msg_size);
...@@ -301,7 +305,7 @@ static void byt_host_done(struct snd_sof_dev *sdev) ...@@ -301,7 +305,7 @@ static void byt_host_done(struct snd_sof_dev *sdev)
SHIM_BYT_IPCD_DONE, SHIM_BYT_IPCD_DONE,
SHIM_BYT_IPCD_DONE); SHIM_BYT_IPCD_DONE);
/* unmask busy interrupt */ /* unmask and prepare to receive next new message */
snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX, snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX,
SHIM_IMRX_BUSY, 0); SHIM_IMRX_BUSY, 0);
} }
...@@ -311,10 +315,6 @@ static void byt_dsp_done(struct snd_sof_dev *sdev) ...@@ -311,10 +315,6 @@ static void byt_dsp_done(struct snd_sof_dev *sdev)
/* clear DONE bit - tell DSP we have completed */ /* clear DONE bit - tell DSP we have completed */
snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IPCX, snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IPCX,
SHIM_BYT_IPCX_DONE, 0); SHIM_BYT_IPCX_DONE, 0);
/* unmask Done interrupt */
snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX,
SHIM_IMRX_DONE, 0);
} }
/* /*
...@@ -453,9 +453,10 @@ static int byt_suspend(struct snd_sof_dev *sdev, u32 target_state) ...@@ -453,9 +453,10 @@ static int byt_suspend(struct snd_sof_dev *sdev, u32 target_state)
static int byt_resume(struct snd_sof_dev *sdev) static int byt_resume(struct snd_sof_dev *sdev)
{ {
/* Enable Interrupt from both sides */ /* enable BUSY and disable DONE Interrupt by default */
snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0); snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX,
snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0); SHIM_IMRX_BUSY | SHIM_IMRX_DONE,
SHIM_IMRX_DONE);
return 0; return 0;
} }
...@@ -606,9 +607,10 @@ static int tangier_pci_probe(struct snd_sof_dev *sdev) ...@@ -606,9 +607,10 @@ static int tangier_pci_probe(struct snd_sof_dev *sdev)
return ret; return ret;
} }
/* enable Interrupt from both sides */ /* enable BUSY and disable DONE Interrupt by default */
snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0); snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX,
snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0); SHIM_IMRX_BUSY | SHIM_IMRX_DONE,
SHIM_IMRX_DONE);
/* set default mailbox offset for FW ready message */ /* set default mailbox offset for FW ready message */
sdev->dsp_box.offset = MBOX_OFFSET; sdev->dsp_box.offset = MBOX_OFFSET;
...@@ -808,9 +810,10 @@ static int byt_acpi_probe(struct snd_sof_dev *sdev) ...@@ -808,9 +810,10 @@ static int byt_acpi_probe(struct snd_sof_dev *sdev)
return ret; return ret;
} }
/* enable Interrupt from both sides */ /* enable BUSY and disable DONE Interrupt by default */
snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0); snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX,
snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0); SHIM_IMRX_BUSY | SHIM_IMRX_DONE,
SHIM_IMRX_DONE);
/* set default mailbox offset for FW ready message */ /* set default mailbox offset for FW ready message */
sdev->dsp_box.offset = MBOX_OFFSET; sdev->dsp_box.offset = MBOX_OFFSET;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment