dmaengine: tegra-apb: Really fix runtime-pm usage
authorJon Hunter <jonathanh@nvidia.com>
Tue, 6 Jun 2017 12:49:29 +0000 (13:49 +0100)
committerVinod Koul <vinod.koul@intel.com>
Fri, 30 Jun 2017 05:43:44 +0000 (11:13 +0530)
Commit edd3bdbe9db1 ("dmaengine: tegra-apb: Correct runtime-pm usage")
added pm_runtime_get/put() calls to the tegra-apb DMA system suspend
callbacks. Runtime PM is disabled during system suspend and so these
APIs cannot be used. Fix the suspend handling for the tegra-apb DMA by
moving the save and restore of the DMA register context into the
runtime PM suspend and resume callbacks, and then use the
pm_runtime_force_suspend/resume() APIs to invoke the runtime PM
callbacks during system suspend.

Fixes: edd3bdbe9db1 ("dmaengine: tegra-apb: Correct runtime-pm usage")
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
drivers/dma/tegra20-apb-dma.c

index 3722b9d8d9fe203124ead98c5fc823da84d4bf84..b9d75a54c896a5d3d7d141d571c395acef2962ff 100644 (file)
@@ -1492,37 +1492,9 @@ static int tegra_dma_remove(struct platform_device *pdev)
 }
 
 static int tegra_dma_runtime_suspend(struct device *dev)
-{
-       struct tegra_dma *tdma = dev_get_drvdata(dev);
-
-       clk_disable_unprepare(tdma->dma_clk);
-       return 0;
-}
-
-static int tegra_dma_runtime_resume(struct device *dev)
-{
-       struct tegra_dma *tdma = dev_get_drvdata(dev);
-       int ret;
-
-       ret = clk_prepare_enable(tdma->dma_clk);
-       if (ret < 0) {
-               dev_err(dev, "clk_enable failed: %d\n", ret);
-               return ret;
-       }
-       return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int tegra_dma_pm_suspend(struct device *dev)
 {
        struct tegra_dma *tdma = dev_get_drvdata(dev);
        int i;
-       int ret;
-
-       /* Enable clock before accessing register */
-       ret = pm_runtime_get_sync(dev);
-       if (ret < 0)
-               return ret;
 
        tdma->reg_gen = tdma_read(tdma, TEGRA_APBDMA_GENERAL);
        for (i = 0; i < tdma->chip_data->nr_channels; i++) {
@@ -1543,21 +1515,21 @@ static int tegra_dma_pm_suspend(struct device *dev)
                                                  TEGRA_APBDMA_CHAN_WCOUNT);
        }
 
-       /* Disable clock */
-       pm_runtime_put(dev);
+       clk_disable_unprepare(tdma->dma_clk);
+
        return 0;
 }
 
-static int tegra_dma_pm_resume(struct device *dev)
+static int tegra_dma_runtime_resume(struct device *dev)
 {
        struct tegra_dma *tdma = dev_get_drvdata(dev);
-       int i;
-       int ret;
+       int i, ret;
 
-       /* Enable clock before accessing register */
-       ret = pm_runtime_get_sync(dev);
-       if (ret < 0)
+       ret = clk_prepare_enable(tdma->dma_clk);
+       if (ret < 0) {
+               dev_err(dev, "clk_enable failed: %d\n", ret);
                return ret;
+       }
 
        tdma_write(tdma, TEGRA_APBDMA_GENERAL, tdma->reg_gen);
        tdma_write(tdma, TEGRA_APBDMA_CONTROL, 0);
@@ -1582,16 +1554,14 @@ static int tegra_dma_pm_resume(struct device *dev)
                        (ch_reg->csr & ~TEGRA_APBDMA_CSR_ENB));
        }
 
-       /* Disable clock */
-       pm_runtime_put(dev);
        return 0;
 }
-#endif
 
 static const struct dev_pm_ops tegra_dma_dev_pm_ops = {
        SET_RUNTIME_PM_OPS(tegra_dma_runtime_suspend, tegra_dma_runtime_resume,
                           NULL)
-       SET_SYSTEM_SLEEP_PM_OPS(tegra_dma_pm_suspend, tegra_dma_pm_resume)
+       SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+                               pm_runtime_force_resume)
 };
 
 static const struct of_device_id tegra_dma_of_match[] = {