ARM: OMAP2+: Block suspend for am3 and am4 if PM is not configured
authorTony Lindgren <tony@atomide.com>
Tue, 25 May 2021 09:33:11 +0000 (12:33 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 25 Jul 2021 12:36:15 +0000 (14:36 +0200)
[ 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>
arch/arm/mach-omap2/pm33xx-core.c

index 56f2c0b..bf0d25f 100644 (file)
@@ -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;
 }