Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: OMAP: Add initial 24xx suspend support

This patch adds support for omap24xx power domains and
allows suspend to work.

Please note that for some reason core power domain still
does not seem to idle.

Signed-off-by: Tony Lindgren <tony@atomide.com>

+601 -7
+1 -1
arch/arm/mach-omap2/Makefile
··· 9 9 obj-$(CONFIG_OMAP_MPU_TIMER) += timer-gp.o 10 10 11 11 # Power Management 12 - obj-$(CONFIG_PM) += pm.o sleep.o 12 + obj-$(CONFIG_PM) += pm.o pm-domain.o sleep.o 13 13 14 14 # Specific board support 15 15 obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
+300
arch/arm/mach-omap2/pm-domain.c
··· 1 + /* 2 + * linux/arch/arm/mach-omap2/pm-domain.c 3 + * 4 + * Power domain functions for OMAP2 5 + * 6 + * Copyright (C) 2006 Nokia Corporation 7 + * Tony Lindgren <tony@atomide.com> 8 + * 9 + * Some code based on earlier OMAP2 sample PM code 10 + * Copyright (C) 2005 Texas Instruments, Inc. 11 + * Richard Woodruff <r-woodruff2@ti.com> 12 + * 13 + * This program is free software; you can redistribute it and/or modify 14 + * it under the terms of the GNU General Public License version 2 as 15 + * published by the Free Software Foundation. 16 + */ 17 + 18 + #include <linux/config.h> 19 + #include <linux/module.h> 20 + #include <linux/init.h> 21 + #include <linux/clk.h> 22 + 23 + #include <asm/io.h> 24 + 25 + #include "prcm-regs.h" 26 + 27 + /* Power domain offsets */ 28 + #define PM_MPU_OFFSET 0x100 29 + #define PM_CORE_OFFSET 0x200 30 + #define PM_GFX_OFFSET 0x300 31 + #define PM_WKUP_OFFSET 0x400 /* Autoidle only */ 32 + #define PM_PLL_OFFSET 0x500 /* Autoidle only */ 33 + #define PM_DSP_OFFSET 0x800 34 + #define PM_MDM_OFFSET 0xc00 35 + 36 + /* Power domain wake-up dependency control register */ 37 + #define PM_WKDEP_OFFSET 0xc8 38 + #define EN_MDM (1 << 5) 39 + #define EN_WKUP (1 << 4) 40 + #define EN_GFX (1 << 3) 41 + #define EN_DSP (1 << 2) 42 + #define EN_MPU (1 << 1) 43 + #define EN_CORE (1 << 0) 44 + 45 + /* Core power domain state transition control register */ 46 + #define PM_PWSTCTRL_OFFSET 0xe0 47 + #define FORCESTATE (1 << 18) /* Only for DSP & GFX */ 48 + #define MEM4RETSTATE (1 << 6) 49 + #define MEM3RETSTATE (1 << 5) 50 + #define MEM2RETSTATE (1 << 4) 51 + #define MEM1RETSTATE (1 << 3) 52 + #define LOGICRETSTATE (1 << 2) /* Logic is retained */ 53 + #define POWERSTATE_OFF 0x3 54 + #define POWERSTATE_RETENTION 0x1 55 + #define POWERSTATE_ON 0x0 56 + 57 + /* Power domain state register */ 58 + #define PM_PWSTST_OFFSET 0xe4 59 + 60 + /* Hardware supervised state transition control register */ 61 + #define CM_CLKSTCTRL_OFFSET 0x48 62 + #define AUTOSTAT_MPU (1 << 0) /* MPU */ 63 + #define AUTOSTAT_DSS (1 << 2) /* Core */ 64 + #define AUTOSTAT_L4 (1 << 1) /* Core */ 65 + #define AUTOSTAT_L3 (1 << 0) /* Core */ 66 + #define AUTOSTAT_GFX (1 << 0) /* GFX */ 67 + #define AUTOSTAT_IVA (1 << 8) /* 2420 IVA in DSP domain */ 68 + #define AUTOSTAT_DSP (1 << 0) /* DSP */ 69 + #define AUTOSTAT_MDM (1 << 0) /* MDM */ 70 + 71 + /* Automatic control of interface clock idling */ 72 + #define CM_AUTOIDLE1_OFFSET 0x30 73 + #define CM_AUTOIDLE2_OFFSET 0x34 /* Core only */ 74 + #define CM_AUTOIDLE3_OFFSET 0x38 /* Core only */ 75 + #define CM_AUTOIDLE4_OFFSET 0x3c /* Core only */ 76 + #define AUTO_54M(x) (((x) & 0x3) << 6) 77 + #define AUTO_96M(x) (((x) & 0x3) << 2) 78 + #define AUTO_DPLL(x) (((x) & 0x3) << 0) 79 + #define AUTO_STOPPED 0x3 80 + #define AUTO_BYPASS_FAST 0x2 /* DPLL only */ 81 + #define AUTO_BYPASS_LOW_POWER 0x1 /* DPLL only */ 82 + #define AUTO_DISABLED 0x0 83 + 84 + /* Voltage control PRCM_VOLTCTRL bits */ 85 + #define AUTO_EXTVOLT (1 << 15) 86 + #define FORCE_EXTVOLT (1 << 14) 87 + #define SETOFF_LEVEL(x) (((x) & 0x3) << 12) 88 + #define MEMRETCTRL (1 << 8) 89 + #define SETRET_LEVEL(x) (((x) & 0x3) << 6) 90 + #define VOLT_LEVEL(x) (((x) & 0x3) << 0) 91 + 92 + #define OMAP24XX_PRCM_VBASE IO_ADDRESS(OMAP24XX_PRCM_BASE) 93 + #define prcm_readl(r) __raw_readl(OMAP24XX_PRCM_VBASE + (r)) 94 + #define prcm_writel(v, r) __raw_writel((v), OMAP24XX_PRCM_VBASE + (r)) 95 + 96 + static u32 pmdomain_get_wakeup_dependencies(int domain_offset) 97 + { 98 + return prcm_readl(domain_offset + PM_WKDEP_OFFSET); 99 + } 100 + 101 + static void pmdomain_set_wakeup_dependencies(u32 state, int domain_offset) 102 + { 103 + prcm_writel(state, domain_offset + PM_WKDEP_OFFSET); 104 + } 105 + 106 + static u32 pmdomain_get_powerstate(int domain_offset) 107 + { 108 + return prcm_readl(domain_offset + PM_PWSTCTRL_OFFSET); 109 + } 110 + 111 + static void pmdomain_set_powerstate(u32 state, int domain_offset) 112 + { 113 + prcm_writel(state, domain_offset + PM_PWSTCTRL_OFFSET); 114 + } 115 + 116 + static u32 pmdomain_get_clock_autocontrol(int domain_offset) 117 + { 118 + return prcm_readl(domain_offset + CM_CLKSTCTRL_OFFSET); 119 + } 120 + 121 + static void pmdomain_set_clock_autocontrol(u32 state, int domain_offset) 122 + { 123 + prcm_writel(state, domain_offset + CM_CLKSTCTRL_OFFSET); 124 + } 125 + 126 + static u32 pmdomain_get_clock_autoidle1(int domain_offset) 127 + { 128 + return prcm_readl(domain_offset + CM_AUTOIDLE1_OFFSET); 129 + } 130 + 131 + /* Core domain only */ 132 + static u32 pmdomain_get_clock_autoidle2(int domain_offset) 133 + { 134 + return prcm_readl(domain_offset + CM_AUTOIDLE2_OFFSET); 135 + } 136 + 137 + /* Core domain only */ 138 + static u32 pmdomain_get_clock_autoidle3(int domain_offset) 139 + { 140 + return prcm_readl(domain_offset + CM_AUTOIDLE3_OFFSET); 141 + } 142 + 143 + /* Core domain only */ 144 + static u32 pmdomain_get_clock_autoidle4(int domain_offset) 145 + { 146 + return prcm_readl(domain_offset + CM_AUTOIDLE4_OFFSET); 147 + } 148 + 149 + static void pmdomain_set_clock_autoidle1(u32 state, int domain_offset) 150 + { 151 + prcm_writel(state, CM_AUTOIDLE1_OFFSET + domain_offset); 152 + } 153 + 154 + /* Core domain only */ 155 + static void pmdomain_set_clock_autoidle2(u32 state, int domain_offset) 156 + { 157 + prcm_writel(state, CM_AUTOIDLE2_OFFSET + domain_offset); 158 + } 159 + 160 + /* Core domain only */ 161 + static void pmdomain_set_clock_autoidle3(u32 state, int domain_offset) 162 + { 163 + prcm_writel(state, CM_AUTOIDLE3_OFFSET + domain_offset); 164 + } 165 + 166 + /* Core domain only */ 167 + static void pmdomain_set_clock_autoidle4(u32 state, int domain_offset) 168 + { 169 + prcm_writel(state, CM_AUTOIDLE4_OFFSET + domain_offset); 170 + } 171 + 172 + /* 173 + * Configures power management domains to idle clocks automatically. 174 + */ 175 + void pmdomain_set_autoidle(void) 176 + { 177 + u32 val; 178 + 179 + /* Set PLL auto stop for 54M, 96M & DPLL */ 180 + pmdomain_set_clock_autoidle1(AUTO_54M(AUTO_STOPPED) | 181 + AUTO_96M(AUTO_STOPPED) | 182 + AUTO_DPLL(AUTO_STOPPED), PM_PLL_OFFSET); 183 + 184 + /* External clock input control 185 + * REVISIT: Should this be in clock framework? 186 + */ 187 + PRCM_CLKSRC_CTRL |= (0x3 << 3); 188 + 189 + /* Configure number of 32KHz clock cycles for sys_clk */ 190 + PRCM_CLKSSETUP = 0x00ff; 191 + 192 + /* Configure automatic voltage transition */ 193 + PRCM_VOLTSETUP = 0; 194 + val = PRCM_VOLTCTRL; 195 + val &= ~(SETOFF_LEVEL(0x3) | VOLT_LEVEL(0x3)); 196 + val |= SETOFF_LEVEL(1) | VOLT_LEVEL(1) | AUTO_EXTVOLT; 197 + PRCM_VOLTCTRL = val; 198 + 199 + /* Disable emulation tools functional clock */ 200 + PRCM_CLKEMUL_CTRL = 0x0; 201 + 202 + /* Set core memory retention state */ 203 + val = pmdomain_get_powerstate(PM_CORE_OFFSET); 204 + if (cpu_is_omap2420()) { 205 + val &= ~(0x7 << 3); 206 + val |= (MEM3RETSTATE | MEM2RETSTATE | MEM1RETSTATE); 207 + } else { 208 + val &= ~(0xf << 3); 209 + val |= (MEM4RETSTATE | MEM3RETSTATE | MEM2RETSTATE | 210 + MEM1RETSTATE); 211 + } 212 + pmdomain_set_powerstate(val, PM_CORE_OFFSET); 213 + 214 + /* OCP interface smart idle. REVISIT: Enable autoidle bit0 ? */ 215 + val = SMS_SYSCONFIG; 216 + val &= ~(0x3 << 3); 217 + val |= (0x2 << 3) | (1 << 0); 218 + SMS_SYSCONFIG |= val; 219 + 220 + val = SDRC_SYSCONFIG; 221 + val &= ~(0x3 << 3); 222 + val |= (0x2 << 3); 223 + SDRC_SYSCONFIG = val; 224 + 225 + /* Configure L3 interface for smart idle. 226 + * REVISIT: Enable autoidle bit0 ? 227 + */ 228 + val = GPMC_SYSCONFIG; 229 + val &= ~(0x3 << 3); 230 + val |= (0x2 << 3) | (1 << 0); 231 + GPMC_SYSCONFIG = val; 232 + 233 + pmdomain_set_powerstate(LOGICRETSTATE | POWERSTATE_RETENTION, 234 + PM_MPU_OFFSET); 235 + pmdomain_set_powerstate(POWERSTATE_RETENTION, PM_CORE_OFFSET); 236 + if (!cpu_is_omap2420()) 237 + pmdomain_set_powerstate(POWERSTATE_RETENTION, PM_MDM_OFFSET); 238 + 239 + /* Assume suspend function has saved the state for DSP and GFX */ 240 + pmdomain_set_powerstate(FORCESTATE | POWERSTATE_OFF, PM_DSP_OFFSET); 241 + pmdomain_set_powerstate(FORCESTATE | POWERSTATE_OFF, PM_GFX_OFFSET); 242 + 243 + #if 0 244 + /* REVISIT: Internal USB needs special handling */ 245 + force_standby_usb(); 246 + if (cpu_is_omap2430()) 247 + force_hsmmc(); 248 + sdram_self_refresh_on_idle_req(1); 249 + #endif 250 + 251 + /* Enable clock auto control for all domains. 252 + * Note that CORE domain includes also DSS, L4 & L3. 253 + */ 254 + pmdomain_set_clock_autocontrol(AUTOSTAT_MPU, PM_MPU_OFFSET); 255 + pmdomain_set_clock_autocontrol(AUTOSTAT_GFX, PM_GFX_OFFSET); 256 + pmdomain_set_clock_autocontrol(AUTOSTAT_DSS | AUTOSTAT_L4 | AUTOSTAT_L3, 257 + PM_CORE_OFFSET); 258 + if (cpu_is_omap2420()) 259 + pmdomain_set_clock_autocontrol(AUTOSTAT_IVA | AUTOSTAT_DSP, 260 + PM_DSP_OFFSET); 261 + else { 262 + pmdomain_set_clock_autocontrol(AUTOSTAT_DSP, PM_DSP_OFFSET); 263 + pmdomain_set_clock_autocontrol(AUTOSTAT_MDM, PM_MDM_OFFSET); 264 + } 265 + 266 + /* Enable clock autoidle for all domains */ 267 + pmdomain_set_clock_autoidle1(0x2, PM_DSP_OFFSET); 268 + if (cpu_is_omap2420()) { 269 + pmdomain_set_clock_autoidle1(0xfffffff9, PM_CORE_OFFSET); 270 + pmdomain_set_clock_autoidle2(0x7, PM_CORE_OFFSET); 271 + pmdomain_set_clock_autoidle1(0x3f, PM_WKUP_OFFSET); 272 + } else { 273 + pmdomain_set_clock_autoidle1(0xeafffff1, PM_CORE_OFFSET); 274 + pmdomain_set_clock_autoidle2(0xfff, PM_CORE_OFFSET); 275 + pmdomain_set_clock_autoidle1(0x7f, PM_WKUP_OFFSET); 276 + pmdomain_set_clock_autoidle1(0x3, PM_MDM_OFFSET); 277 + } 278 + pmdomain_set_clock_autoidle3(0x7, PM_CORE_OFFSET); 279 + pmdomain_set_clock_autoidle4(0x1f, PM_CORE_OFFSET); 280 + } 281 + 282 + /* 283 + * Initializes power domains by removing wake-up dependencies and powering 284 + * down DSP and GFX. Gets called from PM init. Note that DSP and IVA code 285 + * must re-enable DSP and GFX when used. 286 + */ 287 + void __init pmdomain_init(void) 288 + { 289 + /* Remove all domain wakeup dependencies */ 290 + pmdomain_set_wakeup_dependencies(EN_WKUP | EN_CORE, PM_MPU_OFFSET); 291 + pmdomain_set_wakeup_dependencies(0, PM_DSP_OFFSET); 292 + pmdomain_set_wakeup_dependencies(0, PM_GFX_OFFSET); 293 + pmdomain_set_wakeup_dependencies(EN_WKUP | EN_MPU, PM_CORE_OFFSET); 294 + if (cpu_is_omap2430()) 295 + pmdomain_set_wakeup_dependencies(0, PM_MDM_OFFSET); 296 + 297 + /* Power down DSP and GFX */ 298 + pmdomain_set_powerstate(POWERSTATE_OFF | FORCESTATE, PM_DSP_OFFSET); 299 + pmdomain_set_powerstate(POWERSTATE_OFF | FORCESTATE, PM_GFX_OFFSET); 300 + }
+265 -6
arch/arm/mach-omap2/pm.c
··· 23 23 #include <linux/interrupt.h> 24 24 #include <linux/sysfs.h> 25 25 #include <linux/module.h> 26 + #include <linux/delay.h> 26 27 27 28 #include <asm/io.h> 28 29 #include <asm/irq.h> ··· 37 36 #include <asm/arch/sram.h> 38 37 #include <asm/arch/pm.h> 39 38 39 + #include "prcm-regs.h" 40 + 40 41 static struct clk *vclk; 41 42 static void (*omap2_sram_idle)(void); 42 43 static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev); 43 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]; 44 50 45 51 void omap2_pm_idle(void) 46 52 { ··· 95 87 return error; 96 88 } 97 89 90 + #define INT0_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_GPIO_BANK1) | \ 91 + OMAP_IRQ_BIT(INT_24XX_GPIO_BANK2) | \ 92 + OMAP_IRQ_BIT(INT_24XX_GPIO_BANK3)) 93 + 94 + #define INT1_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_GPIO_BANK4)) 95 + 96 + #define INT2_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_UART1_IRQ) | \ 97 + OMAP_IRQ_BIT(INT_24XX_UART2_IRQ) | \ 98 + OMAP_IRQ_BIT(INT_24XX_UART3_IRQ)) 99 + 100 + #define preg(reg) printk("%s\t(0x%p):\t0x%08x\n", #reg, &reg, reg); 101 + 102 + static void omap2_pm_debug(char * desc) 103 + { 104 + printk("%s:\n", desc); 105 + 106 + preg(CM_CLKSTCTRL_MPU); 107 + preg(CM_CLKSTCTRL_CORE); 108 + preg(CM_CLKSTCTRL_GFX); 109 + preg(CM_CLKSTCTRL_DSP); 110 + preg(CM_CLKSTCTRL_MDM); 111 + 112 + preg(PM_PWSTCTRL_MPU); 113 + preg(PM_PWSTCTRL_CORE); 114 + preg(PM_PWSTCTRL_GFX); 115 + preg(PM_PWSTCTRL_DSP); 116 + preg(PM_PWSTCTRL_MDM); 117 + 118 + preg(PM_PWSTST_MPU); 119 + preg(PM_PWSTST_CORE); 120 + preg(PM_PWSTST_GFX); 121 + preg(PM_PWSTST_DSP); 122 + preg(PM_PWSTST_MDM); 123 + 124 + preg(CM_AUTOIDLE1_CORE); 125 + preg(CM_AUTOIDLE2_CORE); 126 + preg(CM_AUTOIDLE3_CORE); 127 + preg(CM_AUTOIDLE4_CORE); 128 + preg(CM_AUTOIDLE_WKUP); 129 + preg(CM_AUTOIDLE_PLL); 130 + preg(CM_AUTOIDLE_DSP); 131 + preg(CM_AUTOIDLE_MDM); 132 + 133 + preg(CM_ICLKEN1_CORE); 134 + preg(CM_ICLKEN2_CORE); 135 + preg(CM_ICLKEN3_CORE); 136 + preg(CM_ICLKEN4_CORE); 137 + preg(CM_ICLKEN_GFX); 138 + preg(CM_ICLKEN_WKUP); 139 + preg(CM_ICLKEN_DSP); 140 + preg(CM_ICLKEN_MDM); 141 + 142 + preg(CM_IDLEST1_CORE); 143 + preg(CM_IDLEST2_CORE); 144 + preg(CM_IDLEST3_CORE); 145 + preg(CM_IDLEST4_CORE); 146 + preg(CM_IDLEST_GFX); 147 + preg(CM_IDLEST_WKUP); 148 + preg(CM_IDLEST_CKGEN); 149 + preg(CM_IDLEST_DSP); 150 + preg(CM_IDLEST_MDM); 151 + 152 + preg(RM_RSTST_MPU); 153 + preg(RM_RSTST_GFX); 154 + preg(RM_RSTST_WKUP); 155 + preg(RM_RSTST_DSP); 156 + preg(RM_RSTST_MDM); 157 + 158 + preg(PM_WKDEP_MPU); 159 + preg(PM_WKDEP_CORE); 160 + preg(PM_WKDEP_GFX); 161 + preg(PM_WKDEP_DSP); 162 + preg(PM_WKDEP_MDM); 163 + 164 + preg(CM_FCLKEN_WKUP); 165 + preg(CM_ICLKEN_WKUP); 166 + preg(CM_IDLEST_WKUP); 167 + preg(CM_AUTOIDLE_WKUP); 168 + preg(CM_CLKSEL_WKUP); 169 + 170 + preg(PM_WKEN_WKUP); 171 + preg(PM_WKST_WKUP); 172 + } 173 + 174 + static inline void omap2_pm_save_registers(void) 175 + { 176 + /* Save interrupt registers */ 177 + OMAP24XX_SAVE(INTC_MIR0); 178 + OMAP24XX_SAVE(INTC_MIR1); 179 + OMAP24XX_SAVE(INTC_MIR2); 180 + 181 + /* Save power control registers */ 182 + OMAP24XX_SAVE(CM_CLKSTCTRL_MPU); 183 + OMAP24XX_SAVE(CM_CLKSTCTRL_CORE); 184 + OMAP24XX_SAVE(CM_CLKSTCTRL_GFX); 185 + OMAP24XX_SAVE(CM_CLKSTCTRL_DSP); 186 + OMAP24XX_SAVE(CM_CLKSTCTRL_MDM); 187 + 188 + /* Save power state registers */ 189 + OMAP24XX_SAVE(PM_PWSTCTRL_MPU); 190 + OMAP24XX_SAVE(PM_PWSTCTRL_CORE); 191 + OMAP24XX_SAVE(PM_PWSTCTRL_GFX); 192 + OMAP24XX_SAVE(PM_PWSTCTRL_DSP); 193 + OMAP24XX_SAVE(PM_PWSTCTRL_MDM); 194 + 195 + /* Save autoidle registers */ 196 + OMAP24XX_SAVE(CM_AUTOIDLE1_CORE); 197 + OMAP24XX_SAVE(CM_AUTOIDLE2_CORE); 198 + OMAP24XX_SAVE(CM_AUTOIDLE3_CORE); 199 + OMAP24XX_SAVE(CM_AUTOIDLE4_CORE); 200 + OMAP24XX_SAVE(CM_AUTOIDLE_WKUP); 201 + OMAP24XX_SAVE(CM_AUTOIDLE_PLL); 202 + OMAP24XX_SAVE(CM_AUTOIDLE_DSP); 203 + OMAP24XX_SAVE(CM_AUTOIDLE_MDM); 204 + 205 + /* Save idle state registers */ 206 + OMAP24XX_SAVE(CM_IDLEST1_CORE); 207 + OMAP24XX_SAVE(CM_IDLEST2_CORE); 208 + OMAP24XX_SAVE(CM_IDLEST3_CORE); 209 + OMAP24XX_SAVE(CM_IDLEST4_CORE); 210 + OMAP24XX_SAVE(CM_IDLEST_GFX); 211 + OMAP24XX_SAVE(CM_IDLEST_WKUP); 212 + OMAP24XX_SAVE(CM_IDLEST_CKGEN); 213 + OMAP24XX_SAVE(CM_IDLEST_DSP); 214 + OMAP24XX_SAVE(CM_IDLEST_MDM); 215 + 216 + /* Save clock registers */ 217 + OMAP24XX_SAVE(CM_FCLKEN1_CORE); 218 + OMAP24XX_SAVE(CM_FCLKEN2_CORE); 219 + OMAP24XX_SAVE(CM_ICLKEN1_CORE); 220 + OMAP24XX_SAVE(CM_ICLKEN2_CORE); 221 + OMAP24XX_SAVE(CM_ICLKEN3_CORE); 222 + OMAP24XX_SAVE(CM_ICLKEN4_CORE); 223 + } 224 + 225 + static inline void omap2_pm_restore_registers(void) 226 + { 227 + /* Restore clock state registers */ 228 + OMAP24XX_RESTORE(CM_CLKSTCTRL_MPU); 229 + OMAP24XX_RESTORE(CM_CLKSTCTRL_CORE); 230 + OMAP24XX_RESTORE(CM_CLKSTCTRL_GFX); 231 + OMAP24XX_RESTORE(CM_CLKSTCTRL_DSP); 232 + OMAP24XX_RESTORE(CM_CLKSTCTRL_MDM); 233 + 234 + /* Restore power state registers */ 235 + OMAP24XX_RESTORE(PM_PWSTCTRL_MPU); 236 + OMAP24XX_RESTORE(PM_PWSTCTRL_CORE); 237 + OMAP24XX_RESTORE(PM_PWSTCTRL_GFX); 238 + OMAP24XX_RESTORE(PM_PWSTCTRL_DSP); 239 + OMAP24XX_RESTORE(PM_PWSTCTRL_MDM); 240 + 241 + /* Restore idle state registers */ 242 + OMAP24XX_RESTORE(CM_IDLEST1_CORE); 243 + OMAP24XX_RESTORE(CM_IDLEST2_CORE); 244 + OMAP24XX_RESTORE(CM_IDLEST3_CORE); 245 + OMAP24XX_RESTORE(CM_IDLEST4_CORE); 246 + OMAP24XX_RESTORE(CM_IDLEST_GFX); 247 + OMAP24XX_RESTORE(CM_IDLEST_WKUP); 248 + OMAP24XX_RESTORE(CM_IDLEST_CKGEN); 249 + OMAP24XX_RESTORE(CM_IDLEST_DSP); 250 + OMAP24XX_RESTORE(CM_IDLEST_MDM); 251 + 252 + /* Restore autoidle registers */ 253 + OMAP24XX_RESTORE(CM_AUTOIDLE1_CORE); 254 + OMAP24XX_RESTORE(CM_AUTOIDLE2_CORE); 255 + OMAP24XX_RESTORE(CM_AUTOIDLE3_CORE); 256 + OMAP24XX_RESTORE(CM_AUTOIDLE4_CORE); 257 + OMAP24XX_RESTORE(CM_AUTOIDLE_WKUP); 258 + OMAP24XX_RESTORE(CM_AUTOIDLE_PLL); 259 + OMAP24XX_RESTORE(CM_AUTOIDLE_DSP); 260 + OMAP24XX_RESTORE(CM_AUTOIDLE_MDM); 261 + 262 + /* Restore clock registers */ 263 + OMAP24XX_RESTORE(CM_FCLKEN1_CORE); 264 + OMAP24XX_RESTORE(CM_FCLKEN2_CORE); 265 + OMAP24XX_RESTORE(CM_ICLKEN1_CORE); 266 + OMAP24XX_RESTORE(CM_ICLKEN2_CORE); 267 + OMAP24XX_RESTORE(CM_ICLKEN3_CORE); 268 + OMAP24XX_RESTORE(CM_ICLKEN4_CORE); 269 + 270 + /* REVISIT: Clear interrupts here */ 271 + 272 + /* Restore interrupt registers */ 273 + OMAP24XX_RESTORE(INTC_MIR0); 274 + OMAP24XX_RESTORE(INTC_MIR1); 275 + OMAP24XX_RESTORE(INTC_MIR2); 276 + } 277 + 278 + static int omap2_pm_suspend(void) 279 + { 280 + int processor_type = 0; 281 + 282 + /* REVISIT: 0x21 or 0x26? */ 283 + if (cpu_is_omap2420()) 284 + processor_type = 0x21; 285 + 286 + if (!processor_type) 287 + return -ENOTSUPP; 288 + 289 + local_irq_disable(); 290 + local_fiq_disable(); 291 + 292 + omap2_pm_save_registers(); 293 + 294 + /* Disable interrupts except for the wake events */ 295 + INTC_MIR_SET0 = 0xffffffff & ~INT0_WAKE_MASK; 296 + INTC_MIR_SET1 = 0xffffffff & ~INT1_WAKE_MASK; 297 + INTC_MIR_SET2 = 0xffffffff & ~INT2_WAKE_MASK; 298 + 299 + pmdomain_set_autoidle(); 300 + 301 + /* Clear old wake-up events */ 302 + PM_WKST1_CORE = 0; 303 + PM_WKST2_CORE = 0; 304 + PM_WKST_WKUP = 0; 305 + 306 + /* Enable wake-up events */ 307 + PM_WKEN1_CORE = (1 << 22) | (1 << 21); /* UART1 & 2 */ 308 + PM_WKEN2_CORE = (1 << 2); /* UART3 */ 309 + PM_WKEN_WKUP = (1 << 2) | (1 << 0); /* GPIO & GPT1 */ 310 + 311 + /* Disable clocks except for CM_ICLKEN2_CORE. It gets disabled 312 + * in the SRAM suspend code */ 313 + CM_FCLKEN1_CORE = 0; 314 + CM_FCLKEN2_CORE = 0; 315 + CM_ICLKEN1_CORE = 0; 316 + CM_ICLKEN3_CORE = 0; 317 + CM_ICLKEN4_CORE = 0; 318 + 319 + omap2_pm_debug("Status before suspend"); 320 + 321 + /* Must wait for serial buffers to clear */ 322 + mdelay(200); 323 + 324 + /* Jump to SRAM suspend code 325 + * REVISIT: When is this SDRC_DLLB_CTRL? 326 + */ 327 + omap2_sram_suspend(SDRC_DLLA_CTRL, processor_type); 328 + 329 + /* Back from sleep */ 330 + omap2_pm_restore_registers(); 331 + 332 + local_fiq_enable(); 333 + local_irq_enable(); 334 + 335 + return 0; 336 + } 337 + 98 338 static int omap2_pm_enter(suspend_state_t state) 99 339 { 340 + int ret = 0; 341 + 100 342 switch (state) 101 343 { 102 344 case PM_SUSPEND_STANDBY: 103 345 case PM_SUSPEND_MEM: 104 - /* FIXME: Add suspend */ 346 + ret = omap2_pm_suspend(); 105 347 break; 106 - 107 348 case PM_SUSPEND_DISK: 108 - return -ENOTSUPP; 109 - 349 + ret = -ENOTSUPP; 350 + break; 110 351 default: 111 - return -EINVAL; 352 + ret = -EINVAL; 112 353 } 113 354 114 - return 0; 355 + return ret; 115 356 } 116 357 117 358 static int omap2_pm_finish(suspend_state_t state) ··· 399 142 400 143 pm_set_ops(&omap_pm_ops); 401 144 pm_idle = omap2_pm_idle; 145 + 146 + pmdomain_init(); 402 147 403 148 return 0; 404 149 }
+2
include/asm-arm/arch-omap/irqs.h
··· 258 258 #define INT_24XX_MCBSP1_IRQ_RX 60 259 259 #define INT_24XX_MCBSP2_IRQ_TX 62 260 260 #define INT_24XX_MCBSP2_IRQ_RX 63 261 + #define INT_24XX_UART1_IRQ 72 262 + #define INT_24XX_UART2_IRQ 73 261 263 #define INT_24XX_UART3_IRQ 74 262 264 263 265 /* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730) and
+33
include/asm-arm/arch-omap/pm.h
··· 299 299 OMAP24XX_SLEEP_SAVE_INTC_MIR0, 300 300 OMAP24XX_SLEEP_SAVE_INTC_MIR1, 301 301 OMAP24XX_SLEEP_SAVE_INTC_MIR2, 302 + 303 + OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_MPU, 304 + OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_CORE, 305 + OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_GFX, 306 + OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_DSP, 307 + OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_MDM, 308 + 309 + OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_MPU, 310 + OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_CORE, 311 + OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_GFX, 312 + OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_DSP, 313 + OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_MDM, 314 + 315 + OMAP24XX_SLEEP_SAVE_CM_IDLEST1_CORE, 316 + OMAP24XX_SLEEP_SAVE_CM_IDLEST2_CORE, 317 + OMAP24XX_SLEEP_SAVE_CM_IDLEST3_CORE, 318 + OMAP24XX_SLEEP_SAVE_CM_IDLEST4_CORE, 319 + OMAP24XX_SLEEP_SAVE_CM_IDLEST_GFX, 320 + OMAP24XX_SLEEP_SAVE_CM_IDLEST_WKUP, 321 + OMAP24XX_SLEEP_SAVE_CM_IDLEST_CKGEN, 322 + OMAP24XX_SLEEP_SAVE_CM_IDLEST_DSP, 323 + OMAP24XX_SLEEP_SAVE_CM_IDLEST_MDM, 324 + 325 + OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE1_CORE, 326 + OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE2_CORE, 327 + OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE3_CORE, 328 + OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE4_CORE, 329 + OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_WKUP, 330 + OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_PLL, 331 + OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_DSP, 332 + OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_MDM, 333 + 302 334 OMAP24XX_SLEEP_SAVE_CM_FCLKEN1_CORE, 303 335 OMAP24XX_SLEEP_SAVE_CM_FCLKEN2_CORE, 304 336 OMAP24XX_SLEEP_SAVE_CM_ICLKEN1_CORE, 305 337 OMAP24XX_SLEEP_SAVE_CM_ICLKEN2_CORE, 338 + OMAP24XX_SLEEP_SAVE_CM_ICLKEN3_CORE, 306 339 OMAP24XX_SLEEP_SAVE_CM_ICLKEN4_CORE, 307 340 OMAP24XX_SLEEP_SAVE_GPIO1_IRQENABLE1, 308 341 OMAP24XX_SLEEP_SAVE_GPIO2_IRQENABLE1,