aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/pm.c')
-rw-r--r--arch/arm/mach-omap2/pm.c271
1 files changed, 265 insertions, 6 deletions
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 562168fa2b16..d7eee99b7e3f 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -23,6 +23,7 @@
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/sysfs.h> 24#include <linux/sysfs.h>
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/delay.h>
26 27
27#include <asm/io.h> 28#include <asm/io.h>
28#include <asm/irq.h> 29#include <asm/irq.h>
@@ -36,11 +37,18 @@
36#include <asm/arch/sram.h> 37#include <asm/arch/sram.h>
37#include <asm/arch/pm.h> 38#include <asm/arch/pm.h>
38 39
40#include "prcm-regs.h"
41
39static struct clk *vclk; 42static struct clk *vclk;
40static void (*omap2_sram_idle)(void); 43static void (*omap2_sram_idle)(void);
41static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev); 44static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev);
42static void (*saved_idle)(void); 45static void (*saved_idle)(void);
43 46
47extern void __init pmdomain_init(void);
48extern void pmdomain_set_autoidle(void);
49
50static unsigned int omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_SIZE];
51
44void omap2_pm_idle(void) 52void omap2_pm_idle(void)
45{ 53{
46 local_irq_disable(); 54 local_irq_disable();
@@ -87,23 +95,272 @@ static int omap2_pm_prepare(suspend_state_t state)
87 return error; 95 return error;
88} 96}
89 97
98#define INT0_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_GPIO_BANK1) | \
99 OMAP_IRQ_BIT(INT_24XX_GPIO_BANK2) | \
100 OMAP_IRQ_BIT(INT_24XX_GPIO_BANK3))
101
102#define INT1_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_GPIO_BANK4))
103
104#define INT2_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_UART1_IRQ) | \
105 OMAP_IRQ_BIT(INT_24XX_UART2_IRQ) | \
106 OMAP_IRQ_BIT(INT_24XX_UART3_IRQ))
107
108#define preg(reg) printk("%s\t(0x%p):\t0x%08x\n", #reg, &reg, reg);
109
110static void omap2_pm_debug(char * desc)
111{
112 printk("%s:\n", desc);
113
114 preg(CM_CLKSTCTRL_MPU);
115 preg(CM_CLKSTCTRL_CORE);
116 preg(CM_CLKSTCTRL_GFX);
117 preg(CM_CLKSTCTRL_DSP);
118 preg(CM_CLKSTCTRL_MDM);
119
120 preg(PM_PWSTCTRL_MPU);
121 preg(PM_PWSTCTRL_CORE);
122 preg(PM_PWSTCTRL_GFX);
123 preg(PM_PWSTCTRL_DSP);
124 preg(PM_PWSTCTRL_MDM);
125
126 preg(PM_PWSTST_MPU);
127 preg(PM_PWSTST_CORE);
128 preg(PM_PWSTST_GFX);
129 preg(PM_PWSTST_DSP);
130 preg(PM_PWSTST_MDM);
131
132 preg(CM_AUTOIDLE1_CORE);
133 preg(CM_AUTOIDLE2_CORE);
134 preg(CM_AUTOIDLE3_CORE);
135 preg(CM_AUTOIDLE4_CORE);
136 preg(CM_AUTOIDLE_WKUP);
137 preg(CM_AUTOIDLE_PLL);
138 preg(CM_AUTOIDLE_DSP);
139 preg(CM_AUTOIDLE_MDM);
140
141 preg(CM_ICLKEN1_CORE);
142 preg(CM_ICLKEN2_CORE);
143 preg(CM_ICLKEN3_CORE);
144 preg(CM_ICLKEN4_CORE);
145 preg(CM_ICLKEN_GFX);
146 preg(CM_ICLKEN_WKUP);
147 preg(CM_ICLKEN_DSP);
148 preg(CM_ICLKEN_MDM);
149
150 preg(CM_IDLEST1_CORE);
151 preg(CM_IDLEST2_CORE);
152 preg(CM_IDLEST3_CORE);
153 preg(CM_IDLEST4_CORE);
154 preg(CM_IDLEST_GFX);
155 preg(CM_IDLEST_WKUP);
156 preg(CM_IDLEST_CKGEN);
157 preg(CM_IDLEST_DSP);
158 preg(CM_IDLEST_MDM);
159
160 preg(RM_RSTST_MPU);
161 preg(RM_RSTST_GFX);
162 preg(RM_RSTST_WKUP);
163 preg(RM_RSTST_DSP);
164 preg(RM_RSTST_MDM);
165
166 preg(PM_WKDEP_MPU);
167 preg(PM_WKDEP_CORE);
168 preg(PM_WKDEP_GFX);
169 preg(PM_WKDEP_DSP);
170 preg(PM_WKDEP_MDM);
171
172 preg(CM_FCLKEN_WKUP);
173 preg(CM_ICLKEN_WKUP);
174 preg(CM_IDLEST_WKUP);
175 preg(CM_AUTOIDLE_WKUP);
176 preg(CM_CLKSEL_WKUP);
177
178 preg(PM_WKEN_WKUP);
179 preg(PM_WKST_WKUP);
180}
181
182static inline void omap2_pm_save_registers(void)
183{
184 /* Save interrupt registers */
185 OMAP24XX_SAVE(INTC_MIR0);
186 OMAP24XX_SAVE(INTC_MIR1);
187 OMAP24XX_SAVE(INTC_MIR2);
188
189 /* Save power control registers */
190 OMAP24XX_SAVE(CM_CLKSTCTRL_MPU);
191 OMAP24XX_SAVE(CM_CLKSTCTRL_CORE);
192 OMAP24XX_SAVE(CM_CLKSTCTRL_GFX);
193 OMAP24XX_SAVE(CM_CLKSTCTRL_DSP);
194 OMAP24XX_SAVE(CM_CLKSTCTRL_MDM);
195
196 /* Save power state registers */
197 OMAP24XX_SAVE(PM_PWSTCTRL_MPU);
198 OMAP24XX_SAVE(PM_PWSTCTRL_CORE);
199 OMAP24XX_SAVE(PM_PWSTCTRL_GFX);
200 OMAP24XX_SAVE(PM_PWSTCTRL_DSP);
201 OMAP24XX_SAVE(PM_PWSTCTRL_MDM);
202
203 /* Save autoidle registers */
204 OMAP24XX_SAVE(CM_AUTOIDLE1_CORE);
205 OMAP24XX_SAVE(CM_AUTOIDLE2_CORE);
206 OMAP24XX_SAVE(CM_AUTOIDLE3_CORE);
207 OMAP24XX_SAVE(CM_AUTOIDLE4_CORE);
208 OMAP24XX_SAVE(CM_AUTOIDLE_WKUP);
209 OMAP24XX_SAVE(CM_AUTOIDLE_PLL);
210 OMAP24XX_SAVE(CM_AUTOIDLE_DSP);
211 OMAP24XX_SAVE(CM_AUTOIDLE_MDM);
212
213 /* Save idle state registers */
214 OMAP24XX_SAVE(CM_IDLEST1_CORE);
215 OMAP24XX_SAVE(CM_IDLEST2_CORE);
216 OMAP24XX_SAVE(CM_IDLEST3_CORE);
217 OMAP24XX_SAVE(CM_IDLEST4_CORE);
218 OMAP24XX_SAVE(CM_IDLEST_GFX);
219 OMAP24XX_SAVE(CM_IDLEST_WKUP);
220 OMAP24XX_SAVE(CM_IDLEST_CKGEN);
221 OMAP24XX_SAVE(CM_IDLEST_DSP);
222 OMAP24XX_SAVE(CM_IDLEST_MDM);
223
224 /* Save clock registers */
225 OMAP24XX_SAVE(CM_FCLKEN1_CORE);
226 OMAP24XX_SAVE(CM_FCLKEN2_CORE);
227 OMAP24XX_SAVE(CM_ICLKEN1_CORE);
228 OMAP24XX_SAVE(CM_ICLKEN2_CORE);
229 OMAP24XX_SAVE(CM_ICLKEN3_CORE);
230 OMAP24XX_SAVE(CM_ICLKEN4_CORE);
231}
232
233static inline void omap2_pm_restore_registers(void)
234{
235 /* Restore clock state registers */
236 OMAP24XX_RESTORE(CM_CLKSTCTRL_MPU);
237 OMAP24XX_RESTORE(CM_CLKSTCTRL_CORE);
238 OMAP24XX_RESTORE(CM_CLKSTCTRL_GFX);
239 OMAP24XX_RESTORE(CM_CLKSTCTRL_DSP);
240 OMAP24XX_RESTORE(CM_CLKSTCTRL_MDM);
241
242 /* Restore power state registers */
243 OMAP24XX_RESTORE(PM_PWSTCTRL_MPU);
244 OMAP24XX_RESTORE(PM_PWSTCTRL_CORE);
245 OMAP24XX_RESTORE(PM_PWSTCTRL_GFX);
246 OMAP24XX_RESTORE(PM_PWSTCTRL_DSP);
247 OMAP24XX_RESTORE(PM_PWSTCTRL_MDM);
248
249 /* Restore idle state registers */
250 OMAP24XX_RESTORE(CM_IDLEST1_CORE);
251 OMAP24XX_RESTORE(CM_IDLEST2_CORE);
252 OMAP24XX_RESTORE(CM_IDLEST3_CORE);
253 OMAP24XX_RESTORE(CM_IDLEST4_CORE);
254 OMAP24XX_RESTORE(CM_IDLEST_GFX);
255 OMAP24XX_RESTORE(CM_IDLEST_WKUP);
256 OMAP24XX_RESTORE(CM_IDLEST_CKGEN);
257 OMAP24XX_RESTORE(CM_IDLEST_DSP);
258 OMAP24XX_RESTORE(CM_IDLEST_MDM);
259
260 /* Restore autoidle registers */
261 OMAP24XX_RESTORE(CM_AUTOIDLE1_CORE);
262 OMAP24XX_RESTORE(CM_AUTOIDLE2_CORE);
263 OMAP24XX_RESTORE(CM_AUTOIDLE3_CORE);
264 OMAP24XX_RESTORE(CM_AUTOIDLE4_CORE);
265 OMAP24XX_RESTORE(CM_AUTOIDLE_WKUP);
266 OMAP24XX_RESTORE(CM_AUTOIDLE_PLL);
267 OMAP24XX_RESTORE(CM_AUTOIDLE_DSP);
268 OMAP24XX_RESTORE(CM_AUTOIDLE_MDM);
269
270 /* Restore clock registers */
271 OMAP24XX_RESTORE(CM_FCLKEN1_CORE);
272 OMAP24XX_RESTORE(CM_FCLKEN2_CORE);
273 OMAP24XX_RESTORE(CM_ICLKEN1_CORE);
274 OMAP24XX_RESTORE(CM_ICLKEN2_CORE);
275 OMAP24XX_RESTORE(CM_ICLKEN3_CORE);
276 OMAP24XX_RESTORE(CM_ICLKEN4_CORE);
277
278 /* REVISIT: Clear interrupts here */
279
280 /* Restore interrupt registers */
281 OMAP24XX_RESTORE(INTC_MIR0);
282 OMAP24XX_RESTORE(INTC_MIR1);
283 OMAP24XX_RESTORE(INTC_MIR2);
284}
285
286static int omap2_pm_suspend(void)
287{
288 int processor_type = 0;
289
290 /* REVISIT: 0x21 or 0x26? */
291 if (cpu_is_omap2420())
292 processor_type = 0x21;
293
294 if (!processor_type)
295 return -ENOTSUPP;
296
297 local_irq_disable();
298 local_fiq_disable();
299
300 omap2_pm_save_registers();
301
302 /* Disable interrupts except for the wake events */
303 INTC_MIR_SET0 = 0xffffffff & ~INT0_WAKE_MASK;
304 INTC_MIR_SET1 = 0xffffffff & ~INT1_WAKE_MASK;
305 INTC_MIR_SET2 = 0xffffffff & ~INT2_WAKE_MASK;
306
307 pmdomain_set_autoidle();
308
309 /* Clear old wake-up events */
310 PM_WKST1_CORE = 0;
311 PM_WKST2_CORE = 0;
312 PM_WKST_WKUP = 0;
313
314 /* Enable wake-up events */
315 PM_WKEN1_CORE = (1 << 22) | (1 << 21); /* UART1 & 2 */
316 PM_WKEN2_CORE = (1 << 2); /* UART3 */
317 PM_WKEN_WKUP = (1 << 2) | (1 << 0); /* GPIO & GPT1 */
318
319 /* Disable clocks except for CM_ICLKEN2_CORE. It gets disabled
320 * in the SRAM suspend code */
321 CM_FCLKEN1_CORE = 0;
322 CM_FCLKEN2_CORE = 0;
323 CM_ICLKEN1_CORE = 0;
324 CM_ICLKEN3_CORE = 0;
325 CM_ICLKEN4_CORE = 0;
326
327 omap2_pm_debug("Status before suspend");
328
329 /* Must wait for serial buffers to clear */
330 mdelay(200);
331
332 /* Jump to SRAM suspend code
333 * REVISIT: When is this SDRC_DLLB_CTRL?
334 */
335 omap2_sram_suspend(SDRC_DLLA_CTRL, processor_type);
336
337 /* Back from sleep */
338 omap2_pm_restore_registers();
339
340 local_fiq_enable();
341 local_irq_enable();
342
343 return 0;
344}
345
90static int omap2_pm_enter(suspend_state_t state) 346static int omap2_pm_enter(suspend_state_t state)
91{ 347{
348 int ret = 0;
349
92 switch (state) 350 switch (state)
93 { 351 {
94 case PM_SUSPEND_STANDBY: 352 case PM_SUSPEND_STANDBY:
95 case PM_SUSPEND_MEM: 353 case PM_SUSPEND_MEM:
96 /* FIXME: Add suspend */ 354 ret = omap2_pm_suspend();
97 break; 355 break;
98
99 case PM_SUSPEND_DISK: 356 case PM_SUSPEND_DISK:
100 return -ENOTSUPP; 357 ret = -ENOTSUPP;
101 358 break;
102 default: 359 default:
103 return -EINVAL; 360 ret = -EINVAL;
104 } 361 }
105 362
106 return 0; 363 return ret;
107} 364}
108 365
109static int omap2_pm_finish(suspend_state_t state) 366static int omap2_pm_finish(suspend_state_t state)
@@ -143,6 +400,8 @@ int __init omap2_pm_init(void)
143 pm_set_ops(&omap_pm_ops); 400 pm_set_ops(&omap_pm_ops);
144 pm_idle = omap2_pm_idle; 401 pm_idle = omap2_pm_idle;
145 402
403 pmdomain_init();
404
146 return 0; 405 return 0;
147} 406}
148 407