ARM: EXYNOS4: Remove PMU configuration for S2RAM
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-exynos4 / pm.c
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/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 #include <mach/pmu.h>
34
35 static struct sleep_save exynos4_set_clksrc[] = {
36         { .reg = S5P_CLKSRC_MASK_TOP                    , .val = 0x00000001, },
37         { .reg = S5P_CLKSRC_MASK_CAM                    , .val = 0x11111111, },
38         { .reg = S5P_CLKSRC_MASK_TV                     , .val = 0x00000111, },
39         { .reg = S5P_CLKSRC_MASK_LCD0                   , .val = 0x00001111, },
40         { .reg = S5P_CLKSRC_MASK_LCD1                   , .val = 0x00001111, },
41         { .reg = S5P_CLKSRC_MASK_MAUDIO                 , .val = 0x00000001, },
42         { .reg = S5P_CLKSRC_MASK_FSYS                   , .val = 0x01011111, },
43         { .reg = S5P_CLKSRC_MASK_PERIL0                 , .val = 0x01111111, },
44         { .reg = S5P_CLKSRC_MASK_PERIL1                 , .val = 0x01110111, },
45         { .reg = S5P_CLKSRC_MASK_DMC                    , .val = 0x00010000, },
46 };
47
48 static struct sleep_save exynos4_core_save[] = {
49         /* CMU side */
50         SAVE_ITEM(S5P_CLKDIV_LEFTBUS),
51         SAVE_ITEM(S5P_CLKGATE_IP_LEFTBUS),
52         SAVE_ITEM(S5P_CLKDIV_RIGHTBUS),
53         SAVE_ITEM(S5P_CLKGATE_IP_RIGHTBUS),
54         SAVE_ITEM(S5P_EPLL_CON0),
55         SAVE_ITEM(S5P_EPLL_CON1),
56         SAVE_ITEM(S5P_VPLL_CON0),
57         SAVE_ITEM(S5P_VPLL_CON1),
58         SAVE_ITEM(S5P_CLKSRC_TOP0),
59         SAVE_ITEM(S5P_CLKSRC_TOP1),
60         SAVE_ITEM(S5P_CLKSRC_CAM),
61         SAVE_ITEM(S5P_CLKSRC_MFC),
62         SAVE_ITEM(S5P_CLKSRC_IMAGE),
63         SAVE_ITEM(S5P_CLKSRC_LCD0),
64         SAVE_ITEM(S5P_CLKSRC_LCD1),
65         SAVE_ITEM(S5P_CLKSRC_MAUDIO),
66         SAVE_ITEM(S5P_CLKSRC_FSYS),
67         SAVE_ITEM(S5P_CLKSRC_PERIL0),
68         SAVE_ITEM(S5P_CLKSRC_PERIL1),
69         SAVE_ITEM(S5P_CLKDIV_CAM),
70         SAVE_ITEM(S5P_CLKDIV_TV),
71         SAVE_ITEM(S5P_CLKDIV_MFC),
72         SAVE_ITEM(S5P_CLKDIV_G3D),
73         SAVE_ITEM(S5P_CLKDIV_IMAGE),
74         SAVE_ITEM(S5P_CLKDIV_LCD0),
75         SAVE_ITEM(S5P_CLKDIV_LCD1),
76         SAVE_ITEM(S5P_CLKDIV_MAUDIO),
77         SAVE_ITEM(S5P_CLKDIV_FSYS0),
78         SAVE_ITEM(S5P_CLKDIV_FSYS1),
79         SAVE_ITEM(S5P_CLKDIV_FSYS2),
80         SAVE_ITEM(S5P_CLKDIV_FSYS3),
81         SAVE_ITEM(S5P_CLKDIV_PERIL0),
82         SAVE_ITEM(S5P_CLKDIV_PERIL1),
83         SAVE_ITEM(S5P_CLKDIV_PERIL2),
84         SAVE_ITEM(S5P_CLKDIV_PERIL3),
85         SAVE_ITEM(S5P_CLKDIV_PERIL4),
86         SAVE_ITEM(S5P_CLKDIV_PERIL5),
87         SAVE_ITEM(S5P_CLKDIV_TOP),
88         SAVE_ITEM(S5P_CLKSRC_MASK_CAM),
89         SAVE_ITEM(S5P_CLKSRC_MASK_TV),
90         SAVE_ITEM(S5P_CLKSRC_MASK_LCD0),
91         SAVE_ITEM(S5P_CLKSRC_MASK_LCD1),
92         SAVE_ITEM(S5P_CLKSRC_MASK_MAUDIO),
93         SAVE_ITEM(S5P_CLKSRC_MASK_FSYS),
94         SAVE_ITEM(S5P_CLKSRC_MASK_PERIL0),
95         SAVE_ITEM(S5P_CLKSRC_MASK_PERIL1),
96         SAVE_ITEM(S5P_CLKGATE_SCLKCAM),
97         SAVE_ITEM(S5P_CLKGATE_IP_CAM),
98         SAVE_ITEM(S5P_CLKGATE_IP_TV),
99         SAVE_ITEM(S5P_CLKGATE_IP_MFC),
100         SAVE_ITEM(S5P_CLKGATE_IP_G3D),
101         SAVE_ITEM(S5P_CLKGATE_IP_IMAGE),
102         SAVE_ITEM(S5P_CLKGATE_IP_LCD0),
103         SAVE_ITEM(S5P_CLKGATE_IP_LCD1),
104         SAVE_ITEM(S5P_CLKGATE_IP_FSYS),
105         SAVE_ITEM(S5P_CLKGATE_IP_GPS),
106         SAVE_ITEM(S5P_CLKGATE_IP_PERIL),
107         SAVE_ITEM(S5P_CLKGATE_IP_PERIR),
108         SAVE_ITEM(S5P_CLKGATE_BLOCK),
109         SAVE_ITEM(S5P_CLKSRC_MASK_DMC),
110         SAVE_ITEM(S5P_CLKSRC_DMC),
111         SAVE_ITEM(S5P_CLKDIV_DMC0),
112         SAVE_ITEM(S5P_CLKDIV_DMC1),
113         SAVE_ITEM(S5P_CLKGATE_IP_DMC),
114         SAVE_ITEM(S5P_CLKSRC_CPU),
115         SAVE_ITEM(S5P_CLKDIV_CPU),
116         SAVE_ITEM(S5P_CLKGATE_SCLKCPU),
117         SAVE_ITEM(S5P_CLKGATE_IP_CPU),
118         /* GIC side */
119         SAVE_ITEM(S5P_VA_GIC_CPU + 0x000),
120         SAVE_ITEM(S5P_VA_GIC_CPU + 0x004),
121         SAVE_ITEM(S5P_VA_GIC_CPU + 0x008),
122         SAVE_ITEM(S5P_VA_GIC_CPU + 0x00C),
123         SAVE_ITEM(S5P_VA_GIC_CPU + 0x014),
124         SAVE_ITEM(S5P_VA_GIC_CPU + 0x018),
125         SAVE_ITEM(S5P_VA_GIC_DIST + 0x000),
126         SAVE_ITEM(S5P_VA_GIC_DIST + 0x004),
127         SAVE_ITEM(S5P_VA_GIC_DIST + 0x100),
128         SAVE_ITEM(S5P_VA_GIC_DIST + 0x104),
129         SAVE_ITEM(S5P_VA_GIC_DIST + 0x108),
130         SAVE_ITEM(S5P_VA_GIC_DIST + 0x300),
131         SAVE_ITEM(S5P_VA_GIC_DIST + 0x304),
132         SAVE_ITEM(S5P_VA_GIC_DIST + 0x308),
133         SAVE_ITEM(S5P_VA_GIC_DIST + 0x400),
134         SAVE_ITEM(S5P_VA_GIC_DIST + 0x404),
135         SAVE_ITEM(S5P_VA_GIC_DIST + 0x408),
136         SAVE_ITEM(S5P_VA_GIC_DIST + 0x40C),
137         SAVE_ITEM(S5P_VA_GIC_DIST + 0x410),
138         SAVE_ITEM(S5P_VA_GIC_DIST + 0x414),
139         SAVE_ITEM(S5P_VA_GIC_DIST + 0x418),
140         SAVE_ITEM(S5P_VA_GIC_DIST + 0x41C),
141         SAVE_ITEM(S5P_VA_GIC_DIST + 0x420),
142         SAVE_ITEM(S5P_VA_GIC_DIST + 0x424),
143         SAVE_ITEM(S5P_VA_GIC_DIST + 0x428),
144         SAVE_ITEM(S5P_VA_GIC_DIST + 0x42C),
145         SAVE_ITEM(S5P_VA_GIC_DIST + 0x430),
146         SAVE_ITEM(S5P_VA_GIC_DIST + 0x434),
147         SAVE_ITEM(S5P_VA_GIC_DIST + 0x438),
148         SAVE_ITEM(S5P_VA_GIC_DIST + 0x43C),
149         SAVE_ITEM(S5P_VA_GIC_DIST + 0x440),
150         SAVE_ITEM(S5P_VA_GIC_DIST + 0x444),
151         SAVE_ITEM(S5P_VA_GIC_DIST + 0x448),
152         SAVE_ITEM(S5P_VA_GIC_DIST + 0x44C),
153         SAVE_ITEM(S5P_VA_GIC_DIST + 0x450),
154         SAVE_ITEM(S5P_VA_GIC_DIST + 0x454),
155         SAVE_ITEM(S5P_VA_GIC_DIST + 0x458),
156         SAVE_ITEM(S5P_VA_GIC_DIST + 0x45C),
157
158         SAVE_ITEM(S5P_VA_GIC_DIST + 0x800),
159         SAVE_ITEM(S5P_VA_GIC_DIST + 0x804),
160         SAVE_ITEM(S5P_VA_GIC_DIST + 0x808),
161         SAVE_ITEM(S5P_VA_GIC_DIST + 0x80C),
162         SAVE_ITEM(S5P_VA_GIC_DIST + 0x810),
163         SAVE_ITEM(S5P_VA_GIC_DIST + 0x814),
164         SAVE_ITEM(S5P_VA_GIC_DIST + 0x818),
165         SAVE_ITEM(S5P_VA_GIC_DIST + 0x81C),
166         SAVE_ITEM(S5P_VA_GIC_DIST + 0x820),
167         SAVE_ITEM(S5P_VA_GIC_DIST + 0x824),
168         SAVE_ITEM(S5P_VA_GIC_DIST + 0x828),
169         SAVE_ITEM(S5P_VA_GIC_DIST + 0x82C),
170         SAVE_ITEM(S5P_VA_GIC_DIST + 0x830),
171         SAVE_ITEM(S5P_VA_GIC_DIST + 0x834),
172         SAVE_ITEM(S5P_VA_GIC_DIST + 0x838),
173         SAVE_ITEM(S5P_VA_GIC_DIST + 0x83C),
174         SAVE_ITEM(S5P_VA_GIC_DIST + 0x840),
175         SAVE_ITEM(S5P_VA_GIC_DIST + 0x844),
176         SAVE_ITEM(S5P_VA_GIC_DIST + 0x848),
177         SAVE_ITEM(S5P_VA_GIC_DIST + 0x84C),
178         SAVE_ITEM(S5P_VA_GIC_DIST + 0x850),
179         SAVE_ITEM(S5P_VA_GIC_DIST + 0x854),
180         SAVE_ITEM(S5P_VA_GIC_DIST + 0x858),
181         SAVE_ITEM(S5P_VA_GIC_DIST + 0x85C),
182
183         SAVE_ITEM(S5P_VA_GIC_DIST + 0xC00),
184         SAVE_ITEM(S5P_VA_GIC_DIST + 0xC04),
185         SAVE_ITEM(S5P_VA_GIC_DIST + 0xC08),
186         SAVE_ITEM(S5P_VA_GIC_DIST + 0xC0C),
187         SAVE_ITEM(S5P_VA_GIC_DIST + 0xC10),
188         SAVE_ITEM(S5P_VA_GIC_DIST + 0xC14),
189
190         SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x000),
191         SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x010),
192         SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x020),
193         SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x030),
194         SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x040),
195         SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x050),
196         SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x060),
197         SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x070),
198         SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x080),
199         SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x090),
200 };
201
202 static struct sleep_save exynos4_l2cc_save[] = {
203         SAVE_ITEM(S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL),
204         SAVE_ITEM(S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL),
205         SAVE_ITEM(S5P_VA_L2CC + L2X0_PREFETCH_CTRL),
206         SAVE_ITEM(S5P_VA_L2CC + L2X0_POWER_CTRL),
207         SAVE_ITEM(S5P_VA_L2CC + L2X0_AUX_CTRL),
208 };
209
210 void exynos4_cpu_suspend(void)
211 {
212         unsigned long tmp;
213         unsigned long mask = 0xFFFFFFFF;
214
215         /* Setting Central Sequence Register for power down mode */
216
217         tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
218         tmp &= ~(S5P_CENTRAL_LOWPWR_CFG);
219         __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
220
221         /* Setting Central Sequence option Register */
222
223         tmp = __raw_readl(S5P_CENTRAL_SEQ_OPTION);
224         tmp &= ~(S5P_USE_MASK);
225         tmp |= S5P_USE_STANDBY_WFI0;
226         __raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
227
228         /* Clear all interrupt pending to avoid early wakeup */
229
230         __raw_writel(mask, (S5P_VA_GIC_DIST + 0x280));
231         __raw_writel(mask, (S5P_VA_GIC_DIST + 0x284));
232         __raw_writel(mask, (S5P_VA_GIC_DIST + 0x288));
233
234         /* Disable all interrupt */
235
236         __raw_writel(0x0, (S5P_VA_GIC_CPU + 0x000));
237         __raw_writel(0x0, (S5P_VA_GIC_DIST + 0x000));
238         __raw_writel(mask, (S5P_VA_GIC_DIST + 0x184));
239         __raw_writel(mask, (S5P_VA_GIC_DIST + 0x188));
240
241         outer_flush_all();
242
243         /* issue the standby signal into the pm unit. */
244         cpu_do_idle();
245
246         /* we should never get past here */
247         panic("sleep resumed to originator?");
248 }
249
250 static void exynos4_pm_prepare(void)
251 {
252         u32 tmp;
253
254         s3c_pm_do_save(exynos4_core_save, ARRAY_SIZE(exynos4_core_save));
255         s3c_pm_do_save(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save));
256
257         tmp = __raw_readl(S5P_INFORM1);
258
259         /* Set value of power down register for sleep mode */
260
261         exynos4_sys_powerdown_conf(SYS_SLEEP);
262         __raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
263
264         /* ensure at least INFORM0 has the resume address */
265
266         __raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0);
267
268         /* Before enter central sequence mode, clock src register have to set */
269
270         s3c_pm_do_restore_core(exynos4_set_clksrc, ARRAY_SIZE(exynos4_set_clksrc));
271
272 }
273
274 static int exynos4_pm_add(struct sys_device *sysdev)
275 {
276         pm_cpu_prep = exynos4_pm_prepare;
277         pm_cpu_sleep = exynos4_cpu_suspend;
278
279         return 0;
280 }
281
282 /* This function copy from linux/arch/arm/kernel/smp_scu.c */
283
284 void exynos4_scu_enable(void __iomem *scu_base)
285 {
286         u32 scu_ctrl;
287
288         scu_ctrl = __raw_readl(scu_base);
289         /* already enabled? */
290         if (scu_ctrl & 1)
291                 return;
292
293         scu_ctrl |= 1;
294         __raw_writel(scu_ctrl, scu_base);
295
296         /*
297          * Ensure that the data accessed by CPU0 before the SCU was
298          * initialised is visible to the other CPUs.
299          */
300         flush_cache_all();
301 }
302
303 static struct sysdev_driver exynos4_pm_driver = {
304         .add            = exynos4_pm_add,
305 };
306
307 static __init int exynos4_pm_drvinit(void)
308 {
309         unsigned int tmp;
310
311         s3c_pm_init();
312
313         /* All wakeup disable */
314
315         tmp = __raw_readl(S5P_WAKEUP_MASK);
316         tmp |= ((0xFF << 8) | (0x1F << 1));
317         __raw_writel(tmp, S5P_WAKEUP_MASK);
318
319         return sysdev_driver_register(&exynos4_sysclass, &exynos4_pm_driver);
320 }
321 arch_initcall(exynos4_pm_drvinit);
322
323 static void exynos4_pm_resume(void)
324 {
325         /* For release retention */
326
327         __raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION);
328         __raw_writel((1 << 28), S5P_PAD_RET_GPIO_OPTION);
329         __raw_writel((1 << 28), S5P_PAD_RET_UART_OPTION);
330         __raw_writel((1 << 28), S5P_PAD_RET_MMCA_OPTION);
331         __raw_writel((1 << 28), S5P_PAD_RET_MMCB_OPTION);
332         __raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION);
333         __raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION);
334
335         s3c_pm_do_restore_core(exynos4_core_save, ARRAY_SIZE(exynos4_core_save));
336
337         exynos4_scu_enable(S5P_VA_SCU);
338
339 #ifdef CONFIG_CACHE_L2X0
340         s3c_pm_do_restore_core(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save));
341         outer_inv_all();
342         /* enable L2X0*/
343         writel_relaxed(1, S5P_VA_L2CC + L2X0_CTRL);
344 #endif
345 }
346
347 static struct syscore_ops exynos4_pm_syscore_ops = {
348         .resume         = exynos4_pm_resume,
349 };
350
351 static __init int exynos4_pm_syscore_init(void)
352 {
353         register_syscore_ops(&exynos4_pm_syscore_ops);
354         return 0;
355 }
356 arch_initcall(exynos4_pm_syscore_init);