diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-27 02:40:50 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-27 02:40:50 -0400 |
| commit | 7e0a6fd5a4723c79cc46c9541e343092302e0e5b (patch) | |
| tree | 7b1e3e7512eecdcc94811982766c25d64150a200 | |
| parent | ca90666287401b475d9e0becf85bd02f069f1de8 (diff) | |
| parent | 6cfa6279edbffa921b7d8c9519bfd83a24ba508e (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.c | 57 | ||||
| -rw-r--r-- | drivers/mmc/host/mmci.c | 12 | ||||
| -rw-r--r-- | drivers/spi/spi-pl022.c | 84 |
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 | */ | ||
| 375 | static 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 | |||
| 386 | static 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 | ||
| 370 | static const struct dev_pm_ops amba_pm = { | 404 | static 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); | ||
