Commit 65a5c3dd authored by Jon Hunter's avatar Jon Hunter Committed by Vinod Koul

dmaengine: tegra-apb: Really fix runtime-pm usage

Commit edd3bdbe ("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: edd3bdbe ("dmaengine: tegra-apb: Correct runtime-pm usage")
Signed-off-by: default avatarJon Hunter <jonathanh@nvidia.com>
Signed-off-by: default avatarVinod Koul <vinod.koul@intel.com>
parent 5f54d3e8
...@@ -1492,37 +1492,9 @@ static int tegra_dma_remove(struct platform_device *pdev) ...@@ -1492,37 +1492,9 @@ static int tegra_dma_remove(struct platform_device *pdev)
} }
static int tegra_dma_runtime_suspend(struct device *dev) 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); struct tegra_dma *tdma = dev_get_drvdata(dev);
int i; 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); tdma->reg_gen = tdma_read(tdma, TEGRA_APBDMA_GENERAL);
for (i = 0; i < tdma->chip_data->nr_channels; i++) { for (i = 0; i < tdma->chip_data->nr_channels; i++) {
...@@ -1543,21 +1515,21 @@ static int tegra_dma_pm_suspend(struct device *dev) ...@@ -1543,21 +1515,21 @@ static int tegra_dma_pm_suspend(struct device *dev)
TEGRA_APBDMA_CHAN_WCOUNT); TEGRA_APBDMA_CHAN_WCOUNT);
} }
/* Disable clock */ clk_disable_unprepare(tdma->dma_clk);
pm_runtime_put(dev);
return 0; 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); struct tegra_dma *tdma = dev_get_drvdata(dev);
int i; int i, ret;
int ret;
/* Enable clock before accessing register */ ret = clk_prepare_enable(tdma->dma_clk);
ret = pm_runtime_get_sync(dev); if (ret < 0) {
if (ret < 0) dev_err(dev, "clk_enable failed: %d\n", ret);
return ret; return ret;
}
tdma_write(tdma, TEGRA_APBDMA_GENERAL, tdma->reg_gen); tdma_write(tdma, TEGRA_APBDMA_GENERAL, tdma->reg_gen);
tdma_write(tdma, TEGRA_APBDMA_CONTROL, 0); tdma_write(tdma, TEGRA_APBDMA_CONTROL, 0);
...@@ -1582,16 +1554,14 @@ static int tegra_dma_pm_resume(struct device *dev) ...@@ -1582,16 +1554,14 @@ static int tegra_dma_pm_resume(struct device *dev)
(ch_reg->csr & ~TEGRA_APBDMA_CSR_ENB)); (ch_reg->csr & ~TEGRA_APBDMA_CSR_ENB));
} }
/* Disable clock */
pm_runtime_put(dev);
return 0; return 0;
} }
#endif
static const struct dev_pm_ops tegra_dma_dev_pm_ops = { static const struct dev_pm_ops tegra_dma_dev_pm_ops = {
SET_RUNTIME_PM_OPS(tegra_dma_runtime_suspend, tegra_dma_runtime_resume, SET_RUNTIME_PM_OPS(tegra_dma_runtime_suspend, tegra_dma_runtime_resume,
NULL) 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[] = { static const struct of_device_id tegra_dma_of_match[] = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment