aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-exynos
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-exynos')
-rw-r--r--arch/arm/mach-exynos/Kconfig11
-rw-r--r--arch/arm/mach-exynos/Makefile4
-rw-r--r--arch/arm/mach-exynos/common.h31
-rw-r--r--arch/arm/mach-exynos/exynos-pmu.h24
-rw-r--r--arch/arm/mach-exynos/exynos.c30
-rw-r--r--arch/arm/mach-exynos/firmware.c67
-rw-r--r--arch/arm/mach-exynos/mcpm-exynos.c32
-rw-r--r--arch/arm/mach-exynos/platsmp.c35
-rw-r--r--arch/arm/mach-exynos/pm.c311
-rw-r--r--arch/arm/mach-exynos/pmu.c669
-rw-r--r--arch/arm/mach-exynos/regs-pmu.h358
-rw-r--r--arch/arm/mach-exynos/sleep.S28
-rw-r--r--arch/arm/mach-exynos/smc.h4
-rw-r--r--arch/arm/mach-exynos/suspend.c566
14 files changed, 1800 insertions, 370 deletions
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 2d0240f241b8..b9e3f1c61baf 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -24,6 +24,7 @@ menuconfig ARCH_EXYNOS
24 select PM_GENERIC_DOMAINS if PM_RUNTIME 24 select PM_GENERIC_DOMAINS if PM_RUNTIME
25 select S5P_DEV_MFC 25 select S5P_DEV_MFC
26 select SRAM 26 select SRAM
27 select MFD_SYSCON
27 help 28 help
28 Support for SAMSUNG EXYNOS SoCs (EXYNOS4/5) 29 Support for SAMSUNG EXYNOS SoCs (EXYNOS4/5)
29 30
@@ -75,6 +76,11 @@ config SOC_EXYNOS4412
75 default y 76 default y
76 depends on ARCH_EXYNOS4 77 depends on ARCH_EXYNOS4
77 78
79config SOC_EXYNOS4415
80 bool "SAMSUNG EXYNOS4415"
81 default y
82 depends on ARCH_EXYNOS4
83
78config SOC_EXYNOS5250 84config SOC_EXYNOS5250
79 bool "SAMSUNG EXYNOS5250" 85 bool "SAMSUNG EXYNOS5250"
80 default y 86 default y
@@ -123,4 +129,9 @@ config EXYNOS5420_MCPM
123 This is needed to provide CPU and cluster power management 129 This is needed to provide CPU and cluster power management
124 on Exynos5420 implementing big.LITTLE. 130 on Exynos5420 implementing big.LITTLE.
125 131
132config EXYNOS_CPU_SUSPEND
133 bool
134 select ARM_CPU_SUSPEND
135 default PM_SLEEP || ARM_EXYNOS_CPUIDLE
136
126endif 137endif
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index d634de588d96..bcefb5473ee4 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -11,13 +11,15 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) += -I$(srctree)/$(src)/include -I$(srctree)
11 11
12obj-$(CONFIG_ARCH_EXYNOS) += exynos.o pmu.o exynos-smc.o firmware.o 12obj-$(CONFIG_ARCH_EXYNOS) += exynos.o pmu.o exynos-smc.o firmware.o
13 13
14obj-$(CONFIG_PM_SLEEP) += pm.o sleep.o 14obj-$(CONFIG_EXYNOS_CPU_SUSPEND) += pm.o sleep.o
15obj-$(CONFIG_PM_SLEEP) += suspend.o
15obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o 16obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
16 17
17obj-$(CONFIG_SMP) += platsmp.o headsmp.o 18obj-$(CONFIG_SMP) += platsmp.o headsmp.o
18 19
19plus_sec := $(call as-instr,.arch_extension sec,+sec) 20plus_sec := $(call as-instr,.arch_extension sec,+sec)
20AFLAGS_exynos-smc.o :=-Wa,-march=armv7-a$(plus_sec) 21AFLAGS_exynos-smc.o :=-Wa,-march=armv7-a$(plus_sec)
22AFLAGS_sleep.o :=-Wa,-march=armv7-a$(plus_sec)
21 23
22obj-$(CONFIG_EXYNOS5420_MCPM) += mcpm-exynos.o 24obj-$(CONFIG_EXYNOS5420_MCPM) += mcpm-exynos.o
23CFLAGS_mcpm-exynos.o += -march=armv7-a 25CFLAGS_mcpm-exynos.o += -march=armv7-a
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index 3d3e6af9d015..865f878063cc 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -12,7 +12,6 @@
12#ifndef __ARCH_ARM_MACH_EXYNOS_COMMON_H 12#ifndef __ARCH_ARM_MACH_EXYNOS_COMMON_H
13#define __ARCH_ARM_MACH_EXYNOS_COMMON_H 13#define __ARCH_ARM_MACH_EXYNOS_COMMON_H
14 14
15#include <linux/reboot.h>
16#include <linux/of.h> 15#include <linux/of.h>
17 16
18#define EXYNOS3250_SOC_ID 0xE3472000 17#define EXYNOS3250_SOC_ID 0xE3472000
@@ -111,11 +110,19 @@ IS_SAMSUNG_CPU(exynos5800, EXYNOS5800_SOC_ID, EXYNOS5_SOC_MASK)
111#define soc_is_exynos5() (soc_is_exynos5250() || soc_is_exynos5410() || \ 110#define soc_is_exynos5() (soc_is_exynos5250() || soc_is_exynos5410() || \
112 soc_is_exynos5420() || soc_is_exynos5800()) 111 soc_is_exynos5420() || soc_is_exynos5800())
113 112
113extern u32 cp15_save_diag;
114extern u32 cp15_save_power;
115
114extern void __iomem *sysram_ns_base_addr; 116extern void __iomem *sysram_ns_base_addr;
115extern void __iomem *sysram_base_addr; 117extern void __iomem *sysram_base_addr;
116extern void __iomem *pmu_base_addr; 118extern void __iomem *pmu_base_addr;
117void exynos_sysram_init(void); 119void exynos_sysram_init(void);
118 120
121enum {
122 FW_DO_IDLE_SLEEP,
123 FW_DO_IDLE_AFTR,
124};
125
119void exynos_firmware_init(void); 126void exynos_firmware_init(void);
120 127
121extern u32 exynos_get_eint_wake_mask(void); 128extern u32 exynos_get_eint_wake_mask(void);
@@ -127,32 +134,20 @@ static inline void exynos_pm_init(void) {}
127#endif 134#endif
128 135
129extern void exynos_cpu_resume(void); 136extern void exynos_cpu_resume(void);
137extern void exynos_cpu_resume_ns(void);
130 138
131extern struct smp_operations exynos_smp_ops; 139extern struct smp_operations exynos_smp_ops;
132 140
133/* PMU(Power Management Unit) support */
134
135#define PMU_TABLE_END (-1U)
136
137enum sys_powerdown {
138 SYS_AFTR,
139 SYS_LPA,
140 SYS_SLEEP,
141 NUM_SYS_POWERDOWN,
142};
143
144struct exynos_pmu_conf {
145 unsigned int offset;
146 unsigned int val[NUM_SYS_POWERDOWN];
147};
148
149extern void exynos_sys_powerdown_conf(enum sys_powerdown mode);
150extern void exynos_cpu_power_down(int cpu); 141extern void exynos_cpu_power_down(int cpu);
151extern void exynos_cpu_power_up(int cpu); 142extern void exynos_cpu_power_up(int cpu);
152extern int exynos_cpu_power_state(int cpu); 143extern int exynos_cpu_power_state(int cpu);
153extern void exynos_cluster_power_down(int cluster); 144extern void exynos_cluster_power_down(int cluster);
154extern void exynos_cluster_power_up(int cluster); 145extern void exynos_cluster_power_up(int cluster);
155extern int exynos_cluster_power_state(int cluster); 146extern int exynos_cluster_power_state(int cluster);
147extern void exynos_cpu_save_register(void);
148extern void exynos_cpu_restore_register(void);
149extern void exynos_pm_central_suspend(void);
150extern int exynos_pm_central_resume(void);
156extern void exynos_enter_aftr(void); 151extern void exynos_enter_aftr(void);
157 152
158extern void s5p_init_cpu(void __iomem *cpuid_addr); 153extern void s5p_init_cpu(void __iomem *cpuid_addr);
diff --git a/arch/arm/mach-exynos/exynos-pmu.h b/arch/arm/mach-exynos/exynos-pmu.h
new file mode 100644
index 000000000000..a2ab0d52b230
--- /dev/null
+++ b/arch/arm/mach-exynos/exynos-pmu.h
@@ -0,0 +1,24 @@
1/*
2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com
4 *
5 * Header for EXYNOS PMU Driver support
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef __EXYNOS_PMU_H
13#define __EXYNOS_PMU_H
14
15enum sys_powerdown {
16 SYS_AFTR,
17 SYS_LPA,
18 SYS_SLEEP,
19 NUM_SYS_POWERDOWN,
20};
21
22extern void exynos_sys_powerdown_conf(enum sys_powerdown mode);
23
24#endif /* __EXYNOS_PMU_H */
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index 6de7cf5ef2b2..c13d0837fa8c 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -87,28 +87,6 @@ static struct map_desc exynos5_iodesc[] __initdata = {
87 }, 87 },
88}; 88};
89 89
90static void exynos_restart(enum reboot_mode mode, const char *cmd)
91{
92 struct device_node *np;
93 u32 val = 0x1;
94 void __iomem *addr = pmu_base_addr + EXYNOS_SWRESET;
95
96 if (of_machine_is_compatible("samsung,exynos5440")) {
97 u32 status;
98 np = of_find_compatible_node(NULL, NULL, "samsung,exynos5440-clock");
99
100 addr = of_iomap(np, 0) + 0xbc;
101 status = __raw_readl(addr);
102
103 addr = of_iomap(np, 0) + 0xcc;
104 val = __raw_readl(addr);
105
106 val = (val & 0xffff0000) | (status & 0xffff);
107 }
108
109 __raw_writel(val, addr);
110}
111
112static struct platform_device exynos_cpuidle = { 90static struct platform_device exynos_cpuidle = {
113 .name = "exynos_cpuidle", 91 .name = "exynos_cpuidle",
114#ifdef CONFIG_ARM_EXYNOS_CPUIDLE 92#ifdef CONFIG_ARM_EXYNOS_CPUIDLE
@@ -202,6 +180,7 @@ static const struct of_device_id exynos_dt_pmu_match[] = {
202 { .compatible = "samsung,exynos4210-pmu" }, 180 { .compatible = "samsung,exynos4210-pmu" },
203 { .compatible = "samsung,exynos4212-pmu" }, 181 { .compatible = "samsung,exynos4212-pmu" },
204 { .compatible = "samsung,exynos4412-pmu" }, 182 { .compatible = "samsung,exynos4412-pmu" },
183 { .compatible = "samsung,exynos4415-pmu" },
205 { .compatible = "samsung,exynos5250-pmu" }, 184 { .compatible = "samsung,exynos5250-pmu" },
206 { .compatible = "samsung,exynos5260-pmu" }, 185 { .compatible = "samsung,exynos5260-pmu" },
207 { .compatible = "samsung,exynos5410-pmu" }, 186 { .compatible = "samsung,exynos5410-pmu" },
@@ -268,7 +247,10 @@ static void __init exynos_dt_machine_init(void)
268 exynos_sysram_init(); 247 exynos_sysram_init();
269 248
270 if (of_machine_is_compatible("samsung,exynos4210") || 249 if (of_machine_is_compatible("samsung,exynos4210") ||
271 of_machine_is_compatible("samsung,exynos5250")) 250 of_machine_is_compatible("samsung,exynos4212") ||
251 (of_machine_is_compatible("samsung,exynos4412") &&
252 of_machine_is_compatible("samsung,trats2")) ||
253 of_machine_is_compatible("samsung,exynos5250"))
272 platform_device_register(&exynos_cpuidle); 254 platform_device_register(&exynos_cpuidle);
273 255
274 platform_device_register_simple("exynos-cpufreq", -1, NULL, 0); 256 platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
@@ -283,6 +265,7 @@ static char const *exynos_dt_compat[] __initconst = {
283 "samsung,exynos4210", 265 "samsung,exynos4210",
284 "samsung,exynos4212", 266 "samsung,exynos4212",
285 "samsung,exynos4412", 267 "samsung,exynos4412",
268 "samsung,exynos4415",
286 "samsung,exynos5", 269 "samsung,exynos5",
287 "samsung,exynos5250", 270 "samsung,exynos5250",
288 "samsung,exynos5260", 271 "samsung,exynos5260",
@@ -328,7 +311,6 @@ DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)")
328 .init_machine = exynos_dt_machine_init, 311 .init_machine = exynos_dt_machine_init,
329 .init_late = exynos_init_late, 312 .init_late = exynos_init_late,
330 .dt_compat = exynos_dt_compat, 313 .dt_compat = exynos_dt_compat,
331 .restart = exynos_restart,
332 .reserve = exynos_reserve, 314 .reserve = exynos_reserve,
333 .dt_fixup = exynos_dt_fixup, 315 .dt_fixup = exynos_dt_fixup,
334MACHINE_END 316MACHINE_END
diff --git a/arch/arm/mach-exynos/firmware.c b/arch/arm/mach-exynos/firmware.c
index e8797bb78871..766f57d2f029 100644
--- a/arch/arm/mach-exynos/firmware.c
+++ b/arch/arm/mach-exynos/firmware.c
@@ -14,16 +14,44 @@
14#include <linux/of.h> 14#include <linux/of.h>
15#include <linux/of_address.h> 15#include <linux/of_address.h>
16 16
17#include <asm/cacheflush.h>
18#include <asm/cputype.h>
17#include <asm/firmware.h> 19#include <asm/firmware.h>
20#include <asm/suspend.h>
18 21
19#include <mach/map.h> 22#include <mach/map.h>
20 23
21#include "common.h" 24#include "common.h"
22#include "smc.h" 25#include "smc.h"
23 26
24static int exynos_do_idle(void) 27#define EXYNOS_SLEEP_MAGIC 0x00000bad
28#define EXYNOS_AFTR_MAGIC 0xfcba0d10
29#define EXYNOS_BOOT_ADDR 0x8
30#define EXYNOS_BOOT_FLAG 0xc
31
32static void exynos_save_cp15(void)
25{ 33{
26 exynos_smc(SMC_CMD_SLEEP, 0, 0, 0); 34 /* Save Power control and Diagnostic registers */
35 asm ("mrc p15, 0, %0, c15, c0, 0\n"
36 "mrc p15, 0, %1, c15, c0, 1\n"
37 : "=r" (cp15_save_power), "=r" (cp15_save_diag)
38 : : "cc");
39}
40
41static int exynos_do_idle(unsigned long mode)
42{
43 switch (mode) {
44 case FW_DO_IDLE_AFTR:
45 if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
46 exynos_save_cp15();
47 __raw_writel(virt_to_phys(exynos_cpu_resume_ns),
48 sysram_ns_base_addr + 0x24);
49 __raw_writel(EXYNOS_AFTR_MAGIC, sysram_ns_base_addr + 0x20);
50 exynos_smc(SMC_CMD_CPU0AFTR, 0, 0, 0);
51 break;
52 case FW_DO_IDLE_SLEEP:
53 exynos_smc(SMC_CMD_SLEEP, 0, 0, 0);
54 }
27 return 0; 55 return 0;
28} 56}
29 57
@@ -69,10 +97,43 @@ static int exynos_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
69 return 0; 97 return 0;
70} 98}
71 99
100static int exynos_cpu_suspend(unsigned long arg)
101{
102 flush_cache_all();
103 outer_flush_all();
104
105 exynos_smc(SMC_CMD_SLEEP, 0, 0, 0);
106
107 pr_info("Failed to suspend the system\n");
108 writel(0, sysram_ns_base_addr + EXYNOS_BOOT_FLAG);
109 return 1;
110}
111
112static int exynos_suspend(void)
113{
114 if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
115 exynos_save_cp15();
116
117 writel(EXYNOS_SLEEP_MAGIC, sysram_ns_base_addr + EXYNOS_BOOT_FLAG);
118 writel(virt_to_phys(exynos_cpu_resume_ns),
119 sysram_ns_base_addr + EXYNOS_BOOT_ADDR);
120
121 return cpu_suspend(0, exynos_cpu_suspend);
122}
123
124static int exynos_resume(void)
125{
126 writel(0, sysram_ns_base_addr + EXYNOS_BOOT_FLAG);
127
128 return 0;
129}
130
72static const struct firmware_ops exynos_firmware_ops = { 131static const struct firmware_ops exynos_firmware_ops = {
73 .do_idle = exynos_do_idle, 132 .do_idle = IS_ENABLED(CONFIG_EXYNOS_CPU_SUSPEND) ? exynos_do_idle : NULL,
74 .set_cpu_boot_addr = exynos_set_cpu_boot_addr, 133 .set_cpu_boot_addr = exynos_set_cpu_boot_addr,
75 .cpu_boot = exynos_cpu_boot, 134 .cpu_boot = exynos_cpu_boot,
135 .suspend = IS_ENABLED(CONFIG_PM_SLEEP) ? exynos_suspend : NULL,
136 .resume = IS_ENABLED(CONFIG_EXYNOS_CPU_SUSPEND) ? exynos_resume : NULL,
76}; 137};
77 138
78void __init exynos_firmware_init(void) 139void __init exynos_firmware_init(void)
diff --git a/arch/arm/mach-exynos/mcpm-exynos.c b/arch/arm/mach-exynos/mcpm-exynos.c
index dc9a764a7c37..b0d3c2e876fb 100644
--- a/arch/arm/mach-exynos/mcpm-exynos.c
+++ b/arch/arm/mach-exynos/mcpm-exynos.c
@@ -15,6 +15,7 @@
15#include <linux/delay.h> 15#include <linux/delay.h>
16#include <linux/io.h> 16#include <linux/io.h>
17#include <linux/of_address.h> 17#include <linux/of_address.h>
18#include <linux/syscore_ops.h>
18 19
19#include <asm/cputype.h> 20#include <asm/cputype.h>
20#include <asm/cp15.h> 21#include <asm/cp15.h>
@@ -30,6 +31,8 @@
30#define EXYNOS5420_USE_ARM_CORE_DOWN_STATE BIT(29) 31#define EXYNOS5420_USE_ARM_CORE_DOWN_STATE BIT(29)
31#define EXYNOS5420_USE_L2_COMMON_UP_STATE BIT(30) 32#define EXYNOS5420_USE_L2_COMMON_UP_STATE BIT(30)
32 33
34static void __iomem *ns_sram_base_addr;
35
33/* 36/*
34 * The common v7_exit_coherency_flush API could not be used because of the 37 * The common v7_exit_coherency_flush API could not be used because of the
35 * Erratum 799270 workaround. This macro is the same as the common one (in 38 * Erratum 799270 workaround. This macro is the same as the common one (in
@@ -318,10 +321,26 @@ static const struct of_device_id exynos_dt_mcpm_match[] = {
318 {}, 321 {},
319}; 322};
320 323
324static void exynos_mcpm_setup_entry_point(void)
325{
326 /*
327 * U-Boot SPL is hardcoded to jump to the start of ns_sram_base_addr
328 * as part of secondary_cpu_start(). Let's redirect it to the
329 * mcpm_entry_point(). This is done during both secondary boot-up as
330 * well as system resume.
331 */
332 __raw_writel(0xe59f0000, ns_sram_base_addr); /* ldr r0, [pc, #0] */
333 __raw_writel(0xe12fff10, ns_sram_base_addr + 4); /* bx r0 */
334 __raw_writel(virt_to_phys(mcpm_entry_point), ns_sram_base_addr + 8);
335}
336
337static struct syscore_ops exynos_mcpm_syscore_ops = {
338 .resume = exynos_mcpm_setup_entry_point,
339};
340
321static int __init exynos_mcpm_init(void) 341static int __init exynos_mcpm_init(void)
322{ 342{
323 struct device_node *node; 343 struct device_node *node;
324 void __iomem *ns_sram_base_addr;
325 unsigned int value, i; 344 unsigned int value, i;
326 int ret; 345 int ret;
327 346
@@ -387,16 +406,9 @@ static int __init exynos_mcpm_init(void)
387 pmu_raw_writel(value, EXYNOS_COMMON_OPTION(i)); 406 pmu_raw_writel(value, EXYNOS_COMMON_OPTION(i));
388 } 407 }
389 408
390 /* 409 exynos_mcpm_setup_entry_point();
391 * U-Boot SPL is hardcoded to jump to the start of ns_sram_base_addr
392 * as part of secondary_cpu_start(). Let's redirect it to the
393 * mcpm_entry_point().
394 */
395 __raw_writel(0xe59f0000, ns_sram_base_addr); /* ldr r0, [pc, #0] */
396 __raw_writel(0xe12fff10, ns_sram_base_addr + 4); /* bx r0 */
397 __raw_writel(virt_to_phys(mcpm_entry_point), ns_sram_base_addr + 8);
398 410
399 iounmap(ns_sram_base_addr); 411 register_syscore_ops(&exynos_mcpm_syscore_ops);
400 412
401 return ret; 413 return ret;
402} 414}
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index 9c6dd1451136..7a1ebfeeeeb8 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -126,6 +126,18 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
126 */ 126 */
127void exynos_cpu_power_down(int cpu) 127void exynos_cpu_power_down(int cpu)
128{ 128{
129 if (cpu == 0 && (of_machine_is_compatible("samsung,exynos5420") ||
130 of_machine_is_compatible("samsung,exynos5800"))) {
131 /*
132 * Bypass power down for CPU0 during suspend. Check for
133 * the SYS_PWR_REG value to decide if we are suspending
134 * the system.
135 */
136 int val = pmu_raw_readl(EXYNOS5_ARM_CORE0_SYS_PWR_REG);
137
138 if (!(val & S5P_CORE_LOCAL_PWR_EN))
139 return;
140 }
129 pmu_raw_writel(0, EXYNOS_ARM_CORE_CONFIGURATION(cpu)); 141 pmu_raw_writel(0, EXYNOS_ARM_CORE_CONFIGURATION(cpu));
130} 142}
131 143
@@ -204,6 +216,26 @@ static inline void __iomem *cpu_boot_reg(int cpu)
204} 216}
205 217
206/* 218/*
219 * Set wake up by local power mode and execute software reset for given core.
220 *
221 * Currently this is needed only when booting secondary CPU on Exynos3250.
222 */
223static void exynos_core_restart(u32 core_id)
224{
225 u32 val;
226
227 if (!of_machine_is_compatible("samsung,exynos3250"))
228 return;
229
230 val = pmu_raw_readl(EXYNOS_ARM_CORE_STATUS(core_id));
231 val |= S5P_CORE_WAKEUP_FROM_LOCAL_CFG;
232 pmu_raw_writel(val, EXYNOS_ARM_CORE_STATUS(core_id));
233
234 pr_info("CPU%u: Software reset\n", core_id);
235 pmu_raw_writel(EXYNOS_CORE_PO_RESET(core_id), EXYNOS_SWRESET);
236}
237
238/*
207 * Write pen_release in a way that is guaranteed to be visible to all 239 * Write pen_release in a way that is guaranteed to be visible to all
208 * observers, irrespective of whether they're taking part in coherency 240 * observers, irrespective of whether they're taking part in coherency
209 * or not. This is necessary for the hotplug code to work reliably. 241 * or not. This is necessary for the hotplug code to work reliably.
@@ -279,6 +311,9 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
279 return -ETIMEDOUT; 311 return -ETIMEDOUT;
280 } 312 }
281 } 313 }
314
315 exynos_core_restart(core_id);
316
282 /* 317 /*
283 * Send the secondary CPU a soft interrupt, thereby causing 318 * Send the secondary CPU a soft interrupt, thereby causing
284 * the boot monitor to read the system wide flags register, 319 * the boot monitor to read the system wide flags register,
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index abefacb45976..86f3ecd88f78 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd. 2 * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com 3 * http://www.samsung.com
4 * 4 *
5 * EXYNOS - Power Management support 5 * EXYNOS - Power Management support
@@ -15,109 +15,45 @@
15 15
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/suspend.h> 17#include <linux/suspend.h>
18#include <linux/syscore_ops.h>
19#include <linux/cpu_pm.h> 18#include <linux/cpu_pm.h>
20#include <linux/io.h> 19#include <linux/io.h>
21#include <linux/irqchip/arm-gic.h>
22#include <linux/err.h> 20#include <linux/err.h>
23#include <linux/clk.h>
24 21
25#include <asm/cacheflush.h> 22#include <asm/firmware.h>
26#include <asm/hardware/cache-l2x0.h>
27#include <asm/smp_scu.h> 23#include <asm/smp_scu.h>
28#include <asm/suspend.h> 24#include <asm/suspend.h>
29 25
30#include <plat/pm-common.h> 26#include <plat/pm-common.h>
31#include <plat/regs-srom.h>
32
33#include <mach/map.h>
34 27
35#include "common.h" 28#include "common.h"
29#include "exynos-pmu.h"
36#include "regs-pmu.h" 30#include "regs-pmu.h"
37#include "regs-sys.h" 31#include "regs-sys.h"
38 32
39/** 33static inline void __iomem *exynos_boot_vector_addr(void)
40 * struct exynos_wkup_irq - Exynos GIC to PMU IRQ mapping
41 * @hwirq: Hardware IRQ signal of the GIC
42 * @mask: Mask in PMU wake-up mask register
43 */
44struct exynos_wkup_irq {
45 unsigned int hwirq;
46 u32 mask;
47};
48
49static struct sleep_save exynos5_sys_save[] = {
50 SAVE_ITEM(EXYNOS5_SYS_I2C_CFG),
51};
52
53static struct sleep_save exynos_core_save[] = {
54 /* SROM side */
55 SAVE_ITEM(S5P_SROM_BW),
56 SAVE_ITEM(S5P_SROM_BC0),
57 SAVE_ITEM(S5P_SROM_BC1),
58 SAVE_ITEM(S5P_SROM_BC2),
59 SAVE_ITEM(S5P_SROM_BC3),
60};
61
62/*
63 * GIC wake-up support
64 */
65
66static u32 exynos_irqwake_intmask = 0xffffffff;
67
68static const struct exynos_wkup_irq exynos4_wkup_irq[] = {
69 { 76, BIT(1) }, /* RTC alarm */
70 { 77, BIT(2) }, /* RTC tick */
71 { /* sentinel */ },
72};
73
74static const struct exynos_wkup_irq exynos5250_wkup_irq[] = {
75 { 75, BIT(1) }, /* RTC alarm */
76 { 76, BIT(2) }, /* RTC tick */
77 { /* sentinel */ },
78};
79
80static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
81{ 34{
82 const struct exynos_wkup_irq *wkup_irq; 35 if (samsung_rev() == EXYNOS4210_REV_1_1)
83 36 return pmu_base_addr + S5P_INFORM7;
84 if (soc_is_exynos5250()) 37 else if (samsung_rev() == EXYNOS4210_REV_1_0)
85 wkup_irq = exynos5250_wkup_irq; 38 return sysram_base_addr + 0x24;
86 else 39 return pmu_base_addr + S5P_INFORM0;
87 wkup_irq = exynos4_wkup_irq;
88
89 while (wkup_irq->mask) {
90 if (wkup_irq->hwirq == data->hwirq) {
91 if (!state)
92 exynos_irqwake_intmask |= wkup_irq->mask;
93 else
94 exynos_irqwake_intmask &= ~wkup_irq->mask;
95 return 0;
96 }
97 ++wkup_irq;
98 }
99
100 return -ENOENT;
101} 40}
102 41
103#define EXYNOS_BOOT_VECTOR_ADDR (samsung_rev() == EXYNOS4210_REV_1_1 ? \ 42static inline void __iomem *exynos_boot_vector_flag(void)
104 pmu_base_addr + S5P_INFORM7 : \ 43{
105 (samsung_rev() == EXYNOS4210_REV_1_0 ? \ 44 if (samsung_rev() == EXYNOS4210_REV_1_1)
106 (sysram_base_addr + 0x24) : \ 45 return pmu_base_addr + S5P_INFORM6;
107 pmu_base_addr + S5P_INFORM0)) 46 else if (samsung_rev() == EXYNOS4210_REV_1_0)
108#define EXYNOS_BOOT_VECTOR_FLAG (samsung_rev() == EXYNOS4210_REV_1_1 ? \ 47 return sysram_base_addr + 0x20;
109 pmu_base_addr + S5P_INFORM6 : \ 48 return pmu_base_addr + S5P_INFORM1;
110 (samsung_rev() == EXYNOS4210_REV_1_0 ? \ 49}
111 (sysram_base_addr + 0x20) : \
112 pmu_base_addr + S5P_INFORM1))
113 50
114#define S5P_CHECK_AFTR 0xFCBA0D10 51#define S5P_CHECK_AFTR 0xFCBA0D10
115#define S5P_CHECK_SLEEP 0x00000BAD
116 52
117/* For Cortex-A9 Diagnostic and Power control register */ 53/* For Cortex-A9 Diagnostic and Power control register */
118static unsigned int save_arm_register[2]; 54static unsigned int save_arm_register[2];
119 55
120static void exynos_cpu_save_register(void) 56void exynos_cpu_save_register(void)
121{ 57{
122 unsigned long tmp; 58 unsigned long tmp;
123 59
@@ -134,7 +70,7 @@ static void exynos_cpu_save_register(void)
134 save_arm_register[1] = tmp; 70 save_arm_register[1] = tmp;
135} 71}
136 72
137static void exynos_cpu_restore_register(void) 73void exynos_cpu_restore_register(void)
138{ 74{
139 unsigned long tmp; 75 unsigned long tmp;
140 76
@@ -153,7 +89,7 @@ static void exynos_cpu_restore_register(void)
153 : "cc"); 89 : "cc");
154} 90}
155 91
156static void exynos_pm_central_suspend(void) 92void exynos_pm_central_suspend(void)
157{ 93{
158 unsigned long tmp; 94 unsigned long tmp;
159 95
@@ -161,9 +97,13 @@ static void exynos_pm_central_suspend(void)
161 tmp = pmu_raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION); 97 tmp = pmu_raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
162 tmp &= ~S5P_CENTRAL_LOWPWR_CFG; 98 tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
163 pmu_raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION); 99 pmu_raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
100
101 /* Setting SEQ_OPTION register */
102 pmu_raw_writel(S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0,
103 S5P_CENTRAL_SEQ_OPTION);
164} 104}
165 105
166static int exynos_pm_central_resume(void) 106int exynos_pm_central_resume(void)
167{ 107{
168 unsigned long tmp; 108 unsigned long tmp;
169 109
@@ -194,17 +134,26 @@ static void exynos_set_wakeupmask(long mask)
194 134
195static void exynos_cpu_set_boot_vector(long flags) 135static void exynos_cpu_set_boot_vector(long flags)
196{ 136{
197 __raw_writel(virt_to_phys(exynos_cpu_resume), EXYNOS_BOOT_VECTOR_ADDR); 137 __raw_writel(virt_to_phys(exynos_cpu_resume),
198 __raw_writel(flags, EXYNOS_BOOT_VECTOR_FLAG); 138 exynos_boot_vector_addr());
139 __raw_writel(flags, exynos_boot_vector_flag());
199} 140}
200 141
201static int exynos_aftr_finisher(unsigned long flags) 142static int exynos_aftr_finisher(unsigned long flags)
202{ 143{
144 int ret;
145
203 exynos_set_wakeupmask(0x0000ff3e); 146 exynos_set_wakeupmask(0x0000ff3e);
204 exynos_cpu_set_boot_vector(S5P_CHECK_AFTR);
205 /* Set value of power down register for aftr mode */ 147 /* Set value of power down register for aftr mode */
206 exynos_sys_powerdown_conf(SYS_AFTR); 148 exynos_sys_powerdown_conf(SYS_AFTR);
207 cpu_do_idle(); 149
150 ret = call_firmware_op(do_idle, FW_DO_IDLE_AFTR);
151 if (ret == -ENOSYS) {
152 if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
153 exynos_cpu_save_register();
154 exynos_cpu_set_boot_vector(S5P_CHECK_AFTR);
155 cpu_do_idle();
156 }
208 157
209 return 1; 158 return 1;
210} 159}
@@ -214,196 +163,16 @@ void exynos_enter_aftr(void)
214 cpu_pm_enter(); 163 cpu_pm_enter();
215 164
216 exynos_pm_central_suspend(); 165 exynos_pm_central_suspend();
217 if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
218 exynos_cpu_save_register();
219 166
220 cpu_suspend(0, exynos_aftr_finisher); 167 cpu_suspend(0, exynos_aftr_finisher);
221 168
222 if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) { 169 if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
223 scu_enable(S5P_VA_SCU); 170 scu_enable(S5P_VA_SCU);
224 exynos_cpu_restore_register(); 171 if (call_firmware_op(resume) == -ENOSYS)
172 exynos_cpu_restore_register();
225 } 173 }
226 174
227 exynos_pm_central_resume(); 175 exynos_pm_central_resume();
228 176
229 cpu_pm_exit(); 177 cpu_pm_exit();
230} 178}
231
232static int exynos_cpu_suspend(unsigned long arg)
233{
234#ifdef CONFIG_CACHE_L2X0
235 outer_flush_all();
236#endif
237
238 if (soc_is_exynos5250())
239 flush_cache_all();
240
241 /* issue the standby signal into the pm unit. */
242 cpu_do_idle();
243
244 pr_info("Failed to suspend the system\n");
245 return 1; /* Aborting suspend */
246}
247
248static void exynos_pm_prepare(void)
249{
250 unsigned int tmp;
251
252 /* Set wake-up mask registers */
253 pmu_raw_writel(exynos_get_eint_wake_mask(), S5P_EINT_WAKEUP_MASK);
254 pmu_raw_writel(exynos_irqwake_intmask & ~(1 << 31), S5P_WAKEUP_MASK);
255
256 s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
257
258 if (soc_is_exynos5250()) {
259 s3c_pm_do_save(exynos5_sys_save, ARRAY_SIZE(exynos5_sys_save));
260 /* Disable USE_RETENTION of JPEG_MEM_OPTION */
261 tmp = pmu_raw_readl(EXYNOS5_JPEG_MEM_OPTION);
262 tmp &= ~EXYNOS5_OPTION_USE_RETENTION;
263 pmu_raw_writel(tmp, EXYNOS5_JPEG_MEM_OPTION);
264 }
265
266 /* Set value of power down register for sleep mode */
267
268 exynos_sys_powerdown_conf(SYS_SLEEP);
269 pmu_raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
270
271 /* ensure at least INFORM0 has the resume address */
272
273 pmu_raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0);
274}
275
276static int exynos_pm_suspend(void)
277{
278 unsigned long tmp;
279
280 exynos_pm_central_suspend();
281
282 /* Setting SEQ_OPTION register */
283
284 tmp = (S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0);
285 pmu_raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
286
287 if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
288 exynos_cpu_save_register();
289
290 return 0;
291}
292
293static void exynos_pm_resume(void)
294{
295 if (exynos_pm_central_resume())
296 goto early_wakeup;
297
298 if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
299 exynos_cpu_restore_register();
300
301 /* For release retention */
302
303 pmu_raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION);
304 pmu_raw_writel((1 << 28), S5P_PAD_RET_GPIO_OPTION);
305 pmu_raw_writel((1 << 28), S5P_PAD_RET_UART_OPTION);
306 pmu_raw_writel((1 << 28), S5P_PAD_RET_MMCA_OPTION);
307 pmu_raw_writel((1 << 28), S5P_PAD_RET_MMCB_OPTION);
308 pmu_raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION);
309 pmu_raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION);
310
311 if (soc_is_exynos5250())
312 s3c_pm_do_restore(exynos5_sys_save,
313 ARRAY_SIZE(exynos5_sys_save));
314
315 s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
316
317 if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
318 scu_enable(S5P_VA_SCU);
319
320early_wakeup:
321
322 /* Clear SLEEP mode set in INFORM1 */
323 pmu_raw_writel(0x0, S5P_INFORM1);
324
325 return;
326}
327
328static struct syscore_ops exynos_pm_syscore_ops = {
329 .suspend = exynos_pm_suspend,
330 .resume = exynos_pm_resume,
331};
332
333/*
334 * Suspend Ops
335 */
336
337static int exynos_suspend_enter(suspend_state_t state)
338{
339 int ret;
340
341 s3c_pm_debug_init();
342
343 S3C_PMDBG("%s: suspending the system...\n", __func__);
344
345 S3C_PMDBG("%s: wakeup masks: %08x,%08x\n", __func__,
346 exynos_irqwake_intmask, exynos_get_eint_wake_mask());
347
348 if (exynos_irqwake_intmask == -1U
349 && exynos_get_eint_wake_mask() == -1U) {
350 pr_err("%s: No wake-up sources!\n", __func__);
351 pr_err("%s: Aborting sleep\n", __func__);
352 return -EINVAL;
353 }
354
355 s3c_pm_save_uarts();
356 exynos_pm_prepare();
357 flush_cache_all();
358 s3c_pm_check_store();
359
360 ret = cpu_suspend(0, exynos_cpu_suspend);
361 if (ret)
362 return ret;
363
364 s3c_pm_restore_uarts();
365
366 S3C_PMDBG("%s: wakeup stat: %08x\n", __func__,
367 pmu_raw_readl(S5P_WAKEUP_STAT));
368
369 s3c_pm_check_restore();
370
371 S3C_PMDBG("%s: resuming the system...\n", __func__);
372
373 return 0;
374}
375
376static int exynos_suspend_prepare(void)
377{
378 s3c_pm_check_prepare();
379
380 return 0;
381}
382
383static void exynos_suspend_finish(void)
384{
385 s3c_pm_check_cleanup();
386}
387
388static const struct platform_suspend_ops exynos_suspend_ops = {
389 .enter = exynos_suspend_enter,
390 .prepare = exynos_suspend_prepare,
391 .finish = exynos_suspend_finish,
392 .valid = suspend_valid_only_mem,
393};
394
395void __init exynos_pm_init(void)
396{
397 u32 tmp;
398
399 /* Platform-specific GIC callback */
400 gic_arch_extn.irq_set_wake = exynos_irq_set_wake;
401
402 /* All wakeup disable */
403 tmp = pmu_raw_readl(S5P_WAKEUP_MASK);
404 tmp |= ((0xFF << 8) | (0x1F << 1));
405 pmu_raw_writel(tmp, S5P_WAKEUP_MASK);
406
407 register_syscore_ops(&exynos_pm_syscore_ops);
408 suspend_set_ops(&exynos_suspend_ops);
409}
diff --git a/arch/arm/mach-exynos/pmu.c b/arch/arm/mach-exynos/pmu.c
index d8fa0337db73..c15761ca2f18 100644
--- a/arch/arm/mach-exynos/pmu.c
+++ b/arch/arm/mach-exynos/pmu.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd. 2 * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com/ 3 * http://www.samsung.com/
4 * 4 *
5 * EXYNOS - CPU PMU(Power Management Unit) support 5 * EXYNOS - CPU PMU(Power Management Unit) support
@@ -10,12 +10,136 @@
10 */ 10 */
11 11
12#include <linux/io.h> 12#include <linux/io.h>
13#include <linux/kernel.h> 13#include <linux/of.h>
14#include <linux/of_address.h>
15#include <linux/platform_device.h>
16#include <linux/delay.h>
17#include <linux/notifier.h>
18#include <linux/reboot.h>
14 19
15#include "common.h" 20
21#include "exynos-pmu.h"
16#include "regs-pmu.h" 22#include "regs-pmu.h"
17 23
18static const struct exynos_pmu_conf *exynos_pmu_config; 24#define PMU_TABLE_END (-1U)
25
26struct exynos_pmu_conf {
27 unsigned int offset;
28 u8 val[NUM_SYS_POWERDOWN];
29};
30
31struct exynos_pmu_data {
32 const struct exynos_pmu_conf *pmu_config;
33 const struct exynos_pmu_conf *pmu_config_extra;
34
35 void (*pmu_init)(void);
36 void (*powerdown_conf)(enum sys_powerdown);
37 void (*powerdown_conf_extra)(enum sys_powerdown);
38};
39
40struct exynos_pmu_context {
41 struct device *dev;
42 const struct exynos_pmu_data *pmu_data;
43};
44
45static void __iomem *pmu_base_addr;
46static struct exynos_pmu_context *pmu_context;
47
48static inline void pmu_raw_writel(u32 val, u32 offset)
49{
50 writel_relaxed(val, pmu_base_addr + offset);
51}
52
53static inline u32 pmu_raw_readl(u32 offset)
54{
55 return readl_relaxed(pmu_base_addr + offset);
56}
57
58static struct exynos_pmu_conf exynos3250_pmu_config[] = {
59 /* { .offset = offset, .val = { AFTR, W-AFTR, SLEEP } */
60 { EXYNOS3_ARM_CORE0_SYS_PWR_REG, { 0x0, 0x0, 0x2} },
61 { EXYNOS3_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
62 { EXYNOS3_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
63 { EXYNOS3_ARM_CORE1_SYS_PWR_REG, { 0x0, 0x0, 0x2} },
64 { EXYNOS3_DIS_IRQ_ARM_CORE1_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
65 { EXYNOS3_DIS_IRQ_ARM_CORE1_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
66 { EXYNOS3_ISP_ARM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
67 { EXYNOS3_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
68 { EXYNOS3_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
69 { EXYNOS3_ARM_COMMON_SYS_PWR_REG, { 0x0, 0x0, 0x2} },
70 { EXYNOS3_ARM_L2_SYS_PWR_REG, { 0x0, 0x0, 0x3} },
71 { EXYNOS3_CMU_ACLKSTOP_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
72 { EXYNOS3_CMU_SCLKSTOP_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
73 { EXYNOS3_CMU_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
74 { EXYNOS3_DRAM_FREQ_DOWN_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
75 { EXYNOS3_DDRPHY_DLLOFF_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
76 { EXYNOS3_LPDDR_PHY_DLL_LOCK_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
77 { EXYNOS3_CMU_ACLKSTOP_COREBLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
78 { EXYNOS3_CMU_SCLKSTOP_COREBLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
79 { EXYNOS3_CMU_RESET_COREBLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
80 { EXYNOS3_APLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
81 { EXYNOS3_MPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
82 { EXYNOS3_BPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
83 { EXYNOS3_VPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
84 { EXYNOS3_EPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
85 { EXYNOS3_UPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
86 { EXYNOS3_EPLLUSER_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
87 { EXYNOS3_MPLLUSER_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
88 { EXYNOS3_BPLLUSER_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
89 { EXYNOS3_CMU_CLKSTOP_CAM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
90 { EXYNOS3_CMU_CLKSTOP_MFC_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
91 { EXYNOS3_CMU_CLKSTOP_G3D_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
92 { EXYNOS3_CMU_CLKSTOP_LCD0_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
93 { EXYNOS3_CMU_CLKSTOP_ISP_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
94 { EXYNOS3_CMU_CLKSTOP_MAUDIO_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
95 { EXYNOS3_CMU_RESET_CAM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
96 { EXYNOS3_CMU_RESET_MFC_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
97 { EXYNOS3_CMU_RESET_G3D_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
98 { EXYNOS3_CMU_RESET_LCD0_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
99 { EXYNOS3_CMU_RESET_ISP_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
100 { EXYNOS3_CMU_RESET_MAUDIO_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
101 { EXYNOS3_TOP_BUS_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
102 { EXYNOS3_TOP_RETENTION_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
103 { EXYNOS3_TOP_PWR_SYS_PWR_REG, { 0x3, 0x3, 0x3} },
104 { EXYNOS3_TOP_BUS_COREBLK_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
105 { EXYNOS3_TOP_RETENTION_COREBLK_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
106 { EXYNOS3_TOP_PWR_COREBLK_SYS_PWR_REG, { 0x3, 0x3, 0x3} },
107 { EXYNOS3_LOGIC_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
108 { EXYNOS3_OSCCLK_GATE_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
109 { EXYNOS3_LOGIC_RESET_COREBLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
110 { EXYNOS3_OSCCLK_GATE_COREBLK_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
111 { EXYNOS3_PAD_RETENTION_DRAM_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
112 { EXYNOS3_PAD_RETENTION_MAUDIO_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
113 { EXYNOS3_PAD_RETENTION_GPIO_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
114 { EXYNOS3_PAD_RETENTION_UART_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
115 { EXYNOS3_PAD_RETENTION_MMC0_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
116 { EXYNOS3_PAD_RETENTION_MMC1_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
117 { EXYNOS3_PAD_RETENTION_MMC2_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
118 { EXYNOS3_PAD_RETENTION_SPI_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
119 { EXYNOS3_PAD_RETENTION_EBIA_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
120 { EXYNOS3_PAD_RETENTION_EBIB_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
121 { EXYNOS3_PAD_RETENTION_JTAG_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
122 { EXYNOS3_PAD_ISOLATION_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
123 { EXYNOS3_PAD_ALV_SEL_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
124 { EXYNOS3_XUSBXTI_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
125 { EXYNOS3_XXTI_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
126 { EXYNOS3_EXT_REGULATOR_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
127 { EXYNOS3_EXT_REGULATOR_COREBLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
128 { EXYNOS3_GPIO_MODE_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
129 { EXYNOS3_GPIO_MODE_MAUDIO_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
130 { EXYNOS3_TOP_ASB_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
131 { EXYNOS3_TOP_ASB_ISOLATION_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
132 { EXYNOS3_TOP_ASB_RESET_COREBLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
133 { EXYNOS3_TOP_ASB_ISOLATION_COREBLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
134 { EXYNOS3_CAM_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
135 { EXYNOS3_MFC_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
136 { EXYNOS3_G3D_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
137 { EXYNOS3_LCD0_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
138 { EXYNOS3_ISP_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
139 { EXYNOS3_MAUDIO_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
140 { EXYNOS3_CMU_SYSCLK_ISP_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
141 { PMU_TABLE_END,},
142};
19 143
20static const struct exynos_pmu_conf exynos4210_pmu_config[] = { 144static const struct exynos_pmu_conf exynos4210_pmu_config[] = {
21 /* { .offset = offset, .val = { AFTR, LPA, SLEEP } */ 145 /* { .offset = offset, .val = { AFTR, LPA, SLEEP } */
@@ -264,6 +388,7 @@ static const struct exynos_pmu_conf exynos5250_pmu_config[] = {
264 { EXYNOS5_INTRAM_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} }, 388 { EXYNOS5_INTRAM_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
265 { EXYNOS5_INTROM_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} }, 389 { EXYNOS5_INTROM_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
266 { EXYNOS5_JPEG_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} }, 390 { EXYNOS5_JPEG_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
391 { EXYNOS5_JPEG_MEM_OPTION, { 0x10, 0x10, 0x0} },
267 { EXYNOS5_HSI_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} }, 392 { EXYNOS5_HSI_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
268 { EXYNOS5_MCUIOP_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} }, 393 { EXYNOS5_MCUIOP_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
269 { EXYNOS5_SATA_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} }, 394 { EXYNOS5_SATA_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
@@ -315,6 +440,189 @@ static const struct exynos_pmu_conf exynos5250_pmu_config[] = {
315 { PMU_TABLE_END,}, 440 { PMU_TABLE_END,},
316}; 441};
317 442
443static struct exynos_pmu_conf exynos5420_pmu_config[] = {
444 /* { .offset = offset, .val = { AFTR, LPA, SLEEP } */
445 { EXYNOS5_ARM_CORE0_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
446 { EXYNOS5_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
447 { EXYNOS5_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
448 { EXYNOS5_ARM_CORE1_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
449 { EXYNOS5_DIS_IRQ_ARM_CORE1_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
450 { EXYNOS5_DIS_IRQ_ARM_CORE1_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
451 { EXYNOS5420_ARM_CORE2_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
452 { EXYNOS5420_DIS_IRQ_ARM_CORE2_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
453 { EXYNOS5420_DIS_IRQ_ARM_CORE2_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
454 { EXYNOS5420_ARM_CORE3_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
455 { EXYNOS5420_DIS_IRQ_ARM_CORE3_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
456 { EXYNOS5420_DIS_IRQ_ARM_CORE3_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
457 { EXYNOS5420_KFC_CORE0_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
458 { EXYNOS5420_DIS_IRQ_KFC_CORE0_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
459 { EXYNOS5420_DIS_IRQ_KFC_CORE0_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
460 { EXYNOS5420_KFC_CORE1_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
461 { EXYNOS5420_DIS_IRQ_KFC_CORE1_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
462 { EXYNOS5420_DIS_IRQ_KFC_CORE1_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
463 { EXYNOS5420_KFC_CORE2_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
464 { EXYNOS5420_DIS_IRQ_KFC_CORE2_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
465 { EXYNOS5420_DIS_IRQ_KFC_CORE2_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
466 { EXYNOS5420_KFC_CORE3_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
467 { EXYNOS5420_DIS_IRQ_KFC_CORE3_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
468 { EXYNOS5420_DIS_IRQ_KFC_CORE3_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
469 { EXYNOS5_ISP_ARM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
470 { EXYNOS5_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
471 { EXYNOS5_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
472 { EXYNOS5420_ARM_COMMON_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
473 { EXYNOS5420_KFC_COMMON_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
474 { EXYNOS5_ARM_L2_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
475 { EXYNOS5420_KFC_L2_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
476 { EXYNOS5_CMU_ACLKSTOP_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
477 { EXYNOS5_CMU_SCLKSTOP_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
478 { EXYNOS5_CMU_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
479 { EXYNOS5_CMU_ACLKSTOP_SYSMEM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
480 { EXYNOS5_CMU_SCLKSTOP_SYSMEM_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
481 { EXYNOS5_CMU_RESET_SYSMEM_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
482 { EXYNOS5_DRAM_FREQ_DOWN_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
483 { EXYNOS5_DDRPHY_DLLOFF_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
484 { EXYNOS5_DDRPHY_DLLLOCK_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
485 { EXYNOS5_APLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
486 { EXYNOS5_MPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
487 { EXYNOS5_VPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
488 { EXYNOS5_EPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
489 { EXYNOS5_BPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
490 { EXYNOS5_CPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
491 { EXYNOS5420_DPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
492 { EXYNOS5420_IPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
493 { EXYNOS5420_KPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
494 { EXYNOS5_MPLLUSER_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
495 { EXYNOS5_BPLLUSER_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
496 { EXYNOS5420_RPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
497 { EXYNOS5420_SPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
498 { EXYNOS5_TOP_BUS_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
499 { EXYNOS5_TOP_RETENTION_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
500 { EXYNOS5_TOP_PWR_SYS_PWR_REG, { 0x3, 0x3, 0x0} },
501 { EXYNOS5_TOP_BUS_SYSMEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
502 { EXYNOS5_TOP_RETENTION_SYSMEM_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
503 { EXYNOS5_TOP_PWR_SYSMEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
504 { EXYNOS5_LOGIC_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
505 { EXYNOS5_OSCCLK_GATE_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
506 { EXYNOS5_LOGIC_RESET_SYSMEM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
507 { EXYNOS5_OSCCLK_GATE_SYSMEM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
508 { EXYNOS5420_INTRAM_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x3} },
509 { EXYNOS5420_INTROM_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x3} },
510 { EXYNOS5_PAD_RETENTION_DRAM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
511 { EXYNOS5_PAD_RETENTION_MAU_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
512 { EXYNOS5420_PAD_RETENTION_JTAG_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
513 { EXYNOS5420_PAD_RETENTION_DRAM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
514 { EXYNOS5420_PAD_RETENTION_UART_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
515 { EXYNOS5420_PAD_RETENTION_MMC0_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
516 { EXYNOS5420_PAD_RETENTION_MMC1_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
517 { EXYNOS5420_PAD_RETENTION_MMC2_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
518 { EXYNOS5420_PAD_RETENTION_HSI_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
519 { EXYNOS5420_PAD_RETENTION_EBIA_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
520 { EXYNOS5420_PAD_RETENTION_EBIB_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
521 { EXYNOS5420_PAD_RETENTION_SPI_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
522 { EXYNOS5420_PAD_RETENTION_DRAM_COREBLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
523 { EXYNOS5_PAD_ISOLATION_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
524 { EXYNOS5_PAD_ISOLATION_SYSMEM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
525 { EXYNOS5_PAD_ALV_SEL_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
526 { EXYNOS5_XUSBXTI_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
527 { EXYNOS5_XXTI_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
528 { EXYNOS5_EXT_REGULATOR_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
529 { EXYNOS5_GPIO_MODE_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
530 { EXYNOS5_GPIO_MODE_SYSMEM_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
531 { EXYNOS5_GPIO_MODE_MAU_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
532 { EXYNOS5_TOP_ASB_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
533 { EXYNOS5_TOP_ASB_ISOLATION_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
534 { EXYNOS5_GSCL_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
535 { EXYNOS5_ISP_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
536 { EXYNOS5_MFC_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
537 { EXYNOS5_G3D_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
538 { EXYNOS5420_DISP1_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
539 { EXYNOS5420_MAU_SYS_PWR_REG, { 0x7, 0x7, 0x0} },
540 { EXYNOS5420_G2D_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
541 { EXYNOS5420_MSC_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
542 { EXYNOS5420_FSYS_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
543 { EXYNOS5420_FSYS2_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
544 { EXYNOS5420_PSGEN_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
545 { EXYNOS5420_PERIC_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
546 { EXYNOS5420_WCORE_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
547 { EXYNOS5_CMU_CLKSTOP_GSCL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
548 { EXYNOS5_CMU_CLKSTOP_ISP_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
549 { EXYNOS5_CMU_CLKSTOP_MFC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
550 { EXYNOS5_CMU_CLKSTOP_G3D_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
551 { EXYNOS5420_CMU_CLKSTOP_DISP1_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
552 { EXYNOS5420_CMU_CLKSTOP_MAU_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
553 { EXYNOS5420_CMU_CLKSTOP_G2D_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
554 { EXYNOS5420_CMU_CLKSTOP_MSC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
555 { EXYNOS5420_CMU_CLKSTOP_FSYS_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
556 { EXYNOS5420_CMU_CLKSTOP_PSGEN_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
557 { EXYNOS5420_CMU_CLKSTOP_PERIC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
558 { EXYNOS5420_CMU_CLKSTOP_WCORE_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
559 { EXYNOS5_CMU_SYSCLK_GSCL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
560 { EXYNOS5_CMU_SYSCLK_ISP_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
561 { EXYNOS5_CMU_SYSCLK_MFC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
562 { EXYNOS5_CMU_SYSCLK_G3D_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
563 { EXYNOS5420_CMU_SYSCLK_DISP1_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
564 { EXYNOS5420_CMU_SYSCLK_MAU_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
565 { EXYNOS5420_CMU_SYSCLK_G2D_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
566 { EXYNOS5420_CMU_SYSCLK_MSC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
567 { EXYNOS5420_CMU_SYSCLK_FSYS_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
568 { EXYNOS5420_CMU_SYSCLK_FSYS2_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
569 { EXYNOS5420_CMU_SYSCLK_PSGEN_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
570 { EXYNOS5420_CMU_SYSCLK_PERIC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
571 { EXYNOS5420_CMU_SYSCLK_WCORE_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
572 { EXYNOS5420_CMU_RESET_FSYS2_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
573 { EXYNOS5420_CMU_RESET_PSGEN_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
574 { EXYNOS5420_CMU_RESET_PERIC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
575 { EXYNOS5420_CMU_RESET_WCORE_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
576 { EXYNOS5_CMU_RESET_GSCL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
577 { EXYNOS5_CMU_RESET_ISP_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
578 { EXYNOS5_CMU_RESET_MFC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
579 { EXYNOS5_CMU_RESET_G3D_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
580 { EXYNOS5420_CMU_RESET_DISP1_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
581 { EXYNOS5420_CMU_RESET_MAU_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
582 { EXYNOS5420_CMU_RESET_G2D_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
583 { EXYNOS5420_CMU_RESET_MSC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
584 { EXYNOS5420_CMU_RESET_FSYS_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
585 { PMU_TABLE_END,},
586};
587
588static unsigned int const exynos3250_list_feed[] = {
589 EXYNOS3_ARM_CORE_OPTION(0),
590 EXYNOS3_ARM_CORE_OPTION(1),
591 EXYNOS3_ARM_CORE_OPTION(2),
592 EXYNOS3_ARM_CORE_OPTION(3),
593 EXYNOS3_ARM_COMMON_OPTION,
594 EXYNOS3_TOP_PWR_OPTION,
595 EXYNOS3_CORE_TOP_PWR_OPTION,
596 S5P_CAM_OPTION,
597 S5P_MFC_OPTION,
598 S5P_G3D_OPTION,
599 S5P_LCD0_OPTION,
600 S5P_ISP_OPTION,
601};
602
603static void exynos3250_powerdown_conf_extra(enum sys_powerdown mode)
604{
605 unsigned int i;
606 unsigned int tmp;
607
608 /* Enable only SC_FEEDBACK */
609 for (i = 0; i < ARRAY_SIZE(exynos3250_list_feed); i++) {
610 tmp = pmu_raw_readl(exynos3250_list_feed[i]);
611 tmp &= ~(EXYNOS3_OPTION_USE_SC_COUNTER);
612 tmp |= EXYNOS3_OPTION_USE_SC_FEEDBACK;
613 pmu_raw_writel(tmp, exynos3250_list_feed[i]);
614 }
615
616 if (mode != SYS_SLEEP)
617 return;
618
619 pmu_raw_writel(XUSBXTI_DURATION, EXYNOS3_XUSBXTI_DURATION);
620 pmu_raw_writel(XXTI_DURATION, EXYNOS3_XXTI_DURATION);
621 pmu_raw_writel(EXT_REGULATOR_DURATION, EXYNOS3_EXT_REGULATOR_DURATION);
622 pmu_raw_writel(EXT_REGULATOR_COREBLK_DURATION,
623 EXYNOS3_EXT_REGULATOR_COREBLK_DURATION);
624}
625
318static unsigned int const exynos5_list_both_cnt_feed[] = { 626static unsigned int const exynos5_list_both_cnt_feed[] = {
319 EXYNOS5_ARM_CORE0_OPTION, 627 EXYNOS5_ARM_CORE0_OPTION,
320 EXYNOS5_ARM_CORE1_OPTION, 628 EXYNOS5_ARM_CORE1_OPTION,
@@ -335,7 +643,76 @@ static unsigned int const exynos5_list_disable_wfi_wfe[] = {
335 EXYNOS5_ISP_ARM_OPTION, 643 EXYNOS5_ISP_ARM_OPTION,
336}; 644};
337 645
338static void exynos5_init_pmu(void) 646static unsigned int const exynos5420_list_disable_pmu_reg[] = {
647 EXYNOS5_CMU_CLKSTOP_GSCL_SYS_PWR_REG,
648 EXYNOS5_CMU_CLKSTOP_ISP_SYS_PWR_REG,
649 EXYNOS5_CMU_CLKSTOP_G3D_SYS_PWR_REG,
650 EXYNOS5420_CMU_CLKSTOP_DISP1_SYS_PWR_REG,
651 EXYNOS5420_CMU_CLKSTOP_MAU_SYS_PWR_REG,
652 EXYNOS5420_CMU_CLKSTOP_G2D_SYS_PWR_REG,
653 EXYNOS5420_CMU_CLKSTOP_MSC_SYS_PWR_REG,
654 EXYNOS5420_CMU_CLKSTOP_FSYS_SYS_PWR_REG,
655 EXYNOS5420_CMU_CLKSTOP_PSGEN_SYS_PWR_REG,
656 EXYNOS5420_CMU_CLKSTOP_PERIC_SYS_PWR_REG,
657 EXYNOS5420_CMU_CLKSTOP_WCORE_SYS_PWR_REG,
658 EXYNOS5_CMU_SYSCLK_GSCL_SYS_PWR_REG,
659 EXYNOS5_CMU_SYSCLK_ISP_SYS_PWR_REG,
660 EXYNOS5_CMU_SYSCLK_G3D_SYS_PWR_REG,
661 EXYNOS5420_CMU_SYSCLK_DISP1_SYS_PWR_REG,
662 EXYNOS5420_CMU_SYSCLK_MAU_SYS_PWR_REG,
663 EXYNOS5420_CMU_SYSCLK_G2D_SYS_PWR_REG,
664 EXYNOS5420_CMU_SYSCLK_MSC_SYS_PWR_REG,
665 EXYNOS5420_CMU_SYSCLK_FSYS_SYS_PWR_REG,
666 EXYNOS5420_CMU_SYSCLK_FSYS2_SYS_PWR_REG,
667 EXYNOS5420_CMU_SYSCLK_PSGEN_SYS_PWR_REG,
668 EXYNOS5420_CMU_SYSCLK_PERIC_SYS_PWR_REG,
669 EXYNOS5420_CMU_SYSCLK_WCORE_SYS_PWR_REG,
670 EXYNOS5420_CMU_RESET_FSYS2_SYS_PWR_REG,
671 EXYNOS5420_CMU_RESET_PSGEN_SYS_PWR_REG,
672 EXYNOS5420_CMU_RESET_PERIC_SYS_PWR_REG,
673 EXYNOS5420_CMU_RESET_WCORE_SYS_PWR_REG,
674 EXYNOS5_CMU_RESET_GSCL_SYS_PWR_REG,
675 EXYNOS5_CMU_RESET_ISP_SYS_PWR_REG,
676 EXYNOS5_CMU_RESET_G3D_SYS_PWR_REG,
677 EXYNOS5420_CMU_RESET_DISP1_SYS_PWR_REG,
678 EXYNOS5420_CMU_RESET_MAU_SYS_PWR_REG,
679 EXYNOS5420_CMU_RESET_G2D_SYS_PWR_REG,
680 EXYNOS5420_CMU_RESET_MSC_SYS_PWR_REG,
681 EXYNOS5420_CMU_RESET_FSYS_SYS_PWR_REG,
682};
683
684static void exynos5_power_off(void)
685{
686 unsigned int tmp;
687
688 pr_info("Power down.\n");
689 tmp = pmu_raw_readl(EXYNOS_PS_HOLD_CONTROL);
690 tmp ^= (1 << 8);
691 pmu_raw_writel(tmp, EXYNOS_PS_HOLD_CONTROL);
692
693 /* Wait a little so we don't give a false warning below */
694 mdelay(100);
695
696 pr_err("Power down failed, please power off system manually.\n");
697 while (1)
698 ;
699}
700
701void exynos5420_powerdown_conf(enum sys_powerdown mode)
702{
703 u32 this_cluster;
704
705 this_cluster = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 1);
706
707 /*
708 * set the cluster id to IROM register to ensure that we wake
709 * up with the current cluster.
710 */
711 pmu_raw_writel(this_cluster, EXYNOS_IROM_DATA2);
712}
713
714
715static void exynos5_powerdown_conf(enum sys_powerdown mode)
339{ 716{
340 unsigned int i; 717 unsigned int i;
341 unsigned int tmp; 718 unsigned int tmp;
@@ -343,7 +720,7 @@ static void exynos5_init_pmu(void)
343 /* 720 /*
344 * Enable both SC_FEEDBACK and SC_COUNTER 721 * Enable both SC_FEEDBACK and SC_COUNTER
345 */ 722 */
346 for (i = 0 ; i < ARRAY_SIZE(exynos5_list_both_cnt_feed) ; i++) { 723 for (i = 0; i < ARRAY_SIZE(exynos5_list_both_cnt_feed); i++) {
347 tmp = pmu_raw_readl(exynos5_list_both_cnt_feed[i]); 724 tmp = pmu_raw_readl(exynos5_list_both_cnt_feed[i]);
348 tmp |= (EXYNOS5_USE_SC_FEEDBACK | 725 tmp |= (EXYNOS5_USE_SC_FEEDBACK |
349 EXYNOS5_USE_SC_COUNTER); 726 EXYNOS5_USE_SC_COUNTER);
@@ -360,7 +737,7 @@ static void exynos5_init_pmu(void)
360 /* 737 /*
361 * Disable WFI/WFE on XXX_OPTION 738 * Disable WFI/WFE on XXX_OPTION
362 */ 739 */
363 for (i = 0 ; i < ARRAY_SIZE(exynos5_list_disable_wfi_wfe) ; i++) { 740 for (i = 0; i < ARRAY_SIZE(exynos5_list_disable_wfi_wfe); i++) {
364 tmp = pmu_raw_readl(exynos5_list_disable_wfi_wfe[i]); 741 tmp = pmu_raw_readl(exynos5_list_disable_wfi_wfe[i]);
365 tmp &= ~(EXYNOS5_OPTION_USE_STANDBYWFE | 742 tmp &= ~(EXYNOS5_OPTION_USE_STANDBYWFE |
366 EXYNOS5_OPTION_USE_STANDBYWFI); 743 EXYNOS5_OPTION_USE_STANDBYWFI);
@@ -372,51 +749,257 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode)
372{ 749{
373 unsigned int i; 750 unsigned int i;
374 751
375 if (soc_is_exynos5250()) 752 const struct exynos_pmu_data *pmu_data = pmu_context->pmu_data;
376 exynos5_init_pmu(); 753
754 if (pmu_data->powerdown_conf)
755 pmu_data->powerdown_conf(mode);
756
757 if (pmu_data->pmu_config) {
758 for (i = 0; (pmu_data->pmu_config[i].offset != PMU_TABLE_END); i++)
759 pmu_raw_writel(pmu_data->pmu_config[i].val[mode],
760 pmu_data->pmu_config[i].offset);
761 }
377 762
378 for (i = 0; (exynos_pmu_config[i].offset != PMU_TABLE_END) ; i++) 763 if (pmu_data->powerdown_conf_extra)
379 pmu_raw_writel(exynos_pmu_config[i].val[mode], 764 pmu_data->powerdown_conf_extra(mode);
380 exynos_pmu_config[i].offset);
381 765
382 if (soc_is_exynos4412()) { 766 if (pmu_data->pmu_config_extra) {
383 for (i = 0; exynos4412_pmu_config[i].offset != PMU_TABLE_END ; i++) 767 for (i = 0; pmu_data->pmu_config_extra[i].offset != PMU_TABLE_END; i++)
384 pmu_raw_writel(exynos4412_pmu_config[i].val[mode], 768 pmu_raw_writel(pmu_data->pmu_config_extra[i].val[mode],
385 exynos4412_pmu_config[i].offset); 769 pmu_data->pmu_config_extra[i].offset);
386 } 770 }
387} 771}
388 772
389static int __init exynos_pmu_init(void) 773static void exynos3250_pmu_init(void)
774{
775 unsigned int value;
776
777 /*
778 * To prevent from issuing new bus request form L2 memory system
779 * If core status is power down, should be set '1' to L2 power down
780 */
781 value = pmu_raw_readl(EXYNOS3_ARM_COMMON_OPTION);
782 value |= EXYNOS3_OPTION_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
783 pmu_raw_writel(value, EXYNOS3_ARM_COMMON_OPTION);
784
785 /* Enable USE_STANDBY_WFI for all CORE */
786 pmu_raw_writel(S5P_USE_STANDBY_WFI_ALL, S5P_CENTRAL_SEQ_OPTION);
787
788 /*
789 * Set PSHOLD port for output high
790 */
791 value = pmu_raw_readl(S5P_PS_HOLD_CONTROL);
792 value |= S5P_PS_HOLD_OUTPUT_HIGH;
793 pmu_raw_writel(value, S5P_PS_HOLD_CONTROL);
794
795 /*
796 * Enable signal for PSHOLD port
797 */
798 value = pmu_raw_readl(S5P_PS_HOLD_CONTROL);
799 value |= S5P_PS_HOLD_EN;
800 pmu_raw_writel(value, S5P_PS_HOLD_CONTROL);
801}
802
803static void exynos5250_pmu_init(void)
390{ 804{
391 unsigned int value; 805 unsigned int value;
806 /*
807 * When SYS_WDTRESET is set, watchdog timer reset request
808 * is ignored by power management unit.
809 */
810 value = pmu_raw_readl(EXYNOS5_AUTO_WDTRESET_DISABLE);
811 value &= ~EXYNOS5_SYS_WDTRESET;
812 pmu_raw_writel(value, EXYNOS5_AUTO_WDTRESET_DISABLE);
813
814 value = pmu_raw_readl(EXYNOS5_MASK_WDTRESET_REQUEST);
815 value &= ~EXYNOS5_SYS_WDTRESET;
816 pmu_raw_writel(value, EXYNOS5_MASK_WDTRESET_REQUEST);
817}
818
819static void exynos5420_pmu_init(void)
820{
821 unsigned int value;
822 int i;
823
824 /*
825 * Set the CMU_RESET, CMU_SYSCLK and CMU_CLKSTOP registers
826 * for local power blocks to Low initially as per Table 8-4:
827 * "System-Level Power-Down Configuration Registers".
828 */
829 for (i = 0; i < ARRAY_SIZE(exynos5420_list_disable_pmu_reg); i++)
830 pmu_raw_writel(0, exynos5420_list_disable_pmu_reg[i]);
831
832 /* Enable USE_STANDBY_WFI for all CORE */
833 pmu_raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL, S5P_CENTRAL_SEQ_OPTION);
834
835 value = pmu_raw_readl(EXYNOS_L2_OPTION(0));
836 value &= ~EXYNOS5_USE_RETENTION;
837 pmu_raw_writel(value, EXYNOS_L2_OPTION(0));
838
839 value = pmu_raw_readl(EXYNOS_L2_OPTION(1));
840 value &= ~EXYNOS5_USE_RETENTION;
841 pmu_raw_writel(value, EXYNOS_L2_OPTION(1));
842
843 /*
844 * If L2_COMMON is turned off, clocks related to ATB async
845 * bridge are gated. Thus, when ISP power is gated, LPI
846 * may get stuck.
847 */
848 value = pmu_raw_readl(EXYNOS5420_LPI_MASK);
849 value |= EXYNOS5420_ATB_ISP_ARM;
850 pmu_raw_writel(value, EXYNOS5420_LPI_MASK);
851
852 value = pmu_raw_readl(EXYNOS5420_LPI_MASK1);
853 value |= EXYNOS5420_ATB_KFC;
854 pmu_raw_writel(value, EXYNOS5420_LPI_MASK1);
855
856 /* Prevent issue of new bus request from L2 memory */
857 value = pmu_raw_readl(EXYNOS5420_ARM_COMMON_OPTION);
858 value |= EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
859 pmu_raw_writel(value, EXYNOS5420_ARM_COMMON_OPTION);
860
861 value = pmu_raw_readl(EXYNOS5420_KFC_COMMON_OPTION);
862 value |= EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
863 pmu_raw_writel(value, EXYNOS5420_KFC_COMMON_OPTION);
864
865 /* This setting is to reduce suspend/resume time */
866 pmu_raw_writel(DUR_WAIT_RESET, EXYNOS5420_LOGIC_RESET_DURATION3);
867
868 /* Serialized CPU wakeup of Eagle */
869 pmu_raw_writel(SPREAD_ENABLE, EXYNOS5420_ARM_INTR_SPREAD_ENABLE);
870
871 pmu_raw_writel(SPREAD_USE_STANDWFI,
872 EXYNOS5420_ARM_INTR_SPREAD_USE_STANDBYWFI);
873
874 pmu_raw_writel(0x1, EXYNOS5420_UP_SCHEDULER);
875
876 pm_power_off = exynos5_power_off;
877 pr_info("EXYNOS5420 PMU initialized\n");
878}
879
880static int pmu_restart_notify(struct notifier_block *this,
881 unsigned long code, void *unused)
882{
883 pmu_raw_writel(0x1, EXYNOS_SWRESET);
884
885 return NOTIFY_DONE;
886}
887
888static const struct exynos_pmu_data exynos3250_pmu_data = {
889 .pmu_config = exynos3250_pmu_config,
890 .pmu_init = exynos3250_pmu_init,
891 .powerdown_conf_extra = exynos3250_powerdown_conf_extra,
892};
392 893
393 exynos_pmu_config = exynos4210_pmu_config; 894static const struct exynos_pmu_data exynos4210_pmu_data = {
394 895 .pmu_config = exynos4210_pmu_config,
395 if (soc_is_exynos4210()) { 896};
396 exynos_pmu_config = exynos4210_pmu_config; 897
397 pr_info("EXYNOS4210 PMU Initialize\n"); 898static const struct exynos_pmu_data exynos4212_pmu_data = {
398 } else if (soc_is_exynos4212() || soc_is_exynos4412()) { 899 .pmu_config = exynos4x12_pmu_config,
399 exynos_pmu_config = exynos4x12_pmu_config; 900};
400 pr_info("EXYNOS4x12 PMU Initialize\n"); 901
401 } else if (soc_is_exynos5250()) { 902static const struct exynos_pmu_data exynos4412_pmu_data = {
402 /* 903 .pmu_config = exynos4x12_pmu_config,
403 * When SYS_WDTRESET is set, watchdog timer reset request 904 .pmu_config_extra = exynos4412_pmu_config,
404 * is ignored by power management unit. 905};
405 */ 906
406 value = pmu_raw_readl(EXYNOS5_AUTO_WDTRESET_DISABLE); 907static const struct exynos_pmu_data exynos5250_pmu_data = {
407 value &= ~EXYNOS5_SYS_WDTRESET; 908 .pmu_config = exynos5250_pmu_config,
408 pmu_raw_writel(value, EXYNOS5_AUTO_WDTRESET_DISABLE); 909 .pmu_init = exynos5250_pmu_init,
409 910 .powerdown_conf = exynos5_powerdown_conf,
410 value = pmu_raw_readl(EXYNOS5_MASK_WDTRESET_REQUEST); 911};
411 value &= ~EXYNOS5_SYS_WDTRESET; 912
412 pmu_raw_writel(value, EXYNOS5_MASK_WDTRESET_REQUEST); 913static struct exynos_pmu_data exynos5420_pmu_data = {
413 914 .pmu_config = exynos5420_pmu_config,
414 exynos_pmu_config = exynos5250_pmu_config; 915 .pmu_init = exynos5420_pmu_init,
415 pr_info("EXYNOS5250 PMU Initialize\n"); 916 .powerdown_conf = exynos5420_powerdown_conf,
416 } else { 917};
417 pr_info("EXYNOS: PMU not supported\n"); 918
919/*
920 * PMU platform driver and devicetree bindings.
921 */
922static const struct of_device_id exynos_pmu_of_device_ids[] = {
923 {
924 .compatible = "samsung,exynos3250-pmu",
925 .data = &exynos3250_pmu_data,
926 }, {
927 .compatible = "samsung,exynos4210-pmu",
928 .data = &exynos4210_pmu_data,
929 }, {
930 .compatible = "samsung,exynos4212-pmu",
931 .data = &exynos4212_pmu_data,
932 }, {
933 .compatible = "samsung,exynos4412-pmu",
934 .data = &exynos4412_pmu_data,
935 }, {
936 .compatible = "samsung,exynos5250-pmu",
937 .data = &exynos5250_pmu_data,
938 }, {
939 .compatible = "samsung,exynos5420-pmu",
940 .data = &exynos5420_pmu_data,
941 },
942 { /*sentinel*/ },
943};
944
945/*
946 * Exynos PMU restart notifier, handles restart functionality
947 */
948static struct notifier_block pmu_restart_handler = {
949 .notifier_call = pmu_restart_notify,
950 .priority = 128,
951};
952
953static int exynos_pmu_probe(struct platform_device *pdev)
954{
955 const struct of_device_id *match;
956 struct device *dev = &pdev->dev;
957 struct resource *res;
958 int ret;
959
960 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
961 pmu_base_addr = devm_ioremap_resource(dev, res);
962 if (IS_ERR(pmu_base_addr))
963 return PTR_ERR(pmu_base_addr);
964
965 pmu_context = devm_kzalloc(&pdev->dev,
966 sizeof(struct exynos_pmu_context),
967 GFP_KERNEL);
968 if (!pmu_context) {
969 dev_err(dev, "Cannot allocate memory.\n");
970 return -ENOMEM;
418 } 971 }
972 pmu_context->dev = dev;
973
974 match = of_match_node(exynos_pmu_of_device_ids, dev->of_node);
975
976 pmu_context->pmu_data = match->data;
977
978 if (pmu_context->pmu_data->pmu_init)
979 pmu_context->pmu_data->pmu_init();
980
981 platform_set_drvdata(pdev, pmu_context);
419 982
983 ret = register_restart_handler(&pmu_restart_handler);
984 if (ret)
985 dev_warn(dev, "can't register restart handler err=%d\n", ret);
986
987 dev_dbg(dev, "Exynos PMU Driver probe done\n");
420 return 0; 988 return 0;
421} 989}
422arch_initcall(exynos_pmu_init); 990
991static struct platform_driver exynos_pmu_driver = {
992 .driver = {
993 .name = "exynos-pmu",
994 .owner = THIS_MODULE,
995 .of_match_table = exynos_pmu_of_device_ids,
996 },
997 .probe = exynos_pmu_probe,
998};
999
1000static int __init exynos_pmu_init(void)
1001{
1002 return platform_driver_register(&exynos_pmu_driver);
1003
1004}
1005postcore_initcall(exynos_pmu_init);
diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h
index 4e9b4440e2bd..b5f4406fc1b5 100644
--- a/arch/arm/mach-exynos/regs-pmu.h
+++ b/arch/arm/mach-exynos/regs-pmu.h
@@ -19,9 +19,24 @@
19#define S5P_CENTRAL_SEQ_OPTION 0x0208 19#define S5P_CENTRAL_SEQ_OPTION 0x0208
20 20
21#define S5P_USE_STANDBY_WFI0 (1 << 16) 21#define S5P_USE_STANDBY_WFI0 (1 << 16)
22#define S5P_USE_STANDBY_WFI1 (1 << 17)
23#define S5P_USE_STANDBY_WFI2 (1 << 19)
24#define S5P_USE_STANDBY_WFI3 (1 << 20)
22#define S5P_USE_STANDBY_WFE0 (1 << 24) 25#define S5P_USE_STANDBY_WFE0 (1 << 24)
26#define S5P_USE_STANDBY_WFE1 (1 << 25)
27#define S5P_USE_STANDBY_WFE2 (1 << 27)
28#define S5P_USE_STANDBY_WFE3 (1 << 28)
29
30#define S5P_USE_STANDBY_WFI_ALL \
31 (S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFI1 | \
32 S5P_USE_STANDBY_WFI2 | S5P_USE_STANDBY_WFI3 | \
33 S5P_USE_STANDBY_WFE0 | S5P_USE_STANDBY_WFE1 | \
34 S5P_USE_STANDBY_WFE2 | S5P_USE_STANDBY_WFE3)
35
23#define S5P_USE_DELAYED_RESET_ASSERTION BIT(12) 36#define S5P_USE_DELAYED_RESET_ASSERTION BIT(12)
24 37
38#define EXYNOS_CORE_PO_RESET(n) ((1 << 4) << n)
39#define EXYNOS_WAKEUP_FROM_LOWPWR (1 << 28)
25#define EXYNOS_SWRESET 0x0400 40#define EXYNOS_SWRESET 0x0400
26#define EXYNOS5440_SWRESET 0x00C4 41#define EXYNOS5440_SWRESET 0x00C4
27 42
@@ -36,6 +51,7 @@
36#define S5P_INFORM7 0x081C 51#define S5P_INFORM7 0x081C
37#define S5P_PMU_SPARE3 0x090C 52#define S5P_PMU_SPARE3 0x090C
38 53
54#define EXYNOS_IROM_DATA2 0x0988
39#define S5P_ARM_CORE0_LOWPWR 0x1000 55#define S5P_ARM_CORE0_LOWPWR 0x1000
40#define S5P_DIS_IRQ_CORE0 0x1004 56#define S5P_DIS_IRQ_CORE0 0x1004
41#define S5P_DIS_IRQ_CENTRAL0 0x1008 57#define S5P_DIS_IRQ_CENTRAL0 0x1008
@@ -118,6 +134,31 @@
118#define EXYNOS_COMMON_OPTION(_nr) \ 134#define EXYNOS_COMMON_OPTION(_nr) \
119 (EXYNOS_COMMON_CONFIGURATION(_nr) + 0x8) 135 (EXYNOS_COMMON_CONFIGURATION(_nr) + 0x8)
120 136
137#define EXYNOS_CORE_LOCAL_PWR_EN 0x3
138
139#define EXYNOS_ARM_COMMON_STATUS 0x2504
140#define EXYNOS_COMMON_OPTION(_nr) \
141 (EXYNOS_COMMON_CONFIGURATION(_nr) + 0x8)
142
143#define EXYNOS_ARM_L2_CONFIGURATION 0x2600
144#define EXYNOS_L2_CONFIGURATION(_nr) \
145 (EXYNOS_ARM_L2_CONFIGURATION + ((_nr) * 0x80))
146#define EXYNOS_L2_STATUS(_nr) \
147 (EXYNOS_L2_CONFIGURATION(_nr) + 0x4)
148#define EXYNOS_L2_OPTION(_nr) \
149 (EXYNOS_L2_CONFIGURATION(_nr) + 0x8)
150#define EXYNOS_L2_COMMON_PWR_EN 0x3
151
152#define EXYNOS_ARM_CORE_X_STATUS_OFFSET 0x4
153
154#define EXYNOS5_APLL_SYSCLK_CONFIGURATION 0x2A00
155#define EXYNOS5_APLL_SYSCLK_STATUS 0x2A04
156
157#define EXYNOS5_ARM_L2_OPTION 0x2608
158#define EXYNOS5_USE_RETENTION BIT(4)
159
160#define EXYNOS5_L2RSTDISABLE_VALUE BIT(3)
161
121#define S5P_PAD_RET_MAUDIO_OPTION 0x3028 162#define S5P_PAD_RET_MAUDIO_OPTION 0x3028
122#define S5P_PAD_RET_GPIO_OPTION 0x3108 163#define S5P_PAD_RET_GPIO_OPTION 0x3108
123#define S5P_PAD_RET_UART_OPTION 0x3128 164#define S5P_PAD_RET_UART_OPTION 0x3128
@@ -126,7 +167,19 @@
126#define S5P_PAD_RET_EBIA_OPTION 0x3188 167#define S5P_PAD_RET_EBIA_OPTION 0x3188
127#define S5P_PAD_RET_EBIB_OPTION 0x31A8 168#define S5P_PAD_RET_EBIB_OPTION 0x31A8
128 169
170#define S5P_PS_HOLD_CONTROL 0x330C
171#define S5P_PS_HOLD_EN (1 << 31)
172#define S5P_PS_HOLD_OUTPUT_HIGH (3 << 8)
173
174#define S5P_CAM_OPTION 0x3C08
175#define S5P_MFC_OPTION 0x3C48
176#define S5P_G3D_OPTION 0x3C68
177#define S5P_LCD0_OPTION 0x3C88
178#define S5P_LCD1_OPTION 0x3CA8
179#define S5P_ISP_OPTION S5P_LCD1_OPTION
180
129#define S5P_CORE_LOCAL_PWR_EN 0x3 181#define S5P_CORE_LOCAL_PWR_EN 0x3
182#define S5P_CORE_WAKEUP_FROM_LOCAL_CFG (0x3 << 8)
130 183
131/* Only for EXYNOS4210 */ 184/* Only for EXYNOS4210 */
132#define S5P_CMU_CLKSTOP_LCD1_LOWPWR 0x1154 185#define S5P_CMU_CLKSTOP_LCD1_LOWPWR 0x1154
@@ -185,11 +238,116 @@
185#define S5P_DIS_IRQ_CORE3 0x1034 238#define S5P_DIS_IRQ_CORE3 0x1034
186#define S5P_DIS_IRQ_CENTRAL3 0x1038 239#define S5P_DIS_IRQ_CENTRAL3 0x1038
187 240
241/* Only for EXYNOS3XXX */
242#define EXYNOS3_ARM_CORE0_SYS_PWR_REG 0x1000
243#define EXYNOS3_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG 0x1004
244#define EXYNOS3_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG 0x1008
245#define EXYNOS3_ARM_CORE1_SYS_PWR_REG 0x1010
246#define EXYNOS3_DIS_IRQ_ARM_CORE1_LOCAL_SYS_PWR_REG 0x1014
247#define EXYNOS3_DIS_IRQ_ARM_CORE1_CENTRAL_SYS_PWR_REG 0x1018
248#define EXYNOS3_ISP_ARM_SYS_PWR_REG 0x1050
249#define EXYNOS3_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG 0x1054
250#define EXYNOS3_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG 0x1058
251#define EXYNOS3_ARM_COMMON_SYS_PWR_REG 0x1080
252#define EXYNOS3_ARM_L2_SYS_PWR_REG 0x10C0
253#define EXYNOS3_CMU_ACLKSTOP_SYS_PWR_REG 0x1100
254#define EXYNOS3_CMU_SCLKSTOP_SYS_PWR_REG 0x1104
255#define EXYNOS3_CMU_RESET_SYS_PWR_REG 0x110C
256#define EXYNOS3_CMU_ACLKSTOP_COREBLK_SYS_PWR_REG 0x1110
257#define EXYNOS3_CMU_SCLKSTOP_COREBLK_SYS_PWR_REG 0x1114
258#define EXYNOS3_CMU_RESET_COREBLK_SYS_PWR_REG 0x111C
259#define EXYNOS3_APLL_SYSCLK_SYS_PWR_REG 0x1120
260#define EXYNOS3_MPLL_SYSCLK_SYS_PWR_REG 0x1124
261#define EXYNOS3_VPLL_SYSCLK_SYS_PWR_REG 0x1128
262#define EXYNOS3_EPLL_SYSCLK_SYS_PWR_REG 0x112C
263#define EXYNOS3_MPLLUSER_SYSCLK_SYS_PWR_REG 0x1130
264#define EXYNOS3_BPLLUSER_SYSCLK_SYS_PWR_REG 0x1134
265#define EXYNOS3_EPLLUSER_SYSCLK_SYS_PWR_REG 0x1138
266#define EXYNOS3_CMU_CLKSTOP_CAM_SYS_PWR_REG 0x1140
267#define EXYNOS3_CMU_CLKSTOP_MFC_SYS_PWR_REG 0x1148
268#define EXYNOS3_CMU_CLKSTOP_G3D_SYS_PWR_REG 0x114C
269#define EXYNOS3_CMU_CLKSTOP_LCD0_SYS_PWR_REG 0x1150
270#define EXYNOS3_CMU_CLKSTOP_ISP_SYS_PWR_REG 0x1154
271#define EXYNOS3_CMU_CLKSTOP_MAUDIO_SYS_PWR_REG 0x1158
272#define EXYNOS3_CMU_RESET_CAM_SYS_PWR_REG 0x1160
273#define EXYNOS3_CMU_RESET_MFC_SYS_PWR_REG 0x1168
274#define EXYNOS3_CMU_RESET_G3D_SYS_PWR_REG 0x116C
275#define EXYNOS3_CMU_RESET_LCD0_SYS_PWR_REG 0x1170
276#define EXYNOS3_CMU_RESET_ISP_SYS_PWR_REG 0x1174
277#define EXYNOS3_CMU_RESET_MAUDIO_SYS_PWR_REG 0x1178
278#define EXYNOS3_TOP_BUS_SYS_PWR_REG 0x1180
279#define EXYNOS3_TOP_RETENTION_SYS_PWR_REG 0x1184
280#define EXYNOS3_TOP_PWR_SYS_PWR_REG 0x1188
281#define EXYNOS3_TOP_BUS_COREBLK_SYS_PWR_REG 0x1190
282#define EXYNOS3_TOP_RETENTION_COREBLK_SYS_PWR_REG 0x1194
283#define EXYNOS3_TOP_PWR_COREBLK_SYS_PWR_REG 0x1198
284#define EXYNOS3_LOGIC_RESET_SYS_PWR_REG 0x11A0
285#define EXYNOS3_OSCCLK_GATE_SYS_PWR_REG 0x11A4
286#define EXYNOS3_LOGIC_RESET_COREBLK_SYS_PWR_REG 0x11B0
287#define EXYNOS3_OSCCLK_GATE_COREBLK_SYS_PWR_REG 0x11B4
288#define EXYNOS3_PAD_RETENTION_DRAM_SYS_PWR_REG 0x1200
289#define EXYNOS3_PAD_RETENTION_MAUDIO_SYS_PWR_REG 0x1204
290#define EXYNOS3_PAD_RETENTION_SPI_SYS_PWR_REG 0x1208
291#define EXYNOS3_PAD_RETENTION_MMC2_SYS_PWR_REG 0x1218
292#define EXYNOS3_PAD_RETENTION_GPIO_SYS_PWR_REG 0x1220
293#define EXYNOS3_PAD_RETENTION_UART_SYS_PWR_REG 0x1224
294#define EXYNOS3_PAD_RETENTION_MMC0_SYS_PWR_REG 0x1228
295#define EXYNOS3_PAD_RETENTION_MMC1_SYS_PWR_REG 0x122C
296#define EXYNOS3_PAD_RETENTION_EBIA_SYS_PWR_REG 0x1230
297#define EXYNOS3_PAD_RETENTION_EBIB_SYS_PWR_REG 0x1234
298#define EXYNOS3_PAD_RETENTION_JTAG_SYS_PWR_REG 0x1238
299#define EXYNOS3_PAD_ISOLATION_SYS_PWR_REG 0x1240
300#define EXYNOS3_PAD_ALV_SEL_SYS_PWR_REG 0x1260
301#define EXYNOS3_XUSBXTI_SYS_PWR_REG 0x1280
302#define EXYNOS3_XXTI_SYS_PWR_REG 0x1284
303#define EXYNOS3_EXT_REGULATOR_SYS_PWR_REG 0x12C0
304#define EXYNOS3_EXT_REGULATOR_COREBLK_SYS_PWR_REG 0x12C4
305#define EXYNOS3_GPIO_MODE_SYS_PWR_REG 0x1300
306#define EXYNOS3_GPIO_MODE_MAUDIO_SYS_PWR_REG 0x1340
307#define EXYNOS3_TOP_ASB_RESET_SYS_PWR_REG 0x1344
308#define EXYNOS3_TOP_ASB_ISOLATION_SYS_PWR_REG 0x1348
309#define EXYNOS3_TOP_ASB_RESET_COREBLK_SYS_PWR_REG 0x1350
310#define EXYNOS3_TOP_ASB_ISOLATION_COREBLK_SYS_PWR_REG 0x1354
311#define EXYNOS3_CAM_SYS_PWR_REG 0x1380
312#define EXYNOS3_MFC_SYS_PWR_REG 0x1388
313#define EXYNOS3_G3D_SYS_PWR_REG 0x138C
314#define EXYNOS3_LCD0_SYS_PWR_REG 0x1390
315#define EXYNOS3_ISP_SYS_PWR_REG 0x1394
316#define EXYNOS3_MAUDIO_SYS_PWR_REG 0x1398
317#define EXYNOS3_DRAM_FREQ_DOWN_SYS_PWR_REG 0x13B0
318#define EXYNOS3_DDRPHY_DLLOFF_SYS_PWR_REG 0x13B4
319#define EXYNOS3_CMU_SYSCLK_ISP_SYS_PWR_REG 0x13B8
320#define EXYNOS3_LPDDR_PHY_DLL_LOCK_SYS_PWR_REG 0x13C0
321#define EXYNOS3_BPLL_SYSCLK_SYS_PWR_REG 0x13C4
322#define EXYNOS3_UPLL_SYSCLK_SYS_PWR_REG 0x13C8
323
324#define EXYNOS3_ARM_CORE0_OPTION 0x2008
325#define EXYNOS3_ARM_CORE_OPTION(_nr) \
326 (EXYNOS3_ARM_CORE0_OPTION + ((_nr) * 0x80))
327
328#define EXYNOS3_ARM_COMMON_OPTION 0x2408
329#define EXYNOS3_TOP_PWR_OPTION 0x2C48
330#define EXYNOS3_CORE_TOP_PWR_OPTION 0x2CA8
331#define EXYNOS3_XUSBXTI_DURATION 0x341C
332#define EXYNOS3_XXTI_DURATION 0x343C
333#define EXYNOS3_EXT_REGULATOR_DURATION 0x361C
334#define EXYNOS3_EXT_REGULATOR_COREBLK_DURATION 0x363C
335#define XUSBXTI_DURATION 0x00000BB8
336#define XXTI_DURATION XUSBXTI_DURATION
337#define EXT_REGULATOR_DURATION 0x00001D4C
338#define EXT_REGULATOR_COREBLK_DURATION EXT_REGULATOR_DURATION
339
340/* for XXX_OPTION */
341#define EXYNOS3_OPTION_USE_SC_COUNTER (1 << 0)
342#define EXYNOS3_OPTION_USE_SC_FEEDBACK (1 << 1)
343#define EXYNOS3_OPTION_SKIP_DEACTIVATE_ACEACP_IN_PWDN (1 << 7)
344
188/* For EXYNOS5 */ 345/* For EXYNOS5 */
189 346
190#define EXYNOS5_AUTO_WDTRESET_DISABLE 0x0408 347#define EXYNOS5_AUTO_WDTRESET_DISABLE 0x0408
191#define EXYNOS5_MASK_WDTRESET_REQUEST 0x040C 348#define EXYNOS5_MASK_WDTRESET_REQUEST 0x040C
192 349
350#define EXYNOS5_USE_RETENTION BIT(4)
193#define EXYNOS5_SYS_WDTRESET (1 << 20) 351#define EXYNOS5_SYS_WDTRESET (1 << 20)
194 352
195#define EXYNOS5_ARM_CORE0_SYS_PWR_REG 0x1000 353#define EXYNOS5_ARM_CORE0_SYS_PWR_REG 0x1000
@@ -329,4 +487,204 @@ static inline unsigned int exynos_pmu_cpunr(unsigned int mpidr)
329 + MPIDR_AFFINITY_LEVEL(mpidr, 0)); 487 + MPIDR_AFFINITY_LEVEL(mpidr, 0));
330} 488}
331 489
490/* Only for EXYNOS5420 */
491#define EXYNOS5420_ISP_ARM_OPTION 0x2488
492#define EXYNOS5420_L2RSTDISABLE_VALUE BIT(3)
493
494#define EXYNOS5420_LPI_MASK 0x0004
495#define EXYNOS5420_LPI_MASK1 0x0008
496#define EXYNOS5420_UFS BIT(8)
497#define EXYNOS5420_ATB_KFC BIT(13)
498#define EXYNOS5420_ATB_ISP_ARM BIT(19)
499#define EXYNOS5420_EMULATION BIT(31)
500#define ATB_ISP_ARM BIT(12)
501#define ATB_KFC BIT(13)
502#define ATB_NOC BIT(14)
503
504#define EXYNOS5420_ARM_INTR_SPREAD_ENABLE 0x0100
505#define EXYNOS5420_ARM_INTR_SPREAD_USE_STANDBYWFI 0x0104
506#define EXYNOS5420_UP_SCHEDULER 0x0120
507#define SPREAD_ENABLE 0xF
508#define SPREAD_USE_STANDWFI 0xF
509
510#define EXYNOS5420_BB_CON1 0x0784
511#define EXYNOS5420_BB_SEL_EN BIT(31)
512#define EXYNOS5420_BB_PMOS_EN BIT(7)
513#define EXYNOS5420_BB_1300X 0XF
514
515#define EXYNOS5420_ARM_CORE2_SYS_PWR_REG 0x1020
516#define EXYNOS5420_DIS_IRQ_ARM_CORE2_LOCAL_SYS_PWR_REG 0x1024
517#define EXYNOS5420_DIS_IRQ_ARM_CORE2_CENTRAL_SYS_PWR_REG 0x1028
518#define EXYNOS5420_ARM_CORE3_SYS_PWR_REG 0x1030
519#define EXYNOS5420_DIS_IRQ_ARM_CORE3_LOCAL_SYS_PWR_REG 0x1034
520#define EXYNOS5420_DIS_IRQ_ARM_CORE3_CENTRAL_SYS_PWR_REG 0x1038
521#define EXYNOS5420_KFC_CORE0_SYS_PWR_REG 0x1040
522#define EXYNOS5420_DIS_IRQ_KFC_CORE0_LOCAL_SYS_PWR_REG 0x1044
523#define EXYNOS5420_DIS_IRQ_KFC_CORE0_CENTRAL_SYS_PWR_REG 0x1048
524#define EXYNOS5420_KFC_CORE1_SYS_PWR_REG 0x1050
525#define EXYNOS5420_DIS_IRQ_KFC_CORE1_LOCAL_SYS_PWR_REG 0x1054
526#define EXYNOS5420_DIS_IRQ_KFC_CORE1_CENTRAL_SYS_PWR_REG 0x1058
527#define EXYNOS5420_KFC_CORE2_SYS_PWR_REG 0x1060
528#define EXYNOS5420_DIS_IRQ_KFC_CORE2_LOCAL_SYS_PWR_REG 0x1064
529#define EXYNOS5420_DIS_IRQ_KFC_CORE2_CENTRAL_SYS_PWR_REG 0x1068
530#define EXYNOS5420_KFC_CORE3_SYS_PWR_REG 0x1070
531#define EXYNOS5420_DIS_IRQ_KFC_CORE3_LOCAL_SYS_PWR_REG 0x1074
532#define EXYNOS5420_DIS_IRQ_KFC_CORE3_CENTRAL_SYS_PWR_REG 0x1078
533#define EXYNOS5420_ISP_ARM_SYS_PWR_REG 0x1090
534#define EXYNOS5420_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG 0x1094
535#define EXYNOS5420_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG 0x1098
536#define EXYNOS5420_ARM_COMMON_SYS_PWR_REG 0x10A0
537#define EXYNOS5420_KFC_COMMON_SYS_PWR_REG 0x10B0
538#define EXYNOS5420_KFC_L2_SYS_PWR_REG 0x10D0
539#define EXYNOS5420_DPLL_SYSCLK_SYS_PWR_REG 0x1158
540#define EXYNOS5420_IPLL_SYSCLK_SYS_PWR_REG 0x115C
541#define EXYNOS5420_KPLL_SYSCLK_SYS_PWR_REG 0x1160
542#define EXYNOS5420_RPLL_SYSCLK_SYS_PWR_REG 0x1174
543#define EXYNOS5420_SPLL_SYSCLK_SYS_PWR_REG 0x1178
544#define EXYNOS5420_INTRAM_MEM_SYS_PWR_REG 0x11B8
545#define EXYNOS5420_INTROM_MEM_SYS_PWR_REG 0x11BC
546#define EXYNOS5420_ONENANDXL_MEM_SYS_PWR 0x11C0
547#define EXYNOS5420_USBDEV_MEM_SYS_PWR 0x11CC
548#define EXYNOS5420_USBDEV1_MEM_SYS_PWR 0x11D0
549#define EXYNOS5420_SDMMC_MEM_SYS_PWR 0x11D4
550#define EXYNOS5420_CSSYS_MEM_SYS_PWR 0x11D8
551#define EXYNOS5420_SECSS_MEM_SYS_PWR 0x11DC
552#define EXYNOS5420_ROTATOR_MEM_SYS_PWR 0x11E0
553#define EXYNOS5420_INTRAM_MEM_SYS_PWR 0x11E4
554#define EXYNOS5420_INTROM_MEM_SYS_PWR 0x11E8
555#define EXYNOS5420_PAD_RETENTION_JTAG_SYS_PWR_REG 0x1208
556#define EXYNOS5420_PAD_RETENTION_DRAM_SYS_PWR_REG 0x1210
557#define EXYNOS5420_PAD_RETENTION_UART_SYS_PWR_REG 0x1214
558#define EXYNOS5420_PAD_RETENTION_MMC0_SYS_PWR_REG 0x1218
559#define EXYNOS5420_PAD_RETENTION_MMC1_SYS_PWR_REG 0x121C
560#define EXYNOS5420_PAD_RETENTION_MMC2_SYS_PWR_REG 0x1220
561#define EXYNOS5420_PAD_RETENTION_HSI_SYS_PWR_REG 0x1224
562#define EXYNOS5420_PAD_RETENTION_EBIA_SYS_PWR_REG 0x1228
563#define EXYNOS5420_PAD_RETENTION_EBIB_SYS_PWR_REG 0x122C
564#define EXYNOS5420_PAD_RETENTION_SPI_SYS_PWR_REG 0x1230
565#define EXYNOS5420_PAD_RETENTION_DRAM_COREBLK_SYS_PWR_REG 0x1234
566#define EXYNOS5420_DISP1_SYS_PWR_REG 0x1410
567#define EXYNOS5420_MAU_SYS_PWR_REG 0x1414
568#define EXYNOS5420_G2D_SYS_PWR_REG 0x1418
569#define EXYNOS5420_MSC_SYS_PWR_REG 0x141C
570#define EXYNOS5420_FSYS_SYS_PWR_REG 0x1420
571#define EXYNOS5420_FSYS2_SYS_PWR_REG 0x1424
572#define EXYNOS5420_PSGEN_SYS_PWR_REG 0x1428
573#define EXYNOS5420_PERIC_SYS_PWR_REG 0x142C
574#define EXYNOS5420_WCORE_SYS_PWR_REG 0x1430
575#define EXYNOS5420_CMU_CLKSTOP_DISP1_SYS_PWR_REG 0x1490
576#define EXYNOS5420_CMU_CLKSTOP_MAU_SYS_PWR_REG 0x1494
577#define EXYNOS5420_CMU_CLKSTOP_G2D_SYS_PWR_REG 0x1498
578#define EXYNOS5420_CMU_CLKSTOP_MSC_SYS_PWR_REG 0x149C
579#define EXYNOS5420_CMU_CLKSTOP_FSYS_SYS_PWR_REG 0x14A0
580#define EXYNOS5420_CMU_CLKSTOP_FSYS2_SYS_PWR_REG 0x14A4
581#define EXYNOS5420_CMU_CLKSTOP_PSGEN_SYS_PWR_REG 0x14A8
582#define EXYNOS5420_CMU_CLKSTOP_PERIC_SYS_PWR_REG 0x14AC
583#define EXYNOS5420_CMU_CLKSTOP_WCORE_SYS_PWR_REG 0x14B0
584#define EXYNOS5420_CMU_SYSCLK_TOPPWR_SYS_PWR_REG 0x14BC
585#define EXYNOS5420_CMU_SYSCLK_DISP1_SYS_PWR_REG 0x14D0
586#define EXYNOS5420_CMU_SYSCLK_MAU_SYS_PWR_REG 0x14D4
587#define EXYNOS5420_CMU_SYSCLK_G2D_SYS_PWR_REG 0x14D8
588#define EXYNOS5420_CMU_SYSCLK_MSC_SYS_PWR_REG 0x14DC
589#define EXYNOS5420_CMU_SYSCLK_FSYS_SYS_PWR_REG 0x14E0
590#define EXYNOS5420_CMU_SYSCLK_FSYS2_SYS_PWR_REG 0x14E4
591#define EXYNOS5420_CMU_SYSCLK_PSGEN_SYS_PWR_REG 0x14E8
592#define EXYNOS5420_CMU_SYSCLK_PERIC_SYS_PWR_REG 0x14EC
593#define EXYNOS5420_CMU_SYSCLK_WCORE_SYS_PWR_REG 0x14F0
594#define EXYNOS5420_CMU_SYSCLK_SYSMEM_TOPPWR_SYS_PWR_REG 0x14F4
595#define EXYNOS5420_CMU_RESET_FSYS2_SYS_PWR_REG 0x1570
596#define EXYNOS5420_CMU_RESET_PSGEN_SYS_PWR_REG 0x1574
597#define EXYNOS5420_CMU_RESET_PERIC_SYS_PWR_REG 0x1578
598#define EXYNOS5420_CMU_RESET_WCORE_SYS_PWR_REG 0x157C
599#define EXYNOS5420_CMU_RESET_DISP1_SYS_PWR_REG 0x1590
600#define EXYNOS5420_CMU_RESET_MAU_SYS_PWR_REG 0x1594
601#define EXYNOS5420_CMU_RESET_G2D_SYS_PWR_REG 0x1598
602#define EXYNOS5420_CMU_RESET_MSC_SYS_PWR_REG 0x159C
603#define EXYNOS5420_CMU_RESET_FSYS_SYS_PWR_REG 0x15A0
604#define EXYNOS5420_SFR_AXI_CGDIS1 0x15E4
605#define EXYNOS_ARM_CORE2_CONFIGURATION 0x2100
606#define EXYNOS5420_ARM_CORE2_OPTION 0x2108
607#define EXYNOS_ARM_CORE3_CONFIGURATION 0x2180
608#define EXYNOS5420_ARM_CORE3_OPTION 0x2188
609#define EXYNOS5420_ARM_COMMON_STATUS 0x2504
610#define EXYNOS5420_ARM_COMMON_OPTION 0x2508
611#define EXYNOS5420_KFC_COMMON_STATUS 0x2584
612#define EXYNOS5420_KFC_COMMON_OPTION 0x2588
613#define EXYNOS5420_LOGIC_RESET_DURATION3 0x2D1C
614
615#define EXYNOS5420_PAD_RET_GPIO_OPTION 0x30C8
616#define EXYNOS5420_PAD_RET_UART_OPTION 0x30E8
617#define EXYNOS5420_PAD_RET_MMCA_OPTION 0x3108
618#define EXYNOS5420_PAD_RET_MMCB_OPTION 0x3128
619#define EXYNOS5420_PAD_RET_MMCC_OPTION 0x3148
620#define EXYNOS5420_PAD_RET_HSI_OPTION 0x3168
621#define EXYNOS5420_PAD_RET_SPI_OPTION 0x31C8
622#define EXYNOS5420_PAD_RET_DRAM_COREBLK_OPTION 0x31E8
623#define EXYNOS_PAD_RET_DRAM_OPTION 0x3008
624#define EXYNOS_PAD_RET_MAUDIO_OPTION 0x3028
625#define EXYNOS_PAD_RET_JTAG_OPTION 0x3048
626#define EXYNOS_PAD_RET_GPIO_OPTION 0x3108
627#define EXYNOS_PAD_RET_UART_OPTION 0x3128
628#define EXYNOS_PAD_RET_MMCA_OPTION 0x3148
629#define EXYNOS_PAD_RET_MMCB_OPTION 0x3168
630#define EXYNOS_PAD_RET_EBIA_OPTION 0x3188
631#define EXYNOS_PAD_RET_EBIB_OPTION 0x31A8
632
633#define EXYNOS_PS_HOLD_CONTROL 0x330C
634
635/* For SYS_PWR_REG */
636#define EXYNOS_SYS_PWR_CFG BIT(0)
637
638#define EXYNOS5420_MFC_CONFIGURATION 0x4060
639#define EXYNOS5420_MFC_STATUS 0x4064
640#define EXYNOS5420_MFC_OPTION 0x4068
641#define EXYNOS5420_G3D_CONFIGURATION 0x4080
642#define EXYNOS5420_G3D_STATUS 0x4084
643#define EXYNOS5420_G3D_OPTION 0x4088
644#define EXYNOS5420_DISP0_CONFIGURATION 0x40A0
645#define EXYNOS5420_DISP0_STATUS 0x40A4
646#define EXYNOS5420_DISP0_OPTION 0x40A8
647#define EXYNOS5420_DISP1_CONFIGURATION 0x40C0
648#define EXYNOS5420_DISP1_STATUS 0x40C4
649#define EXYNOS5420_DISP1_OPTION 0x40C8
650#define EXYNOS5420_MAU_CONFIGURATION 0x40E0
651#define EXYNOS5420_MAU_STATUS 0x40E4
652#define EXYNOS5420_MAU_OPTION 0x40E8
653#define EXYNOS5420_FSYS2_OPTION 0x4168
654#define EXYNOS5420_PSGEN_OPTION 0x4188
655
656/* For EXYNOS_CENTRAL_SEQ_OPTION */
657#define EXYNOS5_USE_STANDBYWFI_ARM_CORE0 BIT(16)
658#define EXYNOS5_USE_STANDBYWFI_ARM_CORE1 BUT(17)
659#define EXYNOS5_USE_STANDBYWFE_ARM_CORE0 BIT(24)
660#define EXYNOS5_USE_STANDBYWFE_ARM_CORE1 BIT(25)
661
662#define EXYNOS5420_ARM_USE_STANDBY_WFI0 BIT(4)
663#define EXYNOS5420_ARM_USE_STANDBY_WFI1 BIT(5)
664#define EXYNOS5420_ARM_USE_STANDBY_WFI2 BIT(6)
665#define EXYNOS5420_ARM_USE_STANDBY_WFI3 BIT(7)
666#define EXYNOS5420_KFC_USE_STANDBY_WFI0 BIT(8)
667#define EXYNOS5420_KFC_USE_STANDBY_WFI1 BIT(9)
668#define EXYNOS5420_KFC_USE_STANDBY_WFI2 BIT(10)
669#define EXYNOS5420_KFC_USE_STANDBY_WFI3 BIT(11)
670#define EXYNOS5420_ARM_USE_STANDBY_WFE0 BIT(16)
671#define EXYNOS5420_ARM_USE_STANDBY_WFE1 BIT(17)
672#define EXYNOS5420_ARM_USE_STANDBY_WFE2 BIT(18)
673#define EXYNOS5420_ARM_USE_STANDBY_WFE3 BIT(19)
674#define EXYNOS5420_KFC_USE_STANDBY_WFE0 BIT(20)
675#define EXYNOS5420_KFC_USE_STANDBY_WFE1 BIT(21)
676#define EXYNOS5420_KFC_USE_STANDBY_WFE2 BIT(22)
677#define EXYNOS5420_KFC_USE_STANDBY_WFE3 BIT(23)
678
679#define DUR_WAIT_RESET 0xF
680
681#define EXYNOS5420_USE_STANDBY_WFI_ALL (EXYNOS5420_ARM_USE_STANDBY_WFI0 \
682 | EXYNOS5420_ARM_USE_STANDBY_WFI1 \
683 | EXYNOS5420_ARM_USE_STANDBY_WFI2 \
684 | EXYNOS5420_ARM_USE_STANDBY_WFI3 \
685 | EXYNOS5420_KFC_USE_STANDBY_WFI0 \
686 | EXYNOS5420_KFC_USE_STANDBY_WFI1 \
687 | EXYNOS5420_KFC_USE_STANDBY_WFI2 \
688 | EXYNOS5420_KFC_USE_STANDBY_WFI3)
689
332#endif /* __ASM_ARCH_REGS_PMU_H */ 690#endif /* __ASM_ARCH_REGS_PMU_H */
diff --git a/arch/arm/mach-exynos/sleep.S b/arch/arm/mach-exynos/sleep.S
index 108a45f4bb62..e3c373082bbe 100644
--- a/arch/arm/mach-exynos/sleep.S
+++ b/arch/arm/mach-exynos/sleep.S
@@ -16,6 +16,7 @@
16 */ 16 */
17 17
18#include <linux/linkage.h> 18#include <linux/linkage.h>
19#include "smc.h"
19 20
20#define CPU_MASK 0xff0ffff0 21#define CPU_MASK 0xff0ffff0
21#define CPU_CORTEX_A9 0x410fc090 22#define CPU_CORTEX_A9 0x410fc090
@@ -55,3 +56,30 @@ ENTRY(exynos_cpu_resume)
55#endif 56#endif
56 b cpu_resume 57 b cpu_resume
57ENDPROC(exynos_cpu_resume) 58ENDPROC(exynos_cpu_resume)
59
60 .align
61
62ENTRY(exynos_cpu_resume_ns)
63 mrc p15, 0, r0, c0, c0, 0
64 ldr r1, =CPU_MASK
65 and r0, r0, r1
66 ldr r1, =CPU_CORTEX_A9
67 cmp r0, r1
68 bne skip_cp15
69
70 adr r0, cp15_save_power
71 ldr r1, [r0]
72 adr r0, cp15_save_diag
73 ldr r2, [r0]
74 mov r0, #SMC_CMD_C15RESUME
75 dsb
76 smc #0
77skip_cp15:
78 b cpu_resume
79ENDPROC(exynos_cpu_resume_ns)
80 .globl cp15_save_diag
81cp15_save_diag:
82 .long 0 @ cp15 diagnostic
83 .globl cp15_save_power
84cp15_save_power:
85 .long 0 @ cp15 power control
diff --git a/arch/arm/mach-exynos/smc.h b/arch/arm/mach-exynos/smc.h
index 13a1dc8ecbf2..f7b82f9c1e21 100644
--- a/arch/arm/mach-exynos/smc.h
+++ b/arch/arm/mach-exynos/smc.h
@@ -26,6 +26,10 @@
26#define SMC_CMD_L2X0INVALL (-24) 26#define SMC_CMD_L2X0INVALL (-24)
27#define SMC_CMD_L2X0DEBUG (-25) 27#define SMC_CMD_L2X0DEBUG (-25)
28 28
29#ifndef __ASSEMBLY__
30
29extern void exynos_smc(u32 cmd, u32 arg1, u32 arg2, u32 arg3); 31extern void exynos_smc(u32 cmd, u32 arg1, u32 arg2, u32 arg3);
30 32
33#endif /* __ASSEMBLY__ */
34
31#endif 35#endif
diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
new file mode 100644
index 000000000000..f8e7dcd17055
--- /dev/null
+++ b/arch/arm/mach-exynos/suspend.c
@@ -0,0 +1,566 @@
1/*
2 * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com
4 *
5 * EXYNOS - Suspend support
6 *
7 * Based on arch/arm/mach-s3c2410/pm.c
8 * Copyright (c) 2006 Simtec Electronics
9 * Ben Dooks <ben@simtec.co.uk>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#include <linux/init.h>
17#include <linux/suspend.h>
18#include <linux/syscore_ops.h>
19#include <linux/cpu_pm.h>
20#include <linux/io.h>
21#include <linux/irqchip/arm-gic.h>
22#include <linux/err.h>
23#include <linux/regulator/machine.h>
24
25#include <asm/cacheflush.h>
26#include <asm/hardware/cache-l2x0.h>
27#include <asm/firmware.h>
28#include <asm/mcpm.h>
29#include <asm/smp_scu.h>
30#include <asm/suspend.h>
31
32#include <plat/pm-common.h>
33#include <plat/regs-srom.h>
34
35#include "common.h"
36#include "regs-pmu.h"
37#include "regs-sys.h"
38#include "exynos-pmu.h"
39
40#define S5P_CHECK_SLEEP 0x00000BAD
41
42#define REG_TABLE_END (-1U)
43
44#define EXYNOS5420_CPU_STATE 0x28
45
46/**
47 * struct exynos_wkup_irq - Exynos GIC to PMU IRQ mapping
48 * @hwirq: Hardware IRQ signal of the GIC
49 * @mask: Mask in PMU wake-up mask register
50 */
51struct exynos_wkup_irq {
52 unsigned int hwirq;
53 u32 mask;
54};
55
56static struct sleep_save exynos5_sys_save[] = {
57 SAVE_ITEM(EXYNOS5_SYS_I2C_CFG),
58};
59
60static struct sleep_save exynos_core_save[] = {
61 /* SROM side */
62 SAVE_ITEM(S5P_SROM_BW),
63 SAVE_ITEM(S5P_SROM_BC0),
64 SAVE_ITEM(S5P_SROM_BC1),
65 SAVE_ITEM(S5P_SROM_BC2),
66 SAVE_ITEM(S5P_SROM_BC3),
67};
68
69struct exynos_pm_data {
70 const struct exynos_wkup_irq *wkup_irq;
71 struct sleep_save *extra_save;
72 int num_extra_save;
73 unsigned int wake_disable_mask;
74 unsigned int *release_ret_regs;
75
76 void (*pm_prepare)(void);
77 void (*pm_resume_prepare)(void);
78 void (*pm_resume)(void);
79 int (*pm_suspend)(void);
80 int (*cpu_suspend)(unsigned long);
81};
82
83struct exynos_pm_data *pm_data;
84
85static int exynos5420_cpu_state;
86static unsigned int exynos_pmu_spare3;
87
88/*
89 * GIC wake-up support
90 */
91
92static u32 exynos_irqwake_intmask = 0xffffffff;
93
94static const struct exynos_wkup_irq exynos4_wkup_irq[] = {
95 { 76, BIT(1) }, /* RTC alarm */
96 { 77, BIT(2) }, /* RTC tick */
97 { /* sentinel */ },
98};
99
100static const struct exynos_wkup_irq exynos5250_wkup_irq[] = {
101 { 75, BIT(1) }, /* RTC alarm */
102 { 76, BIT(2) }, /* RTC tick */
103 { /* sentinel */ },
104};
105
106unsigned int exynos_release_ret_regs[] = {
107 S5P_PAD_RET_MAUDIO_OPTION,
108 S5P_PAD_RET_GPIO_OPTION,
109 S5P_PAD_RET_UART_OPTION,
110 S5P_PAD_RET_MMCA_OPTION,
111 S5P_PAD_RET_MMCB_OPTION,
112 S5P_PAD_RET_EBIA_OPTION,
113 S5P_PAD_RET_EBIB_OPTION,
114 REG_TABLE_END,
115};
116
117unsigned int exynos5420_release_ret_regs[] = {
118 EXYNOS_PAD_RET_DRAM_OPTION,
119 EXYNOS_PAD_RET_MAUDIO_OPTION,
120 EXYNOS_PAD_RET_JTAG_OPTION,
121 EXYNOS5420_PAD_RET_GPIO_OPTION,
122 EXYNOS5420_PAD_RET_UART_OPTION,
123 EXYNOS5420_PAD_RET_MMCA_OPTION,
124 EXYNOS5420_PAD_RET_MMCB_OPTION,
125 EXYNOS5420_PAD_RET_MMCC_OPTION,
126 EXYNOS5420_PAD_RET_HSI_OPTION,
127 EXYNOS_PAD_RET_EBIA_OPTION,
128 EXYNOS_PAD_RET_EBIB_OPTION,
129 EXYNOS5420_PAD_RET_SPI_OPTION,
130 EXYNOS5420_PAD_RET_DRAM_COREBLK_OPTION,
131 REG_TABLE_END,
132};
133
134static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
135{
136 const struct exynos_wkup_irq *wkup_irq;
137
138 if (!pm_data->wkup_irq)
139 return -ENOENT;
140 wkup_irq = pm_data->wkup_irq;
141
142 while (wkup_irq->mask) {
143 if (wkup_irq->hwirq == data->hwirq) {
144 if (!state)
145 exynos_irqwake_intmask |= wkup_irq->mask;
146 else
147 exynos_irqwake_intmask &= ~wkup_irq->mask;
148 return 0;
149 }
150 ++wkup_irq;
151 }
152
153 return -ENOENT;
154}
155
156static int exynos_cpu_do_idle(void)
157{
158 /* issue the standby signal into the pm unit. */
159 cpu_do_idle();
160
161 pr_info("Failed to suspend the system\n");
162 return 1; /* Aborting suspend */
163}
164static void exynos_flush_cache_all(void)
165{
166 flush_cache_all();
167 outer_flush_all();
168}
169
170static int exynos_cpu_suspend(unsigned long arg)
171{
172 exynos_flush_cache_all();
173 return exynos_cpu_do_idle();
174}
175
176static int exynos5420_cpu_suspend(unsigned long arg)
177{
178 /* MCPM works with HW CPU identifiers */
179 unsigned int mpidr = read_cpuid_mpidr();
180 unsigned int cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
181 unsigned int cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
182
183 __raw_writel(0x0, sysram_base_addr + EXYNOS5420_CPU_STATE);
184
185 if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM)) {
186 mcpm_set_entry_vector(cpu, cluster, exynos_cpu_resume);
187
188 /*
189 * Residency value passed to mcpm_cpu_suspend back-end
190 * has to be given clear semantics. Set to 0 as a
191 * temporary value.
192 */
193 mcpm_cpu_suspend(0);
194 }
195
196 pr_info("Failed to suspend the system\n");
197
198 /* return value != 0 means failure */
199 return 1;
200}
201
202static void exynos_pm_set_wakeup_mask(void)
203{
204 /* Set wake-up mask registers */
205 pmu_raw_writel(exynos_get_eint_wake_mask(), S5P_EINT_WAKEUP_MASK);
206 pmu_raw_writel(exynos_irqwake_intmask & ~(1 << 31), S5P_WAKEUP_MASK);
207}
208
209static void exynos_pm_enter_sleep_mode(void)
210{
211 /* Set value of power down register for sleep mode */
212 exynos_sys_powerdown_conf(SYS_SLEEP);
213 pmu_raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
214}
215
216static void exynos_pm_prepare(void)
217{
218 /* Set wake-up mask registers */
219 exynos_pm_set_wakeup_mask();
220
221 s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
222
223 if (pm_data->extra_save)
224 s3c_pm_do_save(pm_data->extra_save,
225 pm_data->num_extra_save);
226
227 exynos_pm_enter_sleep_mode();
228
229 /* ensure at least INFORM0 has the resume address */
230 pmu_raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0);
231}
232
233static void exynos5420_pm_prepare(void)
234{
235 unsigned int tmp;
236
237 /* Set wake-up mask registers */
238 exynos_pm_set_wakeup_mask();
239
240 s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
241
242 exynos_pmu_spare3 = pmu_raw_readl(S5P_PMU_SPARE3);
243 /*
244 * The cpu state needs to be saved and restored so that the
245 * secondary CPUs will enter low power start. Though the U-Boot
246 * is setting the cpu state with low power flag, the kernel
247 * needs to restore it back in case, the primary cpu fails to
248 * suspend for any reason.
249 */
250 exynos5420_cpu_state = __raw_readl(sysram_base_addr +
251 EXYNOS5420_CPU_STATE);
252
253 exynos_pm_enter_sleep_mode();
254
255 /* ensure at least INFORM0 has the resume address */
256 if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM))
257 pmu_raw_writel(virt_to_phys(mcpm_entry_point), S5P_INFORM0);
258
259 tmp = pmu_raw_readl(EXYNOS5_ARM_L2_OPTION);
260 tmp &= ~EXYNOS5_USE_RETENTION;
261 pmu_raw_writel(tmp, EXYNOS5_ARM_L2_OPTION);
262
263 tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1);
264 tmp |= EXYNOS5420_UFS;
265 pmu_raw_writel(tmp, EXYNOS5420_SFR_AXI_CGDIS1);
266
267 tmp = pmu_raw_readl(EXYNOS5420_ARM_COMMON_OPTION);
268 tmp &= ~EXYNOS5420_L2RSTDISABLE_VALUE;
269 pmu_raw_writel(tmp, EXYNOS5420_ARM_COMMON_OPTION);
270
271 tmp = pmu_raw_readl(EXYNOS5420_FSYS2_OPTION);
272 tmp |= EXYNOS5420_EMULATION;
273 pmu_raw_writel(tmp, EXYNOS5420_FSYS2_OPTION);
274
275 tmp = pmu_raw_readl(EXYNOS5420_PSGEN_OPTION);
276 tmp |= EXYNOS5420_EMULATION;
277 pmu_raw_writel(tmp, EXYNOS5420_PSGEN_OPTION);
278}
279
280
281static int exynos_pm_suspend(void)
282{
283 exynos_pm_central_suspend();
284
285 if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
286 exynos_cpu_save_register();
287
288 return 0;
289}
290
291static int exynos5420_pm_suspend(void)
292{
293 u32 this_cluster;
294
295 exynos_pm_central_suspend();
296
297 /* Setting SEQ_OPTION register */
298
299 this_cluster = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 1);
300 if (!this_cluster)
301 pmu_raw_writel(EXYNOS5420_ARM_USE_STANDBY_WFI0,
302 S5P_CENTRAL_SEQ_OPTION);
303 else
304 pmu_raw_writel(EXYNOS5420_KFC_USE_STANDBY_WFI0,
305 S5P_CENTRAL_SEQ_OPTION);
306 return 0;
307}
308
309static void exynos_pm_release_retention(void)
310{
311 unsigned int i;
312
313 for (i = 0; (pm_data->release_ret_regs[i] != REG_TABLE_END); i++)
314 pmu_raw_writel(EXYNOS_WAKEUP_FROM_LOWPWR,
315 pm_data->release_ret_regs[i]);
316}
317
318static void exynos_pm_resume(void)
319{
320 u32 cpuid = read_cpuid_part();
321
322 if (exynos_pm_central_resume())
323 goto early_wakeup;
324
325 /* For release retention */
326 exynos_pm_release_retention();
327
328 if (pm_data->extra_save)
329 s3c_pm_do_restore_core(pm_data->extra_save,
330 pm_data->num_extra_save);
331
332 s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
333
334 if (cpuid == ARM_CPU_PART_CORTEX_A9)
335 scu_enable(S5P_VA_SCU);
336
337 if (call_firmware_op(resume) == -ENOSYS
338 && cpuid == ARM_CPU_PART_CORTEX_A9)
339 exynos_cpu_restore_register();
340
341early_wakeup:
342
343 /* Clear SLEEP mode set in INFORM1 */
344 pmu_raw_writel(0x0, S5P_INFORM1);
345}
346
347static void exynos5420_prepare_pm_resume(void)
348{
349 if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM))
350 WARN_ON(mcpm_cpu_powered_up());
351}
352
353static void exynos5420_pm_resume(void)
354{
355 unsigned long tmp;
356
357 /* Restore the CPU0 low power state register */
358 tmp = pmu_raw_readl(EXYNOS5_ARM_CORE0_SYS_PWR_REG);
359 pmu_raw_writel(tmp | S5P_CORE_LOCAL_PWR_EN,
360 EXYNOS5_ARM_CORE0_SYS_PWR_REG);
361
362 /* Restore the sysram cpu state register */
363 __raw_writel(exynos5420_cpu_state,
364 sysram_base_addr + EXYNOS5420_CPU_STATE);
365
366 pmu_raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL,
367 S5P_CENTRAL_SEQ_OPTION);
368
369 if (exynos_pm_central_resume())
370 goto early_wakeup;
371
372 /* For release retention */
373 exynos_pm_release_retention();
374
375 pmu_raw_writel(exynos_pmu_spare3, S5P_PMU_SPARE3);
376
377 s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
378
379early_wakeup:
380
381 tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1);
382 tmp &= ~EXYNOS5420_UFS;
383 pmu_raw_writel(tmp, EXYNOS5420_SFR_AXI_CGDIS1);
384
385 tmp = pmu_raw_readl(EXYNOS5420_FSYS2_OPTION);
386 tmp &= ~EXYNOS5420_EMULATION;
387 pmu_raw_writel(tmp, EXYNOS5420_FSYS2_OPTION);
388
389 tmp = pmu_raw_readl(EXYNOS5420_PSGEN_OPTION);
390 tmp &= ~EXYNOS5420_EMULATION;
391 pmu_raw_writel(tmp, EXYNOS5420_PSGEN_OPTION);
392
393 /* Clear SLEEP mode set in INFORM1 */
394 pmu_raw_writel(0x0, S5P_INFORM1);
395}
396
397/*
398 * Suspend Ops
399 */
400
401static int exynos_suspend_enter(suspend_state_t state)
402{
403 int ret;
404
405 s3c_pm_debug_init();
406
407 S3C_PMDBG("%s: suspending the system...\n", __func__);
408
409 S3C_PMDBG("%s: wakeup masks: %08x,%08x\n", __func__,
410 exynos_irqwake_intmask, exynos_get_eint_wake_mask());
411
412 if (exynos_irqwake_intmask == -1U
413 && exynos_get_eint_wake_mask() == -1U) {
414 pr_err("%s: No wake-up sources!\n", __func__);
415 pr_err("%s: Aborting sleep\n", __func__);
416 return -EINVAL;
417 }
418
419 s3c_pm_save_uarts();
420 if (pm_data->pm_prepare)
421 pm_data->pm_prepare();
422 flush_cache_all();
423 s3c_pm_check_store();
424
425 ret = call_firmware_op(suspend);
426 if (ret == -ENOSYS)
427 ret = cpu_suspend(0, pm_data->cpu_suspend);
428 if (ret)
429 return ret;
430
431 if (pm_data->pm_resume_prepare)
432 pm_data->pm_resume_prepare();
433 s3c_pm_restore_uarts();
434
435 S3C_PMDBG("%s: wakeup stat: %08x\n", __func__,
436 pmu_raw_readl(S5P_WAKEUP_STAT));
437
438 s3c_pm_check_restore();
439
440 S3C_PMDBG("%s: resuming the system...\n", __func__);
441
442 return 0;
443}
444
445static int exynos_suspend_prepare(void)
446{
447 int ret;
448
449 /*
450 * REVISIT: It would be better if struct platform_suspend_ops
451 * .prepare handler get the suspend_state_t as a parameter to
452 * avoid hard-coding the suspend to mem state. It's safe to do
453 * it now only because the suspend_valid_only_mem function is
454 * used as the .valid callback used to check if a given state
455 * is supported by the platform anyways.
456 */
457 ret = regulator_suspend_prepare(PM_SUSPEND_MEM);
458 if (ret) {
459 pr_err("Failed to prepare regulators for suspend (%d)\n", ret);
460 return ret;
461 }
462
463 s3c_pm_check_prepare();
464
465 return 0;
466}
467
468static void exynos_suspend_finish(void)
469{
470 int ret;
471
472 s3c_pm_check_cleanup();
473
474 ret = regulator_suspend_finish();
475 if (ret)
476 pr_warn("Failed to resume regulators from suspend (%d)\n", ret);
477}
478
479static const struct platform_suspend_ops exynos_suspend_ops = {
480 .enter = exynos_suspend_enter,
481 .prepare = exynos_suspend_prepare,
482 .finish = exynos_suspend_finish,
483 .valid = suspend_valid_only_mem,
484};
485
486static const struct exynos_pm_data exynos4_pm_data = {
487 .wkup_irq = exynos4_wkup_irq,
488 .wake_disable_mask = ((0xFF << 8) | (0x1F << 1)),
489 .release_ret_regs = exynos_release_ret_regs,
490 .pm_suspend = exynos_pm_suspend,
491 .pm_resume = exynos_pm_resume,
492 .pm_prepare = exynos_pm_prepare,
493 .cpu_suspend = exynos_cpu_suspend,
494};
495
496static const struct exynos_pm_data exynos5250_pm_data = {
497 .wkup_irq = exynos5250_wkup_irq,
498 .wake_disable_mask = ((0xFF << 8) | (0x1F << 1)),
499 .release_ret_regs = exynos_release_ret_regs,
500 .extra_save = exynos5_sys_save,
501 .num_extra_save = ARRAY_SIZE(exynos5_sys_save),
502 .pm_suspend = exynos_pm_suspend,
503 .pm_resume = exynos_pm_resume,
504 .pm_prepare = exynos_pm_prepare,
505 .cpu_suspend = exynos_cpu_suspend,
506};
507
508static struct exynos_pm_data exynos5420_pm_data = {
509 .wkup_irq = exynos5250_wkup_irq,
510 .wake_disable_mask = (0x7F << 7) | (0x1F << 1),
511 .release_ret_regs = exynos5420_release_ret_regs,
512 .pm_resume_prepare = exynos5420_prepare_pm_resume,
513 .pm_resume = exynos5420_pm_resume,
514 .pm_suspend = exynos5420_pm_suspend,
515 .pm_prepare = exynos5420_pm_prepare,
516 .cpu_suspend = exynos5420_cpu_suspend,
517};
518
519static struct of_device_id exynos_pmu_of_device_ids[] = {
520 {
521 .compatible = "samsung,exynos4210-pmu",
522 .data = &exynos4_pm_data,
523 }, {
524 .compatible = "samsung,exynos4212-pmu",
525 .data = &exynos4_pm_data,
526 }, {
527 .compatible = "samsung,exynos4412-pmu",
528 .data = &exynos4_pm_data,
529 }, {
530 .compatible = "samsung,exynos5250-pmu",
531 .data = &exynos5250_pm_data,
532 }, {
533 .compatible = "samsung,exynos5420-pmu",
534 .data = &exynos5420_pm_data,
535 },
536 { /*sentinel*/ },
537};
538
539static struct syscore_ops exynos_pm_syscore_ops;
540
541void __init exynos_pm_init(void)
542{
543 const struct of_device_id *match;
544 u32 tmp;
545
546 of_find_matching_node_and_match(NULL, exynos_pmu_of_device_ids, &match);
547 if (!match) {
548 pr_err("Failed to find PMU node\n");
549 return;
550 }
551 pm_data = (struct exynos_pm_data *) match->data;
552
553 /* Platform-specific GIC callback */
554 gic_arch_extn.irq_set_wake = exynos_irq_set_wake;
555
556 /* All wakeup disable */
557 tmp = pmu_raw_readl(S5P_WAKEUP_MASK);
558 tmp |= pm_data->wake_disable_mask;
559 pmu_raw_writel(tmp, S5P_WAKEUP_MASK);
560
561 exynos_pm_syscore_ops.suspend = pm_data->pm_suspend;
562 exynos_pm_syscore_ops.resume = pm_data->pm_resume;
563
564 register_syscore_ops(&exynos_pm_syscore_ops);
565 suspend_set_ops(&exynos_suspend_ops);
566}