From: Tony Lindgren tony@atomide.com
stable inclusion from stable-5.10.53 commit ffa6f08be14acc511a8bdfaf70c66cfe3019edd3 bugzilla: 175574 https://gitee.com/openeuler/kernel/issues/I4DTUX
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
[ Upstream commit 093a474ce10d8ea3db3ef2922aca5a38f34bab1b ]
If the PM related modules are not loaded and PM firmware not configured, the system suspend fails to resume. Let's fix this by adding initial platform_suspend_ops to block suspend and warn about missing modules.
When pm33xx and wkup_m3_ipc have been loaded and m3 coprocessor booted with it's firmware, pm33xx sets up working platform_suspend_ops. Note that we need to configure at least PM_SUSPEND_STANDBY to have suspend_set_ops().
Cc: Dave Gerlach d-gerlach@ti.com Cc: Suman Anna s-anna@ti.com Signed-off-by: Tony Lindgren tony@atomide.com Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Chen Jun chenjun102@huawei.com Acked-by: Weilong Chen chenweilong@huawei.com Signed-off-by: Chen Jun chenjun102@huawei.com --- arch/arm/mach-omap2/pm33xx-core.c | 40 +++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)
diff --git a/arch/arm/mach-omap2/pm33xx-core.c b/arch/arm/mach-omap2/pm33xx-core.c index 56f2c0bcae5a..bf0d25fd2cea 100644 --- a/arch/arm/mach-omap2/pm33xx-core.c +++ b/arch/arm/mach-omap2/pm33xx-core.c @@ -8,6 +8,7 @@
#include <linux/cpuidle.h> #include <linux/platform_data/pm33xx.h> +#include <linux/suspend.h> #include <asm/cpuidle.h> #include <asm/smp_scu.h> #include <asm/suspend.h> @@ -324,6 +325,44 @@ static struct am33xx_pm_platform_data *am33xx_pm_get_pdata(void) return NULL; }
+#ifdef CONFIG_SUSPEND +/* + * Block system suspend initially. Later on pm33xx sets up it's own + * platform_suspend_ops after probe. That depends also on loaded + * wkup_m3_ipc and booted am335x-pm-firmware.elf. + */ +static int amx3_suspend_block(suspend_state_t state) +{ + pr_warn("PM not initialized for pm33xx, wkup_m3_ipc, or am335x-pm-firmware.elf\n"); + + return -EINVAL; +} + +static int amx3_pm_valid(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_STANDBY: + return 1; + default: + return 0; + } +} + +static const struct platform_suspend_ops amx3_blocked_pm_ops = { + .begin = amx3_suspend_block, + .valid = amx3_pm_valid, +}; + +static void __init amx3_block_suspend(void) +{ + suspend_set_ops(&amx3_blocked_pm_ops); +} +#else +static inline void amx3_block_suspend(void) +{ +} +#endif /* CONFIG_SUSPEND */ + int __init amx3_common_pm_init(void) { struct am33xx_pm_platform_data *pdata; @@ -337,6 +376,7 @@ int __init amx3_common_pm_init(void) devinfo.size_data = sizeof(*pdata); devinfo.id = -1; platform_device_register_full(&devinfo); + amx3_block_suspend();
return 0; }