aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2
diff options
context:
space:
mode:
authorDeepthi Dharwar <deepthi@linux.vnet.ibm.com>2011-10-28 06:50:42 -0400
committerLen Brown <len.brown@intel.com>2011-11-06 21:13:58 -0500
commit46bcfad7a819bd17ac4e831b04405152d59784ab (patch)
tree20041e788154d103edff2699f88d4a30320e3ee2 /arch/arm/mach-omap2
parent4202735e8ab6ecfb0381631a0d0b58fefe0bd4e2 (diff)
cpuidle: Single/Global registration of idle states
This patch makes the cpuidle_states structure global (single copy) instead of per-cpu. The statistics needed on per-cpu basis by the governor are kept per-cpu. This simplifies the cpuidle subsystem as state registration is done by single cpu only. Having single copy of cpuidle_states saves memory. Rare case of asymmetric C-states can be handled within the cpuidle driver and architectures such as POWER do not have asymmetric C-states. Having single/global registration of all the idle states, dynamic C-state transitions on x86 are handled by the boot cpu. Here, the boot cpu would disable all the devices, re-populate the states and later enable all the devices, irrespective of the cpu that would receive the notification first. Reference: https://lkml.org/lkml/2011/4/25/83 Signed-off-by: Deepthi Dharwar <deepthi@linux.vnet.ibm.com> Signed-off-by: Trinabh Gupta <g.trinabh@gmail.com> Tested-by: Jean Pihet <j-pihet@ti.com> Reviewed-by: Kevin Hilman <khilman@ti.com> Acked-by: Arjan van de Ven <arjan@linux.intel.com> Acked-by: Kevin Hilman <khilman@ti.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r--arch/arm/mach-omap2/cpuidle34xx.c73
1 files changed, 49 insertions, 24 deletions
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index d3fce7b97fcf..1fe35c24fba2 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -88,12 +88,14 @@ static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
88/** 88/**
89 * omap3_enter_idle - Programs OMAP3 to enter the specified state 89 * omap3_enter_idle - Programs OMAP3 to enter the specified state
90 * @dev: cpuidle device 90 * @dev: cpuidle device
91 * @drv: cpuidle driver
91 * @index: the index of state to be entered 92 * @index: the index of state to be entered
92 * 93 *
93 * Called from the CPUidle framework to program the device to the 94 * Called from the CPUidle framework to program the device to the
94 * specified target state selected by the governor. 95 * specified target state selected by the governor.
95 */ 96 */
96static int omap3_enter_idle(struct cpuidle_device *dev, 97static int omap3_enter_idle(struct cpuidle_device *dev,
98 struct cpuidle_driver *drv,
97 int index) 99 int index)
98{ 100{
99 struct omap3_idle_statedata *cx = 101 struct omap3_idle_statedata *cx =
@@ -148,6 +150,7 @@ return_sleep_time:
148/** 150/**
149 * next_valid_state - Find next valid C-state 151 * next_valid_state - Find next valid C-state
150 * @dev: cpuidle device 152 * @dev: cpuidle device
153 * @drv: cpuidle driver
151 * @index: Index of currently selected c-state 154 * @index: Index of currently selected c-state
152 * 155 *
153 * If the state corresponding to index is valid, index is returned back 156 * If the state corresponding to index is valid, index is returned back
@@ -158,10 +161,11 @@ return_sleep_time:
158 * if it satisfies the enable_off_mode condition. 161 * if it satisfies the enable_off_mode condition.
159 */ 162 */
160static int next_valid_state(struct cpuidle_device *dev, 163static int next_valid_state(struct cpuidle_device *dev,
164 struct cpuidle_driver *drv,
161 int index) 165 int index)
162{ 166{
163 struct cpuidle_state_usage *curr_usage = &dev->states_usage[index]; 167 struct cpuidle_state_usage *curr_usage = &dev->states_usage[index];
164 struct cpuidle_state *curr = &dev->states[index]; 168 struct cpuidle_state *curr = &drv->states[index];
165 struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage); 169 struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage);
166 u32 mpu_deepest_state = PWRDM_POWER_RET; 170 u32 mpu_deepest_state = PWRDM_POWER_RET;
167 u32 core_deepest_state = PWRDM_POWER_RET; 171 u32 core_deepest_state = PWRDM_POWER_RET;
@@ -188,7 +192,7 @@ static int next_valid_state(struct cpuidle_device *dev,
188 192
189 /* Reach the current state starting at highest C-state */ 193 /* Reach the current state starting at highest C-state */
190 for (; idx >= 0; idx--) { 194 for (; idx >= 0; idx--) {
191 if (&dev->states[idx] == curr) { 195 if (&drv->states[idx] == curr) {
192 next_index = idx; 196 next_index = idx;
193 break; 197 break;
194 } 198 }
@@ -224,12 +228,14 @@ static int next_valid_state(struct cpuidle_device *dev,
224/** 228/**
225 * omap3_enter_idle_bm - Checks for any bus activity 229 * omap3_enter_idle_bm - Checks for any bus activity
226 * @dev: cpuidle device 230 * @dev: cpuidle device
231 * @drv: cpuidle driver
227 * @index: array index of target state to be programmed 232 * @index: array index of target state to be programmed
228 * 233 *
229 * This function checks for any pending activity and then programs 234 * This function checks for any pending activity and then programs
230 * the device to the specified or a safer state. 235 * the device to the specified or a safer state.
231 */ 236 */
232static int omap3_enter_idle_bm(struct cpuidle_device *dev, 237static int omap3_enter_idle_bm(struct cpuidle_device *dev,
238 struct cpuidle_driver *drv,
233 int index) 239 int index)
234{ 240{
235 int new_state_idx; 241 int new_state_idx;
@@ -238,7 +244,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
238 int ret; 244 int ret;
239 245
240 if (!omap3_can_sleep()) { 246 if (!omap3_can_sleep()) {
241 new_state_idx = dev->safe_state_index; 247 new_state_idx = drv->safe_state_index;
242 goto select_state; 248 goto select_state;
243 } 249 }
244 250
@@ -248,7 +254,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
248 */ 254 */
249 cam_state = pwrdm_read_pwrst(cam_pd); 255 cam_state = pwrdm_read_pwrst(cam_pd);
250 if (cam_state == PWRDM_POWER_ON) { 256 if (cam_state == PWRDM_POWER_ON) {
251 new_state_idx = dev->safe_state_index; 257 new_state_idx = drv->safe_state_index;
252 goto select_state; 258 goto select_state;
253 } 259 }
254 260
@@ -275,10 +281,10 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
275 if (per_next_state != per_saved_state) 281 if (per_next_state != per_saved_state)
276 pwrdm_set_next_pwrst(per_pd, per_next_state); 282 pwrdm_set_next_pwrst(per_pd, per_next_state);
277 283
278 new_state_idx = next_valid_state(dev, index); 284 new_state_idx = next_valid_state(dev, drv, index);
279 285
280select_state: 286select_state:
281 ret = omap3_enter_idle(dev, new_state_idx); 287 ret = omap3_enter_idle(dev, drv, new_state_idx);
282 288
283 /* Restore original PER state if it was modified */ 289 /* Restore original PER state if it was modified */
284 if (per_next_state != per_saved_state) 290 if (per_next_state != per_saved_state)
@@ -311,22 +317,30 @@ struct cpuidle_driver omap3_idle_driver = {
311 .owner = THIS_MODULE, 317 .owner = THIS_MODULE,
312}; 318};
313 319
314/* Helper to fill the C-state common data and register the driver_data */ 320/* Helper to fill the C-state common data*/
315static inline struct omap3_idle_statedata *_fill_cstate( 321static inline void _fill_cstate(struct cpuidle_driver *drv,
316 struct cpuidle_device *dev,
317 int idx, const char *descr) 322 int idx, const char *descr)
318{ 323{
319 struct omap3_idle_statedata *cx = &omap3_idle_data[idx]; 324 struct cpuidle_state *state = &drv->states[idx];
320 struct cpuidle_state *state = &dev->states[idx];
321 struct cpuidle_state_usage *state_usage = &dev->states_usage[idx];
322 325
323 state->exit_latency = cpuidle_params_table[idx].exit_latency; 326 state->exit_latency = cpuidle_params_table[idx].exit_latency;
324 state->target_residency = cpuidle_params_table[idx].target_residency; 327 state->target_residency = cpuidle_params_table[idx].target_residency;
325 state->flags = CPUIDLE_FLAG_TIME_VALID; 328 state->flags = CPUIDLE_FLAG_TIME_VALID;
326 state->enter = omap3_enter_idle_bm; 329 state->enter = omap3_enter_idle_bm;
327 cx->valid = cpuidle_params_table[idx].valid;
328 sprintf(state->name, "C%d", idx + 1); 330 sprintf(state->name, "C%d", idx + 1);
329 strncpy(state->desc, descr, CPUIDLE_DESC_LEN); 331 strncpy(state->desc, descr, CPUIDLE_DESC_LEN);
332
333}
334
335/* Helper to register the driver_data */
336static inline struct omap3_idle_statedata *_fill_cstate_usage(
337 struct cpuidle_device *dev,
338 int idx)
339{
340 struct omap3_idle_statedata *cx = &omap3_idle_data[idx];
341 struct cpuidle_state_usage *state_usage = &dev->states_usage[idx];
342
343 cx->valid = cpuidle_params_table[idx].valid;
330 cpuidle_set_statedata(state_usage, cx); 344 cpuidle_set_statedata(state_usage, cx);
331 345
332 return cx; 346 return cx;
@@ -341,6 +355,7 @@ static inline struct omap3_idle_statedata *_fill_cstate(
341int __init omap3_idle_init(void) 355int __init omap3_idle_init(void)
342{ 356{
343 struct cpuidle_device *dev; 357 struct cpuidle_device *dev;
358 struct cpuidle_driver *drv = &omap3_idle_driver;
344 struct omap3_idle_statedata *cx; 359 struct omap3_idle_statedata *cx;
345 360
346 mpu_pd = pwrdm_lookup("mpu_pwrdm"); 361 mpu_pd = pwrdm_lookup("mpu_pwrdm");
@@ -348,45 +363,52 @@ int __init omap3_idle_init(void)
348 per_pd = pwrdm_lookup("per_pwrdm"); 363 per_pd = pwrdm_lookup("per_pwrdm");
349 cam_pd = pwrdm_lookup("cam_pwrdm"); 364 cam_pd = pwrdm_lookup("cam_pwrdm");
350 365
351 cpuidle_register_driver(&omap3_idle_driver); 366
367 drv->safe_state_index = -1;
352 dev = &per_cpu(omap3_idle_dev, smp_processor_id()); 368 dev = &per_cpu(omap3_idle_dev, smp_processor_id());
353 dev->safe_state_index = -1;
354 369
355 /* C1 . MPU WFI + Core active */ 370 /* C1 . MPU WFI + Core active */
356 cx = _fill_cstate(dev, 0, "MPU ON + CORE ON"); 371 _fill_cstate(drv, 0, "MPU ON + CORE ON");
357 (&dev->states[0])->enter = omap3_enter_idle; 372 (&drv->states[0])->enter = omap3_enter_idle;
358 dev->safe_state_index = 0; 373 drv->safe_state_index = 0;
374 cx = _fill_cstate_usage(dev, 0);
359 cx->valid = 1; /* C1 is always valid */ 375 cx->valid = 1; /* C1 is always valid */
360 cx->mpu_state = PWRDM_POWER_ON; 376 cx->mpu_state = PWRDM_POWER_ON;
361 cx->core_state = PWRDM_POWER_ON; 377 cx->core_state = PWRDM_POWER_ON;
362 378
363 /* C2 . MPU WFI + Core inactive */ 379 /* C2 . MPU WFI + Core inactive */
364 cx = _fill_cstate(dev, 1, "MPU ON + CORE ON"); 380 _fill_cstate(drv, 1, "MPU ON + CORE ON");
381 cx = _fill_cstate_usage(dev, 1);
365 cx->mpu_state = PWRDM_POWER_ON; 382 cx->mpu_state = PWRDM_POWER_ON;
366 cx->core_state = PWRDM_POWER_ON; 383 cx->core_state = PWRDM_POWER_ON;
367 384
368 /* C3 . MPU CSWR + Core inactive */ 385 /* C3 . MPU CSWR + Core inactive */
369 cx = _fill_cstate(dev, 2, "MPU RET + CORE ON"); 386 _fill_cstate(drv, 2, "MPU RET + CORE ON");
387 cx = _fill_cstate_usage(dev, 2);
370 cx->mpu_state = PWRDM_POWER_RET; 388 cx->mpu_state = PWRDM_POWER_RET;
371 cx->core_state = PWRDM_POWER_ON; 389 cx->core_state = PWRDM_POWER_ON;
372 390
373 /* C4 . MPU OFF + Core inactive */ 391 /* C4 . MPU OFF + Core inactive */
374 cx = _fill_cstate(dev, 3, "MPU OFF + CORE ON"); 392 _fill_cstate(drv, 3, "MPU OFF + CORE ON");
393 cx = _fill_cstate_usage(dev, 3);
375 cx->mpu_state = PWRDM_POWER_OFF; 394 cx->mpu_state = PWRDM_POWER_OFF;
376 cx->core_state = PWRDM_POWER_ON; 395 cx->core_state = PWRDM_POWER_ON;
377 396
378 /* C5 . MPU RET + Core RET */ 397 /* C5 . MPU RET + Core RET */
379 cx = _fill_cstate(dev, 4, "MPU RET + CORE RET"); 398 _fill_cstate(drv, 4, "MPU RET + CORE RET");
399 cx = _fill_cstate_usage(dev, 4);
380 cx->mpu_state = PWRDM_POWER_RET; 400 cx->mpu_state = PWRDM_POWER_RET;
381 cx->core_state = PWRDM_POWER_RET; 401 cx->core_state = PWRDM_POWER_RET;
382 402
383 /* C6 . MPU OFF + Core RET */ 403 /* C6 . MPU OFF + Core RET */
384 cx = _fill_cstate(dev, 5, "MPU OFF + CORE RET"); 404 _fill_cstate(drv, 5, "MPU OFF + CORE RET");
405 cx = _fill_cstate_usage(dev, 5);
385 cx->mpu_state = PWRDM_POWER_OFF; 406 cx->mpu_state = PWRDM_POWER_OFF;
386 cx->core_state = PWRDM_POWER_RET; 407 cx->core_state = PWRDM_POWER_RET;
387 408
388 /* C7 . MPU OFF + Core OFF */ 409 /* C7 . MPU OFF + Core OFF */
389 cx = _fill_cstate(dev, 6, "MPU OFF + CORE OFF"); 410 _fill_cstate(drv, 6, "MPU OFF + CORE OFF");
411 cx = _fill_cstate_usage(dev, 6);
390 /* 412 /*
391 * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot 413 * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
392 * enable OFF mode in a stable form for previous revisions. 414 * enable OFF mode in a stable form for previous revisions.
@@ -400,6 +422,9 @@ int __init omap3_idle_init(void)
400 cx->mpu_state = PWRDM_POWER_OFF; 422 cx->mpu_state = PWRDM_POWER_OFF;
401 cx->core_state = PWRDM_POWER_OFF; 423 cx->core_state = PWRDM_POWER_OFF;
402 424
425 drv->state_count = OMAP3_NUM_STATES;
426 cpuidle_register_driver(&omap3_idle_driver);
427
403 dev->state_count = OMAP3_NUM_STATES; 428 dev->state_count = OMAP3_NUM_STATES;
404 if (cpuidle_register_device(dev)) { 429 if (cpuidle_register_device(dev)) {
405 printk(KERN_ERR "%s: CPUidle register device failed\n", 430 printk(KERN_ERR "%s: CPUidle register device failed\n",