1 /* linux/arch/arm/mach-exynos4/pm.c
3 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
6 * EXYNOS4210 - Power Management support
8 * Based on arch/arm/mach-s3c2410/pm.c
9 * Copyright (c) 2006 Simtec Electronics
10 * Ben Dooks <ben@simtec.co.uk>
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.
17 #include <linux/init.h>
18 #include <linux/suspend.h>
19 #include <linux/syscore_ops.h>
22 #include <asm/cacheflush.h>
23 #include <asm/hardware/cache-l2x0.h>
28 #include <mach/regs-irq.h>
29 #include <mach/regs-gpio.h>
30 #include <mach/regs-clock.h>
31 #include <mach/regs-pmu.h>
32 #include <mach/pm-core.h>
34 static struct sleep_save exynos4_sleep
[] = {
35 { .reg
= S5P_ARM_CORE0_LOWPWR
, .val
= 0x2, },
36 { .reg
= S5P_DIS_IRQ_CORE0
, .val
= 0x0, },
37 { .reg
= S5P_DIS_IRQ_CENTRAL0
, .val
= 0x0, },
38 { .reg
= S5P_ARM_CORE1_LOWPWR
, .val
= 0x2, },
39 { .reg
= S5P_DIS_IRQ_CORE1
, .val
= 0x0, },
40 { .reg
= S5P_DIS_IRQ_CENTRAL1
, .val
= 0x0, },
41 { .reg
= S5P_ARM_COMMON_LOWPWR
, .val
= 0x2, },
42 { .reg
= S5P_L2_0_LOWPWR
, .val
= 0x3, },
43 { .reg
= S5P_L2_1_LOWPWR
, .val
= 0x3, },
44 { .reg
= S5P_CMU_ACLKSTOP_LOWPWR
, .val
= 0x0, },
45 { .reg
= S5P_CMU_SCLKSTOP_LOWPWR
, .val
= 0x0, },
46 { .reg
= S5P_CMU_RESET_LOWPWR
, .val
= 0x0, },
47 { .reg
= S5P_APLL_SYSCLK_LOWPWR
, .val
= 0x0, },
48 { .reg
= S5P_MPLL_SYSCLK_LOWPWR
, .val
= 0x0, },
49 { .reg
= S5P_VPLL_SYSCLK_LOWPWR
, .val
= 0x0, },
50 { .reg
= S5P_EPLL_SYSCLK_LOWPWR
, .val
= 0x0, },
51 { .reg
= S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR
, .val
= 0x0, },
52 { .reg
= S5P_CMU_RESET_GPSALIVE_LOWPWR
, .val
= 0x0, },
53 { .reg
= S5P_CMU_CLKSTOP_CAM_LOWPWR
, .val
= 0x0, },
54 { .reg
= S5P_CMU_CLKSTOP_TV_LOWPWR
, .val
= 0x0, },
55 { .reg
= S5P_CMU_CLKSTOP_MFC_LOWPWR
, .val
= 0x0, },
56 { .reg
= S5P_CMU_CLKSTOP_G3D_LOWPWR
, .val
= 0x0, },
57 { .reg
= S5P_CMU_CLKSTOP_LCD0_LOWPWR
, .val
= 0x0, },
58 { .reg
= S5P_CMU_CLKSTOP_LCD1_LOWPWR
, .val
= 0x0, },
59 { .reg
= S5P_CMU_CLKSTOP_MAUDIO_LOWPWR
, .val
= 0x0, },
60 { .reg
= S5P_CMU_CLKSTOP_GPS_LOWPWR
, .val
= 0x0, },
61 { .reg
= S5P_CMU_RESET_CAM_LOWPWR
, .val
= 0x0, },
62 { .reg
= S5P_CMU_RESET_TV_LOWPWR
, .val
= 0x0, },
63 { .reg
= S5P_CMU_RESET_MFC_LOWPWR
, .val
= 0x0, },
64 { .reg
= S5P_CMU_RESET_G3D_LOWPWR
, .val
= 0x0, },
65 { .reg
= S5P_CMU_RESET_LCD0_LOWPWR
, .val
= 0x0, },
66 { .reg
= S5P_CMU_RESET_LCD1_LOWPWR
, .val
= 0x0, },
67 { .reg
= S5P_CMU_RESET_MAUDIO_LOWPWR
, .val
= 0x0, },
68 { .reg
= S5P_CMU_RESET_GPS_LOWPWR
, .val
= 0x0, },
69 { .reg
= S5P_TOP_BUS_LOWPWR
, .val
= 0x0, },
70 { .reg
= S5P_TOP_RETENTION_LOWPWR
, .val
= 0x1, },
71 { .reg
= S5P_TOP_PWR_LOWPWR
, .val
= 0x3, },
72 { .reg
= S5P_LOGIC_RESET_LOWPWR
, .val
= 0x0, },
73 { .reg
= S5P_ONENAND_MEM_LOWPWR
, .val
= 0x0, },
74 { .reg
= S5P_MODIMIF_MEM_LOWPWR
, .val
= 0x0, },
75 { .reg
= S5P_G2D_ACP_MEM_LOWPWR
, .val
= 0x0, },
76 { .reg
= S5P_USBOTG_MEM_LOWPWR
, .val
= 0x0, },
77 { .reg
= S5P_HSMMC_MEM_LOWPWR
, .val
= 0x0, },
78 { .reg
= S5P_CSSYS_MEM_LOWPWR
, .val
= 0x0, },
79 { .reg
= S5P_SECSS_MEM_LOWPWR
, .val
= 0x0, },
80 { .reg
= S5P_PCIE_MEM_LOWPWR
, .val
= 0x0, },
81 { .reg
= S5P_SATA_MEM_LOWPWR
, .val
= 0x0, },
82 { .reg
= S5P_PAD_RETENTION_DRAM_LOWPWR
, .val
= 0x0, },
83 { .reg
= S5P_PAD_RETENTION_MAUDIO_LOWPWR
, .val
= 0x0, },
84 { .reg
= S5P_PAD_RETENTION_GPIO_LOWPWR
, .val
= 0x0, },
85 { .reg
= S5P_PAD_RETENTION_UART_LOWPWR
, .val
= 0x0, },
86 { .reg
= S5P_PAD_RETENTION_MMCA_LOWPWR
, .val
= 0x0, },
87 { .reg
= S5P_PAD_RETENTION_MMCB_LOWPWR
, .val
= 0x0, },
88 { .reg
= S5P_PAD_RETENTION_EBIA_LOWPWR
, .val
= 0x0, },
89 { .reg
= S5P_PAD_RETENTION_EBIB_LOWPWR
, .val
= 0x0, },
90 { .reg
= S5P_PAD_RETENTION_ISOLATION_LOWPWR
, .val
= 0x0, },
91 { .reg
= S5P_PAD_RETENTION_ALV_SEL_LOWPWR
, .val
= 0x0, },
92 { .reg
= S5P_XUSBXTI_LOWPWR
, .val
= 0x0, },
93 { .reg
= S5P_XXTI_LOWPWR
, .val
= 0x0, },
94 { .reg
= S5P_EXT_REGULATOR_LOWPWR
, .val
= 0x0, },
95 { .reg
= S5P_GPIO_MODE_LOWPWR
, .val
= 0x0, },
96 { .reg
= S5P_GPIO_MODE_MAUDIO_LOWPWR
, .val
= 0x0, },
97 { .reg
= S5P_CAM_LOWPWR
, .val
= 0x0, },
98 { .reg
= S5P_TV_LOWPWR
, .val
= 0x0, },
99 { .reg
= S5P_MFC_LOWPWR
, .val
= 0x0, },
100 { .reg
= S5P_G3D_LOWPWR
, .val
= 0x0, },
101 { .reg
= S5P_LCD0_LOWPWR
, .val
= 0x0, },
102 { .reg
= S5P_LCD1_LOWPWR
, .val
= 0x0, },
103 { .reg
= S5P_MAUDIO_LOWPWR
, .val
= 0x0, },
104 { .reg
= S5P_GPS_LOWPWR
, .val
= 0x0, },
105 { .reg
= S5P_GPS_ALIVE_LOWPWR
, .val
= 0x0, },
108 static struct sleep_save exynos4_set_clksrc
[] = {
109 { .reg
= S5P_CLKSRC_MASK_TOP
, .val
= 0x00000001, },
110 { .reg
= S5P_CLKSRC_MASK_CAM
, .val
= 0x11111111, },
111 { .reg
= S5P_CLKSRC_MASK_TV
, .val
= 0x00000111, },
112 { .reg
= S5P_CLKSRC_MASK_LCD0
, .val
= 0x00001111, },
113 { .reg
= S5P_CLKSRC_MASK_LCD1
, .val
= 0x00001111, },
114 { .reg
= S5P_CLKSRC_MASK_MAUDIO
, .val
= 0x00000001, },
115 { .reg
= S5P_CLKSRC_MASK_FSYS
, .val
= 0x01011111, },
116 { .reg
= S5P_CLKSRC_MASK_PERIL0
, .val
= 0x01111111, },
117 { .reg
= S5P_CLKSRC_MASK_PERIL1
, .val
= 0x01110111, },
118 { .reg
= S5P_CLKSRC_MASK_DMC
, .val
= 0x00010000, },
121 static struct sleep_save exynos4_core_save
[] = {
123 SAVE_ITEM(S5P_CLKDIV_LEFTBUS
),
124 SAVE_ITEM(S5P_CLKGATE_IP_LEFTBUS
),
125 SAVE_ITEM(S5P_CLKDIV_RIGHTBUS
),
126 SAVE_ITEM(S5P_CLKGATE_IP_RIGHTBUS
),
127 SAVE_ITEM(S5P_EPLL_CON0
),
128 SAVE_ITEM(S5P_EPLL_CON1
),
129 SAVE_ITEM(S5P_VPLL_CON0
),
130 SAVE_ITEM(S5P_VPLL_CON1
),
131 SAVE_ITEM(S5P_CLKSRC_TOP0
),
132 SAVE_ITEM(S5P_CLKSRC_TOP1
),
133 SAVE_ITEM(S5P_CLKSRC_CAM
),
134 SAVE_ITEM(S5P_CLKSRC_MFC
),
135 SAVE_ITEM(S5P_CLKSRC_IMAGE
),
136 SAVE_ITEM(S5P_CLKSRC_LCD0
),
137 SAVE_ITEM(S5P_CLKSRC_LCD1
),
138 SAVE_ITEM(S5P_CLKSRC_MAUDIO
),
139 SAVE_ITEM(S5P_CLKSRC_FSYS
),
140 SAVE_ITEM(S5P_CLKSRC_PERIL0
),
141 SAVE_ITEM(S5P_CLKSRC_PERIL1
),
142 SAVE_ITEM(S5P_CLKDIV_CAM
),
143 SAVE_ITEM(S5P_CLKDIV_TV
),
144 SAVE_ITEM(S5P_CLKDIV_MFC
),
145 SAVE_ITEM(S5P_CLKDIV_G3D
),
146 SAVE_ITEM(S5P_CLKDIV_IMAGE
),
147 SAVE_ITEM(S5P_CLKDIV_LCD0
),
148 SAVE_ITEM(S5P_CLKDIV_LCD1
),
149 SAVE_ITEM(S5P_CLKDIV_MAUDIO
),
150 SAVE_ITEM(S5P_CLKDIV_FSYS0
),
151 SAVE_ITEM(S5P_CLKDIV_FSYS1
),
152 SAVE_ITEM(S5P_CLKDIV_FSYS2
),
153 SAVE_ITEM(S5P_CLKDIV_FSYS3
),
154 SAVE_ITEM(S5P_CLKDIV_PERIL0
),
155 SAVE_ITEM(S5P_CLKDIV_PERIL1
),
156 SAVE_ITEM(S5P_CLKDIV_PERIL2
),
157 SAVE_ITEM(S5P_CLKDIV_PERIL3
),
158 SAVE_ITEM(S5P_CLKDIV_PERIL4
),
159 SAVE_ITEM(S5P_CLKDIV_PERIL5
),
160 SAVE_ITEM(S5P_CLKDIV_TOP
),
161 SAVE_ITEM(S5P_CLKSRC_MASK_CAM
),
162 SAVE_ITEM(S5P_CLKSRC_MASK_TV
),
163 SAVE_ITEM(S5P_CLKSRC_MASK_LCD0
),
164 SAVE_ITEM(S5P_CLKSRC_MASK_LCD1
),
165 SAVE_ITEM(S5P_CLKSRC_MASK_MAUDIO
),
166 SAVE_ITEM(S5P_CLKSRC_MASK_FSYS
),
167 SAVE_ITEM(S5P_CLKSRC_MASK_PERIL0
),
168 SAVE_ITEM(S5P_CLKSRC_MASK_PERIL1
),
169 SAVE_ITEM(S5P_CLKGATE_SCLKCAM
),
170 SAVE_ITEM(S5P_CLKGATE_IP_CAM
),
171 SAVE_ITEM(S5P_CLKGATE_IP_TV
),
172 SAVE_ITEM(S5P_CLKGATE_IP_MFC
),
173 SAVE_ITEM(S5P_CLKGATE_IP_G3D
),
174 SAVE_ITEM(S5P_CLKGATE_IP_IMAGE
),
175 SAVE_ITEM(S5P_CLKGATE_IP_LCD0
),
176 SAVE_ITEM(S5P_CLKGATE_IP_LCD1
),
177 SAVE_ITEM(S5P_CLKGATE_IP_FSYS
),
178 SAVE_ITEM(S5P_CLKGATE_IP_GPS
),
179 SAVE_ITEM(S5P_CLKGATE_IP_PERIL
),
180 SAVE_ITEM(S5P_CLKGATE_IP_PERIR
),
181 SAVE_ITEM(S5P_CLKGATE_BLOCK
),
182 SAVE_ITEM(S5P_CLKSRC_MASK_DMC
),
183 SAVE_ITEM(S5P_CLKSRC_DMC
),
184 SAVE_ITEM(S5P_CLKDIV_DMC0
),
185 SAVE_ITEM(S5P_CLKDIV_DMC1
),
186 SAVE_ITEM(S5P_CLKGATE_IP_DMC
),
187 SAVE_ITEM(S5P_CLKSRC_CPU
),
188 SAVE_ITEM(S5P_CLKDIV_CPU
),
189 SAVE_ITEM(S5P_CLKGATE_SCLKCPU
),
190 SAVE_ITEM(S5P_CLKGATE_IP_CPU
),
192 SAVE_ITEM(S5P_VA_GIC_CPU
+ 0x000),
193 SAVE_ITEM(S5P_VA_GIC_CPU
+ 0x004),
194 SAVE_ITEM(S5P_VA_GIC_CPU
+ 0x008),
195 SAVE_ITEM(S5P_VA_GIC_CPU
+ 0x00C),
196 SAVE_ITEM(S5P_VA_GIC_CPU
+ 0x014),
197 SAVE_ITEM(S5P_VA_GIC_CPU
+ 0x018),
198 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x000),
199 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x004),
200 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x100),
201 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x104),
202 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x108),
203 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x300),
204 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x304),
205 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x308),
206 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x400),
207 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x404),
208 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x408),
209 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x40C),
210 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x410),
211 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x414),
212 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x418),
213 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x41C),
214 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x420),
215 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x424),
216 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x428),
217 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x42C),
218 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x430),
219 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x434),
220 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x438),
221 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x43C),
222 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x440),
223 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x444),
224 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x448),
225 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x44C),
226 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x450),
227 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x454),
228 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x458),
229 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x45C),
231 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x800),
232 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x804),
233 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x808),
234 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x80C),
235 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x810),
236 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x814),
237 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x818),
238 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x81C),
239 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x820),
240 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x824),
241 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x828),
242 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x82C),
243 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x830),
244 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x834),
245 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x838),
246 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x83C),
247 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x840),
248 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x844),
249 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x848),
250 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x84C),
251 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x850),
252 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x854),
253 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x858),
254 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0x85C),
256 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0xC00),
257 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0xC04),
258 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0xC08),
259 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0xC0C),
260 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0xC10),
261 SAVE_ITEM(S5P_VA_GIC_DIST
+ 0xC14),
263 SAVE_ITEM(S5P_VA_COMBINER_BASE
+ 0x000),
264 SAVE_ITEM(S5P_VA_COMBINER_BASE
+ 0x010),
265 SAVE_ITEM(S5P_VA_COMBINER_BASE
+ 0x020),
266 SAVE_ITEM(S5P_VA_COMBINER_BASE
+ 0x030),
267 SAVE_ITEM(S5P_VA_COMBINER_BASE
+ 0x040),
268 SAVE_ITEM(S5P_VA_COMBINER_BASE
+ 0x050),
269 SAVE_ITEM(S5P_VA_COMBINER_BASE
+ 0x060),
270 SAVE_ITEM(S5P_VA_COMBINER_BASE
+ 0x070),
271 SAVE_ITEM(S5P_VA_COMBINER_BASE
+ 0x080),
272 SAVE_ITEM(S5P_VA_COMBINER_BASE
+ 0x090),
275 static struct sleep_save exynos4_l2cc_save
[] = {
276 SAVE_ITEM(S5P_VA_L2CC
+ L2X0_TAG_LATENCY_CTRL
),
277 SAVE_ITEM(S5P_VA_L2CC
+ L2X0_DATA_LATENCY_CTRL
),
278 SAVE_ITEM(S5P_VA_L2CC
+ L2X0_PREFETCH_CTRL
),
279 SAVE_ITEM(S5P_VA_L2CC
+ L2X0_POWER_CTRL
),
280 SAVE_ITEM(S5P_VA_L2CC
+ L2X0_AUX_CTRL
),
283 void exynos4_cpu_suspend(void)
286 unsigned long mask
= 0xFFFFFFFF;
288 /* Setting Central Sequence Register for power down mode */
290 tmp
= __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION
);
291 tmp
&= ~(S5P_CENTRAL_LOWPWR_CFG
);
292 __raw_writel(tmp
, S5P_CENTRAL_SEQ_CONFIGURATION
);
294 /* Setting Central Sequence option Register */
296 tmp
= __raw_readl(S5P_CENTRAL_SEQ_OPTION
);
297 tmp
&= ~(S5P_USE_MASK
);
298 tmp
|= S5P_USE_STANDBY_WFI0
;
299 __raw_writel(tmp
, S5P_CENTRAL_SEQ_OPTION
);
301 /* Clear all interrupt pending to avoid early wakeup */
303 __raw_writel(mask
, (S5P_VA_GIC_DIST
+ 0x280));
304 __raw_writel(mask
, (S5P_VA_GIC_DIST
+ 0x284));
305 __raw_writel(mask
, (S5P_VA_GIC_DIST
+ 0x288));
307 /* Disable all interrupt */
309 __raw_writel(0x0, (S5P_VA_GIC_CPU
+ 0x000));
310 __raw_writel(0x0, (S5P_VA_GIC_DIST
+ 0x000));
311 __raw_writel(mask
, (S5P_VA_GIC_DIST
+ 0x184));
312 __raw_writel(mask
, (S5P_VA_GIC_DIST
+ 0x188));
316 /* issue the standby signal into the pm unit. */
319 /* we should never get past here */
320 panic("sleep resumed to originator?");
323 static void exynos4_pm_prepare(void)
327 s3c_pm_do_save(exynos4_core_save
, ARRAY_SIZE(exynos4_core_save
));
328 s3c_pm_do_save(exynos4_l2cc_save
, ARRAY_SIZE(exynos4_l2cc_save
));
330 tmp
= __raw_readl(S5P_INFORM1
);
332 /* Set value of power down register for sleep mode */
334 s3c_pm_do_restore_core(exynos4_sleep
, ARRAY_SIZE(exynos4_sleep
));
335 __raw_writel(S5P_CHECK_SLEEP
, S5P_INFORM1
);
337 /* ensure at least INFORM0 has the resume address */
339 __raw_writel(virt_to_phys(s3c_cpu_resume
), S5P_INFORM0
);
341 /* Before enter central sequence mode, clock src register have to set */
343 s3c_pm_do_restore_core(exynos4_set_clksrc
, ARRAY_SIZE(exynos4_set_clksrc
));
347 static int exynos4_pm_add(struct sys_device
*sysdev
)
349 pm_cpu_prep
= exynos4_pm_prepare
;
350 pm_cpu_sleep
= exynos4_cpu_suspend
;
355 /* This function copy from linux/arch/arm/kernel/smp_scu.c */
357 void exynos4_scu_enable(void __iomem
*scu_base
)
361 scu_ctrl
= __raw_readl(scu_base
);
362 /* already enabled? */
367 __raw_writel(scu_ctrl
, scu_base
);
370 * Ensure that the data accessed by CPU0 before the SCU was
371 * initialised is visible to the other CPUs.
376 static struct sysdev_driver exynos4_pm_driver
= {
377 .add
= exynos4_pm_add
,
380 static __init
int exynos4_pm_drvinit(void)
386 /* All wakeup disable */
388 tmp
= __raw_readl(S5P_WAKEUP_MASK
);
389 tmp
|= ((0xFF << 8) | (0x1F << 1));
390 __raw_writel(tmp
, S5P_WAKEUP_MASK
);
392 return sysdev_driver_register(&exynos4_sysclass
, &exynos4_pm_driver
);
394 arch_initcall(exynos4_pm_drvinit
);
396 static void exynos4_pm_resume(void)
398 /* For release retention */
400 __raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION
);
401 __raw_writel((1 << 28), S5P_PAD_RET_GPIO_OPTION
);
402 __raw_writel((1 << 28), S5P_PAD_RET_UART_OPTION
);
403 __raw_writel((1 << 28), S5P_PAD_RET_MMCA_OPTION
);
404 __raw_writel((1 << 28), S5P_PAD_RET_MMCB_OPTION
);
405 __raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION
);
406 __raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION
);
408 s3c_pm_do_restore_core(exynos4_core_save
, ARRAY_SIZE(exynos4_core_save
));
410 exynos4_scu_enable(S5P_VA_SCU
);
412 #ifdef CONFIG_CACHE_L2X0
413 s3c_pm_do_restore_core(exynos4_l2cc_save
, ARRAY_SIZE(exynos4_l2cc_save
));
416 writel_relaxed(1, S5P_VA_L2CC
+ L2X0_CTRL
);
420 static struct syscore_ops exynos4_pm_syscore_ops
= {
421 .resume
= exynos4_pm_resume
,
424 static __init
int exynos4_pm_syscore_init(void)
426 register_syscore_ops(&exynos4_pm_syscore_ops
);
429 arch_initcall(exynos4_pm_syscore_init
);