1/* 2 * Low-level Power Management code. 3 * 4 * Copyright (C) 2008 Atmel Corporation 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10#include <asm/asm.h> 11#include <asm/asm-offsets.h> 12#include <asm/thread_info.h> 13#include <mach/pm.h> 14 15#include "pm.h" 16#include "sdramc.h" 17 18/* Same as 0xfff00000 but fits in a 21 bit signed immediate */ 19#define PM_BASE -0x100000 20 21 .section .bss, "wa", @nobits 22 .global disable_idle_sleep 23 .type disable_idle_sleep, @object 24disable_idle_sleep: 25 .int 4 26 .size disable_idle_sleep, . - disable_idle_sleep 27 28 /* Keep this close to the irq handlers */ 29 .section .irq.text, "ax", @progbits 30 31 .global cpu_enter_idle 32 .type cpu_enter_idle, @function 33cpu_enter_idle: 34 mask_interrupts 35 get_thread_info r8 36 ld.w r9, r8[TI_flags] 37 bld r9, TIF_NEED_RESCHED 38 brcs .Lret_from_sleep 39 sbr r9, TIF_CPU_GOING_TO_SLEEP 40 st.w r8[TI_flags], r9 41 unmask_interrupts 42 sleep CPU_SLEEP_IDLE 43 .size cpu_idle_sleep, . - cpu_idle_sleep 44 45 /* 46 * Common return path for PM functions that don't run from 47 * SRAM. 48 */ 49 .global cpu_idle_skip_sleep 50 .type cpu_idle_skip_sleep, @function 51cpu_idle_skip_sleep: 52 mask_interrupts 53 ld.w r9, r8[TI_flags] 54 cbr r9, TIF_CPU_GOING_TO_SLEEP 55 st.w r8[TI_flags], r9 56.Lret_from_sleep: 57 unmask_interrupts 58 retal r12 59 .size cpu_idle_skip_sleep, . - cpu_idle_skip_sleep 60 61#ifdef CONFIG_PM 62 .section .init.text, "ax", @progbits 63 64 .global pm_exception 65 .type pm_exception, @function 66pm_exception: 67 /* 68 * Exceptions are masked when we switch to this handler, so 69 * we'll only get "unrecoverable" exceptions (offset 0.) 70 */ 71 sub r12, pc, . - .Lpanic_msg 72 lddpc pc, .Lpanic_addr 73 74 .align 2 75.Lpanic_addr: 76 .long panic 77.Lpanic_msg: 78 .asciz "Unrecoverable exception during suspend\n" 79 .size pm_exception, . - pm_exception 80 81 .global pm_irq0 82 .type pm_irq0, @function 83pm_irq0: 84 /* Disable interrupts and return after the sleep instruction */ 85 mfsr r9, SYSREG_RSR_INT0 86 mtsr SYSREG_RAR_INT0, r8 87 sbr r9, SYSREG_GM_OFFSET 88 mtsr SYSREG_RSR_INT0, r9 89 rete 90 91 /* 92 * void cpu_enter_standby(unsigned long sdramc_base) 93 * 94 * Enter PM_SUSPEND_STANDBY mode. At this point, all drivers 95 * are suspended and interrupts are disabled. Interrupts 96 * marked as 'wakeup' event sources may still come along and 97 * get us out of here. 98 * 99 * The SDRAM will be put into self-refresh mode (which does 100 * not require a clock from the CPU), and the CPU will be put 101 * into "frozen" mode (HSB bus stopped). The SDRAM controller 102 * will automatically bring the SDRAM into normal mode on the 103 * first access, and the power manager will automatically 104 * start the HSB and CPU clocks upon a wakeup event. 105 * 106 * This code uses the same "skip sleep" technique as above. 107 * It is very important that we jump directly to 108 * cpu_after_sleep after the sleep instruction since that's 109 * where we'll end up if the interrupt handler decides that we 110 * need to skip the sleep instruction. 111 */ 112 .global pm_standby 113 .type pm_standby, @function 114pm_standby: 115 /* 116 * interrupts are already masked at this point, and EVBA 117 * points to pm_exception above. 118 */ 119 ld.w r10, r12[SDRAMC_LPR] 120 sub r8, pc, . - 1f /* return address for irq handler */ 121 mov r11, SDRAMC_LPR_LPCB_SELF_RFR 122 bfins r10, r11, 0, 2 /* LPCB <- self Refresh */ 123 sync 0 /* flush write buffer */ 124 st.w r12[SDRAMC_LPR], r10 /* put SDRAM in self-refresh mode */ 125 ld.w r11, r12[SDRAMC_LPR] 126 unmask_interrupts 127 sleep CPU_SLEEP_FROZEN 1281: mask_interrupts 129 retal r12 130 .size pm_standby, . - pm_standby 131 132 .global pm_suspend_to_ram 133 .type pm_suspend_to_ram, @function 134pm_suspend_to_ram: 135 /* 136 * interrupts are already masked at this point, and EVBA 137 * points to pm_exception above. 138 */ 139 mov r11, 0 140 cache r11[2], 8 /* clean all dcache lines */ 141 sync 0 /* flush write buffer */ 142 ld.w r10, r12[SDRAMC_LPR] 143 sub r8, pc, . - 1f /* return address for irq handler */ 144 mov r11, SDRAMC_LPR_LPCB_SELF_RFR 145 bfins r10, r11, 0, 2 /* LPCB <- self refresh */ 146 st.w r12[SDRAMC_LPR], r10 /* put SDRAM in self-refresh mode */ 147 ld.w r11, r12[SDRAMC_LPR] 148 149 unmask_interrupts 150 sleep CPU_SLEEP_STOP 1511: mask_interrupts 152 153 retal r12 154 .size pm_suspend_to_ram, . - pm_suspend_to_ram 155 156 .global pm_sram_end 157 .type pm_sram_end, @function 158pm_sram_end: 159 .size pm_sram_end, 0 160 161#endif /* CONFIG_PM */ 162