diff options
Diffstat (limited to 'arch/arm/mach-s5pv210/pm.c')
-rw-r--r-- | arch/arm/mach-s5pv210/pm.c | 101 |
1 files changed, 89 insertions, 12 deletions
diff --git a/arch/arm/mach-s5pv210/pm.c b/arch/arm/mach-s5pv210/pm.c index 00d1523284da..123163dd2ab0 100644 --- a/arch/arm/mach-s5pv210/pm.c +++ b/arch/arm/mach-s5pv210/pm.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* linux/arch/arm/mach-s5pv210/pm.c | 1 | /* linux/arch/arm/mach-s5pv210/pm.c |
2 | * | 2 | * |
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | 3 | * Copyright (c) 2010-2014 Samsung Electronics Co., Ltd. |
4 | * http://www.samsung.com | 4 | * http://www.samsung.com |
5 | * | 5 | * |
6 | * S5PV210 - Power Management support | 6 | * S5PV210 - Power Management support |
@@ -19,17 +19,28 @@ | |||
19 | #include <linux/syscore_ops.h> | 19 | #include <linux/syscore_ops.h> |
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | 21 | ||
22 | #include <plat/cpu.h> | 22 | #include <asm/cacheflush.h> |
23 | #include <plat/pm.h> | 23 | #include <asm/suspend.h> |
24 | |||
25 | #include <plat/pm-common.h> | ||
24 | 26 | ||
25 | #include <mach/regs-irq.h> | ||
26 | #include <mach/regs-clock.h> | 27 | #include <mach/regs-clock.h> |
27 | 28 | ||
29 | #include "common.h" | ||
30 | |||
28 | static struct sleep_save s5pv210_core_save[] = { | 31 | static struct sleep_save s5pv210_core_save[] = { |
29 | /* Clock ETC */ | 32 | /* Clock ETC */ |
30 | SAVE_ITEM(S5P_MDNIE_SEL), | 33 | SAVE_ITEM(S5P_MDNIE_SEL), |
31 | }; | 34 | }; |
32 | 35 | ||
36 | /* | ||
37 | * VIC wake-up support (TODO) | ||
38 | */ | ||
39 | static u32 s5pv210_irqwake_intmask = 0xffffffff; | ||
40 | |||
41 | /* | ||
42 | * Suspend helpers. | ||
43 | */ | ||
33 | static int s5pv210_cpu_suspend(unsigned long arg) | 44 | static int s5pv210_cpu_suspend(unsigned long arg) |
34 | { | 45 | { |
35 | unsigned long tmp; | 46 | unsigned long tmp; |
@@ -54,8 +65,12 @@ static void s5pv210_pm_prepare(void) | |||
54 | { | 65 | { |
55 | unsigned int tmp; | 66 | unsigned int tmp; |
56 | 67 | ||
68 | /* Set wake-up mask registers */ | ||
69 | __raw_writel(exynos_get_eint_wake_mask(), S5P_EINT_WAKEUP_MASK); | ||
70 | __raw_writel(s5pv210_irqwake_intmask, S5P_WAKEUP_MASK); | ||
71 | |||
57 | /* ensure at least INFORM0 has the resume address */ | 72 | /* ensure at least INFORM0 has the resume address */ |
58 | __raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0); | 73 | __raw_writel(virt_to_phys(s5pv210_cpu_resume), S5P_INFORM0); |
59 | 74 | ||
60 | tmp = __raw_readl(S5P_SLEEP_CFG); | 75 | tmp = __raw_readl(S5P_SLEEP_CFG); |
61 | tmp &= ~(S5P_SLEEP_CFG_OSC_EN | S5P_SLEEP_CFG_USBOSC_EN); | 76 | tmp &= ~(S5P_SLEEP_CFG_OSC_EN | S5P_SLEEP_CFG_USBOSC_EN); |
@@ -75,6 +90,70 @@ static void s5pv210_pm_prepare(void) | |||
75 | s3c_pm_do_save(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save)); | 90 | s3c_pm_do_save(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save)); |
76 | } | 91 | } |
77 | 92 | ||
93 | /* | ||
94 | * Suspend operations. | ||
95 | */ | ||
96 | static int s5pv210_suspend_enter(suspend_state_t state) | ||
97 | { | ||
98 | int ret; | ||
99 | |||
100 | s3c_pm_debug_init(); | ||
101 | |||
102 | S3C_PMDBG("%s: suspending the system...\n", __func__); | ||
103 | |||
104 | S3C_PMDBG("%s: wakeup masks: %08x,%08x\n", __func__, | ||
105 | s5pv210_irqwake_intmask, exynos_get_eint_wake_mask()); | ||
106 | |||
107 | if (s5pv210_irqwake_intmask == -1U | ||
108 | && exynos_get_eint_wake_mask() == -1U) { | ||
109 | pr_err("%s: No wake-up sources!\n", __func__); | ||
110 | pr_err("%s: Aborting sleep\n", __func__); | ||
111 | return -EINVAL; | ||
112 | } | ||
113 | |||
114 | s3c_pm_save_uarts(); | ||
115 | s5pv210_pm_prepare(); | ||
116 | flush_cache_all(); | ||
117 | s3c_pm_check_store(); | ||
118 | |||
119 | ret = cpu_suspend(0, s5pv210_cpu_suspend); | ||
120 | if (ret) | ||
121 | return ret; | ||
122 | |||
123 | s3c_pm_restore_uarts(); | ||
124 | |||
125 | S3C_PMDBG("%s: wakeup stat: %08x\n", __func__, | ||
126 | __raw_readl(S5P_WAKEUP_STAT)); | ||
127 | |||
128 | s3c_pm_check_restore(); | ||
129 | |||
130 | S3C_PMDBG("%s: resuming the system...\n", __func__); | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static int s5pv210_suspend_prepare(void) | ||
136 | { | ||
137 | s3c_pm_check_prepare(); | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static void s5pv210_suspend_finish(void) | ||
143 | { | ||
144 | s3c_pm_check_cleanup(); | ||
145 | } | ||
146 | |||
147 | static const struct platform_suspend_ops s5pv210_suspend_ops = { | ||
148 | .enter = s5pv210_suspend_enter, | ||
149 | .prepare = s5pv210_suspend_prepare, | ||
150 | .finish = s5pv210_suspend_finish, | ||
151 | .valid = suspend_valid_only_mem, | ||
152 | }; | ||
153 | |||
154 | /* | ||
155 | * Syscore operations used to delay restore of certain registers. | ||
156 | */ | ||
78 | static void s5pv210_pm_resume(void) | 157 | static void s5pv210_pm_resume(void) |
79 | { | 158 | { |
80 | u32 tmp; | 159 | u32 tmp; |
@@ -91,13 +170,11 @@ static struct syscore_ops s5pv210_pm_syscore_ops = { | |||
91 | .resume = s5pv210_pm_resume, | 170 | .resume = s5pv210_pm_resume, |
92 | }; | 171 | }; |
93 | 172 | ||
94 | static __init int s5pv210_pm_syscore_init(void) | 173 | /* |
174 | * Initialization entry point. | ||
175 | */ | ||
176 | void __init s5pv210_pm_init(void) | ||
95 | { | 177 | { |
96 | register_syscore_ops(&s5pv210_pm_syscore_ops); | 178 | register_syscore_ops(&s5pv210_pm_syscore_ops); |
97 | 179 | suspend_set_ops(&s5pv210_suspend_ops); | |
98 | pm_cpu_prep = s5pv210_pm_prepare; | ||
99 | pm_cpu_sleep = s5pv210_cpu_suspend; | ||
100 | |||
101 | return 0; | ||
102 | } | 180 | } |
103 | arch_initcall(s5pv210_pm_syscore_init); | ||