aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-10-27 02:40:50 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-10-27 02:40:50 -0400
commit7e0a6fd5a4723c79cc46c9541e343092302e0e5b (patch)
tree7b1e3e7512eecdcc94811982766c25d64150a200
parentca90666287401b475d9e0becf85bd02f069f1de8 (diff)
parent6cfa6279edbffa921b7d8c9519bfd83a24ba508e (diff)
Merge branch 'amba' of http://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-2.6-arm
* 'amba' of http://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-2.6-arm: ARM: 7079/1: spi: Fix builderror in spi-pl022.c PM: add runtime PM support to MMCI PM: add runtime PM support to core Primecell driver
-rw-r--r--drivers/amba/bus.c57
-rw-r--r--drivers/mmc/host/mmci.c12
-rw-r--r--drivers/spi/spi-pl022.c84
3 files changed, 116 insertions, 37 deletions
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index d74926e0939e..84bdaace56c8 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -365,6 +365,40 @@ static int amba_pm_restore_noirq(struct device *dev)
365 365
366#endif /* !CONFIG_HIBERNATE_CALLBACKS */ 366#endif /* !CONFIG_HIBERNATE_CALLBACKS */
367 367
368#ifdef CONFIG_PM_RUNTIME
369/*
370 * Hooks to provide runtime PM of the pclk (bus clock). It is safe to
371 * enable/disable the bus clock at runtime PM suspend/resume as this
372 * does not result in loss of context. However, disabling vcore power
373 * would do, so we leave that to the driver.
374 */
375static int amba_pm_runtime_suspend(struct device *dev)
376{
377 struct amba_device *pcdev = to_amba_device(dev);
378 int ret = pm_generic_runtime_suspend(dev);
379
380 if (ret == 0 && dev->driver)
381 clk_disable(pcdev->pclk);
382
383 return ret;
384}
385
386static int amba_pm_runtime_resume(struct device *dev)
387{
388 struct amba_device *pcdev = to_amba_device(dev);
389 int ret;
390
391 if (dev->driver) {
392 ret = clk_enable(pcdev->pclk);
393 /* Failure is probably fatal to the system, but... */
394 if (ret)
395 return ret;
396 }
397
398 return pm_generic_runtime_resume(dev);
399}
400#endif
401
368#ifdef CONFIG_PM 402#ifdef CONFIG_PM
369 403
370static const struct dev_pm_ops amba_pm = { 404static const struct dev_pm_ops amba_pm = {
@@ -383,8 +417,8 @@ static const struct dev_pm_ops amba_pm = {
383 .poweroff_noirq = amba_pm_poweroff_noirq, 417 .poweroff_noirq = amba_pm_poweroff_noirq,
384 .restore_noirq = amba_pm_restore_noirq, 418 .restore_noirq = amba_pm_restore_noirq,
385 SET_RUNTIME_PM_OPS( 419 SET_RUNTIME_PM_OPS(
386 pm_generic_runtime_suspend, 420 amba_pm_runtime_suspend,
387 pm_generic_runtime_resume, 421 amba_pm_runtime_resume,
388 pm_generic_runtime_idle 422 pm_generic_runtime_idle
389 ) 423 )
390}; 424};
@@ -494,10 +528,18 @@ static int amba_probe(struct device *dev)
494 if (ret) 528 if (ret)
495 break; 529 break;
496 530
531 pm_runtime_get_noresume(dev);
532 pm_runtime_set_active(dev);
533 pm_runtime_enable(dev);
534
497 ret = pcdrv->probe(pcdev, id); 535 ret = pcdrv->probe(pcdev, id);
498 if (ret == 0) 536 if (ret == 0)
499 break; 537 break;
500 538
539 pm_runtime_disable(dev);
540 pm_runtime_set_suspended(dev);
541 pm_runtime_put_noidle(dev);
542
501 amba_put_disable_pclk(pcdev); 543 amba_put_disable_pclk(pcdev);
502 amba_put_disable_vcore(pcdev); 544 amba_put_disable_vcore(pcdev);
503 } while (0); 545 } while (0);
@@ -509,7 +551,16 @@ static int amba_remove(struct device *dev)
509{ 551{
510 struct amba_device *pcdev = to_amba_device(dev); 552 struct amba_device *pcdev = to_amba_device(dev);
511 struct amba_driver *drv = to_amba_driver(dev->driver); 553 struct amba_driver *drv = to_amba_driver(dev->driver);
512 int ret = drv->remove(pcdev); 554 int ret;
555
556 pm_runtime_get_sync(dev);
557 ret = drv->remove(pcdev);
558 pm_runtime_put_noidle(dev);
559
560 /* Undo the runtime PM settings in amba_probe() */
561 pm_runtime_disable(dev);
562 pm_runtime_set_suspended(dev);
563 pm_runtime_put_noidle(dev);
513 564
514 amba_put_disable_pclk(pcdev); 565 amba_put_disable_pclk(pcdev);
515 amba_put_disable_vcore(pcdev); 566 amba_put_disable_vcore(pcdev);
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 56e9a4168264..5e142b7f5ecf 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -29,6 +29,7 @@
29#include <linux/dmaengine.h> 29#include <linux/dmaengine.h>
30#include <linux/dma-mapping.h> 30#include <linux/dma-mapping.h>
31#include <linux/amba/mmci.h> 31#include <linux/amba/mmci.h>
32#include <linux/pm_runtime.h>
32 33
33#include <asm/div64.h> 34#include <asm/div64.h>
34#include <asm/io.h> 35#include <asm/io.h>
@@ -170,6 +171,7 @@ mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
170 * back into the driver... 171 * back into the driver...
171 */ 172 */
172 spin_unlock(&host->lock); 173 spin_unlock(&host->lock);
174 pm_runtime_put(mmc_dev(host->mmc));
173 mmc_request_done(host->mmc, mrq); 175 mmc_request_done(host->mmc, mrq);
174 spin_lock(&host->lock); 176 spin_lock(&host->lock);
175} 177}
@@ -984,6 +986,8 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
984 return; 986 return;
985 } 987 }
986 988
989 pm_runtime_get_sync(mmc_dev(mmc));
990
987 spin_lock_irqsave(&host->lock, flags); 991 spin_lock_irqsave(&host->lock, flags);
988 992
989 host->mrq = mrq; 993 host->mrq = mrq;
@@ -1327,6 +1331,8 @@ static int __devinit mmci_probe(struct amba_device *dev,
1327 1331
1328 mmci_dma_setup(host); 1332 mmci_dma_setup(host);
1329 1333
1334 pm_runtime_put(&dev->dev);
1335
1330 mmc_add_host(mmc); 1336 mmc_add_host(mmc);
1331 1337
1332 return 0; 1338 return 0;
@@ -1364,6 +1370,12 @@ static int __devexit mmci_remove(struct amba_device *dev)
1364 if (mmc) { 1370 if (mmc) {
1365 struct mmci_host *host = mmc_priv(mmc); 1371 struct mmci_host *host = mmc_priv(mmc);
1366 1372
1373 /*
1374 * Undo pm_runtime_put() in probe. We use the _sync
1375 * version here so that we can access the primecell.
1376 */
1377 pm_runtime_get_sync(&dev->dev);
1378
1367 mmc_remove_host(mmc); 1379 mmc_remove_host(mmc);
1368 1380
1369 writel(0, host->base + MMCIMASK0); 1381 writel(0, host->base + MMCIMASK0);
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index 730b4a37b823..3520cf955b95 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -515,9 +515,6 @@ static void giveback(struct pl022 *pl022)
515 if (msg->complete) 515 if (msg->complete)
516 msg->complete(msg->context); 516 msg->complete(msg->context);
517 /* This message is completed, so let's turn off the clocks & power */ 517 /* This message is completed, so let's turn off the clocks & power */
518 clk_disable(pl022->clk);
519 amba_pclk_disable(pl022->adev);
520 amba_vcore_disable(pl022->adev);
521 pm_runtime_put(&pl022->adev->dev); 518 pm_runtime_put(&pl022->adev->dev);
522} 519}
523 520
@@ -1545,9 +1542,6 @@ static void pump_messages(struct work_struct *work)
1545 * (poll/interrupt/DMA) 1542 * (poll/interrupt/DMA)
1546 */ 1543 */
1547 pm_runtime_get_sync(&pl022->adev->dev); 1544 pm_runtime_get_sync(&pl022->adev->dev);
1548 amba_vcore_enable(pl022->adev);
1549 amba_pclk_enable(pl022->adev);
1550 clk_enable(pl022->clk);
1551 restore_state(pl022); 1545 restore_state(pl022);
1552 flush(pl022); 1546 flush(pl022);
1553 1547
@@ -2186,8 +2180,6 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
2186 } 2180 }
2187 printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n", 2181 printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n",
2188 adev->res.start, pl022->virtbase); 2182 adev->res.start, pl022->virtbase);
2189 pm_runtime_enable(dev);
2190 pm_runtime_resume(dev);