aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
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 /drivers/spi
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>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-pl022.c80
1 files changed, 48 insertions, 32 deletions
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index 730b4a37b823..078338f59481 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