2 * linux/arch/arm/mach-omap/pm.c
4 * OMAP Power Management Routines
6 * Original code for the SA11x0:
7 * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
9 * Modified for the PXA250 by Nicolas Pitre:
10 * Copyright (c) 2002 Monta Vista Software, Inc.
12 * Modified for the OMAP1510 by David Singleton:
13 * Copyright (c) 2002 Monta Vista Software, Inc.
15 * Cleanup 2004 for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com>
17 * This program is free software; you can redistribute it and/or modify it
18 * under the terms of the GNU General Public License as published by the
19 * Free Software Foundation; either version 2 of the License, or (at your
20 * option) any later version.
22 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
25 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
29 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * You should have received a copy of the GNU General Public License along
34 * with this program; if not, write to the Free Software Foundation, Inc.,
35 * 675 Mass Ave, Cambridge, MA 02139, USA.
39 #include <linux/sched.h>
40 #include <linux/proc_fs.h>
44 #include <asm/mach-types.h>
45 #include <asm/arch/omap16xx.h>
46 #include <asm/arch/pm.h>
47 #include <asm/arch/mux.h>
48 #include <asm/arch/tps65010.h>
52 static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
53 static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE];
54 static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE];
55 static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
58 * Let's power down on idle, but only if we are really
59 * idle, because once we start down the path of
60 * going idle we continue to do idle even if we get
61 * a clock tick interrupt . .
63 void omap_pm_idle(void)
65 int (*func_ptr)(void) = 0;
66 unsigned int mask32 = 0;
69 * If the DSP is being used let's just idle the CPU, the overhead
70 * to wake up from Big Sleep is big, milliseconds versus micro
71 * seconds for wait for interrupt.
81 mask32 = omap_readl(ARM_SYSST);
85 #if defined(CONFIG_OMAP_32K_TIMER) && defined(CONFIG_NO_IDLE_HZ)
86 /* Override timer to use VST for the next cycle */
87 omap_32k_timer_next_vst_interrupt();
90 if ((mask32 & DSP_IDLE) == 0) {
91 __asm__ volatile ("mcr p15, 0, r0, c7, c0, 4");
94 if (cpu_is_omap1510()) {
95 func_ptr = (void *)(OMAP1510_SRAM_IDLE_SUSPEND);
96 } else if (cpu_is_omap1610() || cpu_is_omap1710()) {
97 func_ptr = (void *)(OMAP1610_SRAM_IDLE_SUSPEND);
98 } else if (cpu_is_omap5912()) {
99 func_ptr = (void *)(OMAP5912_SRAM_IDLE_SUSPEND);
107 * Configuration of the wakeup event is board specific. For the
108 * moment we put it into this helper function. Later it may move
109 * to board specific files.
111 static void omap_pm_wakeup_setup(void)
114 * Enable ARM XOR clock and release peripheral from reset by
115 * writing 1 to PER_EN bit in ARM_RSTCT2, this is required
116 * for UART configuration to use UART2 to wake up.
119 omap_writel(omap_readl(ARM_IDLECT2) | ENABLE_XORCLK, ARM_IDLECT2);
120 omap_writel(omap_readl(ARM_RSTCT2) | PER_EN, ARM_RSTCT2);
121 omap_writew(MODEM_32K_EN, ULPD_CLOCK_CTRL);
124 * Turn off all interrupts except L1-2nd level cascade,
125 * and the L2 wakeup interrupts: keypad and UART2.
128 omap_writel(~IRQ_LEVEL2, OMAP_IH1_MIR);
130 if (cpu_is_omap1510()) {
131 omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_MIR);
134 if (cpu_is_omap16xx()) {
135 omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_0_MIR);
137 omap_writel(~0x0, OMAP_IH2_1_MIR);
138 omap_writel(~0x0, OMAP_IH2_2_MIR);
139 omap_writel(~0x0, OMAP_IH2_3_MIR);
142 /* New IRQ agreement */
143 omap_writel(1, OMAP_IH1_CONTROL);
145 /* external PULL to down, bit 22 = 0 */
146 omap_writel(omap_readl(PULL_DWN_CTRL_2) & ~(1<<22), PULL_DWN_CTRL_2);
149 void omap_pm_suspend(void)
151 unsigned int mask32 = 0;
152 unsigned long arg0 = 0, arg1 = 0;
153 int (*func_ptr)(unsigned short, unsigned short) = 0;
154 unsigned short save_dsp_idlect2;
156 printk("PM: OMAP%x is entering deep sleep now ...\n", system_rev);
158 if (machine_is_omap_osk()) {
159 /* Stop LED1 (D9) blink */
160 tps65010_set_led(LED1, OFF);
164 * Step 1: turn off interrupts
171 * Step 2: save registers
173 * The omap is a strange/beautiful device. The caches, memory
174 * and register state are preserved across power saves.
175 * We have to save and restore very little register state to
178 * Save interrupt, MPUI, ARM and UPLD control registers.
181 if (cpu_is_omap1510()) {
182 MPUI1510_SAVE(OMAP_IH1_MIR);
183 MPUI1510_SAVE(OMAP_IH2_MIR);
184 MPUI1510_SAVE(MPUI_CTRL);
185 MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
186 MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
187 MPUI1510_SAVE(EMIFS_CONFIG);
188 MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
189 } else if (cpu_is_omap16xx()) {
190 MPUI1610_SAVE(OMAP_IH1_MIR);
191 MPUI1610_SAVE(OMAP_IH2_0_MIR);
192 MPUI1610_SAVE(OMAP_IH2_1_MIR);
193 MPUI1610_SAVE(OMAP_IH2_2_MIR);
194 MPUI1610_SAVE(OMAP_IH2_3_MIR);
195 MPUI1610_SAVE(MPUI_CTRL);
196 MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
197 MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
198 MPUI1610_SAVE(EMIFS_CONFIG);
199 MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
203 ARM_SAVE(ARM_IDLECT1);
204 ARM_SAVE(ARM_IDLECT2);
205 ARM_SAVE(ARM_EWUPCT);
206 ARM_SAVE(ARM_RSTCT1);
207 ARM_SAVE(ARM_RSTCT2);
209 ULPD_SAVE(ULPD_CLOCK_CTRL);
210 ULPD_SAVE(ULPD_STATUS_REQ);
213 * Step 3: LOW_PWR signal enabling
215 * Allow the LOW_PWR signal to be visible on MPUIO5 ball.
217 if (cpu_is_omap1510()) {
218 /* POWER_CTRL_REG = 0x1 (LOW_POWER is available) */
219 omap_writew(omap_readw(ULPD_POWER_CTRL) |
220 OMAP1510_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
221 } else if (cpu_is_omap16xx()) {
222 /* POWER_CTRL_REG = 0x1 (LOW_POWER is available) */
223 omap_writew(omap_readw(ULPD_POWER_CTRL) |
224 OMAP1610_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
227 /* configure LOW_PWR pin */
228 omap_cfg_reg(T20_1610_LOW_PWR);
231 * Step 4: OMAP DSP Shutdown
234 /* Set DSP_RST = 1 and DSP_EN = 0, put DSP block into reset */
235 omap_writel((omap_readl(ARM_RSTCT1) | DSP_RST) & ~DSP_ENABLE,
238 /* Set DSP boot mode to DSP-IDLE, DSP_BOOT_MODE = 0x2 */
239 omap_writel(DSP_IDLE_MODE, MPUI_DSP_BOOT_CONFIG);
241 /* Set EN_DSPCK = 0, stop DSP block clock */
242 omap_writel(omap_readl(ARM_CKCTL) & ~DSP_CLOCK_ENABLE, ARM_CKCTL);
244 /* Stop any DSP domain clocks */
245 omap_writel(omap_readl(ARM_IDLECT2) | (1<<EN_APICK), ARM_IDLECT2);
246 save_dsp_idlect2 = __raw_readw(DSP_IDLECT2);
247 __raw_writew(0, DSP_IDLECT2);
250 * Step 5: Wakeup Event Setup
253 omap_pm_wakeup_setup();
256 * Step 6a: ARM and Traffic controller shutdown
258 * Step 6 starts here with clock and watchdog disable
262 mask32 = omap_readl(ARM_IDLECT2);
263 mask32 &= ~(1<<EN_WDTCK); /* bit 0 -> 0 (WDT clock) */
264 mask32 |= (1<<EN_XORPCK); /* bit 1 -> 1 (XORPCK clock) */
265 mask32 &= ~(1<<EN_PERCK); /* bit 2 -> 0 (MPUPER_CK clock) */
266 mask32 &= ~(1<<EN_LCDCK); /* bit 3 -> 0 (LCDC clock) */
267 mask32 &= ~(1<<EN_LBCK); /* bit 4 -> 0 (local bus clock) */
268 mask32 |= (1<<EN_APICK); /* bit 6 -> 1 (MPUI clock) */
269 mask32 &= ~(1<<EN_TIMCK); /* bit 7 -> 0 (MPU timer clock) */
270 mask32 &= ~(1<<DMACK_REQ); /* bit 8 -> 0 (DMAC clock) */
271 mask32 &= ~(1<<EN_GPIOCK); /* bit 9 -> 0 (GPIO clock) */
272 omap_writel(mask32, ARM_IDLECT2);
274 /* disable ARM watchdog */
275 omap_writel(0x00F5, OMAP_WDT_TIMER_MODE);
276 omap_writel(0x00A0, OMAP_WDT_TIMER_MODE);
279 * Step 6b: ARM and Traffic controller shutdown
281 * Step 6 continues here. Prepare jump to power management
282 * assembly code in internal SRAM.
284 * Since the omap_cpu_suspend routine has been copied to
285 * SRAM, we'll do an indirect procedure call to it and pass the
286 * contents of arm_idlect1 and arm_idlect2 so it can restore
287 * them when it wakes up and it will return.
290 arg0 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT1];
291 arg1 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT2];
293 if (cpu_is_omap1510()) {
294 func_ptr = (void *)(OMAP1510_SRAM_API_SUSPEND);
295 } else if (cpu_is_omap1610() || cpu_is_omap1710()) {
296 func_ptr = (void *)(OMAP1610_SRAM_API_SUSPEND);
297 } else if (cpu_is_omap5912()) {
298 func_ptr = (void *)(OMAP5912_SRAM_API_SUSPEND);
302 * Step 6c: ARM and Traffic controller shutdown
304 * Jump to assembly code. The processor will stay there
308 func_ptr(arg0, arg1);
311 * If we are here, processor is woken up!
314 if (cpu_is_omap1510()) {
315 /* POWER_CTRL_REG = 0x0 (LOW_POWER is disabled) */
316 omap_writew(omap_readw(ULPD_POWER_CTRL) &
317 ~OMAP1510_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
318 } else if (cpu_is_omap16xx()) {
319 /* POWER_CTRL_REG = 0x0 (LOW_POWER is disabled) */
320 omap_writew(omap_readw(ULPD_POWER_CTRL) &
321 ~OMAP1610_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
325 /* Restore DSP clocks */
326 omap_writel(omap_readl(ARM_IDLECT2) | (1<<EN_APICK), ARM_IDLECT2);
327 __raw_writew(save_dsp_idlect2, DSP_IDLECT2);
328 ARM_RESTORE(ARM_IDLECT2);
331 * Restore ARM state, except ARM_IDLECT1/2 which omap_cpu_suspend did
334 ARM_RESTORE(ARM_CKCTL);
335 ARM_RESTORE(ARM_EWUPCT);
336 ARM_RESTORE(ARM_RSTCT1);
337 ARM_RESTORE(ARM_RSTCT2);
338 ARM_RESTORE(ARM_SYSST);
339 ULPD_RESTORE(ULPD_CLOCK_CTRL);
340 ULPD_RESTORE(ULPD_STATUS_REQ);
342 if (cpu_is_omap1510()) {
343 MPUI1510_RESTORE(MPUI_CTRL);
344 MPUI1510_RESTORE(MPUI_DSP_BOOT_CONFIG);
345 MPUI1510_RESTORE(MPUI_DSP_API_CONFIG);
346 MPUI1510_RESTORE(EMIFS_CONFIG);
347 MPUI1510_RESTORE(EMIFF_SDRAM_CONFIG);
348 MPUI1510_RESTORE(OMAP_IH1_MIR);
349 MPUI1510_RESTORE(OMAP_IH2_MIR);
350 } else if (cpu_is_omap16xx()) {
351 MPUI1610_RESTORE(MPUI_CTRL);
352 MPUI1610_RESTORE(MPUI_DSP_BOOT_CONFIG);
353 MPUI1610_RESTORE(MPUI_DSP_API_CONFIG);
354 MPUI1610_RESTORE(EMIFS_CONFIG);
355 MPUI1610_RESTORE(EMIFF_SDRAM_CONFIG);
357 MPUI1610_RESTORE(OMAP_IH1_MIR);
358 MPUI1610_RESTORE(OMAP_IH2_0_MIR);
359 MPUI1610_RESTORE(OMAP_IH2_1_MIR);
360 MPUI1610_RESTORE(OMAP_IH2_2_MIR);
361 MPUI1610_RESTORE(OMAP_IH2_3_MIR);
365 * Reenable interrupts
371 printk("PM: OMAP%x is re-starting from deep sleep...\n", system_rev);
373 if (machine_is_omap_osk()) {
374 /* Let LED1 (D9) blink again */
375 tps65010_set_led(LED1, BLINK);
379 #if defined(DEBUG) && defined(CONFIG_PROC_FS)
380 static int g_read_completed;
383 * Read system PM registers for debugging
385 static int omap_pm_read_proc(
387 char **my_first_byte,
393 int my_buffer_offset = 0;
394 char * const my_base = page_buffer;
397 ARM_SAVE(ARM_IDLECT1);
398 ARM_SAVE(ARM_IDLECT2);
399 ARM_SAVE(ARM_EWUPCT);
400 ARM_SAVE(ARM_RSTCT1);
401 ARM_SAVE(ARM_RSTCT2);
404 ULPD_SAVE(ULPD_IT_STATUS);
405 ULPD_SAVE(ULPD_CLOCK_CTRL);
406 ULPD_SAVE(ULPD_SOFT_REQ);
407 ULPD_SAVE(ULPD_STATUS_REQ);
408 ULPD_SAVE(ULPD_DPLL_CTRL);
409 ULPD_SAVE(ULPD_POWER_CTRL);
411 if (cpu_is_omap1510()) {
412 MPUI1510_SAVE(MPUI_CTRL);
413 MPUI1510_SAVE(MPUI_DSP_STATUS);
414 MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
415 MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
416 MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
417 MPUI1510_SAVE(EMIFS_CONFIG);
418 } else if (cpu_is_omap16xx()) {
419 MPUI1610_SAVE(MPUI_CTRL);
420 MPUI1610_SAVE(MPUI_DSP_STATUS);
421 MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
422 MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
423 MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
424 MPUI1610_SAVE(EMIFS_CONFIG);
427 if (virtual_start == 0) {
428 g_read_completed = 0;
430 my_buffer_offset += sprintf(my_base + my_buffer_offset,
431 "ARM_CKCTL_REG: 0x%-8x \n"
432 "ARM_IDLECT1_REG: 0x%-8x \n"
433 "ARM_IDLECT2_REG: 0x%-8x \n"
434 "ARM_EWUPCT_REG: 0x%-8x \n"
435 "ARM_RSTCT1_REG: 0x%-8x \n"
436 "ARM_RSTCT2_REG: 0x%-8x \n"
437 "ARM_SYSST_REG: 0x%-8x \n"
438 "ULPD_IT_STATUS_REG: 0x%-4x \n"
439 "ULPD_CLOCK_CTRL_REG: 0x%-4x \n"
440 "ULPD_SOFT_REQ_REG: 0x%-4x \n"
441 "ULPD_DPLL_CTRL_REG: 0x%-4x \n"
442 "ULPD_STATUS_REQ_REG: 0x%-4x \n"
443 "ULPD_POWER_CTRL_REG: 0x%-4x \n",
445 ARM_SHOW(ARM_IDLECT1),
446 ARM_SHOW(ARM_IDLECT2),
447 ARM_SHOW(ARM_EWUPCT),
448 ARM_SHOW(ARM_RSTCT1),
449 ARM_SHOW(ARM_RSTCT2),
451 ULPD_SHOW(ULPD_IT_STATUS),
452 ULPD_SHOW(ULPD_CLOCK_CTRL),
453 ULPD_SHOW(ULPD_SOFT_REQ),
454 ULPD_SHOW(ULPD_DPLL_CTRL),
455 ULPD_SHOW(ULPD_STATUS_REQ),
456 ULPD_SHOW(ULPD_POWER_CTRL));
458 if (cpu_is_omap1510()) {
459 my_buffer_offset += sprintf(my_base + my_buffer_offset,
460 "MPUI1510_CTRL_REG 0x%-8x \n"
461 "MPUI1510_DSP_STATUS_REG: 0x%-8x \n"
462 "MPUI1510_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
463 "MPUI1510_DSP_API_CONFIG_REG: 0x%-8x \n"
464 "MPUI1510_SDRAM_CONFIG_REG: 0x%-8x \n"
465 "MPUI1510_EMIFS_CONFIG_REG: 0x%-8x \n",
466 MPUI1510_SHOW(MPUI_CTRL),
467 MPUI1510_SHOW(MPUI_DSP_STATUS),
468 MPUI1510_SHOW(MPUI_DSP_BOOT_CONFIG),
469 MPUI1510_SHOW(MPUI_DSP_API_CONFIG),
470 MPUI1510_SHOW(EMIFF_SDRAM_CONFIG),
471 MPUI1510_SHOW(EMIFS_CONFIG));
472 } else if (cpu_is_omap16xx()) {
473 my_buffer_offset += sprintf(my_base + my_buffer_offset,
474 "MPUI1610_CTRL_REG 0x%-8x \n"
475 "MPUI1610_DSP_STATUS_REG: 0x%-8x \n"
476 "MPUI1610_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
477 "MPUI1610_DSP_API_CONFIG_REG: 0x%-8x \n"
478 "MPUI1610_SDRAM_CONFIG_REG: 0x%-8x \n"
479 "MPUI1610_EMIFS_CONFIG_REG: 0x%-8x \n",
480 MPUI1610_SHOW(MPUI_CTRL),
481 MPUI1610_SHOW(MPUI_DSP_STATUS),
482 MPUI1610_SHOW(MPUI_DSP_BOOT_CONFIG),
483 MPUI1610_SHOW(MPUI_DSP_API_CONFIG),
484 MPUI1610_SHOW(EMIFF_SDRAM_CONFIG),
485 MPUI1610_SHOW(EMIFS_CONFIG));
489 } else if (g_read_completed >= 1) {
495 *my_first_byte = page_buffer;
496 return my_buffer_offset;
499 static void omap_pm_init_proc(void)
501 struct proc_dir_entry *entry;
503 entry = create_proc_read_entry("driver/omap_pm",
504 S_IWUSR | S_IRUGO, NULL,
505 omap_pm_read_proc, 0);
508 #endif /* DEBUG && CONFIG_PROC_FS */
511 * omap_pm_prepare - Do preliminary suspend work.
512 * @state: suspend state we're entering.
515 //#include <asm/arch/hardware.h>
517 static int omap_pm_prepare(suspend_state_t state)
523 case PM_SUSPEND_STANDBY:
527 case PM_SUSPEND_DISK:
539 * omap_pm_enter - Actually enter a sleep state.
540 * @state: State we're entering.
544 static int omap_pm_enter(suspend_state_t state)
548 case PM_SUSPEND_STANDBY:
553 case PM_SUSPEND_DISK:
565 * omap_pm_finish - Finish up suspend sequence.
566 * @state: State we're coming out of.
568 * This is called after we wake back up (or if entering the sleep state
572 static int omap_pm_finish(suspend_state_t state)
578 struct pm_ops omap_pm_ops ={
580 .prepare = omap_pm_prepare,
581 .enter = omap_pm_enter,
582 .finish = omap_pm_finish,
585 static int __init omap_pm_init(void)
587 printk("Power Management for TI OMAP.\n");
588 pm_idle = omap_pm_idle;
590 * We copy the assembler sleep/wakeup routines to SRAM.
591 * These routines need to be in SRAM as that's the only
592 * memory the MPU can see when it wakes up.
595 #ifdef CONFIG_ARCH_OMAP1510
596 if (cpu_is_omap1510()) {
597 memcpy((void *)OMAP1510_SRAM_IDLE_SUSPEND,
598 omap1510_idle_loop_suspend,
599 omap1510_idle_loop_suspend_sz);
600 memcpy((void *)OMAP1510_SRAM_API_SUSPEND, omap1510_cpu_suspend,
601 omap1510_cpu_suspend_sz);
604 if (cpu_is_omap1610() || cpu_is_omap1710()) {
605 memcpy((void *)OMAP1610_SRAM_IDLE_SUSPEND,
606 omap1610_idle_loop_suspend,
607 omap1610_idle_loop_suspend_sz);
608 memcpy((void *)OMAP1610_SRAM_API_SUSPEND, omap1610_cpu_suspend,
609 omap1610_cpu_suspend_sz);
610 } else if (cpu_is_omap5912()) {
611 memcpy((void *)OMAP5912_SRAM_IDLE_SUSPEND,
612 omap1610_idle_loop_suspend,
613 omap1610_idle_loop_suspend_sz);
614 memcpy((void *)OMAP5912_SRAM_API_SUSPEND, omap1610_cpu_suspend,
615 omap1610_cpu_suspend_sz);
618 pm_set_ops(&omap_pm_ops);
620 #if defined(DEBUG) && defined(CONFIG_PROC_FS)
626 __initcall(omap_pm_init);