From 3d2e5c480742b4a22534e72e2647b6c8c98a94a4 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Tue, 26 May 2020 15:36:40 -0500 Subject: 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: Keyon Jie Signed-off-by: Pierre-Louis Bossart Tested-by: Enric Balletbo i Serra Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200526203640.25980-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/byt.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index c6ac914ee56c..e6ba8382b1de 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -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) { + /* 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 */ sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, msg->msg_size); @@ -301,7 +305,7 @@ static void byt_host_done(struct snd_sof_dev *sdev) 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, SHIM_IMRX_BUSY, 0); } @@ -311,10 +315,6 @@ static void byt_dsp_done(struct snd_sof_dev *sdev) /* clear DONE bit - tell DSP we have completed */ snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IPCX, 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) static int byt_resume(struct snd_sof_dev *sdev) { - /* Enable Interrupt from both sides */ - snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0); - snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0); + /* enable BUSY and disable DONE Interrupt by default */ + snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, + SHIM_IMRX_BUSY | SHIM_IMRX_DONE, + SHIM_IMRX_DONE); return 0; } @@ -606,9 +607,10 @@ irq: return ret; } - /* enable Interrupt from both sides */ - snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0); - snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0); + /* enable BUSY and disable DONE Interrupt by default */ + snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, + SHIM_IMRX_BUSY | SHIM_IMRX_DONE, + SHIM_IMRX_DONE); /* set default mailbox offset for FW ready message */ sdev->dsp_box.offset = MBOX_OFFSET; @@ -808,9 +810,10 @@ irq: return ret; } - /* enable Interrupt from both sides */ - snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0); - snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0); + /* enable BUSY and disable DONE Interrupt by default */ + snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, + SHIM_IMRX_BUSY | SHIM_IMRX_DONE, + SHIM_IMRX_DONE); /* set default mailbox offset for FW ready message */ sdev->dsp_box.offset = MBOX_OFFSET; -- cgit v1.2.3