2 * linux/arch/arm/mach-omap2/pm.c
4 * OMAP2 Power Management Routines
6 * Copyright (C) 2006 Nokia Corporation
7 * Tony Lindgren <tony@atomide.com>
9 * Copyright (C) 2005 Texas Instruments, Inc.
10 * Richard Woodruff <r-woodruff2@ti.com>
12 * Based on pm.c for omap1
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
20 #include <linux/sched.h>
21 #include <linux/proc_fs.h>
23 #include <linux/interrupt.h>
24 #include <linux/sysfs.h>
25 #include <linux/module.h>
26 #include <linux/delay.h>
30 #include <asm/atomic.h>
31 #include <asm/mach/time.h>
32 #include <asm/mach/irq.h>
33 #include <asm/mach-types.h>
35 #include <asm/arch/irqs.h>
36 #include <asm/arch/clock.h>
37 #include <asm/arch/sram.h>
38 #include <asm/arch/pm.h>
40 #include "prcm-regs.h"
42 static struct clk
*vclk
;
43 static void (*omap2_sram_idle
)(void);
44 static void (*omap2_sram_suspend
)(int dllctrl
, int cpu_rev
);
45 static void (*saved_idle
)(void);
47 extern void __init
pmdomain_init(void);
48 extern void pmdomain_set_autoidle(void);
50 static unsigned int omap24xx_sleep_save
[OMAP24XX_SLEEP_SAVE_SIZE
];
52 void omap2_pm_idle(void)
63 * Since an interrupt may set up a timer, we don't want to
64 * reprogram the hardware timer with interrupts enabled.
65 * Re-enable interrupts only after returning from idle.
67 timer_dyn_reprogram();
74 static int omap2_pm_prepare(suspend_state_t state
)
78 /* We cannot sleep in idle until we have resumed */
84 case PM_SUSPEND_STANDBY
:
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))
102 #define INT1_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_GPIO_BANK4))
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))
108 #define preg(reg) printk("%s\t(0x%p):\t0x%08x\n", #reg, ®, reg);
110 static void omap2_pm_debug(char * desc
)
112 printk("%s:\n", desc
);
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
);
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
);
127 preg(PM_PWSTST_CORE
);
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
);
141 preg(CM_ICLKEN1_CORE
);
142 preg(CM_ICLKEN2_CORE
);
143 preg(CM_ICLKEN3_CORE
);
144 preg(CM_ICLKEN4_CORE
);
146 preg(CM_ICLKEN_WKUP
);
150 preg(CM_IDLEST1_CORE
);
151 preg(CM_IDLEST2_CORE
);
152 preg(CM_IDLEST3_CORE
);
153 preg(CM_IDLEST4_CORE
);
155 preg(CM_IDLEST_WKUP
);
156 preg(CM_IDLEST_CKGEN
);
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
);
182 static inline void omap2_pm_save_registers(void)
184 /* Save interrupt registers */
185 OMAP24XX_SAVE(INTC_MIR0
);
186 OMAP24XX_SAVE(INTC_MIR1
);
187 OMAP24XX_SAVE(INTC_MIR2
);
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
);
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
);
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
);
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
);
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
);
233 static inline void omap2_pm_restore_registers(void)
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
);
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
);
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
);
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
);
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
);
278 /* REVISIT: Clear interrupts here */
280 /* Restore interrupt registers */
281 OMAP24XX_RESTORE(INTC_MIR0
);
282 OMAP24XX_RESTORE(INTC_MIR1
);
283 OMAP24XX_RESTORE(INTC_MIR2
);
286 static int omap2_pm_suspend(void)
288 int processor_type
= 0;
290 /* REVISIT: 0x21 or 0x26? */
291 if (cpu_is_omap2420())
292 processor_type
= 0x21;
300 omap2_pm_save_registers();
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
;
307 pmdomain_set_autoidle();
309 /* Clear old wake-up events */
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 */
319 /* Disable clocks except for CM_ICLKEN2_CORE. It gets disabled
320 * in the SRAM suspend code */
327 omap2_pm_debug("Status before suspend");
329 /* Must wait for serial buffers to clear */
332 /* Jump to SRAM suspend code
333 * REVISIT: When is this SDRC_DLLB_CTRL?
335 omap2_sram_suspend(SDRC_DLLA_CTRL
, processor_type
);
337 /* Back from sleep */
338 omap2_pm_restore_registers();
346 static int omap2_pm_enter(suspend_state_t state
)
352 case PM_SUSPEND_STANDBY
:
354 ret
= omap2_pm_suspend();
356 case PM_SUSPEND_DISK
:
366 static int omap2_pm_finish(suspend_state_t state
)
368 pm_idle
= saved_idle
;
372 static struct pm_ops omap_pm_ops
= {
373 .prepare
= omap2_pm_prepare
,
374 .enter
= omap2_pm_enter
,
375 .finish
= omap2_pm_finish
,
376 .valid
= pm_valid_only_mem
,
379 int __init
omap2_pm_init(void)
381 printk("Power Management for TI OMAP.\n");
383 vclk
= clk_get(NULL
, "virt_prcm_set");
385 printk(KERN_ERR
"Could not get PM vclk\n");
390 * We copy the assembler sleep/wakeup routines to SRAM.
391 * These routines need to be in SRAM as that's the only
392 * memory the MPU can see when it wakes up.
394 omap2_sram_idle
= omap_sram_push(omap24xx_idle_loop_suspend
,
395 omap24xx_idle_loop_suspend_sz
);
397 omap2_sram_suspend
= omap_sram_push(omap24xx_cpu_suspend
,
398 omap24xx_cpu_suspend_sz
);
400 pm_set_ops(&omap_pm_ops
);
401 pm_idle
= omap2_pm_idle
;
408 __initcall(omap2_pm_init
);