[PATCH v2 1/2] dma: img-mdc: Add suspend / resume handling

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add suspend / resume handling using suspend_late and resume_early, and
check that all channels are idle before suspending.

DMA drivers should use suspend_late / resume_early to ensure that all
DMA client devices are suspended before the DMA device itself, and that
client devices are resumed after the DMA device. This avoids suspending
the DMA device while transactions are still active.

It is the responsibility of client drivers to terminate all DMA
transactions in their suspend handlers, so there should be no active
transactions by the time suspend_late is called.

There's no need to save and restore registers for MDC during suspend /
resume, as all transactions will be terminated as a result of the
suspend, and all required registers are programmed anyway at the start
of any new transactions following resume.

Signed-off-by: Ed Blake <ed.blake@xxxxxxxxxxx>
---
Changes in v2:
 - The resume_early function was modified to directly return the result
   of clk_prepare_enable.
---
 drivers/dma/img-mdc-dma.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/drivers/dma/img-mdc-dma.c b/drivers/dma/img-mdc-dma.c
index 54db1411ce73..c4d8d5ad2876 100644
--- a/drivers/dma/img-mdc-dma.c
+++ b/drivers/dma/img-mdc-dma.c
@@ -1009,9 +1009,42 @@ static int mdc_dma_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int img_mdc_suspend_late(struct device *dev)
+{
+	struct mdc_dma *mdma = dev_get_drvdata(dev);
+	int i;
+
+	/* Check that all channels are idle */
+	for (i = 0; i < mdma->nr_channels; i++) {
+		struct mdc_chan *mchan = &mdma->channels[i];
+
+		if (unlikely(mchan->desc))
+			return -EBUSY;
+	}
+
+	clk_disable_unprepare(mdma->clk);
+
+	return 0;
+}
+
+static int img_mdc_resume_early(struct device *dev)
+{
+	struct mdc_dma *mdma = dev_get_drvdata(dev);
+
+	return clk_prepare_enable(mdma->clk);
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct dev_pm_ops img_mdc_pm_ops = {
+	SET_LATE_SYSTEM_SLEEP_PM_OPS(img_mdc_suspend_late,
+				     img_mdc_resume_early)
+};
+
 static struct platform_driver mdc_dma_driver = {
 	.driver = {
 		.name = "img-mdc-dma",
+		.pm = &img_mdc_pm_ops,
 		.of_match_table = of_match_ptr(mdc_dma_of_match),
 	},
 	.probe = mdc_dma_probe,
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe dmaengine" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux PCI]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux