diff options
| author | Pierre-Yves MORDRET <pierre-yves.mordret@st.com> | 2019-01-03 05:17:10 -0500 |
|---|---|---|
| committer | Vinod Koul <vkoul@kernel.org> | 2019-01-06 23:22:24 -0500 |
| commit | 89e987e3b4d6b87b2b12c3bdfc90bfef16e68b4e (patch) | |
| tree | 241375db023bdce12e99b51d0050814d79394772 | |
| parent | 4f3ceca254e0fa75ccb9c716480f9b30e1f6c0e9 (diff) | |
dmaengine: stm32-mdma: Add PM Runtime support
Use pm_runtime engine for clock management purpose
Signed-off-by: Pierre-Yves MORDRET <pierre-yves.mordret@st.com>
Signed-off-by: Vinod Koul <vkoul@kernel.org>
| -rw-r--r-- | drivers/dma/stm32-mdma.c | 52 |
1 files changed, 46 insertions, 6 deletions
diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c index 485dea177704..4e0eede599a8 100644 --- a/drivers/dma/stm32-mdma.c +++ b/drivers/dma/stm32-mdma.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <linux/of_device.h> | 37 | #include <linux/of_device.h> |
| 38 | #include <linux/of_dma.h> | 38 | #include <linux/of_dma.h> |
| 39 | #include <linux/platform_device.h> | 39 | #include <linux/platform_device.h> |
| 40 | #include <linux/pm_runtime.h> | ||
| 40 | #include <linux/reset.h> | 41 | #include <linux/reset.h> |
| 41 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
| 42 | 43 | ||
| @@ -1456,15 +1457,13 @@ static int stm32_mdma_alloc_chan_resources(struct dma_chan *c) | |||
| 1456 | return -ENOMEM; | 1457 | return -ENOMEM; |
| 1457 | } | 1458 | } |
| 1458 | 1459 | ||
| 1459 | ret = clk_prepare_enable(dmadev->clk); | 1460 | ret = pm_runtime_get_sync(dmadev->ddev.dev); |
| 1460 | if (ret < 0) { | 1461 | if (ret < 0) |
| 1461 | dev_err(chan2dev(chan), "clk_prepare_enable failed: %d\n", ret); | ||
| 1462 | return ret; | 1462 | return ret; |
| 1463 | } | ||
| 1464 | 1463 | ||
| 1465 | ret = stm32_mdma_disable_chan(chan); | 1464 | ret = stm32_mdma_disable_chan(chan); |
| 1466 | if (ret < 0) | 1465 | if (ret < 0) |
| 1467 | clk_disable_unprepare(dmadev->clk); | 1466 | pm_runtime_put(dmadev->ddev.dev); |
| 1468 | 1467 | ||
| 1469 | return ret; | 1468 | return ret; |
| 1470 | } | 1469 | } |
| @@ -1484,7 +1483,7 @@ static void stm32_mdma_free_chan_resources(struct dma_chan *c) | |||
| 1484 | spin_unlock_irqrestore(&chan->vchan.lock, flags); | 1483 | spin_unlock_irqrestore(&chan->vchan.lock, flags); |
| 1485 | } | 1484 | } |
| 1486 | 1485 | ||
| 1487 | clk_disable_unprepare(dmadev->clk); | 1486 | pm_runtime_put(dmadev->ddev.dev); |
| 1488 | vchan_free_chan_resources(to_virt_chan(c)); | 1487 | vchan_free_chan_resources(to_virt_chan(c)); |
| 1489 | dmam_pool_destroy(chan->desc_pool); | 1488 | dmam_pool_destroy(chan->desc_pool); |
| 1490 | chan->desc_pool = NULL; | 1489 | chan->desc_pool = NULL; |
| @@ -1599,6 +1598,12 @@ static int stm32_mdma_probe(struct platform_device *pdev) | |||
| 1599 | return ret; | 1598 | return ret; |
| 1600 | } | 1599 | } |
| 1601 | 1600 | ||
| 1601 | ret = clk_prepare_enable(dmadev->clk); | ||
| 1602 | if (ret < 0) { | ||
| 1603 | dev_err(&pdev->dev, "clk_prep_enable error: %d\n", ret); | ||
| 1604 | return ret; | ||
| 1605 | } | ||
| 1606 | |||
| 1602 | dmadev->rst = devm_reset_control_get(&pdev->dev, NULL); | 1607 | dmadev->rst = devm_reset_control_get(&pdev->dev, NULL); |
| 1603 | if (!IS_ERR(dmadev->rst)) { | 1608 | if (!IS_ERR(dmadev->rst)) { |
| 1604 | reset_control_assert(dmadev->rst); | 1609 | reset_control_assert(dmadev->rst); |
| @@ -1670,6 +1675,10 @@ static int stm32_mdma_probe(struct platform_device *pdev) | |||
| 1670 | } | 1675 | } |
| 1671 | 1676 | ||
| 1672 | platform_set_drvdata(pdev, dmadev); | 1677 | platform_set_drvdata(pdev, dmadev); |
| 1678 | pm_runtime_set_active(&pdev->dev); | ||
| 1679 | pm_runtime_enable(&pdev->dev); | ||
| 1680 | pm_runtime_get_noresume(&pdev->dev); | ||
| 1681 | pm_runtime_put(&pdev->dev); | ||
| 1673 | 1682 | ||
| 1674 | dev_info(&pdev->dev, "STM32 MDMA driver registered\n"); | 1683 | dev_info(&pdev->dev, "STM32 MDMA driver registered\n"); |
| 1675 | 1684 | ||
| @@ -1679,11 +1688,42 @@ err_unregister: | |||
| 1679 | return ret; | 1688 | return ret; |
| 1680 | } | 1689 | } |
| 1681 | 1690 | ||
| 1691 | #ifdef CONFIG_PM | ||
| 1692 | static int stm32_mdma_runtime_suspend(struct device *dev) | ||
| 1693 | { | ||
| 1694 | struct stm32_mdma_device *dmadev = dev_get_drvdata(dev); | ||
| 1695 | |||
| 1696 | clk_disable_unprepare(dmadev->clk); | ||
| 1697 | |||
| 1698 | return 0; | ||
| 1699 | } | ||
| 1700 | |||
| 1701 | static int stm32_mdma_runtime_resume(struct device *dev) | ||
| 1702 | { | ||
| 1703 | struct stm32_mdma_device *dmadev = dev_get_drvdata(dev); | ||
| 1704 | int ret; | ||
| 1705 | |||
| 1706 | ret = clk_prepare_enable(dmadev->clk); | ||
| 1707 | if (ret) { | ||
| 1708 | dev_err(dev, "failed to prepare_enable clock\n"); | ||
| 1709 | return ret; | ||
| 1710 | } | ||
| 1711 | |||
| 1712 | return 0; | ||
| 1713 | } | ||
| 1714 | #endif | ||
| 1715 | |||
| 1716 | static const struct dev_pm_ops stm32_mdma_pm_ops = { | ||
| 1717 | SET_RUNTIME_PM_OPS(stm32_mdma_runtime_suspend, | ||
| 1718 | stm32_mdma_runtime_resume, NULL) | ||
| 1719 | }; | ||
| 1720 | |||
| 1682 | static struct platform_driver stm32_mdma_driver = { | 1721 | static struct platform_driver stm32_mdma_driver = { |
| 1683 | .probe = stm32_mdma_probe, | 1722 | .probe = stm32_mdma_probe, |
| 1684 | .driver = { | 1723 | .driver = { |
| 1685 | .name = "stm32-mdma", | 1724 | .name = "stm32-mdma", |
| 1686 | .of_match_table = stm32_mdma_of_match, | 1725 | .of_match_table = stm32_mdma_of_match, |
| 1726 | .pm = &stm32_mdma_pm_ops, | ||
| 1687 | }, | 1727 | }, |
| 1688 | }; | 1728 | }; |
| 1689 | 1729 | ||
