summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre-Yves MORDRET <pierre-yves.mordret@st.com>2019-01-03 05:17:08 -0500
committerVinod Koul <vkoul@kernel.org>2019-01-06 23:22:24 -0500
commit48bc73ba14bcd4080d971ed7049e81f2a4f4302e (patch)
treeefd2f91e0533ca0704cd06f4a3940286f9a1ce25
parentca4c72c01e349ff6313ced02e8e66f8e691530a9 (diff)
dmaengine: stm32-dma: 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-dma.c58
1 files changed, 51 insertions, 7 deletions
diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c
index 48f7c0fc1af9..ba239b529fa9 100644
--- a/drivers/dma/stm32-dma.c
+++ b/drivers/dma/stm32-dma.c
@@ -23,6 +23,7 @@
23#include <linux/of_device.h> 23#include <linux/of_device.h>
24#include <linux/of_dma.h> 24#include <linux/of_dma.h>
25#include <linux/platform_device.h> 25#include <linux/platform_device.h>
26#include <linux/pm_runtime.h>
26#include <linux/reset.h> 27#include <linux/reset.h>
27#include <linux/sched.h> 28#include <linux/sched.h>
28#include <linux/slab.h> 29#include <linux/slab.h>
@@ -1115,15 +1116,14 @@ static int stm32_dma_alloc_chan_resources(struct dma_chan *c)
1115 int ret; 1116 int ret;
1116 1117
1117 chan->config_init = false; 1118 chan->config_init = false;
1118 ret = clk_prepare_enable(dmadev->clk); 1119
1119 if (ret < 0) { 1120 ret = pm_runtime_get_sync(dmadev->ddev.dev);
1120 dev_err(chan2dev(chan), "clk_prepare_enable failed: %d\n", ret); 1121 if (ret < 0)
1121 return ret; 1122 return ret;
1122 }
1123 1123
1124 ret = stm32_dma_disable_chan(chan); 1124 ret = stm32_dma_disable_chan(chan);
1125 if (ret < 0) 1125 if (ret < 0)
1126 clk_disable_unprepare(dmadev->clk); 1126 pm_runtime_put(dmadev->ddev.dev);
1127 1127
1128 return ret; 1128 return ret;
1129} 1129}
@@ -1143,7 +1143,7 @@ static void stm32_dma_free_chan_resources(struct dma_chan *c)
1143 spin_unlock_irqrestore(&chan->vchan.lock, flags); 1143 spin_unlock_irqrestore(&chan->vchan.lock, flags);
1144 } 1144 }
1145 1145
1146 clk_disable_unprepare(dmadev->clk); 1146 pm_runtime_put(dmadev->ddev.dev);
1147 1147
1148 vchan_free_chan_resources(to_virt_chan(c)); 1148 vchan_free_chan_resources(to_virt_chan(c));
1149} 1149}
@@ -1243,6 +1243,12 @@ static int stm32_dma_probe(struct platform_device *pdev)
1243 return PTR_ERR(dmadev->clk); 1243 return PTR_ERR(dmadev->clk);
1244 } 1244 }
1245 1245
1246 ret = clk_prepare_enable(dmadev->clk);
1247 if (ret < 0) {
1248 dev_err(&pdev->dev, "clk_prep_enable error: %d\n", ret);
1249 return ret;
1250 }
1251
1246 dmadev->mem2mem = of_property_read_bool(pdev->dev.of_node, 1252 dmadev->mem2mem = of_property_read_bool(pdev->dev.of_node,
1247 "st,mem2mem"); 1253 "st,mem2mem");
1248 1254
@@ -1292,7 +1298,7 @@ static int stm32_dma_probe(struct platform_device *pdev)
1292 1298
1293 ret = dma_async_device_register(dd); 1299 ret = dma_async_device_register(dd);
1294 if (ret) 1300 if (ret)
1295 return ret; 1301 goto clk_free;
1296 1302
1297 for (i = 0; i < STM32_DMA_MAX_CHANNELS; i++) { 1303 for (i = 0; i < STM32_DMA_MAX_CHANNELS; i++) {
1298 chan = &dmadev->chan[i]; 1304 chan = &dmadev->chan[i];
@@ -1324,20 +1330,58 @@ static int stm32_dma_probe(struct platform_device *pdev)
1324 1330
1325 platform_set_drvdata(pdev, dmadev); 1331 platform_set_drvdata(pdev, dmadev);
1326 1332
1333 pm_runtime_set_active(&pdev->dev);
1334 pm_runtime_enable(&pdev->dev);
1335 pm_runtime_get_noresume(&pdev->dev);
1336 pm_runtime_put(&pdev->dev);
1337
1327 dev_info(&pdev->dev, "STM32 DMA driver registered\n"); 1338 dev_info(&pdev->dev, "STM32 DMA driver registered\n");
1328 1339
1329 return 0; 1340 return 0;
1330 1341
1331err_unregister: 1342err_unregister:
1332 dma_async_device_unregister(dd); 1343 dma_async_device_unregister(dd);
1344clk_free:
1345 clk_disable_unprepare(dmadev->clk);
1333 1346
1334 return ret; 1347 return ret;
1335} 1348}
1336 1349
1350#ifdef CONFIG_PM
1351static int stm32_dma_runtime_suspend(struct device *dev)
1352{
1353 struct stm32_dma_device *dmadev = dev_get_drvdata(dev);
1354
1355 clk_disable_unprepare(dmadev->clk);
1356
1357 return 0;
1358}
1359
1360static int stm32_dma_runtime_resume(struct device *dev)
1361{
1362 struct stm32_dma_device *dmadev = dev_get_drvdata(dev);
1363 int ret;
1364
1365 ret = clk_prepare_enable(dmadev->clk);
1366 if (ret) {
1367 dev_err(dev, "failed to prepare_enable clock\n");
1368 return ret;
1369 }
1370
1371 return 0;
1372}
1373#endif
1374
1375static const struct dev_pm_ops stm32_dma_pm_ops = {
1376 SET_RUNTIME_PM_OPS(stm32_dma_runtime_suspend,
1377 stm32_dma_runtime_resume, NULL)
1378};
1379
1337static struct platform_driver stm32_dma_driver = { 1380static struct platform_driver stm32_dma_driver = {
1338 .driver = { 1381 .driver = {
1339 .name = "stm32-dma", 1382 .name = "stm32-dma",
1340 .of_match_table = stm32_dma_of_match, 1383 .of_match_table = stm32_dma_of_match,
1384 .pm = &stm32_dma_pm_ops,
1341 }, 1385 },
1342}; 1386};
1343 1387