ARM: mvebu: Add standby support
authorGregory CLEMENT <gregory.clement@free-electrons.com>
Fri, 3 Jul 2015 11:55:51 +0000 (13:55 +0200)
committerGregory CLEMENT <gregory.clement@free-electrons.com>
Sat, 25 Jul 2015 15:17:05 +0000 (17:17 +0200)
Until now only one Armada XP and one Armada 388 based board supported
suspend to ram. However, most of the recent mvebu SoCs can support the
standby mode. Unlike for the suspend to ram, nothing special has to be
done for these SoCs. This patch allows the system to use the standby
mode on Armada 370, 38x, 39x and XP SoCs. There are issues with the
Armada 375, and the support might be added (if possible) in a future
patch.

Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
arch/arm/mach-mvebu/common.h
arch/arm/mach-mvebu/pm-board.c
arch/arm/mach-mvebu/pm.c

index 3e0aca1f288aee526b9bb76c9538bb7040d1e076..6b775492cfadc07cb568fa77b5c753e0a06e76f0 100644 (file)
@@ -25,6 +25,6 @@ int mvebu_system_controller_get_soc_id(u32 *dev, u32 *rev);
 
 void __iomem *mvebu_get_scu_base(void);
 
-int mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd));
-
+int mvebu_pm_suspend_init(void (*board_pm_enter)(void __iomem *sdram_reg,
+                                                       u32 srcmd));
 #endif
index 3ab06e7252c3c5baf2b10e7669398bc3f69ba9dd..db17121d7d639ce6439b64941a082445593741c5 100644 (file)
@@ -134,11 +134,19 @@ static int __init mvebu_armada_pm_init(void)
        if (!gpio_ctrl)
                return -ENOMEM;
 
-       mvebu_pm_init(mvebu_armada_pm_enter);
+       mvebu_pm_suspend_init(mvebu_armada_pm_enter);
 
 out:
        of_node_put(np);
        return ret;
 }
 
-late_initcall(mvebu_armada_pm_init);
+/*
+ * Registering the mvebu_board_pm_enter callback must be done before
+ * the platform_suspend_ops will be registered. In the same time we
+ * also need to have the gpio devices registered. That's why we use a
+ * device_initcall_sync which is called after all the device_initcall
+ * (used by the gpio device) but before the late_initcall (used to
+ * register the platform_suspend_ops)
+ */
+device_initcall_sync(mvebu_armada_pm_init);
index ca94f07407f19d824eaf0154cb032a3368f7eaa5..b058307088f327b0441dba34222f109365199a03 100644 (file)
@@ -163,13 +163,10 @@ static int mvebu_pm_store_bootinfo(void)
        return 0;
 }
 
-static int mvebu_pm_enter(suspend_state_t state)
+static int mvebu_enter_suspend(void)
 {
        int ret;
 
-       if (state != PM_SUSPEND_MEM)
-               return -EINVAL;
-
        ret = mvebu_pm_store_bootinfo();
        if (ret)
                return ret;
@@ -185,16 +182,57 @@ static int mvebu_pm_enter(suspend_state_t state)
        set_cpu_coherent();
 
        cpu_pm_exit();
+       return 0;
+}
+
+static int mvebu_pm_enter(suspend_state_t state)
+{
+       switch (state) {
+       case PM_SUSPEND_STANDBY:
+               cpu_do_idle();
+               break;
+       case PM_SUSPEND_MEM:
+               return mvebu_enter_suspend();
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int mvebu_pm_valid(suspend_state_t state)
+{
+       if (state == PM_SUSPEND_STANDBY)
+               return 1;
+
+       if (state == PM_SUSPEND_MEM && mvebu_board_pm_enter != NULL)
+               return 1;
 
        return 0;
 }
 
 static const struct platform_suspend_ops mvebu_pm_ops = {
        .enter = mvebu_pm_enter,
-       .valid = suspend_valid_only_mem,
+       .valid = mvebu_pm_valid,
 };
 
-int __init mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd))
+static int __init mvebu_pm_init(void)
+{
+       if (!of_machine_is_compatible("marvell,armadaxp") &&
+           !of_machine_is_compatible("marvell,armada370") &&
+           !of_machine_is_compatible("marvell,armada380") &&
+           !of_machine_is_compatible("marvell,armada390"))
+               return -ENODEV;
+
+       suspend_set_ops(&mvebu_pm_ops);
+
+       return 0;
+}
+
+
+late_initcall(mvebu_pm_init);
+
+int __init mvebu_pm_suspend_init(void (*board_pm_enter)(void __iomem *sdram_reg,
+                                                       u32 srcmd))
 {
        struct device_node *np;
        struct resource res;
@@ -226,7 +264,5 @@ int __init mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 src
 
        mvebu_board_pm_enter = board_pm_enter;
 
-       suspend_set_ops(&mvebu_pm_ops);
-
        return 0;
 }