提交 d6d757c9 编写于 作者: K keita kobayashi 提交者: Simon Horman

ARM: shmobile: APMU: Add Core-Standby-state for Suspend to RAM

This patch add Core-Standby-state for Suspend to RAM.
Signed-off-by: NKeita Kobayashi <keita.kobayashi.ym@renesas.com>
Acked-by: NMagnus Damm <damm+renesas@opensource.se>
[horms+renesas@verge.net.au: rebase]
Signed-off-by: NSimon Horman <horms+renesas@verge.net.au>
上级 5f6108bb
...@@ -35,8 +35,10 @@ extern void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv); ...@@ -35,8 +35,10 @@ extern void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv);
#ifdef CONFIG_SUSPEND #ifdef CONFIG_SUSPEND
int shmobile_suspend_init(void); int shmobile_suspend_init(void);
void shmobile_smp_apmu_suspend_init(void);
#else #else
static inline int shmobile_suspend_init(void) { return 0; } static inline int shmobile_suspend_init(void) { return 0; }
static inline void shmobile_smp_apmu_suspend_init(void) { return 0; }
#endif #endif
#ifdef CONFIG_CPU_IDLE #ifdef CONFIG_CPU_IDLE
......
...@@ -7,15 +7,19 @@ ...@@ -7,15 +7,19 @@
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <linux/cpu_pm.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/suspend.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/cp15.h> #include <asm/cp15.h>
#include <asm/proc-fns.h>
#include <asm/smp_plat.h> #include <asm/smp_plat.h>
#include <asm/suspend.h>
#include "common.h" #include "common.h"
static struct { static struct {
...@@ -141,7 +145,7 @@ int shmobile_smp_apmu_boot_secondary(unsigned int cpu, struct task_struct *idle) ...@@ -141,7 +145,7 @@ int shmobile_smp_apmu_boot_secondary(unsigned int cpu, struct task_struct *idle)
return apmu_wrap(cpu, apmu_power_on); return apmu_wrap(cpu, apmu_power_on);
} }
#ifdef CONFIG_HOTPLUG_CPU #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_SUSPEND)
/* nicked from arch/arm/mach-exynos/hotplug.c */ /* nicked from arch/arm/mach-exynos/hotplug.c */
static inline void cpu_enter_lowpower_a15(void) static inline void cpu_enter_lowpower_a15(void)
{ {
...@@ -172,16 +176,40 @@ static inline void cpu_enter_lowpower_a15(void) ...@@ -172,16 +176,40 @@ static inline void cpu_enter_lowpower_a15(void)
dsb(); dsb();
} }
void shmobile_smp_apmu_cpu_die(unsigned int cpu) void shmobile_smp_apmu_cpu_shutdown(unsigned int cpu)
{ {
/* For this particular CPU deregister boot vector */
shmobile_smp_hook(cpu, 0, 0);
/* Select next sleep mode using the APMU */ /* Select next sleep mode using the APMU */
apmu_wrap(cpu, apmu_power_off); apmu_wrap(cpu, apmu_power_off);
/* Do ARM specific CPU shutdown */ /* Do ARM specific CPU shutdown */
cpu_enter_lowpower_a15(); cpu_enter_lowpower_a15();
}
static inline void cpu_leave_lowpower(void)
{
unsigned int v;
asm volatile("mrc p15, 0, %0, c1, c0, 0\n"
" orr %0, %0, %1\n"
" mcr p15, 0, %0, c1, c0, 0\n"
" mrc p15, 0, %0, c1, c0, 1\n"
" orr %0, %0, %2\n"
" mcr p15, 0, %0, c1, c0, 1\n"
: "=&r" (v)
: "Ir" (CR_C), "Ir" (0x40)
: "cc");
}
#endif
#if defined(CONFIG_HOTPLUG_CPU)
void shmobile_smp_apmu_cpu_die(unsigned int cpu)
{
/* For this particular CPU deregister boot vector */
shmobile_smp_hook(cpu, 0, 0);
/* Shutdown CPU core */
shmobile_smp_apmu_cpu_shutdown(cpu);
/* jump to shared mach-shmobile sleep / reset code */ /* jump to shared mach-shmobile sleep / reset code */
shmobile_smp_sleep(); shmobile_smp_sleep();
...@@ -192,3 +220,27 @@ int shmobile_smp_apmu_cpu_kill(unsigned int cpu) ...@@ -192,3 +220,27 @@ int shmobile_smp_apmu_cpu_kill(unsigned int cpu)
return apmu_wrap(cpu, apmu_power_off_poll); return apmu_wrap(cpu, apmu_power_off_poll);
} }
#endif #endif
#if defined(CONFIG_SUSPEND)
static int shmobile_smp_apmu_do_suspend(unsigned long cpu)
{
shmobile_smp_hook(cpu, virt_to_phys(cpu_resume), 0);
shmobile_smp_apmu_cpu_shutdown(cpu);
cpu_do_idle(); /* WFI selects Core Standby */
return 1;
}
static int shmobile_smp_apmu_enter_suspend(suspend_state_t state)
{
cpu_suspend(smp_processor_id(), shmobile_smp_apmu_do_suspend);
cpu_leave_lowpower();
return 0;
}
void shmobile_smp_apmu_suspend_init(void)
{
shmobile_suspend_ops.enter = shmobile_smp_apmu_enter_suspend;
}
#else
void shmobile_smp_apmu_suspend_init(void) {}
#endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册