From ada7aec7eec0ca2d2a9d2208548813d5dda8108e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 26 Sep 2012 18:06:22 +0200 Subject: [PATCH] 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 Cc: Viresh Kumar Acked-by: Ulf Hansson Signed-off-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/spi/spi-pl022.c | 66 +++++++++++++++++++++++++++-------------- 1 file 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) return 0; } +#if defined(CONFIG_SUSPEND) || defined(CONFIG_PM_RUNTIME) +/* + * These two functions are used from both suspend/resume and + * the runtime counterparts to handle external resources like + * clocks, pins and regulators when going to sleep. + */ +static void pl022_suspend_resources(struct pl022 *pl022) +{ + int ret; + + clk_disable(pl022->clk); + + /* Optionally let pins go into sleep states */ + if (!IS_ERR(pl022->pins_sleep)) { + ret = pinctrl_select_state(pl022->pinctrl, + pl022->pins_sleep); + if (ret) + dev_err(&pl022->adev->dev, + "could not set pins to sleep state\n"); + } +} + +static void pl022_resume_resources(struct pl022 *pl022) +{ + int ret; + + /* Optionaly enable pins to be muxed in and configured */ + if (!IS_ERR(pl022->pins_default)) { + ret = pinctrl_select_state(pl022->pinctrl, + pl022->pins_default); + if (ret) + dev_err(&pl022->adev->dev, + "could not set default pins\n"); + } + + clk_enable(pl022->clk); +} +#endif + #ifdef CONFIG_SUSPEND static int pl022_suspend(struct device *dev) { @@ -2311,6 +2350,7 @@ static int pl022_suspend(struct device *dev) dev_warn(dev, "cannot suspend master\n"); return ret; } + pl022_suspend_resources(pl022); dev_dbg(dev, "suspended\n"); return 0; @@ -2321,6 +2361,8 @@ static int pl022_resume(struct device *dev) struct pl022 *pl022 = dev_get_drvdata(dev); int ret; + pl022_resume_resources(pl022); + /* Start the queue running */ ret = spi_master_resume(pl022->master); if (ret) @@ -2336,36 +2378,16 @@ static int pl022_resume(struct device *dev) static int pl022_runtime_suspend(struct device *dev) { struct pl022 *pl022 = dev_get_drvdata(dev); - int status = 0; - - clk_disable(pl022->clk); - - /* Optionally let pins go into sleep states */ - if (!IS_ERR(pl022->pins_sleep)) { - status = pinctrl_select_state(pl022->pinctrl, - pl022->pins_sleep); - if (status) - dev_err(dev, "could not set pins to sleep state\n"); - } + pl022_suspend_resources(pl022); return 0; } static int pl022_runtime_resume(struct device *dev) { struct pl022 *pl022 = dev_get_drvdata(dev); - int status = 0; - - /* Optionaly enable pins to be muxed in and configured */ - if (!IS_ERR(pl022->pins_default)) { - status = pinctrl_select_state(pl022->pinctrl, - pl022->pins_default); - if (status) - dev_err(dev, "could not set default pins\n"); - } - - clk_enable(pl022->clk); + pl022_resume_resources(pl022); return 0; } #endif