aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2011-08-14 04:13:48 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-09-22 11:21:42 -0400
commit92b97f0aaccbf9de4a29696e6253bf82e8850d1d (patch)
tree0da0f934d8451ca450186c3a77d4fb6de7909f4b
parent93ee7a9340d64f20295aacc3fb6a22b759323280 (diff)
PM: add runtime PM support to core Primecell driver
Add runtime PM support to the core Primecell driver, following the PCI model of how this is done. Rather than having every driver fiddle about with enabling runtime PM, that's dealt with in the core and instead, drivers just do a put() in their probe and a balancing get() in their remove function to activate runtime PM for the device. As we're dealing with enabling runtime PM in the core, fix up spi-pl022 as it must not enable and disable runtime PM itself anymore. Tested-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--drivers/amba/bus.c57
-rw-r--r--drivers/spi/spi-pl022.c80
2 files changed, 102 insertions, 35 deletions
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index d74926e0939..84bdaace56c 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/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index 730b4a37b82..078338f5948 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,10 +2281,10 @@ 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 pl011_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);
@@ -2300,34 +2293,58 @@ static int pl022_suspend(struct amba_device *adev, pm_message_t state)
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(&adev->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