2008-10-08 16:00:58 +04:00
/*
* linux / arch / arm / mach - omap2 / cpuidle34xx . c
*
* OMAP3 CPU IDLE Routines
*
* Copyright ( C ) 2008 Texas Instruments , Inc .
* Rajendra Nayak < rnayak @ ti . com >
*
* Copyright ( C ) 2007 Texas Instruments , Inc .
* Karthik Dasu < karthik - dp @ ti . com >
*
* Copyright ( C ) 2006 Nokia Corporation
* Tony Lindgren < tony @ atomide . com >
*
* Copyright ( C ) 2005 Texas Instruments , Inc .
* Richard Woodruff < r - woodruff2 @ ti . com >
*
* Based on pm . c for omap2
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
2009-03-20 16:21:02 +03:00
# include <linux/sched.h>
2008-10-08 16:00:58 +04:00
# include <linux/cpuidle.h>
# include <plat/prcm.h>
2008-10-08 16:01:22 +04:00
# include <plat/irqs.h>
2010-12-22 07:05:16 +03:00
# include "powerdomain.h"
2010-12-22 07:05:15 +03:00
# include "clockdomain.h"
2008-10-29 03:32:11 +03:00
# include <plat/serial.h>
2008-10-08 16:00:58 +04:00
2008-10-29 03:30:07 +03:00
# include "pm.h"
2010-10-08 21:40:20 +04:00
# include "control.h"
2008-10-29 03:30:07 +03:00
2008-10-08 16:00:58 +04:00
# ifdef CONFIG_CPU_IDLE
2009-03-13 19:04:25 +03:00
# define OMAP3_MAX_STATES 7
# define OMAP3_STATE_C1 0 /* C1 - MPU WFI + Core active */
# define OMAP3_STATE_C2 1 /* C2 - MPU WFI + Core inactive */
# define OMAP3_STATE_C3 2 /* C3 - MPU CSWR + Core inactive */
# define OMAP3_STATE_C4 3 /* C4 - MPU OFF + Core iactive */
# define OMAP3_STATE_C5 4 /* C5 - MPU RET + Core RET */
# define OMAP3_STATE_C6 5 /* C6 - MPU OFF + Core RET */
# define OMAP3_STATE_C7 6 /* C7 - MPU OFF + Core OFF */
2008-10-08 16:00:58 +04:00
2010-01-28 20:46:43 +03:00
# define OMAP3_STATE_MAX OMAP3_STATE_C7
2011-01-12 10:56:15 +03:00
# define CPUIDLE_FLAG_CHECK_BM 0x10000 /* use omap3_enter_idle_bm() */
2008-10-08 16:00:58 +04:00
struct omap3_processor_cx {
u8 valid ;
u8 type ;
u32 sleep_latency ;
u32 wakeup_latency ;
u32 mpu_state ;
u32 core_state ;
u32 threshold ;
u32 flags ;
2011-02-11 18:12:12 +03:00
const char * desc ;
2008-10-08 16:00:58 +04:00
} ;
struct omap3_processor_cx omap3_power_states [ OMAP3_MAX_STATES ] ;
struct omap3_processor_cx current_cx_state ;
2010-09-09 03:37:42 +04:00
struct powerdomain * mpu_pd , * core_pd , * per_pd ;
struct powerdomain * cam_pd ;
2008-10-08 16:00:58 +04:00
2009-12-16 03:37:18 +03:00
/*
* The latencies / thresholds for various C states have
* to be configured from the respective board files .
* These are some default values ( which might not provide
* the best power savings ) used on boards which do not
* pass these details from the board file .
*/
static struct cpuidle_params cpuidle_params_table [ ] = {
/* C1 */
2009-10-29 11:30:19 +03:00
{ 1 , 2 , 2 , 5 } ,
2009-12-16 03:37:18 +03:00
/* C2 */
2009-10-29 11:30:19 +03:00
{ 1 , 10 , 10 , 30 } ,
2009-12-16 03:37:18 +03:00
/* C3 */
2009-10-29 11:30:19 +03:00
{ 1 , 50 , 50 , 300 } ,
2009-12-16 03:37:18 +03:00
/* C4 */
2009-10-29 11:30:19 +03:00
{ 1 , 1500 , 1800 , 4000 } ,
2009-12-16 03:37:18 +03:00
/* C5 */
2009-10-29 11:30:19 +03:00
{ 1 , 2500 , 7500 , 12000 } ,
2009-12-16 03:37:18 +03:00
/* C6 */
2009-10-29 11:30:19 +03:00
{ 1 , 3000 , 8500 , 15000 } ,
2009-12-16 03:37:18 +03:00
/* C7 */
2009-10-29 11:30:19 +03:00
{ 1 , 10000 , 30000 , 300000 } ,
2009-12-16 03:37:18 +03:00
} ;
2008-10-08 16:00:58 +04:00
static int omap3_idle_bm_check ( void )
{
2008-10-08 16:01:22 +04:00
if ( ! omap3_can_sleep ( ) )
return 1 ;
2008-10-08 16:00:58 +04:00
return 0 ;
}
2009-03-13 19:19:16 +03:00
static int _cpuidle_allow_idle ( struct powerdomain * pwrdm ,
struct clockdomain * clkdm )
{
2011-02-26 02:06:48 +03:00
clkdm_allow_idle ( clkdm ) ;
2009-03-13 19:19:16 +03:00
return 0 ;
}
static int _cpuidle_deny_idle ( struct powerdomain * pwrdm ,
struct clockdomain * clkdm )
{
2011-02-26 02:06:48 +03:00
clkdm_deny_idle ( clkdm ) ;
2009-03-13 19:19:16 +03:00
return 0 ;
}
2008-10-08 16:00:58 +04:00
/**
* omap3_enter_idle - Programs OMAP3 to enter the specified state
* @ dev : cpuidle device
* @ state : The target state to be programmed
*
* Called from the CPUidle framework to program the device to the
* specified target state selected by the governor .
*/
static int omap3_enter_idle ( struct cpuidle_device * dev ,
struct cpuidle_state * state )
{
struct omap3_processor_cx * cx = cpuidle_get_statedata ( state ) ;
struct timespec ts_preidle , ts_postidle , ts_idle ;
2008-10-29 03:30:07 +03:00
u32 mpu_state = cx - > mpu_state , core_state = cx - > core_state ;
2008-10-08 16:00:58 +04:00
current_cx_state = * cx ;
/* Used to keep track of the total time in idle */
getnstimeofday ( & ts_preidle ) ;
local_irq_disable ( ) ;
local_fiq_disable ( ) ;
2008-10-28 11:59:05 +03:00
pwrdm_set_next_pwrst ( mpu_pd , mpu_state ) ;
pwrdm_set_next_pwrst ( core_pd , core_state ) ;
2008-10-08 16:01:22 +04:00
2009-03-20 16:21:02 +03:00
if ( omap_irq_pending ( ) | | need_resched ( ) )
2008-10-08 16:01:22 +04:00
goto return_sleep_time ;
2008-10-08 16:00:58 +04:00
2009-03-13 19:19:16 +03:00
if ( cx - > type = = OMAP3_STATE_C1 ) {
pwrdm_for_each_clkdm ( mpu_pd , _cpuidle_deny_idle ) ;
pwrdm_for_each_clkdm ( core_pd , _cpuidle_deny_idle ) ;
}
2008-10-08 16:00:58 +04:00
/* Execute ARM wfi */
omap_sram_idle ( ) ;
2009-03-13 19:19:16 +03:00
if ( cx - > type = = OMAP3_STATE_C1 ) {
pwrdm_for_each_clkdm ( mpu_pd , _cpuidle_allow_idle ) ;
pwrdm_for_each_clkdm ( core_pd , _cpuidle_allow_idle ) ;
}
2008-10-08 16:01:22 +04:00
return_sleep_time :
2008-10-08 16:00:58 +04:00
getnstimeofday ( & ts_postidle ) ;
ts_idle = timespec_sub ( ts_postidle , ts_preidle ) ;
local_irq_enable ( ) ;
local_fiq_enable ( ) ;
2009-10-26 16:10:40 +03:00
return ts_idle . tv_nsec / NSEC_PER_USEC + ts_idle . tv_sec * USEC_PER_SEC ;
2008-10-08 16:00:58 +04:00
}
2010-01-28 20:46:43 +03:00
/**
* next_valid_state - Find next valid c - state
* @ dev : cpuidle device
* @ state : Currently selected c - state
*
* If the current state is valid , it is returned back to the caller .
* Else , this function searches for a lower c - state which is still
* valid ( as defined in omap3_power_states [ ] ) .
*/
static struct cpuidle_state * next_valid_state ( struct cpuidle_device * dev ,
struct cpuidle_state * curr )
{
struct cpuidle_state * next = NULL ;
struct omap3_processor_cx * cx ;
cx = ( struct omap3_processor_cx * ) cpuidle_get_statedata ( curr ) ;
/* Check if current state is valid */
if ( cx - > valid ) {
return curr ;
} else {
u8 idx = OMAP3_STATE_MAX ;
/*
* Reach the current state starting at highest C - state
*/
for ( ; idx > = OMAP3_STATE_C1 ; idx - - ) {
if ( & dev - > states [ idx ] = = curr ) {
next = & dev - > states [ idx ] ;
break ;
}
}
/*
* Should never hit this condition .
*/
WARN_ON ( next = = NULL ) ;
/*
* Drop to next valid state .
* Start search from the next ( lower ) state .
*/
idx - - ;
for ( ; idx > = OMAP3_STATE_C1 ; idx - - ) {
struct omap3_processor_cx * cx ;
cx = cpuidle_get_statedata ( & dev - > states [ idx ] ) ;
if ( cx - > valid ) {
next = & dev - > states [ idx ] ;
break ;
}
}
/*
* C1 and C2 are always valid .
* So , no need to check for ' next = = NULL ' outside this loop .
*/
}
return next ;
}
2008-10-08 16:00:58 +04:00
/**
* omap3_enter_idle_bm - Checks for any bus activity
* @ dev : cpuidle device
* @ state : The target state to be programmed
*
* Used for C states with CPUIDLE_FLAG_CHECK_BM flag set . This
* function checks for any pending activity and then programs the
* device to the specified or a safer state .
*/
static int omap3_enter_idle_bm ( struct cpuidle_device * dev ,
struct cpuidle_state * state )
{
2010-01-28 20:46:43 +03:00
struct cpuidle_state * new_state = next_valid_state ( dev , state ) ;
2010-09-09 03:37:42 +04:00
u32 core_next_state , per_next_state = 0 , per_saved_state = 0 ;
u32 cam_state ;
struct omap3_processor_cx * cx ;
int ret ;
2008-10-29 03:32:11 +03:00
2008-10-08 16:00:58 +04:00
if ( ( state - > flags & CPUIDLE_FLAG_CHECK_BM ) & & omap3_idle_bm_check ( ) ) {
2008-10-29 03:32:11 +03:00
BUG_ON ( ! dev - > safe_state ) ;
new_state = dev - > safe_state ;
2010-09-09 03:37:42 +04:00
goto select_state ;
}
cx = cpuidle_get_statedata ( state ) ;
core_next_state = cx - > core_state ;
/*
* FIXME : we currently manage device - specific idle states
* for PER and CORE in combination with CPU - specific
* idle states . This is wrong , and device - specific
tree-wide: fix comment/printk typos
"gadget", "through", "command", "maintain", "maintain", "controller", "address",
"between", "initiali[zs]e", "instead", "function", "select", "already",
"equal", "access", "management", "hierarchy", "registration", "interest",
"relative", "memory", "offset", "already",
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2010-11-01 22:38:34 +03:00
* idle management needs to be separated out into
2010-09-09 03:37:42 +04:00
* its own code .
*/
/*
* Prevent idle completely if CAM is active .
* CAM does not have wakeup capability in OMAP3 .
*/
cam_state = pwrdm_read_pwrst ( cam_pd ) ;
if ( cam_state = = PWRDM_POWER_ON ) {
new_state = dev - > safe_state ;
goto select_state ;
}
/*
* Prevent PER off if CORE is not in retention or off as this
* would disable PER wakeups completely .
*/
per_next_state = per_saved_state = pwrdm_read_next_pwrst ( per_pd ) ;
if ( ( per_next_state = = PWRDM_POWER_OFF ) & &
2010-10-01 19:35:47 +04:00
( core_next_state > PWRDM_POWER_RET ) )
2010-09-09 03:37:42 +04:00
per_next_state = PWRDM_POWER_RET ;
2008-10-29 03:32:11 +03:00
2010-09-09 03:37:42 +04:00
/* Are we changing PER target state? */
if ( per_next_state ! = per_saved_state )
pwrdm_set_next_pwrst ( per_pd , per_next_state ) ;
select_state :
2008-10-29 03:32:11 +03:00
dev - > last_state = new_state ;
2010-09-09 03:37:42 +04:00
ret = omap3_enter_idle ( dev , new_state ) ;
/* Restore original PER state if it was modified */
if ( per_next_state ! = per_saved_state )
pwrdm_set_next_pwrst ( per_pd , per_saved_state ) ;
return ret ;
2008-10-08 16:00:58 +04:00
}
DEFINE_PER_CPU ( struct cpuidle_device , omap3_idle_dev ) ;
2010-01-28 20:46:43 +03:00
/**
2010-12-20 23:05:08 +03:00
* omap3_cpuidle_update_states ( ) - Update the cpuidle states
2011-03-31 05:57:33 +04:00
* @ mpu_deepest_state : Enable states up to and including this for mpu domain
* @ core_deepest_state : Enable states up to and including this for core domain
2010-01-28 20:46:43 +03:00
*
2010-12-20 23:05:08 +03:00
* This goes through the list of states available and enables and disables the
* validity of C states based on deepest state that can be achieved for the
* variable domain
2010-01-28 20:46:43 +03:00
*/
2010-12-20 23:05:08 +03:00
void omap3_cpuidle_update_states ( u32 mpu_deepest_state , u32 core_deepest_state )
2010-01-28 20:46:43 +03:00
{
int i ;
for ( i = OMAP3_STATE_C1 ; i < OMAP3_MAX_STATES ; i + + ) {
struct omap3_processor_cx * cx = & omap3_power_states [ i ] ;
2010-12-20 23:05:08 +03:00
if ( ( cx - > mpu_state > = mpu_deepest_state ) & &
( cx - > core_state > = core_deepest_state ) ) {
2010-01-28 20:46:43 +03:00
cx - > valid = 1 ;
} else {
2010-12-20 23:05:08 +03:00
cx - > valid = 0 ;
2010-01-28 20:46:43 +03:00
}
}
}
2009-12-16 03:37:18 +03:00
void omap3_pm_init_cpuidle ( struct cpuidle_params * cpuidle_board_params )
{
int i ;
if ( ! cpuidle_board_params )
return ;
for ( i = OMAP3_STATE_C1 ; i < OMAP3_MAX_STATES ; i + + ) {
2009-10-29 11:30:19 +03:00
cpuidle_params_table [ i ] . valid =
cpuidle_board_params [ i ] . valid ;
2009-12-16 03:37:18 +03:00
cpuidle_params_table [ i ] . sleep_latency =
cpuidle_board_params [ i ] . sleep_latency ;
cpuidle_params_table [ i ] . wake_latency =
cpuidle_board_params [ i ] . wake_latency ;
cpuidle_params_table [ i ] . threshold =
cpuidle_board_params [ i ] . threshold ;
}
return ;
}
2008-10-08 16:00:58 +04:00
/* omap3_init_power_states - Initialises the OMAP3 specific C states.
*
* Below is the desciption of each C state .
2009-03-13 19:19:16 +03:00
* C1 . MPU WFI + Core active
* C2 . MPU WFI + Core inactive
* C3 . MPU CSWR + Core inactive
* C4 . MPU OFF + Core inactive
* C5 . MPU CSWR + Core CSWR
* C6 . MPU OFF + Core CSWR
* C7 . MPU OFF + Core OFF
2008-10-08 16:00:58 +04:00
*/
void omap_init_power_states ( void )
{
/* C1 . MPU WFI + Core active */
2009-10-29 11:30:19 +03:00
omap3_power_states [ OMAP3_STATE_C1 ] . valid =
cpuidle_params_table [ OMAP3_STATE_C1 ] . valid ;
2008-10-08 16:00:58 +04:00
omap3_power_states [ OMAP3_STATE_C1 ] . type = OMAP3_STATE_C1 ;
2009-12-16 03:37:18 +03:00
omap3_power_states [ OMAP3_STATE_C1 ] . sleep_latency =
cpuidle_params_table [ OMAP3_STATE_C1 ] . sleep_latency ;
omap3_power_states [ OMAP3_STATE_C1 ] . wakeup_latency =
cpuidle_params_table [ OMAP3_STATE_C1 ] . wake_latency ;
omap3_power_states [ OMAP3_STATE_C1 ] . threshold =
cpuidle_params_table [ OMAP3_STATE_C1 ] . threshold ;
2008-10-08 16:00:58 +04:00
omap3_power_states [ OMAP3_STATE_C1 ] . mpu_state = PWRDM_POWER_ON ;
omap3_power_states [ OMAP3_STATE_C1 ] . core_state = PWRDM_POWER_ON ;
omap3_power_states [ OMAP3_STATE_C1 ] . flags = CPUIDLE_FLAG_TIME_VALID ;
2011-02-11 18:12:12 +03:00
omap3_power_states [ OMAP3_STATE_C1 ] . desc = " MPU ON + CORE ON " ;
2008-10-08 16:00:58 +04:00
2009-03-13 19:19:16 +03:00
/* C2 . MPU WFI + Core inactive */
2009-10-29 11:30:19 +03:00
omap3_power_states [ OMAP3_STATE_C2 ] . valid =
cpuidle_params_table [ OMAP3_STATE_C2 ] . valid ;
2008-10-08 16:00:58 +04:00
omap3_power_states [ OMAP3_STATE_C2 ] . type = OMAP3_STATE_C2 ;
2009-12-16 03:37:18 +03:00
omap3_power_states [ OMAP3_STATE_C2 ] . sleep_latency =
cpuidle_params_table [ OMAP3_STATE_C2 ] . sleep_latency ;
omap3_power_states [ OMAP3_STATE_C2 ] . wakeup_latency =
cpuidle_params_table [ OMAP3_STATE_C2 ] . wake_latency ;
omap3_power_states [ OMAP3_STATE_C2 ] . threshold =
cpuidle_params_table [ OMAP3_STATE_C2 ] . threshold ;
2009-03-13 19:19:16 +03:00
omap3_power_states [ OMAP3_STATE_C2 ] . mpu_state = PWRDM_POWER_ON ;
2008-10-08 16:00:58 +04:00
omap3_power_states [ OMAP3_STATE_C2 ] . core_state = PWRDM_POWER_ON ;
2010-09-09 03:37:42 +04:00
omap3_power_states [ OMAP3_STATE_C2 ] . flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM ;
2011-02-11 18:12:12 +03:00
omap3_power_states [ OMAP3_STATE_C2 ] . desc = " MPU ON + CORE ON " ;
2008-10-08 16:00:58 +04:00
2009-03-13 19:19:16 +03:00
/* C3 . MPU CSWR + Core inactive */
2009-10-29 11:30:19 +03:00
omap3_power_states [ OMAP3_STATE_C3 ] . valid =
cpuidle_params_table [ OMAP3_STATE_C3 ] . valid ;
2008-10-08 16:00:58 +04:00
omap3_power_states [ OMAP3_STATE_C3 ] . type = OMAP3_STATE_C3 ;
2009-12-16 03:37:18 +03:00
omap3_power_states [ OMAP3_STATE_C3 ] . sleep_latency =
cpuidle_params_table [ OMAP3_STATE_C3 ] . sleep_latency ;
omap3_power_states [ OMAP3_STATE_C3 ] . wakeup_latency =
cpuidle_params_table [ OMAP3_STATE_C3 ] . wake_latency ;
omap3_power_states [ OMAP3_STATE_C3 ] . threshold =
cpuidle_params_table [ OMAP3_STATE_C3 ] . threshold ;
2009-03-13 19:19:16 +03:00
omap3_power_states [ OMAP3_STATE_C3 ] . mpu_state = PWRDM_POWER_RET ;
2008-10-08 16:00:58 +04:00
omap3_power_states [ OMAP3_STATE_C3 ] . core_state = PWRDM_POWER_ON ;
2008-10-29 03:32:11 +03:00
omap3_power_states [ OMAP3_STATE_C3 ] . flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM ;
2011-02-11 18:12:12 +03:00
omap3_power_states [ OMAP3_STATE_C3 ] . desc = " MPU RET + CORE ON " ;
2008-10-08 16:00:58 +04:00
2009-03-13 19:19:16 +03:00
/* C4 . MPU OFF + Core inactive */
2009-10-29 11:30:19 +03:00
omap3_power_states [ OMAP3_STATE_C4 ] . valid =
cpuidle_params_table [ OMAP3_STATE_C4 ] . valid ;
2008-10-08 16:00:58 +04:00
omap3_power_states [ OMAP3_STATE_C4 ] . type = OMAP3_STATE_C4 ;
2009-12-16 03:37:18 +03:00
omap3_power_states [ OMAP3_STATE_C4 ] . sleep_latency =
cpuidle_params_table [ OMAP3_STATE_C4 ] . sleep_latency ;
omap3_power_states [ OMAP3_STATE_C4 ] . wakeup_latency =
cpuidle_params_table [ OMAP3_STATE_C4 ] . wake_latency ;
omap3_power_states [ OMAP3_STATE_C4 ] . threshold =
cpuidle_params_table [ OMAP3_STATE_C4 ] . threshold ;
2009-03-13 19:19:16 +03:00
omap3_power_states [ OMAP3_STATE_C4 ] . mpu_state = PWRDM_POWER_OFF ;
omap3_power_states [ OMAP3_STATE_C4 ] . core_state = PWRDM_POWER_ON ;
2008-10-08 16:00:58 +04:00
omap3_power_states [ OMAP3_STATE_C4 ] . flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM ;
2011-02-11 18:12:12 +03:00
omap3_power_states [ OMAP3_STATE_C4 ] . desc = " MPU OFF + CORE ON " ;
2008-10-08 16:00:58 +04:00
2009-03-13 19:19:16 +03:00
/* C5 . MPU CSWR + Core CSWR*/
2009-10-29 11:30:19 +03:00
omap3_power_states [ OMAP3_STATE_C5 ] . valid =
cpuidle_params_table [ OMAP3_STATE_C5 ] . valid ;
2008-10-08 16:00:58 +04:00
omap3_power_states [ OMAP3_STATE_C5 ] . type = OMAP3_STATE_C5 ;
2009-12-16 03:37:18 +03:00
omap3_power_states [ OMAP3_STATE_C5 ] . sleep_latency =
cpuidle_params_table [ OMAP3_STATE_C5 ] . sleep_latency ;
omap3_power_states [ OMAP3_STATE_C5 ] . wakeup_latency =
cpuidle_params_table [ OMAP3_STATE_C5 ] . wake_latency ;
omap3_power_states [ OMAP3_STATE_C5 ] . threshold =
cpuidle_params_table [ OMAP3_STATE_C5 ] . threshold ;
2009-03-13 19:19:16 +03:00
omap3_power_states [ OMAP3_STATE_C5 ] . mpu_state = PWRDM_POWER_RET ;
2008-10-08 16:00:58 +04:00
omap3_power_states [ OMAP3_STATE_C5 ] . core_state = PWRDM_POWER_RET ;
omap3_power_states [ OMAP3_STATE_C5 ] . flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM ;
2011-02-11 18:12:12 +03:00
omap3_power_states [ OMAP3_STATE_C5 ] . desc = " MPU RET + CORE RET " ;
2008-10-08 16:00:58 +04:00
2009-03-13 19:19:16 +03:00
/* C6 . MPU OFF + Core CSWR */
2009-10-29 11:30:19 +03:00
omap3_power_states [ OMAP3_STATE_C6 ] . valid =
cpuidle_params_table [ OMAP3_STATE_C6 ] . valid ;
2008-10-08 16:00:58 +04:00
omap3_power_states [ OMAP3_STATE_C6 ] . type = OMAP3_STATE_C6 ;
2009-12-16 03:37:18 +03:00
omap3_power_states [ OMAP3_STATE_C6 ] . sleep_latency =
cpuidle_params_table [ OMAP3_STATE_C6 ] . sleep_latency ;
omap3_power_states [ OMAP3_STATE_C6 ] . wakeup_latency =
cpuidle_params_table [ OMAP3_STATE_C6 ] . wake_latency ;
omap3_power_states [ OMAP3_STATE_C6 ] . threshold =
cpuidle_params_table [ OMAP3_STATE_C6 ] . threshold ;
2008-10-08 16:00:58 +04:00
omap3_power_states [ OMAP3_STATE_C6 ] . mpu_state = PWRDM_POWER_OFF ;
2009-03-13 19:19:16 +03:00
omap3_power_states [ OMAP3_STATE_C6 ] . core_state = PWRDM_POWER_RET ;
2008-10-08 16:00:58 +04:00
omap3_power_states [ OMAP3_STATE_C6 ] . flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM ;
2011-02-11 18:12:12 +03:00
omap3_power_states [ OMAP3_STATE_C6 ] . desc = " MPU OFF + CORE RET " ;
2009-03-13 19:19:16 +03:00
/* C7 . MPU OFF + Core OFF */
2009-10-29 11:30:19 +03:00
omap3_power_states [ OMAP3_STATE_C7 ] . valid =
cpuidle_params_table [ OMAP3_STATE_C7 ] . valid ;
2009-03-13 19:19:16 +03:00
omap3_power_states [ OMAP3_STATE_C7 ] . type = OMAP3_STATE_C7 ;
2009-12-16 03:37:18 +03:00
omap3_power_states [ OMAP3_STATE_C7 ] . sleep_latency =
cpuidle_params_table [ OMAP3_STATE_C7 ] . sleep_latency ;
omap3_power_states [ OMAP3_STATE_C7 ] . wakeup_latency =
cpuidle_params_table [ OMAP3_STATE_C7 ] . wake_latency ;
omap3_power_states [ OMAP3_STATE_C7 ] . threshold =
cpuidle_params_table [ OMAP3_STATE_C7 ] . threshold ;
2009-03-13 19:19:16 +03:00
omap3_power_states [ OMAP3_STATE_C7 ] . mpu_state = PWRDM_POWER_OFF ;
omap3_power_states [ OMAP3_STATE_C7 ] . core_state = PWRDM_POWER_OFF ;
omap3_power_states [ OMAP3_STATE_C7 ] . flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM ;
2011-02-11 18:12:12 +03:00
omap3_power_states [ OMAP3_STATE_C7 ] . desc = " MPU OFF + CORE OFF " ;
2010-12-20 23:05:09 +03:00
/*
* Erratum i583 : implementation for ES rev < Es1 .2 on 3630. We cannot
* enable OFF mode in a stable form for previous revisions .
* we disable C7 state as a result .
*/
if ( IS_PM34XX_ERRATUM ( PM_SDRC_WAKEUP_ERRATUM_i583 ) ) {
omap3_power_states [ OMAP3_STATE_C7 ] . valid = 0 ;
cpuidle_params_table [ OMAP3_STATE_C7 ] . valid = 0 ;
2011-01-31 16:35:25 +03:00
pr_warn ( " %s: core off state C7 disabled due to i583 \n " ,
2010-12-20 23:05:09 +03:00
__func__ ) ;
}
2008-10-08 16:00:58 +04:00
}
struct cpuidle_driver omap3_idle_driver = {
. name = " omap3_idle " ,
. owner = THIS_MODULE ,
} ;
/**
* omap3_idle_init - Init routine for OMAP3 idle
*
* Registers the OMAP3 specific cpuidle driver with the cpuidle
* framework with the valid set of states .
*/
2008-09-26 12:04:20 +04:00
int __init omap3_idle_init ( void )
2008-10-08 16:00:58 +04:00
{
int i , count = 0 ;
struct omap3_processor_cx * cx ;
struct cpuidle_state * state ;
struct cpuidle_device * dev ;
mpu_pd = pwrdm_lookup ( " mpu_pwrdm " ) ;
2008-10-08 16:01:22 +04:00
core_pd = pwrdm_lookup ( " core_pwrdm " ) ;
2010-09-09 03:37:42 +04:00
per_pd = pwrdm_lookup ( " per_pwrdm " ) ;
cam_pd = pwrdm_lookup ( " cam_pwrdm " ) ;
2008-10-08 16:00:58 +04:00
omap_init_power_states ( ) ;
cpuidle_register_driver ( & omap3_idle_driver ) ;
dev = & per_cpu ( omap3_idle_dev , smp_processor_id ( ) ) ;
2009-03-13 19:04:25 +03:00
for ( i = OMAP3_STATE_C1 ; i < OMAP3_MAX_STATES ; i + + ) {
2008-10-08 16:00:58 +04:00
cx = & omap3_power_states [ i ] ;
state = & dev - > states [ count ] ;
if ( ! cx - > valid )
continue ;
cpuidle_set_statedata ( state , cx ) ;
state - > exit_latency = cx - > sleep_latency + cx - > wakeup_latency ;
state - > target_residency = cx - > threshold ;
state - > flags = cx - > flags ;
state - > enter = ( state - > flags & CPUIDLE_FLAG_CHECK_BM ) ?
omap3_enter_idle_bm : omap3_enter_idle ;
if ( cx - > type = = OMAP3_STATE_C1 )
dev - > safe_state = state ;
sprintf ( state - > name , " C%d " , count + 1 ) ;
2011-02-11 18:12:12 +03:00
strncpy ( state - > desc , cx - > desc , CPUIDLE_DESC_LEN ) ;
2008-10-08 16:00:58 +04:00
count + + ;
}
if ( ! count )
return - EINVAL ;
dev - > state_count = count ;
2010-12-20 23:05:08 +03:00
if ( enable_off_mode )
omap3_cpuidle_update_states ( PWRDM_POWER_OFF , PWRDM_POWER_OFF ) ;
else
omap3_cpuidle_update_states ( PWRDM_POWER_RET , PWRDM_POWER_RET ) ;
2010-01-28 20:46:43 +03:00
2008-10-08 16:00:58 +04:00
if ( cpuidle_register_device ( dev ) ) {
printk ( KERN_ERR " %s: CPUidle register device failed \n " ,
__func__ ) ;
return - EIO ;
}
return 0 ;
}
2008-09-26 12:04:20 +04:00
# else
int __init omap3_idle_init ( void )
{
return 0 ;
}
2008-10-08 16:00:58 +04:00
# endif /* CONFIG_CPU_IDLE */