diff options
author | Tony Lindgren <tony@atomide.com> | 2012-06-27 07:50:21 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2012-06-27 07:50:21 -0400 |
commit | 4556494b06801b56d2b09e4cce0885902b2429bf (patch) | |
tree | 92a79b38473b6ec1aa25b366a5caf1fa2e86a901 | |
parent | 9a17d88e0586bb7189655f8f99484a872a474626 (diff) | |
parent | 05011f711fc751456972d126bbb8081723629408 (diff) |
Merge branch 'for_3.6/pm/performance' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm into devel-pm
-rw-r--r-- | arch/arm/mach-omap2/cpuidle34xx.c | 71 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap-mpuss-lowpower.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm34xx.c | 21 | ||||
-rw-r--r-- | arch/arm/mach-omap2/powerdomain.c | 16 | ||||
-rw-r--r-- | arch/arm/mach-omap2/powerdomain.h | 4 |
5 files changed, 57 insertions, 59 deletions
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 207bc1c7759f..e6ae3fe5cdc6 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c | |||
@@ -77,20 +77,6 @@ static struct omap3_idle_statedata omap3_idle_data[] = { | |||
77 | 77 | ||
78 | static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd; | 78 | static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd; |
79 | 79 | ||
80 | static int _cpuidle_allow_idle(struct powerdomain *pwrdm, | ||
81 | struct clockdomain *clkdm) | ||
82 | { | ||
83 | clkdm_allow_idle(clkdm); | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static int _cpuidle_deny_idle(struct powerdomain *pwrdm, | ||
88 | struct clockdomain *clkdm) | ||
89 | { | ||
90 | clkdm_deny_idle(clkdm); | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static int __omap3_enter_idle(struct cpuidle_device *dev, | 80 | static int __omap3_enter_idle(struct cpuidle_device *dev, |
95 | struct cpuidle_driver *drv, | 81 | struct cpuidle_driver *drv, |
96 | int index) | 82 | int index) |
@@ -108,8 +94,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev, | |||
108 | 94 | ||
109 | /* Deny idle for C1 */ | 95 | /* Deny idle for C1 */ |
110 | if (index == 0) { | 96 | if (index == 0) { |
111 | pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); | 97 | clkdm_deny_idle(mpu_pd->pwrdm_clkdms[0]); |
112 | pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); | 98 | clkdm_deny_idle(core_pd->pwrdm_clkdms[0]); |
113 | } | 99 | } |
114 | 100 | ||
115 | /* | 101 | /* |
@@ -131,8 +117,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev, | |||
131 | 117 | ||
132 | /* Re-allow idle for C1 */ | 118 | /* Re-allow idle for C1 */ |
133 | if (index == 0) { | 119 | if (index == 0) { |
134 | pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); | 120 | clkdm_allow_idle(mpu_pd->pwrdm_clkdms[0]); |
135 | pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); | 121 | clkdm_allow_idle(core_pd->pwrdm_clkdms[0]); |
136 | } | 122 | } |
137 | 123 | ||
138 | return_sleep_time: | 124 | return_sleep_time: |
@@ -178,7 +164,7 @@ static int next_valid_state(struct cpuidle_device *dev, | |||
178 | u32 mpu_deepest_state = PWRDM_POWER_RET; | 164 | u32 mpu_deepest_state = PWRDM_POWER_RET; |
179 | u32 core_deepest_state = PWRDM_POWER_RET; | 165 | u32 core_deepest_state = PWRDM_POWER_RET; |
180 | int idx; | 166 | int idx; |
181 | int next_index = -1; | 167 | int next_index = 0; /* C1 is the default value */ |
182 | 168 | ||
183 | if (enable_off_mode) { | 169 | if (enable_off_mode) { |
184 | mpu_deepest_state = PWRDM_POWER_OFF; | 170 | mpu_deepest_state = PWRDM_POWER_OFF; |
@@ -209,12 +195,6 @@ static int next_valid_state(struct cpuidle_device *dev, | |||
209 | } | 195 | } |
210 | } | 196 | } |
211 | 197 | ||
212 | /* | ||
213 | * C1 is always valid. | ||
214 | * So, no need to check for 'next_index == -1' outside | ||
215 | * this loop. | ||
216 | */ | ||
217 | |||
218 | return next_index; | 198 | return next_index; |
219 | } | 199 | } |
220 | 200 | ||
@@ -228,23 +208,22 @@ static int next_valid_state(struct cpuidle_device *dev, | |||
228 | * the device to the specified or a safer state. | 208 | * the device to the specified or a safer state. |
229 | */ | 209 | */ |
230 | static int omap3_enter_idle_bm(struct cpuidle_device *dev, | 210 | static int omap3_enter_idle_bm(struct cpuidle_device *dev, |
231 | struct cpuidle_driver *drv, | 211 | struct cpuidle_driver *drv, |
232 | int index) | 212 | int index) |
233 | { | 213 | { |
234 | int new_state_idx; | 214 | int new_state_idx; |
235 | u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state; | 215 | u32 core_next_state, per_next_state = 0, per_saved_state = 0; |
236 | struct omap3_idle_statedata *cx; | 216 | struct omap3_idle_statedata *cx; |
237 | int ret; | 217 | int ret; |
238 | 218 | ||
239 | /* | 219 | /* |
240 | * Prevent idle completely if CAM is active. | 220 | * Use only C1 if CAM is active. |
241 | * CAM does not have wakeup capability in OMAP3. | 221 | * CAM does not have wakeup capability in OMAP3. |
242 | */ | 222 | */ |
243 | cam_state = pwrdm_read_pwrst(cam_pd); | 223 | if (pwrdm_read_pwrst(cam_pd) == PWRDM_POWER_ON) |
244 | if (cam_state == PWRDM_POWER_ON) { | ||
245 | new_state_idx = drv->safe_state_index; | 224 | new_state_idx = drv->safe_state_index; |
246 | goto select_state; | 225 | else |
247 | } | 226 | new_state_idx = next_valid_state(dev, drv, index); |
248 | 227 | ||
249 | /* | 228 | /* |
250 | * FIXME: we currently manage device-specific idle states | 229 | * FIXME: we currently manage device-specific idle states |
@@ -254,24 +233,28 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, | |||
254 | * its own code. | 233 | * its own code. |
255 | */ | 234 | */ |
256 | 235 | ||
257 | /* | 236 | /* Program PER state */ |
258 | * Prevent PER off if CORE is not in retention or off as this | 237 | cx = &omap3_idle_data[new_state_idx]; |
259 | * would disable PER wakeups completely. | ||
260 | */ | ||
261 | cx = &omap3_idle_data[index]; | ||
262 | core_next_state = cx->core_state; | 238 | core_next_state = cx->core_state; |
263 | per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); | 239 | per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); |
264 | if ((per_next_state == PWRDM_POWER_OFF) && | 240 | if (new_state_idx == 0) { |
265 | (core_next_state > PWRDM_POWER_RET)) | 241 | /* In C1 do not allow PER state lower than CORE state */ |
266 | per_next_state = PWRDM_POWER_RET; | 242 | if (per_next_state < core_next_state) |
243 | per_next_state = core_next_state; | ||
244 | } else { | ||
245 | /* | ||
246 | * Prevent PER OFF if CORE is not in RETention or OFF as this | ||
247 | * would disable PER wakeups completely. | ||
248 | */ | ||
249 | if ((per_next_state == PWRDM_POWER_OFF) && | ||
250 | (core_next_state > PWRDM_POWER_RET)) | ||
251 | per_next_state = PWRDM_POWER_RET; | ||
252 | } | ||
267 | 253 | ||
268 | /* Are we changing PER target state? */ | 254 | /* Are we changing PER target state? */ |
269 | if (per_next_state != per_saved_state) | 255 | if (per_next_state != per_saved_state) |
270 | pwrdm_set_next_pwrst(per_pd, per_next_state); | 256 | pwrdm_set_next_pwrst(per_pd, per_next_state); |
271 | 257 | ||
272 | new_state_idx = next_valid_state(dev, drv, index); | ||
273 | |||
274 | select_state: | ||
275 | ret = omap3_enter_idle(dev, drv, new_state_idx); | 258 | ret = omap3_enter_idle(dev, drv, new_state_idx); |
276 | 259 | ||
277 | /* Restore original PER state if it was modified */ | 260 | /* Restore original PER state if it was modified */ |
@@ -288,7 +271,7 @@ struct cpuidle_driver omap3_idle_driver = { | |||
288 | .owner = THIS_MODULE, | 271 | .owner = THIS_MODULE, |
289 | .states = { | 272 | .states = { |
290 | { | 273 | { |
291 | .enter = omap3_enter_idle, | 274 | .enter = omap3_enter_idle_bm, |
292 | .exit_latency = 2 + 2, | 275 | .exit_latency = 2 + 2, |
293 | .target_residency = 5, | 276 | .target_residency = 5, |
294 | .flags = CPUIDLE_FLAG_TIME_VALID, | 277 | .flags = CPUIDLE_FLAG_TIME_VALID, |
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index 13670aa84e58..e35a86bf4e1d 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c | |||
@@ -255,7 +255,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) | |||
255 | return -ENXIO; | 255 | return -ENXIO; |
256 | } | 256 | } |
257 | 257 | ||
258 | pwrdm_pre_transition(); | 258 | pwrdm_pre_transition(NULL); |
259 | 259 | ||
260 | /* | 260 | /* |
261 | * Check MPUSS next state and save interrupt controller if needed. | 261 | * Check MPUSS next state and save interrupt controller if needed. |
@@ -287,7 +287,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) | |||
287 | wakeup_cpu = smp_processor_id(); | 287 | wakeup_cpu = smp_processor_id(); |
288 | set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON); | 288 | set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON); |
289 | 289 | ||
290 | pwrdm_post_transition(); | 290 | pwrdm_post_transition(NULL); |
291 | 291 | ||
292 | return 0; | 292 | return 0; |
293 | } | 293 | } |
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index e67d898433fb..e63fdd02c6f5 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c | |||
@@ -70,7 +70,6 @@ void (*omap3_do_wfi_sram)(void); | |||
70 | 70 | ||
71 | static struct powerdomain *mpu_pwrdm, *neon_pwrdm; | 71 | static struct powerdomain *mpu_pwrdm, *neon_pwrdm; |
72 | static struct powerdomain *core_pwrdm, *per_pwrdm; | 72 | static struct powerdomain *core_pwrdm, *per_pwrdm; |
73 | static struct powerdomain *cam_pwrdm; | ||
74 | 73 | ||
75 | static void omap3_core_save_context(void) | 74 | static void omap3_core_save_context(void) |
76 | { | 75 | { |
@@ -273,16 +272,21 @@ void omap_sram_idle(void) | |||
273 | per_next_state = pwrdm_read_next_pwrst(per_pwrdm); | 272 | per_next_state = pwrdm_read_next_pwrst(per_pwrdm); |
274 | core_next_state = pwrdm_read_next_pwrst(core_pwrdm); | 273 | core_next_state = pwrdm_read_next_pwrst(core_pwrdm); |
275 | 274 | ||
276 | pwrdm_pre_transition(); | 275 | if (mpu_next_state < PWRDM_POWER_ON) { |
276 | pwrdm_pre_transition(mpu_pwrdm); | ||
277 | pwrdm_pre_transition(neon_pwrdm); | ||
278 | } | ||
277 | 279 | ||
278 | /* PER */ | 280 | /* PER */ |
279 | if (per_next_state < PWRDM_POWER_ON) { | 281 | if (per_next_state < PWRDM_POWER_ON) { |
282 | pwrdm_pre_transition(per_pwrdm); | ||
280 | per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0; | 283 | per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0; |
281 | omap2_gpio_prepare_for_idle(per_going_off); | 284 | omap2_gpio_prepare_for_idle(per_going_off); |
282 | } | 285 | } |
283 | 286 | ||
284 | /* CORE */ | 287 | /* CORE */ |
285 | if (core_next_state < PWRDM_POWER_ON) { | 288 | if (core_next_state < PWRDM_POWER_ON) { |
289 | pwrdm_pre_transition(core_pwrdm); | ||
286 | if (core_next_state == PWRDM_POWER_OFF) { | 290 | if (core_next_state == PWRDM_POWER_OFF) { |
287 | omap3_core_save_context(); | 291 | omap3_core_save_context(); |
288 | omap3_cm_save_context(); | 292 | omap3_cm_save_context(); |
@@ -335,16 +339,20 @@ void omap_sram_idle(void) | |||
335 | omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK, | 339 | omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK, |
336 | OMAP3430_GR_MOD, | 340 | OMAP3430_GR_MOD, |
337 | OMAP3_PRM_VOLTCTRL_OFFSET); | 341 | OMAP3_PRM_VOLTCTRL_OFFSET); |
342 | pwrdm_post_transition(core_pwrdm); | ||
338 | } | 343 | } |
339 | omap3_intc_resume_idle(); | 344 | omap3_intc_resume_idle(); |
340 | 345 | ||
341 | pwrdm_post_transition(); | ||
342 | |||
343 | /* PER */ | 346 | /* PER */ |
344 | if (per_next_state < PWRDM_POWER_ON) | 347 | if (per_next_state < PWRDM_POWER_ON) { |
345 | omap2_gpio_resume_after_idle(); | 348 | omap2_gpio_resume_after_idle(); |
349 | pwrdm_post_transition(per_pwrdm); | ||
350 | } | ||
346 | 351 | ||
347 | clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]); | 352 | if (mpu_next_state < PWRDM_POWER_ON) { |
353 | pwrdm_post_transition(mpu_pwrdm); | ||
354 | pwrdm_post_transition(neon_pwrdm); | ||
355 | } | ||
348 | } | 356 | } |
349 | 357 | ||
350 | static void omap3_pm_idle(void) | 358 | static void omap3_pm_idle(void) |
@@ -705,7 +713,6 @@ int __init omap3_pm_init(void) | |||
705 | neon_pwrdm = pwrdm_lookup("neon_pwrdm"); | 713 | neon_pwrdm = pwrdm_lookup("neon_pwrdm"); |
706 | per_pwrdm = pwrdm_lookup("per_pwrdm"); | 714 | per_pwrdm = pwrdm_lookup("per_pwrdm"); |
707 | core_pwrdm = pwrdm_lookup("core_pwrdm"); | 715 | core_pwrdm = pwrdm_lookup("core_pwrdm"); |
708 | cam_pwrdm = pwrdm_lookup("cam_pwrdm"); | ||
709 | 716 | ||
710 | neon_clkdm = clkdm_lookup("neon_clkdm"); | 717 | neon_clkdm = clkdm_lookup("neon_clkdm"); |
711 | mpu_clkdm = clkdm_lookup("mpu_clkdm"); | 718 | mpu_clkdm = clkdm_lookup("mpu_clkdm"); |
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 96114901b932..eefe179045e6 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c | |||
@@ -981,15 +981,23 @@ int pwrdm_state_switch(struct powerdomain *pwrdm) | |||
981 | return ret; | 981 | return ret; |
982 | } | 982 | } |
983 | 983 | ||
984 | int pwrdm_pre_transition(void) | 984 | int pwrdm_pre_transition(struct powerdomain *pwrdm) |
985 | { | 985 | { |
986 | pwrdm_for_each(_pwrdm_pre_transition_cb, NULL); | 986 | if (pwrdm) |
987 | _pwrdm_pre_transition_cb(pwrdm, NULL); | ||
988 | else | ||
989 | pwrdm_for_each(_pwrdm_pre_transition_cb, NULL); | ||
990 | |||
987 | return 0; | 991 | return 0; |
988 | } | 992 | } |
989 | 993 | ||
990 | int pwrdm_post_transition(void) | 994 | int pwrdm_post_transition(struct powerdomain *pwrdm) |
991 | { | 995 | { |
992 | pwrdm_for_each(_pwrdm_post_transition_cb, NULL); | 996 | if (pwrdm) |
997 | _pwrdm_post_transition_cb(pwrdm, NULL); | ||
998 | else | ||
999 | pwrdm_for_each(_pwrdm_post_transition_cb, NULL); | ||
1000 | |||
993 | return 0; | 1001 | return 0; |
994 | } | 1002 | } |
995 | 1003 | ||
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h index 8f88d65c46ea..a6a4604801ad 100644 --- a/arch/arm/mach-omap2/powerdomain.h +++ b/arch/arm/mach-omap2/powerdomain.h | |||
@@ -213,8 +213,8 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm); | |||
213 | int pwrdm_wait_transition(struct powerdomain *pwrdm); | 213 | int pwrdm_wait_transition(struct powerdomain *pwrdm); |
214 | 214 | ||
215 | int pwrdm_state_switch(struct powerdomain *pwrdm); | 215 | int pwrdm_state_switch(struct powerdomain *pwrdm); |
216 | int pwrdm_pre_transition(void); | 216 | int pwrdm_pre_transition(struct powerdomain *pwrdm); |
217 | int pwrdm_post_transition(void); | 217 | int pwrdm_post_transition(struct powerdomain *pwrdm); |
218 | int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm); | 218 | int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm); |
219 | int pwrdm_get_context_loss_count(struct powerdomain *pwrdm); | 219 | int pwrdm_get_context_loss_count(struct powerdomain *pwrdm); |
220 | bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm); | 220 | bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm); |