summaryrefslogtreecommitdiff
path: root/services
diff options
context:
space:
mode:
authorSoby Mathew <soby.mathew@arm.com>2016-03-24 16:56:29 +0000
committerSoby Mathew <soby.mathew@arm.com>2016-07-18 17:52:15 +0100
commit532ed6183868036e4a4f83cd7a71b93266a3bdb7 (patch)
treef49b622aa47b6b94eebfb58de1f59df30dd6c423 /services
parentda554d7439b1e9b64d06dd50c6eb29bf1c952805 (diff)
Introduce `el3_runtime` and `PSCI` libraries
This patch moves the PSCI services and BL31 frameworks like context management and per-cpu data into new library components `PSCI` and `el3_runtime` respectively. This enables PSCI to be built independently from BL31. A new `psci_lib.mk` makefile is introduced which adds the relevant PSCI library sources and gets included by `bl31.mk`. Other changes which are done as part of this patch are: * The runtime services framework is now moved to the `common/` folder to enable reuse. * The `asm_macros.S` and `assert_macros.S` helpers are moved to architecture specific folder. * The `plat_psci_common.c` is moved from the `plat/common/aarch64/` folder to `plat/common` folder. The original file location now has a stub which just includes the file from new location to maintain platform compatibility. Most of the changes wouldn't affect platform builds as they just involve changes to the generic bl1.mk and bl31.mk makefiles. NOTE: THE `plat_psci_common.c` FILE HAS MOVED LOCATION AND THE STUB FILE AT THE ORIGINAL LOCATION IS NOW DEPRECATED. PLATFORMS SHOULD MODIFY THEIR MAKEFILES TO INCLUDE THE FILE FROM THE NEW LOCATION. Change-Id: I6bd87d5b59424995c6a65ef8076d4fda91ad5e86
Diffstat (limited to 'services')
-rw-r--r--services/std_svc/psci/psci_common.c928
-rw-r--r--services/std_svc/psci/psci_entry.S111
-rw-r--r--services/std_svc/psci/psci_helpers.S154
-rw-r--r--services/std_svc/psci/psci_main.c440
-rw-r--r--services/std_svc/psci/psci_off.c169
-rw-r--r--services/std_svc/psci/psci_on.c212
-rw-r--r--services/std_svc/psci/psci_private.h254
-rw-r--r--services/std_svc/psci/psci_setup.c261
-rw-r--r--services/std_svc/psci/psci_stat.c309
-rw-r--r--services/std_svc/psci/psci_suspend.c284
-rw-r--r--services/std_svc/psci/psci_system_off.c70
11 files changed, 0 insertions, 3192 deletions
diff --git a/services/std_svc/psci/psci_common.c b/services/std_svc/psci/psci_common.c
deleted file mode 100644
index 2a0afb4c..00000000
--- a/services/std_svc/psci/psci_common.c
+++ /dev/null
@@ -1,928 +0,0 @@
-/*
- * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <arch.h>
-#include <arch_helpers.h>
-#include <assert.h>
-#include <bl_common.h>
-#include <context.h>
-#include <context_mgmt.h>
-#include <debug.h>
-#include <platform.h>
-#include <string.h>
-#include "psci_private.h"
-
-/*
- * SPD power management operations, expected to be supplied by the registered
- * SPD on successful SP initialization
- */
-const spd_pm_ops_t *psci_spd_pm;
-
-/*
- * PSCI requested local power state map. This array is used to store the local
- * power states requested by a CPU for power levels from level 1 to
- * PLAT_MAX_PWR_LVL. It does not store the requested local power state for power
- * level 0 (PSCI_CPU_PWR_LVL) as the requested and the target power state for a
- * CPU are the same.
- *
- * During state coordination, the platform is passed an array containing the
- * local states requested for a particular non cpu power domain by each cpu
- * within the domain.
- *
- * TODO: Dense packing of the requested states will cause cache thrashing
- * when multiple power domains write to it. If we allocate the requested
- * states at each power level in a cache-line aligned per-domain memory,
- * the cache thrashing can be avoided.
- */
-static plat_local_state_t
- psci_req_local_pwr_states[PLAT_MAX_PWR_LVL][PLATFORM_CORE_COUNT];
-
-
-/*******************************************************************************
- * Arrays that hold the platform's power domain tree information for state
- * management of power domains.
- * Each node in the array 'psci_non_cpu_pd_nodes' corresponds to a power domain
- * which is an ancestor of a CPU power domain.
- * Each node in the array 'psci_cpu_pd_nodes' corresponds to a cpu power domain
- ******************************************************************************/
-non_cpu_pd_node_t psci_non_cpu_pd_nodes[PSCI_NUM_NON_CPU_PWR_DOMAINS]
-#if USE_COHERENT_MEM
-__section("tzfw_coherent_mem")
-#endif
-;
-
-DEFINE_BAKERY_LOCK(psci_locks[PSCI_NUM_NON_CPU_PWR_DOMAINS]);
-
-cpu_pd_node_t psci_cpu_pd_nodes[PLATFORM_CORE_COUNT];
-
-/*******************************************************************************
- * Pointer to functions exported by the platform to complete power mgmt. ops
- ******************************************************************************/
-const plat_psci_ops_t *psci_plat_pm_ops;
-
-/******************************************************************************
- * Check that the maximum power level supported by the platform makes sense
- *****************************************************************************/
-CASSERT(PLAT_MAX_PWR_LVL <= PSCI_MAX_PWR_LVL && \
- PLAT_MAX_PWR_LVL >= PSCI_CPU_PWR_LVL, \
- assert_platform_max_pwrlvl_check);
-
-/*
- * The plat_local_state used by the platform is one of these types: RUN,
- * RETENTION and OFF. The platform can define further sub-states for each type
- * apart from RUN. This categorization is done to verify the sanity of the
- * psci_power_state passed by the platform and to print debug information. The
- * categorization is done on the basis of the following conditions:
- *
- * 1. If (plat_local_state == 0) then the category is STATE_TYPE_RUN.
- *
- * 2. If (0 < plat_local_state <= PLAT_MAX_RET_STATE), then the category is
- * STATE_TYPE_RETN.
- *
- * 3. If (plat_local_state > PLAT_MAX_RET_STATE), then the category is
- * STATE_TYPE_OFF.
- */
-typedef enum plat_local_state_type {
- STATE_TYPE_RUN = 0,
- STATE_TYPE_RETN,
- STATE_TYPE_OFF
-} plat_local_state_type_t;
-
-/* The macro used to categorize plat_local_state. */
-#define find_local_state_type(plat_local_state) \
- ((plat_local_state) ? ((plat_local_state > PLAT_MAX_RET_STATE) \
- ? STATE_TYPE_OFF : STATE_TYPE_RETN) \
- : STATE_TYPE_RUN)
-
-/******************************************************************************
- * Check that the maximum retention level supported by the platform is less
- * than the maximum off level.
- *****************************************************************************/
-CASSERT(PLAT_MAX_RET_STATE < PLAT_MAX_OFF_STATE, \
- assert_platform_max_off_and_retn_state_check);
-
-/******************************************************************************
- * This function ensures that the power state parameter in a CPU_SUSPEND request
- * is valid. If so, it returns the requested states for each power level.
- *****************************************************************************/
-int psci_validate_power_state(unsigned int power_state,
- psci_power_state_t *state_info)
-{
- /* Check SBZ bits in power state are zero */
- if (psci_check_power_state(power_state))
- return PSCI_E_INVALID_PARAMS;
-
- assert(psci_plat_pm_ops->validate_power_state);
-
- /* Validate the power_state using platform pm_ops */
- return psci_plat_pm_ops->validate_power_state(power_state, state_info);
-}
-
-/******************************************************************************
- * This function retrieves the `psci_power_state_t` for system suspend from
- * the platform.
- *****************************************************************************/
-void psci_query_sys_suspend_pwrstate(psci_power_state_t *state_info)
-{
- /*
- * Assert that the required pm_ops hook is implemented to ensure that
- * the capability detected during psci_setup() is valid.
- */
- assert(psci_plat_pm_ops->get_sys_suspend_power_state);
-
- /*
- * Query the platform for the power_state required for system suspend
- */
- psci_plat_pm_ops->get_sys_suspend_power_state(state_info);
-}
-
-/*******************************************************************************
- * This function verifies that the all the other cores in the system have been
- * turned OFF and the current CPU is the last running CPU in the system.
- * Returns 1 (true) if the current CPU is the last ON CPU or 0 (false)
- * otherwise.
- ******************************************************************************/
-unsigned int psci_is_last_on_cpu(void)
-{
- unsigned int cpu_idx, my_idx = plat_my_core_pos();
-
- for (cpu_idx = 0; cpu_idx < PLATFORM_CORE_COUNT; cpu_idx++) {
- if (cpu_idx == my_idx) {
- assert(psci_get_aff_info_state() == AFF_STATE_ON);
- continue;
- }
-
- if (psci_get_aff_info_state_by_idx(cpu_idx) != AFF_STATE_OFF)
- return 0;
- }
-
- return 1;
-}
-
-/*******************************************************************************
- * Routine to return the maximum power level to traverse to after a cpu has
- * been physically powered up. It is expected to be called immediately after
- * reset from assembler code.
- ******************************************************************************/
-static unsigned int get_power_on_target_pwrlvl(void)
-{
- unsigned int pwrlvl;
-
- /*
- * Assume that this cpu was suspended and retrieve its target power
- * level. If it is invalid then it could only have been turned off
- * earlier. PLAT_MAX_PWR_LVL will be the highest power level a
- * cpu can be turned off to.
- */
- pwrlvl = psci_get_suspend_pwrlvl();
- if (pwrlvl == PSCI_INVALID_PWR_LVL)
- pwrlvl = PLAT_MAX_PWR_LVL;
- return pwrlvl;
-}
-
-/******************************************************************************
- * Helper function to update the requested local power state array. This array
- * does not store the requested state for the CPU power level. Hence an
- * assertion is added to prevent us from accessing the wrong index.
- *****************************************************************************/
-static void psci_set_req_local_pwr_state(unsigned int pwrlvl,
- unsigned int cpu_idx,
- plat_local_state_t req_pwr_state)
-{
- assert(pwrlvl > PSCI_CPU_PWR_LVL);
- psci_req_local_pwr_states[pwrlvl - 1][cpu_idx] = req_pwr_state;
-}
-
-/******************************************************************************
- * This function initializes the psci_req_local_pwr_states.
- *****************************************************************************/
-void psci_init_req_local_pwr_states(void)
-{
- /* Initialize the requested state of all non CPU power domains as OFF */
- memset(&psci_req_local_pwr_states, PLAT_MAX_OFF_STATE,
- sizeof(psci_req_local_pwr_states));
-}
-
-/******************************************************************************
- * Helper function to return a reference to an array containing the local power
- * states requested by each cpu for a power domain at 'pwrlvl'. The size of the
- * array will be the number of cpu power domains of which this power domain is
- * an ancestor. These requested states will be used to determine a suitable
- * target state for this power domain during psci state coordination. An
- * assertion is added to prevent us from accessing the CPU power level.
- *****************************************************************************/
-static plat_local_state_t *psci_get_req_local_pwr_states(unsigned int pwrlvl,
- unsigned int cpu_idx)
-{
- assert(pwrlvl > PSCI_CPU_PWR_LVL);
-
- return &psci_req_local_pwr_states[pwrlvl - 1][cpu_idx];
-}
-
-/******************************************************************************
- * Helper function to return the current local power state of each power domain
- * from the current cpu power domain to its ancestor at the 'end_pwrlvl'. This
- * function will be called after a cpu is powered on to find the local state
- * each power domain has emerged from.
- *****************************************************************************/
-static void psci_get_target_local_pwr_states(unsigned int end_pwrlvl,
- psci_power_state_t *target_state)
-{
- unsigned int parent_idx, lvl;
- plat_local_state_t *pd_state = target_state->pwr_domain_state;
-
- pd_state[PSCI_CPU_PWR_LVL] = psci_get_cpu_local_state();
- parent_idx = psci_cpu_pd_nodes[plat_my_core_pos()].parent_node;
-
- /* Copy the local power state from node to state_info */
- for (lvl = PSCI_CPU_PWR_LVL + 1; lvl <= end_pwrlvl; lvl++) {
-#if !USE_COHERENT_MEM
- /*
- * If using normal memory for psci_non_cpu_pd_nodes, we need
- * to flush before reading the local power state as another
- * cpu in the same power domain could have updated it and this
- * code runs before caches are enabled.
- */
- flush_dcache_range(
- (uintptr_t) &psci_non_cpu_pd_nodes[parent_idx],
- sizeof(psci_non_cpu_pd_nodes[parent_idx]));
-#endif
- pd_state[lvl] = psci_non_cpu_pd_nodes[parent_idx].local_state;
- parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node;
- }
-
- /* Set the the higher levels to RUN */
- for (; lvl <= PLAT_MAX_PWR_LVL; lvl++)
- target_state->pwr_domain_state[lvl] = PSCI_LOCAL_STATE_RUN;
-}
-
-/******************************************************************************
- * Helper function to set the target local power state that each power domain
- * from the current cpu power domain to its ancestor at the 'end_pwrlvl' will
- * enter. This function will be called after coordination of requested power
- * states has been done for each power level.
- *****************************************************************************/
-static void psci_set_target_local_pwr_states(unsigned int end_pwrlvl,
- const psci_power_state_t *target_state)
-{
- unsigned int parent_idx, lvl;
- const plat_local_state_t *pd_state = target_state->pwr_domain_state;
-
- psci_set_cpu_local_state(pd_state[PSCI_CPU_PWR_LVL]);
-
- /*
- * Need to flush as local_state will be accessed with Data Cache
- * disabled during power on
- */
- flush_cpu_data(psci_svc_cpu_data.local_state);
-
- parent_idx = psci_cpu_pd_nodes[plat_my_core_pos()].parent_node;
-
- /* Copy the local_state from state_info */
- for (lvl = 1; lvl <= end_pwrlvl; lvl++) {
- psci_non_cpu_pd_nodes[parent_idx].local_state = pd_state[lvl];
-#if !USE_COHERENT_MEM
- flush_dcache_range(
- (uintptr_t)&psci_non_cpu_pd_nodes[parent_idx],
- sizeof(psci_non_cpu_pd_nodes[parent_idx]));
-#endif
- parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node;
- }
-}
-
-
-/*******************************************************************************
- * PSCI helper function to get the parent nodes corresponding to a cpu_index.
- ******************************************************************************/
-void psci_get_parent_pwr_domain_nodes(unsigned int cpu_idx,
- unsigned int end_lvl,
- unsigned int node_index[])
-{
- unsigned int parent_node = psci_cpu_pd_nodes[cpu_idx].parent_node;
- int i;
-
- for (i = PSCI_CPU_PWR_LVL + 1; i <= end_lvl; i++) {
- *node_index++ = parent_node;
- parent_node = psci_non_cpu_pd_nodes[parent_node].parent_node;
- }
-}
-
-/******************************************************************************
- * This function is invoked post CPU power up and initialization. It sets the
- * affinity info state, target power state and requested power state for the
- * current CPU and all its ancestor power domains to RUN.
- *****************************************************************************/
-void psci_set_pwr_domains_to_run(unsigned int end_pwrlvl)
-{
- unsigned int parent_idx, cpu_idx = plat_my_core_pos(), lvl;
- parent_idx = psci_cpu_pd_nodes[cpu_idx].parent_node;
-
- /* Reset the local_state to RUN for the non cpu power domains. */
- for (lvl = PSCI_CPU_PWR_LVL + 1; lvl <= end_pwrlvl; lvl++) {
- psci_non_cpu_pd_nodes[parent_idx].local_state =
- PSCI_LOCAL_STATE_RUN;
-#if !USE_COHERENT_MEM
- flush_dcache_range(
- (uintptr_t) &psci_non_cpu_pd_nodes[parent_idx],
- sizeof(psci_non_cpu_pd_nodes[parent_idx]));
-#endif
- psci_set_req_local_pwr_state(lvl,
- cpu_idx,
- PSCI_LOCAL_STATE_RUN);
- parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node;
- }
-
- /* Set the affinity info state to ON */
- psci_set_aff_info_state(AFF_STATE_ON);
-
- psci_set_cpu_local_state(PSCI_LOCAL_STATE_RUN);
- flush_cpu_data(psci_svc_cpu_data);
-}
-
-/******************************************************************************
- * This function is passed the local power states requested for each power
- * domain (state_info) between the current CPU domain and its ancestors until
- * the target power level (end_pwrlvl). It updates the array of requested power
- * states with this information.
- *
- * Then, for each level (apart from the CPU level) until the 'end_pwrlvl', it
- * retrieves the states requested by all the cpus of which the power domain at
- * that level is an ancestor. It passes this information to the platform to
- * coordinate and return the target power state. If the target state for a level
- * is RUN then subsequent levels are not considered. At the CPU level, state
- * coordination is not required. Hence, the requested and the target states are
- * the same.
- *
- * The 'state_info' is updated with the target state for each level between the
- * CPU and the 'end_pwrlvl' and returned to the caller.
- *
- * This function will only be invoked with data cache enabled and while
- * powering down a core.
- *****************************************************************************/
-void psci_do_state_coordination(unsigned int end_pwrlvl,
- psci_power_state_t *state_info)
-{
- unsigned int lvl, parent_idx, cpu_idx = plat_my_core_pos();
- unsigned int start_idx, ncpus;
- plat_local_state_t target_state, *req_states;
-
- assert(end_pwrlvl <= PLAT_MAX_PWR_LVL);
- parent_idx = psci_cpu_pd_nodes[cpu_idx].parent_node;
-
- /* For level 0, the requested state will be equivalent
- to target state */
- for (lvl = PSCI_CPU_PWR_LVL + 1; lvl <= end_pwrlvl; lvl++) {
-
- /* First update the requested power state */
- psci_set_req_local_pwr_state(lvl, cpu_idx,
- state_info->pwr_domain_state[lvl]);
-
- /* Get the requested power states for this power level */
- start_idx = psci_non_cpu_pd_nodes[parent_idx].cpu_start_idx;
- req_states = psci_get_req_local_pwr_states(lvl, start_idx);
-
- /*
- * Let the platform coordinate amongst the requested states at
- * this power level and return the target local power state.
- */
- ncpus = psci_non_cpu_pd_nodes[parent_idx].ncpus;
- target_state = plat_get_target_pwr_state(lvl,
- req_states,
- ncpus);
-
- state_info->pwr_domain_state[lvl] = target_state;
-
- /* Break early if the negotiated target power state is RUN */
- if (is_local_state_run(state_info->pwr_domain_state[lvl]))
- break;
-
- parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node;
- }
-
- /*
- * This is for cases when we break out of the above loop early because
- * the target power state is RUN at a power level < end_pwlvl.
- * We update the requested power state from state_info and then
- * set the target state as RUN.
- */
- for (lvl = lvl + 1; lvl <= end_pwrlvl; lvl++) {
- psci_set_req_local_pwr_state(lvl, cpu_idx,
- state_info->pwr_domain_state[lvl]);
- state_info->pwr_domain_state[lvl] = PSCI_LOCAL_STATE_RUN;
-
- }
-
- /* Update the target state in the power domain nodes */
- psci_set_target_local_pwr_states(end_pwrlvl, state_info);
-}
-
-/******************************************************************************
- * This function validates a suspend request by making sure that if a standby
- * state is requested then no power level is turned off and the highest power
- * level is placed in a standby/retention state.
- *
- * It also ensures that the state level X will enter is not shallower than the
- * state level X + 1 will enter.
- *
- * This validation will be enabled only for DEBUG builds as the platform is
- * expected to perform these validations as well.
- *****************************************************************************/
-int psci_validate_suspend_req(const psci_power_state_t *state_info,
- unsigned int is_power_down_state)
-{
- unsigned int max_off_lvl, target_lvl, max_retn_lvl;
- plat_local_state_t state;
- plat_local_state_type_t req_state_type, deepest_state_type;
- int i;
-
- /* Find the target suspend power level */
- target_lvl = psci_find_target_suspend_lvl(state_info);
- if (target_lvl == PSCI_INVALID_PWR_LVL)
- return PSCI_E_INVALID_PARAMS;
-
- /* All power domain levels are in a RUN state to begin with */
- deepest_state_type = STATE_TYPE_RUN;
-
- for (i = target_lvl; i >= PSCI_CPU_PWR_LVL; i--) {
- state = state_info->pwr_domain_state[i];
- req_state_type = find_local_state_type(state);
-
- /*
- * While traversing from the highest power level to the lowest,
- * the state requested for lower levels has to be the same or
- * deeper i.e. equal to or greater than the state at the higher
- * levels. If this condition is true, then the requested state
- * becomes the deepest state encountered so far.
- */
- if (req_state_type < deepest_state_type)
- return PSCI_E_INVALID_PARAMS;
- deepest_state_type = req_state_type;
- }
-
- /* Find the highest off power level */
- max_off_lvl = psci_find_max_off_lvl(state_info);
-
- /* The target_lvl is either equal to the max_off_lvl or max_retn_lvl */
- max_retn_lvl = PSCI_INVALID_PWR_LVL;
- if (target_lvl != max_off_lvl)
- max_retn_lvl = target_lvl;
-
- /*
- * If this is not a request for a power down state then max off level
- * has to be invalid and max retention level has to be a valid power
- * level.
- */
- if (!is_power_down_state && (max_off_lvl != PSCI_INVALID_PWR_LVL ||
- max_retn_lvl == PSCI_INVALID_PWR_LVL))
- return PSCI_E_INVALID_PARAMS;
-
- return PSCI_E_SUCCESS;
-}
-
-/******************************************************************************
- * This function finds the highest power level which will be powered down
- * amongst all the power levels specified in the 'state_info' structure
- *****************************************************************************/
-unsigned int psci_find_max_off_lvl(const psci_power_state_t *state_info)
-{
- int i;
-
- for (i = PLAT_MAX_PWR_LVL; i >= PSCI_CPU_PWR_LVL; i--) {
- if (is_local_state_off(state_info->pwr_domain_state[i]))
- return i;
- }
-
- return PSCI_INVALID_PWR_LVL;
-}
-
-/******************************************************************************
- * This functions finds the level of the highest power domain which will be
- * placed in a low power state during a suspend operation.
- *****************************************************************************/
-unsigned int psci_find_target_suspend_lvl(const psci_power_state_t *state_info)
-{
- int i;
-
- for (i = PLAT_MAX_PWR_LVL; i >= PSCI_CPU_PWR_LVL; i--) {
- if (!is_local_state_run(state_info->pwr_domain_state[i]))
- return i;
- }
-
- return PSCI_INVALID_PWR_LVL;
-}
-
-/*******************************************************************************
- * This function is passed a cpu_index and the highest level in the topology
- * tree that the operation should be applied to. It picks up locks in order of
- * increasing power domain level in the range specified.
- ******************************************************************************/
-void psci_acquire_pwr_domain_locks(unsigned int end_pwrlvl,
- unsigned int cpu_idx)
-{
- unsigned int parent_idx = psci_cpu_pd_nodes[cpu_idx].parent_node;
- unsigned int level;
-
- /* No locking required for level 0. Hence start locking from level 1 */
- for (level = PSCI_CPU_PWR_LVL + 1; level <= end_pwrlvl; level++) {
- psci_lock_get(&psci_non_cpu_pd_nodes[parent_idx]);
- parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node;
- }
-}
-
-/*******************************************************************************
- * This function is passed a cpu_index and the highest level in the topology
- * tree that the operation should be applied to. It releases the locks in order
- * of decreasing power domain level in the range specified.
- ******************************************************************************/
-void psci_release_pwr_domain_locks(unsigned int end_pwrlvl,
- unsigned int cpu_idx)
-{
- unsigned int parent_idx, parent_nodes[PLAT_MAX_PWR_LVL] = {0};
- int level;
-
- /* Get the parent nodes */
- psci_get_parent_pwr_domain_nodes(cpu_idx, end_pwrlvl, parent_nodes);
-
- /* Unlock top down. No unlocking required for level 0. */
- for (level = end_pwrlvl; level >= PSCI_CPU_PWR_LVL + 1; level--) {
- parent_idx = parent_nodes[level - 1];
- psci_lock_release(&psci_non_cpu_pd_nodes[parent_idx]);
- }
-}
-
-/*******************************************************************************
- * Simple routine to determine whether a mpidr is valid or not.
- ******************************************************************************/
-int psci_validate_mpidr(u_register_t mpidr)
-{
- if (plat_core_pos_by_mpidr(mpidr) < 0)
- return PSCI_E_INVALID_PARAMS;
-
- return PSCI_E_SUCCESS;
-}
-
-/*******************************************************************************
- * This function determines the full entrypoint information for the requested
- * PSCI entrypoint on power on/resume and returns it.
- ******************************************************************************/
-static int psci_get_ns_ep_info(entry_point_info_t *ep,
- uintptr_t entrypoint,
- u_register_t context_id)
-{
- u_register_t ep_attr, sctlr;
- unsigned int daif, ee, mode;
- u_register_t ns_scr_el3 = read_scr_el3();
- u_register_t ns_sctlr_el1 = read_sctlr_el1();
-
- sctlr = ns_scr_el3 & SCR_HCE_BIT ? read_sctlr_el2() : ns_sctlr_el1;
- ee = 0;
-
- ep_attr = NON_SECURE | EP_ST_DISABLE;
- if (sctlr & SCTLR_EE_BIT) {
- ep_attr |= EP_EE_BIG;
- ee = 1;
- }
- 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;
-
- /*
- * Figure out whether the cpu enters the non-secure address space
- * in aarch32 or aarch64
- */
- if (ns_scr_el3 & SCR_RW_BIT) {
-
- /*
- * Check whether a Thumb entry point has been provided for an
- * aarch64 EL
- */
- if (entrypoint & 0x1)
- return PSCI_E_INVALID_ADDRESS;
-
- mode = ns_scr_el3 & SCR_HCE_BIT ? MODE_EL2 : MODE_EL1;
-
- ep->spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
- } else {
-
- mode = ns_scr_el3 & SCR_HCE_BIT ? MODE32_hyp : MODE32_svc;
-
- /*
- * TODO: Choose async. exception bits if HYP mode is not
- * implemented according to the values of SCR.{AW, FW} bits
- */
- daif = DAIF_ABT_BIT | DAIF_IRQ_BIT | DAIF_FIQ_BIT;
-
- ep->spsr = SPSR_MODE32(mode, entrypoint & 0x1, ee, daif);
- }
-
- return PSCI_E_SUCCESS;
-}
-
-/*******************************************************************************
- * This function validates the entrypoint with the platform layer if the
- * appropriate pm_ops hook is exported by the platform and returns the
- * 'entry_point_info'.
- ******************************************************************************/
-int psci_validate_entry_point(entry_point_info_t *ep,
- uintptr_t entrypoint,
- u_register_t context_id)
-{
- int rc;
-
- /* Validate the entrypoint using platform psci_ops */
- if (psci_plat_pm_ops->validate_ns_entrypoint) {
- rc = psci_plat_pm_ops->validate_ns_entrypoint(entrypoint);
- if (rc != PSCI_E_SUCCESS)
- return PSCI_E_INVALID_ADDRESS;
- }
-
- /*
- * 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);
- return rc;
-}
-
-/*******************************************************************************
- * Generic handler which is called when a cpu is physically powered on. It
- * traverses the node information and finds the highest power level powered
- * off and performs generic, architectural, platform setup and state management
- * to power on that power level and power levels below it.
- * e.g. For a cpu that's been powered on, it will call the platform specific
- * 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(void)
-{
- unsigned int end_pwrlvl, cpu_idx = plat_my_core_pos();
- psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} };
-
- /*
- * 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
- * that by the time all locks are taken, the system topology is snapshot
- * and state management can be done safely.
- */
- psci_acquire_pwr_domain_locks(end_pwrlvl,
- cpu_idx);
-
-#if ENABLE_PSCI_STAT
- /*
- * Capture power up time-stamp.
- * No cache maintenance is required as caches are off
- * and writes are direct to the main memory.
- */
- PMF_CAPTURE_TIMESTAMP(psci_svc, PSCI_STAT_ID_EXIT_LOW_PWR,
- PMF_NO_CACHE_MAINT);
-#endif
-
- psci_get_target_local_pwr_states(end_pwrlvl, &state_info);
-
- /*
- * 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.
- */
- 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
- * power domains which are ancestors of this CPU to run.
- */
- psci_set_pwr_domains_to_run(end_pwrlvl);
-
-#if ENABLE_PSCI_STAT
- /*
- * Update PSCI stats.
- * Caches are off when writing stats data on the power down path.
- * Since caches are now enabled, it's necessary to do cache
- * maintenance before reading that same data.
- */
- psci_stats_update_pwr_up(end_pwrlvl, &state_info, PMF_CACHE_MAINT);
-#endif
-
- /*
- * This loop releases the lock corresponding to each power level
- * in the reverse order to which they were acquired.
- */
- psci_release_pwr_domain_locks(end_pwrlvl,
- cpu_idx);
-}
-
-/*******************************************************************************
- * This function initializes the set of hooks that PSCI invokes as part of power
- * management operation. The power management hooks are expected to be provided
- * by the SPD, after it finishes all its initialization
- ******************************************************************************/
-void psci_register_spd_pm_hook(const spd_pm_ops_t *pm)
-{
- assert(pm);
- psci_spd_pm = pm;
-
- if (pm->svc_migrate)
- psci_caps |= define_psci_cap(PSCI_MIG_AARCH64);
-
- if (pm->svc_migrate_info)
- psci_caps |= define_psci_cap(PSCI_MIG_INFO_UP_CPU_AARCH64)
- | define_psci_cap(PSCI_MIG_INFO_TYPE);
-}
-
-/*******************************************************************************
- * This function invokes the migrate info hook in the spd_pm_ops. It performs
- * the necessary return value validation. If the Secure Payload is UP and
- * migrate capable, it returns the mpidr of the CPU on which the Secure payload
- * is resident through the mpidr parameter. Else the value of the parameter on
- * return is undefined.
- ******************************************************************************/
-int psci_spd_migrate_info(u_register_t *mpidr)
-{
- int rc;
-
- if (!psci_spd_pm || !psci_spd_pm->svc_migrate_info)
- return PSCI_E_NOT_SUPPORTED;
-
- rc = psci_spd_pm->svc_migrate_info(mpidr);
-
- assert(rc == PSCI_TOS_UP_MIG_CAP || rc == PSCI_TOS_NOT_UP_MIG_CAP \
- || rc == PSCI_TOS_NOT_PRESENT_MP || rc == PSCI_E_NOT_SUPPORTED);
-
- return rc;
-}
-
-
-/*******************************************************************************
- * This function prints the state of all power domains present in the
- * system
- ******************************************************************************/
-void psci_print_power_domain_map(void)
-{
-#if LOG_LEVEL >= LOG_LEVEL_INFO
- unsigned int idx;
- plat_local_state_t state;
- plat_local_state_type_t state_type;
-
- /* This array maps to the PSCI_STATE_X definitions in psci.h */
- static const char * const psci_state_type_str[] = {
- "ON",
- "RETENTION",
- "OFF",
- };
-
- INFO("PSCI Power Domain Map:\n");
- for (idx = 0; idx < (PSCI_NUM_PWR_DOMAINS - PLATFORM_CORE_COUNT);
- idx++) {
- state_type = find_local_state_type(
- psci_non_cpu_pd_nodes[idx].local_state);
- INFO(" Domain Node : Level %u, parent_node %d,"
- " State %s (0x%x)\n",
- psci_non_cpu_pd_nodes[idx].level,
- psci_non_cpu_pd_nodes[idx].parent_node,
- psci_state_type_str[state_type],
- psci_non_cpu_pd_nodes[idx].local_state);
- }
-
- for (idx = 0; idx < PLATFORM_CORE_COUNT; idx++) {
- state = psci_get_cpu_local_state_by_idx(idx);
- state_type = find_local_state_type(state);
- INFO(" CPU Node : MPID 0x%llx, parent_node %d,"
- " State %s (0x%x)\n",
- (unsigned long long)psci_cpu_pd_nodes[idx].mpidr,
- psci_cpu_pd_nodes[idx].parent_node,
- psci_state_type_str[state_type],
- psci_get_cpu_local_state_by_idx(idx));
- }
-#endif
-}
-
-#if ENABLE_PLAT_COMPAT
-/*******************************************************************************
- * PSCI Compatibility helper function to return the 'power_state' parameter of
- * the PSCI CPU SUSPEND request for the current CPU. Returns PSCI_INVALID_DATA
- * if not invoked within CPU_SUSPEND for the current CPU.
- ******************************************************************************/
-int psci_get_suspend_powerstate(void)
-{
- /* Sanity check to verify that CPU is within CPU_SUSPEND */
- if (psci_get_aff_info_state() == AFF_STATE_ON &&
- !is_local_state_run(psci_get_cpu_local_state()))
- return psci_power_state_compat[plat_my_core_pos()];
-
- return PSCI_INVALID_DATA;
-}
-
-/*******************************************************************************
- * PSCI Compatibility helper function to return the state id of the current
- * cpu encoded in the 'power_state' parameter. Returns PSCI_INVALID_DATA
- * if not invoked within CPU_SUSPEND for the current CPU.
- ******************************************************************************/
-int psci_get_suspend_stateid(void)
-{
- unsigned int power_state;
- power_state = psci_get_suspend_powerstate();
- if (power_state != PSCI_INVALID_DATA)
- return psci_get_pstate_id(power_state);
-
- return PSCI_INVALID_DATA;
-}
-
-/*******************************************************************************
- * PSCI Compatibility helper function to return the state id encoded in the
- * 'power_state' parameter of the CPU specified by 'mpidr'. Returns
- * PSCI_INVALID_DATA if the CPU is not in CPU_SUSPEND.
- ******************************************************************************/
-int psci_get_suspend_stateid_by_mpidr(unsigned long mpidr)
-{
- int cpu_idx = plat_core_pos_by_mpidr(mpidr);
-
- if (cpu_idx == -1)
- return PSCI_INVALID_DATA;
-
- /* Sanity check to verify that the CPU is in CPU_SUSPEND */
- if (psci_get_aff_info_state_by_idx(cpu_idx) == AFF_STATE_ON &&
- !is_local_state_run(psci_get_cpu_local_state_by_idx(cpu_idx)))
- return psci_get_pstate_id(psci_power_state_compat[cpu_idx]);
-
- return PSCI_INVALID_DATA;
-}
-
-/*******************************************************************************
- * This function returns highest affinity level which is in OFF
- * state. The affinity instance with which the level is associated is
- * determined by the caller.
- ******************************************************************************/
-unsigned int psci_get_max_phys_off_afflvl(void)
-{
- psci_power_state_t state_info;
-
- memset(&state_info, 0, sizeof(state_info));
- psci_get_target_local_pwr_states(PLAT_MAX_PWR_LVL, &state_info);
-
- return psci_find_target_suspend_lvl(&state_info);
-}
-
-/*******************************************************************************
- * PSCI Compatibility helper function to return target affinity level requested
- * for the CPU_SUSPEND. This function assumes affinity levels correspond to
- * power domain levels on the platform.
- ******************************************************************************/
-int psci_get_suspend_afflvl(void)
-{
- return psci_get_suspend_pwrlvl();
-}
-
-#endif
diff --git a/services/std_svc/psci/psci_entry.S b/services/std_svc/psci/psci_entry.S
deleted file mode 100644
index f8c0afa2..00000000
--- a/services/std_svc/psci/psci_entry.S
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <arch.h>
-#include <asm_macros.S>
-#include <el3_common_macros.S>
-#include <psci.h>
-#include <xlat_tables.h>
-
- .globl psci_entrypoint
- .globl psci_power_down_wfi
-
- /* --------------------------------------------------------------------
- * 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_entrypoint
- /*
- * On the warm boot path, most of the EL3 initialisations performed by
- * 'el3_entrypoint_common' must be skipped:
- *
- * - Only when the platform bypasses the BL1/BL31 entrypoint by
- * programming the reset address do we need to set the CPU endianness.
- * In other cases, we assume this has been taken care by the
- * entrypoint code.
- *
- * - No need to determine the type of boot, we know it is a warm boot.
- *
- * - Do not try to distinguish between primary and secondary CPUs, this
- * notion only exists for a cold boot.
- *
- * - No need to initialise the memory or the C runtime environment,
- * it has been done once and for all on the cold boot path.
- */
- el3_entrypoint_common \
- _set_endian=PROGRAMMABLE_RESET_ADDRESS \
- _warm_boot_mailbox=0 \
- _secondary_cold_boot=0 \
- _init_memory=0 \
- _init_c_runtime=0 \
- _exception_vectors=runtime_exceptions
-
- /* --------------------------------------------
- * Enable the MMU with the DCache disabled. It
- * is safe to use stacks allocated in normal
- * memory as a result. All memory accesses are
- * marked nGnRnE when the MMU is disabled. So
- * all the stack writes will make it to memory.
- * All memory accesses are marked Non-cacheable
- * when the MMU is enabled but D$ is disabled.
- * So used stack memory is guaranteed to be
- * visible immediately after the MMU is enabled
- * Enabling the DCache at the same time as the
- * MMU can lead to speculatively fetched and
- * possibly stale stack memory being read from
- * other caches. This can lead to coherency
- * issues.
- * --------------------------------------------
- */
- mov x0, #DISABLE_DCACHE
- bl bl31_plat_enable_mmu
-
- bl psci_power_up_finish
-
- b el3_exit
-endfunc psci_entrypoint
-
- /* --------------------------------------------
- * This function is called to indicate to the
- * power controller that it is safe to power
- * down this cpu. It should not exit the wfi
- * and will be released from reset upon power
- * up. 'wfi_spill' is used to catch erroneous
- * exits from wfi.
- * --------------------------------------------
- */
-func psci_power_down_wfi
- dsb sy // ensure write buffer empty
- wfi
- bl plat_panic_handler
-endfunc psci_power_down_wfi
-
diff --git a/services/std_svc/psci/psci_helpers.S b/services/std_svc/psci/psci_helpers.S
deleted file mode 100644
index 6ccf943c..00000000
--- a/services/std_svc/psci/psci_helpers.S
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <asm_macros.S>
-#include <assert_macros.S>
-#include <platform_def.h>
-#include <psci.h>
-
- .globl psci_do_pwrdown_cache_maintenance
- .globl psci_do_pwrup_cache_maintenance
-
-/* -----------------------------------------------------------------------
- * void psci_do_pwrdown_cache_maintenance(unsigned int power level);
- *
- * This function performs cache maintenance for the specified power
- * level. The levels of cache affected are determined by the power
- * level which is passed as the argument i.e. level 0 results
- * in a flush of the L1 cache. Both the L1 and L2 caches are flushed
- * for a higher power level.
- *
- * Additionally, this function also ensures that stack memory is correctly
- * flushed out to avoid coherency issues due to a change in its memory
- * attributes after the data cache is disabled.
- * -----------------------------------------------------------------------
- */
-func psci_do_pwrdown_cache_maintenance
- stp x29, x30, [sp,#-16]!
- stp x19, x20, [sp,#-16]!
-
- /* ---------------------------------------------
- * Determine to how many levels of cache will be
- * subject to cache maintenance. Power level
- * 0 implies that only the cpu is being powered
- * down. Only the L1 data cache needs to be
- * flushed to the PoU in this case. For a higher
- * power level we are assuming that a flush
- * of L1 data and L2 unified cache is enough.
- * This information should be provided by the
- * platform.
- * ---------------------------------------------
- */
- cmp w0, #PSCI_CPU_PWR_LVL
- b.eq do_core_pwr_dwn
- bl prepare_cluster_pwr_dwn
- b do_stack_maintenance
-
-do_core_pwr_dwn:
- bl prepare_core_pwr_dwn
-
- /* ---------------------------------------------
- * Do stack maintenance by flushing the used
- * stack to the main memory and invalidating the
- * remainder.
- * ---------------------------------------------
- */
-do_stack_maintenance:
- bl plat_get_my_stack
-
- /* ---------------------------------------------
- * Calculate and store the size of the used
- * stack memory in x1.
- * ---------------------------------------------
- */
- mov x19, x0
- mov x1, sp
- sub x1, x0, x1
- mov x0, sp
- bl flush_dcache_range
-
- /* ---------------------------------------------
- * Calculate and store the size of the unused
- * stack memory in x1. Calculate and store the
- * stack base address in x0.
- * ---------------------------------------------
- */
- sub x0, x19, #PLATFORM_STACK_SIZE
- sub x1, sp, x0
- bl inv_dcache_range
-
- ldp x19, x20, [sp], #16
- ldp x29, x30, [sp], #16
- ret
-endfunc psci_do_pwrdown_cache_maintenance
-
-
-/* -----------------------------------------------------------------------
- * void psci_do_pwrup_cache_maintenance(void);
- *
- * This function performs cache maintenance after this cpu is powered up.
- * Currently, this involves managing the used stack memory before turning
- * on the data cache.
- * -----------------------------------------------------------------------
- */
-func psci_do_pwrup_cache_maintenance
- stp x29, x30, [sp,#-16]!
-
- /* ---------------------------------------------
- * Ensure any inflight stack writes have made it
- * to main memory.
- * ---------------------------------------------
- */
- dmb st
-
- /* ---------------------------------------------
- * Calculate and store the size of the used
- * stack memory in x1. Calculate and store the
- * stack base address in x0.
- * ---------------------------------------------
- */
- bl plat_get_my_stack
- mov x1, sp
- sub x1, x0, x1
- mov x0, sp
- bl inv_dcache_range
-
- /* ---------------------------------------------
- * Enable the data cache.
- * ---------------------------------------------
- */
- mrs x0, sctlr_el3
- orr x0, x0, #SCTLR_C_BIT
- msr sctlr_el3, x0
- isb
-
- ldp x29, x30, [sp], #16
- ret
-endfunc psci_do_pwrup_cache_maintenance
diff --git a/services/std_svc/psci/psci_main.c b/services/std_svc/psci/psci_main.c
deleted file mode 100644
index 04ef10e7..00000000
--- a/services/std_svc/psci/psci_main.c
+++ /dev/null
@@ -1,440 +0,0 @@
-/*
- * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <arch.h>
-#include <arch_helpers.h>
-#include <assert.h>
-#include <debug.h>
-#include <platform.h>
-#include <runtime_svc.h>
-#include <std_svc.h>
-#include <string.h>
-#include "psci_private.h"
-
-/*******************************************************************************
- * PSCI frontend api for servicing SMCs. Described in the PSCI spec.
- ******************************************************************************/
-int psci_cpu_on(u_register_t target_cpu,
- uintptr_t entrypoint,
- u_register_t context_id)
-
-{
- int rc;
- entry_point_info_t ep;
-
- /* Determine if the cpu exists of not */
- rc = psci_validate_mpidr(target_cpu);
- if (rc != PSCI_E_SUCCESS)
- return PSCI_E_INVALID_PARAMS;
-
- /* Validate the entry point and get the entry_point_info */
- rc = psci_validate_entry_point(&ep, entrypoint, context_id);
- if (rc != PSCI_E_SUCCESS)
- return rc;
-
- /*
- * To turn this cpu on, specify which power
- * levels need to be turned on
- */
- return psci_cpu_on_start(target_cpu, &ep);
-}
-
-unsigned int psci_version(void)
-{
- return PSCI_MAJOR_VER | PSCI_MINOR_VER;
-}
-
-int psci_cpu_suspend(unsigned int power_state,
- uintptr_t entrypoint,
- u_register_t context_id)
-{
- int rc;
- unsigned int target_pwrlvl, is_power_down_state;
- entry_point_info_t ep;
- psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} };
- plat_local_state_t cpu_pd_state;
-
- /* Validate the power_state parameter */
- rc = psci_validate_power_state(power_state, &state_info);
- if (rc != PSCI_E_SUCCESS) {
- assert(rc == PSCI_E_INVALID_PARAMS);
- return rc;
- }
-
- /*
- * Get the value of the state type bit from the power state parameter.
- */
- is_power_down_state = psci_get_pstate_type(power_state);
-
- /* Sanity check the requested suspend levels */
- assert(psci_validate_suspend_req(&state_info, is_power_down_state)
- == PSCI_E_SUCCESS);
-
- target_pwrlvl = psci_find_target_suspend_lvl(&state_info);
-
- /* Fast path for CPU standby.*/
- if (is_cpu_standby_req(is_power_down_state, target_pwrlvl)) {
- if (!psci_plat_pm_ops->cpu_standby)
- return PSCI_E_INVALID_PARAMS;
-
- /*
- * Set the state of the CPU power domain to the platform
- * specific retention state and enter the standby state.
- */
- cpu_pd_state = state_info.pwr_domain_state[PSCI_CPU_PWR_LVL];
- psci_set_cpu_local_state(cpu_pd_state);
-
-#if ENABLE_PSCI_STAT
- /*
- * Capture time-stamp before CPU standby
- * No cache maintenance is needed as caches
- * are ON through out the CPU standby operation.
- */
- PMF_CAPTURE_TIMESTAMP(psci_svc, PSCI_STAT_ID_ENTER_LOW_PWR,
- PMF_NO_CACHE_MAINT);
-#endif
-
- psci_plat_pm_ops->cpu_standby(cpu_pd_state);
-
- /* Upon exit from standby, set the state back to RUN. */
- psci_set_cpu_local_state(PSCI_LOCAL_STATE_RUN);
-
-#if ENABLE_PSCI_STAT
- /* Capture time-stamp after CPU standby */
- PMF_CAPTURE_TIMESTAMP(psci_svc, PSCI_STAT_ID_EXIT_LOW_PWR,
- PMF_NO_CACHE_MAINT);
-
- /* Update PSCI stats */
- psci_stats_update_pwr_up(PSCI_CPU_PWR_LVL, &state_info,
- PMF_NO_CACHE_MAINT);
-#endif
-
- return PSCI_E_SUCCESS;
- }
-
- /*
- * If a power down state has been requested, we need to verify entry
- * point and program entry information.
- */
- if (is_power_down_state) {
- rc = psci_validate_entry_point(&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. This function
- * might return if the power down was abandoned for any reason, e.g.
- * arrival of an interrupt
- */
- psci_cpu_suspend_start(&ep,
- target_pwrlvl,
- &state_info,
- is_power_down_state);
-
- return PSCI_E_SUCCESS;
-}
-
-
-int psci_system_suspend(uintptr_t entrypoint, u_register_t context_id)
-{
- int rc;
- psci_power_state_t state_info;
- entry_point_info_t ep;
-
- /* Check if the current CPU is the last ON CPU in the system */
- if (!psci_is_last_on_cpu())
- return PSCI_E_DENIED;
-
- /* Validate the entry point and get the entry_point_info */
- rc = psci_validate_entry_point(&ep, entrypoint, context_id);
- if (rc != PSCI_E_SUCCESS)
- return rc;
-
- /* Query the psci_power_state for system suspend */
- psci_query_sys_suspend_pwrstate(&state_info);
-
- /* Ensure that the psci_power_state makes sense */
- assert(psci_find_target_suspend_lvl(&state_info) == PLAT_MAX_PWR_LVL);
- assert(psci_validate_suspend_req(&state_info, PSTATE_TYPE_POWERDOWN)
- == PSCI_E_SUCCESS);
- assert(is_local_state_off(state_info.pwr_domain_state[PLAT_MAX_PWR_LVL]));
-
- /*
- * Do what is needed to enter the system suspend state. This function
- * might return if the power down was abandoned for any reason, e.g.
- * arrival of an interrupt
- */
- psci_cpu_suspend_start(&ep,
- PLAT_MAX_PWR_LVL,
- &state_info,
- PSTATE_TYPE_POWERDOWN);
-
- return PSCI_E_SUCCESS;
-}
-
-int psci_cpu_off(void)
-{
- int rc;
- unsigned int target_pwrlvl = PLAT_MAX_PWR_LVL;
-
- /*
- * Do what is needed to power off this CPU and possible higher power
- * levels if it able to do so. Upon success, enter the final wfi
- * which will power down this CPU.
- */
- rc = psci_do_cpu_off(target_pwrlvl);
-
- /*
- * The only error cpu_off can return is E_DENIED. So check if that's
- * indeed the case.
- */
- assert(rc == PSCI_E_DENIED);
-
- return rc;
-}
-
-int psci_affinity_info(u_register_t target_affinity,
- unsigned int lowest_affinity_level)
-{
- unsigned int target_idx;
-
- /* We dont support level higher than PSCI_CPU_PWR_LVL */
- if (lowest_affinity_level > PSCI_CPU_PWR_LVL)
- return PSCI_E_INVALID_PARAMS;
-
- /* Calculate the cpu index of the target */
- target_idx = plat_core_pos_by_mpidr(target_affinity);
- if (target_idx == -1)
- return PSCI_E_INVALID_PARAMS;
-
- return psci_get_aff_info_state_by_idx(target_idx);
-}
-
-int psci_migrate(u_register_t target_cpu)
-{
- int rc;
- u_register_t resident_cpu_mpidr;
-
- rc = psci_spd_migrate_info(&resident_cpu_mpidr);
- if (rc != PSCI_TOS_UP_MIG_CAP)
- return (rc == PSCI_TOS_NOT_UP_MIG_CAP) ?
- PSCI_E_DENIED : PSCI_E_NOT_SUPPORTED;
-
- /*
- * Migrate should only be invoked on the CPU where
- * the Secure OS is resident.
- */
- if (resident_cpu_mpidr != read_mpidr_el1())
- return PSCI_E_NOT_PRESENT;
-
- /* Check the validity of the specified target cpu */
- rc = psci_validate_mpidr(target_cpu);
- if (rc != PSCI_E_SUCCESS)
- return PSCI_E_INVALID_PARAMS;
-
- assert(psci_spd_pm && psci_spd_pm->svc_migrate);
-
- rc = psci_spd_pm->svc_migrate(read_mpidr_el1(), target_cpu);
- assert(rc == PSCI_E_SUCCESS || rc == PSCI_E_INTERN_FAIL);
-
- return rc;
-}
-
-int psci_migrate_info_type(void)
-{
- u_register_t resident_cpu_mpidr;
-
- return psci_spd_migrate_info(&resident_cpu_mpidr);
-}
-
-long psci_migrate_info_up_cpu(void)
-{
- u_register_t resident_cpu_mpidr;
- int rc;
-
- /*
- * Return value of this depends upon what
- * psci_spd_migrate_info() returns.
- */
- rc = psci_spd_migrate_info(&resident_cpu_mpidr);
- if (rc != PSCI_TOS_NOT_UP_MIG_CAP && rc != PSCI_TOS_UP_MIG_CAP)
- return PSCI_E_INVALID_PARAMS;
-
- return resident_cpu_mpidr;
-}
-
-int psci_features(unsigned int psci_fid)
-{
- unsigned int local_caps = psci_caps;
-
- /* Check if it is a 64 bit function */
- if (((psci_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_64)
- local_caps &= PSCI_CAP_64BIT_MASK;
-
- /* Check for invalid fid */
- if (!(is_std_svc_call(psci_fid) && is_valid_fast_smc(psci_fid)
- && is_psci_fid(psci_fid)))
- return PSCI_E_NOT_SUPPORTED;
-
-
- /* Check if the psci fid is supported or not */
- if (!(local_caps & define_psci_cap(psci_fid)))
- return PSCI_E_NOT_SUPPORTED;
-
- /* Format the feature flags */
- if (psci_fid == PSCI_CPU_SUSPEND_AARCH32 ||
- psci_fid == PSCI_CPU_SUSPEND_AARCH64) {
- /*
- * The trusted firmware does not support OS Initiated Mode.
- */
- return (FF_PSTATE << FF_PSTATE_SHIFT) |
- ((!FF_SUPPORTS_OS_INIT_MODE) << FF_MODE_SUPPORT_SHIFT);
- }
-
- /* Return 0 for all other fid's */
- return PSCI_E_SUCCESS;
-}
-
-/*******************************************************************************
- * PSCI top level handler for servicing SMCs.
- ******************************************************************************/
-uintptr_t psci_smc_handler(uint32_t smc_fid,
- u_register_t x1,
- u_register_t x2,
- u_register_t x3,
- u_register_t x4,
- void *cookie,
- void *handle,
- u_register_t flags)
-{
- if (is_caller_secure(flags))
- SMC_RET1(handle, SMC_UNK);
-
- /* Check the fid against the capabilities */
- if (!(psci_caps & define_psci_cap(smc_fid)))
- SMC_RET1(handle, SMC_UNK);
-
- if (((smc_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_32) {
- /* 32-bit PSCI function, clear top parameter bits */
-
- x1 = (uint32_t)x1;
- x2 = (uint32_t)x2;
- x3 = (uint32_t)x3;
-
- switch (smc_fid) {
- case PSCI_VERSION:
- SMC_RET1(handle, psci_version());
-
- case PSCI_CPU_OFF:
- SMC_RET1(handle, psci_cpu_off());
-
- case PSCI_CPU_SUSPEND_AARCH32:
- SMC_RET1(handle, psci_cpu_suspend(x1, x2, x3));
-
- case PSCI_CPU_ON_AARCH32:
- SMC_RET1(handle, psci_cpu_on(x1, x2, x3));
-
- case PSCI_AFFINITY_INFO_AARCH32:
- SMC_RET1(handle, psci_affinity_info(x1, x2));
-
- case PSCI_MIG_AARCH32:
- SMC_RET1(handle, psci_migrate(x1));
-
- case PSCI_MIG_INFO_TYPE:
- SMC_RET1(handle, psci_migrate_info_type());
-
- case PSCI_MIG_INFO_UP_CPU_AARCH32:
- SMC_RET1(handle, psci_migrate_info_up_cpu());
-
- case PSCI_SYSTEM_SUSPEND_AARCH32:
- SMC_RET1(handle, psci_system_suspend(x1, x2));
-
- case PSCI_SYSTEM_OFF:
- psci_system_off();
- /* We should never return from psci_system_off() */
-
- case PSCI_SYSTEM_RESET:
- psci_system_reset();
- /* We should never return from psci_system_reset() */
-
- case PSCI_FEATURES:
- SMC_RET1(handle, psci_features(x1));
-
-#if ENABLE_PSCI_STAT
- case PSCI_STAT_RESIDENCY_AARCH32:
- SMC_RET1(handle, psci_stat_residency(x1, x2));
-
- case PSCI_STAT_COUNT_AARCH32:
- SMC_RET1(handle, psci_stat_count(x1, x2));
-#endif
-
- default:
- break;
- }
- } else {
- /* 64-bit PSCI function */
-
- switch (smc_fid) {
- case PSCI_CPU_SUSPEND_AARCH64:
- SMC_RET1(handle, psci_cpu_suspend(x1, x2, x3));
-
- case PSCI_CPU_ON_AARCH64:
- SMC_RET1(handle, psci_cpu_on(x1, x2, x3));
-
- case PSCI_AFFINITY_INFO_AARCH64:
- SMC_RET1(handle, psci_affinity_info(x1, x2));
-
- case PSCI_MIG_AARCH64:
- SMC_RET1(handle, psci_migrate(x1));
-
- case PSCI_MIG_INFO_UP_CPU_AARCH64:
- SMC_RET1(handle, psci_migrate_info_up_cpu());
-
- case PSCI_SYSTEM_SUSPEND_AARCH64:
- SMC_RET1(handle, psci_system_suspend(x1, x2));
-
-#if ENABLE_PSCI_STAT
- case PSCI_STAT_RESIDENCY_AARCH64:
- SMC_RET1(handle, psci_stat_residency(x1, x2));
-
- case PSCI_STAT_COUNT_AARCH64:
- SMC_RET1(handle, psci_stat_count(x1, x2));
-#endif
-
- default:
- break;
- }
- }
-
- WARN("Unimplemented PSCI Call: 0x%x \n", smc_fid);
- SMC_RET1(handle, SMC_UNK);
-}
diff --git a/services/std_svc/psci/psci_off.c b/services/std_svc/psci/psci_off.c
deleted file mode 100644
index 36dab497..00000000
--- a/services/std_svc/psci/psci_off.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <arch.h>
-#include <arch_helpers.h>
-#include <assert.h>
-#include <debug.h>
-#include <platform.h>
-#include <string.h>
-#include "psci_private.h"
-
-/******************************************************************************
- * Construct the psci_power_state to request power OFF at all power levels.
- ******************************************************************************/
-static void psci_set_power_off_state(psci_power_state_t *state_info)
-{
- int lvl;
-
- for (lvl = PSCI_CPU_PWR_LVL; lvl <= PLAT_MAX_PWR_LVL; lvl++)
- state_info->pwr_domain_state[lvl] = PLAT_MAX_OFF_STATE;
-}
-
-/******************************************************************************
- * Top level handler which is called when a cpu wants to power itself down.
- * It's assumed that along with turning the cpu power domain off, power
- * domains at higher levels will be turned off as far as possible. It finds
- * the highest level where a domain has to be powered off by traversing the
- * node information and then performs generic, architectural, platform setup
- * and state management required to turn OFF that power domain and domains
- * below it. e.g. For a cpu that's to be powered OFF, it could mean programming
- * the power controller whereas for a cluster that's to be powered off, it will
- * call the platform specific code which will disable coherency at the
- * interconnect level if the cpu is the last in the cluster and also the
- * program the power controller.
- ******************************************************************************/
-int psci_do_cpu_off(unsigned int end_pwrlvl)
-{
- int rc = PSCI_E_SUCCESS, idx = plat_my_core_pos();
- psci_power_state_t state_info;
-
- /*
- * This function must only be called on platforms where the
- * CPU_OFF platform hooks have been implemented.
- */
- assert(psci_plat_pm_ops->pwr_domain_off);
-
- /*
- * This function acquires the lock corresponding to each power
- * level so that by the time all locks are taken, the system topology
- * is snapshot and state management can be done safely.
- */
- psci_acquire_pwr_domain_locks(end_pwrlvl,
- idx);
-
- /*
- * Call the cpu off handler registered by the Secure Payload Dispatcher
- * to let it do any bookkeeping. Assume that the SPD always reports an
- * E_DENIED error if SP refuse to power down
- */
- if (psci_spd_pm && psci_spd_pm->svc_off) {
- rc = psci_spd_pm->svc_off(0);
- if (rc)
- goto exit;
- }
-
- /* Construct the psci_power_state for CPU_OFF */
- psci_set_power_off_state(&state_info);
-
- /*
- * This function is passed the requested state info and
- * it returns the negotiated state info for each power level upto
- * the end level specified.
- */
- psci_do_state_coordination(end_pwrlvl, &state_info);
-
-#if ENABLE_PSCI_STAT
- /* Update the last cpu for each level till end_pwrlvl */
- psci_stats_update_pwr_down(end_pwrlvl, &state_info);
-#endif
-
- /*
- * Arch. management. Perform the necessary steps to flush all
- * cpu caches.
- */
- psci_do_pwrdown_cache_maintenance(psci_find_max_off_lvl(&state_info));
-
- /*
- * Plat. management: Perform platform specific actions to turn this
- * cpu off e.g. exit cpu coherency, program the power controller etc.
- */
- psci_plat_pm_ops->pwr_domain_off(&state_info);
-
-#if ENABLE_PSCI_STAT
- /*
- * Capture time-stamp while entering low power state.
- * No cache maintenance needed because caches are off
- * and writes are direct to main memory.
- */
- PMF_CAPTURE_TIMESTAMP(psci_svc, PSCI_STAT_ID_ENTER_LOW_PWR,
- PMF_NO_CACHE_MAINT);
-#endif
-
-exit:
- /*
- * Release the locks corresponding to each power level in the
- * reverse order to which they were acquired.
- */
- psci_release_pwr_domain_locks(end_pwrlvl,
- idx);
-
- /*
- * Check if all actions needed to safely power down this cpu have
- * successfully completed.
- */
- if (rc == PSCI_E_SUCCESS) {
- /*
- * Set the affinity info state to OFF. This writes directly to
- * main memory as caches are disabled, so cache maintenance is
- * required to ensure that later cached reads of aff_info_state
- * return AFF_STATE_OFF. A dsbish() ensures ordering of the
- * update to the affinity info state prior to cache line
- * invalidation.
- */
- flush_cpu_data(psci_svc_cpu_data.aff_info_state);
- psci_set_aff_info_state(AFF_STATE_OFF);
- dsbish();
- inv_cpu_data(psci_svc_cpu_data.aff_info_state);
-
- if (psci_plat_pm_ops->pwr_domain_pwr_down_wfi) {
- /* This function must not return */
- psci_plat_pm_ops->pwr_domain_pwr_down_wfi(&state_info);
- } else {
- /*
- * Enter a wfi loop which will allow the power
- * controller to physically power down this cpu.
- */
- psci_power_down_wfi();
- }
- }
-
- return rc;
-}
diff --git a/services/std_svc/psci/psci_on.c b/services/std_svc/psci/psci_on.c
deleted file mode 100644
index c8c36cd0..00000000
--- a/services/std_svc/psci/psci_on.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <arch.h>
-#include <arch_helpers.h>
-#include <assert.h>
-#include <bl_common.h>
-#include <bl31.h>
-#include <debug.h>
-#include <context_mgmt.h>
-#include <platform.h>
-#include <runtime_svc.h>
-#include <stddef.h>
-#include "psci_private.h"
-
-/*******************************************************************************
- * This function checks whether a cpu which has been requested to be turned on
- * is OFF to begin with.
- ******************************************************************************/
-static int cpu_on_validate_state(aff_info_state_t aff_state)
-{
- if (aff_state == AFF_STATE_ON)
- return PSCI_E_ALREADY_ON;
-
- if (aff_state == AFF_STATE_ON_PENDING)
- return PSCI_E_ON_PENDING;
-
- assert(aff_state == AFF_STATE_OFF);
- return PSCI_E_SUCCESS;
-}
-
-/*******************************************************************************
- * Generic handler which is called to physically power on a cpu identified by
- * its mpidr. It performs the generic, architectural, platform setup and state
- * management to power on the target cpu e.g. it will ensure that
- * enough information is stashed for it to resume execution in the non-secure
- * security state.
- *
- * The state of all the relevant power domains are changed after calling the
- * platform handler as it can return error.
- ******************************************************************************/
-int psci_cpu_on_start(u_register_t target_cpu,
- entry_point_info_t *ep)
-{
- int rc;
- unsigned int target_idx = plat_core_pos_by_mpidr(target_cpu);
- aff_info_state_t target_aff_state;
-
- /* Calling function must supply valid input arguments */
- assert((int) target_idx >= 0);
- assert(ep != NULL);
-
- /*
- * This function must only be called on platforms where the
- * CPU_ON platform hooks have been implemented.
- */
- assert(psci_plat_pm_ops->pwr_domain_on &&
- psci_plat_pm_ops->pwr_domain_on_finish);
-
- /* Protect against multiple CPUs trying to turn ON the same target CPU */
- psci_spin_lock_cpu(target_idx);
-
- /*
- * Generic management: Ensure that the cpu is off to be
- * turned on.
- */
- rc = cpu_on_validate_state(psci_get_aff_info_state_by_idx(target_idx));
- if (rc != PSCI_E_SUCCESS)
- goto exit;
-
- /*
- * Call the cpu on handler registered by the Secure Payload Dispatcher
- * to let it do any bookeeping. If the handler encounters an error, it's
- * expected to assert within
- */
- if (psci_spd_pm && psci_spd_pm->svc_on)
- psci_spd_pm->svc_on(target_cpu);
-
- /*
- * Set the Affinity info state of the target cpu to ON_PENDING.
- * Flush aff_info_state as it will be accessed with caches
- * turned OFF.
- */
- psci_set_aff_info_state_by_idx(target_idx, AFF_STATE_ON_PENDING);
- flush_cpu_data_by_index(target_idx, psci_svc_cpu_data.aff_info_state);
-
- /*
- * The cache line invalidation by the target CPU after setting the
- * state to OFF (see psci_do_cpu_off()), could cause the update to
- * aff_info_state to be invalidated. Retry the update if the target
- * CPU aff_info_state is not ON_PENDING.
- */
- target_aff_state = psci_get_aff_info_state_by_idx(target_idx);
- if (target_aff_state != AFF_STATE_ON_PENDING) {
- assert(target_aff_state == AFF_STATE_OFF);
- psci_set_aff_info_state_by_idx(target_idx, AFF_STATE_ON_PENDING);
- flush_cpu_data_by_index(target_idx, psci_svc_cpu_data.aff_info_state);
-
- assert(psci_get_aff_info_state_by_idx(target_idx) == AFF_STATE_ON_PENDING);
- }
-
- /*
- * Perform generic, architecture and platform specific handling.
- */
- /*
- * 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(target_cpu);
- assert(rc == PSCI_E_SUCCESS || rc == PSCI_E_INTERN_FAIL);
-
- if (rc == PSCI_E_SUCCESS)
- /* Store the re-entry information for the non-secure world. */
- cm_init_context_by_index(target_idx, ep);
- else {
- /* Restore the state on error. */
- psci_set_aff_info_state_by_idx(target_idx, AFF_STATE_OFF);
- flush_cpu_data_by_index(target_idx, psci_svc_cpu_data.aff_info_state);
- }
-
-exit:
- psci_spin_unlock_cpu(target_idx);
- return rc;
-}
-
-/*******************************************************************************
- * The following function finish an earlier power on request. They
- * are called by the common finisher routine in psci_common.c. The `state_info`
- * is the psci_power_state from which this CPU has woken up from.
- ******************************************************************************/
-void psci_cpu_on_finish(unsigned int cpu_idx,
- psci_power_state_t *state_info)
-{
- /*
- * Plat. management: Perform the platform specific actions
- * for this cpu e.g. enabling the gic or zeroing the mailbox
- * register. The actual state of this cpu has already been
- * changed.
- */
- psci_plat_pm_ops->pwr_domain_on_finish(state_info);
-
- /*
- * Arch. management: Enable data cache and manage stack memory
- */
- psci_do_pwrup_cache_maintenance();
-
- /*
- * All the platform specific actions for turning this cpu
- * on have completed. Perform enough arch.initialization
- * to run in the non-secure address space.
- */
- bl31_arch_setup();
-
- /*
- * Lock the CPU spin lock to make sure that the context initialization
- * is done. Since the lock is only used in this function to create
- * a synchronization point with cpu_on_start(), it can be released
- * immediately.
- */
- psci_spin_lock_cpu(cpu_idx);
- psci_spin_unlock_cpu(cpu_idx);
-
- /* Ensure we have been explicitly woken up by another cpu */
- assert(psci_get_aff_info_state() == AFF_STATE_ON_PENDING);
-
- /*
- * Call the cpu on finish handler registered by the Secure Payload
- * Dispatcher to let it do any bookeeping. If the handler encounters an
- * error, it's expected to assert within
- */
- if (psci_spd_pm && psci_spd_pm->svc_on_finish)
- psci_spd_pm->svc_on_finish(0);
-
- /* Populate the mpidr field within the cpu node array */
- /* This needs to be done only once */
- psci_cpu_pd_nodes[cpu_idx].mpidr = read_mpidr() & MPIDR_AFFINITY_MASK;
-
- /*
- * Generic management: Now we just need to retrieve the
- * information that we had stashed away during the cpu_on
- * call to set this cpu on its way.
- */
- cm_prepare_el3_exit(NON_SECURE);
-}
diff --git a/services/std_svc/psci/psci_private.h b/services/std_svc/psci/psci_private.h
deleted file mode 100644
index f42ce551..00000000
--- a/services/std_svc/psci/psci_private.h
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __PSCI_PRIVATE_H__
-#define __PSCI_PRIVATE_H__
-
-#include <arch.h>
-#include <bakery_lock.h>
-#include <bl_common.h>
-#include <cpu_data.h>
-#include <pmf.h>
-#include <psci.h>
-#include <spinlock.h>
-
-/*
- * The following helper macros abstract the interface to the Bakery
- * Lock API.
- */
-#define psci_lock_init(non_cpu_pd_node, idx) \
- ((non_cpu_pd_node)[(idx)].lock_index = (idx))
-#define psci_lock_get(non_cpu_pd_node) \
- bakery_lock_get(&psci_locks[(non_cpu_pd_node)->lock_index])
-#define psci_lock_release(non_cpu_pd_node) \
- bakery_lock_release(&psci_locks[(non_cpu_pd_node)->lock_index])
-
-/*
- * The PSCI capability which are provided by the generic code but does not
- * depend on the platform or spd capabilities.
- */
-#define PSCI_GENERIC_CAP \
- (define_psci_cap(PSCI_VERSION) | \
- define_psci_cap(PSCI_AFFINITY_INFO_AARCH64) | \
- define_psci_cap(PSCI_FEATURES))
-
-/*
- * The PSCI capabilities mask for 64 bit functions.
- */
-#define PSCI_CAP_64BIT_MASK \
- (define_psci_cap(PSCI_CPU_SUSPEND_AARCH64) | \
- define_psci_cap(PSCI_CPU_ON_AARCH64) | \
- define_psci_cap(PSCI_AFFINITY_INFO_AARCH64) | \
- define_psci_cap(PSCI_MIG_AARCH64) | \
- define_psci_cap(PSCI_MIG_INFO_UP_CPU_AARCH64) | \
- define_psci_cap(PSCI_SYSTEM_SUSPEND_AARCH64) | \
- define_psci_cap(PSCI_STAT_RESIDENCY_AARCH64) | \
- define_psci_cap(PSCI_STAT_COUNT_AARCH64))
-
-/*
- * Helper macros to get/set the fields of PSCI per-cpu data.
- */
-#define psci_set_aff_info_state(aff_state) \
- set_cpu_data(psci_svc_cpu_data.aff_info_state, aff_state)
-#define psci_get_aff_info_state() \
- get_cpu_data(psci_svc_cpu_data.aff_info_state)
-#define psci_get_aff_info_state_by_idx(idx) \
- get_cpu_data_by_index(idx, psci_svc_cpu_data.aff_info_state)
-#define psci_set_aff_info_state_by_idx(idx, aff_state) \
- set_cpu_data_by_index(idx, psci_svc_cpu_data.aff_info_state,\
- aff_state)
-#define psci_get_suspend_pwrlvl() \
- get_cpu_data(psci_svc_cpu_data.target_pwrlvl)
-#define psci_set_suspend_pwrlvl(target_lvl) \
- set_cpu_data(psci_svc_cpu_data.target_pwrlvl, target_lvl)
-#define psci_set_cpu_local_state(state) \
- set_cpu_data(psci_svc_cpu_data.local_state, state)
-#define psci_get_cpu_local_state() \
- get_cpu_data(psci_svc_cpu_data.local_state)
-#define psci_get_cpu_local_state_by_idx(idx) \
- get_cpu_data_by_index(idx, psci_svc_cpu_data.local_state)
-
-/*
- * Helper macros for the CPU level spinlocks
- */
-#define psci_spin_lock_cpu(idx) spin_lock(&psci_cpu_pd_nodes[idx].cpu_lock)
-#define psci_spin_unlock_cpu(idx) spin_unlock(&psci_cpu_pd_nodes[idx].cpu_lock)
-
-/* Helper macro to identify a CPU standby request in PSCI Suspend call */
-#define is_cpu_standby_req(is_power_down_state, retn_lvl) \
- (((!(is_power_down_state)) && ((retn_lvl) == 0)) ? 1 : 0)
-
-/* Following are used as ID's to capture time-stamp */
-#define PSCI_STAT_ID_ENTER_LOW_PWR 0
-#define PSCI_STAT_ID_EXIT_LOW_PWR 1
-#define PSCI_STAT_TOTAL_IDS 2
-
-/* Declare PMF service functions for PSCI */
-PMF_DECLARE_CAPTURE_TIMESTAMP(psci_svc)
-PMF_DECLARE_GET_TIMESTAMP(psci_svc)
-
-/*******************************************************************************
- * The following two data structures implement the power domain tree. The tree
- * is used to track the state of all the nodes i.e. power domain instances
- * described by the platform. The tree consists of nodes that describe CPU power
- * domains i.e. leaf nodes and all other power domains which are parents of a
- * CPU power domain i.e. non-leaf nodes.
- ******************************************************************************/
-typedef struct non_cpu_pwr_domain_node {
- /*
- * Index of the first CPU power domain node level 0 which has this node
- * as its parent.
- */
- unsigned int cpu_start_idx;
-
- /*
- * Number of CPU power domains which are siblings of the domain indexed
- * by 'cpu_start_idx' i.e. all the domains in the range 'cpu_start_idx
- * -> cpu_start_idx + ncpus' have this node as their parent.
- */
- unsigned int ncpus;
-
- /*
- * Index of the parent power domain node.
- * TODO: Figure out whether to whether using pointer is more efficient.
- */
- unsigned int parent_node;
-
- plat_local_state_t local_state;
-
- unsigned char level;
-
- /* For indexing the psci_lock array*/
- unsigned char lock_index;
-} non_cpu_pd_node_t;
-
-typedef struct cpu_pwr_domain_node {
- u_register_t mpidr;
-
- /*
- * Index of the parent power domain node.
- * TODO: Figure out whether to whether using pointer is more efficient.
- */
- unsigned int parent_node;
-
- /*
- * A CPU power domain does not require state coordination like its
- * parent power domains. Hence this node does not include a bakery
- * lock. A spinlock is required by the CPU_ON handler to prevent a race
- * when multiple CPUs try to turn ON the same target CPU.
- */
- spinlock_t cpu_lock;
-} cpu_pd_node_t;
-
-/*******************************************************************************
- * Data prototypes
- ******************************************************************************/
-extern const plat_psci_ops_t *psci_plat_pm_ops;
-extern non_cpu_pd_node_t psci_non_cpu_pd_nodes[PSCI_NUM_NON_CPU_PWR_DOMAINS];
-extern cpu_pd_node_t psci_cpu_pd_nodes[PLATFORM_CORE_COUNT];
-extern unsigned int psci_caps;
-
-/* One bakery lock is required for each non-cpu power domain */
-DECLARE_BAKERY_LOCK(psci_locks[PSCI_NUM_NON_CPU_PWR_DOMAINS]);
-
-/*******************************************************************************
- * SPD's power management hooks registered with PSCI
- ******************************************************************************/
-extern const spd_pm_ops_t *psci_spd_pm;
-
-/*******************************************************************************
- * Function prototypes
- ******************************************************************************/
-/* Private exported functions from psci_common.c */
-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(u_register_t mpidr);
-void psci_init_req_local_pwr_states(void);
-void psci_power_up_finish(void);
-int psci_validate_entry_point(entry_point_info_t *ep,
- uintptr_t entrypoint, u_register_t context_id);
-void psci_get_parent_pwr_domain_nodes(unsigned int cpu_idx,
- unsigned int end_lvl,
- unsigned int node_index[]);
-void psci_do_state_coordination(unsigned int end_pwrlvl,
- psci_power_state_t *state_info);
-void psci_acquire_pwr_domain_locks(unsigned int end_pwrlvl,
- unsigned int cpu_idx);
-void psci_release_pwr_domain_locks(unsigned int end_pwrlvl,
- unsigned int cpu_idx);
-int psci_validate_suspend_req(const psci_power_state_t *state_info,
- unsigned int is_power_down_state_req);
-unsigned int psci_find_max_off_lvl(const psci_power_state_t *state_info);
-unsigned int psci_find_target_suspend_lvl(const psci_power_state_t *state_info);
-void psci_set_pwr_domains_to_run(unsigned int end_pwrlvl);
-void psci_print_power_domain_map(void);
-unsigned int psci_is_last_on_cpu(void);
-int psci_spd_migrate_info(u_register_t *mpidr);
-
-/* Private exported functions from psci_on.c */
-int psci_cpu_on_start(u_register_t target_cpu,
- entry_point_info_t *ep);
-
-void psci_cpu_on_finish(unsigned int cpu_idx,
- psci_power_state_t *state_info);
-
-/* Private exported functions from psci_off.c */
-int psci_do_cpu_off(unsigned int end_pwrlvl);
-
-/* Private exported functions from psci_suspend.c */
-void psci_cpu_suspend_start(entry_point_info_t *ep,
- unsigned int end_pwrlvl,
- psci_power_state_t *state_info,
- unsigned int is_power_down_state_req);
-
-void psci_cpu_suspend_finish(unsigned int cpu_idx,
- psci_power_state_t *state_info);
-
-/* Private exported functions from psci_helpers.S */
-void psci_do_pwrdown_cache_maintenance(unsigned int pwr_level);
-void psci_do_pwrup_cache_maintenance(void);
-
-/* Private exported functions from psci_system_off.c */
-void __dead2 psci_system_off(void);
-void __dead2 psci_system_reset(void);
-
-/* Private exported functions from psci_stat.c */
-void psci_stats_update_pwr_down(unsigned int end_pwrlvl,
- const psci_power_state_t *state_info);
-void psci_stats_update_pwr_up(unsigned int end_pwrlvl,
- const psci_power_state_t *state_info,
- unsigned int flags);
-u_register_t psci_stat_residency(u_register_t target_cpu,
- unsigned int power_state);
-u_register_t psci_stat_count(u_register_t target_cpu,
- unsigned int power_state);
-
-#endif /* __PSCI_PRIVATE_H__ */
diff --git a/services/std_svc/psci/psci_setup.c b/services/std_svc/psci/psci_setup.c
deleted file mode 100644
index 975b2571..00000000
--- a/services/std_svc/psci/psci_setup.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <arch.h>
-#include <arch_helpers.h>
-#include <assert.h>
-#include <bl_common.h>
-#include <context.h>
-#include <context_mgmt.h>
-#include <platform.h>
-#include <stddef.h>
-#include "psci_private.h"
-
-/*******************************************************************************
- * Per cpu non-secure contexts used to program the architectural state prior
- * return to the normal world.
- * TODO: Use the memory allocator to set aside memory for the contexts instead
- * of relying on platform defined constants.
- ******************************************************************************/
-static cpu_context_t psci_ns_context[PLATFORM_CORE_COUNT];
-
-/******************************************************************************
- * Define the psci capability variable.
- *****************************************************************************/
-unsigned int psci_caps;
-
-/*******************************************************************************
- * Function which initializes the 'psci_non_cpu_pd_nodes' or the
- * 'psci_cpu_pd_nodes' corresponding to the power level.
- ******************************************************************************/
-static void psci_init_pwr_domain_node(unsigned int node_idx,
- unsigned int parent_idx,
- unsigned int level)
-{
- if (level > PSCI_CPU_PWR_LVL) {
- psci_non_cpu_pd_nodes[node_idx].level = level;
- psci_lock_init(psci_non_cpu_pd_nodes, node_idx);
- psci_non_cpu_pd_nodes[node_idx].parent_node = parent_idx;
- psci_non_cpu_pd_nodes[node_idx].local_state =
- PLAT_MAX_OFF_STATE;
- } else {
- psci_cpu_data_t *svc_cpu_data;
-
- psci_cpu_pd_nodes[node_idx].parent_node = parent_idx;
-
- /* Initialize with an invalid mpidr */
- psci_cpu_pd_nodes[node_idx].mpidr = PSCI_INVALID_MPIDR;
-
- svc_cpu_data =
- &(_cpu_data_by_index(node_idx)->psci_svc_cpu_data);
-
- /* Set the Affinity Info for the cores as OFF */
- svc_cpu_data->aff_info_state = AFF_STATE_OFF;
-
- /* Invalidate the suspend level for the cpu */
- svc_cpu_data->target_pwrlvl = PSCI_INVALID_PWR_LVL;
-
- /* Set the power state to OFF state */
- svc_cpu_data->local_state = PLAT_MAX_OFF_STATE;
-
- flush_dcache_range((uintptr_t)svc_cpu_data,
- sizeof(*svc_cpu_data));
-
- cm_set_context_by_index(node_idx,
- (void *) &psci_ns_context[node_idx],
- NON_SECURE);
- }
-}
-
-/*******************************************************************************
- * This functions updates cpu_start_idx and ncpus field for each of the node in
- * psci_non_cpu_pd_nodes[]. It does so by comparing the parent nodes of each of
- * the CPUs and check whether they match with the parent of the previous
- * CPU. The basic assumption for this work is that children of the same parent
- * are allocated adjacent indices. The platform should ensure this though proper
- * mapping of the CPUs to indices via plat_core_pos_by_mpidr() and
- * plat_my_core_pos() APIs.
- *******************************************************************************/
-static void psci_update_pwrlvl_limits(void)
-{
- int j;
- unsigned int nodes_idx[PLAT_MAX_PWR_LVL] = {0};
- unsigned int temp_index[PLAT_MAX_PWR_LVL], cpu_idx;
-
- for (cpu_idx = 0; cpu_idx < PLATFORM_CORE_COUNT; cpu_idx++) {
- psci_get_parent_pwr_domain_nodes(cpu_idx,
- PLAT_MAX_PWR_LVL,
- temp_index);
- for (j = PLAT_MAX_PWR_LVL - 1; j >= 0; j--) {
- if (temp_index[j] != nodes_idx[j]) {
- nodes_idx[j] = temp_index[j];
- psci_non_cpu_pd_nodes[nodes_idx[j]].cpu_start_idx
- = cpu_idx;
- }
- psci_non_cpu_pd_nodes[nodes_idx[j]].ncpus++;
- }
- }
-}
-
-/*******************************************************************************
- * Core routine to populate the power domain tree. The tree descriptor passed by
- * the platform is populated breadth-first and the first entry in the map
- * informs the number of root power domains. The parent nodes of the root nodes
- * will point to an invalid entry(-1).
- ******************************************************************************/
-static void populate_power_domain_tree(const unsigned char *topology)
-{
- unsigned int i, j = 0, num_nodes_at_lvl = 1, num_nodes_at_next_lvl;
- unsigned int node_index = 0, parent_node_index = 0, num_children;
- int level = PLAT_MAX_PWR_LVL;
-
- /*
- * For each level the inputs are:
- * - number of nodes at this level in plat_array i.e. num_nodes_at_level
- * This is the sum of values of nodes at the parent level.
- * - Index of first entry at this level in the plat_array i.e.
- * parent_node_index.
- * - Index of first free entry in psci_non_cpu_pd_nodes[] or
- * psci_cpu_pd_nodes[] i.e. node_index depending upon the level.
- */
- while (level >= PSCI_CPU_PWR_LVL) {
- num_nodes_at_next_lvl = 0;
- /*
- * For each entry (parent node) at this level in the plat_array:
- * - Find the number of children
- * - Allocate a node in a power domain array for each child
- * - Set the parent of the child to the parent_node_index - 1
- * - Increment parent_node_index to point to the next parent
- * - Accumulate the number of children at next level.
- */
- for (i = 0; i < num_nodes_at_lvl; i++) {
- assert(parent_node_index <=
- PSCI_NUM_NON_CPU_PWR_DOMAINS);
- num_children = topology[parent_node_index];
-
- for (j = node_index;
- j < node_index + num_children; j++)
- psci_init_pwr_domain_node(j,
- parent_node_index - 1,
- level);
-
- node_index = j;
- num_nodes_at_next_lvl += num_children;
- parent_node_index++;
- }
-
- num_nodes_at_lvl = num_nodes_at_next_lvl;
- level--;
-
- /* Reset the index for the cpu power domain array */
- if (level == PSCI_CPU_PWR_LVL)
- node_index = 0;
- }
-
- /* Validate the sanity of array exported by the platform */
- assert(j == PLATFORM_CORE_COUNT);
-}
-
-/*******************************************************************************
- * This function initializes the power domain topology tree by querying the
- * platform. The power domain nodes higher than the CPU are populated in the
- * array psci_non_cpu_pd_nodes[] and the CPU power domains are populated in
- * psci_cpu_pd_nodes[]. The platform exports its static topology map through the
- * populate_power_domain_topology_tree() API. The algorithm populates the
- * psci_non_cpu_pd_nodes and psci_cpu_pd_nodes iteratively by using this
- * topology map. On a platform that implements two clusters of 2 cpus each, and
- * supporting 3 domain levels, the populated psci_non_cpu_pd_nodes would look
- * like this:
- *
- * ---------------------------------------------------
- * | system node | cluster 0 node | cluster 1 node |
- * ---------------------------------------------------
- *
- * And populated psci_cpu_pd_nodes would look like this :
- * <- cpus cluster0 -><- cpus cluster1 ->
- * ------------------------------------------------
- * | CPU 0 | CPU 1 | CPU 2 | CPU 3 |
- * ------------------------------------------------
- ******************************************************************************/
-int psci_setup(void)
-{
- const unsigned char *topology_tree;
-
- /* Query the topology map from the platform */
- topology_tree = plat_get_power_domain_tree_desc();
-
- /* Populate the power domain arrays using the platform topology map */
- populate_power_domain_tree(topology_tree);
-
- /* Update the CPU limits for each node in psci_non_cpu_pd_nodes */
- psci_update_pwrlvl_limits();
-
- /* Populate the mpidr field of cpu node for this CPU */
- psci_cpu_pd_nodes[plat_my_core_pos()].mpidr =
- read_mpidr() & MPIDR_AFFINITY_MASK;
-
- psci_init_req_local_pwr_states();
-
- /*
- * Set the requested and target state of this CPU and all the higher
- * power domain levels for this CPU to run.
- */
- psci_set_pwr_domains_to_run(PLAT_MAX_PWR_LVL);
-
- plat_setup_psci_ops((uintptr_t)psci_entrypoint,
- &psci_plat_pm_ops);
- assert(psci_plat_pm_ops);
-
- /* Initialize the psci capability */
- psci_caps = PSCI_GENERIC_CAP;
-
- if (psci_plat_pm_ops->pwr_domain_off)
- psci_caps |= define_psci_cap(PSCI_CPU_OFF);
- if (psci_plat_pm_ops->pwr_domain_on &&
- psci_plat_pm_ops->pwr_domain_on_finish)
- psci_caps |= define_psci_cap(PSCI_CPU_ON_AARCH64);
- if (psci_plat_pm_ops->pwr_domain_suspend &&
- psci_plat_pm_ops->pwr_domain_suspend_finish) {
- psci_caps |= define_psci_cap(PSCI_CPU_SUSPEND_AARCH64);
- if (psci_plat_pm_ops->get_sys_suspend_power_state)
- psci_caps |= define_psci_cap(PSCI_SYSTEM_SUSPEND_AARCH64);
- }
- if (psci_plat_pm_ops->system_off)
- psci_caps |= define_psci_cap(PSCI_SYSTEM_OFF);
- if (psci_plat_pm_ops->system_reset)
- psci_caps |= define_psci_cap(PSCI_SYSTEM_RESET);
-
-#if ENABLE_PSCI_STAT
- psci_caps |= define_psci_cap(PSCI_STAT_RESIDENCY_AARCH64);
- psci_caps |= define_psci_cap(PSCI_STAT_COUNT_AARCH64);
-#endif
-
- return 0;
-}
diff --git a/services/std_svc/psci/psci_stat.c b/services/std_svc/psci/psci_stat.c
deleted file mode 100644
index 155bbb07..00000000
--- a/services/std_svc/psci/psci_stat.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <assert.h>
-#include <debug.h>
-#include <platform.h>
-#include <platform_def.h>
-#include "psci_private.h"
-
-#ifndef PLAT_MAX_PWR_LVL_STATES
-#define PLAT_MAX_PWR_LVL_STATES 2
-#endif
-
-/* Ticks elapsed in one second by a signal of 1 MHz */
-#define MHZ_TICKS_PER_SEC 1000000
-
-/* Following structure is used for PSCI STAT */
-typedef struct psci_stat {
- u_register_t residency;
- u_register_t count;
-} psci_stat_t;
-
-/*
- * Following is used to keep track of the last cpu
- * that goes to power down in non cpu power domains.
- */
-static int last_cpu_in_non_cpu_pd[PSCI_NUM_NON_CPU_PWR_DOMAINS] = {-1};
-
-/*
- * Following are used to store PSCI STAT values for
- * CPU and non CPU power domains.
- */
-static psci_stat_t psci_cpu_stat[PLATFORM_CORE_COUNT]
- [PLAT_MAX_PWR_LVL_STATES];
-static psci_stat_t psci_non_cpu_stat[PSCI_NUM_NON_CPU_PWR_DOMAINS]
- [PLAT_MAX_PWR_LVL_STATES];
-
-/* Register PMF PSCI service */
-PMF_REGISTER_SERVICE(psci_svc, PMF_PSCI_STAT_SVC_ID,
- PSCI_STAT_TOTAL_IDS, PMF_STORE_ENABLE)
-
-/* The divisor to use to convert raw timestamp into microseconds */
-u_register_t residency_div;
-
-/*
- * This macro calculates the stats residency in microseconds,
- * taking in account the wrap around condition.
- */
-#define calc_stat_residency(_pwrupts, _pwrdnts, _res) \
- do { \
- if (_pwrupts < _pwrdnts) \
- _res = UINT64_MAX - _pwrdnts + _pwrupts;\
- else \
- _res = _pwrupts - _pwrdnts; \
- /* Convert timestamp into microseconds */ \
- _res = _res/residency_div; \
- } while (0)
-
-/*
- * This functions returns the index into the `psci_stat_t` array given the
- * local power state and power domain level. If the platform implements the
- * `get_pwr_lvl_state_idx` pm hook, then that will be used to return the index.
- */
-static int get_stat_idx(plat_local_state_t local_state, int pwr_lvl)
-{
- int idx;
-
- if (psci_plat_pm_ops->get_pwr_lvl_state_idx == NULL) {
- assert(PLAT_MAX_PWR_LVL_STATES == 2);
- if (is_local_state_retn(local_state))
- return 0;
-
- assert(is_local_state_off(local_state));
- return 1;
- }
-
- idx = psci_plat_pm_ops->get_pwr_lvl_state_idx(local_state, pwr_lvl);
- assert((idx >= 0) && (idx < PLAT_MAX_PWR_LVL_STATES));
- return idx;
-}
-
-/*******************************************************************************
- * This function is passed the target local power states for each power
- * domain (state_info) between the current CPU domain and its ancestors until
- * the target power level (end_pwrlvl).
- *
- * Then, for each level (apart from the CPU level) until the 'end_pwrlvl', it
- * updates the `last_cpu_in_non_cpu_pd[]` with last power down cpu id.
- *
- * This function will only be invoked with data cache enabled and while
- * powering down a core.
- ******************************************************************************/
-void psci_stats_update_pwr_down(unsigned int end_pwrlvl,
- const psci_power_state_t *state_info)
-{
- int lvl, parent_idx, cpu_idx = plat_my_core_pos();
-
- assert(end_pwrlvl <= PLAT_MAX_PWR_LVL);
- assert(state_info);
-
- parent_idx = psci_cpu_pd_nodes[cpu_idx].parent_node;
-
- for (lvl = PSCI_CPU_PWR_LVL + 1; lvl <= end_pwrlvl; lvl++) {
-
- /* Break early if the target power state is RUN */
- if (is_local_state_run(state_info->pwr_domain_state[lvl]))
- break;
-
- /*
- * The power domain is entering a low power state, so this is
- * the last CPU for this power domain
- */
- last_cpu_in_non_cpu_pd[parent_idx] = cpu_idx;
-
- parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node;
- }
-
-}
-
-/*******************************************************************************
- * This function updates the PSCI STATS(residency time and count) for CPU
- * and NON-CPU power domains.
- * It is called with caches enabled and locks acquired(for NON-CPU domain)
- ******************************************************************************/
-void psci_stats_update_pwr_up(unsigned int end_pwrlvl,
- const psci_power_state_t *state_info,
- unsigned int flags)
-{
- int parent_idx, cpu_idx = plat_my_core_pos();
- int lvl, stat_idx;
- plat_local_state_t local_state;
- unsigned long long pwrup_ts = 0, pwrdn_ts = 0;
- u_register_t residency;
-
- assert(end_pwrlvl <= PLAT_MAX_PWR_LVL);
- assert(state_info);
-
- /* Initialize the residency divisor if not already initialized */
- if (!residency_div) {
- /* Pre-calculate divisor so that it can be directly used to
- convert time-stamp into microseconds */
- residency_div = read_cntfrq_el0() / MHZ_TICKS_PER_SEC;
- assert(residency_div);
- }
-
- /* Get power down time-stamp for current CPU */
- PMF_GET_TIMESTAMP_BY_INDEX(psci_svc, PSCI_STAT_ID_ENTER_LOW_PWR,
- cpu_idx, flags, pwrdn_ts);
-
- /* In the case of 1st power on just return */
- if (!pwrdn_ts)
- return;
-
- /* Get power up time-stamp for current CPU */
- PMF_GET_TIMESTAMP_BY_INDEX(psci_svc, PSCI_STAT_ID_EXIT_LOW_PWR,
- cpu_idx, flags, pwrup_ts);
-
- /* Get the index into the stats array */
- local_state = state_info->pwr_domain_state[PSCI_CPU_PWR_LVL];
- stat_idx = get_stat_idx(local_state, PSCI_CPU_PWR_LVL);
-
- /* Calculate stats residency */
- calc_stat_residency(pwrup_ts, pwrdn_ts, residency);
-
- /* Update CPU stats. */
- psci_cpu_stat[cpu_idx][stat_idx].residency += residency;
- psci_cpu_stat[cpu_idx][stat_idx].count++;
-
- /*
- * Check what power domains above CPU were off
- * prior to this CPU powering on.
- */
- parent_idx = psci_cpu_pd_nodes[cpu_idx].parent_node;
- for (lvl = PSCI_CPU_PWR_LVL + 1; lvl <= end_pwrlvl; lvl++) {
- local_state = state_info->pwr_domain_state[lvl];
- if (is_local_state_run(local_state)) {
- /* Break early */
- break;
- }
-
- assert(last_cpu_in_non_cpu_pd[parent_idx] != -1);
-
- /* Get power down time-stamp for last CPU */
- PMF_GET_TIMESTAMP_BY_INDEX(psci_svc, PSCI_STAT_ID_ENTER_LOW_PWR,
- last_cpu_in_non_cpu_pd[parent_idx],
- flags, pwrdn_ts);
-
- /* Initialize back to reset value */
- last_cpu_in_non_cpu_pd[parent_idx] = -1;
-
- /* Get the index into the stats array */
- stat_idx = get_stat_idx(local_state, lvl);
-
- /* Calculate stats residency */
- calc_stat_residency(pwrup_ts, pwrdn_ts, residency);
-
- /* Update non cpu stats */
- psci_non_cpu_stat[parent_idx][stat_idx].residency += residency;
- psci_non_cpu_stat[parent_idx][stat_idx].count++;
-
- parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node;
- }
-
-}
-
-/*******************************************************************************
- * This function returns the appropriate count and residency time of the
- * local state for the highest power level expressed in the `power_state`
- * for the node represented by `target_cpu`.
- ******************************************************************************/
-int psci_get_stat(u_register_t target_cpu, unsigned int power_state,
- psci_stat_t *psci_stat)
-{
- int rc, pwrlvl, lvl, parent_idx, stat_idx, target_idx;
- psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} };
- plat_local_state_t local_state;
-
- /* Validate the target_cpu parameter and determine the cpu index */
- target_idx = plat_core_pos_by_mpidr(target_cpu);
- if (target_idx == -1)
- return PSCI_E_INVALID_PARAMS;
-
- /* Validate the power_state parameter */
- if (!psci_plat_pm_ops->translate_power_state_by_mpidr)
- rc = psci_validate_power_state(power_state, &state_info);
- else
- rc = psci_plat_pm_ops->translate_power_state_by_mpidr(
- target_cpu, power_state, &state_info);
-
- if (rc != PSCI_E_SUCCESS)
- return PSCI_E_INVALID_PARAMS;
-
- /* Find the highest power level */
- pwrlvl = psci_find_target_suspend_lvl(&state_info);
- if (pwrlvl == PSCI_INVALID_PWR_LVL)
- return PSCI_E_INVALID_PARAMS;
-
- /* Get the index into the stats array */
- local_state = state_info.pwr_domain_state[pwrlvl];
- stat_idx = get_stat_idx(local_state, pwrlvl);
-
- if (pwrlvl > PSCI_CPU_PWR_LVL) {
- /* Get the power domain index */
- parent_idx = psci_cpu_pd_nodes[target_idx].parent_node;
- for (lvl = PSCI_CPU_PWR_LVL + 1; lvl < pwrlvl; lvl++)
- parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node;
-
- /* Get the non cpu power domain stats */
- *psci_stat = psci_non_cpu_stat[parent_idx][stat_idx];
- } else {
- /* Get the cpu power domain stats */
- *psci_stat = psci_cpu_stat[target_idx][stat_idx];
- }
-
- return PSCI_E_SUCCESS;
-}
-
-/* This is the top level function for PSCI_STAT_RESIDENCY SMC. */
-u_register_t psci_stat_residency(u_register_t target_cpu,
- unsigned int power_state)
-{
- psci_stat_t psci_stat;
-
- int rc = psci_get_stat(target_cpu, power_state, &psci_stat);
- if (rc == PSCI_E_SUCCESS)
- return psci_stat.residency;
- else
- return 0;
-}
-
-/* This is the top level function for PSCI_STAT_COUNT SMC. */
-u_register_t psci_stat_count(u_register_t target_cpu,
- unsigned int power_state)
-{
- psci_stat_t psci_stat;
-
- int rc = psci_get_stat(target_cpu, power_state, &psci_stat);
- if (rc == PSCI_E_SUCCESS)
- return psci_stat.count;
- else
- return 0;
-}
diff --git a/services/std_svc/psci/psci_suspend.c b/services/std_svc/psci/psci_suspend.c
deleted file mode 100644
index e6c8cd99..00000000
--- a/services/std_svc/psci/psci_suspend.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <assert.h>
-#include <bl_common.h>
-#include <arch.h>
-#include <arch_helpers.h>
-#include <context.h>
-#include <context_mgmt.h>
-#include <cpu_data.h>
-#include <debug.h>
-#include <platform.h>
-#include <runtime_svc.h>
-#include <stddef.h>
-#include "psci_private.h"
-
-/*******************************************************************************
- * This function does generic and platform specific operations after a wake-up
- * from standby/retention states at multiple power levels.
- ******************************************************************************/
-static void psci_suspend_to_standby_finisher(unsigned int cpu_idx,
- psci_power_state_t *state_info,
- unsigned int end_pwrlvl)
-{
- psci_acquire_pwr_domain_locks(end_pwrlvl,
- cpu_idx);
-
- /*
- * Plat. management: Allow the platform to do operations
- * on waking up from retention.
- */
- psci_plat_pm_ops->pwr_domain_suspend_finish(state_info);
-
- /*
- * Set the requested and target state of this CPU and all the higher
- * power domain levels for this CPU to run.
- */
- psci_set_pwr_domains_to_run(end_pwrlvl);
-
- psci_release_pwr_domain_locks(end_pwrlvl,
- cpu_idx);
-}
-
-/*******************************************************************************
- * This function does generic and platform specific suspend to power down
- * operations.
- ******************************************************************************/
-static void psci_suspend_to_pwrdown_start(unsigned int end_pwrlvl,
- entry_point_info_t *ep,
- psci_power_state_t *state_info)
-{
- unsigned int max_off_lvl = psci_find_max_off_lvl(state_info);
-
- /* Save PSCI target power level for the suspend finisher handler */
- psci_set_suspend_pwrlvl(end_pwrlvl);
-
- /*
- * Flush the target power level as it will be accessed on power up with
- * Data cache disabled.
- */
- flush_cpu_data(psci_svc_cpu_data.target_pwrlvl);
-
- /*
- * Call the cpu suspend handler registered by the Secure Payload
- * Dispatcher to let it do any book-keeping. If the handler encounters an
- * error, it's expected to assert within
- */
- if (psci_spd_pm && psci_spd_pm->svc_suspend)
- psci_spd_pm->svc_suspend(max_off_lvl);
-
- /*
- * Store the re-entry information for the non-secure world.
- */
- cm_init_my_context(ep);
-
- /*
- * Arch. management. Perform the necessary steps to flush all
- * cpu caches. Currently we assume that the power level correspond
- * the cache level.
- * TODO : Introduce a mechanism to query the cache level to flush
- * and the cpu-ops power down to perform from the platform.
- */
- psci_do_pwrdown_cache_maintenance(max_off_lvl);
-}
-
-/*******************************************************************************
- * Top level handler which is called when a cpu wants to suspend its execution.
- * It is assumed that along with suspending the cpu power domain, power domains
- * at higher levels until the target power level will be suspended as well. It
- * coordinates with the platform to negotiate the target state for each of
- * the power domain level till the target power domain level. It then performs
- * generic, architectural, platform setup and state management required to
- * suspend that power domain level and power domain levels below it.
- * e.g. For a cpu that's to be suspended, it could mean programming the
- * power controller whereas for a cluster that's to be suspended, it will call
- * the platform specific code which will disable coherency at the interconnect
- * level if the cpu is the last in the cluster and also the program the power
- * controller.
- *
- * All the required parameter checks are performed at the beginning and after
- * the state transition has been done, no further error is expected and it is
- * not possible to undo any of the actions taken beyond that point.
- ******************************************************************************/
-void psci_cpu_suspend_start(entry_point_info_t *ep,
- unsigned int end_pwrlvl,
- psci_power_state_t *state_info,
- unsigned int is_power_down_state)
-{
- int skip_wfi = 0;
- unsigned int idx = plat_my_core_pos();
-
- /*
- * This function must only be called on platforms where the
- * CPU_SUSPEND platform hooks have been implemented.
- */
- assert(psci_plat_pm_ops->pwr_domain_suspend &&
- psci_plat_pm_ops->pwr_domain_suspend_finish);
-
- /*
- * This function acquires the lock corresponding to each power
- * level so that by the time all locks are taken, the system topology
- * is snapshot and state management can be done safely.
- */
- psci_acquire_pwr_domain_locks(end_pwrlvl,
- idx);
-
- /*
- * We check if there are any pending interrupts after the delay
- * introduced by lock contention to increase the chances of early
- * detection that a wake-up interrupt has fired.
- */
- if (read_isr_el1()) {
- skip_wfi = 1;
- goto exit;
- }
-
- /*
- * This function is passed the requested state info and
- * it returns the negotiated state info for each power level upto
- * the end level specified.
- */
- psci_do_state_coordination(end_pwrlvl, state_info);
-
-#if ENABLE_PSCI_STAT
- /* Update the last cpu for each level till end_pwrlvl */
- psci_stats_update_pwr_down(end_pwrlvl, state_info);
-#endif
-
- if (is_power_down_state)
- psci_suspend_to_pwrdown_start(end_pwrlvl, ep, state_info);
-
- /*
- * 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(state_info);
-
-#if ENABLE_PSCI_STAT
- /*
- * Capture time-stamp while entering low power state.
- * No cache maintenance needed because caches are off
- * and writes are direct to main memory.
- */
- PMF_CAPTURE_TIMESTAMP(psci_svc, PSCI_STAT_ID_ENTER_LOW_PWR,
- PMF_NO_CACHE_MAINT);
-#endif
-
-exit:
- /*
- * Release the locks corresponding to each power level in the
- * reverse order to which they were acquired.
- */
- psci_release_pwr_domain_locks(end_pwrlvl,
- idx);
- if (skip_wfi)
- return;
-
- if (is_power_down_state) {
- /* The function calls below must not return */
- if (psci_plat_pm_ops->pwr_domain_pwr_down_wfi)
- psci_plat_pm_ops->pwr_domain_pwr_down_wfi(state_info);
- else
- psci_power_down_wfi();
- }
-
- /*
- * We will reach here if only retention/standby states have been
- * requested at multiple power levels. This means that the cpu
- * context will be preserved.
- */
- wfi();
-
- /*
- * After we wake up from context retaining suspend, call the
- * context retaining suspend finisher.
- */
- psci_suspend_to_standby_finisher(idx, state_info, end_pwrlvl);
-}
-
-/*******************************************************************************
- * The following functions finish an earlier suspend request. They
- * are called by the common finisher routine in psci_common.c. The `state_info`
- * is the psci_power_state from which this CPU has woken up from.
- ******************************************************************************/
-void psci_cpu_suspend_finish(unsigned int cpu_idx,
- psci_power_state_t *state_info)
-{
- unsigned int counter_freq;
- unsigned int max_off_lvl;
-
- /* Ensure we have been woken up from a suspended state */
- assert(psci_get_aff_info_state() == AFF_STATE_ON && is_local_state_off(\
- state_info->pwr_domain_state[PSCI_CPU_PWR_LVL]));
-
- /*
- * Plat. management: Perform the platform specific actions
- * before we change the state of the cpu e.g. enabling the
- * gic or zeroing the mailbox register. If anything goes
- * wrong then assert as there is no way to recover from this
- * situation.
- */
- psci_plat_pm_ops->pwr_domain_suspend_finish(state_info);
-
- /*
- * Arch. management: Enable the data cache, manage stack memory and
- * restore the stashed EL3 architectural context from the 'cpu_context'
- * structure for this cpu.
- */
- psci_do_pwrup_cache_maintenance();
-
- /* Re-init the cntfrq_el0 register */
- counter_freq = plat_get_syscnt_freq2();
- write_cntfrq_el0(counter_freq);
-
- /*
- * Call the cpu suspend finish handler registered by the Secure Payload
- * Dispatcher to let it do any bookeeping. If the handler encounters an
- * error, it's expected to assert within
- */
- if (psci_spd_pm && psci_spd_pm->svc_suspend) {
- max_off_lvl = psci_find_max_off_lvl(state_info);
- assert (max_off_lvl != PSCI_INVALID_PWR_LVL);
- psci_spd_pm->svc_suspend_finish(max_off_lvl);
- }
-
- /* Invalidate the suspend level for the cpu */
- psci_set_suspend_pwrlvl(PSCI_INVALID_PWR_LVL);
-
- /*
- * Generic management: Now we just need to retrieve the
- * information that we had stashed away during the suspend
- * call to set this cpu on its way.
- */
- cm_prepare_el3_exit(NON_SECURE);
-}
diff --git a/services/std_svc/psci/psci_system_off.c b/services/std_svc/psci/psci_system_off.c
deleted file mode 100644
index 28315d6b..00000000
--- a/services/std_svc/psci/psci_system_off.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stddef.h>
-#include <arch_helpers.h>
-#include <assert.h>
-#include <debug.h>
-#include <platform.h>
-#include "psci_private.h"
-
-void psci_system_off(void)
-{
- psci_print_power_domain_map();
-
- assert(psci_plat_pm_ops->system_off);
-
- /* Notify the Secure Payload Dispatcher */
- if (psci_spd_pm && psci_spd_pm->svc_system_off) {
- psci_spd_pm->svc_system_off();
- }
-
- /* Call the platform specific hook */
- psci_plat_pm_ops->system_off();
-
- /* This function does not return. We should never get here */
-}
-
-void psci_system_reset(void)
-{
- psci_print_power_domain_map();
-
- assert(psci_plat_pm_ops->system_reset);
-
- /* Notify the Secure Payload Dispatcher */
- if (psci_spd_pm && psci_spd_pm->svc_system_reset) {
- psci_spd_pm->svc_system_reset();
- }
-
- /* Call the platform specific hook */
- psci_plat_pm_ops->system_reset();
-
- /* This function does not return. We should never get here */
-}