From: Claudiu Beznea <claudiu.bez...@microchip.com> Add support to check if platform is off in suspend. The check is based on pm_data.mode and CPU's regulator which will be turn off in suspend.
Signed-off-by: Claudiu Beznea <claudiu.bez...@microchip.com> --- arch/arm/mach-at91/pm.c | 61 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 51e808adb00c..be9bd482772b 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -16,6 +16,7 @@ #include <linux/of.h> #include <linux/of_platform.h> #include <linux/parser.h> +#include <linux/regulator/consumer.h> #include <linux/suspend.h> #include <linux/clk/at91_pmc.h> @@ -164,6 +165,47 @@ static int at91_pm_config_ws(unsigned int pm_mode, bool set) return mode ? 0 : -EPERM; } +static const struct of_device_id sama5d2_cpu_reg_ids[] = { + { .compatible = "active-semi,act8945a", .data = "VDD_1V2" }, + { /* sentinel */ } +}; + +static struct regulator *at91_pm_cpu_regulator_get(void) +{ + struct device *cpu_dev = get_cpu_device(0); + static struct regulator *cpu_reg; + const struct of_device_id *match; + struct platform_device *pdev; + struct device_node *np; + + if (!cpu_dev) + return cpu_reg; + + if (!cpu_reg) { + for_each_matching_node_and_match(np, sama5d2_cpu_reg_ids, + &match) { + pdev = of_find_device_by_node(np); + if (!pdev) + continue; + + cpu_reg = regulator_get(cpu_dev, match->data); + put_device(&pdev->dev); + break; + } + } + + return cpu_reg; +} + +static bool at91_pm_state_allowed(suspend_state_t state) +{ + struct regulator *reg; + + reg = at91_pm_cpu_regulator_get(); + + return reg && regulator_is_disabled_in_suspend(reg, state); +} + /* * Called after processes are frozen, but before we shutdown devices. */ @@ -182,6 +224,9 @@ static int at91_pm_begin(suspend_state_t state) pm_data.mode = -1; } + if (pm_data.mode == AT91_PM_BACKUP && !at91_pm_state_allowed(state)) + return -EPERM; + return at91_pm_config_ws(pm_data.mode, true); } @@ -321,12 +366,20 @@ static void at91_pm_end(void) at91_pm_config_ws(pm_data.mode, false); } +static bool at91_pm_off_in_suspend(suspend_state_t state) +{ + if (pm_data.mode != AT91_PM_BACKUP) + return false; + + return at91_pm_state_allowed(state); +} static const struct platform_suspend_ops at91_pm_ops = { - .valid = at91_pm_valid_state, - .begin = at91_pm_begin, - .enter = at91_pm_enter, - .end = at91_pm_end, + .valid = at91_pm_valid_state, + .begin = at91_pm_begin, + .enter = at91_pm_enter, + .end = at91_pm_end, + .off_in_suspend = at91_pm_off_in_suspend, }; static struct platform_device at91_cpuidle_device = { -- 2.7.4