diff options
-rw-r--r-- | arch/arm/mach-omap2/common.h | 6 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap-mpuss-lowpower.c | 65 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm44xx.c | 4 |
3 files changed, 72 insertions, 3 deletions
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h index 3312174d64ba..0911e843f079 100644 --- a/arch/arm/mach-omap2/common.h +++ b/arch/arm/mach-omap2/common.h | |||
@@ -190,6 +190,7 @@ extern int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state); | |||
190 | extern int omap4_finish_suspend(unsigned long cpu_state); | 190 | extern int omap4_finish_suspend(unsigned long cpu_state); |
191 | extern void omap4_cpu_resume(void); | 191 | extern void omap4_cpu_resume(void); |
192 | extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state); | 192 | extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state); |
193 | extern u32 omap4_mpuss_read_prev_context_state(void); | ||
193 | #else | 194 | #else |
194 | static inline int omap4_enter_lowpower(unsigned int cpu, | 195 | static inline int omap4_enter_lowpower(unsigned int cpu, |
195 | unsigned int power_state) | 196 | unsigned int power_state) |
@@ -216,6 +217,11 @@ static inline int omap4_finish_suspend(unsigned long cpu_state) | |||
216 | 217 | ||
217 | static inline void omap4_cpu_resume(void) | 218 | static inline void omap4_cpu_resume(void) |
218 | {} | 219 | {} |
220 | |||
221 | static inline u32 omap4_mpuss_read_prev_context_state(void) | ||
222 | { | ||
223 | return 0; | ||
224 | } | ||
219 | #endif | 225 | #endif |
220 | #endif /* __ASSEMBLER__ */ | 226 | #endif /* __ASSEMBLER__ */ |
221 | #endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */ | 227 | #endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */ |
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index 907a048fe5e9..549aff1bfecb 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c | |||
@@ -24,8 +24,8 @@ | |||
24 | * ON ON ON | 24 | * ON ON ON |
25 | * ON(Inactive) OFF ON(Inactive) | 25 | * ON(Inactive) OFF ON(Inactive) |
26 | * OFF OFF CSWR | 26 | * OFF OFF CSWR |
27 | * OFF OFF OSWR (*TBD) | 27 | * OFF OFF OSWR |
28 | * OFF OFF OFF* (*TBD) | 28 | * OFF OFF OFF(Device OFF *TBD) |
29 | * ---------------------------------------------- | 29 | * ---------------------------------------------- |
30 | * | 30 | * |
31 | * Note: CPU0 is the master core and it is the last CPU to go down | 31 | * Note: CPU0 is the master core and it is the last CPU to go down |
@@ -56,7 +56,11 @@ | |||
56 | #include "common.h" | 56 | #include "common.h" |
57 | #include "omap4-sar-layout.h" | 57 | #include "omap4-sar-layout.h" |
58 | #include "pm.h" | 58 | #include "pm.h" |
59 | #include "powerdomain.h" | 59 | #include "prcm_mpu44xx.h" |
60 | #include "prminst44xx.h" | ||
61 | #include "prcm44xx.h" | ||
62 | #include "prm44xx.h" | ||
63 | #include "prm-regbits-44xx.h" | ||
60 | 64 | ||
61 | #ifdef CONFIG_SMP | 65 | #ifdef CONFIG_SMP |
62 | 66 | ||
@@ -138,6 +142,48 @@ static void scu_pwrst_prepare(unsigned int cpu_id, unsigned int cpu_state) | |||
138 | __raw_writel(scu_pwr_st, pm_info->scu_sar_addr); | 142 | __raw_writel(scu_pwr_st, pm_info->scu_sar_addr); |
139 | } | 143 | } |
140 | 144 | ||
145 | /* Helper functions for MPUSS OSWR */ | ||
146 | static inline void mpuss_clear_prev_logic_pwrst(void) | ||
147 | { | ||
148 | u32 reg; | ||
149 | |||
150 | reg = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, | ||
151 | OMAP4430_PRM_MPU_INST, OMAP4_RM_MPU_MPU_CONTEXT_OFFSET); | ||
152 | omap4_prminst_write_inst_reg(reg, OMAP4430_PRM_PARTITION, | ||
153 | OMAP4430_PRM_MPU_INST, OMAP4_RM_MPU_MPU_CONTEXT_OFFSET); | ||
154 | } | ||
155 | |||
156 | static inline void cpu_clear_prev_logic_pwrst(unsigned int cpu_id) | ||
157 | { | ||
158 | u32 reg; | ||
159 | |||
160 | if (cpu_id) { | ||
161 | reg = omap4_prcm_mpu_read_inst_reg(OMAP4430_PRCM_MPU_CPU1_INST, | ||
162 | OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET); | ||
163 | omap4_prcm_mpu_write_inst_reg(reg, OMAP4430_PRCM_MPU_CPU1_INST, | ||
164 | OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET); | ||
165 | } else { | ||
166 | reg = omap4_prcm_mpu_read_inst_reg(OMAP4430_PRCM_MPU_CPU0_INST, | ||
167 | OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET); | ||
168 | omap4_prcm_mpu_write_inst_reg(reg, OMAP4430_PRCM_MPU_CPU0_INST, | ||
169 | OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET); | ||
170 | } | ||
171 | } | ||
172 | |||
173 | /** | ||
174 | * omap4_mpuss_read_prev_context_state: | ||
175 | * Function returns the MPUSS previous context state | ||
176 | */ | ||
177 | u32 omap4_mpuss_read_prev_context_state(void) | ||
178 | { | ||
179 | u32 reg; | ||
180 | |||
181 | reg = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, | ||
182 | OMAP4430_PRM_MPU_INST, OMAP4_RM_MPU_MPU_CONTEXT_OFFSET); | ||
183 | reg &= OMAP4430_LOSTCONTEXT_DFF_MASK; | ||
184 | return reg; | ||
185 | } | ||
186 | |||
141 | /* | 187 | /* |
142 | * Store the CPU cluster state for L2X0 low power operations. | 188 | * Store the CPU cluster state for L2X0 low power operations. |
143 | */ | 189 | */ |
@@ -210,8 +256,18 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) | |||
210 | return -ENXIO; | 256 | return -ENXIO; |
211 | } | 257 | } |
212 | 258 | ||
259 | /* | ||
260 | * Check MPUSS next state and save interrupt controller if needed. | ||
261 | * In MPUSS OSWR or device OFF, interrupt controller contest is lost. | ||
262 | */ | ||
263 | mpuss_clear_prev_logic_pwrst(); | ||
213 | pwrdm_clear_all_prev_pwrst(mpuss_pd); | 264 | pwrdm_clear_all_prev_pwrst(mpuss_pd); |
265 | if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) && | ||
266 | (pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF)) | ||
267 | save_state = 2; | ||
268 | |||
214 | clear_cpu_prev_pwrst(cpu); | 269 | clear_cpu_prev_pwrst(cpu); |
270 | cpu_clear_prev_logic_pwrst(cpu); | ||
215 | set_cpu_next_pwrst(cpu, power_state); | 271 | set_cpu_next_pwrst(cpu, power_state); |
216 | set_cpu_wakeup_addr(cpu, virt_to_phys(omap4_cpu_resume)); | 272 | set_cpu_wakeup_addr(cpu, virt_to_phys(omap4_cpu_resume)); |
217 | scu_pwrst_prepare(cpu, power_state); | 273 | scu_pwrst_prepare(cpu, power_state); |
@@ -294,6 +350,7 @@ int __init omap4_mpuss_init(void) | |||
294 | 350 | ||
295 | /* Clear CPU previous power domain state */ | 351 | /* Clear CPU previous power domain state */ |
296 | pwrdm_clear_all_prev_pwrst(pm_info->pwrdm); | 352 | pwrdm_clear_all_prev_pwrst(pm_info->pwrdm); |
353 | cpu_clear_prev_logic_pwrst(0); | ||
297 | 354 | ||
298 | /* Initialise CPU0 power domain state to ON */ | 355 | /* Initialise CPU0 power domain state to ON */ |
299 | pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON); | 356 | pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON); |
@@ -310,6 +367,7 @@ int __init omap4_mpuss_init(void) | |||
310 | 367 | ||
311 | /* Clear CPU previous power domain state */ | 368 | /* Clear CPU previous power domain state */ |
312 | pwrdm_clear_all_prev_pwrst(pm_info->pwrdm); | 369 | pwrdm_clear_all_prev_pwrst(pm_info->pwrdm); |
370 | cpu_clear_prev_logic_pwrst(1); | ||
313 | 371 | ||
314 | /* Initialise CPU1 power domain state to ON */ | 372 | /* Initialise CPU1 power domain state to ON */ |
315 | pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON); | 373 | pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON); |
@@ -320,6 +378,7 @@ int __init omap4_mpuss_init(void) | |||
320 | return -ENODEV; | 378 | return -ENODEV; |
321 | } | 379 | } |
322 | pwrdm_clear_all_prev_pwrst(mpuss_pd); | 380 | pwrdm_clear_all_prev_pwrst(mpuss_pd); |
381 | mpuss_clear_prev_logic_pwrst(); | ||
323 | 382 | ||
324 | /* Save device type on scratchpad for low level code to use */ | 383 | /* Save device type on scratchpad for low level code to use */ |
325 | if (omap_type() != OMAP2_DEVICE_TYPE_GP) | 384 | if (omap_type() != OMAP2_DEVICE_TYPE_GP) |
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c index 6dc9bbe0a4a8..92daae07d634 100644 --- a/arch/arm/mach-omap2/pm44xx.c +++ b/arch/arm/mach-omap2/pm44xx.c | |||
@@ -27,6 +27,7 @@ struct power_state { | |||
27 | u32 next_state; | 27 | u32 next_state; |
28 | #ifdef CONFIG_SUSPEND | 28 | #ifdef CONFIG_SUSPEND |
29 | u32 saved_state; | 29 | u32 saved_state; |
30 | u32 saved_logic_state; | ||
30 | #endif | 31 | #endif |
31 | struct list_head node; | 32 | struct list_head node; |
32 | }; | 33 | }; |
@@ -43,11 +44,13 @@ static int omap4_pm_suspend(void) | |||
43 | /* Save current powerdomain state */ | 44 | /* Save current powerdomain state */ |
44 | list_for_each_entry(pwrst, &pwrst_list, node) { | 45 | list_for_each_entry(pwrst, &pwrst_list, node) { |
45 | pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm); | 46 | pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm); |
47 | pwrst->saved_logic_state = pwrdm_read_logic_retst(pwrst->pwrdm); | ||
46 | } | 48 | } |
47 | 49 | ||
48 | /* Set targeted power domain states by suspend */ | 50 | /* Set targeted power domain states by suspend */ |
49 | list_for_each_entry(pwrst, &pwrst_list, node) { | 51 | list_for_each_entry(pwrst, &pwrst_list, node) { |
50 | omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state); | 52 | omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state); |
53 | pwrdm_set_logic_retst(pwrst->pwrdm, PWRDM_POWER_OFF); | ||
51 | } | 54 | } |
52 | 55 | ||
53 | /* | 56 | /* |
@@ -71,6 +74,7 @@ static int omap4_pm_suspend(void) | |||
71 | ret = -1; | 74 | ret = -1; |
72 | } | 75 | } |
73 | omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state); | 76 | omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state); |
77 | pwrdm_set_logic_retst(pwrst->pwrdm, pwrst->saved_logic_state); | ||
74 | } | 78 | } |
75 | if (ret) | 79 | if (ret) |
76 | pr_crit("Could not enter target state in pm_suspend\n"); | 80 | pr_crit("Could not enter target state in pm_suspend\n"); |