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 | |
| 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>
| -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); |
