diff options
author | Jaecheol Lee <jc.lee@samsung.com> | 2011-03-09 23:33:59 -0500 |
---|---|---|
committer | Kukjin Kim <kgene.kim@samsung.com> | 2011-03-11 20:18:24 -0500 |
commit | 1663895cb434b586d022d6414f03316469cf284d (patch) | |
tree | 3dc1c732836c82903973c270576aec2ac7ec4b51 /arch/arm/mach-exynos4/pm.c | |
parent | b77ca655f343bf85578b24b1a3edfbc08336544c (diff) |
ARM: EXYNOS4: Suspend to RAM Support
This patch adds support suspend to ram for EXYNOS4210.
As a note, this includes function of outer cache flush
because it is used before entering PM.
Signed-off-by: Jaecheol Lee <jc.lee@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'arch/arm/mach-exynos4/pm.c')
-rw-r--r-- | arch/arm/mach-exynos4/pm.c | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/arch/arm/mach-exynos4/pm.c b/arch/arm/mach-exynos4/pm.c new file mode 100644 index 000000000000..10d917d9e3ad --- /dev/null +++ b/arch/arm/mach-exynos4/pm.c | |||
@@ -0,0 +1,420 @@ | |||
1 | /* linux/arch/arm/mach-exynos4/pm.c | ||
2 | * | ||
3 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * EXYNOS4210 - Power Management support | ||
7 | * | ||
8 | * Based on arch/arm/mach-s3c2410/pm.c | ||
9 | * Copyright (c) 2006 Simtec Electronics | ||
10 | * Ben Dooks <ben@simtec.co.uk> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | */ | ||
16 | |||
17 | #include <linux/init.h> | ||
18 | #include <linux/suspend.h> | ||
19 | #include <linux/io.h> | ||
20 | |||
21 | #include <asm/cacheflush.h> | ||
22 | #include <asm/hardware/cache-l2x0.h> | ||
23 | |||
24 | #include <plat/cpu.h> | ||
25 | #include <plat/pm.h> | ||
26 | |||
27 | #include <mach/regs-irq.h> | ||
28 | #include <mach/regs-gpio.h> | ||
29 | #include <mach/regs-clock.h> | ||
30 | #include <mach/regs-pmu.h> | ||
31 | #include <mach/pm-core.h> | ||
32 | |||
33 | static struct sleep_save exynos4_sleep[] = { | ||
34 | { .reg = S5P_ARM_CORE0_LOWPWR , .val = 0x2, }, | ||
35 | { .reg = S5P_DIS_IRQ_CORE0 , .val = 0x0, }, | ||
36 | { .reg = S5P_DIS_IRQ_CENTRAL0 , .val = 0x0, }, | ||
37 | { .reg = S5P_ARM_CORE1_LOWPWR , .val = 0x2, }, | ||
38 | { .reg = S5P_DIS_IRQ_CORE1 , .val = 0x0, }, | ||
39 | { .reg = S5P_DIS_IRQ_CENTRAL1 , .val = 0x0, }, | ||
40 | { .reg = S5P_ARM_COMMON_LOWPWR , .val = 0x2, }, | ||
41 | { .reg = S5P_L2_0_LOWPWR , .val = 0x3, }, | ||
42 | { .reg = S5P_L2_1_LOWPWR , .val = 0x3, }, | ||
43 | { .reg = S5P_CMU_ACLKSTOP_LOWPWR , .val = 0x0, }, | ||
44 | { .reg = S5P_CMU_SCLKSTOP_LOWPWR , .val = 0x0, }, | ||
45 | { .reg = S5P_CMU_RESET_LOWPWR , .val = 0x0, }, | ||
46 | { .reg = S5P_APLL_SYSCLK_LOWPWR , .val = 0x0, }, | ||
47 | { .reg = S5P_MPLL_SYSCLK_LOWPWR , .val = 0x0, }, | ||
48 | { .reg = S5P_VPLL_SYSCLK_LOWPWR , .val = 0x0, }, | ||
49 | { .reg = S5P_EPLL_SYSCLK_LOWPWR , .val = 0x0, }, | ||
50 | { .reg = S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR , .val = 0x0, }, | ||
51 | { .reg = S5P_CMU_RESET_GPSALIVE_LOWPWR , .val = 0x0, }, | ||
52 | { .reg = S5P_CMU_CLKSTOP_CAM_LOWPWR , .val = 0x0, }, | ||
53 | { .reg = S5P_CMU_CLKSTOP_TV_LOWPWR , .val = 0x0, }, | ||
54 | { .reg = S5P_CMU_CLKSTOP_MFC_LOWPWR , .val = 0x0, }, | ||
55 | { .reg = S5P_CMU_CLKSTOP_G3D_LOWPWR , .val = 0x0, }, | ||
56 | { .reg = S5P_CMU_CLKSTOP_LCD0_LOWPWR , .val = 0x0, }, | ||
57 | { .reg = S5P_CMU_CLKSTOP_LCD1_LOWPWR , .val = 0x0, }, | ||
58 | { .reg = S5P_CMU_CLKSTOP_MAUDIO_LOWPWR , .val = 0x0, }, | ||
59 | { .reg = S5P_CMU_CLKSTOP_GPS_LOWPWR , .val = 0x0, }, | ||
60 | { .reg = S5P_CMU_RESET_CAM_LOWPWR , .val = 0x0, }, | ||
61 | { .reg = S5P_CMU_RESET_TV_LOWPWR , .val = 0x0, }, | ||
62 | { .reg = S5P_CMU_RESET_MFC_LOWPWR , .val = 0x0, }, | ||
63 | { .reg = S5P_CMU_RESET_G3D_LOWPWR , .val = 0x0, }, | ||
64 | { .reg = S5P_CMU_RESET_LCD0_LOWPWR , .val = 0x0, }, | ||
65 | { .reg = S5P_CMU_RESET_LCD1_LOWPWR , .val = 0x0, }, | ||
66 | { .reg = S5P_CMU_RESET_MAUDIO_LOWPWR , .val = 0x0, }, | ||
67 | { .reg = S5P_CMU_RESET_GPS_LOWPWR , .val = 0x0, }, | ||
68 | { .reg = S5P_TOP_BUS_LOWPWR , .val = 0x0, }, | ||
69 | { .reg = S5P_TOP_RETENTION_LOWPWR , .val = 0x1, }, | ||
70 | { .reg = S5P_TOP_PWR_LOWPWR , .val = 0x3, }, | ||
71 | { .reg = S5P_LOGIC_RESET_LOWPWR , .val = 0x0, }, | ||
72 | { .reg = S5P_ONENAND_MEM_LOWPWR , .val = 0x0, }, | ||
73 | { .reg = S5P_MODIMIF_MEM_LOWPWR , .val = 0x0, }, | ||
74 | { .reg = S5P_G2D_ACP_MEM_LOWPWR , .val = 0x0, }, | ||
75 | { .reg = S5P_USBOTG_MEM_LOWPWR , .val = 0x0, }, | ||
76 | { .reg = S5P_HSMMC_MEM_LOWPWR , .val = 0x0, }, | ||
77 | { .reg = S5P_CSSYS_MEM_LOWPWR , .val = 0x0, }, | ||
78 | { .reg = S5P_SECSS_MEM_LOWPWR , .val = 0x0, }, | ||
79 | { .reg = S5P_PCIE_MEM_LOWPWR , .val = 0x0, }, | ||
80 | { .reg = S5P_SATA_MEM_LOWPWR , .val = 0x0, }, | ||
81 | { .reg = S5P_PAD_RETENTION_DRAM_LOWPWR , .val = 0x0, }, | ||
82 | { .reg = S5P_PAD_RETENTION_MAUDIO_LOWPWR , .val = 0x0, }, | ||
83 | { .reg = S5P_PAD_RETENTION_GPIO_LOWPWR , .val = 0x0, }, | ||
84 | { .reg = S5P_PAD_RETENTION_UART_LOWPWR , .val = 0x0, }, | ||
85 | { .reg = S5P_PAD_RETENTION_MMCA_LOWPWR , .val = 0x0, }, | ||
86 | { .reg = S5P_PAD_RETENTION_MMCB_LOWPWR , .val = 0x0, }, | ||
87 | { .reg = S5P_PAD_RETENTION_EBIA_LOWPWR , .val = 0x0, }, | ||
88 | { .reg = S5P_PAD_RETENTION_EBIB_LOWPWR , .val = 0x0, }, | ||
89 | { .reg = S5P_PAD_RETENTION_ISOLATION_LOWPWR , .val = 0x0, }, | ||
90 | { .reg = S5P_PAD_RETENTION_ALV_SEL_LOWPWR , .val = 0x0, }, | ||
91 | { .reg = S5P_XUSBXTI_LOWPWR , .val = 0x0, }, | ||
92 | { .reg = S5P_XXTI_LOWPWR , .val = 0x0, }, | ||
93 | { .reg = S5P_EXT_REGULATOR_LOWPWR , .val = 0x0, }, | ||
94 | { .reg = S5P_GPIO_MODE_LOWPWR , .val = 0x0, }, | ||
95 | { .reg = S5P_GPIO_MODE_MAUDIO_LOWPWR , .val = 0x0, }, | ||
96 | { .reg = S5P_CAM_LOWPWR , .val = 0x0, }, | ||
97 | { .reg = S5P_TV_LOWPWR , .val = 0x0, }, | ||
98 | { .reg = S5P_MFC_LOWPWR , .val = 0x0, }, | ||
99 | { .reg = S5P_G3D_LOWPWR , .val = 0x0, }, | ||
100 | { .reg = S5P_LCD0_LOWPWR , .val = 0x0, }, | ||
101 | { .reg = S5P_LCD1_LOWPWR , .val = 0x0, }, | ||
102 | { .reg = S5P_MAUDIO_LOWPWR , .val = 0x0, }, | ||
103 | { .reg = S5P_GPS_LOWPWR , .val = 0x0, }, | ||
104 | { .reg = S5P_GPS_ALIVE_LOWPWR , .val = 0x0, }, | ||
105 | }; | ||
106 | |||
107 | static struct sleep_save exynos4_set_clksrc[] = { | ||
108 | { .reg = S5P_CLKSRC_MASK_TOP , .val = 0x00000001, }, | ||
109 | { .reg = S5P_CLKSRC_MASK_CAM , .val = 0x11111111, }, | ||
110 | { .reg = S5P_CLKSRC_MASK_TV , .val = 0x00000111, }, | ||
111 | { .reg = S5P_CLKSRC_MASK_LCD0 , .val = 0x00001111, }, | ||
112 | { .reg = S5P_CLKSRC_MASK_LCD1 , .val = 0x00001111, }, | ||
113 | { .reg = S5P_CLKSRC_MASK_MAUDIO , .val = 0x00000001, }, | ||
114 | { .reg = S5P_CLKSRC_MASK_FSYS , .val = 0x01011111, }, | ||
115 | { .reg = S5P_CLKSRC_MASK_PERIL0 , .val = 0x01111111, }, | ||
116 | { .reg = S5P_CLKSRC_MASK_PERIL1 , .val = 0x01110111, }, | ||
117 | { .reg = S5P_CLKSRC_MASK_DMC , .val = 0x00010000, }, | ||
118 | }; | ||
119 | |||
120 | static struct sleep_save exynos4_core_save[] = { | ||
121 | /* CMU side */ | ||
122 | SAVE_ITEM(S5P_CLKDIV_LEFTBUS), | ||
123 | SAVE_ITEM(S5P_CLKGATE_IP_LEFTBUS), | ||
124 | SAVE_ITEM(S5P_CLKDIV_RIGHTBUS), | ||
125 | SAVE_ITEM(S5P_CLKGATE_IP_RIGHTBUS), | ||
126 | SAVE_ITEM(S5P_EPLL_CON0), | ||
127 | SAVE_ITEM(S5P_EPLL_CON1), | ||
128 | SAVE_ITEM(S5P_VPLL_CON0), | ||
129 | SAVE_ITEM(S5P_VPLL_CON1), | ||
130 | SAVE_ITEM(S5P_CLKSRC_TOP0), | ||
131 | SAVE_ITEM(S5P_CLKSRC_TOP1), | ||
132 | SAVE_ITEM(S5P_CLKSRC_CAM), | ||
133 | SAVE_ITEM(S5P_CLKSRC_MFC), | ||
134 | SAVE_ITEM(S5P_CLKSRC_IMAGE), | ||
135 | SAVE_ITEM(S5P_CLKSRC_LCD0), | ||
136 | SAVE_ITEM(S5P_CLKSRC_LCD1), | ||
137 | SAVE_ITEM(S5P_CLKSRC_MAUDIO), | ||
138 | SAVE_ITEM(S5P_CLKSRC_FSYS), | ||
139 | SAVE_ITEM(S5P_CLKSRC_PERIL0), | ||
140 | SAVE_ITEM(S5P_CLKSRC_PERIL1), | ||
141 | SAVE_ITEM(S5P_CLKDIV_CAM), | ||
142 | SAVE_ITEM(S5P_CLKDIV_TV), | ||
143 | SAVE_ITEM(S5P_CLKDIV_MFC), | ||
144 | SAVE_ITEM(S5P_CLKDIV_G3D), | ||
145 | SAVE_ITEM(S5P_CLKDIV_IMAGE), | ||
146 | SAVE_ITEM(S5P_CLKDIV_LCD0), | ||
147 | SAVE_ITEM(S5P_CLKDIV_LCD1), | ||
148 | SAVE_ITEM(S5P_CLKDIV_MAUDIO), | ||
149 | SAVE_ITEM(S5P_CLKDIV_FSYS0), | ||
150 | SAVE_ITEM(S5P_CLKDIV_FSYS1), | ||
151 | SAVE_ITEM(S5P_CLKDIV_FSYS2), | ||
152 | SAVE_ITEM(S5P_CLKDIV_FSYS3), | ||
153 | SAVE_ITEM(S5P_CLKDIV_PERIL0), | ||
154 | SAVE_ITEM(S5P_CLKDIV_PERIL1), | ||
155 | SAVE_ITEM(S5P_CLKDIV_PERIL2), | ||
156 | SAVE_ITEM(S5P_CLKDIV_PERIL3), | ||
157 | SAVE_ITEM(S5P_CLKDIV_PERIL4), | ||
158 | SAVE_ITEM(S5P_CLKDIV_PERIL5), | ||
159 | SAVE_ITEM(S5P_CLKDIV_TOP), | ||
160 | SAVE_ITEM(S5P_CLKSRC_MASK_CAM), | ||
161 | SAVE_ITEM(S5P_CLKSRC_MASK_TV), | ||
162 | SAVE_ITEM(S5P_CLKSRC_MASK_LCD0), | ||
163 | SAVE_ITEM(S5P_CLKSRC_MASK_LCD1), | ||
164 | SAVE_ITEM(S5P_CLKSRC_MASK_MAUDIO), | ||
165 | SAVE_ITEM(S5P_CLKSRC_MASK_FSYS), | ||
166 | SAVE_ITEM(S5P_CLKSRC_MASK_PERIL0), | ||
167 | SAVE_ITEM(S5P_CLKSRC_MASK_PERIL1), | ||
168 | SAVE_ITEM(S5P_CLKGATE_SCLKCAM), | ||
169 | SAVE_ITEM(S5P_CLKGATE_IP_CAM), | ||
170 | SAVE_ITEM(S5P_CLKGATE_IP_TV), | ||
171 | SAVE_ITEM(S5P_CLKGATE_IP_MFC), | ||
172 | SAVE_ITEM(S5P_CLKGATE_IP_G3D), | ||
173 | SAVE_ITEM(S5P_CLKGATE_IP_IMAGE), | ||
174 | SAVE_ITEM(S5P_CLKGATE_IP_LCD0), | ||
175 | SAVE_ITEM(S5P_CLKGATE_IP_LCD1), | ||
176 | SAVE_ITEM(S5P_CLKGATE_IP_FSYS), | ||
177 | SAVE_ITEM(S5P_CLKGATE_IP_GPS), | ||
178 | SAVE_ITEM(S5P_CLKGATE_IP_PERIL), | ||
179 | SAVE_ITEM(S5P_CLKGATE_IP_PERIR), | ||
180 | SAVE_ITEM(S5P_CLKGATE_BLOCK), | ||
181 | SAVE_ITEM(S5P_CLKSRC_MASK_DMC), | ||
182 | SAVE_ITEM(S5P_CLKSRC_DMC), | ||
183 | SAVE_ITEM(S5P_CLKDIV_DMC0), | ||
184 | SAVE_ITEM(S5P_CLKDIV_DMC1), | ||
185 | SAVE_ITEM(S5P_CLKGATE_IP_DMC), | ||
186 | SAVE_ITEM(S5P_CLKSRC_CPU), | ||
187 | SAVE_ITEM(S5P_CLKDIV_CPU), | ||
188 | SAVE_ITEM(S5P_CLKGATE_SCLKCPU), | ||
189 | SAVE_ITEM(S5P_CLKGATE_IP_CPU), | ||
190 | /* GIC side */ | ||
191 | SAVE_ITEM(S5P_VA_GIC_CPU + 0x000), | ||
192 | SAVE_ITEM(S5P_VA_GIC_CPU + 0x004), | ||
193 | SAVE_ITEM(S5P_VA_GIC_CPU + 0x008), | ||
194 | SAVE_ITEM(S5P_VA_GIC_CPU + 0x00C), | ||
195 | SAVE_ITEM(S5P_VA_GIC_CPU + 0x014), | ||
196 | SAVE_ITEM(S5P_VA_GIC_CPU + 0x018), | ||
197 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x000), | ||
198 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x004), | ||
199 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x100), | ||
200 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x104), | ||
201 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x108), | ||
202 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x300), | ||
203 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x304), | ||
204 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x308), | ||
205 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x400), | ||
206 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x404), | ||
207 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x408), | ||
208 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x40C), | ||
209 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x410), | ||
210 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x414), | ||
211 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x418), | ||
212 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x41C), | ||
213 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x420), | ||
214 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x424), | ||
215 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x428), | ||
216 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x42C), | ||
217 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x430), | ||
218 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x434), | ||
219 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x438), | ||
220 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x43C), | ||
221 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x440), | ||
222 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x444), | ||
223 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x448), | ||
224 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x44C), | ||
225 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x450), | ||
226 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x454), | ||
227 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x458), | ||
228 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x45C), | ||
229 | |||
230 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x800), | ||
231 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x804), | ||
232 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x808), | ||
233 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x80C), | ||
234 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x810), | ||
235 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x814), | ||
236 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x818), | ||
237 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x81C), | ||
238 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x820), | ||
239 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x824), | ||
240 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x828), | ||
241 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x82C), | ||
242 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x830), | ||
243 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x834), | ||
244 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x838), | ||
245 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x83C), | ||
246 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x840), | ||
247 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x844), | ||
248 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x848), | ||
249 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x84C), | ||
250 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x850), | ||
251 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x854), | ||
252 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x858), | ||
253 | SAVE_ITEM(S5P_VA_GIC_DIST + 0x85C), | ||
254 | |||
255 | SAVE_ITEM(S5P_VA_GIC_DIST + 0xC00), | ||
256 | SAVE_ITEM(S5P_VA_GIC_DIST + 0xC04), | ||
257 | SAVE_ITEM(S5P_VA_GIC_DIST + 0xC08), | ||
258 | SAVE_ITEM(S5P_VA_GIC_DIST + 0xC0C), | ||
259 | SAVE_ITEM(S5P_VA_GIC_DIST + 0xC10), | ||
260 | SAVE_ITEM(S5P_VA_GIC_DIST + 0xC14), | ||
261 | |||
262 | SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x000), | ||
263 | SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x010), | ||
264 | SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x020), | ||
265 | SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x030), | ||
266 | SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x040), | ||
267 | SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x050), | ||
268 | SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x060), | ||
269 | SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x070), | ||
270 | SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x080), | ||
271 | SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x090), | ||
272 | }; | ||
273 | |||
274 | static struct sleep_save exynos4_l2cc_save[] = { | ||
275 | SAVE_ITEM(S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL), | ||
276 | SAVE_ITEM(S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL), | ||
277 | SAVE_ITEM(S5P_VA_L2CC + L2X0_PREFETCH_CTRL), | ||
278 | SAVE_ITEM(S5P_VA_L2CC + L2X0_POWER_CTRL), | ||
279 | SAVE_ITEM(S5P_VA_L2CC + L2X0_AUX_CTRL), | ||
280 | }; | ||
281 | |||
282 | void exynos4_cpu_suspend(void) | ||
283 | { | ||
284 | unsigned long tmp; | ||
285 | unsigned long mask = 0xFFFFFFFF; | ||
286 | |||
287 | /* Setting Central Sequence Register for power down mode */ | ||
288 | |||
289 | tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION); | ||
290 | tmp &= ~(S5P_CENTRAL_LOWPWR_CFG); | ||
291 | __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION); | ||
292 | |||
293 | /* Setting Central Sequence option Register */ | ||
294 | |||
295 | tmp = __raw_readl(S5P_CENTRAL_SEQ_OPTION); | ||
296 | tmp &= ~(S5P_USE_MASK); | ||
297 | tmp |= S5P_USE_STANDBY_WFI0; | ||
298 | __raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION); | ||
299 | |||
300 | /* Clear all interrupt pending to avoid early wakeup */ | ||
301 | |||
302 | __raw_writel(mask, (S5P_VA_GIC_DIST + 0x280)); | ||
303 | __raw_writel(mask, (S5P_VA_GIC_DIST + 0x284)); | ||
304 | __raw_writel(mask, (S5P_VA_GIC_DIST + 0x288)); | ||
305 | |||
306 | /* Disable all interrupt */ | ||
307 | |||
308 | __raw_writel(0x0, (S5P_VA_GIC_CPU + 0x000)); | ||
309 | __raw_writel(0x0, (S5P_VA_GIC_DIST + 0x000)); | ||
310 | __raw_writel(mask, (S5P_VA_GIC_DIST + 0x184)); | ||
311 | __raw_writel(mask, (S5P_VA_GIC_DIST + 0x188)); | ||
312 | |||
313 | outer_flush_all(); | ||
314 | |||
315 | /* issue the standby signal into the pm unit. */ | ||
316 | cpu_do_idle(); | ||
317 | |||
318 | /* we should never get past here */ | ||
319 | panic("sleep resumed to originator?"); | ||
320 | } | ||
321 | |||
322 | static void exynos4_pm_prepare(void) | ||
323 | { | ||
324 | u32 tmp; | ||
325 | |||
326 | s3c_pm_do_save(exynos4_core_save, ARRAY_SIZE(exynos4_core_save)); | ||
327 | s3c_pm_do_save(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save)); | ||
328 | |||
329 | tmp = __raw_readl(S5P_INFORM1); | ||
330 | |||
331 | /* Set value of power down register for sleep mode */ | ||
332 | |||
333 | s3c_pm_do_restore_core(exynos4_sleep, ARRAY_SIZE(exynos4_sleep)); | ||
334 | __raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1); | ||
335 | |||
336 | /* ensure at least INFORM0 has the resume address */ | ||
337 | |||
338 | __raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0); | ||
339 | |||
340 | /* Before enter central sequence mode, clock src register have to set */ | ||
341 | |||
342 | s3c_pm_do_restore_core(exynos4_set_clksrc, ARRAY_SIZE(exynos4_set_clksrc)); | ||
343 | |||
344 | } | ||
345 | |||
346 | static int exynos4_pm_add(struct sys_device *sysdev) | ||
347 | { | ||
348 | pm_cpu_prep = exynos4_pm_prepare; | ||
349 | pm_cpu_sleep = exynos4_cpu_suspend; | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | /* This function copy from linux/arch/arm/kernel/smp_scu.c */ | ||
355 | |||
356 | void exynos4_scu_enable(void __iomem *scu_base) | ||
357 | { | ||
358 | u32 scu_ctrl; | ||
359 | |||
360 | scu_ctrl = __raw_readl(scu_base); | ||
361 | /* already enabled? */ | ||
362 | if (scu_ctrl & 1) | ||
363 | return; | ||
364 | |||
365 | scu_ctrl |= 1; | ||
366 | __raw_writel(scu_ctrl, scu_base); | ||
367 | |||
368 | /* | ||
369 | * Ensure that the data accessed by CPU0 before the SCU was | ||
370 | * initialised is visible to the other CPUs. | ||
371 | */ | ||
372 | flush_cache_all(); | ||
373 | } | ||
374 | |||
375 | static int exynos4_pm_resume(struct sys_device *dev) | ||
376 | { | ||
377 | /* For release retention */ | ||
378 | |||
379 | __raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION); | ||
380 | __raw_writel((1 << 28), S5P_PAD_RET_GPIO_OPTION); | ||
381 | __raw_writel((1 << 28), S5P_PAD_RET_UART_OPTION); | ||
382 | __raw_writel((1 << 28), S5P_PAD_RET_MMCA_OPTION); | ||
383 | __raw_writel((1 << 28), S5P_PAD_RET_MMCB_OPTION); | ||
384 | __raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION); | ||
385 | __raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION); | ||
386 | |||
387 | s3c_pm_do_restore_core(exynos4_core_save, ARRAY_SIZE(exynos4_core_save)); | ||
388 | |||
389 | exynos4_scu_enable(S5P_VA_SCU); | ||
390 | |||
391 | #ifdef CONFIG_CACHE_L2X0 | ||
392 | s3c_pm_do_restore_core(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save)); | ||
393 | outer_inv_all(); | ||
394 | /* enable L2X0*/ | ||
395 | writel_relaxed(1, S5P_VA_L2CC + L2X0_CTRL); | ||
396 | #endif | ||
397 | |||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | static struct sysdev_driver exynos4_pm_driver = { | ||
402 | .add = exynos4_pm_add, | ||
403 | .resume = exynos4_pm_resume, | ||
404 | }; | ||
405 | |||
406 | static __init int exynos4_pm_drvinit(void) | ||
407 | { | ||
408 | unsigned int tmp; | ||
409 | |||
410 | s3c_pm_init(); | ||
411 | |||
412 | /* All wakeup disable */ | ||
413 | |||
414 | tmp = __raw_readl(S5P_WAKEUP_MASK); | ||
415 | tmp |= ((0xFF << 8) | (0x1F << 1)); | ||
416 | __raw_writel(tmp, S5P_WAKEUP_MASK); | ||
417 | |||
418 | return sysdev_driver_register(&exynos4_sysclass, &exynos4_pm_driver); | ||
419 | } | ||
420 | arch_initcall(exynos4_pm_drvinit); | ||