diff options
author | Robin Gong <b38343@freescale.com> | 2015-10-12 12:46:14 +0800 |
---|---|---|
committer | Nitin Garg <nitin.garg@nxp.com> | 2016-01-14 11:01:53 -0600 |
commit | 70dbe82f8fb504497ab5d544ce0c30cfca15c515 (patch) | |
tree | fab6b6894c1340f5ab7c75f7ce3de36066ccc47d /drivers/dma | |
parent | b7dfd1158ff2dff21f483d8f678379cc50dc46e0 (diff) |
MLK-11689: dma: imx-sdma: correct channel context restore
Before, checking SDMA_H_C0PTR register to know whether sdma controller turned
off in DSM, if yes restore channel context back. Unfortunatly, this checking
is wrong, because SDMA_H_C0PTR has been initialized as non-zero value in
sdma_resume, which means channel context will never be restored back if mega/
fast off on i.mx6sx or i.mx7d. Using 'suspend_off' flag to keep this 'restore
needed' requirement.
Signed-off-by: Robin Gong <b38343@freescale.com>
(cherry picked from commit 565d4c45926a03029d7750a57f3e3f2404de7301)
Diffstat (limited to 'drivers/dma')
-rw-r--r-- | drivers/dma/imx-sdma.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 0a2761d72801..3d388f5c9c27 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -419,6 +419,7 @@ struct sdma_engine { dma_addr_t bd0_phys; bool bd0_iram; struct sdma_buffer_descriptor *bd0; + bool suspend_off; }; static struct sdma_driver_data sdma_imx31 = { @@ -1275,6 +1276,16 @@ static int sdma_channel_resume(struct dma_chan *chan) if (!(sdmac->flags & IMX_DMA_SG_LOOP)) return -EINVAL; + /* + * restore back context since context may loss if mega/fast OFF + */ + if (sdma->suspend_off) { + if (sdma_load_context(sdmac)) { + dev_err(sdmac->sdma->dev, "context load failed.\n"); + return -EINVAL; + } + } + sdma_enable_channel(sdmac->sdma, sdmac->channel); spin_lock_irqsave(&sdmac->vc.lock, flags); sdmac->status = DMA_IN_PROGRESS; @@ -2317,6 +2328,8 @@ static int sdma_suspend(struct device *dev) struct sdma_engine *sdma = platform_get_drvdata(pdev); int i, ret = 0; + sdma->suspend_off = false; + /* Do nothing if not i.MX6SX or i.MX7D*/ if (sdma->drvdata != &sdma_imx6sx && sdma->drvdata != &sdma_imx7d) return 0; @@ -2367,6 +2380,9 @@ static int sdma_resume(struct device *dev) clk_disable(sdma->clk_ahb); return 0; } + + sdma->suspend_off = true; + /* restore regs and load firmware */ for (i = 0; i < MXC_SDMA_SAVED_REG_NUM; i++) { /* |