aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkeita kobayashi <keita.kobayashi.ym@renesas.com>2014-05-29 03:24:27 -0400
committerSimon Horman <horms+renesas@verge.net.au>2014-06-17 06:32:06 -0400
commitd6d757c9a4e06e118fa5158fa74e03c514d862d2 (patch)
tree27c59bbe976a568cf6ee0daf81d89e98cf1ea6c1
parent5f6108bb9643949bf5ec0bc9f5cbde588c542c7f (diff)
ARM: shmobile: APMU: Add Core-Standby-state for Suspend to RAM
This patch add Core-Standby-state for Suspend to RAM. Signed-off-by: Keita Kobayashi <keita.kobayashi.ym@renesas.com> Acked-by: Magnus Damm <damm+renesas@opensource.se> [horms+renesas@verge.net.au: rebase] Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
-rw-r--r--arch/arm/mach-shmobile/common.h2
-rw-r--r--arch/arm/mach-shmobile/platsmp-apmu.c60
2 files changed, 58 insertions, 4 deletions
diff --git a/arch/arm/mach-shmobile/common.h b/arch/arm/mach-shmobile/common.h
index f7a360edcc35..8f0cd5791583 100644
--- a/arch/arm/mach-shmobile/common.h
+++ b/arch/arm/mach-shmobile/common.h
@@ -35,8 +35,10 @@ extern void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv);
35 35
36#ifdef CONFIG_SUSPEND 36#ifdef CONFIG_SUSPEND
37int shmobile_suspend_init(void); 37int shmobile_suspend_init(void);
38void shmobile_smp_apmu_suspend_init(void);
38#else 39#else
39static inline int shmobile_suspend_init(void) { return 0; } 40static inline int shmobile_suspend_init(void) { return 0; }
41static inline void shmobile_smp_apmu_suspend_init(void) { return 0; }
40#endif 42#endif
41 43
42#ifdef CONFIG_CPU_IDLE 44#ifdef CONFIG_CPU_IDLE
diff --git a/arch/arm/mach-shmobile/platsmp-apmu.c b/arch/arm/mach-shmobile/platsmp-apmu.c
index fe648f5d8f06..590e35c22a60 100644
--- a/arch/arm/mach-shmobile/platsmp-apmu.c
+++ b/arch/arm/mach-shmobile/platsmp-apmu.c
@@ -7,15 +7,19 @@
7 * it under the terms of the GNU General Public License version 2 as 7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. 8 * published by the Free Software Foundation.
9 */ 9 */
10#include <linux/cpu_pm.h>
10#include <linux/delay.h> 11#include <linux/delay.h>
11#include <linux/init.h> 12#include <linux/init.h>
12#include <linux/io.h> 13#include <linux/io.h>
13#include <linux/ioport.h> 14#include <linux/ioport.h>
14#include <linux/of_address.h> 15#include <linux/of_address.h>
15#include <linux/smp.h> 16#include <linux/smp.h>
17#include <linux/suspend.h>
16#include <asm/cacheflush.h> 18#include <asm/cacheflush.h>
17#include <asm/cp15.h> 19#include <asm/cp15.h>
20#include <asm/proc-fns.h>
18#include <asm/smp_plat.h> 21#include <asm/smp_plat.h>
22#include <asm/suspend.h>
19#include "common.h" 23#include "common.h"
20 24
21static struct { 25static struct {
@@ -141,7 +145,7 @@ int shmobile_smp_apmu_boot_secondary(unsigned int cpu, struct task_struct *idle)
141 return apmu_wrap(cpu, apmu_power_on); 145 return apmu_wrap(cpu, apmu_power_on);
142} 146}
143 147
144#ifdef CONFIG_HOTPLUG_CPU 148#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_SUSPEND)
145/* nicked from arch/arm/mach-exynos/hotplug.c */ 149/* nicked from arch/arm/mach-exynos/hotplug.c */
146static inline void cpu_enter_lowpower_a15(void) 150static inline void cpu_enter_lowpower_a15(void)
147{ 151{
@@ -172,16 +176,40 @@ static inline void cpu_enter_lowpower_a15(void)
172 dsb(); 176 dsb();
173} 177}
174 178
175void shmobile_smp_apmu_cpu_die(unsigned int cpu) 179void shmobile_smp_apmu_cpu_shutdown(unsigned int cpu)
176{ 180{
177 /* For this particular CPU deregister boot vector */
178 shmobile_smp_hook(cpu, 0, 0);
179 181
180 /* Select next sleep mode using the APMU */ 182 /* Select next sleep mode using the APMU */
181 apmu_wrap(cpu, apmu_power_off); 183 apmu_wrap(cpu, apmu_power_off);
182 184
183 /* Do ARM specific CPU shutdown */ 185 /* Do ARM specific CPU shutdown */
184 cpu_enter_lowpower_a15(); 186 cpu_enter_lowpower_a15();
187}
188
189static inline void cpu_leave_lowpower(void)
190{
191 unsigned int v;
192
193 asm volatile("mrc p15, 0, %0, c1, c0, 0\n"
194 " orr %0, %0, %1\n"
195 " mcr p15, 0, %0, c1, c0, 0\n"
196 " mrc p15, 0, %0, c1, c0, 1\n"
197 " orr %0, %0, %2\n"
198 " mcr p15, 0, %0, c1, c0, 1\n"
199 : "=&r" (v)
200 : "Ir" (CR_C), "Ir" (0x40)
201 : "cc");
202}
203#endif
204
205#if defined(CONFIG_HOTPLUG_CPU)
206void shmobile_smp_apmu_cpu_die(unsigned int cpu)
207{
208 /* For this particular CPU deregister boot vector */
209 shmobile_smp_hook(cpu, 0, 0);
210
211 /* Shutdown CPU core */
212 shmobile_smp_apmu_cpu_shutdown(cpu);
185 213
186 /* jump to shared mach-shmobile sleep / reset code */ 214 /* jump to shared mach-shmobile sleep / reset code */
187 shmobile_smp_sleep(); 215 shmobile_smp_sleep();
@@ -192,3 +220,27 @@ int shmobile_smp_apmu_cpu_kill(unsigned int cpu)
192 return apmu_wrap(cpu, apmu_power_off_poll); 220 return apmu_wrap(cpu, apmu_power_off_poll);
193} 221}
194#endif 222#endif
223
224#if defined(CONFIG_SUSPEND)
225static int shmobile_smp_apmu_do_suspend(unsigned long cpu)
226{
227 shmobile_smp_hook(cpu, virt_to_phys(cpu_resume), 0);
228 shmobile_smp_apmu_cpu_shutdown(cpu);
229 cpu_do_idle(); /* WFI selects Core Standby */
230 return 1;
231}
232
233static int shmobile_smp_apmu_enter_suspend(suspend_state_t state)
234{
235 cpu_suspend(smp_processor_id(), shmobile_smp_apmu_do_suspend);
236 cpu_leave_lowpower();
237 return 0;
238}
239
240void shmobile_smp_apmu_suspend_init(void)
241{
242 shmobile_suspend_ops.enter = shmobile_smp_apmu_enter_suspend;
243}
244#else
245void shmobile_smp_apmu_suspend_init(void) {}
246#endif