aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>2014-09-25 04:59:41 -0400
committerKukjin Kim <kgene.kim@samsung.com>2014-10-20 11:06:36 -0400
commita135e20185fe6f0258fa6837455043f3063601d8 (patch)
tree001820cdbf32025e4bb147cdf3e048fb24cc75df
parent0b7778a801fde0eacd5ee08242290273507e60a2 (diff)
ARM: EXYNOS: add secure firmware support to AFTR mode code
* Move cp15 registers saving to exynos_save_cp15() helper and add additional helper usage to do_idle firmware method. * Use resume firmware method instead of exynos_cpu_restore_register() and skip exynos_cpu_save_register() on boards with secure firmware enabled. * Use sysram_ns_base_addr + 0x24/0x20 addresses instead of the default ones used by exynos_cpu_set_boot_vector() on boards with secure firmware enabled. * Use do_idle firmware method instead of cpu_do_idle() on boards with secure firmware enabled. Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Acked-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
-rw-r--r--arch/arm/mach-exynos/firmware.c24
-rw-r--r--arch/arm/mach-exynos/pm.c17
2 files changed, 29 insertions, 12 deletions
diff --git a/arch/arm/mach-exynos/firmware.c b/arch/arm/mach-exynos/firmware.c
index e57b7c3039a2..2c5bc6bfcbdf 100644
--- a/arch/arm/mach-exynos/firmware.c
+++ b/arch/arm/mach-exynos/firmware.c
@@ -25,13 +25,28 @@
25#include "smc.h" 25#include "smc.h"
26 26
27#define EXYNOS_SLEEP_MAGIC 0x00000bad 27#define EXYNOS_SLEEP_MAGIC 0x00000bad
28#define EXYNOS_AFTR_MAGIC 0xfcba0d10
28#define EXYNOS_BOOT_ADDR 0x8 29#define EXYNOS_BOOT_ADDR 0x8
29#define EXYNOS_BOOT_FLAG 0xc 30#define EXYNOS_BOOT_FLAG 0xc
30 31
32static void exynos_save_cp15(void)
33{
34 /* Save Power control and Diagnostic registers */
35 asm ("mrc p15, 0, %0, c15, c0, 0\n"
36 "mrc p15, 0, %1, c15, c0, 1\n"
37 : "=r" (cp15_save_power), "=r" (cp15_save_diag)
38 : : "cc");
39}
40
31static int exynos_do_idle(unsigned long mode) 41static int exynos_do_idle(unsigned long mode)
32{ 42{
33 switch (mode) { 43 switch (mode) {
34 case FW_DO_IDLE_AFTR: 44 case FW_DO_IDLE_AFTR:
45 if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
46 exynos_save_cp15();
47 __raw_writel(virt_to_phys(exynos_cpu_resume_ns),
48 sysram_ns_base_addr + 0x24);
49 __raw_writel(EXYNOS_AFTR_MAGIC, sysram_ns_base_addr + 0x20);
35 exynos_smc(SMC_CMD_CPU0AFTR, 0, 0, 0); 50 exynos_smc(SMC_CMD_CPU0AFTR, 0, 0, 0);
36 break; 51 break;
37 case FW_DO_IDLE_SLEEP: 52 case FW_DO_IDLE_SLEEP:
@@ -96,13 +111,8 @@ static int exynos_cpu_suspend(unsigned long arg)
96 111
97static int exynos_suspend(void) 112static int exynos_suspend(void)
98{ 113{
99 if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) { 114 if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
100 /* Save Power control and Diagnostic registers */ 115 exynos_save_cp15();
101 asm ("mrc p15, 0, %0, c15, c0, 0\n"
102 "mrc p15, 0, %1, c15, c0, 1\n"
103 : "=r" (cp15_save_power), "=r" (cp15_save_diag)
104 : : "cc");
105 }
106 116
107 writel(EXYNOS_SLEEP_MAGIC, sysram_ns_base_addr + EXYNOS_BOOT_FLAG); 117 writel(EXYNOS_SLEEP_MAGIC, sysram_ns_base_addr + EXYNOS_BOOT_FLAG);
108 writel(virt_to_phys(exynos_cpu_resume_ns), 118 writel(virt_to_phys(exynos_cpu_resume_ns),
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index 3407fc162449..6796fce923e2 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -236,11 +236,19 @@ static void exynos_cpu_set_boot_vector(long flags)
236 236
237static int exynos_aftr_finisher(unsigned long flags) 237static int exynos_aftr_finisher(unsigned long flags)
238{ 238{
239 int ret;
240
239 exynos_set_wakeupmask(0x0000ff3e); 241 exynos_set_wakeupmask(0x0000ff3e);
240 exynos_cpu_set_boot_vector(S5P_CHECK_AFTR);
241 /* Set value of power down register for aftr mode */ 242 /* Set value of power down register for aftr mode */
242 exynos_sys_powerdown_conf(SYS_AFTR); 243 exynos_sys_powerdown_conf(SYS_AFTR);
243 cpu_do_idle(); 244
245 ret = call_firmware_op(do_idle, FW_DO_IDLE_AFTR);
246 if (ret == -ENOSYS) {
247 if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
248 exynos_cpu_save_register();
249 exynos_cpu_set_boot_vector(S5P_CHECK_AFTR);
250 cpu_do_idle();
251 }
244 252
245 return 1; 253 return 1;
246} 254}
@@ -250,14 +258,13 @@ void exynos_enter_aftr(void)
250 cpu_pm_enter(); 258 cpu_pm_enter();
251 259
252 exynos_pm_central_suspend(); 260 exynos_pm_central_suspend();
253 if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
254 exynos_cpu_save_register();
255 261
256 cpu_suspend(0, exynos_aftr_finisher); 262 cpu_suspend(0, exynos_aftr_finisher);
257 263
258 if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) { 264 if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
259 scu_enable(S5P_VA_SCU); 265 scu_enable(S5P_VA_SCU);
260 exynos_cpu_restore_register(); 266 if (call_firmware_op(resume) == -ENOSYS)
267 exynos_cpu_restore_register();
261 } 268 }
262 269
263 exynos_pm_central_resume(); 270 exynos_pm_central_resume();