#include "psci_private.h"
typedef int (*afflvl_on_handler_t)(unsigned long target_cpu,
- aff_map_node_t *node,
- unsigned long ns_entrypoint,
- unsigned long context_id);
+ aff_map_node_t *node);
/*******************************************************************************
* This function checks whether a cpu which has been requested to be turned on
* TODO: Split this code across separate handlers for each type of setup?
******************************************************************************/
static int psci_afflvl0_on(unsigned long target_cpu,
- aff_map_node_t *cpu_node,
- unsigned long ns_entrypoint,
- unsigned long context_id)
+ aff_map_node_t *cpu_node)
{
unsigned long psci_entrypoint;
- uint32_t ns_scr_el3 = read_scr_el3();
- uint32_t ns_sctlr_el1 = read_sctlr_el1();
- int rc;
/* Sanity check to safeguard against data corruption */
assert(cpu_node->level == MPIDR_AFFLVL0);
if (psci_spd_pm && psci_spd_pm->svc_on)
psci_spd_pm->svc_on(target_cpu);
- /*
- * Arch. management: Derive the re-entry information for
- * the non-secure world from the non-secure state from
- * where this call originated.
- */
- rc = psci_save_ns_entry(target_cpu, ns_entrypoint, context_id,
- ns_scr_el3, ns_sctlr_el1);
- if (rc != PSCI_E_SUCCESS)
- return rc;
-
/* Set the secure world (EL3) re-entry point after BL1 */
psci_entrypoint = (unsigned long) psci_aff_on_finish_entry;
* TODO: Split this code across separate handlers for each type of setup?
******************************************************************************/
static int psci_afflvl1_on(unsigned long target_cpu,
- aff_map_node_t *cluster_node,
- unsigned long ns_entrypoint,
- unsigned long context_id)
+ aff_map_node_t *cluster_node)
{
unsigned long psci_entrypoint;
* TODO: Split this code across separate handlers for each type of setup?
******************************************************************************/
static int psci_afflvl2_on(unsigned long target_cpu,
- aff_map_node_t *system_node,
- unsigned long ns_entrypoint,
- unsigned long context_id)
+ aff_map_node_t *system_node)
{
unsigned long psci_entrypoint;
static int psci_call_on_handlers(aff_map_node_t *target_cpu_nodes[],
int start_afflvl,
int end_afflvl,
- unsigned long target_cpu,
- unsigned long entrypoint,
- unsigned long context_id)
+ unsigned long target_cpu)
{
int rc = PSCI_E_INVALID_PARAMS, level;
aff_map_node_t *node;
* affinity levels.
*/
rc = psci_afflvl_on_handlers[level](target_cpu,
- node,
- entrypoint,
- context_id);
+ node);
if (rc != PSCI_E_SUCCESS)
break;
}
* first.
******************************************************************************/
int psci_afflvl_on(unsigned long target_cpu,
- unsigned long entrypoint,
- unsigned long context_id,
+ entry_point_info_t *ep,
int start_afflvl,
int end_afflvl)
{
rc = psci_call_on_handlers(target_cpu_nodes,
start_afflvl,
end_afflvl,
- target_cpu,
- entrypoint,
- context_id);
+ target_cpu);
/*
* This function updates the state of each affinity instance
* corresponding to the mpidr in the range of affinity levels
* specified.
*/
- if (rc == PSCI_E_SUCCESS)
+ if (rc == PSCI_E_SUCCESS) {
psci_do_afflvl_state_mgmt(start_afflvl,
end_afflvl,
target_cpu_nodes,
PSCI_STATE_ON_PENDING);
+ /*
+ * Store the re-entry information for the non-secure world.
+ */
+ cm_init_context(target_cpu, ep);
+ }
exit:
/*
#include "psci_private.h"
typedef int (*afflvl_suspend_handler_t)(aff_map_node_t *node,
- unsigned long ns_entrypoint,
- unsigned long context_id,
unsigned int power_state);
/*******************************************************************************
* level which is called when that affinity level is about to be suspended.
******************************************************************************/
static int psci_afflvl0_suspend(aff_map_node_t *cpu_node,
- unsigned long ns_entrypoint,
- unsigned long context_id,
unsigned int power_state)
{
unsigned long psci_entrypoint;
- uint32_t ns_scr_el3 = read_scr_el3();
- uint32_t ns_sctlr_el1 = read_sctlr_el1();
- int rc;
/* Sanity check to safeguard against data corruption */
assert(cpu_node->level == MPIDR_AFFLVL0);
psci_set_suspend_power_state(power_state);
/*
- * Generic management: Store the re-entry information for the non-secure
- * world and allow the secure world to suspend itself
+ * Generic management: Allow the Secure world to suspend itself
*/
/*
if (psci_spd_pm && psci_spd_pm->svc_suspend)
psci_spd_pm->svc_suspend(power_state);
- /*
- * Generic management: Store the re-entry information for the
- * non-secure world
- */
- rc = psci_save_ns_entry(read_mpidr_el1(), ns_entrypoint, context_id,
- ns_scr_el3, ns_sctlr_el1);
- if (rc != PSCI_E_SUCCESS)
- return rc;
/* Set the secure world (EL3) re-entry point after BL1 */
psci_entrypoint = (unsigned long) psci_aff_suspend_finish_entry;
}
static int psci_afflvl1_suspend(aff_map_node_t *cluster_node,
- unsigned long ns_entrypoint,
- unsigned long context_id,
unsigned int power_state)
{
unsigned int plat_state;
static int psci_afflvl2_suspend(aff_map_node_t *system_node,
- unsigned long ns_entrypoint,
- unsigned long context_id,
unsigned int power_state)
{
unsigned int plat_state;
static int psci_call_suspend_handlers(aff_map_node_t *mpidr_nodes[],
int start_afflvl,
int end_afflvl,
- unsigned long entrypoint,
- unsigned long context_id,
unsigned int power_state)
{
int rc = PSCI_E_INVALID_PARAMS, level;
* lower affinity levels.
*/
rc = psci_afflvl_suspend_handlers[level](node,
- entrypoint,
- context_id,
power_state);
if (rc != PSCI_E_SUCCESS)
break;
* to turn off affinity level X it is neccesary to turn off affinity level X - 1
* first.
******************************************************************************/
-int psci_afflvl_suspend(unsigned long entrypoint,
- unsigned long context_id,
+int psci_afflvl_suspend(entry_point_info_t *ep,
unsigned int power_state,
int start_afflvl,
int end_afflvl)
/* Stash the highest affinity level that will be turned off */
psci_set_max_phys_off_afflvl(max_phys_off_afflvl);
+ /*
+ * Store the re-entry information for the non-secure world.
+ */
+ cm_init_context(read_mpidr_el1(), ep);
+
/* Perform generic, architecture and platform specific handling */
rc = psci_call_suspend_handlers(mpidr_nodes,
start_afflvl,
end_afflvl,
- entrypoint,
- context_id,
power_state);
/*
/*******************************************************************************
* This function determines the full entrypoint information for the requested
- * PSCI entrypoint on power on/resume and saves this in the non-secure CPU
- * cpu_context, ready for when the core boots.
+ * PSCI entrypoint on power on/resume and returns it.
******************************************************************************/
-int psci_save_ns_entry(uint64_t mpidr,
- uint64_t entrypoint, uint64_t context_id,
- uint32_t ns_scr_el3, uint32_t ns_sctlr_el1)
+int psci_get_ns_ep_info(entry_point_info_t *ep,
+ uint64_t entrypoint, uint64_t context_id)
{
uint32_t ep_attr, mode, sctlr, daif, ee;
- entry_point_info_t ep;
+ uint32_t ns_scr_el3 = read_scr_el3();
+ uint32_t ns_sctlr_el1 = read_sctlr_el1();
sctlr = ns_scr_el3 & SCR_HCE_BIT ? read_sctlr_el2() : ns_sctlr_el1;
ee = 0;
ep_attr |= EP_EE_BIG;
ee = 1;
}
- SET_PARAM_HEAD(&ep, PARAM_EP, VERSION_1, ep_attr);
+ SET_PARAM_HEAD(ep, PARAM_EP, VERSION_1, ep_attr);
- ep.pc = entrypoint;
- memset(&ep.args, 0, sizeof(ep.args));
- ep.args.arg0 = context_id;
+ ep->pc = entrypoint;
+ memset(&ep->args, 0, sizeof(ep->args));
+ ep->args.arg0 = context_id;
/*
* Figure out whether the cpu enters the non-secure address space
mode = ns_scr_el3 & SCR_HCE_BIT ? MODE_EL2 : MODE_EL1;
- ep.spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ ep->spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
} else {
mode = ns_scr_el3 & SCR_HCE_BIT ? MODE32_hyp : MODE32_svc;
*/
daif = DAIF_ABT_BIT | DAIF_IRQ_BIT | DAIF_FIQ_BIT;
- ep.spsr = SPSR_MODE32(mode, entrypoint & 0x1, ee, daif);
+ ep->spsr = SPSR_MODE32(mode, entrypoint & 0x1, ee, daif);
}
- /* initialise an entrypoint to set up the CPU context */
- cm_init_context(mpidr, &ep);
-
return PSCI_E_SUCCESS;
}
{
int rc;
unsigned int start_afflvl, end_afflvl;
+ entry_point_info_t ep;
/* Determine if the cpu exists of not */
rc = psci_validate_mpidr(target_cpu, MPIDR_AFFLVL0);
goto exit;
}
+ /*
+ * Verify and derive the re-entry information for
+ * the non-secure world from the non-secure state from
+ * where this call originated.
+ */
+ rc = psci_get_ns_ep_info(&ep, entrypoint, context_id);
+ if (rc != PSCI_E_SUCCESS)
+ return rc;
+
+
/*
* To turn this cpu on, specify which affinity
* levels need to be turned on
start_afflvl = MPIDR_AFFLVL0;
end_afflvl = get_max_afflvl();
rc = psci_afflvl_on(target_cpu,
- entrypoint,
- context_id,
+ &ep,
start_afflvl,
end_afflvl);
{
int rc;
unsigned int target_afflvl, pstate_type;
+ entry_point_info_t ep;
/* Check SBZ bits in power state are zero */
if (psci_validate_power_state(power_state))
return rc;
}
+ /*
+ * Verify and derive the re-entry information for
+ * the non-secure world from the non-secure state from
+ * where this call originated.
+ */
+ rc = psci_get_ns_ep_info(&ep, entrypoint, context_id);
+ if (rc != PSCI_E_SUCCESS)
+ return rc;
+
/*
* Do what is needed to enter the power down state. Upon success,
* enter the final wfi which will power down this cpu else return
* an error.
*/
- rc = psci_afflvl_suspend(entrypoint,
- context_id,
+ rc = psci_afflvl_suspend(&ep,
power_state,
MPIDR_AFFLVL0,
target_afflvl);
#include <arch.h>
#include <bakery_lock.h>
+#include <bl_common.h>
#include <psci.h>
/*
void psci_afflvl_power_on_finish(int,
int,
afflvl_power_on_finisher_t *);
-int psci_save_ns_entry(uint64_t mpidr,
- uint64_t entrypoint, uint64_t context_id,
- uint32_t caller_scr_el3, uint32_t caller_sctlr_el1);
+int psci_get_ns_ep_info(entry_point_info_t *ep,
+ uint64_t entrypoint, uint64_t context_id);
int psci_check_afflvl_range(int start_afflvl, int end_afflvl);
void psci_do_afflvl_state_mgmt(uint32_t start_afflvl,
uint32_t end_afflvl,
aff_map_node_t *psci_get_aff_map_node(unsigned long, int);
/* Private exported functions from psci_affinity_on.c */
-int psci_afflvl_on(unsigned long,
- unsigned long,
- unsigned long,
- int,
- int);
+int psci_afflvl_on(unsigned long target_cpu,
+ entry_point_info_t *ep,
+ int start_afflvl,
+ int end_afflvl);
/* Private exported functions from psci_affinity_off.c */
int psci_afflvl_off(int, int);
/* Private exported functions from psci_affinity_suspend.c */
-int psci_afflvl_suspend(unsigned long,
- unsigned long,
- unsigned int,
- int,
- int);
+int psci_afflvl_suspend(entry_point_info_t *ep,
+ unsigned int power_state,
+ int start_afflvl,
+ int end_afflvl);
+
unsigned int psci_afflvl_suspend_finish(int, int);
void psci_set_suspend_power_state(unsigned int power_state);