aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@stericsson.com>2012-09-26 12:06:22 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-09-28 09:05:07 -0400
commitada7aec7eec0ca2d2a9d2208548813d5dda8108e (patch)
tree7620085b15946b76cd480d01695968c736a886bf /drivers/spi
parentaeef9915b9a40d257ec94f9900a3fb4a15da2ab7 (diff)
spi/pl022: get/put resources on suspend/resume
This factors out the resource handling in runtime suspend/resume and also calls it from the ordinary suspend and resume hooks. The semantics require that ordinary PM op suspend is called with runtime PM in resumed mode, so that ordinary suspend can assume that it will e.g. decrease the clock reference counter to 0, runtime resume having previously increased it to 1. Cc: Vipul Kumar Samar <vipulkumar.samar@st.com> Cc: Viresh Kumar <viresh.kumar@linaro.org> Acked-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Linus Walleij <linus.walleij@stericsson.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-pl022.c66
1 files changed, 44 insertions, 22 deletions
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index 15737bcee9fb..919464102d33 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -2300,6 +2300,45 @@ pl022_remove(struct amba_device *adev)
2300 return 0; 2300 return 0;
2301} 2301}
2302 2302
2303#if defined(CONFIG_SUSPEND) || defined(CONFIG_PM_RUNTIME)
2304/*
2305 * These two functions are used from both suspend/resume and
2306 * the runtime counterparts to handle external resources like
2307 * clocks, pins and regulators when going to sleep.
2308 */
2309static void pl022_suspend_resources(struct pl022 *pl022)
2310{
2311 int ret;
2312
2313 clk_disable(pl022->clk);
2314
2315 /* Optionally let pins go into sleep states */
2316 if (!IS_ERR(pl022->pins_sleep)) {
2317 ret = pinctrl_select_state(pl022->pinctrl,
2318 pl022->pins_sleep);
2319 if (ret)
2320 dev_err(&pl022->adev->dev,
2321 "could not set pins to sleep state\n");
2322 }
2323}
2324
2325static void pl022_resume_resources(struct pl022 *pl022)
2326{
2327 int ret;
2328
2329 /* Optionaly enable pins to be muxed in and configured */
2330 if (!IS_ERR(pl022->pins_default)) {
2331 ret = pinctrl_select_state(pl022->pinctrl,
2332 pl022->pins_default);
2333 if (ret)
2334 dev_err(&pl022->adev->dev,
2335 "could not set default pins\n");
2336 }
2337
2338 clk_enable(pl022->clk);
2339}
2340#endif
2341
2303#ifdef CONFIG_SUSPEND 2342#ifdef CONFIG_SUSPEND
2304static int pl022_suspend(struct device *dev) 2343static int pl022_suspend(struct device *dev)
2305{ 2344{
@@ -2311,6 +2350,7 @@ static int pl022_suspend(struct device *dev)
2311 dev_warn(dev, "cannot suspend master\n"); 2350 dev_warn(dev, "cannot suspend master\n");
2312 return ret; 2351 return ret;
2313 } 2352 }
2353 pl022_suspend_resources(pl022);
2314 2354
2315 dev_dbg(dev, "suspended\n"); 2355 dev_dbg(dev, "suspended\n");
2316 return 0; 2356 return 0;
@@ -2321,6 +2361,8 @@ static int pl022_resume(struct device *dev)
2321 struct pl022 *pl022 = dev_get_drvdata(dev); 2361 struct pl022 *pl022 = dev_get_drvdata(dev);
2322 int ret; 2362 int ret;
2323 2363
2364 pl022_resume_resources(pl022);
2365
2324 /* Start the queue running */ 2366 /* Start the queue running */
2325 ret = spi_master_resume(pl022->master); 2367 ret = spi_master_resume(pl022->master);
2326 if (ret) 2368 if (ret)
@@ -2336,36 +2378,16 @@ static int pl022_resume(struct device *dev)
2336static int pl022_runtime_suspend(struct device *dev) 2378static int pl022_runtime_suspend(struct device *dev)
2337{ 2379{
2338 struct pl022 *pl022 = dev_get_drvdata(dev); 2380 struct pl022 *pl022 = dev_get_drvdata(dev);
2339 int status = 0;
2340
2341 clk_disable(pl022->clk);
2342
2343 /* Optionally let pins go into sleep states */
2344 if (!IS_ERR(pl022->pins_sleep)) {
2345 status = pinctrl_select_state(pl022->pinctrl,
2346 pl022->pins_sleep);
2347 if (status)
2348 dev_err(dev, "could not set pins to sleep state\n");
2349 }
2350 2381
2382 pl022_suspend_resources(pl022);
2351 return 0; 2383 return 0;
2352} 2384}
2353 2385
2354static int pl022_runtime_resume(struct device *dev) 2386static int pl022_runtime_resume(struct device *dev)
2355{ 2387{
2356 struct pl022 *pl022 = dev_get_drvdata(dev); 2388 struct pl022 *pl022 = dev_get_drvdata(dev);
2357 int status = 0;
2358
2359 /* Optionaly enable pins to be muxed in and configured */
2360 if (!IS_ERR(pl022->pins_default)) {
2361 status = pinctrl_select_state(pl022->pinctrl,
2362 pl022->pins_default);
2363 if (status)
2364 dev_err(dev, "could not set default pins\n");
2365 }
2366
2367 clk_enable(pl022->clk);
2368 2389
2390 pl022_resume_resources(pl022);
2369 return 0; 2391 return 0;
2370} 2392}
2371#endif 2393#endif