1 /* 2 * linux/arch/arm/mach-omap2/pm.c 3 * 4 * OMAP2 Power Management Routines 5 * 6 * Copyright (C) 2006 Nokia Corporation 7 * Tony Lindgren <tony@atomide.com> 8 * 9 * Copyright (C) 2005 Texas Instruments, Inc. 10 * Richard Woodruff <r-woodruff2@ti.com> 11 * 12 * Based on pm.c for omap1 13 * 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. 17 */ 18 19 #include <linux/suspend.h> 20 #include <linux/sched.h> 21 #include <linux/proc_fs.h> 22 #include <linux/interrupt.h> 23 #include <linux/sysfs.h> 24 #include <linux/module.h> 25 #include <linux/delay.h> 26 27 #include <asm/io.h> 28 #include <asm/irq.h> 29 #include <asm/atomic.h> 30 #include <asm/mach/time.h> 31 #include <asm/mach/irq.h> 32 #include <asm/mach-types.h> 33 34 #include <asm/arch/irqs.h> 35 #include <asm/arch/clock.h> 36 #include <asm/arch/sram.h> 37 #include <asm/arch/pm.h> 38 39 #include "prcm-regs.h" 40 41 static struct clk *vclk; 42 static void (*omap2_sram_idle)(void); 43 static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev); 44 static void (*saved_idle)(void); 45 46 extern void __init pmdomain_init(void); 47 extern void pmdomain_set_autoidle(void); 48 49 static unsigned int omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_SIZE]; 50 51 void omap2_pm_idle(void) 52 { 53 local_irq_disable(); 54 local_fiq_disable(); 55 if (need_resched()) { 56 local_fiq_enable(); 57 local_irq_enable(); 58 return; 59 } 60 61 /* 62 * Since an interrupt may set up a timer, we don't want to 63 * reprogram the hardware timer with interrupts enabled. 64 * Re-enable interrupts only after returning from idle. 65 */ 66 timer_dyn_reprogram(); 67 68 omap2_sram_idle(); 69 local_fiq_enable(); 70 local_irq_enable(); 71 } 72 73 static int omap2_pm_prepare(void) 74 { 75 /* We cannot sleep in idle until we have resumed */ 76 saved_idle = pm_idle; 77 pm_idle = NULL; 78 return 0; 79 } 80 81 #define INT0_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_GPIO_BANK1) | \ 82 OMAP_IRQ_BIT(INT_24XX_GPIO_BANK2) | \ 83 OMAP_IRQ_BIT(INT_24XX_GPIO_BANK3)) 84 85 #define INT1_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_GPIO_BANK4)) 86 87 #define INT2_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_UART1_IRQ) | \ 88 OMAP_IRQ_BIT(INT_24XX_UART2_IRQ) | \ 89 OMAP_IRQ_BIT(INT_24XX_UART3_IRQ)) 90 91 #define preg(reg) printk("%s\t(0x%p):\t0x%08x\n", #reg, ®, reg); 92 93 static void omap2_pm_debug(char * desc) 94 { 95 printk("%s:\n", desc); 96 97 preg(CM_CLKSTCTRL_MPU); 98 preg(CM_CLKSTCTRL_CORE); 99 preg(CM_CLKSTCTRL_GFX); 100 preg(CM_CLKSTCTRL_DSP); 101 preg(CM_CLKSTCTRL_MDM); 102 103 preg(PM_PWSTCTRL_MPU); 104 preg(PM_PWSTCTRL_CORE); 105 preg(PM_PWSTCTRL_GFX); 106 preg(PM_PWSTCTRL_DSP); 107 preg(PM_PWSTCTRL_MDM); 108 109 preg(PM_PWSTST_MPU); 110 preg(PM_PWSTST_CORE); 111 preg(PM_PWSTST_GFX); 112 preg(PM_PWSTST_DSP); 113 preg(PM_PWSTST_MDM); 114 115 preg(CM_AUTOIDLE1_CORE); 116 preg(CM_AUTOIDLE2_CORE); 117 preg(CM_AUTOIDLE3_CORE); 118 preg(CM_AUTOIDLE4_CORE); 119 preg(CM_AUTOIDLE_WKUP); 120 preg(CM_AUTOIDLE_PLL); 121 preg(CM_AUTOIDLE_DSP); 122 preg(CM_AUTOIDLE_MDM); 123 124 preg(CM_ICLKEN1_CORE); 125 preg(CM_ICLKEN2_CORE); 126 preg(CM_ICLKEN3_CORE); 127 preg(CM_ICLKEN4_CORE); 128 preg(CM_ICLKEN_GFX); 129 preg(CM_ICLKEN_WKUP); 130 preg(CM_ICLKEN_DSP); 131 preg(CM_ICLKEN_MDM); 132 133 preg(CM_IDLEST1_CORE); 134 preg(CM_IDLEST2_CORE); 135 preg(CM_IDLEST3_CORE); 136 preg(CM_IDLEST4_CORE); 137 preg(CM_IDLEST_GFX); 138 preg(CM_IDLEST_WKUP); 139 preg(CM_IDLEST_CKGEN); 140 preg(CM_IDLEST_DSP); 141 preg(CM_IDLEST_MDM); 142 143 preg(RM_RSTST_MPU); 144 preg(RM_RSTST_GFX); 145 preg(RM_RSTST_WKUP); 146 preg(RM_RSTST_DSP); 147 preg(RM_RSTST_MDM); 148 149 preg(PM_WKDEP_MPU); 150 preg(PM_WKDEP_CORE); 151 preg(PM_WKDEP_GFX); 152 preg(PM_WKDEP_DSP); 153 preg(PM_WKDEP_MDM); 154 155 preg(CM_FCLKEN_WKUP); 156 preg(CM_ICLKEN_WKUP); 157 preg(CM_IDLEST_WKUP); 158 preg(CM_AUTOIDLE_WKUP); 159 preg(CM_CLKSEL_WKUP); 160 161 preg(PM_WKEN_WKUP); 162 preg(PM_WKST_WKUP); 163 } 164 165 static inline void omap2_pm_save_registers(void) 166 { 167 /* Save interrupt registers */ 168 OMAP24XX_SAVE(INTC_MIR0); 169 OMAP24XX_SAVE(INTC_MIR1); 170 OMAP24XX_SAVE(INTC_MIR2); 171 172 /* Save power control registers */ 173 OMAP24XX_SAVE(CM_CLKSTCTRL_MPU); 174 OMAP24XX_SAVE(CM_CLKSTCTRL_CORE); 175 OMAP24XX_SAVE(CM_CLKSTCTRL_GFX); 176 OMAP24XX_SAVE(CM_CLKSTCTRL_DSP); 177 OMAP24XX_SAVE(CM_CLKSTCTRL_MDM); 178 179 /* Save power state registers */ 180 OMAP24XX_SAVE(PM_PWSTCTRL_MPU); 181 OMAP24XX_SAVE(PM_PWSTCTRL_CORE); 182 OMAP24XX_SAVE(PM_PWSTCTRL_GFX); 183 OMAP24XX_SAVE(PM_PWSTCTRL_DSP); 184 OMAP24XX_SAVE(PM_PWSTCTRL_MDM); 185 186 /* Save autoidle registers */ 187 OMAP24XX_SAVE(CM_AUTOIDLE1_CORE); 188 OMAP24XX_SAVE(CM_AUTOIDLE2_CORE); 189 OMAP24XX_SAVE(CM_AUTOIDLE3_CORE); 190 OMAP24XX_SAVE(CM_AUTOIDLE4_CORE); 191 OMAP24XX_SAVE(CM_AUTOIDLE_WKUP); 192 OMAP24XX_SAVE(CM_AUTOIDLE_PLL); 193 OMAP24XX_SAVE(CM_AUTOIDLE_DSP); 194 OMAP24XX_SAVE(CM_AUTOIDLE_MDM); 195 196 /* Save idle state registers */ 197 OMAP24XX_SAVE(CM_IDLEST1_CORE); 198 OMAP24XX_SAVE(CM_IDLEST2_CORE); 199 OMAP24XX_SAVE(CM_IDLEST3_CORE); 200 OMAP24XX_SAVE(CM_IDLEST4_CORE); 201 OMAP24XX_SAVE(CM_IDLEST_GFX); 202 OMAP24XX_SAVE(CM_IDLEST_WKUP); 203 OMAP24XX_SAVE(CM_IDLEST_CKGEN); 204 OMAP24XX_SAVE(CM_IDLEST_DSP); 205 OMAP24XX_SAVE(CM_IDLEST_MDM); 206 207 /* Save clock registers */ 208 OMAP24XX_SAVE(CM_FCLKEN1_CORE); 209 OMAP24XX_SAVE(CM_FCLKEN2_CORE); 210 OMAP24XX_SAVE(CM_ICLKEN1_CORE); 211 OMAP24XX_SAVE(CM_ICLKEN2_CORE); 212 OMAP24XX_SAVE(CM_ICLKEN3_CORE); 213 OMAP24XX_SAVE(CM_ICLKEN4_CORE); 214 } 215 216 static inline void omap2_pm_restore_registers(void) 217 { 218 /* Restore clock state registers */ 219 OMAP24XX_RESTORE(CM_CLKSTCTRL_MPU); 220 OMAP24XX_RESTORE(CM_CLKSTCTRL_CORE); 221 OMAP24XX_RESTORE(CM_CLKSTCTRL_GFX); 222 OMAP24XX_RESTORE(CM_CLKSTCTRL_DSP); 223 OMAP24XX_RESTORE(CM_CLKSTCTRL_MDM); 224 225 /* Restore power state registers */ 226 OMAP24XX_RESTORE(PM_PWSTCTRL_MPU); 227 OMAP24XX_RESTORE(PM_PWSTCTRL_CORE); 228 OMAP24XX_RESTORE(PM_PWSTCTRL_GFX); 229 OMAP24XX_RESTORE(PM_PWSTCTRL_DSP); 230 OMAP24XX_RESTORE(PM_PWSTCTRL_MDM); 231 232 /* Restore idle state registers */ 233 OMAP24XX_RESTORE(CM_IDLEST1_CORE); 234 OMAP24XX_RESTORE(CM_IDLEST2_CORE); 235 OMAP24XX_RESTORE(CM_IDLEST3_CORE); 236 OMAP24XX_RESTORE(CM_IDLEST4_CORE); 237 OMAP24XX_RESTORE(CM_IDLEST_GFX); 238 OMAP24XX_RESTORE(CM_IDLEST_WKUP); 239 OMAP24XX_RESTORE(CM_IDLEST_CKGEN); 240 OMAP24XX_RESTORE(CM_IDLEST_DSP); 241 OMAP24XX_RESTORE(CM_IDLEST_MDM); 242 243 /* Restore autoidle registers */ 244 OMAP24XX_RESTORE(CM_AUTOIDLE1_CORE); 245 OMAP24XX_RESTORE(CM_AUTOIDLE2_CORE); 246 OMAP24XX_RESTORE(CM_AUTOIDLE3_CORE); 247 OMAP24XX_RESTORE(CM_AUTOIDLE4_CORE); 248 OMAP24XX_RESTORE(CM_AUTOIDLE_WKUP); 249 OMAP24XX_RESTORE(CM_AUTOIDLE_PLL); 250 OMAP24XX_RESTORE(CM_AUTOIDLE_DSP); 251 OMAP24XX_RESTORE(CM_AUTOIDLE_MDM); 252 253 /* Restore clock registers */ 254 OMAP24XX_RESTORE(CM_FCLKEN1_CORE); 255 OMAP24XX_RESTORE(CM_FCLKEN2_CORE); 256 OMAP24XX_RESTORE(CM_ICLKEN1_CORE); 257 OMAP24XX_RESTORE(CM_ICLKEN2_CORE); 258 OMAP24XX_RESTORE(CM_ICLKEN3_CORE); 259 OMAP24XX_RESTORE(CM_ICLKEN4_CORE); 260 261 /* REVISIT: Clear interrupts here */ 262 263 /* Restore interrupt registers */ 264 OMAP24XX_RESTORE(INTC_MIR0); 265 OMAP24XX_RESTORE(INTC_MIR1); 266 OMAP24XX_RESTORE(INTC_MIR2); 267 } 268 269 static int omap2_pm_suspend(void) 270 { 271 int processor_type = 0; 272 273 /* REVISIT: 0x21 or 0x26? */ 274 if (cpu_is_omap2420()) 275 processor_type = 0x21; 276 277 if (!processor_type) 278 return -ENOTSUPP; 279 280 local_irq_disable(); 281 local_fiq_disable(); 282 283 omap2_pm_save_registers(); 284 285 /* Disable interrupts except for the wake events */ 286 INTC_MIR_SET0 = 0xffffffff & ~INT0_WAKE_MASK; 287 INTC_MIR_SET1 = 0xffffffff & ~INT1_WAKE_MASK; 288 INTC_MIR_SET2 = 0xffffffff & ~INT2_WAKE_MASK; 289 290 pmdomain_set_autoidle(); 291 292 /* Clear old wake-up events */ 293 PM_WKST1_CORE = 0; 294 PM_WKST2_CORE = 0; 295 PM_WKST_WKUP = 0; 296 297 /* Enable wake-up events */ 298 PM_WKEN1_CORE = (1 << 22) | (1 << 21); /* UART1 & 2 */ 299 PM_WKEN2_CORE = (1 << 2); /* UART3 */ 300 PM_WKEN_WKUP = (1 << 2) | (1 << 0); /* GPIO & GPT1 */ 301 302 /* Disable clocks except for CM_ICLKEN2_CORE. It gets disabled 303 * in the SRAM suspend code */ 304 CM_FCLKEN1_CORE = 0; 305 CM_FCLKEN2_CORE = 0; 306 CM_ICLKEN1_CORE = 0; 307 CM_ICLKEN3_CORE = 0; 308 CM_ICLKEN4_CORE = 0; 309 310 omap2_pm_debug("Status before suspend"); 311 312 /* Must wait for serial buffers to clear */ 313 mdelay(200); 314 315 /* Jump to SRAM suspend code 316 * REVISIT: When is this SDRC_DLLB_CTRL? 317 */ 318 omap2_sram_suspend(SDRC_DLLA_CTRL, processor_type); 319 320 /* Back from sleep */ 321 omap2_pm_restore_registers(); 322 323 local_fiq_enable(); 324 local_irq_enable(); 325 326 return 0; 327 } 328 329 static int omap2_pm_enter(suspend_state_t state) 330 { 331 int ret = 0; 332 333 switch (state) 334 { 335 case PM_SUSPEND_STANDBY: 336 case PM_SUSPEND_MEM: 337 ret = omap2_pm_suspend(); 338 break; 339 default: 340 ret = -EINVAL; 341 } 342 343 return ret; 344 } 345 346 static void omap2_pm_finish(void) 347 { 348 pm_idle = saved_idle; 349 } 350 351 static struct platform_suspend_ops omap_pm_ops = { 352 .prepare = omap2_pm_prepare, 353 .enter = omap2_pm_enter, 354 .finish = omap2_pm_finish, 355 .valid = suspend_valid_only_mem, 356 }; 357 358 int __init omap2_pm_init(void) 359 { 360 printk("Power Management for TI OMAP.\n"); 361 362 vclk = clk_get(NULL, "virt_prcm_set"); 363 if (IS_ERR(vclk)) { 364 printk(KERN_ERR "Could not get PM vclk\n"); 365 return -ENODEV; 366 } 367 368 /* 369 * We copy the assembler sleep/wakeup routines to SRAM. 370 * These routines need to be in SRAM as that's the only 371 * memory the MPU can see when it wakes up. 372 */ 373 omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend, 374 omap24xx_idle_loop_suspend_sz); 375 376 omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend, 377 omap24xx_cpu_suspend_sz); 378 379 suspend_set_ops(&omap_pm_ops); 380 pm_idle = omap2_pm_idle; 381 382 pmdomain_init(); 383 384 return 0; 385 } 386 387 __initcall(omap2_pm_init); 388