MLK-11689: dma: imx-sdma: correct channel context restore
authorRobin Gong <b38343@freescale.com>
Mon, 12 Oct 2015 04:46:14 +0000 (12:46 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:21:37 +0000 (15:21 -0500)
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)
(cherry picked from commit 70dbe82f8fb504497ab5d544ce0c30cfca15c515)

drivers/dma/imx-sdma.c

index 166cff3..1ebe622 100644 (file)
@@ -421,6 +421,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 = {
@@ -1301,6 +1302,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;
@@ -2348,6 +2359,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
            && sdma->drvdata != &sdma_imx6ul)
@@ -2400,6 +2413,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++) {
                /*