Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+10 −40
Original line number Diff line number Diff line
@@ -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[] = {