aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/shdma.c
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2010-02-11 11:50:18 -0500
committerPaul Mundt <lethal@linux-sh.org>2010-03-01 21:09:07 -0500
commit20f2a3b5d57701c54bdd59b89dd37fe775926bae (patch)
tree28a69ee7db15840fa886c51524c52a1a787487e4 /drivers/dma/shdma.c
parent8b1935e6a36b0967efc593d67ed3aebbfbc1f5b1 (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.c20
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:
1079eirq_err: 1096eirq_err:
1080#endif 1097#endif
1081rst_err: 1098rst_err:
1099 pm_runtime_put(&pdev->dev);
1082 if (dmars) 1100 if (dmars)
1083 iounmap(shdev->dmars); 1101 iounmap(shdev->dmars);
1084emapdmars: 1102emapdmars:
@@ -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);