From 3e7dde425dbcc7965398e92909d898c4ebc9fdb8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 22 Jan 2014 18:41:36 +0000 Subject: spi/pl022: Unprepare clocks while suspended When the driver was converted to clk_prepare() the suspend path didn't have any changes made so the clock remains prepared throughout the runtime of the driver. Unprepare it when suspended so that any savings that can be made as a result are made. Signed-off-by: Mark Brown Acked-by: Linus Walleij --- drivers/spi/spi-pl022.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/spi/spi-pl022.c') diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 2789b452e711..4ec49eae6141 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2296,7 +2296,7 @@ pl022_remove(struct amba_device *adev) */ static void pl022_suspend_resources(struct pl022 *pl022, bool runtime) { - clk_disable(pl022->clk); + clk_disable_unprepare(pl022->clk); if (runtime) pinctrl_pm_select_idle_state(&pl022->adev->dev); @@ -2312,7 +2312,7 @@ static void pl022_resume_resources(struct pl022 *pl022, bool runtime) /* Then let's idle the pins until the next transfer happens */ pinctrl_pm_select_idle_state(&pl022->adev->dev); - clk_enable(pl022->clk); + clk_prepare_enable(pl022->clk); } #endif -- cgit v1.2.1 From 6cac167b826eced25a2756b996a93c6f7833c49b Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 4 Feb 2014 16:58:50 +0100 Subject: spi: pl022: Simplify clock handling Make use of clk_prepare_enable and clk_disable_unprepare to simplify code. No functional change. Signed-off-by: Ulf Hansson Signed-off-by: Mark Brown --- drivers/spi/spi-pl022.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'drivers/spi/spi-pl022.c') diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 4ec49eae6141..5f7594bc2086 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2183,13 +2183,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) goto err_no_clk; } - status = clk_prepare(pl022->clk); - if (status) { - dev_err(&adev->dev, "could not prepare SSP/SPI bus clock\n"); - goto err_clk_prep; - } - - status = clk_enable(pl022->clk); + status = clk_prepare_enable(pl022->clk); if (status) { dev_err(&adev->dev, "could not enable SSP/SPI bus clock\n"); goto err_no_clk_en; @@ -2250,10 +2244,8 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) if (platform_info->enable_dma) pl022_dma_remove(pl022); err_no_irq: - clk_disable(pl022->clk); + clk_disable_unprepare(pl022->clk); err_no_clk_en: - clk_unprepare(pl022->clk); - err_clk_prep: err_no_clk: err_no_ioremap: amba_release_regions(adev); @@ -2281,8 +2273,7 @@ pl022_remove(struct amba_device *adev) if (pl022->master_info->enable_dma) pl022_dma_remove(pl022); - clk_disable(pl022->clk); - clk_unprepare(pl022->clk); + clk_disable_unprepare(pl022->clk); amba_release_regions(adev); tasklet_disable(&pl022->pump_transfers); return 0; -- cgit v1.2.1 From 8535736c27cc4e25b9948d857138315f45b6fa34 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 4 Feb 2014 16:58:51 +0100 Subject: spi: pl022: Remove redundant pinctrl to default state in probe The driver core is now taking care of putting our pins into default state at probe. Thus we can remove the redundant call for it in probe. Signed-off-by: Ulf Hansson Signed-off-by: Mark Brown --- drivers/spi/spi-pl022.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/spi/spi-pl022.c') diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 5f7594bc2086..74a072924b65 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2109,8 +2109,6 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) pl022->chipselects = devm_kzalloc(dev, num_cs * sizeof(int), GFP_KERNEL); - pinctrl_pm_select_default_state(dev); - /* * Bus Number Which has been Assigned to this SSP controller * on this board -- cgit v1.2.1 From 736198b0486c8d5032456de0813515d954df978a Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Sat, 1 Mar 2014 11:56:06 +0100 Subject: spi: pl022: Let runtime PM callbacks be available for CONFIG_PM Convert to the SET_PM_RUNTIME_PM macro while defining the runtime PM callbacks. This means the callbacks becomes available for both CONFIG_PM_SLEEP and CONFIG_PM_RUNTIME, which is needed to handle the combinations of these scenarios. Signed-off-by: Ulf Hansson Signed-off-by: Mark Brown --- drivers/spi/spi-pl022.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/spi/spi-pl022.c') diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 74a072924b65..6dfcabf74728 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2277,7 +2277,7 @@ pl022_remove(struct amba_device *adev) return 0; } -#if defined(CONFIG_SUSPEND) || defined(CONFIG_PM_RUNTIME) +#ifdef CONFIG_PM /* * These two functions are used from both suspend/resume and * the runtime counterparts to handle external resources like @@ -2343,7 +2343,7 @@ static int pl022_resume(struct device *dev) } #endif /* CONFIG_PM */ -#ifdef CONFIG_PM_RUNTIME +#ifdef CONFIG_PM static int pl022_runtime_suspend(struct device *dev) { struct pl022 *pl022 = dev_get_drvdata(dev); @@ -2363,7 +2363,7 @@ static int pl022_runtime_resume(struct device *dev) static const struct dev_pm_ops pl022_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(pl022_suspend, pl022_resume) - SET_RUNTIME_PM_OPS(pl022_runtime_suspend, pl022_runtime_resume, NULL) + SET_PM_RUNTIME_PM_OPS(pl022_runtime_suspend, pl022_runtime_resume, NULL) }; static struct vendor_data vendor_arm = { -- cgit v1.2.1 From 84a5dc41f64faadb79cde600b130c8cbd7e21977 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Sat, 1 Mar 2014 11:56:07 +0100 Subject: spi: pl022: Don't ignore power domain and amba bus at system suspend Previously only the resources controlled by the driver were put into low power state at system suspend. Both the amba bus and a potential power domain were ignored. Moreover, while putting the device into low power state we first brought it back to full power, but for no particular reason. To handle both issues above, use pm_runtime_force_suspend|resume() from the system suspend|resume callbacks. Signed-off-by: Ulf Hansson Signed-off-by: Mark Brown --- drivers/spi/spi-pl022.c | 54 +++++++++++++++++-------------------------------- 1 file changed, 18 insertions(+), 36 deletions(-) (limited to 'drivers/spi/spi-pl022.c') diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 6dfcabf74728..d37e840944d6 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2277,35 +2277,7 @@ pl022_remove(struct amba_device *adev) return 0; } -#ifdef CONFIG_PM -/* - * 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, bool runtime) -{ - clk_disable_unprepare(pl022->clk); - - if (runtime) - pinctrl_pm_select_idle_state(&pl022->adev->dev); - else - pinctrl_pm_select_sleep_state(&pl022->adev->dev); -} - -static void pl022_resume_resources(struct pl022 *pl022, bool runtime) -{ - /* First go to the default state */ - pinctrl_pm_select_default_state(&pl022->adev->dev); - if (!runtime) - /* Then let's idle the pins until the next transfer happens */ - pinctrl_pm_select_idle_state(&pl022->adev->dev); - - clk_prepare_enable(pl022->clk); -} -#endif - -#ifdef CONFIG_SUSPEND +#ifdef CONFIG_PM_SLEEP static int pl022_suspend(struct device *dev) { struct pl022 *pl022 = dev_get_drvdata(dev); @@ -2317,8 +2289,13 @@ static int pl022_suspend(struct device *dev) return ret; } - pm_runtime_get_sync(dev); - pl022_suspend_resources(pl022, false); + ret = pm_runtime_force_suspend(dev); + if (ret) { + spi_master_resume(pl022->master); + return ret; + } + + pinctrl_pm_select_sleep_state(dev); dev_dbg(dev, "suspended\n"); return 0; @@ -2329,8 +2306,9 @@ static int pl022_resume(struct device *dev) struct pl022 *pl022 = dev_get_drvdata(dev); int ret; - pl022_resume_resources(pl022, false); - pm_runtime_put(dev); + ret = pm_runtime_force_resume(dev); + if (ret) + dev_err(dev, "problem resuming\n"); /* Start the queue running */ ret = spi_master_resume(pl022->master); @@ -2341,14 +2319,16 @@ static int pl022_resume(struct device *dev) return ret; } -#endif /* CONFIG_PM */ +#endif #ifdef CONFIG_PM static int pl022_runtime_suspend(struct device *dev) { struct pl022 *pl022 = dev_get_drvdata(dev); - pl022_suspend_resources(pl022, true); + clk_disable_unprepare(pl022->clk); + pinctrl_pm_select_idle_state(dev); + return 0; } @@ -2356,7 +2336,9 @@ static int pl022_runtime_resume(struct device *dev) { struct pl022 *pl022 = dev_get_drvdata(dev); - pl022_resume_resources(pl022, true); + pinctrl_pm_select_default_state(dev); + clk_prepare_enable(pl022->clk); + return 0; } #endif -- cgit v1.2.1