aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGregory CLEMENT <gregory.clement@free-electrons.com>2015-07-03 07:55:51 -0400
committerGregory CLEMENT <gregory.clement@free-electrons.com>2015-07-25 11:17:05 -0400
commit3cbd6a6ca81c9e8438b592099495a7c2b72de9e3 (patch)
tree90ea439ced4bb70a3ebbde0de9faa077f8a15f65
parentbb253e743affa9d0053add8d3a1089df82f1c854 (diff)
ARM: mvebu: Add standby support
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>
-rw-r--r--arch/arm/mach-mvebu/common.h4
-rw-r--r--arch/arm/mach-mvebu/pm-board.c12
-rw-r--r--arch/arm/mach-mvebu/pm.c52
3 files changed, 56 insertions, 12 deletions
diff --git a/arch/arm/mach-mvebu/common.h b/arch/arm/mach-mvebu/common.h
index 3e0aca1f288a..6b775492cfad 100644
--- a/arch/arm/mach-mvebu/common.h
+++ b/arch/arm/mach-mvebu/common.h
@@ -25,6 +25,6 @@ int mvebu_system_controller_get_soc_id(u32 *dev, u32 *rev);
25 25
26void __iomem *mvebu_get_scu_base(void); 26void __iomem *mvebu_get_scu_base(void);
27 27
28int mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd)); 28int mvebu_pm_suspend_init(void (*board_pm_enter)(void __iomem *sdram_reg,
29 29 u32 srcmd));
30#endif 30#endif
diff --git a/arch/arm/mach-mvebu/pm-board.c b/arch/arm/mach-mvebu/pm-board.c
index 3ab06e7252c3..db17121d7d63 100644
--- a/arch/arm/mach-mvebu/pm-board.c
+++ b/arch/arm/mach-mvebu/pm-board.c
@@ -134,11 +134,19 @@ static int __init mvebu_armada_pm_init(void)
134 if (!gpio_ctrl) 134 if (!gpio_ctrl)
135 return -ENOMEM; 135 return -ENOMEM;
136 136
137 mvebu_pm_init(mvebu_armada_pm_enter); 137 mvebu_pm_suspend_init(mvebu_armada_pm_enter);
138 138
139out: 139out:
140 of_node_put(np); 140 of_node_put(np);
141 return ret; 141 return ret;
142} 142}
143 143
144late_initcall(mvebu_armada_pm_init); 144/*
145 * Registering the mvebu_board_pm_enter callback must be done before
146 * the platform_suspend_ops will be registered. In the same time we
147 * also need to have the gpio devices registered. That's why we use a
148 * device_initcall_sync which is called after all the device_initcall
149 * (used by the gpio device) but before the late_initcall (used to
150 * register the platform_suspend_ops)
151 */
152device_initcall_sync(mvebu_armada_pm_init);
diff --git a/arch/arm/mach-mvebu/pm.c b/arch/arm/mach-mvebu/pm.c
index ca94f07407f1..b058307088f3 100644
--- a/arch/arm/mach-mvebu/pm.c
+++ b/arch/arm/mach-mvebu/pm.c
@@ -163,13 +163,10 @@ static int mvebu_pm_store_bootinfo(void)
163 return 0; 163 return 0;
164} 164}
165 165
166static int mvebu_pm_enter(suspend_state_t state) 166static int mvebu_enter_suspend(void)
167{ 167{
168 int ret; 168 int ret;
169 169
170 if (state != PM_SUSPEND_MEM)
171 return -EINVAL;
172
173 ret = mvebu_pm_store_bootinfo(); 170 ret = mvebu_pm_store_bootinfo();
174 if (ret) 171 if (ret)
175 return ret; 172 return ret;
@@ -185,16 +182,57 @@ static int mvebu_pm_enter(suspend_state_t state)
185 set_cpu_coherent(); 182 set_cpu_coherent();
186 183
187 cpu_pm_exit(); 184 cpu_pm_exit();
185 return 0;
186}
187
188static int mvebu_pm_enter(suspend_state_t state)
189{
190 switch (state) {
191 case PM_SUSPEND_STANDBY:
192 cpu_do_idle();
193 break;
194 case PM_SUSPEND_MEM:
195 return mvebu_enter_suspend();
196 default:
197 return -EINVAL;
198 }
199 return 0;
200}
201
202static int mvebu_pm_valid(suspend_state_t state)
203{
204 if (state == PM_SUSPEND_STANDBY)
205 return 1;
206
207 if (state == PM_SUSPEND_MEM && mvebu_board_pm_enter != NULL)
208 return 1;
188 209
189 return 0; 210 return 0;
190} 211}
191 212
192static const struct platform_suspend_ops mvebu_pm_ops = { 213static const struct platform_suspend_ops mvebu_pm_ops = {
193 .enter = mvebu_pm_enter, 214 .enter = mvebu_pm_enter,
194 .valid = suspend_valid_only_mem, 215 .valid = mvebu_pm_valid,
195}; 216};
196 217
197int __init mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd)) 218static int __init mvebu_pm_init(void)
219{
220 if (!of_machine_is_compatible("marvell,armadaxp") &&
221 !of_machine_is_compatible("marvell,armada370") &&
222 !of_machine_is_compatible("marvell,armada380") &&
223 !of_machine_is_compatible("marvell,armada390"))
224 return -ENODEV;
225
226 suspend_set_ops(&mvebu_pm_ops);
227
228 return 0;
229}
230
231
232late_initcall(mvebu_pm_init);
233
234int __init mvebu_pm_suspend_init(void (*board_pm_enter)(void __iomem *sdram_reg,
235 u32 srcmd))
198{ 236{
199 struct device_node *np; 237 struct device_node *np;
200 struct resource res; 238 struct resource res;
@@ -226,7 +264,5 @@ int __init mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 src
226 264
227 mvebu_board_pm_enter = board_pm_enter; 265 mvebu_board_pm_enter = board_pm_enter;
228 266
229 suspend_set_ops(&mvebu_pm_ops);
230
231 return 0; 267 return 0;
232} 268}