diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2010-02-11 11:50:18 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2010-03-01 21:09:07 -0500 |
commit | 20f2a3b5d57701c54bdd59b89dd37fe775926bae (patch) | |
tree | 28a69ee7db15840fa886c51524c52a1a787487e4 /drivers/dma/shdma.c | |
parent | 8b1935e6a36b0967efc593d67ed3aebbfbc1f5b1 (diff) |
dmaengine: shdma: add runtime PM support.
Provided platforms implement runtime PM, this disables the controller, when not
in use.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/dma/shdma.c')
-rw-r--r-- | drivers/dma/shdma.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index b419afaa2389..ea6779f3e73f 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c | |||
@@ -24,7 +24,10 @@ | |||
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/dma-mapping.h> | 25 | #include <linux/dma-mapping.h> |
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/pm_runtime.h> | ||
28 | |||
27 | #include <asm/dmaengine.h> | 29 | #include <asm/dmaengine.h> |
30 | |||
28 | #include "shdma.h" | 31 | #include "shdma.h" |
29 | 32 | ||
30 | /* DMA descriptor control */ | 33 | /* DMA descriptor control */ |
@@ -287,6 +290,8 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan) | |||
287 | struct sh_desc *desc; | 290 | struct sh_desc *desc; |
288 | struct sh_dmae_slave *param = chan->private; | 291 | struct sh_dmae_slave *param = chan->private; |
289 | 292 | ||
293 | pm_runtime_get_sync(sh_chan->dev); | ||
294 | |||
290 | /* | 295 | /* |
291 | * This relies on the guarantee from dmaengine that alloc_chan_resources | 296 | * This relies on the guarantee from dmaengine that alloc_chan_resources |
292 | * never runs concurrently with itself or free_chan_resources. | 297 | * never runs concurrently with itself or free_chan_resources. |
@@ -328,6 +333,9 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan) | |||
328 | } | 333 | } |
329 | spin_unlock_bh(&sh_chan->desc_lock); | 334 | spin_unlock_bh(&sh_chan->desc_lock); |
330 | 335 | ||
336 | if (!sh_chan->descs_allocated) | ||
337 | pm_runtime_put(sh_chan->dev); | ||
338 | |||
331 | return sh_chan->descs_allocated; | 339 | return sh_chan->descs_allocated; |
332 | } | 340 | } |
333 | 341 | ||
@@ -339,6 +347,7 @@ static void sh_dmae_free_chan_resources(struct dma_chan *chan) | |||
339 | struct sh_dmae_chan *sh_chan = to_sh_chan(chan); | 347 | struct sh_dmae_chan *sh_chan = to_sh_chan(chan); |
340 | struct sh_desc *desc, *_desc; | 348 | struct sh_desc *desc, *_desc; |
341 | LIST_HEAD(list); | 349 | LIST_HEAD(list); |
350 | int descs = sh_chan->descs_allocated; | ||
342 | 351 | ||
343 | dmae_halt(sh_chan); | 352 | dmae_halt(sh_chan); |
344 | 353 | ||
@@ -359,6 +368,9 @@ static void sh_dmae_free_chan_resources(struct dma_chan *chan) | |||
359 | 368 | ||
360 | spin_unlock_bh(&sh_chan->desc_lock); | 369 | spin_unlock_bh(&sh_chan->desc_lock); |
361 | 370 | ||
371 | if (descs > 0) | ||
372 | pm_runtime_put(sh_chan->dev); | ||
373 | |||
362 | list_for_each_entry_safe(desc, _desc, &list, node) | 374 | list_for_each_entry_safe(desc, _desc, &list, node) |
363 | kfree(desc); | 375 | kfree(desc); |
364 | } | 376 | } |
@@ -978,6 +990,9 @@ static int __init sh_dmae_probe(struct platform_device *pdev) | |||
978 | /* platform data */ | 990 | /* platform data */ |
979 | shdev->pdata = pdata; | 991 | shdev->pdata = pdata; |
980 | 992 | ||
993 | pm_runtime_enable(&pdev->dev); | ||
994 | pm_runtime_get_sync(&pdev->dev); | ||
995 | |||
981 | /* reset dma controller */ | 996 | /* reset dma controller */ |
982 | err = sh_dmae_rst(shdev); | 997 | err = sh_dmae_rst(shdev); |
983 | if (err) | 998 | if (err) |
@@ -1066,6 +1081,8 @@ static int __init sh_dmae_probe(struct platform_device *pdev) | |||
1066 | goto chan_probe_err; | 1081 | goto chan_probe_err; |
1067 | } | 1082 | } |
1068 | 1083 | ||
1084 | pm_runtime_put(&pdev->dev); | ||
1085 | |||
1069 | platform_set_drvdata(pdev, shdev); | 1086 | platform_set_drvdata(pdev, shdev); |
1070 | dma_async_device_register(&shdev->common); | 1087 | dma_async_device_register(&shdev->common); |
1071 | 1088 | ||
@@ -1079,6 +1096,7 @@ eirqres: | |||
1079 | eirq_err: | 1096 | eirq_err: |
1080 | #endif | 1097 | #endif |
1081 | rst_err: | 1098 | rst_err: |
1099 | pm_runtime_put(&pdev->dev); | ||
1082 | if (dmars) | 1100 | if (dmars) |
1083 | iounmap(shdev->dmars); | 1101 | iounmap(shdev->dmars); |
1084 | emapdmars: | 1102 | emapdmars: |
@@ -1108,6 +1126,8 @@ static int __exit sh_dmae_remove(struct platform_device *pdev) | |||
1108 | /* channel data remove */ | 1126 | /* channel data remove */ |
1109 | sh_dmae_chan_remove(shdev); | 1127 | sh_dmae_chan_remove(shdev); |
1110 | 1128 | ||
1129 | pm_runtime_disable(&pdev->dev); | ||
1130 | |||
1111 | if (shdev->dmars) | 1131 | if (shdev->dmars) |
1112 | iounmap(shdev->dmars); | 1132 | iounmap(shdev->dmars); |
1113 | iounmap(shdev->chan_reg); | 1133 | iounmap(shdev->chan_reg); |