From 3edaea57a861661e9e4511dca4591e9768c941e2 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 18 Jun 2020 22:02:34 +0300 Subject: [PATCH] MLK-24263-8 ASoC: SOF: imx8m: Implement reset callback Resume common flow (System PM / Runtime PM) is like this: sof_resume -> specific device resume -> snd_sof_load_firmware -> snd_sof_dsp_reset (1) -> load_modules() -> snd_sof_run_firmware (2) We need to implement dsp_reset callback (1) that will actually reset the DSP but keep it stalled. In order to implement this we do the following: -> put DSP into reset (assert CoreReset bit from PWRCTL) -> stall the DSP using RunStall bit from AudioDSP_REG2 Audiomix -> take DSP out of reset (de-assert CoreReset bit from PWRCTL) At this moment the DSP is taken out of reset and Stalled! This means that we can load the firmware and then start the DSP (2). Until now we resetted the DSP by turning down the Audiomix PD. This doesn't work for Runtime PM if another IP is keeping Audiomix PD up. By introducing dsp_reset() we no longer rely on turning off the audiomix to reset the DSP. Signed-off-by: Daniel Baluta Reviewed-by: Shengjiu Wang --- sound/soc/sof/imx/imx8m.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/sound/soc/sof/imx/imx8m.c b/sound/soc/sof/imx/imx8m.c index 513cf7f2e78b..a081633ac376 100644 --- a/sound/soc/sof/imx/imx8m.c +++ b/sound/soc/sof/imx/imx8m.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "../ops.h" #include "../../fsl/fsl_dsp_audiomix.h" @@ -38,6 +39,11 @@ #define MBOX_OFFSET 0x800000 #define MBOX_SIZE 0x1000 +#define IMX8M_DAP_DEBUG 0x28800000 +#define IMX8M_DAP_DEBUG_SIZE (64 * 1024) +#define IMX8M_DAP_PWRCTL (0x4000 + 0x3020) +#define IMX8M_PWRCTL_CORERESET BIT(16) + #define IMX8M_DSP_CLK_NUM 5 static const char *imx8m_dsp_clks[IMX8M_DSP_CLK_NUM] = { "ocram", @@ -64,6 +70,7 @@ struct imx8m_priv { struct device_link **link; struct clk *clks[IMX8M_DSP_CLK_NUM]; + void __iomem *dap; }; int imx8m_dsp_configure_audmix(struct imx8m_priv *dsp_priv) @@ -176,6 +183,29 @@ static int imx8m_run(struct snd_sof_dev *sdev) return 0; } +static int imx8m_reset(struct snd_sof_dev *sdev) { + + struct imx8m_priv *dsp_priv = (struct imx8m_priv *)sdev->private; + u32 pwrctl; + + /* put DSP into reset and stall */ + pwrctl = readl(dsp_priv->dap + IMX8M_DAP_PWRCTL); + pwrctl |= IMX8M_PWRCTL_CORERESET; + writel(pwrctl, dsp_priv->dap + IMX8M_DAP_PWRCTL); + + /* keep reset asserted for 10 cycles */ + usleep_range(1, 2); + + imx_audiomix_dsp_stall(dsp_priv->audiomix); + + /* take the DSP out of reset and keep stalled for FW loading */ + pwrctl = readl(dsp_priv->dap + IMX8M_DAP_PWRCTL); + pwrctl &= ~IMX8M_PWRCTL_CORERESET; + writel(pwrctl, dsp_priv->dap + IMX8M_DAP_PWRCTL); + + return 0; +} + static int imx8m_probe(struct snd_sof_dev *sdev) { struct platform_device *pdev = @@ -271,6 +301,12 @@ done_pm: goto exit_pdev_unregister; } + priv->dap = devm_ioremap(sdev->dev, IMX8M_DAP_DEBUG, IMX8M_DAP_DEBUG_SIZE); + if (!priv->dap ) { + dev_err(sdev->dev, "error: failed to map DAP debug memory area"); + return -ENODEV; + } + sdev->bar[SOF_FW_BLK_TYPE_IRAM] = devm_ioremap(sdev->dev, base, size); if (!sdev->bar[SOF_FW_BLK_TYPE_IRAM]) { dev_err(sdev->dev, "failed to ioremap base 0x%x size 0x%x\n", @@ -441,6 +477,7 @@ struct snd_sof_dsp_ops sof_imx8m_ops = { .remove = imx8m_remove, /* DSP core boot */ .run = imx8m_run, + .reset = imx8m_reset, /* Block IO */ .block_read = sof_block_read,