diff options
Diffstat (limited to 'services')
-rw-r--r-- | services/std_svc/psci1.0/psci_common.c | 37 | ||||
-rw-r--r-- | services/std_svc/psci1.0/psci_entry.S | 27 | ||||
-rw-r--r-- | services/std_svc/psci1.0/psci_on.c | 7 | ||||
-rw-r--r-- | services/std_svc/psci1.0/psci_private.h | 7 | ||||
-rw-r--r-- | services/std_svc/psci1.0/psci_setup.c | 3 | ||||
-rw-r--r-- | services/std_svc/psci1.0/psci_suspend.c | 11 |
6 files changed, 46 insertions, 46 deletions
diff --git a/services/std_svc/psci1.0/psci_common.c b/services/std_svc/psci1.0/psci_common.c index 70cc98d12..0b885cde3 100644 --- a/services/std_svc/psci1.0/psci_common.c +++ b/services/std_svc/psci1.0/psci_common.c @@ -189,7 +189,7 @@ unsigned int psci_is_last_on_cpu(void) * been physically powered up. It is expected to be called immediately after * reset from assembler code. ******************************************************************************/ -int get_power_on_target_pwrlvl(void) +static int get_power_on_target_pwrlvl(void) { int pwrlvl; @@ -651,11 +651,26 @@ int psci_get_ns_ep_info(entry_point_info_t *ep, * code to enable the gic cpu interface and for a cluster it will enable * coherency at the interconnect level in addition to gic cpu interface. ******************************************************************************/ -void psci_power_up_finish(int end_pwrlvl, - pwrlvl_power_on_finisher_t power_on_handler) +void psci_power_up_finish(void) { unsigned int cpu_idx = plat_my_core_pos(); psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} }; + int end_pwrlvl; + + /* + * Verify that we have been explicitly turned ON or resumed from + * suspend. + */ + if (psci_get_aff_info_state() == AFF_STATE_OFF) { + ERROR("Unexpected affinity info state"); + panic(); + } + + /* + * Get the maximum power domain level to traverse to after this cpu + * has been physically powered up. + */ + end_pwrlvl = get_power_on_target_pwrlvl(); /* * This function acquires the lock corresponding to each power level so @@ -668,9 +683,21 @@ void psci_power_up_finish(int end_pwrlvl, psci_get_target_local_pwr_states(end_pwrlvl, &state_info); /* - * Perform generic, architecture and platform specific handling. + * This CPU could be resuming from suspend or it could have just been + * turned on. To distinguish between these 2 cases, we examine the + * affinity state of the CPU: + * - If the affinity state is ON_PENDING then it has just been + * turned on. + * - Else it is resuming from suspend. + * + * Depending on the type of warm reset identified, choose the right set + * of power management handler and perform the generic, architecture + * and platform specific handling. */ - power_on_handler(cpu_idx, &state_info); + if (psci_get_aff_info_state() == AFF_STATE_ON_PENDING) + psci_cpu_on_finish(cpu_idx, &state_info); + else + psci_cpu_suspend_finish(cpu_idx, &state_info); /* * Set the requested and target state of this CPU and all the higher diff --git a/services/std_svc/psci1.0/psci_entry.S b/services/std_svc/psci1.0/psci_entry.S index 4e7456dbd..73c33779a 100644 --- a/services/std_svc/psci1.0/psci_entry.S +++ b/services/std_svc/psci1.0/psci_entry.S @@ -34,25 +34,16 @@ #include <psci.h> #include <xlat_tables.h> - .globl psci_cpu_on_finish_entry - .globl psci_cpu_suspend_finish_entry + .globl psci_entrypoint .globl psci_power_down_wfi - /* ----------------------------------------------------- - * This cpu has been physically powered up. Depending - * upon whether it was resumed from suspend or simply - * turned on, call the common power on finisher with - * the handlers (chosen depending upon original state). - * ----------------------------------------------------- + /* -------------------------------------------------------------------- + * This CPU has been physically powered up. It is either resuming from + * suspend or has simply been turned on. In both cases, call the power + * on finisher. + * -------------------------------------------------------------------- */ -func psci_cpu_on_finish_entry - adr x23, psci_cpu_on_finish - b psci_power_up_entry - -psci_cpu_suspend_finish_entry: - adr x23, psci_cpu_suspend_finish - -psci_power_up_entry: +func psci_entrypoint /* * On the warm boot path, most of the EL3 initialisations performed by * 'el3_entrypoint_common' must be skipped: @@ -98,12 +89,10 @@ psci_power_up_entry: mov x0, #DISABLE_DCACHE bl bl31_plat_enable_mmu - bl get_power_on_target_pwrlvl - mov x1, x23 bl psci_power_up_finish b el3_exit -endfunc psci_cpu_on_finish_entry +endfunc psci_entrypoint /* -------------------------------------------- * This function is called to indicate to the diff --git a/services/std_svc/psci1.0/psci_on.c b/services/std_svc/psci1.0/psci_on.c index 542cc239e..d68198f2e 100644 --- a/services/std_svc/psci1.0/psci_on.c +++ b/services/std_svc/psci1.0/psci_on.c @@ -89,7 +89,6 @@ int psci_cpu_on_start(unsigned long target_cpu, int end_pwrlvl) { int rc; - unsigned long psci_entrypoint; unsigned int target_idx = plat_core_pos_by_mpidr(target_cpu); /* @@ -126,16 +125,12 @@ int psci_cpu_on_start(unsigned long target_cpu, /* * Perform generic, architecture and platform specific handling. */ - /* Set the secure world (EL3) re-entry point after BL1 */ - psci_entrypoint = (unsigned long) psci_cpu_on_finish_entry; - /* * Plat. management: Give the platform the current state * of the target cpu to allow it to perform the necessary * steps to power on. */ - rc = psci_plat_pm_ops->pwr_domain_on((u_register_t)target_cpu, - psci_entrypoint); + rc = psci_plat_pm_ops->pwr_domain_on((u_register_t)target_cpu); assert(rc == PSCI_E_SUCCESS || rc == PSCI_E_INTERN_FAIL); if (rc == PSCI_E_SUCCESS) diff --git a/services/std_svc/psci1.0/psci_private.h b/services/std_svc/psci1.0/psci_private.h index 8d08df4da..e2e32c796 100644 --- a/services/std_svc/psci1.0/psci_private.h +++ b/services/std_svc/psci1.0/psci_private.h @@ -166,9 +166,6 @@ typedef struct cpu_pwr_domain_node { spinlock_t cpu_lock; } cpu_pd_node_t; -typedef void (*pwrlvl_power_on_finisher_t)(unsigned int cpu_idx, - psci_power_state_t *state_info); - /******************************************************************************* * Data prototypes ******************************************************************************/ @@ -190,10 +187,8 @@ int psci_validate_power_state(unsigned int power_state, psci_power_state_t *state_info); void psci_query_sys_suspend_pwrstate(psci_power_state_t *state_info); int psci_validate_mpidr(unsigned long mpidr); -int get_power_on_target_pwrlvl(void); void psci_init_req_local_pwr_states(void); -void psci_power_up_finish(int end_pwrlvl, - pwrlvl_power_on_finisher_t power_on_handler); +void psci_power_up_finish(void); int psci_get_ns_ep_info(entry_point_info_t *ep, uint64_t entrypoint, uint64_t context_id); void psci_get_parent_pwr_domain_nodes(unsigned int cpu_idx, diff --git a/services/std_svc/psci1.0/psci_setup.c b/services/std_svc/psci1.0/psci_setup.c index 599c09bcb..ce4da9599 100644 --- a/services/std_svc/psci1.0/psci_setup.c +++ b/services/std_svc/psci1.0/psci_setup.c @@ -245,7 +245,8 @@ int32_t psci_setup(void) */ psci_set_pwr_domains_to_run(PLAT_MAX_PWR_LVL); - plat_setup_psci_ops(&psci_plat_pm_ops); + plat_setup_psci_ops((uintptr_t)psci_entrypoint, + &psci_plat_pm_ops); assert(psci_plat_pm_ops); /* Initialize the psci capability */ diff --git a/services/std_svc/psci1.0/psci_suspend.c b/services/std_svc/psci1.0/psci_suspend.c index 2e4270f0a..71e477842 100644 --- a/services/std_svc/psci1.0/psci_suspend.c +++ b/services/std_svc/psci1.0/psci_suspend.c @@ -133,7 +133,6 @@ void psci_cpu_suspend_start(entry_point_info_t *ep, { int skip_wfi = 0; unsigned int idx = plat_my_core_pos(); - unsigned long psci_entrypoint; /* * This function must only be called on platforms where the @@ -167,22 +166,16 @@ void psci_cpu_suspend_start(entry_point_info_t *ep, */ psci_do_state_coordination(end_pwrlvl, state_info); - psci_entrypoint = 0; - if (is_power_down_state) { + if (is_power_down_state) psci_suspend_to_pwrdown_start(end_pwrlvl, ep, state_info); - /* Set the secure world (EL3) re-entry point after BL1. */ - psci_entrypoint = - (unsigned long) psci_cpu_suspend_finish_entry; - } - /* * Plat. management: Allow the platform to perform the * necessary actions to turn off this cpu e.g. set the * platform defined mailbox with the psci entrypoint, * program the power controller etc. */ - psci_plat_pm_ops->pwr_domain_suspend(psci_entrypoint, state_info); + psci_plat_pm_ops->pwr_domain_suspend(state_info); exit: /* |