summaryrefslogtreecommitdiff
path: root/patches.tizen/0330-ARM-EXYNOS-Add-support-for-firmware-assisted-suspend.patch
blob: fa13e116186c44db24c77b53d03d910574e41750 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
From ae053e0f8ffeb64f36bf220eb5d54cef4b734543 Mon Sep 17 00:00:00 2001
From: Tomasz Figa <t.figa@samsung.com>
Date: Thu, 21 Mar 2013 18:48:45 +0100
Subject: [PATCH 0330/1302] ARM: EXYNOS: Add support for firmware-assisted
 suspend/resume

This patch adds firmware ops related to system suspend/resume that
allows suspend/resume of systems with secure firmware.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
---
 arch/arm/include/asm/firmware.h | 12 ++++++++++++
 arch/arm/mach-exynos/firmware.c | 28 ++++++++++++++++++++++++++++
 arch/arm/mach-exynos/pm.c       |  9 +++++++--
 3 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/firmware.h b/arch/arm/include/asm/firmware.h
index 1563130..f459d25 100644
--- a/arch/arm/include/asm/firmware.h
+++ b/arch/arm/include/asm/firmware.h
@@ -37,6 +37,18 @@ struct firmware_ops {
 	 * Initializes L2 cache
 	 */
 	int (*l2x0_init)(void);
+	/*
+	 * Suspends the system
+	 */
+	int (*suspend)(unsigned long resume_addr);
+	/*
+	 * Acknowledges system resume
+	 */
+	int (*resume)(void);
+	/*
+	 * Restores coprocessor 15 registers
+	 */
+	int (*c15resume)(u32 *regs);
 };
 
 /* Global pointer for current firmware_ops structure, can't be NULL. */
diff --git a/arch/arm/mach-exynos/firmware.c b/arch/arm/mach-exynos/firmware.c
index da5fb26..3f98bf7 100644
--- a/arch/arm/mach-exynos/firmware.c
+++ b/arch/arm/mach-exynos/firmware.c
@@ -20,6 +20,8 @@
 
 #include "smc.h"
 
+#define EXYNOS_SLEEP_MAGIC	0x00000BAD
+
 static int exynos_do_idle(void)
 {
 	exynos_smc(SMC_CMD_SLEEP, 0, 0, 0);
@@ -47,11 +49,37 @@ static int exynos_l2x0_init(void)
 	return 0;
 }
 
+static int exynos_suspend(unsigned long resume_addr)
+{
+	writel(EXYNOS_SLEEP_MAGIC, S5P_VA_SYSRAM_NS + 0xC);
+	writel(resume_addr, S5P_VA_SYSRAM_NS + 0x8);
+	exynos_smc(SMC_CMD_SLEEP, 0, 0, 0);
+
+	return 0;
+}
+
+static int exynos_resume(void)
+{
+	writel(0, S5P_VA_SYSRAM_NS + 0xC);
+
+	return 0;
+}
+
+static int exynos_c15resume(u32 *regs)
+{
+	exynos_smc(SMC_CMD_C15RESUME, regs[0], regs[1], 0);
+
+	return 0;
+}
+
 static const struct firmware_ops exynos_firmware_ops = {
 	.do_idle		= exynos_do_idle,
 	.set_cpu_boot_addr	= exynos_set_cpu_boot_addr,
 	.cpu_boot		= exynos_cpu_boot,
 	.l2x0_init	= exynos_l2x0_init,
+	.suspend	= exynos_suspend,
+	.resume		= exynos_resume,
+	.c15resume	= exynos_c15resume,
 };
 
 void __init exynos_firmware_init(void)
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index 83c4999..e195e3e 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -36,6 +36,7 @@
 #include <mach/pm-core.h>
 
 #include "common.h"
+#include "smc.h"
 
 static struct sleep_save exynos4_set_clksrc[] = {
 	{ .reg = EXYNOS4_CLKSRC_MASK_TOP		, .val = 0x00000001, },
@@ -88,7 +89,8 @@ static int exynos_cpu_suspend(unsigned long arg)
 #endif
 
 	/* issue the standby signal into the pm unit. */
-	cpu_do_idle();
+	if (call_firmware_op(suspend, virt_to_phys(s3c_cpu_resume)) == -ENOSYS)
+		cpu_do_idle();
 
 	pr_info("Failed to suspend the system\n");
 	return 1; /* Aborting suspend */
@@ -286,7 +288,9 @@ static void exynos_pm_resume(void)
 		/* No need to perform below restore code */
 		goto early_wakeup;
 	}
-	if (!soc_is_exynos5250()) {
+	if (!soc_is_exynos5250()
+	    && call_firmware_op(c15resume, save_arm_register) == -ENOSYS)
+	{
 		/* Restore Power control register */
 		tmp = save_arm_register[0];
 		asm volatile ("mcr p15, 0, %0, c15, c0, 0"
@@ -328,6 +332,7 @@ early_wakeup:
 
 	/* Clear SLEEP mode set in INFORM1 */
 	__raw_writel(0x0, S5P_INFORM1);
+	call_firmware_op(resume);
 
 	return;
 }
-- 
1.8.3.2