summaryrefslogtreecommitdiff
path: root/drivers/dma
diff options
context:
space:
mode:
authorRobin Gong <b38343@freescale.com>2015-10-12 12:46:14 +0800
committerNitin Garg <nitin.garg@nxp.com>2016-01-14 11:01:53 -0600
commit70dbe82f8fb504497ab5d544ce0c30cfca15c515 (patch)
treefab6b6894c1340f5ab7c75f7ce3de36066ccc47d /drivers/dma
parentb7dfd1158ff2dff21f483d8f678379cc50dc46e0 (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.c16
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++) {
/*