diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2011-04-29 13:09:25 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2011-05-22 23:44:33 -0400 |
commit | 467017b83b5bc445be5d275cf727b4f7ba3d2b2d (patch) | |
tree | a7c0a41d9e99488a73b42544e40b8c31a2ef84ef | |
parent | 2dc666673b5a39d005579a0ef63ae69b5094e686 (diff) |
dmaengine: shdma: add runtime- and system-level power management
This patch extends and fixes runtime power management in the shdma
driver to support powering down the DMA controller and adds support
for system-level suspend and resume.
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 | 68 | ||||
-rw-r--r-- | drivers/dma/shdma.h | 1 |
2 files changed, 69 insertions, 0 deletions
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 727f51e903d9..00b5f320b0e8 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c | |||
@@ -1255,6 +1255,8 @@ rst_err: | |||
1255 | spin_unlock_irqrestore(&sh_dmae_lock, flags); | 1255 | spin_unlock_irqrestore(&sh_dmae_lock, flags); |
1256 | 1256 | ||
1257 | pm_runtime_put(&pdev->dev); | 1257 | pm_runtime_put(&pdev->dev); |
1258 | pm_runtime_disable(&pdev->dev); | ||
1259 | |||
1258 | if (dmars) | 1260 | if (dmars) |
1259 | iounmap(shdev->dmars); | 1261 | iounmap(shdev->dmars); |
1260 | emapdmars: | 1262 | emapdmars: |
@@ -1313,12 +1315,78 @@ static void sh_dmae_shutdown(struct platform_device *pdev) | |||
1313 | sh_dmae_ctl_stop(shdev); | 1315 | sh_dmae_ctl_stop(shdev); |
1314 | } | 1316 | } |
1315 | 1317 | ||
1318 | static int sh_dmae_runtime_suspend(struct device *dev) | ||
1319 | { | ||
1320 | return 0; | ||
1321 | } | ||
1322 | |||
1323 | static int sh_dmae_runtime_resume(struct device *dev) | ||
1324 | { | ||
1325 | struct sh_dmae_device *shdev = dev_get_drvdata(dev); | ||
1326 | |||
1327 | return sh_dmae_rst(shdev); | ||
1328 | } | ||
1329 | |||
1330 | #ifdef CONFIG_PM | ||
1331 | static int sh_dmae_suspend(struct device *dev) | ||
1332 | { | ||
1333 | struct sh_dmae_device *shdev = dev_get_drvdata(dev); | ||
1334 | int i; | ||
1335 | |||
1336 | for (i = 0; i < shdev->pdata->channel_num; i++) { | ||
1337 | struct sh_dmae_chan *sh_chan = shdev->chan[i]; | ||
1338 | if (sh_chan->descs_allocated) | ||
1339 | sh_chan->pm_error = pm_runtime_put_sync(dev); | ||
1340 | } | ||
1341 | |||
1342 | return 0; | ||
1343 | } | ||
1344 | |||
1345 | static int sh_dmae_resume(struct device *dev) | ||
1346 | { | ||
1347 | struct sh_dmae_device *shdev = dev_get_drvdata(dev); | ||
1348 | int i; | ||
1349 | |||
1350 | for (i = 0; i < shdev->pdata->channel_num; i++) { | ||
1351 | struct sh_dmae_chan *sh_chan = shdev->chan[i]; | ||
1352 | struct sh_dmae_slave *param = sh_chan->common.private; | ||
1353 | |||
1354 | if (!sh_chan->descs_allocated) | ||
1355 | continue; | ||
1356 | |||
1357 | if (!sh_chan->pm_error) | ||
1358 | pm_runtime_get_sync(dev); | ||
1359 | |||
1360 | if (param) { | ||
1361 | const struct sh_dmae_slave_config *cfg = param->config; | ||
1362 | dmae_set_dmars(sh_chan, cfg->mid_rid); | ||
1363 | dmae_set_chcr(sh_chan, cfg->chcr); | ||
1364 | } else { | ||
1365 | dmae_init(sh_chan); | ||
1366 | } | ||
1367 | } | ||
1368 | |||
1369 | return 0; | ||
1370 | } | ||
1371 | #else | ||
1372 | #define sh_dmae_suspend NULL | ||
1373 | #define sh_dmae_resume NULL | ||
1374 | #endif | ||
1375 | |||
1376 | const struct dev_pm_ops sh_dmae_pm = { | ||
1377 | .suspend = sh_dmae_suspend, | ||
1378 | .resume = sh_dmae_resume, | ||
1379 | .runtime_suspend = sh_dmae_runtime_suspend, | ||
1380 | .runtime_resume = sh_dmae_runtime_resume, | ||
1381 | }; | ||
1382 | |||
1316 | static struct platform_driver sh_dmae_driver = { | 1383 | static struct platform_driver sh_dmae_driver = { |
1317 | .remove = __exit_p(sh_dmae_remove), | 1384 | .remove = __exit_p(sh_dmae_remove), |
1318 | .shutdown = sh_dmae_shutdown, | 1385 | .shutdown = sh_dmae_shutdown, |
1319 | .driver = { | 1386 | .driver = { |
1320 | .owner = THIS_MODULE, | 1387 | .owner = THIS_MODULE, |
1321 | .name = "sh-dma-engine", | 1388 | .name = "sh-dma-engine", |
1389 | .pm = &sh_dmae_pm, | ||
1322 | }, | 1390 | }, |
1323 | }; | 1391 | }; |
1324 | 1392 | ||
diff --git a/drivers/dma/shdma.h b/drivers/dma/shdma.h index 52e4fb173805..3f9d3cd06584 100644 --- a/drivers/dma/shdma.h +++ b/drivers/dma/shdma.h | |||
@@ -37,6 +37,7 @@ struct sh_dmae_chan { | |||
37 | int id; /* Raw id of this channel */ | 37 | int id; /* Raw id of this channel */ |
38 | u32 __iomem *base; | 38 | u32 __iomem *base; |
39 | char dev_id[16]; /* unique name per DMAC of channel */ | 39 | char dev_id[16]; /* unique name per DMAC of channel */ |
40 | int pm_error; | ||
40 | }; | 41 | }; |
41 | 42 | ||
42 | struct sh_dmae_device { | 43 | struct sh_dmae_device { |