aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap2/common.h6
-rw-r--r--arch/arm/mach-omap2/omap-mpuss-lowpower.c65
-rw-r--r--arch/arm/mach-omap2/pm44xx.c4
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);
190extern int omap4_finish_suspend(unsigned long cpu_state); 190extern int omap4_finish_suspend(unsigned long cpu_state);
191extern void omap4_cpu_resume(void); 191extern void omap4_cpu_resume(void);
192extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state); 192extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state);
193extern u32 omap4_mpuss_read_prev_context_state(void);
193#else 194#else
194static inline int omap4_enter_lowpower(unsigned int cpu, 195static 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
217static inline void omap4_cpu_resume(void) 218static inline void omap4_cpu_resume(void)
218{} 219{}
220
221static 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 */
146static 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
156static 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 */
177u32 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");