1 /* 2 * linux/arch/arm/mach-omap2/cpuidle34xx.c 3 * 4 * OMAP3 CPU IDLE Routines 5 * 6 * Copyright (C) 2008 Texas Instruments, Inc. 7 * Rajendra Nayak <rnayak@ti.com> 8 * 9 * Copyright (C) 2007 Texas Instruments, Inc. 10 * Karthik Dasu <karthik-dp@ti.com> 11 * 12 * Copyright (C) 2006 Nokia Corporation 13 * Tony Lindgren <tony@atomide.com> 14 * 15 * Copyright (C) 2005 Texas Instruments, Inc. 16 * Richard Woodruff <r-woodruff2@ti.com> 17 * 18 * Based on pm.c for omap2 19 * 20 * This program is free software; you can redistribute it and/or modify 21 * it under the terms of the GNU General Public License version 2 as 22 * published by the Free Software Foundation. 23 */ 24 25 #include <linux/sched.h> 26 #include <linux/cpuidle.h> 27 28 #include <plat/prcm.h> 29 #include <plat/irqs.h> 30 #include <plat/powerdomain.h> 31 #include <plat/clockdomain.h> 32 #include <plat/control.h> 33 #include <plat/serial.h> 34 35 #include "pm.h" 36 37 #ifdef CONFIG_CPU_IDLE 38 39 #define OMAP3_MAX_STATES 7 40 #define OMAP3_STATE_C1 0 /* C1 - MPU WFI + Core active */ 41 #define OMAP3_STATE_C2 1 /* C2 - MPU WFI + Core inactive */ 42 #define OMAP3_STATE_C3 2 /* C3 - MPU CSWR + Core inactive */ 43 #define OMAP3_STATE_C4 3 /* C4 - MPU OFF + Core iactive */ 44 #define OMAP3_STATE_C5 4 /* C5 - MPU RET + Core RET */ 45 #define OMAP3_STATE_C6 5 /* C6 - MPU OFF + Core RET */ 46 #define OMAP3_STATE_C7 6 /* C7 - MPU OFF + Core OFF */ 47 48 #define OMAP3_STATE_MAX OMAP3_STATE_C7 49 50 struct omap3_processor_cx { 51 u8 valid; 52 u8 type; 53 u32 sleep_latency; 54 u32 wakeup_latency; 55 u32 mpu_state; 56 u32 core_state; 57 u32 threshold; 58 u32 flags; 59 }; 60 61 struct omap3_processor_cx omap3_power_states[OMAP3_MAX_STATES]; 62 struct omap3_processor_cx current_cx_state; 63 struct powerdomain *mpu_pd, *core_pd; 64 65 /* 66 * The latencies/thresholds for various C states have 67 * to be configured from the respective board files. 68 * These are some default values (which might not provide 69 * the best power savings) used on boards which do not 70 * pass these details from the board file. 71 */ 72 static struct cpuidle_params cpuidle_params_table[] = { 73 /* C1 */ 74 {1, 2, 2, 5}, 75 /* C2 */ 76 {1, 10, 10, 30}, 77 /* C3 */ 78 {1, 50, 50, 300}, 79 /* C4 */ 80 {1, 1500, 1800, 4000}, 81 /* C5 */ 82 {1, 2500, 7500, 12000}, 83 /* C6 */ 84 {1, 3000, 8500, 15000}, 85 /* C7 */ 86 {1, 10000, 30000, 300000}, 87 }; 88 89 static int omap3_idle_bm_check(void) 90 { 91 if (!omap3_can_sleep()) 92 return 1; 93 return 0; 94 } 95 96 static int _cpuidle_allow_idle(struct powerdomain *pwrdm, 97 struct clockdomain *clkdm) 98 { 99 omap2_clkdm_allow_idle(clkdm); 100 return 0; 101 } 102 103 static int _cpuidle_deny_idle(struct powerdomain *pwrdm, 104 struct clockdomain *clkdm) 105 { 106 omap2_clkdm_deny_idle(clkdm); 107 return 0; 108 } 109 110 /** 111 * omap3_enter_idle - Programs OMAP3 to enter the specified state 112 * @dev: cpuidle device 113 * @state: The target state to be programmed 114 * 115 * Called from the CPUidle framework to program the device to the 116 * specified target state selected by the governor. 117 */ 118 static int omap3_enter_idle(struct cpuidle_device *dev, 119 struct cpuidle_state *state) 120 { 121 struct omap3_processor_cx *cx = cpuidle_get_statedata(state); 122 struct timespec ts_preidle, ts_postidle, ts_idle; 123 u32 mpu_state = cx->mpu_state, core_state = cx->core_state; 124 125 current_cx_state = *cx; 126 127 /* Used to keep track of the total time in idle */ 128 getnstimeofday(&ts_preidle); 129 130 local_irq_disable(); 131 local_fiq_disable(); 132 133 pwrdm_set_next_pwrst(mpu_pd, mpu_state); 134 pwrdm_set_next_pwrst(core_pd, core_state); 135 136 if (omap_irq_pending() || need_resched()) 137 goto return_sleep_time; 138 139 if (cx->type == OMAP3_STATE_C1) { 140 pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); 141 pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); 142 } 143 144 /* Execute ARM wfi */ 145 omap_sram_idle(); 146 147 if (cx->type == OMAP3_STATE_C1) { 148 pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); 149 pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); 150 } 151 152 return_sleep_time: 153 getnstimeofday(&ts_postidle); 154 ts_idle = timespec_sub(ts_postidle, ts_preidle); 155 156 local_irq_enable(); 157 local_fiq_enable(); 158 159 return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC; 160 } 161 162 /** 163 * next_valid_state - Find next valid c-state 164 * @dev: cpuidle device 165 * @state: Currently selected c-state 166 * 167 * If the current state is valid, it is returned back to the caller. 168 * Else, this function searches for a lower c-state which is still 169 * valid (as defined in omap3_power_states[]). 170 */ 171 static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev, 172 struct cpuidle_state *curr) 173 { 174 struct cpuidle_state *next = NULL; 175 struct omap3_processor_cx *cx; 176 177 cx = (struct omap3_processor_cx *)cpuidle_get_statedata(curr); 178 179 /* Check if current state is valid */ 180 if (cx->valid) { 181 return curr; 182 } else { 183 u8 idx = OMAP3_STATE_MAX; 184 185 /* 186 * Reach the current state starting at highest C-state 187 */ 188 for (; idx >= OMAP3_STATE_C1; idx--) { 189 if (&dev->states[idx] == curr) { 190 next = &dev->states[idx]; 191 break; 192 } 193 } 194 195 /* 196 * Should never hit this condition. 197 */ 198 WARN_ON(next == NULL); 199 200 /* 201 * Drop to next valid state. 202 * Start search from the next (lower) state. 203 */ 204 idx--; 205 for (; idx >= OMAP3_STATE_C1; idx--) { 206 struct omap3_processor_cx *cx; 207 208 cx = cpuidle_get_statedata(&dev->states[idx]); 209 if (cx->valid) { 210 next = &dev->states[idx]; 211 break; 212 } 213 } 214 /* 215 * C1 and C2 are always valid. 216 * So, no need to check for 'next==NULL' outside this loop. 217 */ 218 } 219 220 return next; 221 } 222 223 /** 224 * omap3_enter_idle_bm - Checks for any bus activity 225 * @dev: cpuidle device 226 * @state: The target state to be programmed 227 * 228 * Used for C states with CPUIDLE_FLAG_CHECK_BM flag set. This 229 * function checks for any pending activity and then programs the 230 * device to the specified or a safer state. 231 */ 232 static int omap3_enter_idle_bm(struct cpuidle_device *dev, 233 struct cpuidle_state *state) 234 { 235 struct cpuidle_state *new_state = next_valid_state(dev, state); 236 237 if ((state->flags & CPUIDLE_FLAG_CHECK_BM) && omap3_idle_bm_check()) { 238 BUG_ON(!dev->safe_state); 239 new_state = dev->safe_state; 240 } 241 242 dev->last_state = new_state; 243 return omap3_enter_idle(dev, new_state); 244 } 245 246 DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev); 247 248 /** 249 * omap3_cpuidle_update_states - Update the cpuidle states. 250 * 251 * Currently, this function toggles the validity of idle states based upon 252 * the flag 'enable_off_mode'. When the flag is set all states are valid. 253 * Else, states leading to OFF state set to be invalid. 254 */ 255 void omap3_cpuidle_update_states(void) 256 { 257 int i; 258 259 for (i = OMAP3_STATE_C1; i < OMAP3_MAX_STATES; i++) { 260 struct omap3_processor_cx *cx = &omap3_power_states[i]; 261 262 if (enable_off_mode) { 263 cx->valid = 1; 264 } else { 265 if ((cx->mpu_state == PWRDM_POWER_OFF) || 266 (cx->core_state == PWRDM_POWER_OFF)) 267 cx->valid = 0; 268 } 269 } 270 } 271 272 void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params) 273 { 274 int i; 275 276 if (!cpuidle_board_params) 277 return; 278 279 for (i = OMAP3_STATE_C1; i < OMAP3_MAX_STATES; i++) { 280 cpuidle_params_table[i].valid = 281 cpuidle_board_params[i].valid; 282 cpuidle_params_table[i].sleep_latency = 283 cpuidle_board_params[i].sleep_latency; 284 cpuidle_params_table[i].wake_latency = 285 cpuidle_board_params[i].wake_latency; 286 cpuidle_params_table[i].threshold = 287 cpuidle_board_params[i].threshold; 288 } 289 return; 290 } 291 292 /* omap3_init_power_states - Initialises the OMAP3 specific C states. 293 * 294 * Below is the desciption of each C state. 295 * C1 . MPU WFI + Core active 296 * C2 . MPU WFI + Core inactive 297 * C3 . MPU CSWR + Core inactive 298 * C4 . MPU OFF + Core inactive 299 * C5 . MPU CSWR + Core CSWR 300 * C6 . MPU OFF + Core CSWR 301 * C7 . MPU OFF + Core OFF 302 */ 303 void omap_init_power_states(void) 304 { 305 /* C1 . MPU WFI + Core active */ 306 omap3_power_states[OMAP3_STATE_C1].valid = 307 cpuidle_params_table[OMAP3_STATE_C1].valid; 308 omap3_power_states[OMAP3_STATE_C1].type = OMAP3_STATE_C1; 309 omap3_power_states[OMAP3_STATE_C1].sleep_latency = 310 cpuidle_params_table[OMAP3_STATE_C1].sleep_latency; 311 omap3_power_states[OMAP3_STATE_C1].wakeup_latency = 312 cpuidle_params_table[OMAP3_STATE_C1].wake_latency; 313 omap3_power_states[OMAP3_STATE_C1].threshold = 314 cpuidle_params_table[OMAP3_STATE_C1].threshold; 315 omap3_power_states[OMAP3_STATE_C1].mpu_state = PWRDM_POWER_ON; 316 omap3_power_states[OMAP3_STATE_C1].core_state = PWRDM_POWER_ON; 317 omap3_power_states[OMAP3_STATE_C1].flags = CPUIDLE_FLAG_TIME_VALID; 318 319 /* C2 . MPU WFI + Core inactive */ 320 omap3_power_states[OMAP3_STATE_C2].valid = 321 cpuidle_params_table[OMAP3_STATE_C2].valid; 322 omap3_power_states[OMAP3_STATE_C2].type = OMAP3_STATE_C2; 323 omap3_power_states[OMAP3_STATE_C2].sleep_latency = 324 cpuidle_params_table[OMAP3_STATE_C2].sleep_latency; 325 omap3_power_states[OMAP3_STATE_C2].wakeup_latency = 326 cpuidle_params_table[OMAP3_STATE_C2].wake_latency; 327 omap3_power_states[OMAP3_STATE_C2].threshold = 328 cpuidle_params_table[OMAP3_STATE_C2].threshold; 329 omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_ON; 330 omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON; 331 omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID; 332 333 /* C3 . MPU CSWR + Core inactive */ 334 omap3_power_states[OMAP3_STATE_C3].valid = 335 cpuidle_params_table[OMAP3_STATE_C3].valid; 336 omap3_power_states[OMAP3_STATE_C3].type = OMAP3_STATE_C3; 337 omap3_power_states[OMAP3_STATE_C3].sleep_latency = 338 cpuidle_params_table[OMAP3_STATE_C3].sleep_latency; 339 omap3_power_states[OMAP3_STATE_C3].wakeup_latency = 340 cpuidle_params_table[OMAP3_STATE_C3].wake_latency; 341 omap3_power_states[OMAP3_STATE_C3].threshold = 342 cpuidle_params_table[OMAP3_STATE_C3].threshold; 343 omap3_power_states[OMAP3_STATE_C3].mpu_state = PWRDM_POWER_RET; 344 omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_ON; 345 omap3_power_states[OMAP3_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID | 346 CPUIDLE_FLAG_CHECK_BM; 347 348 /* C4 . MPU OFF + Core inactive */ 349 omap3_power_states[OMAP3_STATE_C4].valid = 350 cpuidle_params_table[OMAP3_STATE_C4].valid; 351 omap3_power_states[OMAP3_STATE_C4].type = OMAP3_STATE_C4; 352 omap3_power_states[OMAP3_STATE_C4].sleep_latency = 353 cpuidle_params_table[OMAP3_STATE_C4].sleep_latency; 354 omap3_power_states[OMAP3_STATE_C4].wakeup_latency = 355 cpuidle_params_table[OMAP3_STATE_C4].wake_latency; 356 omap3_power_states[OMAP3_STATE_C4].threshold = 357 cpuidle_params_table[OMAP3_STATE_C4].threshold; 358 omap3_power_states[OMAP3_STATE_C4].mpu_state = PWRDM_POWER_OFF; 359 omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_ON; 360 omap3_power_states[OMAP3_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID | 361 CPUIDLE_FLAG_CHECK_BM; 362 363 /* C5 . MPU CSWR + Core CSWR*/ 364 omap3_power_states[OMAP3_STATE_C5].valid = 365 cpuidle_params_table[OMAP3_STATE_C5].valid; 366 omap3_power_states[OMAP3_STATE_C5].type = OMAP3_STATE_C5; 367 omap3_power_states[OMAP3_STATE_C5].sleep_latency = 368 cpuidle_params_table[OMAP3_STATE_C5].sleep_latency; 369 omap3_power_states[OMAP3_STATE_C5].wakeup_latency = 370 cpuidle_params_table[OMAP3_STATE_C5].wake_latency; 371 omap3_power_states[OMAP3_STATE_C5].threshold = 372 cpuidle_params_table[OMAP3_STATE_C5].threshold; 373 omap3_power_states[OMAP3_STATE_C5].mpu_state = PWRDM_POWER_RET; 374 omap3_power_states[OMAP3_STATE_C5].core_state = PWRDM_POWER_RET; 375 omap3_power_states[OMAP3_STATE_C5].flags = CPUIDLE_FLAG_TIME_VALID | 376 CPUIDLE_FLAG_CHECK_BM; 377 378 /* C6 . MPU OFF + Core CSWR */ 379 omap3_power_states[OMAP3_STATE_C6].valid = 380 cpuidle_params_table[OMAP3_STATE_C6].valid; 381 omap3_power_states[OMAP3_STATE_C6].type = OMAP3_STATE_C6; 382 omap3_power_states[OMAP3_STATE_C6].sleep_latency = 383 cpuidle_params_table[OMAP3_STATE_C6].sleep_latency; 384 omap3_power_states[OMAP3_STATE_C6].wakeup_latency = 385 cpuidle_params_table[OMAP3_STATE_C6].wake_latency; 386 omap3_power_states[OMAP3_STATE_C6].threshold = 387 cpuidle_params_table[OMAP3_STATE_C6].threshold; 388 omap3_power_states[OMAP3_STATE_C6].mpu_state = PWRDM_POWER_OFF; 389 omap3_power_states[OMAP3_STATE_C6].core_state = PWRDM_POWER_RET; 390 omap3_power_states[OMAP3_STATE_C6].flags = CPUIDLE_FLAG_TIME_VALID | 391 CPUIDLE_FLAG_CHECK_BM; 392 393 /* C7 . MPU OFF + Core OFF */ 394 omap3_power_states[OMAP3_STATE_C7].valid = 395 cpuidle_params_table[OMAP3_STATE_C7].valid; 396 omap3_power_states[OMAP3_STATE_C7].type = OMAP3_STATE_C7; 397 omap3_power_states[OMAP3_STATE_C7].sleep_latency = 398 cpuidle_params_table[OMAP3_STATE_C7].sleep_latency; 399 omap3_power_states[OMAP3_STATE_C7].wakeup_latency = 400 cpuidle_params_table[OMAP3_STATE_C7].wake_latency; 401 omap3_power_states[OMAP3_STATE_C7].threshold = 402 cpuidle_params_table[OMAP3_STATE_C7].threshold; 403 omap3_power_states[OMAP3_STATE_C7].mpu_state = PWRDM_POWER_OFF; 404 omap3_power_states[OMAP3_STATE_C7].core_state = PWRDM_POWER_OFF; 405 omap3_power_states[OMAP3_STATE_C7].flags = CPUIDLE_FLAG_TIME_VALID | 406 CPUIDLE_FLAG_CHECK_BM; 407 } 408 409 struct cpuidle_driver omap3_idle_driver = { 410 .name = "omap3_idle", 411 .owner = THIS_MODULE, 412 }; 413 414 /** 415 * omap3_idle_init - Init routine for OMAP3 idle 416 * 417 * Registers the OMAP3 specific cpuidle driver with the cpuidle 418 * framework with the valid set of states. 419 */ 420 int __init omap3_idle_init(void) 421 { 422 int i, count = 0; 423 struct omap3_processor_cx *cx; 424 struct cpuidle_state *state; 425 struct cpuidle_device *dev; 426 427 mpu_pd = pwrdm_lookup("mpu_pwrdm"); 428 core_pd = pwrdm_lookup("core_pwrdm"); 429 430 omap_init_power_states(); 431 cpuidle_register_driver(&omap3_idle_driver); 432 433 dev = &per_cpu(omap3_idle_dev, smp_processor_id()); 434 435 for (i = OMAP3_STATE_C1; i < OMAP3_MAX_STATES; i++) { 436 cx = &omap3_power_states[i]; 437 state = &dev->states[count]; 438 439 if (!cx->valid) 440 continue; 441 cpuidle_set_statedata(state, cx); 442 state->exit_latency = cx->sleep_latency + cx->wakeup_latency; 443 state->target_residency = cx->threshold; 444 state->flags = cx->flags; 445 state->enter = (state->flags & CPUIDLE_FLAG_CHECK_BM) ? 446 omap3_enter_idle_bm : omap3_enter_idle; 447 if (cx->type == OMAP3_STATE_C1) 448 dev->safe_state = state; 449 sprintf(state->name, "C%d", count+1); 450 count++; 451 } 452 453 if (!count) 454 return -EINVAL; 455 dev->state_count = count; 456 457 omap3_cpuidle_update_states(); 458 459 if (cpuidle_register_device(dev)) { 460 printk(KERN_ERR "%s: CPUidle register device failed\n", 461 __func__); 462 return -EIO; 463 } 464 465 return 0; 466 } 467 #else 468 int __init omap3_idle_init(void) 469 { 470 return 0; 471 } 472 #endif /* CONFIG_CPU_IDLE */ 473