@ -41,6 +41,8 @@
# include <psci.h>
# include "css_scpi.h"
unsigned long wakeup_address ;
/*******************************************************************************
* Private function to program the mailbox for a cpu before it is released
* from reset .
@ -50,32 +52,27 @@ static void css_program_mailbox(uint64_t mpidr, uint64_t address)
uint64_t linear_id ;
uint64_t mbox ;
linear_id = platform_get _core_pos ( mpidr ) ;
linear_id = plat_arm_calc _core_pos ( mpidr ) ;
mbox = TRUSTED_MAILBOXES_BASE + ( linear_id < < TRUSTED_MAILBOX_SHIFT ) ;
* ( ( uint64_t * ) mbox ) = address ;
flush_dcache_range ( mbox , sizeof ( mbox ) ) ;
}
/*******************************************************************************
* Handler called when an affinity instance is about to be turned on . The
* Handler called when a power domain is about to be turned on . The
* level and mpidr determine the affinity instance .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int32_t css_affinst_on ( uint64_t mpidr ,
uint64_t sec_entrypoint ,
uint32_t afflvl ,
uint32_t state )
int css_pwr_domain_on ( u_register_t mpidr )
{
/*
* SCP takes care of powering up higher affinity level s so we
* SCP takes care of powering up parent power domains so we
* only need to care about level 0
*/
if ( afflvl ! = MPIDR_AFFLVL0 )
return PSCI_E_SUCCESS ;
/*
* Setup mailbox with address for CPU entrypoint when it next powers up
*/
css_program_mailbox ( mpidr , sec_entrypoint ) ;
css_program_mailbox ( mpidr , wakeup_address ) ;
scpi_set_css_power_state ( mpidr , scpi_power_on , scpi_power_on ,
scpi_power_on ) ;
@ -84,29 +81,22 @@ int32_t css_affinst_on(uint64_t mpidr,
}
/*******************************************************************************
* Handler called when an affinity instance has just been powered on after
* being turned off earlier . The level and mpidr determine the affinity
* instance . The ' state ' arg . allows the platform to decide whether the cluster
* was turned off prior to wakeup and do what ' s necessary to setup it up
* correctly .
* Handler called when a power level has just been powered on after
* being turned off earlier . The target_state encodes the low power state that
* each level has woken up from .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void css_aff inst _on_finish ( uint32_t afflvl , uint32_t state )
void css_pwr_domain_on_finish ( const psci_power_state_t * target_state )
{
unsigned long mpidr ;
/* Determine if any platform actions need to be executed. */
if ( arm_do_affinst_actions ( afflvl , state ) = = - EAGAIN )
return ;
/* Get the mpidr for this cpu */
mpidr = read_mpidr_el1 ( ) ;
assert ( target_state - > pwr_domain_state [ ARM_PWR_LVL0 ] = =
ARM_LOCAL_STATE_OFF ) ;
/*
* Perform the common cluster specific operations i . e enable coherency
* if this cluster was off .
*/
if ( afflvl ! = MPIDR_AFFLVL0 )
cci_enable_snoop_dvm_reqs ( MPIDR_AFFLVL1_VAL ( mpidr ) ) ;
if ( target_state - > pwr_domain_state [ ARM_PWR_LVL1 ] = =
ARM_LOCAL_STATE_OFF )
cci_enable_snoop_dvm_reqs ( MPIDR_AFFLVL1_VAL ( read_mpidr_el1 ( ) ) ) ;
/* Enable the gic cpu interface */
arm_gic_cpuif_setup ( ) ;
@ -115,16 +105,16 @@ void css_affinst_on_finish(uint32_t afflvl, uint32_t state)
arm_gic_pcpu_distif_setup ( ) ;
/* Clear the mailbox for this cpu. */
css_program_mailbox ( mpidr , 0 ) ;
css_program_mailbox ( read_ mpidr_el1 ( ) , 0 ) ;
}
/*******************************************************************************
* Common function called while turning a cpu off or suspending it . It is called
* from css_off ( ) or css_suspend ( ) when these functions in turn are called for
* the highest affinity level which will be powered down . It performs the
* actions common to the OFF and SUSPEND calls .
* power domain at the highest power level which will be powered down . It
* performs the actions common to the OFF and SUSPEND calls .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void css_power_down_common ( uint32_t afflvl )
static void css_power_down_common ( const psci_power_state_t * target_state )
{
uint32_t cluster_state = scpi_power_on ;
@ -132,7 +122,8 @@ static void css_power_down_common(uint32_t afflvl)
arm_gic_cpuif_deactivate ( ) ;
/* Cluster is to be turned off, so disable coherency */
if ( afflvl > MPIDR_AFFLVL0 ) {
if ( target_state - > pwr_domain_state [ ARM_PWR_LVL1 ] = =
ARM_LOCAL_STATE_OFF ) {
cci_disable_snoop_dvm_reqs ( MPIDR_AFFLVL1_VAL ( read_mpidr ( ) ) ) ;
cluster_state = scpi_power_off ;
}
@ -148,64 +139,60 @@ static void css_power_down_common(uint32_t afflvl)
}
/*******************************************************************************
* Handler called when an affinity instance is about to be turned off . The
* level and mpidr determine the affinity instance . The ' state ' arg . allows the
* platform to decide whether the cluster is being turned off and take
* appropriate actions .
*
* CAUTION : There is no guarantee that caches will remain turned on across calls
* to this function as each affinity level is dealt with . So do not write & read
* global variables across calls . It will be wise to do flush a write to the
* global to prevent unpredictable results .
* Handler called when a power domain is about to be turned off . The
* target_state encodes the power state that each level should transition to .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void css_affinst_off ( uint32_t afflvl , uint32_t state )
static void css_pwr_domain_off ( const psci_power_state_t * target_state )
{
/* Determine if any platform actions need to be executed */
if ( arm_do_affinst_actions ( afflvl , state ) = = - EAGAIN )
return ;
assert ( target_state - > pwr_domain_state [ ARM_PWR_LVL0 ] = =
ARM_LOCAL_STATE_OFF ) ;
css_power_down_common ( afflvl ) ;
css_power_down_common ( target_state ) ;
}
/*******************************************************************************
* Handler called when an affinity instance is about to be suspended . The
* level and mpidr determine the affinity instance . The ' state ' arg . allows the
* platform to decide whether the cluster is being turned off and take apt
* actions . The ' sec_entrypoint ' determines the address in BL3 - 1 from where
* execution should resume .
*
* CAUTION : There is no guarantee that caches will remain turned on across calls
* to this function as each affinity level is dealt with . So do not write & read
* global variables across calls . It will be wise to do flush a write to the
* global to prevent unpredictable results .
* Handler called when a power domain is about to be suspended . The
* target_state encodes the power state that each level should transition to .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void css_affinst_suspend ( uint64_t sec_entrypoint ,
uint32_t afflvl ,
uint32_t state )
static void css_pwr_domain_suspend ( const psci_power_state_t * target_state )
{
/* Determine if any platform actions need to be executed */
if ( arm_do_affinst_actions ( afflvl , state ) = = - EAGAIN )
/*
* Juno has retention only at cpu level . Just return
* as nothing is to be done for retention .
*/
if ( target_state - > pwr_domain_state [ ARM_PWR_LVL0 ] = =
ARM_LOCAL_STATE_RET )
return ;
assert ( target_state - > pwr_domain_state [ ARM_PWR_LVL0 ] = =
ARM_LOCAL_STATE_OFF ) ;
/*
* Setup mailbox with address for CPU entrypoint when it next powers up .
*/
css_program_mailbox ( read_mpidr_el1 ( ) , sec_entrypoint ) ;
css_program_mailbox ( read_mpidr_el1 ( ) , wakeup_address ) ;
css_power_down_common ( afflvl ) ;
css_power_down_common ( target_state ) ;
}
/*******************************************************************************
* Handler called when an affinity instance has just been powered on after
* having been suspended earlier . The level and mpidr determine the affinity
* instance .
* Handler called when a power domain has just been powered on after
* having been suspended earlier . The target_state encodes the low power state
* that each level has woken up from .
* TODO : At the moment we reuse the on finisher and reinitialize the secure
* context . Need to implement a separate suspend finisher .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void css_aff inst _suspend_finish ( uint32_t afflvl ,
uint32_t state )
static void css_pwr_dom ain_suspend_finish (
const psci_power_state_t * target_ state)
{
css_affinst_on_finish ( afflvl , state ) ;
/*
* Return as nothing is to be done on waking up from retention .
*/
if ( target_state - > pwr_domain_state [ ARM_PWR_LVL0 ] = =
ARM_LOCAL_STATE_RET )
return ;
css_pwr_domain_on_finish ( target_state ) ;
}
/*******************************************************************************
@ -244,12 +231,14 @@ static void __dead2 css_system_reset(void)
}
/*******************************************************************************
* Handler called when an affinity instance is about to enter standby .
* Handler called when the CPU power domain is about to enter standby .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void css_affinst_standby ( unsigned int power _state )
void css_cpu_standby ( plat_local_state_t cpu _state )
{
unsigned int scr ;
assert ( cpu_state = = ARM_LOCAL_STATE_RET ) ;
scr = read_scr_el3 ( ) ;
/* Enable PhysicalIRQ bit for NS world to wake the CPU */
write_scr_el3 ( scr | SCR_IRQ_BIT ) ;
@ -267,23 +256,28 @@ void css_affinst_standby(unsigned int power_state)
/*******************************************************************************
* Export the platform handlers to enable psci to invoke them
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static const plat_pm _ops_t css_ops = {
. aff inst _on = css_aff inst _on ,
. aff inst _on_finish = css_aff inst _on_finish ,
. aff inst _off = css_aff inst _off ,
. affinst_standby = css_affinst _standby,
. aff inst _suspend = css_aff inst _suspend ,
. aff inst _suspend_finish = css_aff inst _suspend_finish ,
static const plat_psci _ops_t css_ops = {
. pwr_dom ain_on = css_pwr_dom ain_on ,
. pwr_dom ain_on_finish = css_pwr_dom ain_on_finish ,
. pwr_dom ain_off = css_pwr_dom ain_off ,
. cpu_standby = css_cpu _standby,
. pwr_dom ain_suspend = css_pwr_dom ain_suspend ,
. pwr_dom ain_suspend_finish = css_pwr_dom ain_suspend_finish ,
. system_off = css_system_off ,
. system_reset = css_system_reset ,
. validate_power_state = arm_validate_power_state
} ;
/*******************************************************************************
* Export the platform specific power ops .
* Export the platform specific psci ops .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int32_t platform_setup_pm ( const plat_pm_ops_t * * plat_ops )
int plat_setup_psci_ops ( uintptr_t sec_entrypoint ,
const plat_psci_ops_t * * psci_ops )
{
* plat_ops = & css_ops ;
* psci_ops = & css_ops ;
wakeup_address = sec_entrypoint ;
flush_dcache_range ( ( unsigned long ) & wakeup_address ,
sizeof ( wakeup_address ) ) ;
return 0 ;
}