diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-23 20:43:53 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-23 20:43:53 -0400 |
commit | a5ebba6b54bc8038a38d3eacac3a79bbeaf3ee24 (patch) | |
tree | d36eb26a7efd4e00381bc9f6474ea3ec31340585 /arch/arm/mach-omap2/cpuidle34xx.c | |
parent | e81218f5f0fd219bd75768d845159ba4810bdd48 (diff) | |
parent | 6b21a9ce0402e0c5fd2adfa3d41328fdd8f55a9a (diff) |
Merge tag 'pm' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull arm-soc power management changes from Arnd Bergmann:
"These are various power management related changes, mainly concerning
cpuidle on i.MX and OMAP, as well as a the move of the omap
smartreflex driver to live in the power subsystem."
Fix up conflicts in arch/arm/mach-{imx/mach-imx6q.c,omap2/prm2xxx_3xxx.h}
* tag 'pm' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (37 commits)
ARM: OMAP2+: PM: fix IRQ_NOAUTOEN removal by mis-merge
ARM: OMAP2+: do not allow SmartReflex to be built as a module
ARM: OMAP2: Use hwmod to initialize mmc for 2420
ARM: OMAP3: PM: cpuidle: optimize the clkdm idle latency in C1 state
ARM: OMAP3: PM: cpuidle: optimize the PER latency in C1 state
ARM: OMAP3: PM: cpuidle: default to C1 in next_valid_state
ARM: OMAP3: PM: cleanup cam_pwrdm leftovers
ARM: OMAP3: PM: call pre/post transition per powerdomain
ARM: OMAP2+: powerdomain: allow pre/post transtion to be per pwrdm
ARM: OMAP3: PM: Remove IO Daisychain control from cpuidle
ARM: OMAP3PLUS: hwmod: reconfigure IO Daisychain during hwmod mux
ARM: OMAP3+: PRM: Enable IO wake up
ARM: OMAP4: PRM: Add IO Daisychain support
ARM: OMAP3: PM: Move IO Daisychain function to omap3 prm file
ARM: OMAP3: PM: correct enable/disable of daisy io chain
ARM: OMAP2+: PRM: fix compile for OMAP4-only build
W1: OMAP HDQ1W: use runtime PM
ARM: OMAP2+: HDQ1W: use omap_device
W1: OMAP HDQ1W: use 32-bit register accesses
W1: OMAP HDQ1W: allow driver to be built on all OMAP2+
...
Diffstat (limited to 'arch/arm/mach-omap2/cpuidle34xx.c')
-rw-r--r-- | arch/arm/mach-omap2/cpuidle34xx.c | 71 |
1 files changed, 27 insertions, 44 deletions
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 31344528eb54..f2a49a48ef59 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c | |||
@@ -75,20 +75,6 @@ static struct omap3_idle_statedata omap3_idle_data[] = { | |||
75 | 75 | ||
76 | static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd; | 76 | static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd; |
77 | 77 | ||
78 | static int _cpuidle_allow_idle(struct powerdomain *pwrdm, | ||
79 | struct clockdomain *clkdm) | ||
80 | { | ||
81 | clkdm_allow_idle(clkdm); | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | static int _cpuidle_deny_idle(struct powerdomain *pwrdm, | ||
86 | struct clockdomain *clkdm) | ||
87 | { | ||
88 | clkdm_deny_idle(clkdm); | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | static int __omap3_enter_idle(struct cpuidle_device *dev, | 78 | static int __omap3_enter_idle(struct cpuidle_device *dev, |
93 | struct cpuidle_driver *drv, | 79 | struct cpuidle_driver *drv, |
94 | int index) | 80 | int index) |
@@ -106,8 +92,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev, | |||
106 | 92 | ||
107 | /* Deny idle for C1 */ | 93 | /* Deny idle for C1 */ |
108 | if (index == 0) { | 94 | if (index == 0) { |
109 | pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); | 95 | clkdm_deny_idle(mpu_pd->pwrdm_clkdms[0]); |
110 | pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); | 96 | clkdm_deny_idle(core_pd->pwrdm_clkdms[0]); |
111 | } | 97 | } |
112 | 98 | ||
113 | /* | 99 | /* |
@@ -129,8 +115,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev, | |||
129 | 115 | ||
130 | /* Re-allow idle for C1 */ | 116 | /* Re-allow idle for C1 */ |
131 | if (index == 0) { | 117 | if (index == 0) { |
132 | pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); | 118 | clkdm_allow_idle(mpu_pd->pwrdm_clkdms[0]); |
133 | pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); | 119 | clkdm_allow_idle(core_pd->pwrdm_clkdms[0]); |
134 | } | 120 | } |
135 | 121 | ||
136 | return_sleep_time: | 122 | return_sleep_time: |
@@ -176,7 +162,7 @@ static int next_valid_state(struct cpuidle_device *dev, | |||
176 | u32 mpu_deepest_state = PWRDM_POWER_RET; | 162 | u32 mpu_deepest_state = PWRDM_POWER_RET; |
177 | u32 core_deepest_state = PWRDM_POWER_RET; | 163 | u32 core_deepest_state = PWRDM_POWER_RET; |
178 | int idx; | 164 | int idx; |
179 | int next_index = -1; | 165 | int next_index = 0; /* C1 is the default value */ |
180 | 166 | ||
181 | if (enable_off_mode) { | 167 | if (enable_off_mode) { |
182 | mpu_deepest_state = PWRDM_POWER_OFF; | 168 | mpu_deepest_state = PWRDM_POWER_OFF; |
@@ -207,12 +193,6 @@ static int next_valid_state(struct cpuidle_device *dev, | |||
207 | } | 193 | } |
208 | } | 194 | } |
209 | 195 | ||
210 | /* | ||
211 | * C1 is always valid. | ||
212 | * So, no need to check for 'next_index == -1' outside | ||
213 | * this loop. | ||
214 | */ | ||
215 | |||
216 | return next_index; | 196 | return next_index; |
217 | } | 197 | } |
218 | 198 | ||
@@ -226,23 +206,22 @@ static int next_valid_state(struct cpuidle_device *dev, | |||
226 | * the device to the specified or a safer state. | 206 | * the device to the specified or a safer state. |
227 | */ | 207 | */ |
228 | static int omap3_enter_idle_bm(struct cpuidle_device *dev, | 208 | static int omap3_enter_idle_bm(struct cpuidle_device *dev, |
229 | struct cpuidle_driver *drv, | 209 | struct cpuidle_driver *drv, |
230 | int index) | 210 | int index) |
231 | { | 211 | { |
232 | int new_state_idx; | 212 | int new_state_idx; |
233 | u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state; | 213 | u32 core_next_state, per_next_state = 0, per_saved_state = 0; |
234 | struct omap3_idle_statedata *cx; | 214 | struct omap3_idle_statedata *cx; |
235 | int ret; | 215 | int ret; |
236 | 216 | ||
237 | /* | 217 | /* |
238 | * Prevent idle completely if CAM is active. | 218 | * Use only C1 if CAM is active. |
239 | * CAM does not have wakeup capability in OMAP3. | 219 | * CAM does not have wakeup capability in OMAP3. |
240 | */ | 220 | */ |
241 | cam_state = pwrdm_read_pwrst(cam_pd); | 221 | if (pwrdm_read_pwrst(cam_pd) == PWRDM_POWER_ON) |
242 | if (cam_state == PWRDM_POWER_ON) { | ||
243 | new_state_idx = drv->safe_state_index; | 222 | new_state_idx = drv->safe_state_index; |
244 | goto select_state; | 223 | else |
245 | } | 224 | new_state_idx = next_valid_state(dev, drv, index); |
246 | 225 | ||
247 | /* | 226 | /* |
248 | * FIXME: we currently manage device-specific idle states | 227 | * FIXME: we currently manage device-specific idle states |
@@ -252,24 +231,28 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, | |||
252 | * its own code. | 231 | * its own code. |
253 | */ | 232 | */ |
254 | 233 | ||
255 | /* | 234 | /* Program PER state */ |
256 | * Prevent PER off if CORE is not in retention or off as this | 235 | cx = &omap3_idle_data[new_state_idx]; |
257 | * would disable PER wakeups completely. | ||
258 | */ | ||
259 | cx = &omap3_idle_data[index]; | ||
260 | core_next_state = cx->core_state; | 236 | core_next_state = cx->core_state; |
261 | per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); | 237 | per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); |
262 | if ((per_next_state == PWRDM_POWER_OFF) && | 238 | if (new_state_idx == 0) { |
263 | (core_next_state > PWRDM_POWER_RET)) | 239 | /* In C1 do not allow PER state lower than CORE state */ |
264 | per_next_state = PWRDM_POWER_RET; | 240 | if (per_next_state < core_next_state) |
241 | per_next_state = core_next_state; | ||
242 | } else { | ||
243 | /* | ||
244 | * Prevent PER OFF if CORE is not in RETention or OFF as this | ||
245 | * would disable PER wakeups completely. | ||
246 | */ | ||
247 | if ((per_next_state == PWRDM_POWER_OFF) && | ||
248 | (core_next_state > PWRDM_POWER_RET)) | ||
249 | per_next_state = PWRDM_POWER_RET; | ||
250 | } | ||
265 | 251 | ||
266 | /* Are we changing PER target state? */ | 252 | /* Are we changing PER target state? */ |
267 | if (per_next_state != per_saved_state) | 253 | if (per_next_state != per_saved_state) |
268 | pwrdm_set_next_pwrst(per_pd, per_next_state); | 254 | pwrdm_set_next_pwrst(per_pd, per_next_state); |
269 | 255 | ||
270 | new_state_idx = next_valid_state(dev, drv, index); | ||
271 | |||
272 | select_state: | ||
273 | ret = omap3_enter_idle(dev, drv, new_state_idx); | 256 | ret = omap3_enter_idle(dev, drv, new_state_idx); |
274 | 257 | ||
275 | /* Restore original PER state if it was modified */ | 258 | /* Restore original PER state if it was modified */ |
@@ -286,7 +269,7 @@ struct cpuidle_driver omap3_idle_driver = { | |||
286 | .owner = THIS_MODULE, | 269 | .owner = THIS_MODULE, |
287 | .states = { | 270 | .states = { |
288 | { | 271 | { |
289 | .enter = omap3_enter_idle, | 272 | .enter = omap3_enter_idle_bm, |
290 | .exit_latency = 2 + 2, | 273 | .exit_latency = 2 + 2, |
291 | .target_residency = 5, | 274 | .target_residency = 5, |
292 | .flags = CPUIDLE_FLAG_TIME_VALID, | 275 | .flags = CPUIDLE_FLAG_TIME_VALID, |