aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-exynos4/pm.c
diff options
context:
space:
mode:
authorJaecheol Lee <jc.lee@samsung.com>2011-03-09 23:33:59 -0500
committerKukjin Kim <kgene.kim@samsung.com>2011-03-11 20:18:24 -0500
commit1663895cb434b586d022d6414f03316469cf284d (patch)
tree3dc1c732836c82903973c270576aec2ac7ec4b51 /arch/arm/mach-exynos4/pm.c
parentb77ca655f343bf85578b24b1a3edfbc08336544c (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.c420
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
33static 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
107static 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
120static 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
274static 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
282void 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
322static 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
346static 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
356void 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
375static 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
401static struct sysdev_driver exynos4_pm_driver = {
402 .add = exynos4_pm_add,
403 .resume = exynos4_pm_resume,
404};
405
406static __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}
420arch_initcall(exynos4_pm_drvinit);