2008-08-19 12:08:40 +04:00
/*
* OMAP powerdomain control
*
2011-09-15 02:01:21 +04:00
* Copyright ( C ) 2007 - 2008 , 2011 Texas Instruments , Inc .
2011-03-08 05:28:15 +03:00
* Copyright ( C ) 2007 - 2011 Nokia Corporation
2008-08-19 12:08:40 +04:00
*
* Written by Paul Walmsley
2010-01-27 06:12:53 +03:00
* Added OMAP4 specific support by Abhijit Pagare < abhijitpagare @ ti . com >
2010-05-19 06:24:05 +04:00
* State counting code by Tero Kristo < tero . kristo @ nokia . com >
2010-01-27 06:12:53 +03:00
*
2008-08-19 12:08:40 +04:00
* 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-12-09 02:33:10 +03:00
# undef DEBUG
2008-08-19 12:08:40 +04:00
# include <linux/kernel.h>
# include <linux/types.h>
# include <linux/list.h>
# include <linux/errno.h>
2010-12-22 06:01:19 +03:00
# include <linux/string.h>
2011-03-03 13:25:43 +03:00
# include <trace/events/power.h>
2010-12-22 01:30:55 +03:00
# include "cm2xxx_3xxx.h"
2010-12-22 07:05:14 +03:00
# include "prcm44xx.h"
2010-12-22 01:30:55 +03:00
# include "cm44xx.h"
# include "prm2xxx_3xxx.h"
2010-12-22 01:30:54 +03:00
# include "prm44xx.h"
2008-08-19 12:08:40 +04:00
2011-03-03 13:25:43 +03:00
# include <asm/cpu.h>
2012-08-31 21:59:07 +04:00
2010-12-22 07:05:16 +03:00
# include "powerdomain.h"
2010-12-22 07:05:15 +03:00
# include "clockdomain.h"
2008-08-19 12:08:40 +04:00
2012-08-31 21:59:07 +04:00
# include "soc.h"
2008-10-15 19:13:49 +04:00
# include "pm.h"
2011-03-03 13:25:43 +03:00
# define PWRDM_TRACE_STATES_FLAG (1<<31)
2008-10-15 18:48:43 +04:00
enum {
PWRDM_STATE_NOW = 0 ,
PWRDM_STATE_PREV ,
} ;
2010-01-27 06:12:53 +03:00
2008-08-19 12:08:40 +04:00
/* pwrdm_list contains all registered struct powerdomains */
static LIST_HEAD ( pwrdm_list ) ;
2010-12-22 06:01:18 +03:00
static struct pwrdm_ops * arch_pwrdm ;
2008-08-19 12:08:40 +04:00
/* Private functions */
static struct powerdomain * _pwrdm_lookup ( const char * name )
{
struct powerdomain * pwrdm , * temp_pwrdm ;
pwrdm = NULL ;
list_for_each_entry ( temp_pwrdm , & pwrdm_list , node ) {
if ( ! strcmp ( name , temp_pwrdm - > name ) ) {
pwrdm = temp_pwrdm ;
break ;
}
}
return pwrdm ;
}
2010-01-27 06:13:00 +03:00
/**
* _pwrdm_register - register a powerdomain
* @ pwrdm : struct powerdomain * to register
*
* Adds a powerdomain to the internal powerdomain list . Returns
* - EINVAL if given a null pointer , - EEXIST if a powerdomain is
* already registered by the provided name , or 0 upon success .
*/
static int _pwrdm_register ( struct powerdomain * pwrdm )
{
int i ;
2011-03-17 01:52:47 +03:00
struct voltagedomain * voltdm ;
2010-01-27 06:13:00 +03:00
2010-12-22 07:05:14 +03:00
if ( ! pwrdm | | ! pwrdm - > name )
2010-01-27 06:13:00 +03:00
return - EINVAL ;
2010-12-22 07:05:14 +03:00
if ( cpu_is_omap44xx ( ) & &
pwrdm - > prcm_partition = = OMAP4430_INVALID_PRCM_PARTITION ) {
pr_err ( " powerdomain: %s: missing OMAP4 PRCM partition ID \n " ,
pwrdm - > name ) ;
return - EINVAL ;
}
2010-01-27 06:13:00 +03:00
if ( _pwrdm_lookup ( pwrdm - > name ) )
return - EEXIST ;
2011-03-17 01:52:47 +03:00
voltdm = voltdm_lookup ( pwrdm - > voltdm . name ) ;
if ( ! voltdm ) {
pr_err ( " powerdomain: %s: voltagedomain %s does not exist \n " ,
pwrdm - > name , pwrdm - > voltdm . name ) ;
return - EINVAL ;
}
pwrdm - > voltdm . ptr = voltdm ;
2011-03-17 02:13:15 +03:00
INIT_LIST_HEAD ( & pwrdm - > voltdm_node ) ;
voltdm_add_pwrdm ( voltdm , pwrdm ) ;
2011-03-17 01:52:47 +03:00
2010-01-27 06:13:00 +03:00
list_add ( & pwrdm - > node , & pwrdm_list ) ;
/* Initialize the powerdomain's state counter */
2010-01-27 06:13:01 +03:00
for ( i = 0 ; i < PWRDM_MAX_PWRSTS ; i + + )
2010-01-27 06:13:00 +03:00
pwrdm - > state_counter [ i ] = 0 ;
2010-02-24 22:05:50 +03:00
pwrdm - > ret_logic_off_counter = 0 ;
for ( i = 0 ; i < pwrdm - > banks ; i + + )
pwrdm - > ret_mem_off_counter [ i ] = 0 ;
2010-01-27 06:13:00 +03:00
pwrdm_wait_transition ( pwrdm ) ;
pwrdm - > state = pwrdm_read_pwrst ( pwrdm ) ;
pwrdm - > state_counter [ pwrdm - > state ] = 1 ;
pr_debug ( " powerdomain: registered %s \n " , pwrdm - > name ) ;
return 0 ;
}
2010-02-24 22:05:50 +03:00
static void _update_logic_membank_counters ( struct powerdomain * pwrdm )
{
int i ;
u8 prev_logic_pwrst , prev_mem_pwrst ;
prev_logic_pwrst = pwrdm_read_prev_logic_pwrst ( pwrdm ) ;
if ( ( pwrdm - > pwrsts_logic_ret = = PWRSTS_OFF_RET ) & &
( prev_logic_pwrst = = PWRDM_POWER_OFF ) )
pwrdm - > ret_logic_off_counter + + ;
for ( i = 0 ; i < pwrdm - > banks ; i + + ) {
prev_mem_pwrst = pwrdm_read_prev_mem_pwrst ( pwrdm , i ) ;
if ( ( pwrdm - > pwrsts_mem_ret [ i ] = = PWRSTS_OFF_RET ) & &
( prev_mem_pwrst = = PWRDM_POWER_OFF ) )
pwrdm - > ret_mem_off_counter [ i ] + + ;
}
}
2008-10-15 18:48:43 +04:00
static int _pwrdm_state_switch ( struct powerdomain * pwrdm , int flag )
{
2011-03-03 13:25:43 +03:00
int prev , state , trace_state = 0 ;
2008-10-15 18:48:43 +04:00
if ( pwrdm = = NULL )
return - EINVAL ;
state = pwrdm_read_pwrst ( pwrdm ) ;
switch ( flag ) {
case PWRDM_STATE_NOW :
prev = pwrdm - > state ;
break ;
case PWRDM_STATE_PREV :
prev = pwrdm_read_prev_pwrst ( pwrdm ) ;
if ( pwrdm - > state ! = prev )
pwrdm - > state_counter [ prev ] + + ;
2010-02-24 22:05:50 +03:00
if ( prev = = PWRDM_POWER_RET )
_update_logic_membank_counters ( pwrdm ) ;
2011-03-03 13:25:43 +03:00
/*
* If the power domain did not hit the desired state ,
* generate a trace event with both the desired and hit states
*/
if ( state ! = prev ) {
trace_state = ( PWRDM_TRACE_STATES_FLAG |
( ( state & OMAP_POWERSTATE_MASK ) < < 8 ) |
( ( prev & OMAP_POWERSTATE_MASK ) < < 0 ) ) ;
trace_power_domain_target ( pwrdm - > name , trace_state ,
smp_processor_id ( ) ) ;
}
2008-10-15 18:48:43 +04:00
break ;
default :
return - EINVAL ;
}
if ( state ! = prev )
pwrdm - > state_counter [ state ] + + ;
2008-10-15 19:13:49 +04:00
pm_dbg_update_time ( pwrdm , prev ) ;
2008-10-15 18:48:43 +04:00
pwrdm - > state = state ;
return 0 ;
}
2008-10-15 19:13:49 +04:00
static int _pwrdm_pre_transition_cb ( struct powerdomain * pwrdm , void * unused )
2008-10-15 18:48:43 +04:00
{
pwrdm_clear_all_prev_pwrst ( pwrdm ) ;
_pwrdm_state_switch ( pwrdm , PWRDM_STATE_NOW ) ;
return 0 ;
}
2008-10-15 19:13:49 +04:00
static int _pwrdm_post_transition_cb ( struct powerdomain * pwrdm , void * unused )
2008-10-15 18:48:43 +04:00
{
_pwrdm_state_switch ( pwrdm , PWRDM_STATE_PREV ) ;
return 0 ;
}
2008-08-19 12:08:40 +04:00
/* Public functions */
/**
2011-09-15 02:01:21 +04:00
* pwrdm_register_platform_funcs - register powerdomain implementation fns
* @ po : func pointers for arch specific implementations
2008-08-19 12:08:40 +04:00
*
2011-09-15 02:01:21 +04:00
* Register the list of function pointers used to implement the
* powerdomain functions on different OMAP SoCs . Should be called
* before any other pwrdm_register * ( ) function . Returns - EINVAL if
* @ po is null , - EEXIST if platform functions have already been
* registered , or 0 upon success .
2008-08-19 12:08:40 +04:00
*/
2011-09-15 02:01:21 +04:00
int pwrdm_register_platform_funcs ( struct pwrdm_ops * po )
{
if ( ! po )
return - EINVAL ;
if ( arch_pwrdm )
return - EEXIST ;
arch_pwrdm = po ;
return 0 ;
}
/**
* pwrdm_register_pwrdms - register SoC powerdomains
* @ ps : pointer to an array of struct powerdomain to register
*
* Register the powerdomains available on a particular OMAP SoC . Must
* be called after pwrdm_register_platform_funcs ( ) . May be called
* multiple times . Returns - EACCES if called before
* pwrdm_register_platform_funcs ( ) ; - EINVAL if the argument @ ps is
* null ; or 0 upon success .
*/
int pwrdm_register_pwrdms ( struct powerdomain * * ps )
2008-08-19 12:08:40 +04:00
{
struct powerdomain * * p = NULL ;
2011-09-15 02:01:21 +04:00
if ( ! arch_pwrdm )
return - EEXIST ;
2010-12-22 06:01:18 +03:00
2011-09-15 02:01:21 +04:00
if ( ! ps )
return - EINVAL ;
for ( p = ps ; * p ; p + + )
_pwrdm_register ( * p ) ;
return 0 ;
}
/**
* pwrdm_complete_init - set up the powerdomain layer
*
* Do whatever is necessary to initialize registered powerdomains and
* powerdomain code . Currently , this programs the next power state
* for each powerdomain to ON . This prevents powerdomains from
* unexpectedly losing context or entering high wakeup latency modes
* with non - power - management - enabled kernels . Must be called after
* pwrdm_register_pwrdms ( ) . Returns - EACCES if called before
* pwrdm_register_pwrdms ( ) , or 0 upon success .
*/
int pwrdm_complete_init ( void )
{
struct powerdomain * temp_p ;
if ( list_empty ( & pwrdm_list ) )
return - EACCES ;
2011-08-20 02:59:39 +04:00
list_for_each_entry ( temp_p , & pwrdm_list , node )
pwrdm_set_next_pwrst ( temp_p , PWRDM_POWER_ON ) ;
2011-09-15 02:01:21 +04:00
return 0 ;
2008-08-19 12:08:40 +04:00
}
/**
* pwrdm_lookup - look up a powerdomain by name , return a pointer
* @ name : name of powerdomain
*
2010-01-27 06:13:02 +03:00
* Find a registered powerdomain by its name @ name . Returns a pointer
* to the struct powerdomain if found , or NULL otherwise .
2008-08-19 12:08:40 +04:00
*/
struct powerdomain * pwrdm_lookup ( const char * name )
{
struct powerdomain * pwrdm ;
if ( ! name )
return NULL ;
pwrdm = _pwrdm_lookup ( name ) ;
return pwrdm ;
}
/**
2010-01-27 06:13:00 +03:00
* pwrdm_for_each - call function on each registered clockdomain
2008-08-19 12:08:40 +04:00
* @ fn : callback function *
*
2010-01-27 06:13:02 +03:00
* Call the supplied function @ fn for each registered powerdomain .
* The callback function @ fn can return anything but 0 to bail out
* early from the iterator . Returns the last return value of the
* callback function , which should be 0 for success or anything else
* to indicate failure ; or - EINVAL if the function pointer is null .
2008-08-19 12:08:40 +04:00
*/
2010-01-27 06:13:00 +03:00
int pwrdm_for_each ( int ( * fn ) ( struct powerdomain * pwrdm , void * user ) ,
void * user )
2008-08-19 12:08:40 +04:00
{
struct powerdomain * temp_pwrdm ;
int ret = 0 ;
if ( ! fn )
return - EINVAL ;
list_for_each_entry ( temp_pwrdm , & pwrdm_list , node ) {
2008-10-15 19:13:49 +04:00
ret = ( * fn ) ( temp_pwrdm , user ) ;
2008-08-19 12:08:40 +04:00
if ( ret )
break ;
}
2009-10-01 11:01:55 +04:00
return ret ;
}
2008-08-19 12:08:44 +04:00
/**
* pwrdm_add_clkdm - add a clockdomain to a powerdomain
* @ pwrdm : struct powerdomain * to add the clockdomain to
* @ clkdm : struct clockdomain * to associate with a powerdomain
*
2010-01-27 06:13:02 +03:00
* Associate the clockdomain @ clkdm with a powerdomain @ pwrdm . This
2008-08-19 12:08:44 +04:00
* enables the use of pwrdm_for_each_clkdm ( ) . Returns - EINVAL if
* presented with invalid pointers ; - ENOMEM if memory could not be allocated ;
* or 0 upon success .
*/
int pwrdm_add_clkdm ( struct powerdomain * pwrdm , struct clockdomain * clkdm )
{
int i ;
int ret = - EINVAL ;
if ( ! pwrdm | | ! clkdm )
return - EINVAL ;
2012-07-26 10:54:26 +04:00
pr_debug ( " powerdomain: %s: associating clockdomain %s \n " ,
pwrdm - > name , clkdm - > name ) ;
2008-08-19 12:08:44 +04:00
for ( i = 0 ; i < PWRDM_MAX_CLKDMS ; i + + ) {
if ( ! pwrdm - > pwrdm_clkdms [ i ] )
break ;
# ifdef DEBUG
if ( pwrdm - > pwrdm_clkdms [ i ] = = clkdm ) {
ret = - EINVAL ;
goto pac_exit ;
}
# endif
}
if ( i = = PWRDM_MAX_CLKDMS ) {
2012-07-26 10:54:26 +04:00
pr_debug ( " powerdomain: %s: increase PWRDM_MAX_CLKDMS for clkdm %s \n " ,
pwrdm - > name , clkdm - > name ) ;
2008-08-19 12:08:44 +04:00
WARN_ON ( 1 ) ;
ret = - ENOMEM ;
goto pac_exit ;
}
pwrdm - > pwrdm_clkdms [ i ] = clkdm ;
ret = 0 ;
pac_exit :
return ret ;
}
/**
* pwrdm_del_clkdm - remove a clockdomain from a powerdomain
* @ pwrdm : struct powerdomain * to add the clockdomain to
* @ clkdm : struct clockdomain * to associate with a powerdomain
*
2010-01-27 06:13:02 +03:00
* Dissociate the clockdomain @ clkdm from the powerdomain
* @ pwrdm . Returns - EINVAL if presented with invalid pointers ; - ENOENT
* if @ clkdm was not associated with the powerdomain , or 0 upon
* success .
2008-08-19 12:08:44 +04:00
*/
int pwrdm_del_clkdm ( struct powerdomain * pwrdm , struct clockdomain * clkdm )
{
int ret = - EINVAL ;
int i ;
if ( ! pwrdm | | ! clkdm )
return - EINVAL ;
2012-07-26 10:54:26 +04:00
pr_debug ( " powerdomain: %s: dissociating clockdomain %s \n " ,
pwrdm - > name , clkdm - > name ) ;
2008-08-19 12:08:44 +04:00
for ( i = 0 ; i < PWRDM_MAX_CLKDMS ; i + + )
if ( pwrdm - > pwrdm_clkdms [ i ] = = clkdm )
break ;
if ( i = = PWRDM_MAX_CLKDMS ) {
2012-07-26 10:54:26 +04:00
pr_debug ( " powerdomain: %s: clkdm %s not associated?! \n " ,
pwrdm - > name , clkdm - > name ) ;
2008-08-19 12:08:44 +04:00
ret = - ENOENT ;
goto pdc_exit ;
}
pwrdm - > pwrdm_clkdms [ i ] = NULL ;
ret = 0 ;
pdc_exit :
return ret ;
}
/**
* pwrdm_for_each_clkdm - call function on each clkdm in a pwrdm
* @ pwrdm : struct powerdomain * to iterate over
* @ fn : callback function *
*
2010-01-27 06:13:02 +03:00
* Call the supplied function @ fn for each clockdomain in the powerdomain
* @ pwrdm . The callback function can return anything but 0 to bail
2010-01-27 06:13:00 +03:00
* out early from the iterator . Returns - EINVAL if presented with
* invalid pointers ; or passes along the last return value of the
* callback function , which should be 0 for success or anything else
* to indicate failure .
2008-08-19 12:08:44 +04:00
*/
int pwrdm_for_each_clkdm ( struct powerdomain * pwrdm ,
int ( * fn ) ( struct powerdomain * pwrdm ,
struct clockdomain * clkdm ) )
{
int ret = 0 ;
int i ;
if ( ! fn )
return - EINVAL ;
for ( i = 0 ; i < PWRDM_MAX_CLKDMS & & ! ret ; i + + )
ret = ( * fn ) ( pwrdm , pwrdm - > pwrdm_clkdms [ i ] ) ;
return ret ;
}
2011-03-17 01:52:47 +03:00
/**
* pwrdm_get_voltdm - return a ptr to the voltdm that this pwrdm resides in
* @ pwrdm : struct powerdomain *
*
* Return a pointer to the struct voltageomain that the specified powerdomain
* @ pwrdm exists in .
*/
struct voltagedomain * pwrdm_get_voltdm ( struct powerdomain * pwrdm )
{
return pwrdm - > voltdm . ptr ;
}
2008-08-19 12:08:40 +04:00
/**
* pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain
* @ pwrdm : struct powerdomain *
*
2010-01-27 06:13:02 +03:00
* Return the number of controllable memory banks in powerdomain @ pwrdm ,
2008-08-19 12:08:40 +04:00
* starting with 1. Returns - EINVAL if the powerdomain pointer is null .
*/
int pwrdm_get_mem_bank_count ( struct powerdomain * pwrdm )
{
if ( ! pwrdm )
return - EINVAL ;
return pwrdm - > banks ;
}
/**
* pwrdm_set_next_pwrst - set next powerdomain power state
* @ pwrdm : struct powerdomain * to set
* @ pwrst : one of the PWRDM_POWER_ * macros
*
2010-01-27 06:13:02 +03:00
* Set the powerdomain @ pwrdm ' s next power state to @ pwrst . The powerdomain
2008-08-19 12:08:40 +04:00
* may not enter this state immediately if the preconditions for this state
* have not been satisfied . Returns - EINVAL if the powerdomain pointer is
* null or if the power state is invalid for the powerdomin , or returns 0
* upon success .
*/
int pwrdm_set_next_pwrst ( struct powerdomain * pwrdm , u8 pwrst )
{
2010-12-22 06:01:18 +03:00
int ret = - EINVAL ;
2008-08-19 12:08:40 +04:00
if ( ! pwrdm )
return - EINVAL ;
if ( ! ( pwrdm - > pwrsts & ( 1 < < pwrst ) ) )
return - EINVAL ;
2012-07-26 10:54:26 +04:00
pr_debug ( " powerdomain: %s: setting next powerstate to %0x \n " ,
2008-08-19 12:08:40 +04:00
pwrdm - > name , pwrst ) ;
2011-03-03 13:25:43 +03:00
if ( arch_pwrdm & & arch_pwrdm - > pwrdm_set_next_pwrst ) {
/* Trace the pwrdm desired target state */
trace_power_domain_target ( pwrdm - > name , pwrst ,
smp_processor_id ( ) ) ;
/* Program the pwrdm desired target state */
2010-12-22 06:01:18 +03:00
ret = arch_pwrdm - > pwrdm_set_next_pwrst ( pwrdm , pwrst ) ;
2011-03-03 13:25:43 +03:00
}
2008-08-19 12:08:40 +04:00
2010-12-22 06:01:18 +03:00
return ret ;
2008-08-19 12:08:40 +04:00
}
/**
* pwrdm_read_next_pwrst - get next powerdomain power state
* @ pwrdm : struct powerdomain * to get power state
*
2010-01-27 06:13:02 +03:00
* Return the powerdomain @ pwrdm ' s next power state . Returns - EINVAL
2008-08-19 12:08:40 +04:00
* if the powerdomain pointer is null or returns the next power state
* upon success .
*/
int pwrdm_read_next_pwrst ( struct powerdomain * pwrdm )
{
2010-12-22 06:01:18 +03:00
int ret = - EINVAL ;
2008-08-19 12:08:40 +04:00
if ( ! pwrdm )
return - EINVAL ;
2010-12-22 06:01:18 +03:00
if ( arch_pwrdm & & arch_pwrdm - > pwrdm_read_next_pwrst )
ret = arch_pwrdm - > pwrdm_read_next_pwrst ( pwrdm ) ;
return ret ;
2008-08-19 12:08:40 +04:00
}
/**
* pwrdm_read_pwrst - get current powerdomain power state
* @ pwrdm : struct powerdomain * to get power state
*
2010-01-27 06:13:02 +03:00
* Return the powerdomain @ pwrdm ' s current power state . Returns - EINVAL
2008-08-19 12:08:40 +04:00
* if the powerdomain pointer is null or returns the current power state
2012-06-30 01:04:52 +04:00
* upon success . Note that if the power domain only supports the ON state
* then just return ON as the current state .
2008-08-19 12:08:40 +04:00
*/
int pwrdm_read_pwrst ( struct powerdomain * pwrdm )
{
2010-12-22 06:01:18 +03:00
int ret = - EINVAL ;
2008-08-19 12:08:40 +04:00
if ( ! pwrdm )
return - EINVAL ;
2012-06-30 01:04:52 +04:00
if ( pwrdm - > pwrsts = = PWRSTS_ON )
return PWRDM_POWER_ON ;
2010-12-22 06:01:18 +03:00
if ( arch_pwrdm & & arch_pwrdm - > pwrdm_read_pwrst )
ret = arch_pwrdm - > pwrdm_read_pwrst ( pwrdm ) ;
return ret ;
2008-08-19 12:08:40 +04:00
}
/**
* pwrdm_read_prev_pwrst - get previous powerdomain power state
* @ pwrdm : struct powerdomain * to get previous power state
*
2010-01-27 06:13:02 +03:00
* Return the powerdomain @ pwrdm ' s previous power state . Returns - EINVAL
2008-08-19 12:08:40 +04:00
* if the powerdomain pointer is null or returns the previous power state
* upon success .
*/
int pwrdm_read_prev_pwrst ( struct powerdomain * pwrdm )
{
2010-12-22 06:01:18 +03:00
int ret = - EINVAL ;
2008-08-19 12:08:40 +04:00
if ( ! pwrdm )
return - EINVAL ;
2010-12-22 06:01:18 +03:00
if ( arch_pwrdm & & arch_pwrdm - > pwrdm_read_prev_pwrst )
ret = arch_pwrdm - > pwrdm_read_prev_pwrst ( pwrdm ) ;
return ret ;
2008-08-19 12:08:40 +04:00
}
/**
* pwrdm_set_logic_retst - set powerdomain logic power state upon retention
* @ pwrdm : struct powerdomain * to set
* @ pwrst : one of the PWRDM_POWER_ * macros
*
2010-01-27 06:13:02 +03:00
* Set the next power state @ pwrst that the logic portion of the
* powerdomain @ pwrdm will enter when the powerdomain enters retention .
* This will be either RETENTION or OFF , if supported . Returns
* - EINVAL if the powerdomain pointer is null or the target power
* state is not not supported , or returns 0 upon success .
2008-08-19 12:08:40 +04:00
*/
int pwrdm_set_logic_retst ( struct powerdomain * pwrdm , u8 pwrst )
{
2010-12-22 06:01:18 +03:00
int ret = - EINVAL ;
2010-05-19 04:47:24 +04:00
2008-08-19 12:08:40 +04:00
if ( ! pwrdm )
return - EINVAL ;
if ( ! ( pwrdm - > pwrsts_logic_ret & ( 1 < < pwrst ) ) )
return - EINVAL ;
2012-07-26 10:54:26 +04:00
pr_debug ( " powerdomain: %s: setting next logic powerstate to %0x \n " ,
2008-08-19 12:08:40 +04:00
pwrdm - > name , pwrst ) ;
2010-12-22 06:01:18 +03:00
if ( arch_pwrdm & & arch_pwrdm - > pwrdm_set_logic_retst )
ret = arch_pwrdm - > pwrdm_set_logic_retst ( pwrdm , pwrst ) ;
2008-08-19 12:08:40 +04:00
2010-12-22 06:01:18 +03:00
return ret ;
2008-08-19 12:08:40 +04:00
}
/**
* pwrdm_set_mem_onst - set memory power state while powerdomain ON
* @ pwrdm : struct powerdomain * to set
* @ bank : memory bank number to set ( 0 - 3 )
* @ pwrst : one of the PWRDM_POWER_ * macros
*
2010-01-27 06:13:02 +03:00
* Set the next power state @ pwrst that memory bank @ bank of the
* powerdomain @ pwrdm will enter when the powerdomain enters the ON
* state . @ bank will be a number from 0 to 3 , and represents different
* types of memory , depending on the powerdomain . Returns - EINVAL if
* the powerdomain pointer is null or the target power state is not
* not supported for this memory bank , - EEXIST if the target memory
* bank does not exist or is not controllable , or returns 0 upon
* success .
2008-08-19 12:08:40 +04:00
*/
int pwrdm_set_mem_onst ( struct powerdomain * pwrdm , u8 bank , u8 pwrst )
{
2010-12-22 06:01:19 +03:00
int ret = - EINVAL ;
2008-08-19 12:08:40 +04:00
if ( ! pwrdm )
return - EINVAL ;
if ( pwrdm - > banks < ( bank + 1 ) )
return - EEXIST ;
if ( ! ( pwrdm - > pwrsts_mem_on [ bank ] & ( 1 < < pwrst ) ) )
return - EINVAL ;
2012-07-26 10:54:26 +04:00
pr_debug ( " powerdomain: %s: setting next memory powerstate for bank %0x while pwrdm-ON to %0x \n " ,
pwrdm - > name , bank , pwrst ) ;
2008-08-19 12:08:40 +04:00
2010-12-22 06:01:19 +03:00
if ( arch_pwrdm & & arch_pwrdm - > pwrdm_set_mem_onst )
ret = arch_pwrdm - > pwrdm_set_mem_onst ( pwrdm , bank , pwrst ) ;
2008-08-19 12:08:40 +04:00
2010-12-22 06:01:19 +03:00
return ret ;
2008-08-19 12:08:40 +04:00
}
/**
* pwrdm_set_mem_retst - set memory power state while powerdomain in RET
* @ pwrdm : struct powerdomain * to set
* @ bank : memory bank number to set ( 0 - 3 )
* @ pwrst : one of the PWRDM_POWER_ * macros
*
2010-01-27 06:13:02 +03:00
* Set the next power state @ pwrst that memory bank @ bank of the
* powerdomain @ pwrdm will enter when the powerdomain enters the
* RETENTION state . Bank will be a number from 0 to 3 , and represents
* different types of memory , depending on the powerdomain . @ pwrst
* will be either RETENTION or OFF , if supported . Returns - EINVAL if
* the powerdomain pointer is null or the target power state is not
* not supported for this memory bank , - EEXIST if the target memory
* bank does not exist or is not controllable , or returns 0 upon
* success .
2008-08-19 12:08:40 +04:00
*/
int pwrdm_set_mem_retst ( struct powerdomain * pwrdm , u8 bank , u8 pwrst )
{
2010-12-22 06:01:19 +03:00
int ret = - EINVAL ;
2008-08-19 12:08:40 +04:00
if ( ! pwrdm )
return - EINVAL ;
if ( pwrdm - > banks < ( bank + 1 ) )
return - EEXIST ;
if ( ! ( pwrdm - > pwrsts_mem_ret [ bank ] & ( 1 < < pwrst ) ) )
return - EINVAL ;
2012-07-26 10:54:26 +04:00
pr_debug ( " powerdomain: %s: setting next memory powerstate for bank %0x while pwrdm-RET to %0x \n " ,
pwrdm - > name , bank , pwrst ) ;
2008-08-19 12:08:40 +04:00
2010-12-22 06:01:19 +03:00
if ( arch_pwrdm & & arch_pwrdm - > pwrdm_set_mem_retst )
ret = arch_pwrdm - > pwrdm_set_mem_retst ( pwrdm , bank , pwrst ) ;
2008-08-19 12:08:40 +04:00
2010-12-22 06:01:19 +03:00
return ret ;
2008-08-19 12:08:40 +04:00
}
/**
* pwrdm_read_logic_pwrst - get current powerdomain logic retention power state
* @ pwrdm : struct powerdomain * to get current logic retention power state
*
2010-01-27 06:13:02 +03:00
* Return the power state that the logic portion of powerdomain @ pwrdm
* will enter when the powerdomain enters retention . Returns - EINVAL
* if the powerdomain pointer is null or returns the logic retention
* power state upon success .
2008-08-19 12:08:40 +04:00
*/
int pwrdm_read_logic_pwrst ( struct powerdomain * pwrdm )
{
2010-12-22 06:01:18 +03:00
int ret = - EINVAL ;
2008-08-19 12:08:40 +04:00
if ( ! pwrdm )
return - EINVAL ;
2010-12-22 06:01:18 +03:00
if ( arch_pwrdm & & arch_pwrdm - > pwrdm_read_logic_pwrst )
ret = arch_pwrdm - > pwrdm_read_logic_pwrst ( pwrdm ) ;
return ret ;
2008-08-19 12:08:40 +04:00
}
/**
* pwrdm_read_prev_logic_pwrst - get previous powerdomain logic power state
* @ pwrdm : struct powerdomain * to get previous logic power state
*
2010-01-27 06:13:02 +03:00
* Return the powerdomain @ pwrdm ' s previous logic power state . Returns
* - EINVAL if the powerdomain pointer is null or returns the previous
* logic power state upon success .
2008-08-19 12:08:40 +04:00
*/
int pwrdm_read_prev_logic_pwrst ( struct powerdomain * pwrdm )
{
2010-12-22 06:01:18 +03:00
int ret = - EINVAL ;
2008-08-19 12:08:40 +04:00
if ( ! pwrdm )
return - EINVAL ;
2010-12-22 06:01:18 +03:00
if ( arch_pwrdm & & arch_pwrdm - > pwrdm_read_prev_logic_pwrst )
ret = arch_pwrdm - > pwrdm_read_prev_logic_pwrst ( pwrdm ) ;
return ret ;
2008-08-19 12:08:40 +04:00
}
2010-02-24 22:05:49 +03:00
/**
* pwrdm_read_logic_retst - get next powerdomain logic power state
* @ pwrdm : struct powerdomain * to get next logic power state
*
* Return the powerdomain pwrdm ' s logic power state . Returns - EINVAL
* if the powerdomain pointer is null or returns the next logic
* power state upon success .
*/
int pwrdm_read_logic_retst ( struct powerdomain * pwrdm )
{
2010-12-22 06:01:18 +03:00
int ret = - EINVAL ;
2010-02-24 22:05:49 +03:00
if ( ! pwrdm )
return - EINVAL ;
2010-12-22 06:01:18 +03:00
if ( arch_pwrdm & & arch_pwrdm - > pwrdm_read_logic_retst )
ret = arch_pwrdm - > pwrdm_read_logic_retst ( pwrdm ) ;
return ret ;
2010-02-24 22:05:49 +03:00
}
2008-08-19 12:08:40 +04:00
/**
* pwrdm_read_mem_pwrst - get current memory bank power state
* @ pwrdm : struct powerdomain * to get current memory bank power state
* @ bank : memory bank number ( 0 - 3 )
*
2010-01-27 06:13:02 +03:00
* Return the powerdomain @ pwrdm ' s current memory power state for bank
* @ bank . Returns - EINVAL if the powerdomain pointer is null , - EEXIST if
2008-08-19 12:08:40 +04:00
* the target memory bank does not exist or is not controllable , or
* returns the current memory power state upon success .
*/
int pwrdm_read_mem_pwrst ( struct powerdomain * pwrdm , u8 bank )
{
2010-12-22 06:01:19 +03:00
int ret = - EINVAL ;
2008-08-19 12:08:40 +04:00
if ( ! pwrdm )
2010-12-22 06:01:19 +03:00
return ret ;
2008-08-19 12:08:40 +04:00
if ( pwrdm - > banks < ( bank + 1 ) )
2010-12-22 06:01:19 +03:00
return ret ;
2008-08-19 12:08:40 +04:00
2009-12-09 02:33:15 +03:00
if ( pwrdm - > flags & PWRDM_HAS_MPU_QUIRK )
bank = 1 ;
2010-12-22 06:01:19 +03:00
if ( arch_pwrdm & & arch_pwrdm - > pwrdm_read_mem_pwrst )
ret = arch_pwrdm - > pwrdm_read_mem_pwrst ( pwrdm , bank ) ;
2008-08-19 12:08:40 +04:00
2010-12-22 06:01:19 +03:00
return ret ;
2008-08-19 12:08:40 +04:00
}
/**
* pwrdm_read_prev_mem_pwrst - get previous memory bank power state
* @ pwrdm : struct powerdomain * to get previous memory bank power state
* @ bank : memory bank number ( 0 - 3 )
*
2010-01-27 06:13:02 +03:00
* Return the powerdomain @ pwrdm ' s previous memory power state for
* bank @ bank . Returns - EINVAL if the powerdomain pointer is null ,
* - EEXIST if the target memory bank does not exist or is not
* controllable , or returns the previous memory power state upon
* success .
2008-08-19 12:08:40 +04:00
*/
int pwrdm_read_prev_mem_pwrst ( struct powerdomain * pwrdm , u8 bank )
{
2010-12-22 06:01:19 +03:00
int ret = - EINVAL ;
2008-08-19 12:08:40 +04:00
if ( ! pwrdm )
2010-12-22 06:01:19 +03:00
return ret ;
2008-08-19 12:08:40 +04:00
if ( pwrdm - > banks < ( bank + 1 ) )
2010-12-22 06:01:19 +03:00
return ret ;
2008-08-19 12:08:40 +04:00
2009-12-09 02:33:15 +03:00
if ( pwrdm - > flags & PWRDM_HAS_MPU_QUIRK )
bank = 1 ;
2010-12-22 06:01:19 +03:00
if ( arch_pwrdm & & arch_pwrdm - > pwrdm_read_prev_mem_pwrst )
ret = arch_pwrdm - > pwrdm_read_prev_mem_pwrst ( pwrdm , bank ) ;
2008-08-19 12:08:40 +04:00
2010-12-22 06:01:19 +03:00
return ret ;
2008-08-19 12:08:40 +04:00
}
2010-02-24 22:05:49 +03:00
/**
* pwrdm_read_mem_retst - get next memory bank power state
* @ pwrdm : struct powerdomain * to get mext memory bank power state
* @ bank : memory bank number ( 0 - 3 )
*
* Return the powerdomain pwrdm ' s next memory power state for bank
* x . Returns - EINVAL if the powerdomain pointer is null , - EEXIST if
* the target memory bank does not exist or is not controllable , or
* returns the next memory power state upon success .
*/
int pwrdm_read_mem_retst ( struct powerdomain * pwrdm , u8 bank )
{
2010-12-22 06:01:19 +03:00
int ret = - EINVAL ;
2010-02-24 22:05:49 +03:00
if ( ! pwrdm )
2010-12-22 06:01:19 +03:00
return ret ;
2010-02-24 22:05:49 +03:00
if ( pwrdm - > banks < ( bank + 1 ) )
2010-12-22 06:01:19 +03:00
return ret ;
2010-02-24 22:05:49 +03:00
2010-12-22 06:01:19 +03:00
if ( arch_pwrdm & & arch_pwrdm - > pwrdm_read_mem_retst )
ret = arch_pwrdm - > pwrdm_read_mem_retst ( pwrdm , bank ) ;
2010-02-24 22:05:49 +03:00
2010-12-22 06:01:19 +03:00
return ret ;
2010-02-24 22:05:49 +03:00
}
2008-08-19 12:08:40 +04:00
/**
* pwrdm_clear_all_prev_pwrst - clear previous powerstate register for a pwrdm
* @ pwrdm : struct powerdomain * to clear
*
2010-01-27 06:13:02 +03:00
* Clear the powerdomain ' s previous power state register @ pwrdm .
* Clears the entire register , including logic and memory bank
* previous power states . Returns - EINVAL if the powerdomain pointer
* is null , or returns 0 upon success .
2008-08-19 12:08:40 +04:00
*/
int pwrdm_clear_all_prev_pwrst ( struct powerdomain * pwrdm )
{
2010-12-22 06:01:19 +03:00
int ret = - EINVAL ;
2008-08-19 12:08:40 +04:00
if ( ! pwrdm )
2010-12-22 06:01:19 +03:00
return ret ;
2008-08-19 12:08:40 +04:00
/*
* XXX should get the powerdomain ' s current state here ;
* warn & fail if it is not ON .
*/
2012-07-26 10:54:26 +04:00
pr_debug ( " powerdomain: %s: clearing previous power state reg \n " ,
2008-08-19 12:08:40 +04:00
pwrdm - > name ) ;
2010-12-22 06:01:19 +03:00
if ( arch_pwrdm & & arch_pwrdm - > pwrdm_clear_all_prev_pwrst )
ret = arch_pwrdm - > pwrdm_clear_all_prev_pwrst ( pwrdm ) ;
2008-08-19 12:08:40 +04:00
2010-12-22 06:01:19 +03:00
return ret ;
2008-08-19 12:08:40 +04:00
}
[ARM] OMAP3 pwrdm: add hardware save-and-restore (SAR) support
OMAP3430ES2+ introduces a new feature: optional powerdomain context
hardware save-and-restore (SAR). Currently, this feature only applies
to USBHOST and USBTLL module context when the USBHOST or CORE
powerdomains enter a low-power sleep state[1]. This feature avoids
re-enumeration of USB devices when the powerdomains return from idle,
which is potentially time-consuming.
This patch adds support for enabling and disabling hardware
save-and-restore to the powerdomain code. Three new functions are
added, pwrdm_enable_hdwr_sar(), pwrdm_disable_hdwr_sar(), and
pwrdm_can_hdwr_sar(). A new struct powerdomain "flags" field is
added, with a PWRDM_HAS_HDWR_SAR flag to indicate powerdomains with
SAR support.
Thanks to Jouni Högander <jouni.hogander@nokia.com> for reviewing an
earlier version of these patches, and Richard Woodruff <r-woodruff2@ti.com>
for clarifying the purpose of these bits.
1. For the USBHOST controller module, context loss occurs when the
USBHOST powerdomain enters off-idle. For USBTLL, context loss
occurs either if CORE enters off-idle, or if the CORE logic is
configured to turn off when CORE enters retention-idle (OSWR).
34xx ES2 TRM 4.8.6.1.1, 4.8.6.1.2
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2008-06-26 04:09:37 +04:00
/**
* pwrdm_enable_hdwr_sar - enable automatic hardware SAR for a pwrdm
* @ pwrdm : struct powerdomain *
*
* Enable automatic context save - and - restore upon power state change
2010-01-27 06:13:02 +03:00
* for some devices in the powerdomain @ pwrdm . Warning : this only
* affects a subset of devices in a powerdomain ; check the TRM
* closely . Returns - EINVAL if the powerdomain pointer is null or if
* the powerdomain does not support automatic save - and - restore , or
* returns 0 upon success .
[ARM] OMAP3 pwrdm: add hardware save-and-restore (SAR) support
OMAP3430ES2+ introduces a new feature: optional powerdomain context
hardware save-and-restore (SAR). Currently, this feature only applies
to USBHOST and USBTLL module context when the USBHOST or CORE
powerdomains enter a low-power sleep state[1]. This feature avoids
re-enumeration of USB devices when the powerdomains return from idle,
which is potentially time-consuming.
This patch adds support for enabling and disabling hardware
save-and-restore to the powerdomain code. Three new functions are
added, pwrdm_enable_hdwr_sar(), pwrdm_disable_hdwr_sar(), and
pwrdm_can_hdwr_sar(). A new struct powerdomain "flags" field is
added, with a PWRDM_HAS_HDWR_SAR flag to indicate powerdomains with
SAR support.
Thanks to Jouni Högander <jouni.hogander@nokia.com> for reviewing an
earlier version of these patches, and Richard Woodruff <r-woodruff2@ti.com>
for clarifying the purpose of these bits.
1. For the USBHOST controller module, context loss occurs when the
USBHOST powerdomain enters off-idle. For USBTLL, context loss
occurs either if CORE enters off-idle, or if the CORE logic is
configured to turn off when CORE enters retention-idle (OSWR).
34xx ES2 TRM 4.8.6.1.1, 4.8.6.1.2
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2008-06-26 04:09:37 +04:00
*/
int pwrdm_enable_hdwr_sar ( struct powerdomain * pwrdm )
{
2010-12-22 06:01:19 +03:00
int ret = - EINVAL ;
[ARM] OMAP3 pwrdm: add hardware save-and-restore (SAR) support
OMAP3430ES2+ introduces a new feature: optional powerdomain context
hardware save-and-restore (SAR). Currently, this feature only applies
to USBHOST and USBTLL module context when the USBHOST or CORE
powerdomains enter a low-power sleep state[1]. This feature avoids
re-enumeration of USB devices when the powerdomains return from idle,
which is potentially time-consuming.
This patch adds support for enabling and disabling hardware
save-and-restore to the powerdomain code. Three new functions are
added, pwrdm_enable_hdwr_sar(), pwrdm_disable_hdwr_sar(), and
pwrdm_can_hdwr_sar(). A new struct powerdomain "flags" field is
added, with a PWRDM_HAS_HDWR_SAR flag to indicate powerdomains with
SAR support.
Thanks to Jouni Högander <jouni.hogander@nokia.com> for reviewing an
earlier version of these patches, and Richard Woodruff <r-woodruff2@ti.com>
for clarifying the purpose of these bits.
1. For the USBHOST controller module, context loss occurs when the
USBHOST powerdomain enters off-idle. For USBTLL, context loss
occurs either if CORE enters off-idle, or if the CORE logic is
configured to turn off when CORE enters retention-idle (OSWR).
34xx ES2 TRM 4.8.6.1.1, 4.8.6.1.2
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2008-06-26 04:09:37 +04:00
if ( ! pwrdm )
2010-12-22 06:01:19 +03:00
return ret ;
[ARM] OMAP3 pwrdm: add hardware save-and-restore (SAR) support
OMAP3430ES2+ introduces a new feature: optional powerdomain context
hardware save-and-restore (SAR). Currently, this feature only applies
to USBHOST and USBTLL module context when the USBHOST or CORE
powerdomains enter a low-power sleep state[1]. This feature avoids
re-enumeration of USB devices when the powerdomains return from idle,
which is potentially time-consuming.
This patch adds support for enabling and disabling hardware
save-and-restore to the powerdomain code. Three new functions are
added, pwrdm_enable_hdwr_sar(), pwrdm_disable_hdwr_sar(), and
pwrdm_can_hdwr_sar(). A new struct powerdomain "flags" field is
added, with a PWRDM_HAS_HDWR_SAR flag to indicate powerdomains with
SAR support.
Thanks to Jouni Högander <jouni.hogander@nokia.com> for reviewing an
earlier version of these patches, and Richard Woodruff <r-woodruff2@ti.com>
for clarifying the purpose of these bits.
1. For the USBHOST controller module, context loss occurs when the
USBHOST powerdomain enters off-idle. For USBTLL, context loss
occurs either if CORE enters off-idle, or if the CORE logic is
configured to turn off when CORE enters retention-idle (OSWR).
34xx ES2 TRM 4.8.6.1.1, 4.8.6.1.2
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2008-06-26 04:09:37 +04:00
if ( ! ( pwrdm - > flags & PWRDM_HAS_HDWR_SAR ) )
2010-12-22 06:01:19 +03:00
return ret ;
[ARM] OMAP3 pwrdm: add hardware save-and-restore (SAR) support
OMAP3430ES2+ introduces a new feature: optional powerdomain context
hardware save-and-restore (SAR). Currently, this feature only applies
to USBHOST and USBTLL module context when the USBHOST or CORE
powerdomains enter a low-power sleep state[1]. This feature avoids
re-enumeration of USB devices when the powerdomains return from idle,
which is potentially time-consuming.
This patch adds support for enabling and disabling hardware
save-and-restore to the powerdomain code. Three new functions are
added, pwrdm_enable_hdwr_sar(), pwrdm_disable_hdwr_sar(), and
pwrdm_can_hdwr_sar(). A new struct powerdomain "flags" field is
added, with a PWRDM_HAS_HDWR_SAR flag to indicate powerdomains with
SAR support.
Thanks to Jouni Högander <jouni.hogander@nokia.com> for reviewing an
earlier version of these patches, and Richard Woodruff <r-woodruff2@ti.com>
for clarifying the purpose of these bits.
1. For the USBHOST controller module, context loss occurs when the
USBHOST powerdomain enters off-idle. For USBTLL, context loss
occurs either if CORE enters off-idle, or if the CORE logic is
configured to turn off when CORE enters retention-idle (OSWR).
34xx ES2 TRM 4.8.6.1.1, 4.8.6.1.2
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2008-06-26 04:09:37 +04:00
2012-07-26 10:54:26 +04:00
pr_debug ( " powerdomain: %s: setting SAVEANDRESTORE bit \n " , pwrdm - > name ) ;
[ARM] OMAP3 pwrdm: add hardware save-and-restore (SAR) support
OMAP3430ES2+ introduces a new feature: optional powerdomain context
hardware save-and-restore (SAR). Currently, this feature only applies
to USBHOST and USBTLL module context when the USBHOST or CORE
powerdomains enter a low-power sleep state[1]. This feature avoids
re-enumeration of USB devices when the powerdomains return from idle,
which is potentially time-consuming.
This patch adds support for enabling and disabling hardware
save-and-restore to the powerdomain code. Three new functions are
added, pwrdm_enable_hdwr_sar(), pwrdm_disable_hdwr_sar(), and
pwrdm_can_hdwr_sar(). A new struct powerdomain "flags" field is
added, with a PWRDM_HAS_HDWR_SAR flag to indicate powerdomains with
SAR support.
Thanks to Jouni Högander <jouni.hogander@nokia.com> for reviewing an
earlier version of these patches, and Richard Woodruff <r-woodruff2@ti.com>
for clarifying the purpose of these bits.
1. For the USBHOST controller module, context loss occurs when the
USBHOST powerdomain enters off-idle. For USBTLL, context loss
occurs either if CORE enters off-idle, or if the CORE logic is
configured to turn off when CORE enters retention-idle (OSWR).
34xx ES2 TRM 4.8.6.1.1, 4.8.6.1.2
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2008-06-26 04:09:37 +04:00
2010-12-22 06:01:19 +03:00
if ( arch_pwrdm & & arch_pwrdm - > pwrdm_enable_hdwr_sar )
ret = arch_pwrdm - > pwrdm_enable_hdwr_sar ( pwrdm ) ;
[ARM] OMAP3 pwrdm: add hardware save-and-restore (SAR) support
OMAP3430ES2+ introduces a new feature: optional powerdomain context
hardware save-and-restore (SAR). Currently, this feature only applies
to USBHOST and USBTLL module context when the USBHOST or CORE
powerdomains enter a low-power sleep state[1]. This feature avoids
re-enumeration of USB devices when the powerdomains return from idle,
which is potentially time-consuming.
This patch adds support for enabling and disabling hardware
save-and-restore to the powerdomain code. Three new functions are
added, pwrdm_enable_hdwr_sar(), pwrdm_disable_hdwr_sar(), and
pwrdm_can_hdwr_sar(). A new struct powerdomain "flags" field is
added, with a PWRDM_HAS_HDWR_SAR flag to indicate powerdomains with
SAR support.
Thanks to Jouni Högander <jouni.hogander@nokia.com> for reviewing an
earlier version of these patches, and Richard Woodruff <r-woodruff2@ti.com>
for clarifying the purpose of these bits.
1. For the USBHOST controller module, context loss occurs when the
USBHOST powerdomain enters off-idle. For USBTLL, context loss
occurs either if CORE enters off-idle, or if the CORE logic is
configured to turn off when CORE enters retention-idle (OSWR).
34xx ES2 TRM 4.8.6.1.1, 4.8.6.1.2
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2008-06-26 04:09:37 +04:00
2010-12-22 06:01:19 +03:00
return ret ;
[ARM] OMAP3 pwrdm: add hardware save-and-restore (SAR) support
OMAP3430ES2+ introduces a new feature: optional powerdomain context
hardware save-and-restore (SAR). Currently, this feature only applies
to USBHOST and USBTLL module context when the USBHOST or CORE
powerdomains enter a low-power sleep state[1]. This feature avoids
re-enumeration of USB devices when the powerdomains return from idle,
which is potentially time-consuming.
This patch adds support for enabling and disabling hardware
save-and-restore to the powerdomain code. Three new functions are
added, pwrdm_enable_hdwr_sar(), pwrdm_disable_hdwr_sar(), and
pwrdm_can_hdwr_sar(). A new struct powerdomain "flags" field is
added, with a PWRDM_HAS_HDWR_SAR flag to indicate powerdomains with
SAR support.
Thanks to Jouni Högander <jouni.hogander@nokia.com> for reviewing an
earlier version of these patches, and Richard Woodruff <r-woodruff2@ti.com>
for clarifying the purpose of these bits.
1. For the USBHOST controller module, context loss occurs when the
USBHOST powerdomain enters off-idle. For USBTLL, context loss
occurs either if CORE enters off-idle, or if the CORE logic is
configured to turn off when CORE enters retention-idle (OSWR).
34xx ES2 TRM 4.8.6.1.1, 4.8.6.1.2
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2008-06-26 04:09:37 +04:00
}
/**
* pwrdm_disable_hdwr_sar - disable automatic hardware SAR for a pwrdm
* @ pwrdm : struct powerdomain *
*
* Disable automatic context save - and - restore upon power state change
2010-01-27 06:13:02 +03:00
* for some devices in the powerdomain @ pwrdm . Warning : this only
* affects a subset of devices in a powerdomain ; check the TRM
* closely . Returns - EINVAL if the powerdomain pointer is null or if
* the powerdomain does not support automatic save - and - restore , or
* returns 0 upon success .
[ARM] OMAP3 pwrdm: add hardware save-and-restore (SAR) support
OMAP3430ES2+ introduces a new feature: optional powerdomain context
hardware save-and-restore (SAR). Currently, this feature only applies
to USBHOST and USBTLL module context when the USBHOST or CORE
powerdomains enter a low-power sleep state[1]. This feature avoids
re-enumeration of USB devices when the powerdomains return from idle,
which is potentially time-consuming.
This patch adds support for enabling and disabling hardware
save-and-restore to the powerdomain code. Three new functions are
added, pwrdm_enable_hdwr_sar(), pwrdm_disable_hdwr_sar(), and
pwrdm_can_hdwr_sar(). A new struct powerdomain "flags" field is
added, with a PWRDM_HAS_HDWR_SAR flag to indicate powerdomains with
SAR support.
Thanks to Jouni Högander <jouni.hogander@nokia.com> for reviewing an
earlier version of these patches, and Richard Woodruff <r-woodruff2@ti.com>
for clarifying the purpose of these bits.
1. For the USBHOST controller module, context loss occurs when the
USBHOST powerdomain enters off-idle. For USBTLL, context loss
occurs either if CORE enters off-idle, or if the CORE logic is
configured to turn off when CORE enters retention-idle (OSWR).
34xx ES2 TRM 4.8.6.1.1, 4.8.6.1.2
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2008-06-26 04:09:37 +04:00
*/
int pwrdm_disable_hdwr_sar ( struct powerdomain * pwrdm )
{
2010-12-22 06:01:19 +03:00
int ret = - EINVAL ;
[ARM] OMAP3 pwrdm: add hardware save-and-restore (SAR) support
OMAP3430ES2+ introduces a new feature: optional powerdomain context
hardware save-and-restore (SAR). Currently, this feature only applies
to USBHOST and USBTLL module context when the USBHOST or CORE
powerdomains enter a low-power sleep state[1]. This feature avoids
re-enumeration of USB devices when the powerdomains return from idle,
which is potentially time-consuming.
This patch adds support for enabling and disabling hardware
save-and-restore to the powerdomain code. Three new functions are
added, pwrdm_enable_hdwr_sar(), pwrdm_disable_hdwr_sar(), and
pwrdm_can_hdwr_sar(). A new struct powerdomain "flags" field is
added, with a PWRDM_HAS_HDWR_SAR flag to indicate powerdomains with
SAR support.
Thanks to Jouni Högander <jouni.hogander@nokia.com> for reviewing an
earlier version of these patches, and Richard Woodruff <r-woodruff2@ti.com>
for clarifying the purpose of these bits.
1. For the USBHOST controller module, context loss occurs when the
USBHOST powerdomain enters off-idle. For USBTLL, context loss
occurs either if CORE enters off-idle, or if the CORE logic is
configured to turn off when CORE enters retention-idle (OSWR).
34xx ES2 TRM 4.8.6.1.1, 4.8.6.1.2
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2008-06-26 04:09:37 +04:00
if ( ! pwrdm )
2010-12-22 06:01:19 +03:00
return ret ;
[ARM] OMAP3 pwrdm: add hardware save-and-restore (SAR) support
OMAP3430ES2+ introduces a new feature: optional powerdomain context
hardware save-and-restore (SAR). Currently, this feature only applies
to USBHOST and USBTLL module context when the USBHOST or CORE
powerdomains enter a low-power sleep state[1]. This feature avoids
re-enumeration of USB devices when the powerdomains return from idle,
which is potentially time-consuming.
This patch adds support for enabling and disabling hardware
save-and-restore to the powerdomain code. Three new functions are
added, pwrdm_enable_hdwr_sar(), pwrdm_disable_hdwr_sar(), and
pwrdm_can_hdwr_sar(). A new struct powerdomain "flags" field is
added, with a PWRDM_HAS_HDWR_SAR flag to indicate powerdomains with
SAR support.
Thanks to Jouni Högander <jouni.hogander@nokia.com> for reviewing an
earlier version of these patches, and Richard Woodruff <r-woodruff2@ti.com>
for clarifying the purpose of these bits.
1. For the USBHOST controller module, context loss occurs when the
USBHOST powerdomain enters off-idle. For USBTLL, context loss
occurs either if CORE enters off-idle, or if the CORE logic is
configured to turn off when CORE enters retention-idle (OSWR).
34xx ES2 TRM 4.8.6.1.1, 4.8.6.1.2
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2008-06-26 04:09:37 +04:00
if ( ! ( pwrdm - > flags & PWRDM_HAS_HDWR_SAR ) )
2010-12-22 06:01:19 +03:00
return ret ;
[ARM] OMAP3 pwrdm: add hardware save-and-restore (SAR) support
OMAP3430ES2+ introduces a new feature: optional powerdomain context
hardware save-and-restore (SAR). Currently, this feature only applies
to USBHOST and USBTLL module context when the USBHOST or CORE
powerdomains enter a low-power sleep state[1]. This feature avoids
re-enumeration of USB devices when the powerdomains return from idle,
which is potentially time-consuming.
This patch adds support for enabling and disabling hardware
save-and-restore to the powerdomain code. Three new functions are
added, pwrdm_enable_hdwr_sar(), pwrdm_disable_hdwr_sar(), and
pwrdm_can_hdwr_sar(). A new struct powerdomain "flags" field is
added, with a PWRDM_HAS_HDWR_SAR flag to indicate powerdomains with
SAR support.
Thanks to Jouni Högander <jouni.hogander@nokia.com> for reviewing an
earlier version of these patches, and Richard Woodruff <r-woodruff2@ti.com>
for clarifying the purpose of these bits.
1. For the USBHOST controller module, context loss occurs when the
USBHOST powerdomain enters off-idle. For USBTLL, context loss
occurs either if CORE enters off-idle, or if the CORE logic is
configured to turn off when CORE enters retention-idle (OSWR).
34xx ES2 TRM 4.8.6.1.1, 4.8.6.1.2
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2008-06-26 04:09:37 +04:00
2012-07-26 10:54:26 +04:00
pr_debug ( " powerdomain: %s: clearing SAVEANDRESTORE bit \n " , pwrdm - > name ) ;
[ARM] OMAP3 pwrdm: add hardware save-and-restore (SAR) support
OMAP3430ES2+ introduces a new feature: optional powerdomain context
hardware save-and-restore (SAR). Currently, this feature only applies
to USBHOST and USBTLL module context when the USBHOST or CORE
powerdomains enter a low-power sleep state[1]. This feature avoids
re-enumeration of USB devices when the powerdomains return from idle,
which is potentially time-consuming.
This patch adds support for enabling and disabling hardware
save-and-restore to the powerdomain code. Three new functions are
added, pwrdm_enable_hdwr_sar(), pwrdm_disable_hdwr_sar(), and
pwrdm_can_hdwr_sar(). A new struct powerdomain "flags" field is
added, with a PWRDM_HAS_HDWR_SAR flag to indicate powerdomains with
SAR support.
Thanks to Jouni Högander <jouni.hogander@nokia.com> for reviewing an
earlier version of these patches, and Richard Woodruff <r-woodruff2@ti.com>
for clarifying the purpose of these bits.
1. For the USBHOST controller module, context loss occurs when the
USBHOST powerdomain enters off-idle. For USBTLL, context loss
occurs either if CORE enters off-idle, or if the CORE logic is
configured to turn off when CORE enters retention-idle (OSWR).
34xx ES2 TRM 4.8.6.1.1, 4.8.6.1.2
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2008-06-26 04:09:37 +04:00
2010-12-22 06:01:19 +03:00
if ( arch_pwrdm & & arch_pwrdm - > pwrdm_disable_hdwr_sar )
ret = arch_pwrdm - > pwrdm_disable_hdwr_sar ( pwrdm ) ;
[ARM] OMAP3 pwrdm: add hardware save-and-restore (SAR) support
OMAP3430ES2+ introduces a new feature: optional powerdomain context
hardware save-and-restore (SAR). Currently, this feature only applies
to USBHOST and USBTLL module context when the USBHOST or CORE
powerdomains enter a low-power sleep state[1]. This feature avoids
re-enumeration of USB devices when the powerdomains return from idle,
which is potentially time-consuming.
This patch adds support for enabling and disabling hardware
save-and-restore to the powerdomain code. Three new functions are
added, pwrdm_enable_hdwr_sar(), pwrdm_disable_hdwr_sar(), and
pwrdm_can_hdwr_sar(). A new struct powerdomain "flags" field is
added, with a PWRDM_HAS_HDWR_SAR flag to indicate powerdomains with
SAR support.
Thanks to Jouni Högander <jouni.hogander@nokia.com> for reviewing an
earlier version of these patches, and Richard Woodruff <r-woodruff2@ti.com>
for clarifying the purpose of these bits.
1. For the USBHOST controller module, context loss occurs when the
USBHOST powerdomain enters off-idle. For USBTLL, context loss
occurs either if CORE enters off-idle, or if the CORE logic is
configured to turn off when CORE enters retention-idle (OSWR).
34xx ES2 TRM 4.8.6.1.1, 4.8.6.1.2
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2008-06-26 04:09:37 +04:00
2010-12-22 06:01:19 +03:00
return ret ;
[ARM] OMAP3 pwrdm: add hardware save-and-restore (SAR) support
OMAP3430ES2+ introduces a new feature: optional powerdomain context
hardware save-and-restore (SAR). Currently, this feature only applies
to USBHOST and USBTLL module context when the USBHOST or CORE
powerdomains enter a low-power sleep state[1]. This feature avoids
re-enumeration of USB devices when the powerdomains return from idle,
which is potentially time-consuming.
This patch adds support for enabling and disabling hardware
save-and-restore to the powerdomain code. Three new functions are
added, pwrdm_enable_hdwr_sar(), pwrdm_disable_hdwr_sar(), and
pwrdm_can_hdwr_sar(). A new struct powerdomain "flags" field is
added, with a PWRDM_HAS_HDWR_SAR flag to indicate powerdomains with
SAR support.
Thanks to Jouni Högander <jouni.hogander@nokia.com> for reviewing an
earlier version of these patches, and Richard Woodruff <r-woodruff2@ti.com>
for clarifying the purpose of these bits.
1. For the USBHOST controller module, context loss occurs when the
USBHOST powerdomain enters off-idle. For USBTLL, context loss
occurs either if CORE enters off-idle, or if the CORE logic is
configured to turn off when CORE enters retention-idle (OSWR).
34xx ES2 TRM 4.8.6.1.1, 4.8.6.1.2
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2008-06-26 04:09:37 +04:00
}
/**
* pwrdm_has_hdwr_sar - test whether powerdomain supports hardware SAR
* @ pwrdm : struct powerdomain *
*
2010-01-27 06:13:02 +03:00
* Returns 1 if powerdomain @ pwrdm supports hardware save - and - restore
[ARM] OMAP3 pwrdm: add hardware save-and-restore (SAR) support
OMAP3430ES2+ introduces a new feature: optional powerdomain context
hardware save-and-restore (SAR). Currently, this feature only applies
to USBHOST and USBTLL module context when the USBHOST or CORE
powerdomains enter a low-power sleep state[1]. This feature avoids
re-enumeration of USB devices when the powerdomains return from idle,
which is potentially time-consuming.
This patch adds support for enabling and disabling hardware
save-and-restore to the powerdomain code. Three new functions are
added, pwrdm_enable_hdwr_sar(), pwrdm_disable_hdwr_sar(), and
pwrdm_can_hdwr_sar(). A new struct powerdomain "flags" field is
added, with a PWRDM_HAS_HDWR_SAR flag to indicate powerdomains with
SAR support.
Thanks to Jouni Högander <jouni.hogander@nokia.com> for reviewing an
earlier version of these patches, and Richard Woodruff <r-woodruff2@ti.com>
for clarifying the purpose of these bits.
1. For the USBHOST controller module, context loss occurs when the
USBHOST powerdomain enters off-idle. For USBTLL, context loss
occurs either if CORE enters off-idle, or if the CORE logic is
configured to turn off when CORE enters retention-idle (OSWR).
34xx ES2 TRM 4.8.6.1.1, 4.8.6.1.2
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2008-06-26 04:09:37 +04:00
* for some devices , or 0 if it does not .
*/
bool pwrdm_has_hdwr_sar ( struct powerdomain * pwrdm )
{
return ( pwrdm & & pwrdm - > flags & PWRDM_HAS_HDWR_SAR ) ? 1 : 0 ;
}
2010-05-19 06:24:03 +04:00
/**
* pwrdm_set_lowpwrstchange - Request a low power state change
* @ pwrdm : struct powerdomain *
*
* Allows a powerdomain to transtion to a lower power sleep state
* from an existing sleep state without waking up the powerdomain .
* Returns - EINVAL if the powerdomain pointer is null or if the
* powerdomain does not support LOWPOWERSTATECHANGE , or returns 0
* upon success .
*/
int pwrdm_set_lowpwrstchange ( struct powerdomain * pwrdm )
{
2010-12-22 06:01:19 +03:00
int ret = - EINVAL ;
2010-05-19 06:24:03 +04:00
if ( ! pwrdm )
return - EINVAL ;
if ( ! ( pwrdm - > flags & PWRDM_HAS_LOWPOWERSTATECHANGE ) )
return - EINVAL ;
pr_debug ( " powerdomain: %s: setting LOWPOWERSTATECHANGE bit \n " ,
pwrdm - > name ) ;
2010-12-22 06:01:19 +03:00
if ( arch_pwrdm & & arch_pwrdm - > pwrdm_set_lowpwrstchange )
ret = arch_pwrdm - > pwrdm_set_lowpwrstchange ( pwrdm ) ;
2010-05-19 06:24:03 +04:00
2010-12-22 06:01:19 +03:00
return ret ;
2010-05-19 06:24:03 +04:00
}
2008-08-19 12:08:40 +04:00
/**
* pwrdm_wait_transition - wait for powerdomain power transition to finish
* @ pwrdm : struct powerdomain * to wait for
*
2010-01-27 06:13:02 +03:00
* If the powerdomain @ pwrdm is in the process of a state transition ,
2008-08-19 12:08:40 +04:00
* spin until it completes the power transition , or until an iteration
* bailout value is reached . Returns - EINVAL if the powerdomain
* pointer is null , - EAGAIN if the bailout value was reached , or
* returns 0 upon success .
*/
int pwrdm_wait_transition ( struct powerdomain * pwrdm )
{
2010-12-22 06:01:19 +03:00
int ret = - EINVAL ;
2008-08-19 12:08:40 +04:00
if ( ! pwrdm )
return - EINVAL ;
2010-12-22 06:01:19 +03:00
if ( arch_pwrdm & & arch_pwrdm - > pwrdm_wait_transition )
ret = arch_pwrdm - > pwrdm_wait_transition ( pwrdm ) ;
2008-08-19 12:08:40 +04:00
2010-12-22 06:01:19 +03:00
return ret ;
2008-08-19 12:08:40 +04:00
}
2008-10-15 18:48:43 +04:00
int pwrdm_state_switch ( struct powerdomain * pwrdm )
{
2012-03-12 18:34:32 +04:00
int ret ;
ret = pwrdm_wait_transition ( pwrdm ) ;
if ( ! ret )
ret = _pwrdm_state_switch ( pwrdm , PWRDM_STATE_NOW ) ;
return ret ;
2008-10-15 18:48:43 +04:00
}
2012-05-12 03:00:24 +04:00
int pwrdm_pre_transition ( struct powerdomain * pwrdm )
2008-10-15 18:48:43 +04:00
{
2012-05-12 03:00:24 +04:00
if ( pwrdm )
_pwrdm_pre_transition_cb ( pwrdm , NULL ) ;
else
pwrdm_for_each ( _pwrdm_pre_transition_cb , NULL ) ;
2008-10-15 18:48:43 +04:00
return 0 ;
}
2012-05-12 03:00:24 +04:00
int pwrdm_post_transition ( struct powerdomain * pwrdm )
2008-10-15 18:48:43 +04:00
{
2012-05-12 03:00:24 +04:00
if ( pwrdm )
_pwrdm_post_transition_cb ( pwrdm , NULL ) ;
else
pwrdm_for_each ( _pwrdm_post_transition_cb , NULL ) ;
2008-10-15 18:48:43 +04:00
return 0 ;
}
2010-12-22 07:31:55 +03:00
/**
* pwrdm_get_context_loss_count - get powerdomain ' s context loss count
* @ pwrdm : struct powerdomain * to wait for
*
* Context loss count is the sum of powerdomain off - mode counter , the
2011-06-09 17:56:23 +04:00
* logic off counter and the per - bank memory off counter . Returns negative
2010-12-22 07:31:55 +03:00
* ( and WARNs ) upon error , otherwise , returns the context loss count .
*/
2011-06-09 17:56:23 +04:00
int pwrdm_get_context_loss_count ( struct powerdomain * pwrdm )
2010-12-22 07:31:55 +03:00
{
int i , count ;
if ( ! pwrdm ) {
WARN ( 1 , " powerdomain: %s: pwrdm is null \n " , __func__ ) ;
2011-06-09 17:56:23 +04:00
return - ENODEV ;
2010-12-22 07:31:55 +03:00
}
count = pwrdm - > state_counter [ PWRDM_POWER_OFF ] ;
count + = pwrdm - > ret_logic_off_counter ;
for ( i = 0 ; i < pwrdm - > banks ; i + + )
count + = pwrdm - > ret_mem_off_counter [ i ] ;
2011-06-09 17:56:23 +04:00
/*
* Context loss count has to be a non - negative value . Clear the sign
* bit to get a value range from 0 to INT_MAX .
*/
count & = INT_MAX ;
pr_debug ( " powerdomain: %s: context loss count = %d \n " ,
2010-12-22 07:31:55 +03:00
pwrdm - > name , count ) ;
return count ;
}
2011-03-08 05:28:15 +03:00
/**
* pwrdm_can_ever_lose_context - can this powerdomain ever lose context ?
* @ pwrdm : struct powerdomain *
*
* Given a struct powerdomain * @ pwrdm , returns 1 if the powerdomain
* can lose either memory or logic context or if @ pwrdm is invalid , or
* returns 0 otherwise . This function is not concerned with how the
* powerdomain registers are programmed ( i . e . , to go off or not ) ; it ' s
* concerned with whether it ' s ever possible for this powerdomain to
* go off while some other part of the chip is active . This function
* assumes that every powerdomain can go to either ON or INACTIVE .
*/
bool pwrdm_can_ever_lose_context ( struct powerdomain * pwrdm )
{
int i ;
if ( IS_ERR_OR_NULL ( pwrdm ) ) {
pr_debug ( " powerdomain: %s: invalid powerdomain pointer \n " ,
__func__ ) ;
return 1 ;
}
if ( pwrdm - > pwrsts & PWRSTS_OFF )
return 1 ;
if ( pwrdm - > pwrsts & PWRSTS_RET ) {
if ( pwrdm - > pwrsts_logic_ret & PWRSTS_OFF )
return 1 ;
for ( i = 0 ; i < pwrdm - > banks ; i + + )
if ( pwrdm - > pwrsts_mem_ret [ i ] & PWRSTS_OFF )
return 1 ;
}
for ( i = 0 ; i < pwrdm - > banks ; i + + )
if ( pwrdm - > pwrsts_mem_on [ i ] & PWRSTS_OFF )
return 1 ;
return 0 ;
}