forked from Minki/linux
dmaengine: tegra-apb: Really fix runtime-pm usage
Commitedd3bdbe9d
("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:edd3bdbe9d
("dmaengine: tegra-apb: Correct runtime-pm usage") Signed-off-by: Jon Hunter <jonathanh@nvidia.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
This commit is contained in:
parent
5f54d3e869
commit
65a5c3dd3e
@ -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[] = {
|
||||
|
Loading…
Reference in New Issue
Block a user