diff options
| author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-02 18:04:12 -0400 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-02 18:04:12 -0400 | 
| commit | a8c4c20dfa8b28a3c99e33c639d9c2ea5657741e (patch) | |
| tree | 887b64d29b5a46d9ab2ca1267d8a2f05b5845561 /arch/arm/mach-omap2/pm.c | |
| parent | 168d04b3b4de7723eb73b3cffc9cb75224e0f393 (diff) | |
| parent | 2dc7667b9d0674db6572723356fe3857031101a4 (diff) | |
Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (44 commits)
  [ARM] 3541/2: workaround for PXA27x erratum E7
  [ARM] nommu: provide a way for correct control register value selection
  [ARM] 3705/1: add supersection support to ioremap()
  [ARM] 3707/1: iwmmxt: use the generic thread notifier infrastructure
  [ARM] 3706/2: ep93xx: add cirrus logic edb9315a support
  [ARM] 3704/1: format IOP Kconfig with tabs, create more consistency
  [ARM] 3703/1: Add help description for ARCH_EP80219
  [ARM] 3678/1: MMC: Make OMAP MMC work
  [ARM] 3677/1: OMAP: Update H2 defconfig
  [ARM] 3676/1: ARM: OMAP: Fix dmtimers and timer32k to compile on OMAP1
  [ARM] Add section support to ioremap
  [ARM] Fix sa11x0 SDRAM selection
  [ARM] Set bit 4 on section mappings correctly depending on CPU
  [ARM] 3666/1: TRIZEPS4 [1/5] core
  ARM: OMAP: Multiplexing for 24xx GPMC wait pin monitoring
  ARM: OMAP: Fix SRAM to use MT_MEMORY instead of MT_DEVICE
  ARM: OMAP: Update dmtimers
  ARM: OMAP: Make clock variables static
  ARM: OMAP: Fix GPMC compilation when DEBUG is defined
  ARM: OMAP: Mux updates for external DMA and GPIO
  ...
Diffstat (limited to 'arch/arm/mach-omap2/pm.c')
| -rw-r--r-- | arch/arm/mach-omap2/pm.c | 271 | 
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 | |||
| 39 | static struct clk *vclk; | 42 | static struct clk *vclk; | 
| 40 | static void (*omap2_sram_idle)(void); | 43 | static void (*omap2_sram_idle)(void); | 
| 41 | static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev); | 44 | static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev); | 
| 42 | static void (*saved_idle)(void); | 45 | static void (*saved_idle)(void); | 
| 43 | 46 | ||
| 47 | extern void __init pmdomain_init(void); | ||
| 48 | extern void pmdomain_set_autoidle(void); | ||
| 49 | |||
| 50 | static unsigned int omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_SIZE]; | ||
| 51 | |||
| 44 | void omap2_pm_idle(void) | 52 | void 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); | ||
| 109 | |||
| 110 | static 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 | |||
| 182 | static 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 | |||
| 233 | static 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 | |||
| 286 | static 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 | |||
| 90 | static int omap2_pm_enter(suspend_state_t state) | 346 | static 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 | ||
| 109 | static int omap2_pm_finish(suspend_state_t state) | 366 | static 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 | ||
