aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/cpuidle34xx.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-07-23 20:43:53 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-07-23 20:43:53 -0400
commita5ebba6b54bc8038a38d3eacac3a79bbeaf3ee24 (patch)
treed36eb26a7efd4e00381bc9f6474ea3ec31340585 /arch/arm/mach-omap2/cpuidle34xx.c
parente81218f5f0fd219bd75768d845159ba4810bdd48 (diff)
parent6b21a9ce0402e0c5fd2adfa3d41328fdd8f55a9a (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.c71
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
76static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd; 76static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;
77 77
78static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
79 struct clockdomain *clkdm)
80{
81 clkdm_allow_idle(clkdm);
82 return 0;
83}
84
85static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
86 struct clockdomain *clkdm)
87{
88 clkdm_deny_idle(clkdm);
89 return 0;
90}
91
92static int __omap3_enter_idle(struct cpuidle_device *dev, 78static 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
136return_sleep_time: 122return_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 */
228static int omap3_enter_idle_bm(struct cpuidle_device *dev, 208static 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
272select_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,