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);
2191 2183
2192 pl022->clk = clk_get(&adev->dev, NULL); 2184 pl022->clk = clk_get(&adev->dev, NULL);
2193 if (IS_ERR(pl022->clk)) { 2185 if (IS_ERR(pl022->clk)) {
@@ -2195,7 +2187,6 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
2195 dev_err(&adev->dev, "could not retrieve SSP/SPI bus clock\n"); 2187 dev_err(&adev->dev, "could not retrieve SSP/SPI bus clock\n");
2196 goto err_no_clk; 2188 goto err_no_clk;
2197 } 2189 }
2198
2199 /* Disable SSP */ 2190 /* Disable SSP */
2200 writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)), 2191 writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)),
2201 SSP_CR1(pl022->virtbase)); 2192 SSP_CR1(pl022->virtbase));
@@ -2235,12 +2226,9 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
2235 goto err_spi_register; 2226 goto err_spi_register;
2236 } 2227 }
2237 dev_dbg(dev, "probe succeeded\n"); 2228 dev_dbg(dev, "probe succeeded\n");
2238 /* 2229
2239 * Disable the silicon block pclk and any voltage domain and just 2230 /* let runtime pm put suspend */
2240 * power it up and clock it when it's needed 2231 pm_runtime_put(dev);
2241 */
2242 amba_pclk_disable(adev);
2243 amba_vcore_disable(adev);
2244 return 0; 2232 return 0;
2245 2233
2246 err_spi_register: 2234 err_spi_register:
@@ -2249,7 +2237,6 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
2249 destroy_queue(pl022); 2237 destroy_queue(pl022);
2250 pl022_dma_remove(pl022); 2238 pl022_dma_remove(pl022);
2251 free_irq(adev->irq[0], pl022); 2239 free_irq(adev->irq[0], pl022);
2252 pm_runtime_disable(&adev->dev);
2253 err_no_irq: 2240 err_no_irq:
2254 clk_put(pl022->clk); 2241 clk_put(pl022->clk);
2255 err_no_clk: 2242 err_no_clk:
@@ -2271,6 +2258,12 @@ pl022_remove(struct amba_device *adev)
2271 if (!pl022) 2258 if (!pl022)
2272 return 0; 2259 return 0;
2273 2260
2261 /*
2262 * undo pm_runtime_put() in probe. I assume that we're not
2263 * accessing the primecell here.
2264 */
2265 pm_runtime_get_noresume(&adev->dev);
2266
2274 /* Remove the queue */ 2267 /* Remove the queue */
2275 if (destroy_queue(pl022) != 0) 2268 if (destroy_queue(pl022) != 0)
2276 dev_err(&adev->dev, "queue remove failed\n"); 2269 dev_err(&adev->dev, "queue remove failed\n");
@@ -2288,46 +2281,70 @@ pl022_remove(struct amba_device *adev)
2288 return 0; 2281 return 0;
2289} 2282}
2290 2283
2291#ifdef CONFIG_PM 2284#ifdef CONFIG_SUSPEND
2292static int pl022_suspend(struct amba_device *adev, pm_message_t state) 2285static int pl022_suspend(struct device *dev)
2293{ 2286{
2294 struct pl022 *pl022 = amba_get_drvdata(adev); 2287 struct pl022 *pl022 = dev_get_drvdata(dev);
2295 int status = 0; 2288 int status = 0;
2296 2289
2297 status = stop_queue(pl022); 2290 status = stop_queue(pl022);
2298 if (status) { 2291 if (status) {
2299 dev_warn(&adev->dev, "suspend cannot stop queue\n"); 2292 dev_warn(dev, "suspend cannot stop queue\n");
2300 return status; 2293 return status;
2301 } 2294 }
2302 2295
2303 amba_vcore_enable(adev); 2296 amba_vcore_enable(pl022->adev);
2304 amba_pclk_enable(adev); 2297 amba_pclk_enable(pl022->adev);
2305 load_ssp_default_config(pl022); 2298 load_ssp_default_config(pl022);
2306 amba_pclk_disable(adev); 2299 amba_pclk_disable(pl022->adev);
2307 amba_vcore_disable(adev); 2300 amba_vcore_disable(pl022->adev);
2308 dev_dbg(&adev->dev, "suspended\n"); 2301 dev_dbg(dev, "suspended\n");
2309 return 0; 2302 return 0;
2310} 2303}
2311 2304
2312static int pl022_resume(struct amba_device *adev) 2305static int pl022_resume(struct device *dev)
2313{ 2306{
2314 struct pl022 *pl022 = amba_get_drvdata(adev); 2307 struct pl022 *pl022 = dev_get_drvdata(dev);
2315 int status = 0; 2308 int status = 0;
2316 2309
2317 /* Start the queue running */ 2310 /* Start the queue running */
2318 status = start_queue(pl022); 2311 status = start_queue(pl022);
2319 if (status) 2312 if (status)
2320 dev_err(&adev->dev, "problem starting queue (%d)\n", status); 2313 dev_err(dev, "problem starting queue (%d)\n", status);
2321 else 2314 else
2322 dev_dbg(&adev->dev, "resumed\n"); 2315 dev_dbg(dev, "resumed\n");
2323 2316
2324 return status; 2317 return status;
2325} 2318}
2326#else
2327#define pl022_suspend NULL
2328#define pl022_resume NULL
2329#endif /* CONFIG_PM */ 2319#endif /* CONFIG_PM */
2330 2320
2321#ifdef CONFIG_PM_RUNTIME
2322static int pl022_runtime_suspend(struct device *dev)
2323{
2324 struct pl022 *pl022 = dev_get_drvdata(dev);
2325
2326 clk_disable(pl022->clk);
2327 amba_vcore_disable(pl022->adev);
2328
2329 return 0;
2330}
2331
2332static int pl022_runtime_resume(struct device *dev)
2333{
2334 struct pl022 *pl022 = dev_get_drvdata(dev);
2335
2336 amba_vcore_enable(pl022->adev);
2337 clk_enable(pl022->clk);
2338
2339 return 0;
2340}
2341#endif
2342
2343static const struct dev_pm_ops pl022_dev_pm_ops = {
2344 SET_SYSTEM_SLEEP_PM_OPS(pl022_suspend, pl022_resume)
2345 SET_RUNTIME_PM_OPS(pl022_runtime_suspend, pl022_runtime_resume, NULL)
2346};
2347
2331static struct vendor_data vendor_arm = { 2348static struct vendor_data vendor_arm = {
2332 .fifodepth = 8, 2349 .fifodepth = 8,
2333 .max_bpw = 16, 2350 .max_bpw = 16,
@@ -2407,12 +2424,11 @@ static struct amba_id pl022_ids[] = {
2407static struct amba_driver pl022_driver = { 2424static struct amba_driver pl022_driver = {
2408 .drv = { 2425 .drv = {
2409 .name = "ssp-pl022", 2426 .name = "ssp-pl022",
2427 .pm = &pl022_dev_pm_ops,
2410 }, 2428 },
2411 .id_table = pl022_ids, 2429 .id_table = pl022_ids,
2412 .probe = pl022_probe, 2430 .probe = pl022_probe,
2413 .remove = __devexit_p(pl022_remove), 2431 .remove = __devexit_p(pl022_remove),
2414 .suspend = pl022_suspend,
2415 .resume = pl022_resume,
2416}; 2432};
2417 2433
2418 2434