Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/mach-exynos4/pm.c
10817 views
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 <[email protected]>
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/syscore_ops.h>
20
#include <linux/io.h>
21
22
#include <asm/cacheflush.h>
23
#include <asm/hardware/cache-l2x0.h>
24
25
#include <plat/cpu.h>
26
#include <plat/pm.h>
27
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>
33
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, },
106
};
107
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, },
119
};
120
121
static struct sleep_save exynos4_core_save[] = {
122
/* CMU side */
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),
191
/* GIC side */
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),
230
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),
255
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),
262
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),
273
};
274
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),
281
};
282
283
void exynos4_cpu_suspend(void)
284
{
285
unsigned long tmp;
286
unsigned long mask = 0xFFFFFFFF;
287
288
/* Setting Central Sequence Register for power down mode */
289
290
tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
291
tmp &= ~(S5P_CENTRAL_LOWPWR_CFG);
292
__raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
293
294
/* Setting Central Sequence option Register */
295
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);
300
301
/* Clear all interrupt pending to avoid early wakeup */
302
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));
306
307
/* Disable all interrupt */
308
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));
313
314
outer_flush_all();
315
316
/* issue the standby signal into the pm unit. */
317
cpu_do_idle();
318
319
/* we should never get past here */
320
panic("sleep resumed to originator?");
321
}
322
323
static void exynos4_pm_prepare(void)
324
{
325
u32 tmp;
326
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));
329
330
tmp = __raw_readl(S5P_INFORM1);
331
332
/* Set value of power down register for sleep mode */
333
334
s3c_pm_do_restore_core(exynos4_sleep, ARRAY_SIZE(exynos4_sleep));
335
__raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
336
337
/* ensure at least INFORM0 has the resume address */
338
339
__raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0);
340
341
/* Before enter central sequence mode, clock src register have to set */
342
343
s3c_pm_do_restore_core(exynos4_set_clksrc, ARRAY_SIZE(exynos4_set_clksrc));
344
345
}
346
347
static int exynos4_pm_add(struct sys_device *sysdev)
348
{
349
pm_cpu_prep = exynos4_pm_prepare;
350
pm_cpu_sleep = exynos4_cpu_suspend;
351
352
return 0;
353
}
354
355
/* This function copy from linux/arch/arm/kernel/smp_scu.c */
356
357
void exynos4_scu_enable(void __iomem *scu_base)
358
{
359
u32 scu_ctrl;
360
361
scu_ctrl = __raw_readl(scu_base);
362
/* already enabled? */
363
if (scu_ctrl & 1)
364
return;
365
366
scu_ctrl |= 1;
367
__raw_writel(scu_ctrl, scu_base);
368
369
/*
370
* Ensure that the data accessed by CPU0 before the SCU was
371
* initialised is visible to the other CPUs.
372
*/
373
flush_cache_all();
374
}
375
376
static struct sysdev_driver exynos4_pm_driver = {
377
.add = exynos4_pm_add,
378
};
379
380
static __init int exynos4_pm_drvinit(void)
381
{
382
unsigned int tmp;
383
384
s3c_pm_init();
385
386
/* All wakeup disable */
387
388
tmp = __raw_readl(S5P_WAKEUP_MASK);
389
tmp |= ((0xFF << 8) | (0x1F << 1));
390
__raw_writel(tmp, S5P_WAKEUP_MASK);
391
392
return sysdev_driver_register(&exynos4_sysclass, &exynos4_pm_driver);
393
}
394
arch_initcall(exynos4_pm_drvinit);
395
396
static void exynos4_pm_resume(void)
397
{
398
/* For release retention */
399
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);
407
408
s3c_pm_do_restore_core(exynos4_core_save, ARRAY_SIZE(exynos4_core_save));
409
410
exynos4_scu_enable(S5P_VA_SCU);
411
412
#ifdef CONFIG_CACHE_L2X0
413
s3c_pm_do_restore_core(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save));
414
outer_inv_all();
415
/* enable L2X0*/
416
writel_relaxed(1, S5P_VA_L2CC + L2X0_CTRL);
417
#endif
418
}
419
420
static struct syscore_ops exynos4_pm_syscore_ops = {
421
.resume = exynos4_pm_resume,
422
};
423
424
static __init int exynos4_pm_syscore_init(void)
425
{
426
register_syscore_ops(&exynos4_pm_syscore_ops);
427
return 0;
428
}
429
arch_initcall(exynos4_pm_syscore_init);
430
431