PSCI: Remove references to affinity based power management
authorSoby Mathew <soby.mathew@arm.com>
Tue, 5 May 2015 15:33:16 +0000 (16:33 +0100)
committerSoby Mathew <soby.mathew@arm.com>
Wed, 5 Aug 2015 13:15:26 +0000 (14:15 +0100)
As per Section 4.2.2. in the PSCI specification, the term "affinity"
is used in the context of describing the hierarchical arrangement
of cores. This often, but not always, maps directly to the processor
power domain topology of the system. The current PSCI implementation
assumes that this is always the case i.e. MPIDR based levels of
affinity always map to levels in a power domain topology tree.

This patch is the first in a series of patches which remove this
assumption. It removes all occurences of the terms "affinity
instances and levels" when used to describe the power domain
topology. Only the terminology is changed in this patch. Subsequent
patches will implement functional changes to remove the above
mentioned assumption.

Change-Id: Iee162f051b228828310610c5a320ff9d31009b4e

15 files changed:
include/bl31/services/psci1.0/psci.h
include/plat/common/psci1.0/platform.h
services/std_svc/psci1.0/psci_afflvl_off.c [deleted file]
services/std_svc/psci1.0/psci_afflvl_on.c [deleted file]
services/std_svc/psci1.0/psci_afflvl_suspend.c [deleted file]
services/std_svc/psci1.0/psci_common.c
services/std_svc/psci1.0/psci_entry.S
services/std_svc/psci1.0/psci_helpers.S
services/std_svc/psci1.0/psci_main.c
services/std_svc/psci1.0/psci_off.c [new file with mode: 0644]
services/std_svc/psci1.0/psci_on.c [new file with mode: 0644]
services/std_svc/psci1.0/psci_private.h
services/std_svc/psci1.0/psci_setup.c
services/std_svc/psci1.0/psci_suspend.c [new file with mode: 0644]
services/std_svc/psci1.0/psci_system_off.c

index 905fc8ab0b683e6a25db358d319548688cb3bd15..d00796c5f48b94181f0798263925cb1036b2aed5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * 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:
 #define __PSCI_H__
 
 #include <bakery_lock.h>
-#include <platform_def.h>      /* for PLATFORM_NUM_AFFS */
+#include <platform_def.h>      /* for PLAT_NUM_PWR_DOMAINS */
 
 /*******************************************************************************
- * Number of affinity instances whose state this psci imp. can track
+ * Number of power domains whose state this psci imp. can track
  ******************************************************************************/
-#ifdef PLATFORM_NUM_AFFS
-#define PSCI_NUM_AFFS          PLATFORM_NUM_AFFS
+#ifdef PLAT_NUM_PWR_DOMAINS
+#define PSCI_NUM_PWR_DOMAINS   PLAT_NUM_PWR_DOMAINS
 #else
-#define PSCI_NUM_AFFS          (2 * PLATFORM_CORE_COUNT)
+#define PSCI_NUM_PWR_DOMAINS   (2 * PLATFORM_CORE_COUNT)
 #endif
 
 /*******************************************************************************
  ******************************************************************************/
 #define PSTATE_ID_SHIFT                0
 #define PSTATE_TYPE_SHIFT      16
-#define PSTATE_AFF_LVL_SHIFT   24
+#define PSTATE_PWR_LVL_SHIFT   24
 
 #define PSTATE_ID_MASK         0xffff
 #define PSTATE_TYPE_MASK       0x1
-#define PSTATE_AFF_LVL_MASK    0x3
+#define PSTATE_PWR_LVL_MASK    0x3
 #define PSTATE_VALID_MASK     0xFCFE0000
 
 #define PSTATE_TYPE_STANDBY    0x0
                                        PSTATE_ID_MASK)
 #define psci_get_pstate_type(pstate)   (((pstate) >> PSTATE_TYPE_SHIFT) & \
                                        PSTATE_TYPE_MASK)
-#define psci_get_pstate_afflvl(pstate) (((pstate) >> PSTATE_AFF_LVL_SHIFT) & \
-                                       PSTATE_AFF_LVL_MASK)
-#define psci_make_powerstate(state_id, type, afflvl) \
+#define psci_get_pstate_pwrlvl(pstate) ((pstate >> PSTATE_PWR_LVL_SHIFT) & \
+                                       PSTATE_PWR_LVL_MASK)
+#define psci_make_powerstate(state_id, type, pwrlvl) \
                        (((state_id) & PSTATE_ID_MASK) << PSTATE_ID_SHIFT) |\
                        (((type) & PSTATE_TYPE_MASK) << PSTATE_TYPE_SHIFT) |\
-                       (((afflvl) & PSTATE_AFF_LVL_MASK) << PSTATE_AFF_LVL_SHIFT)
+                       (((pwrlvl) & PSTATE_PWR_LVL_MASK) << PSTATE_PWR_LVL_SHIFT)
 
 /*******************************************************************************
  * PSCI CPU_FEATURES feature flag specific defines
 #define PSCI_E_DISABLED                -8
 
 /*******************************************************************************
- * PSCI affinity state related constants. An affinity instance could be present
- * or absent physically to cater for asymmetric topologies. If present then it
- * could in one of the 4 further defined states.
+ * PSCI power domain state related constants. A power domain instance could
+ * be present or absent physically to cater for asymmetric topologies. If
+ * present then it could be in one of the 4 further defined states.
  ******************************************************************************/
 #define PSCI_STATE_SHIFT       1
 #define PSCI_STATE_MASK                0xff
 
-#define PSCI_AFF_ABSENT                0x0
-#define PSCI_AFF_PRESENT       0x1
+#define PSCI_PWR_DOMAIN_ABSENT         0x0
+#define PSCI_PWR_DOMAIN_PRESENT                0x1
 #define PSCI_STATE_ON          0x0
 #define PSCI_STATE_OFF         0x1
 #define PSCI_STATE_ON_PENDING  0x2
 typedef struct psci_cpu_data {
        uint32_t power_state;
 #if !USE_COHERENT_MEM
-       bakery_info_t pcpu_bakery_info[PSCI_NUM_AFFS];
+       bakery_info_t pcpu_bakery_info[PSCI_NUM_PWR_DOMAINS];
 #endif
 } psci_cpu_data_t;
 
@@ -181,15 +181,15 @@ typedef struct psci_cpu_data {
  * perform common low level pm functions
  ******************************************************************************/
 typedef struct plat_pm_ops {
-       void (*affinst_standby)(unsigned int power_state);
-       int (*affinst_on)(unsigned long mpidr,
+       void (*pwr_domain_standby)(unsigned int power_state);
+       int (*pwr_domain_on)(unsigned long mpidr,
                          unsigned long sec_entrypoint,
-                         unsigned int afflvl);
-       void (*affinst_off)(unsigned int afflvl);
-       void (*affinst_suspend)(unsigned long sec_entrypoint,
-                              unsigned int afflvl);
-       void (*affinst_on_finish)(unsigned int afflvl);
-       void (*affinst_suspend_finish)(unsigned int afflvl);
+                         unsigned int pwrlvl);
+       void (*pwr_domain_off)(unsigned int pwrlvl);
+       void (*pwr_domain_suspend)(unsigned long sec_entrypoint,
+                              unsigned int pwrlvl);
+       void (*pwr_domain_on_finish)(unsigned int pwrlvl);
+       void (*pwr_domain_suspend_finish)(unsigned int pwrlvl);
        void (*system_off)(void) __dead2;
        void (*system_reset)(void) __dead2;
        int (*validate_power_state)(unsigned int power_state);
@@ -227,12 +227,12 @@ int psci_cpu_on(unsigned long,
                unsigned long,
                unsigned long);
 void __dead2 psci_power_down_wfi(void);
-void psci_aff_on_finish_entry(void);
-void psci_aff_suspend_finish_entry(void);
+void psci_cpu_on_finish_entry(void);
+void psci_cpu_suspend_finish_entry(void);
 void psci_register_spd_pm_hook(const spd_pm_ops_t *);
 int psci_get_suspend_stateid_by_mpidr(unsigned long);
 int psci_get_suspend_stateid(void);
-int psci_get_suspend_afflvl(void);
+int psci_get_suspend_pwrlvl(void);
 
 uint64_t psci_smc_handler(uint32_t smc_fid,
                          uint64_t x1,
index 469d46b678cd9f7470b71df5615962798159bd17..50af4f85e6b63c2340569faf81175051b0398171 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * 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:
@@ -182,8 +182,8 @@ struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type);
  * Mandatory PSCI functions (BL3-1)
  ******************************************************************************/
 int platform_setup_pm(const struct plat_pm_ops **);
-unsigned int plat_get_aff_count(unsigned int, unsigned long);
-unsigned int plat_get_aff_state(unsigned int, unsigned long);
+unsigned int plat_get_pwr_domain_count(unsigned int, unsigned long);
+unsigned int plat_get_pwr_domain_state(unsigned int, unsigned long);
 
 /*******************************************************************************
  * Optional BL3-1 functions (may be overridden)
diff --git a/services/std_svc/psci1.0/psci_afflvl_off.c b/services/std_svc/psci1.0/psci_afflvl_off.c
deleted file mode 100644 (file)
index b966822..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2013-2014, 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 <string.h>
-#include "psci_private.h"
-
-/******************************************************************************
- * Top level handler which is called when a cpu wants to power itself down.
- * It's assumed that along with turning the cpu off, higher affinity levels
- * will be turned off as far as possible. It finds the highest level to be
- * powered off by traversing the node information and then performs generic,
- * architectural, platform setup and state management required to turn OFF
- * that affinity level and affinity levels 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_afflvl_off(int end_afflvl)
-{
-       int rc;
-       mpidr_aff_map_nodes_t mpidr_nodes;
-       unsigned int max_phys_off_afflvl;
-
-       /*
-        * This function must only be called on platforms where the
-        * CPU_OFF platform hooks have been implemented.
-        */
-       assert(psci_plat_pm_ops->affinst_off);
-
-       /*
-        * Collect the pointers to the nodes in the topology tree for
-        * each affinity instance in the mpidr. If this function does
-        * not return successfully then either the mpidr or the affinity
-        * levels are incorrect. Either way, this an internal TF error
-        * therefore assert.
-        */
-       rc = psci_get_aff_map_nodes(read_mpidr_el1() & MPIDR_AFFINITY_MASK,
-                                   MPIDR_AFFLVL0,
-                                   end_afflvl,
-                                   mpidr_nodes);
-       assert(rc == PSCI_E_SUCCESS);
-
-       /*
-        * This function acquires the lock corresponding to each affinity
-        * level so that by the time all locks are taken, the system topology
-        * is snapshot and state management can be done safely.
-        */
-       psci_acquire_afflvl_locks(MPIDR_AFFLVL0,
-                                 end_afflvl,
-                                 mpidr_nodes);
-
-
-       /*
-        * 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;
-       }
-
-       /*
-        * This function updates the state of each affinity instance
-        * corresponding to the mpidr in the range of affinity levels
-        * specified.
-        */
-       psci_do_afflvl_state_mgmt(MPIDR_AFFLVL0,
-                                 end_afflvl,
-                                 mpidr_nodes,
-                                 PSCI_STATE_OFF);
-
-       max_phys_off_afflvl = psci_find_max_phys_off_afflvl(MPIDR_AFFLVL0,
-                                                          end_afflvl,
-                                                          mpidr_nodes);
-       assert(max_phys_off_afflvl != PSCI_INVALID_DATA);
-
-       /*
-        * Arch. management. Perform the necessary steps to flush all
-        * cpu caches.
-        */
-       psci_do_pwrdown_cache_maintenance(max_phys_off_afflvl);
-
-       /*
-        * 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->affinst_off(max_phys_off_afflvl);
-
-exit:
-       /*
-        * Release the locks corresponding to each affinity level in the
-        * reverse order to which they were acquired.
-        */
-       psci_release_afflvl_locks(MPIDR_AFFLVL0,
-                                 end_afflvl,
-                                 mpidr_nodes);
-
-       /*
-        * Check if all actions needed to safely power down this cpu have
-        * successfully completed. Enter a wfi loop which will allow the
-        * power controller to physically power down this cpu.
-        */
-       if (rc == PSCI_E_SUCCESS)
-               psci_power_down_wfi();
-
-       return rc;
-}
diff --git a/services/std_svc/psci1.0/psci_afflvl_on.c b/services/std_svc/psci1.0/psci_afflvl_on.c
deleted file mode 100644 (file)
index 61003dc..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (c) 2013-2014, 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(unsigned int psci_state)
-{
-       if (psci_state == PSCI_STATE_ON || psci_state == PSCI_STATE_SUSPEND)
-               return PSCI_E_ALREADY_ON;
-
-       if (psci_state == PSCI_STATE_ON_PENDING)
-               return PSCI_E_ON_PENDING;
-
-       assert(psci_state == PSCI_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 affinity levels is changed after calling the
- * platform handler as it can return error.
- ******************************************************************************/
-int psci_afflvl_on(unsigned long target_cpu,
-                  entry_point_info_t *ep,
-                  int end_afflvl)
-{
-       int rc;
-       mpidr_aff_map_nodes_t target_cpu_nodes;
-       unsigned long psci_entrypoint;
-
-       /*
-        * This function must only be called on platforms where the
-        * CPU_ON platform hooks have been implemented.
-        */
-       assert(psci_plat_pm_ops->affinst_on &&
-                       psci_plat_pm_ops->affinst_on_finish);
-
-       /*
-        * Collect the pointers to the nodes in the topology tree for
-        * each affinity instance in the mpidr. If this function does
-        * not return successfully then either the mpidr or the affinity
-        * levels are incorrect.
-        */
-       rc = psci_get_aff_map_nodes(target_cpu,
-                                   MPIDR_AFFLVL0,
-                                   end_afflvl,
-                                   target_cpu_nodes);
-       assert(rc == PSCI_E_SUCCESS);
-
-       /*
-        * This function acquires the lock corresponding to each affinity
-        * level so that by the time all locks are taken, the system topology
-        * is snapshot and state management can be done safely.
-        */
-       psci_acquire_afflvl_locks(MPIDR_AFFLVL0,
-                                 end_afflvl,
-                                 target_cpu_nodes);
-
-       /*
-        * Generic management: Ensure that the cpu is off to be
-        * turned on.
-        */
-       rc = cpu_on_validate_state(psci_get_state(
-                                   target_cpu_nodes[MPIDR_AFFLVL0]));
-       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);
-
-       /*
-        * This function updates the state of each affinity instance
-        * corresponding to the mpidr in the range of affinity levels
-        * specified.
-        */
-       psci_do_afflvl_state_mgmt(MPIDR_AFFLVL0,
-                                  end_afflvl,
-                                  target_cpu_nodes,
-                                  PSCI_STATE_ON_PENDING);
-
-       /*
-        * Perform generic, architecture and platform specific handling.
-        */
-       /* Set the secure world (EL3) re-entry point after BL1 */
-       psci_entrypoint = (unsigned long) psci_aff_on_finish_entry;
-
-       /*
-        * Plat. management: Give the platform the current state
-        * of the target cpu to allow it to perform the necessary
-        * steps to power on.
-        */
-       rc = psci_plat_pm_ops->affinst_on(target_cpu,
-                                   psci_entrypoint,
-                                   MPIDR_AFFLVL0);
-       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(target_cpu, ep);
-       else
-               /* Restore the state on error. */
-               psci_do_afflvl_state_mgmt(MPIDR_AFFLVL0,
-                                         end_afflvl,
-                                         target_cpu_nodes,
-                                         PSCI_STATE_OFF);
-exit:
-       /*
-        * This loop releases the lock corresponding to each affinity level
-        * in the reverse order to which they were acquired.
-        */
-       psci_release_afflvl_locks(MPIDR_AFFLVL0,
-                                 end_afflvl,
-                                 target_cpu_nodes);
-
-       return rc;
-}
-
-/*******************************************************************************
- * The following function finish an earlier affinity power on request. They
- * are called by the common finisher routine in psci_common.c.
- ******************************************************************************/
-void psci_afflvl_on_finisher(aff_map_node_t *node[], int afflvl)
-{
-       assert(node[afflvl]->level == afflvl);
-
-       /* Ensure we have been explicitly woken up by another cpu */
-       assert(psci_get_state(node[MPIDR_AFFLVL0]) == PSCI_STATE_ON_PENDING);
-
-       /*
-        * 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->affinst_on_finish(afflvl);
-
-       /*
-        * 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();
-
-       /*
-        * 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);
-
-       /*
-        * 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);
-
-       /* Clean caches before re-entering normal world */
-       dcsw_op_louis(DCCSW);
-}
-
diff --git a/services/std_svc/psci1.0/psci_afflvl_suspend.c b/services/std_svc/psci1.0/psci_afflvl_suspend.c
deleted file mode 100644 (file)
index 9b57a47..0000000
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright (c) 2013-2014, 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 saves the power state parameter passed in the current PSCI
- * cpu_suspend call in the per-cpu data array.
- ******************************************************************************/
-void psci_set_suspend_power_state(unsigned int power_state)
-{
-       set_cpu_data(psci_svc_cpu_data.power_state, power_state);
-       flush_cpu_data(psci_svc_cpu_data.power_state);
-}
-
-/*******************************************************************************
- * This function gets the affinity level till which the current cpu could be
- * powered down during a cpu_suspend call. Returns PSCI_INVALID_DATA if the
- * power state is invalid.
- ******************************************************************************/
-int psci_get_suspend_afflvl(void)
-{
-       unsigned int power_state;
-
-       power_state = get_cpu_data(psci_svc_cpu_data.power_state);
-
-       return ((power_state == PSCI_INVALID_DATA) ?
-               power_state : psci_get_pstate_afflvl(power_state));
-}
-
-/*******************************************************************************
- * This function gets the state id of the current cpu from the power state
- * parameter saved in the per-cpu data array. Returns PSCI_INVALID_DATA if the
- * power state saved is invalid.
- ******************************************************************************/
-int psci_get_suspend_stateid(void)
-{
-       unsigned int power_state;
-
-       power_state = get_cpu_data(psci_svc_cpu_data.power_state);
-
-       return ((power_state == PSCI_INVALID_DATA) ?
-               power_state : psci_get_pstate_id(power_state));
-}
-
-/*******************************************************************************
- * This function gets the state id of the cpu specified by the 'mpidr' parameter
- * from the power state parameter saved in the per-cpu data array. Returns
- * PSCI_INVALID_DATA if the power state saved is invalid.
- ******************************************************************************/
-int psci_get_suspend_stateid_by_mpidr(unsigned long mpidr)
-{
-       unsigned int power_state;
-
-       power_state = get_cpu_data_by_mpidr(mpidr,
-                                           psci_svc_cpu_data.power_state);
-
-       return ((power_state == PSCI_INVALID_DATA) ?
-               power_state : psci_get_pstate_id(power_state));
-}
-
-/*******************************************************************************
- * Top level handler which is called when a cpu wants to suspend its execution.
- * It is assumed that along with suspending the cpu, higher affinity levels
- * until the target affinity level will be suspended as well.  It finds the
- * highest level to be suspended by traversing the node information and then
- * performs generic, architectural, platform setup and state management
- * required to suspend that affinity level and affinity 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_afflvl_suspend(entry_point_info_t *ep,
-                       int end_afflvl)
-{
-       int skip_wfi = 0;
-       mpidr_aff_map_nodes_t mpidr_nodes;
-       unsigned int max_phys_off_afflvl;
-       unsigned long psci_entrypoint;
-
-       /*
-        * This function must only be called on platforms where the
-        * CPU_SUSPEND platform hooks have been implemented.
-        */
-       assert(psci_plat_pm_ops->affinst_suspend &&
-                       psci_plat_pm_ops->affinst_suspend_finish);
-
-       /*
-        * Collect the pointers to the nodes in the topology tree for
-        * each affinity instance in the mpidr. If this function does
-        * not return successfully then either the mpidr or the affinity
-        * levels are incorrect. Either way, this an internal TF error
-        * therefore assert.
-        */
-       if (psci_get_aff_map_nodes(read_mpidr_el1() & MPIDR_AFFINITY_MASK,
-                  MPIDR_AFFLVL0, end_afflvl, mpidr_nodes) != PSCI_E_SUCCESS)
-               assert(0);
-
-       /*
-        * This function acquires the lock corresponding to each affinity
-        * level so that by the time all locks are taken, the system topology
-        * is snapshot and state management can be done safely.
-        */
-       psci_acquire_afflvl_locks(MPIDR_AFFLVL0,
-                                 end_afflvl,
-                                 mpidr_nodes);
-
-       /*
-        * 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;
-       }
-
-       /*
-        * Call the cpu suspend 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)
-               psci_spd_pm->svc_suspend(0);
-
-       /*
-        * This function updates the state of each affinity instance
-        * corresponding to the mpidr in the range of affinity levels
-        * specified.
-        */
-       psci_do_afflvl_state_mgmt(MPIDR_AFFLVL0,
-                                 end_afflvl,
-                                 mpidr_nodes,
-                                 PSCI_STATE_SUSPEND);
-
-       max_phys_off_afflvl = psci_find_max_phys_off_afflvl(MPIDR_AFFLVL0,
-                                                           end_afflvl,
-                                                           mpidr_nodes);
-       assert(max_phys_off_afflvl != PSCI_INVALID_DATA);
-
-       /*
-        * Store the re-entry information for the non-secure world.
-        */
-       cm_init_context(read_mpidr_el1(), ep);
-
-       /* Set the secure world (EL3) re-entry point after BL1 */
-       psci_entrypoint = (unsigned long) psci_aff_suspend_finish_entry;
-
-       /*
-        * Arch. management. Perform the necessary steps to flush all
-        * cpu caches.
-        */
-       psci_do_pwrdown_cache_maintenance(max_phys_off_afflvl);
-
-       /*
-        * 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->affinst_suspend(psci_entrypoint,
-                                       max_phys_off_afflvl);
-
-exit:
-       /*
-        * Release the locks corresponding to each affinity level in the
-        * reverse order to which they were acquired.
-        */
-       psci_release_afflvl_locks(MPIDR_AFFLVL0,
-                                 end_afflvl,
-                                 mpidr_nodes);
-       if (!skip_wfi)
-               psci_power_down_wfi();
-}
-
-/*******************************************************************************
- * The following functions finish an earlier affinity suspend request. They
- * are called by the common finisher routine in psci_common.c.
- ******************************************************************************/
-void psci_afflvl_suspend_finisher(aff_map_node_t *node[], int afflvl)
-{
-       int32_t suspend_level;
-       uint64_t counter_freq;
-
-       assert(node[afflvl]->level == afflvl);
-
-       /* Ensure we have been woken up from a suspended state */
-       assert(psci_get_state(node[MPIDR_AFFLVL0]) == PSCI_STATE_SUSPEND);
-
-       /*
-        * 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->affinst_suspend_finish(afflvl);
-
-       /*
-        * 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_freq();
-       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) {
-               suspend_level = psci_get_suspend_afflvl();
-               assert (suspend_level != PSCI_INVALID_DATA);
-               psci_spd_pm->svc_suspend_finish(suspend_level);
-       }
-
-       /* Invalidate the suspend context for the node */
-       psci_set_suspend_power_state(PSCI_INVALID_DATA);
-
-       /*
-        * 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);
-
-       /* Clean caches before re-entering normal world */
-       dcsw_op_louis(DCCSW);
-}
-
index 55bf7ef893b13c763b74ce75e377b5fa342ff374..55578379dcf38b59a278656b1e4025fa6ef730d5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * 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:
@@ -47,10 +47,10 @@ const spd_pm_ops_t *psci_spd_pm;
 
 /*******************************************************************************
  * Grand array that holds the platform's topology information for state
- * management of affinity instances. Each node (aff_map_node) in the array
- * corresponds to an affinity instance e.g. cluster, cpu within an mpidr
+ * management of power domain instances. Each node (pwr_map_node) in the array
+ * corresponds to a power domain instance e.g. cluster, cpu within an mpidr
  ******************************************************************************/
-aff_map_node_t psci_aff_map[PSCI_NUM_AFFS]
+pwr_map_node_t psci_pwr_domain_map[PSCI_NUM_PWR_DOMAINS]
 #if USE_COHERENT_MEM
 __attribute__ ((section("tzfw_coherent_mem")))
 #endif
@@ -62,33 +62,34 @@ __attribute__ ((section("tzfw_coherent_mem")))
 const plat_pm_ops_t *psci_plat_pm_ops;
 
 /*******************************************************************************
- * Check that the maximum affinity level supported by the platform makes sense
+ * Check that the maximum power level supported by the platform makes sense
  * ****************************************************************************/
-CASSERT(PLATFORM_MAX_AFFLVL <= MPIDR_MAX_AFFLVL && \
-               PLATFORM_MAX_AFFLVL >= MPIDR_AFFLVL0, \
-               assert_platform_max_afflvl_check);
+CASSERT(PLAT_MAX_PWR_LVL <= MPIDR_MAX_AFFLVL && \
+               PLAT_MAX_PWR_LVL >= MPIDR_AFFLVL0, \
+               assert_platform_max_pwrlvl_check);
 
 /*******************************************************************************
- * This function is passed an array of pointers to affinity level nodes in the
- * topology tree for an mpidr. It iterates through the nodes to find the highest
- * affinity level which is marked as physically powered off.
+ * This function is passed an array of pointers to power domain nodes in the
+ * topology tree for an mpidr. It iterates through the nodes to find the
+ * highest power level where the power domain is marked as physically powered
+ * off.
  ******************************************************************************/
-uint32_t psci_find_max_phys_off_afflvl(uint32_t start_afflvl,
-                                      uint32_t end_afflvl,
-                                      aff_map_node_t *mpidr_nodes[])
+uint32_t psci_find_max_phys_off_pwrlvl(uint32_t start_pwrlvl,
+                                      uint32_t end_pwrlvl,
+                                      pwr_map_node_t *mpidr_nodes[])
 {
-       uint32_t max_afflvl = PSCI_INVALID_DATA;
+       uint32_t max_pwrlvl = PSCI_INVALID_DATA;
 
-       for (; start_afflvl <= end_afflvl; start_afflvl++) {
-               if (mpidr_nodes[start_afflvl] == NULL)
+       for (; start_pwrlvl <= end_pwrlvl; start_pwrlvl++) {
+               if (mpidr_nodes[start_pwrlvl] == NULL)
                        continue;
 
-               if (psci_get_phys_state(mpidr_nodes[start_afflvl]) ==
+               if (psci_get_phys_state(mpidr_nodes[start_pwrlvl]) ==
                    PSCI_STATE_OFF)
-                       max_afflvl = start_afflvl;
+                       max_pwrlvl = start_pwrlvl;
        }
 
-       return max_afflvl;
+       return max_pwrlvl;
 }
 
 /*******************************************************************************
@@ -102,21 +103,21 @@ unsigned int psci_is_last_on_cpu(void)
        unsigned long mpidr = read_mpidr_el1() & MPIDR_AFFINITY_MASK;
        unsigned int i;
 
-       for (i = psci_aff_limits[MPIDR_AFFLVL0].min;
-                       i <= psci_aff_limits[MPIDR_AFFLVL0].max; i++) {
+       for (i = psci_pwr_lvl_limits[MPIDR_AFFLVL0].min;
+                       i <= psci_pwr_lvl_limits[MPIDR_AFFLVL0].max; i++) {
 
-               assert(psci_aff_map[i].level == MPIDR_AFFLVL0);
+               assert(psci_pwr_domain_map[i].level == MPIDR_AFFLVL0);
 
-               if (!(psci_aff_map[i].state & PSCI_AFF_PRESENT))
+               if (!(psci_pwr_domain_map[i].state & PSCI_AFF_PRESENT))
                        continue;
 
-               if (psci_aff_map[i].mpidr == mpidr) {
-                       assert(psci_get_state(&psci_aff_map[i])
+               if (psci_pwr_domain_map[i].mpidr == mpidr) {
+                       assert(psci_get_state(&psci_pwr_domain_map[i])
                                        == PSCI_STATE_ON);
                        continue;
                }
 
-               if (psci_get_state(&psci_aff_map[i]) != PSCI_STATE_OFF)
+               if (psci_get_state(&psci_pwr_domain_map[i]) != PSCI_STATE_OFF)
                        return 0;
        }
 
@@ -124,20 +125,20 @@ unsigned int psci_is_last_on_cpu(void)
 }
 
 /*******************************************************************************
- * Routine to return the maximum affinity level to traverse to after a cpu has
+ * 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.
  ******************************************************************************/
-int get_power_on_target_afflvl(void)
+int get_power_on_target_pwrlvl(void)
 {
-       int afflvl;
+       int pwrlvl;
 
 #if DEBUG
        unsigned int state;
-       aff_map_node_t *node;
+       pwr_map_node_t *node;
 
        /* Retrieve our node from the topology tree */
-       node = psci_get_aff_map_node(read_mpidr_el1() & MPIDR_AFFINITY_MASK,
+       node = psci_get_pwr_map_node(read_mpidr_el1() & MPIDR_AFFINITY_MASK,
                                     MPIDR_AFFLVL0);
        assert(node);
 
@@ -150,73 +151,74 @@ int get_power_on_target_afflvl(void)
 #endif
 
        /*
-        * Assume that this cpu was suspended and retrieve its target affinity
+        * 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. PLATFORM_MAX_AFFLVL will be the highest affinity level a
+        * earlier. PLAT_MAX_PWR_LVL will be the highest power level a
         * cpu can be turned off to.
         */
-       afflvl = psci_get_suspend_afflvl();
-       if (afflvl == PSCI_INVALID_DATA)
-               afflvl = PLATFORM_MAX_AFFLVL;
-       return afflvl;
+       pwrlvl = psci_get_suspend_pwrlvl();
+       if (pwrlvl == PSCI_INVALID_DATA)
+               pwrlvl = PLAT_MAX_PWR_LVL;
+       return pwrlvl;
 }
 
 /*******************************************************************************
- * Simple routine to set the id of an affinity instance at a given level in the
- * mpidr.
+ * Simple routine to set the id of a power domain instance at a given level
+ * in the mpidr. The assumption is that the affinity level and the power
+ * level are the same.
  ******************************************************************************/
-unsigned long mpidr_set_aff_inst(unsigned long mpidr,
-                                unsigned char aff_inst,
-                                int aff_lvl)
+unsigned long mpidr_set_pwr_domain_inst(unsigned long mpidr,
+                                unsigned char pwr_inst,
+                                int pwr_lvl)
 {
        unsigned long aff_shift;
 
-       assert(aff_lvl <= MPIDR_AFFLVL3);
+       assert(pwr_lvl <= MPIDR_AFFLVL3);
 
        /*
         * Decide the number of bits to shift by depending upon
-        * the affinity level
+        * the power level
         */
-       aff_shift = get_afflvl_shift(aff_lvl);
+       aff_shift = get_afflvl_shift(pwr_lvl);
 
        /* Clear the existing affinity instance & set the new one*/
        mpidr &= ~(((unsigned long)MPIDR_AFFLVL_MASK) << aff_shift);
-       mpidr |= ((unsigned long)aff_inst) << aff_shift;
+       mpidr |= ((unsigned long)pwr_inst) << aff_shift;
 
        return mpidr;
 }
 
 /*******************************************************************************
- * This function sanity checks a range of affinity levels.
+ * This function sanity checks a range of power levels.
  ******************************************************************************/
-int psci_check_afflvl_range(int start_afflvl, int end_afflvl)
+int psci_check_pwrlvl_range(int start_pwrlvl, int end_pwrlvl)
 {
        /* Sanity check the parameters passed */
-       if (end_afflvl > PLATFORM_MAX_AFFLVL)
+       if (end_pwrlvl > PLAT_MAX_PWR_LVL)
                return PSCI_E_INVALID_PARAMS;
 
-       if (start_afflvl < MPIDR_AFFLVL0)
+       if (start_pwrlvl < MPIDR_AFFLVL0)
                return PSCI_E_INVALID_PARAMS;
 
-       if (end_afflvl < start_afflvl)
+       if (end_pwrlvl < start_pwrlvl)
                return PSCI_E_INVALID_PARAMS;
 
        return PSCI_E_SUCCESS;
 }
 
 /*******************************************************************************
- * This function is passed an array of pointers to affinity level nodes in the
+ * This function is passed an array of pointers to power domain nodes in the
  * topology tree for an mpidr and the state which each node should transition
- * to. It updates the state of each node between the specified affinity levels.
+ * to. It updates the state of each node between the specified power levels.
  ******************************************************************************/
-void psci_do_afflvl_state_mgmt(uint32_t start_afflvl,
-                              uint32_t end_afflvl,
-                              aff_map_node_t *mpidr_nodes[],
+void psci_do_state_coordination(uint32_t start_pwrlvl,
+                              uint32_t end_pwrlvl,
+                              pwr_map_node_t *mpidr_nodes[],
                               uint32_t state)
 {
        uint32_t level;
 
-       for (level = start_afflvl; level <= end_afflvl; level++) {
+       for (level = start_pwrlvl; level <= end_pwrlvl; level++) {
                if (mpidr_nodes[level] == NULL)
                        continue;
                psci_set_state(mpidr_nodes[level], state);
@@ -224,17 +226,17 @@ void psci_do_afflvl_state_mgmt(uint32_t start_afflvl,
 }
 
 /*******************************************************************************
- * This function is passed an array of pointers to affinity level nodes in the
- * topology tree for an mpidr. It picks up locks for each affinity level bottom
+ * This function is passed an array of pointers to power domain nodes in the
+ * topology tree for an mpidr. It picks up locks for each power level bottom
  * up in the range specified.
  ******************************************************************************/
-void psci_acquire_afflvl_locks(int start_afflvl,
-                              int end_afflvl,
-                              aff_map_node_t *mpidr_nodes[])
+void psci_acquire_pwr_domain_locks(int start_pwrlvl,
+                              int end_pwrlvl,
+                              pwr_map_node_t *mpidr_nodes[])
 {
        int level;
 
-       for (level = start_afflvl; level <= end_afflvl; level++) {
+       for (level = start_pwrlvl; level <= end_pwrlvl; level++) {
                if (mpidr_nodes[level] == NULL)
                        continue;
 
@@ -243,17 +245,17 @@ void psci_acquire_afflvl_locks(int start_afflvl,
 }
 
 /*******************************************************************************
- * This function is passed an array of pointers to affinity level nodes in the
- * topology tree for an mpidr. It releases the lock for each affinity level top
+ * This function is passed an array of pointers to power domain nodes in the
+ * topology tree for an mpidr. It releases the lock for each power level top
  * down in the range specified.
  ******************************************************************************/
-void psci_release_afflvl_locks(int start_afflvl,
-                              int end_afflvl,
-                              aff_map_node_t *mpidr_nodes[])
+void psci_release_pwr_domain_locks(int start_pwrlvl,
+                              int end_pwrlvl,
+                              pwr_map_node_t *mpidr_nodes[])
 {
        int level;
 
-       for (level = end_afflvl; level >= start_afflvl; level--) {
+       for (level = end_pwrlvl; level >= start_pwrlvl; level--) {
                if (mpidr_nodes[level] == NULL)
                        continue;
 
@@ -262,15 +264,15 @@ void psci_release_afflvl_locks(int start_afflvl,
 }
 
 /*******************************************************************************
- * Simple routine to determine whether an affinity instance at a given level
- * in an mpidr exists or not.
+ * Simple routine to determine whether an power domain instance at a given
+ * level in an mpidr exists or not.
  ******************************************************************************/
 int psci_validate_mpidr(unsigned long mpidr, int level)
 {
-       aff_map_node_t *node;
+       pwr_map_node_t *node;
 
-       node = psci_get_aff_map_node(mpidr, level);
-       if (node && (node->state & PSCI_AFF_PRESENT))
+       node = psci_get_pwr_map_node(mpidr, level);
+       if (node && (node->state & PSCI_PWR_DOMAIN_PRESENT))
                return PSCI_E_SUCCESS;
        else
                return PSCI_E_INVALID_PARAMS;
@@ -334,10 +336,10 @@ int psci_get_ns_ep_info(entry_point_info_t *ep,
 }
 
 /*******************************************************************************
- * This function takes a pointer to an affinity node in the topology tree and
- * returns its state. State of a non-leaf node needs to be calculated.
+ * This function takes a pointer to a power domain node in the topology tree
+ * and returns its state. State of a non-leaf node needs to be calculated.
  ******************************************************************************/
-unsigned short psci_get_state(aff_map_node_t *node)
+unsigned short psci_get_state(pwr_map_node_t *node)
 {
 #if !USE_COHERENT_MEM
        flush_dcache_range((uint64_t) node, sizeof(*node));
@@ -350,11 +352,11 @@ unsigned short psci_get_state(aff_map_node_t *node)
                return (node->state >> PSCI_STATE_SHIFT) & PSCI_STATE_MASK;
 
        /*
-        * For an affinity level higher than a cpu, the state has to be
+        * For a power level higher than a cpu, the state has to be
         * calculated. It depends upon the value of the reference count
-        * which is managed by each node at the next lower affinity level
+        * which is managed by each node at the next lower power level
         * e.g. for a cluster, each cpu increments/decrements the reference
-        * count. If the reference count is 0 then the affinity level is
+        * count. If the reference count is 0 then the power level is
         * OFF else ON.
         */
        if (node->ref_count)
@@ -364,16 +366,16 @@ unsigned short psci_get_state(aff_map_node_t *node)
 }
 
 /*******************************************************************************
- * This function takes a pointer to an affinity node in the topology tree and
- * a target state. State of a non-leaf node needs to be converted to a reference
- * count. State of a leaf node can be set directly.
+ * This function takes a pointer to a power domain node in the topology
+ * tree and a target state. State of a non-leaf node needs to be converted
+ * to a reference count. State of a leaf node can be set directly.
  ******************************************************************************/
-void psci_set_state(aff_map_node_t *node, unsigned short state)
+void psci_set_state(pwr_map_node_t *node, unsigned short state)
 {
        assert(node->level >= MPIDR_AFFLVL0 && node->level <= MPIDR_MAX_AFFLVL);
 
        /*
-        * For an affinity level higher than a cpu, the state is used
+        * For a power level higher than a cpu, the state is used
         * to decide whether the reference count is incremented or
         * decremented. Entry into the ON_PENDING state does not have
         * effect.
@@ -389,7 +391,7 @@ void psci_set_state(aff_map_node_t *node, unsigned short state)
                        break;
                case PSCI_STATE_ON_PENDING:
                        /*
-                        * An affinity level higher than a cpu will not undergo
+                        * A power level higher than a cpu will not undergo
                         * a state change when it is about to be turned on
                         */
                        return;
@@ -407,13 +409,13 @@ void psci_set_state(aff_map_node_t *node, unsigned short state)
 }
 
 /*******************************************************************************
- * An affinity level could be on, on_pending, suspended or off. These are the
+ * A power domain could be on, on_pending, suspended or off. These are the
  * logical states it can be in. Physically either it is off or on. When it is in
  * the state on_pending then it is about to be turned on. It is not possible to
- * tell whether that's actually happenned or not. So we err on the side of
- * caution & treat the affinity level as being turned off.
+ * tell whether that's actually happened or not. So we err on the side of
+ * caution & treat the power domain as being turned off.
  ******************************************************************************/
-unsigned short psci_get_phys_state(aff_map_node_t *node)
+unsigned short psci_get_phys_state(pwr_map_node_t *node)
 {
        unsigned int state;
 
@@ -423,70 +425,67 @@ unsigned short psci_get_phys_state(aff_map_node_t *node)
 
 /*******************************************************************************
  * Generic handler which is called when a cpu is physically powered on. It
- * traverses the node information and finds the highest affinity level powered
+ * 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 affinity level and affinity levels below it.
+ * 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.
- *
- * The state of all the relevant affinity levels is changed prior to calling
- * the platform specific code.
  ******************************************************************************/
-void psci_afflvl_power_on_finish(int end_afflvl,
-                                afflvl_power_on_finisher_t pon_handler)
+void psci_power_up_finish(int end_pwrlvl,
+                                pwrlvl_power_on_finisher_t pon_handler)
 {
-       mpidr_aff_map_nodes_t mpidr_nodes;
+       mpidr_pwr_map_nodes_t mpidr_nodes;
        int rc;
-       unsigned int max_phys_off_afflvl;
+       unsigned int max_phys_off_pwrlvl;
 
 
        /*
         * Collect the pointers to the nodes in the topology tree for
-        * each affinity instance in the mpidr. If this function does
-        * not return successfully then either the mpidr or the affinity
+        * each power domain instances in the mpidr. If this function does
+        * not return successfully then either the mpidr or the power
         * levels are incorrect. Either case is an irrecoverable error.
         */
-       rc = psci_get_aff_map_nodes(read_mpidr_el1() & MPIDR_AFFINITY_MASK,
+       rc = psci_get_pwr_map_nodes(read_mpidr_el1() & MPIDR_AFFINITY_MASK,
                                    MPIDR_AFFLVL0,
-                                   end_afflvl,
+                                   end_pwrlvl,
                                    mpidr_nodes);
        if (rc != PSCI_E_SUCCESS)
                panic();
 
        /*
-        * This function acquires the lock corresponding to each affinity
+        * 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_afflvl_locks(MPIDR_AFFLVL0,
-                                 end_afflvl,
+       psci_acquire_pwr_domain_locks(MPIDR_AFFLVL0,
+                                 end_pwrlvl,
                                  mpidr_nodes);
 
-       max_phys_off_afflvl = psci_find_max_phys_off_afflvl(MPIDR_AFFLVL0,
-                                                           end_afflvl,
+       max_phys_off_pwrlvl = psci_find_max_phys_off_pwrlvl(MPIDR_AFFLVL0,
+                                                           end_pwrlvl,
                                                            mpidr_nodes);
-       assert(max_phys_off_afflvl != PSCI_INVALID_DATA);
+       assert(max_phys_off_pwrlvl != PSCI_INVALID_DATA);
 
        /* Perform generic, architecture and platform specific handling */
-       pon_handler(mpidr_nodes, max_phys_off_afflvl);
+       pon_handler(mpidr_nodes, max_phys_off_pwrlvl);
 
        /*
-        * This function updates the state of each affinity instance
-        * corresponding to the mpidr in the range of affinity levels
+        * This function updates the state of each power instance
+        * corresponding to the mpidr in the range of power levels
         * specified.
         */
-       psci_do_afflvl_state_mgmt(MPIDR_AFFLVL0,
-                                 end_afflvl,
+       psci_do_state_coordination(MPIDR_AFFLVL0,
+                                 end_pwrlvl,
                                  mpidr_nodes,
                                  PSCI_STATE_ON);
 
        /*
-        * This loop releases the lock corresponding to each affinity level
+        * This loop releases the lock corresponding to each power level
         * in the reverse order to which they were acquired.
         */
-       psci_release_afflvl_locks(MPIDR_AFFLVL0,
-                                 end_afflvl,
+       psci_release_pwr_domain_locks(MPIDR_AFFLVL0,
+                                 end_pwrlvl,
                                  mpidr_nodes);
 }
 
@@ -532,13 +531,13 @@ int psci_spd_migrate_info(uint64_t *mpidr)
 
 
 /*******************************************************************************
- * This function prints the state of all affinity instances present in the
+ * This function prints the state of all power domains present in the
  * system
  ******************************************************************************/
-void psci_print_affinity_map(void)
+void psci_print_power_domain_map(void)
 {
 #if LOG_LEVEL >= LOG_LEVEL_INFO
-       aff_map_node_t *node;
+       pwr_map_node_t *node;
        unsigned int idx;
        /* This array maps to the PSCI_STATE_X definitions in psci.h */
        static const char *psci_state_str[] = {
@@ -548,13 +547,13 @@ void psci_print_affinity_map(void)
                "SUSPEND"
        };
 
-       INFO("PSCI Affinity Map:\n");
-       for (idx = 0; idx < PSCI_NUM_AFFS ; idx++) {
-               node = &psci_aff_map[idx];
-               if (!(node->state & PSCI_AFF_PRESENT)) {
+       INFO("PSCI Power Domain Map:\n");
+       for (idx = 0; idx < PSCI_NUM_PWR_DOMAINS; idx++) {
+               node = &psci_pwr_domain_map[idx];
+               if (!(node->state & PSCI_PWR_DOMAIN_PRESENT)) {
                        continue;
                }
-               INFO("  AffInst: Level %u, MPID 0x%lx, State %s\n",
+               INFO("  pwrInst: Level %u, MPID 0x%lx, State %s\n",
                                node->level, node->mpidr,
                                psci_state_str[psci_get_state(node)]);
        }
index 13a0b860a1eb06c8a650cd226680b5dbb8e5a1ec..4e7456dbd421cd70eec7dff69be9b4cfd5fc428b 100644 (file)
@@ -34,8 +34,8 @@
 #include <psci.h>
 #include <xlat_tables.h>
 
-       .globl  psci_aff_on_finish_entry
-       .globl  psci_aff_suspend_finish_entry
+       .globl  psci_cpu_on_finish_entry
+       .globl  psci_cpu_suspend_finish_entry
        .globl  psci_power_down_wfi
 
        /* -----------------------------------------------------
         * the handlers (chosen depending upon original state).
         * -----------------------------------------------------
         */
-func psci_aff_on_finish_entry
-       adr     x23, psci_afflvl_on_finisher
-       b       psci_aff_common_finish_entry
+func psci_cpu_on_finish_entry
+       adr     x23, psci_cpu_on_finish
+       b       psci_power_up_entry
 
-psci_aff_suspend_finish_entry:
-       adr     x23, psci_afflvl_suspend_finisher
+psci_cpu_suspend_finish_entry:
+       adr     x23, psci_cpu_suspend_finish
 
-psci_aff_common_finish_entry:
+psci_power_up_entry:
        /*
         * On the warm boot path, most of the EL3 initialisations performed by
         * 'el3_entrypoint_common' must be skipped:
@@ -98,12 +98,12 @@ psci_aff_common_finish_entry:
        mov     x0, #DISABLE_DCACHE
        bl      bl31_plat_enable_mmu
 
-       bl      get_power_on_target_afflvl
+       bl      get_power_on_target_pwrlvl
        mov     x1, x23
-       bl      psci_afflvl_power_on_finish
+       bl      psci_power_up_finish
 
        b       el3_exit
-endfunc psci_aff_on_finish_entry
+endfunc psci_cpu_on_finish_entry
 
        /* --------------------------------------------
         * This function is called to indicate to the
index 05a80f2d4acb3e76a44ecf459a71eeb1b5d88ffa..07fb889389a3e8600e3631ca451906e643b2bdc9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * 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:
        .globl  psci_do_pwrup_cache_maintenance
 
 /* -----------------------------------------------------------------------
- * void psci_do_pwrdown_cache_maintenance(uint32_t affinity level);
+ * void psci_do_pwrdown_cache_maintenance(uint32_t power level);
  *
- * This function performs cache maintenance if the specified affinity
- * level is the equal to the level of the highest affinity instance which
- * will be/is physically powered off. The levels of cache affected are
- * determined by the affinity 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 affinity 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
@@ -58,11 +57,11 @@ func psci_do_pwrdown_cache_maintenance
 
        /* ---------------------------------------------
         * Determine to how many levels of cache will be
-        * subject to cache maintenance. Affinity level
+        * 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
-        * affinity level we are assuming that a flush
+        * 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.
index 9741fb68fdf33f8e8433589543bee2e2bb5c79bd..0421b15f8295dd67bae57aaa55504fe1fa897cd3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * 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:
@@ -46,7 +46,7 @@ int psci_cpu_on(unsigned long target_cpu,
 
 {
        int rc;
-       unsigned int end_afflvl;
+       unsigned int end_pwrlvl;
        entry_point_info_t ep;
 
        /* Determine if the cpu exists of not */
@@ -74,13 +74,13 @@ int psci_cpu_on(unsigned long target_cpu,
                return rc;
 
        /*
-        * To turn this cpu on, specify which affinity
+        * To turn this cpu on, specify which power
         * levels need to be turned on
         */
-       end_afflvl = PLATFORM_MAX_AFFLVL;
-       rc = psci_afflvl_on(target_cpu,
+       end_pwrlvl = PLAT_MAX_PWR_LVL;
+       rc = psci_cpu_on_start(target_cpu,
                            &ep,
-                           end_afflvl);
+                           end_pwrlvl);
        return rc;
 }
 
@@ -94,7 +94,7 @@ int psci_cpu_suspend(unsigned int power_state,
                     unsigned long context_id)
 {
        int rc;
-       unsigned int target_afflvl, pstate_type;
+       unsigned int target_pwrlvl, pstate_type;
        entry_point_info_t ep;
 
        /* Check SBZ bits in power state are zero */
@@ -102,8 +102,8 @@ int psci_cpu_suspend(unsigned int power_state,
                return PSCI_E_INVALID_PARAMS;
 
        /* Sanity check the requested state */
-       target_afflvl = psci_get_pstate_afflvl(power_state);
-       if (target_afflvl > PLATFORM_MAX_AFFLVL)
+       target_pwrlvl = psci_get_pstate_pwrlvl(power_state);
+       if (target_pwrlvl > PLAT_MAX_PWR_LVL)
                return PSCI_E_INVALID_PARAMS;
 
        /* Validate the power_state using platform pm_ops */
@@ -132,10 +132,10 @@ int psci_cpu_suspend(unsigned int power_state,
         * a standby state.
         */
        if (pstate_type == PSTATE_TYPE_STANDBY) {
-               if  (!psci_plat_pm_ops->affinst_standby)
+               if  (!psci_plat_pm_ops->pwr_domain_standby)
                        return PSCI_E_INVALID_PARAMS;
 
-               psci_plat_pm_ops->affinst_standby(power_state);
+               psci_plat_pm_ops->pwr_domain_standby(power_state);
                return PSCI_E_SUCCESS;
        }
 
@@ -155,8 +155,8 @@ int psci_cpu_suspend(unsigned int power_state,
         * Do what is needed to enter the power down state. Upon success,
         * enter the final wfi which will power down this CPU.
         */
-       psci_afflvl_suspend(&ep,
-                           target_afflvl);
+       psci_cpu_suspend_start(&ep,
+                           target_pwrlvl);
 
        /* Reset PSCI power state parameter for the core. */
        psci_set_suspend_power_state(PSCI_INVALID_DATA);
@@ -210,9 +210,7 @@ int psci_system_suspend(unsigned long entrypoint,
         * Do what is needed to enter the power down state. Upon success,
         * enter the final wfi which will power down this cpu.
         */
-       psci_afflvl_suspend(&ep,
-                           MPIDR_AFFLVL0,
-                           PLATFORM_MAX_AFFLVL);
+       psci_cpu_suspend_start(&ep, PLAT_MAX_PWR_LVL);
 
        /* Reset PSCI power state parameter for the core. */
        psci_set_suspend_power_state(PSCI_INVALID_DATA);
@@ -222,15 +220,14 @@ int psci_system_suspend(unsigned long entrypoint,
 int psci_cpu_off(void)
 {
        int rc;
-       int target_afflvl = PLATFORM_MAX_AFFLVL;
+       int target_pwrlvl = PLAT_MAX_PWR_LVL;
 
        /*
-        * Traverse from the highest to the lowest affinity level. When the
-        * lowest affinity level is hit, all the locks are acquired. State
-        * management is done immediately followed by cpu, cluster ...
-        * ..target_afflvl specific actions as this function unwinds back.
+        * 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_afflvl_off(target_afflvl);
+       rc = psci_do_cpu_off(target_pwrlvl);
 
        /*
         * The only error cpu_off can return is E_DENIED. So check if that's
@@ -245,28 +242,28 @@ int psci_affinity_info(unsigned long target_affinity,
                       unsigned int lowest_affinity_level)
 {
        int rc = PSCI_E_INVALID_PARAMS;
-       unsigned int aff_state;
-       aff_map_node_t *node;
+       unsigned int pwr_domain_state;
+       pwr_map_node_t *node;
 
-       if (lowest_affinity_level > PLATFORM_MAX_AFFLVL)
+       if (lowest_affinity_level > PLAT_MAX_PWR_LVL)
                return rc;
 
-       node = psci_get_aff_map_node(target_affinity, lowest_affinity_level);
-       if (node && (node->state & PSCI_AFF_PRESENT)) {
+       node = psci_get_pwr_map_node(target_affinity, lowest_affinity_level);
+       if (node && (node->state & PSCI_PWR_DOMAIN_PRESENT)) {
 
                /*
-                * TODO: For affinity levels higher than 0 i.e. cpu, the
+                * TODO: For power levels higher than 0 i.e. cpu, the
                 * state will always be either ON or OFF. Need to investigate
                 * how critical is it to support ON_PENDING here.
                 */
-               aff_state = psci_get_state(node);
+               pwr_domain_state = psci_get_state(node);
 
                /* A suspended cpu is available & on for the OS */
-               if (aff_state == PSCI_STATE_SUSPEND) {
-                       aff_state = PSCI_STATE_ON;
+               if (pwr_domain_state == PSCI_STATE_SUSPEND) {
+                       pwr_domain_state = PSCI_STATE_ON;
                }
 
-               rc = aff_state;
+               rc = pwr_domain_state;
        }
 
        return rc;
diff --git a/services/std_svc/psci1.0/psci_off.c b/services/std_svc/psci1.0/psci_off.c
new file mode 100644 (file)
index 0000000..f4fb980
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * 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 <string.h>
+#include "psci_private.h"
+
+/******************************************************************************
+ * 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(int end_pwrlvl)
+{
+       int rc;
+       mpidr_pwr_map_nodes_t mpidr_nodes;
+       unsigned int max_phys_off_pwrlvl;
+
+       /*
+        * 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);
+
+       /*
+        * Collect the pointers to the nodes in the topology tree for
+        * each power domain instance in the mpidr. If this function does
+        * not return successfully then either the mpidr or the power
+        * levels are incorrect. Either way, this an internal TF error
+        * therefore assert.
+        */
+       rc = psci_get_pwr_map_nodes(read_mpidr_el1() & MPIDR_AFFINITY_MASK,
+                                   MPIDR_AFFLVL0,
+                                   end_pwrlvl,
+                                   mpidr_nodes);
+       assert(rc == PSCI_E_SUCCESS);
+
+       /*
+        * 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(MPIDR_AFFLVL0,
+                                 end_pwrlvl,
+                                 mpidr_nodes);
+
+
+       /*
+        * 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;
+       }
+
+       /*
+        * This function updates the state of each power domain instance
+        * corresponding to the mpidr in the range of power levels
+        * specified.
+        */
+       psci_do_state_coordination(MPIDR_AFFLVL0,
+                                 end_pwrlvl,
+                                 mpidr_nodes,
+                                 PSCI_STATE_OFF);
+
+       max_phys_off_pwrlvl = psci_find_max_phys_off_pwrlvl(MPIDR_AFFLVL0,
+                                                          end_pwrlvl,
+                                                          mpidr_nodes);
+       assert(max_phys_off_pwrlvl != PSCI_INVALID_DATA);
+
+       /*
+        * Arch. management. Perform the necessary steps to flush all
+        * cpu caches.
+        */
+       psci_do_pwrdown_cache_maintenance(max_phys_off_pwrlvl);
+
+       /*
+        * 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(max_phys_off_pwrlvl);
+
+exit:
+       /*
+        * Release the locks corresponding to each power level in the
+        * reverse order to which they were acquired.
+        */
+       psci_release_pwr_domain_locks(MPIDR_AFFLVL0,
+                                 end_pwrlvl,
+                                 mpidr_nodes);
+
+       /*
+        * Check if all actions needed to safely power down this cpu have
+        * successfully completed. Enter a wfi loop which will allow the
+        * power controller to physically power down this cpu.
+        */
+       if (rc == PSCI_E_SUCCESS)
+               psci_power_down_wfi();
+
+       return rc;
+}
diff --git a/services/std_svc/psci1.0/psci_on.c b/services/std_svc/psci1.0/psci_on.c
new file mode 100644 (file)
index 0000000..43f58f9
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * 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(unsigned int psci_state)
+{
+       if (psci_state == PSCI_STATE_ON || psci_state == PSCI_STATE_SUSPEND)
+               return PSCI_E_ALREADY_ON;
+
+       if (psci_state == PSCI_STATE_ON_PENDING)
+               return PSCI_E_ON_PENDING;
+
+       assert(psci_state == PSCI_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(unsigned long target_cpu,
+                  entry_point_info_t *ep,
+                  int end_pwrlvl)
+{
+       int rc;
+       mpidr_pwr_map_nodes_t target_cpu_nodes;
+       unsigned long psci_entrypoint;
+
+       /*
+        * 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);
+
+       /*
+        * Collect the pointers to the nodes in the topology tree for
+        * each power domain instance in the mpidr. If this function does
+        * not return successfully then either the mpidr or the power
+        * levels are incorrect.
+        */
+       rc = psci_get_pwr_map_nodes(target_cpu,
+                                   MPIDR_AFFLVL0,
+                                   end_pwrlvl,
+                                   target_cpu_nodes);
+       assert(rc == PSCI_E_SUCCESS);
+
+       /*
+        * 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(MPIDR_AFFLVL0,
+                                 end_pwrlvl,
+                                 target_cpu_nodes);
+
+       /*
+        * Generic management: Ensure that the cpu is off to be
+        * turned on.
+        */
+       rc = cpu_on_validate_state(psci_get_state(
+                                   target_cpu_nodes[MPIDR_AFFLVL0]));
+       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);
+
+       /*
+        * This function updates the state of each affinity instance
+        * corresponding to the mpidr in the range of affinity levels
+        * specified.
+        */
+       psci_do_state_coordination(MPIDR_AFFLVL0,
+                                  end_pwrlvl,
+                                  target_cpu_nodes,
+                                  PSCI_STATE_ON_PENDING);
+
+       /*
+        * Perform generic, architecture and platform specific handling.
+        */
+       /* Set the secure world (EL3) re-entry point after BL1 */
+       psci_entrypoint = (unsigned long) psci_cpu_on_finish_entry;
+
+       /*
+        * Plat. management: Give the platform the current state
+        * of the target cpu to allow it to perform the necessary
+        * steps to power on.
+        */
+       rc = psci_plat_pm_ops->pwr_domain_on(target_cpu,
+                                   psci_entrypoint,
+                                   MPIDR_AFFLVL0);
+       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(target_cpu, ep);
+       else
+               /* Restore the state on error. */
+               psci_do_state_coordination(MPIDR_AFFLVL0,
+                                         end_pwrlvl,
+                                         target_cpu_nodes,
+                                         PSCI_STATE_OFF);
+exit:
+       /*
+        * This loop releases the lock corresponding to each power level
+        * in the reverse order to which they were acquired.
+        */
+       psci_release_pwr_domain_locks(MPIDR_AFFLVL0,
+                                 end_pwrlvl,
+                                 target_cpu_nodes);
+
+       return rc;
+}
+
+/*******************************************************************************
+ * The following function finish an earlier power on request. They
+ * are called by the common finisher routine in psci_common.c.
+ ******************************************************************************/
+void psci_cpu_on_finish(pwr_map_node_t *node[], int pwrlvl)
+{
+       assert(node[pwrlvl]->level == pwrlvl);
+
+       /* Ensure we have been explicitly woken up by another cpu */
+       assert(psci_get_state(node[MPIDR_AFFLVL0]) == PSCI_STATE_ON_PENDING);
+
+       /*
+        * 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(pwrlvl);
+
+       /*
+        * 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();
+
+       /*
+        * 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);
+
+       /*
+        * 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);
+
+       /* Clean caches before re-entering normal world */
+       dcsw_op_louis(DCCSW);
+}
+
index 7797fa7927a2d124e81f8dd53af535e3a89c0248..e56d848bce51e0e903c6c70434d6d46eaf663695 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * 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:
  * Lock API.
  */
 #if USE_COHERENT_MEM
-#define psci_lock_init(aff_map, idx)   bakery_lock_init(&(aff_map)[(idx)].lock)
+#define psci_lock_init(pwr_map, idx)   bakery_lock_init(&(pwr_map)[(idx)].lock)
 #define psci_lock_get(node)            bakery_lock_get(&((node)->lock))
 #define psci_lock_release(node)                bakery_lock_release(&((node)->lock))
 #else
-#define psci_lock_init(aff_map, idx)   ((aff_map)[(idx)].aff_map_index = (idx))
-#define psci_lock_get(node)            bakery_lock_get((node)->aff_map_index,    \
+#define psci_lock_init(pwr_map, idx)   \
+                               ((pwr_map)[(idx)].pwr_domain_index = (idx))
+#define psci_lock_get(node)            \
+                               bakery_lock_get((node)->pwr_domain_index,\
                                                CPU_DATA_PSCI_LOCK_OFFSET)
-#define psci_lock_release(node)                bakery_lock_release((node)->aff_map_index,\
+#define psci_lock_release(node)                \
+                               bakery_lock_release((node)->pwr_domain_index,\
                                                CPU_DATA_PSCI_LOCK_OFFSET)
 #endif
 
@@ -75,9 +78,9 @@
 
 /*******************************************************************************
  * The following two data structures hold the topology tree which in turn tracks
- * the state of the all the affinity instances supported by the platform.
+ * the state of the all the power domain instances supported by the platform.
  ******************************************************************************/
-typedef struct aff_map_node {
+typedef struct pwr_map_node {
        unsigned long mpidr;
        unsigned char ref_count;
        unsigned char state;
@@ -86,25 +89,25 @@ typedef struct aff_map_node {
        bakery_lock_t lock;
 #else
        /* For indexing the bakery_info array in per CPU data */
-       unsigned char aff_map_index;
+       unsigned char pwr_domain_index;
 #endif
-} aff_map_node_t;
+} pwr_map_node_t;
 
-typedef struct aff_limits_node {
+typedef struct pwr_lvl_limits_node {
        int min;
        int max;
-} aff_limits_node_t;
+} pwr_lvl_limits_node_t;
 
-typedef aff_map_node_t (*mpidr_aff_map_nodes_t[MPIDR_MAX_AFFLVL + 1]);
-typedef void (*afflvl_power_on_finisher_t)(aff_map_node_t *mpidr_nodes[],
-                                       int afflvl);
+typedef pwr_map_node_t (*mpidr_pwr_map_nodes_t[MPIDR_MAX_AFFLVL + 1]);
+typedef void (*pwrlvl_power_on_finisher_t)(pwr_map_node_t *mpidr_nodes[],
+                                       int pwrlvl);
 
 /*******************************************************************************
  * Data prototypes
  ******************************************************************************/
 extern const plat_pm_ops_t *psci_plat_pm_ops;
-extern aff_map_node_t psci_aff_map[PSCI_NUM_AFFS];
-extern aff_limits_node_t psci_aff_limits[MPIDR_MAX_AFFLVL + 1];
+extern pwr_map_node_t psci_pwr_domain_map[PSCI_NUM_PWR_DOMAINS];
+extern pwr_lvl_limits_node_t psci_pwr_domain_map[MPIDR_MAX_AFFLVL + 1];
 extern uint32_t psci_caps;
 
 /*******************************************************************************
@@ -116,61 +119,61 @@ extern const spd_pm_ops_t *psci_spd_pm;
  * Function prototypes
  ******************************************************************************/
 /* Private exported functions from psci_common.c */
-unsigned short psci_get_state(aff_map_node_t *node);
-unsigned short psci_get_phys_state(aff_map_node_t *node);
-void psci_set_state(aff_map_node_t *node, unsigned short state);
-unsigned long mpidr_set_aff_inst(unsigned long, unsigned char, int);
+unsigned short psci_get_state(pwr_map_node_t *node);
+unsigned short psci_get_phys_state(pwr_map_node_t *node);
+void psci_set_state(pwr_map_node_t *node, unsigned short state);
+unsigned long mpidr_set_pwr_domain_inst(unsigned long, unsigned char, int);
 int psci_validate_mpidr(unsigned long, int);
-int get_power_on_target_afflvl(void);
-void psci_afflvl_power_on_finish(int end_afflvl,
-                                afflvl_power_on_finisher_t pon_handler);
+int get_power_on_target_pwrlvl(void);
+void psci_power_up_finish(int end_pwrlvl,
+                                pwrlvl_power_on_finisher_t pon_handler);
 int psci_get_ns_ep_info(entry_point_info_t *ep,
                       uint64_t entrypoint, uint64_t context_id);
-int psci_check_afflvl_range(int start_afflvl, int end_afflvl);
-void psci_do_afflvl_state_mgmt(uint32_t start_afflvl,
-                              uint32_t end_afflvl,
-                              aff_map_node_t *mpidr_nodes[],
+int psci_check_pwrlvl_range(int start_pwrlvl, int end_pwrlvl);
+void psci_do_state_coordination(uint32_t start_pwrlvl,
+                              uint32_t end_pwrlvl,
+                              pwr_map_node_t *mpidr_nodes[],
                               uint32_t state);
-void psci_acquire_afflvl_locks(int start_afflvl,
-                              int end_afflvl,
-                              aff_map_node_t *mpidr_nodes[]);
-void psci_release_afflvl_locks(int start_afflvl,
-                               int end_afflvl,
-                               mpidr_aff_map_nodes_t mpidr_nodes);
-void psci_print_affinity_map(void);
-uint32_t psci_find_max_phys_off_afflvl(uint32_t start_afflvl,
-                                      uint32_t end_afflvl,
-                                      aff_map_node_t *mpidr_nodes[]);
+void psci_acquire_pwr_domain_locks(int start_pwrlvl,
+                              int end_pwrlvl,
+                              pwr_map_node_t *mpidr_nodes[]);
+void psci_release_pwr_domain_locks(int start_pwrlvl,
+                               int end_pwrlvl,
+                               mpidr_pwr_map_nodes_t mpidr_nodes);
+void psci_print_power_domain_map(void);
+uint32_t psci_find_max_phys_off_pwrlvl(uint32_t start_pwrlvl,
+                                      uint32_t end_pwrlvl,
+                                      pwr_map_node_t *mpidr_nodes[]);
 unsigned int psci_is_last_on_cpu(void);
 int psci_spd_migrate_info(uint64_t *mpidr);
 
 /* Private exported functions from psci_setup.c */
-int psci_get_aff_map_nodes(unsigned long mpidr,
-                               int start_afflvl,
-                               int end_afflvl,
-                               aff_map_node_t *mpidr_nodes[]);
-aff_map_node_t *psci_get_aff_map_node(unsigned long, int);
-
-/* Private exported functions from psci_affinity_on.c */
-int psci_afflvl_on(unsigned long target_cpu,
+int psci_get_pwr_map_nodes(unsigned long mpidr,
+                               int start_pwrlvl,
+                               int end_pwrlvl,
+                               pwr_map_node_t *mpidr_nodes[]);
+pwr_map_node_t *psci_get_pwr_map_node(unsigned long, int);
+
+/* Private exported functions from psci_cpu_on.c */
+int psci_cpu_on_start(unsigned long target_cpu,
                   entry_point_info_t *ep,
-                  int end_afflvl);
+                  int end_pwrlvl);
 
-void psci_afflvl_on_finisher(aff_map_node_t *node[], int afflvl);
+void psci_cpu_on_finish(pwr_map_node_t *node[], int pwrlvl);
 
-/* Private exported functions from psci_affinity_off.c */
-int psci_afflvl_off(int end_afflvl);
+/* Private exported functions from psci_cpu_off.c */
+int psci_do_cpu_off(int end_pwrlvl);
 
-/* Private exported functions from psci_affinity_suspend.c */
-void psci_afflvl_suspend(entry_point_info_t *ep,
-                       int end_afflvl);
+/* Private exported functions from psci_cpu_suspend.c */
+void psci_cpu_suspend_start(entry_point_info_t *ep,
+                       int end_pwrlvl);
 
-void psci_afflvl_suspend_finisher(aff_map_node_t *node[], int afflvl);
+void psci_cpu_suspend_finish(pwr_map_node_t *node[], int pwrlvl);
 
 void psci_set_suspend_power_state(unsigned int power_state);
 
 /* Private exported functions from psci_helpers.S */
-void psci_do_pwrdown_cache_maintenance(uint32_t affinity_level);
+void psci_do_pwrdown_cache_maintenance(uint32_t pwr_level);
 void psci_do_pwrup_cache_maintenance(void);
 
 /* Private exported functions from psci_system_off.c */
index a04f8e792ef8010208fbd3eef2433e6aa7f5631e..002e220e6e5b0b9c7340a1feded6de0cd20f85ff 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * 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:
  * 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. Using PSCI_NUM_AFFS will be an
- * overkill.
+ * of relying on platform defined constants. Using PSCI_NUM_PWR_DOMAINS will be
+ * an overkill.
  ******************************************************************************/
 static cpu_context_t psci_ns_context[PLATFORM_CORE_COUNT];
 
 /*******************************************************************************
- * In a system, a certain number of affinity instances are present at an
- * affinity level. The cumulative number of instances across all levels are
- * stored in 'psci_aff_map'. The topology tree has been flattenned into this
- * array. To retrieve nodes, information about the extents of each affinity
- * level i.e. start index and end index needs to be present. 'psci_aff_limits'
- * stores this information.
+ * In a system, a certain number of power domain instances are present at a
+ * power level. The cumulative number of instances across all levels are
+ * stored in 'psci_pwr_domain_map'. The topology tree has been flattenned into
+ * this array. To retrieve nodes, information about the extents of each power
+ * level i.e. start index and end index needs to be present.
+ * 'psci_pwr_lvl_limits' stores this information.
  ******************************************************************************/
-aff_limits_node_t psci_aff_limits[MPIDR_MAX_AFFLVL + 1];
+pwr_lvl_limits_node_t psci_pwr_lvl_limits[MPIDR_MAX_AFFLVL + 1];
 
 /******************************************************************************
  * Define the psci capability variable.
@@ -64,12 +64,12 @@ uint32_t psci_caps;
 
 
 /*******************************************************************************
- * Routines for retrieving the node corresponding to an affinity level instance
+ * Routines for retrieving the node corresponding to a power domain instance
  * in the mpidr. The first one uses binary search to find the node corresponding
- * to the mpidr (key) at a particular affinity level. The second routine decides
- * extents of the binary search at each affinity level.
+ * to the mpidr (key) at a particular power level. The second routine decides
+ * extents of the binary search at each power level.
  ******************************************************************************/
-static int psci_aff_map_get_idx(unsigned long key,
+static int psci_pwr_domain_map_get_idx(unsigned long key,
                                int min_idx,
                                int max_idx)
 {
@@ -85,80 +85,80 @@ static int psci_aff_map_get_idx(unsigned long key,
        /*
         * Make sure we are within array limits.
         */
-       assert(min_idx >= 0 && max_idx < PSCI_NUM_AFFS);
+       assert(min_idx >= 0 && max_idx < PSCI_NUM_PWR_DOMAINS);
 
        /*
         * Bisect the array around 'mid' and then recurse into the array chunk
         * where the key is likely to be found. The mpidrs in each node in the
-        * 'psci_aff_map' for a given affinity level are stored in an ascending
-        * order which makes the binary search possible.
+        * 'psci_pwr_domain_map' for a given power level are stored in an
+        * ascending order which makes the binary search possible.
         */
        mid = min_idx + ((max_idx - min_idx) >> 1);     /* Divide by 2 */
 
-       if (psci_aff_map[mid].mpidr > key)
-               return psci_aff_map_get_idx(key, min_idx, mid - 1);
-       else if (psci_aff_map[mid].mpidr < key)
-               return psci_aff_map_get_idx(key, mid + 1, max_idx);
+       if (psci_pwr_domain_map[mid].mpidr > key)
+               return psci_pwr_domain_map_get_idx(key, min_idx, mid - 1);
+       else if (psci_pwr_domain_map[mid].mpidr < key)
+               return psci_pwr_domain_map_get_idx(key, mid + 1, max_idx);
        else
                return mid;
 }
 
-aff_map_node_t *psci_get_aff_map_node(unsigned long mpidr, int aff_lvl)
+pwr_map_node_t *psci_get_pwr_map_node(unsigned long mpidr, int pwr_lvl)
 {
        int rc;
 
-       if (aff_lvl > PLATFORM_MAX_AFFLVL)
+       if (pwr_lvl > PLAT_MAX_PWR_LVL)
                return NULL;
 
-       /* Right shift the mpidr to the required affinity level */
-       mpidr = mpidr_mask_lower_afflvls(mpidr, aff_lvl);
+       /* Right shift the mpidr to the required power level */
+       mpidr = mpidr_mask_lower_afflvls(mpidr, pwr_lvl);
 
-       rc = psci_aff_map_get_idx(mpidr,
-                                 psci_aff_limits[aff_lvl].min,
-                                 psci_aff_limits[aff_lvl].max);
+       rc = psci_pwr_domain_map_get_idx(mpidr,
+                                 psci_pwr_lvl_limits[pwr_lvl].min,
+                                 psci_pwr_lvl_limits[pwr_lvl].max);
        if (rc >= 0)
-               return &psci_aff_map[rc];
+               return &psci_pwr_domain_map[rc];
        else
                return NULL;
 }
 
 /*******************************************************************************
  * This function populates an array with nodes corresponding to a given range of
- * affinity levels in an mpidr. It returns successfully only when the affinity
- * levels are correct, the mpidr is valid i.e. no affinity level is absent from
- * the topology tree & the affinity instance at level 0 is not absent.
+ * power levels in an mpidr. It returns successfully only when the power
+ * levels are correct, the mpidr is valid i.e. no power level is absent from
+ * the topology tree & the power domain instance at level 0 is not absent.
  ******************************************************************************/
-int psci_get_aff_map_nodes(unsigned long mpidr,
-                          int start_afflvl,
-                          int end_afflvl,
-                          aff_map_node_t *mpidr_nodes[])
+int psci_get_pwr_map_nodes(unsigned long mpidr,
+                          int start_pwrlvl,
+                          int end_pwrlvl,
+                          pwr_map_node_t *mpidr_nodes[])
 {
        int rc = PSCI_E_INVALID_PARAMS, level;
-       aff_map_node_t *node;
+       pwr_map_node_t *node;
 
-       rc = psci_check_afflvl_range(start_afflvl, end_afflvl);
+       rc = psci_check_pwrlvl_range(start_pwrlvl, end_pwrlvl);
        if (rc != PSCI_E_SUCCESS)
                return rc;
 
-       for (level = start_afflvl; level <= end_afflvl; level++) {
+       for (level = start_pwrlvl; level <= end_pwrlvl; level++) {
 
                /*
-                * Grab the node for each affinity level. No affinity level
+                * Grab the node for each power level. No power level
                 * can be missing as that would mean that the topology tree
                 * is corrupted.
                 */
-               node = psci_get_aff_map_node(mpidr, level);
+               node = psci_get_pwr_map_node(mpidr, level);
                if (node == NULL) {
                        rc = PSCI_E_INVALID_PARAMS;
                        break;
                }
 
                /*
-                * Skip absent affinity levels unless it's afffinity level 0.
+                * Skip absent power levels unless it's power level 0.
                 * An absent cpu means that the mpidr is invalid. Save the
-                * pointer to the node for the present affinity level
+                * pointer to the node for the present power level
                 */
-               if (!(node->state & PSCI_AFF_PRESENT)) {
+               if (!(node->state & PSCI_PWR_DOMAIN_PRESENT)) {
                        if (level == MPIDR_AFFLVL0) {
                                rc = PSCI_E_INVALID_PARAMS;
                                break;
@@ -173,39 +173,38 @@ int psci_get_aff_map_nodes(unsigned long mpidr,
 }
 
 /*******************************************************************************
- * Function which initializes the 'aff_map_node' corresponding to an affinity
- * level instance. Each node has a unique mpidr, level and bakery lock. The data
- * field is opaque and holds affinity level specific data e.g. for affinity
- * level 0 it contains the index into arrays that hold the secure/non-secure
- * state for a cpu that's been turned on/off
+ * Function which initializes the 'pwr_map_node' corresponding to a power
+ * domain instance. Each node has a unique mpidr, level and bakery lock.
  ******************************************************************************/
-static void psci_init_aff_map_node(unsigned long mpidr,
+static void psci_init_pwr_map_node(unsigned long mpidr,
                                   int level,
                                   unsigned int idx)
 {
        unsigned char state;
        uint32_t linear_id;
-       psci_aff_map[idx].mpidr = mpidr;
-       psci_aff_map[idx].level = level;
-       psci_lock_init(psci_aff_map, idx);
+       psci_pwr_domain_map[idx].mpidr = mpidr;
+       psci_pwr_domain_map[idx].level = level;
+       psci_lock_init(psci_pwr_domain_map, idx);
 
        /*
-        * If an affinity instance is present then mark it as OFF to begin with.
+        * If an power domain instance is present then mark it as OFF
+        * to begin with.
         */
-       state = plat_get_aff_state(level, mpidr);
-       psci_aff_map[idx].state = state;
+       state = plat_get_pwr_domain_state(level, mpidr);
+       psci_pwr_domain_map[idx].state = state;
 
        if (level == MPIDR_AFFLVL0) {
 
                /*
-                * Mark the cpu as OFF. Higher affinity level reference counts
+                * Mark the cpu as OFF. Higher power level reference counts
                 * have already been memset to 0
                 */
-               if (state & PSCI_AFF_PRESENT)
-                       psci_set_state(&psci_aff_map[idx], PSCI_STATE_OFF);
+               if (state & PSCI_PWR_DOMAIN_PRESENT)
+                       psci_set_state(&psci_pwr_domain_map[idx],
+                                               PSCI_STATE_OFF);
 
                /*
-                * Associate a non-secure context with this affinity
+                * Associate a non-secure context with this power
                 * instance through the context management library.
                 */
                linear_id = platform_get_core_pos(mpidr);
@@ -228,65 +227,68 @@ static void psci_init_aff_map_node(unsigned long mpidr,
 
 /*******************************************************************************
  * Core routine used by the Breadth-First-Search algorithm to populate the
- * affinity tree. Each level in the tree corresponds to an affinity level. This
- * routine's aim is to traverse to the target affinity level and populate nodes
- * in the 'psci_aff_map' for all the siblings at that level. It uses the current
- * affinity level to keep track of how many levels from the root of the tree
- * have been traversed. If the current affinity level != target affinity level,
+ * power domain tree. Each level in the tree corresponds to a power level. This
+ * routine's aim is to traverse to the target power level and populate nodes
+ * in the 'psci_pwr_domain_map' for all the siblings at that level. It uses the
+ * current power level to keep track of how many levels from the root of the
+ * tree have been traversed. If the current power level != target power level,
  * then the platform is asked to return the number of children that each
- * affinity instance has at the current affinity level. Traversal is then done
- * for each child at the next lower level i.e. current affinity level - 1.
+ * power domain instance has at the current power level. Traversal is then done
+ * for each child at the next lower level i.e. current power level - 1.
  *
- * CAUTION: This routine assumes that affinity instance ids are allocated in a
- * monotonically increasing manner at each affinity level in a mpidr starting
+ * CAUTION: This routine assumes that power domain instance ids are allocated
+ * in a monotonically increasing manner at each power level in a mpidr starting
  * from 0. If the platform breaks this assumption then this code will have to
  * be reworked accordingly.
  ******************************************************************************/
-static unsigned int psci_init_aff_map(unsigned long mpidr,
-                                     unsigned int affmap_idx,
-                                     int cur_afflvl,
-                                     int tgt_afflvl)
+static unsigned int psci_init_pwr_map(unsigned long mpidr,
+                                     unsigned int pwrmap_idx,
+                                     int cur_pwrlvl,
+                                     int tgt_pwrlvl)
 {
-       unsigned int ctr, aff_count;
+       unsigned int ctr, pwr_inst_count;
 
-       assert(cur_afflvl >= tgt_afflvl);
+       assert(cur_pwrlvl >= tgt_pwrlvl);
 
        /*
-        * Find the number of siblings at the current affinity level &
+        * Find the number of siblings at the current power level &
         * assert if there are none 'cause then we have been invoked with
         * an invalid mpidr.
         */
-       aff_count = plat_get_aff_count(cur_afflvl, mpidr);
-       assert(aff_count);
-
-       if (tgt_afflvl < cur_afflvl) {
-               for (ctr = 0; ctr < aff_count; ctr++) {
-                       mpidr = mpidr_set_aff_inst(mpidr, ctr, cur_afflvl);
-                       affmap_idx = psci_init_aff_map(mpidr,
-                                                      affmap_idx,
-                                                      cur_afflvl - 1,
-                                                      tgt_afflvl);
+       pwr_inst_count = plat_get_pwr_domain_count(cur_pwrlvl, mpidr);
+       assert(pwr_inst_count);
+
+       if (tgt_pwrlvl < cur_pwrlvl) {
+               for (ctr = 0; ctr < pwr_inst_count; ctr++) {
+                       mpidr = mpidr_set_pwr_domain_inst(mpidr, ctr,
+                                                               cur_pwrlvl);
+                       pwrmap_idx = psci_init_pwr_map(mpidr,
+                                                      pwrmap_idx,
+                                                      cur_pwrlvl - 1,
+                                                      tgt_pwrlvl);
                }
        } else {
-               for (ctr = 0; ctr < aff_count; ctr++, affmap_idx++) {
-                       mpidr = mpidr_set_aff_inst(mpidr, ctr, cur_afflvl);
-                       psci_init_aff_map_node(mpidr, cur_afflvl, affmap_idx);
+               for (ctr = 0; ctr < pwr_inst_count; ctr++, pwrmap_idx++) {
+                       mpidr = mpidr_set_pwr_domain_inst(mpidr, ctr,
+                                                               cur_pwrlvl);
+                       psci_init_pwr_map_node(mpidr, cur_pwrlvl, pwrmap_idx);
                }
 
-               /* affmap_idx is 1 greater than the max index of cur_afflvl */
-               psci_aff_limits[cur_afflvl].max = affmap_idx - 1;
+               /* pwrmap_idx is 1 greater than the max index of cur_pwrlvl */
+               psci_pwr_lvl_limits[cur_pwrlvl].max = pwrmap_idx - 1;
        }
 
-       return affmap_idx;
+       return pwrmap_idx;
 }
 
 /*******************************************************************************
  * This function initializes the topology tree by querying the platform. To do
- * so, it's helper routines implement a Breadth-First-Search. At each affinity
- * level the platform conveys the number of affinity instances that exist i.e.
- * the affinity count. The algorithm populates the psci_aff_map recursively
- * using this information. On a platform that implements two clusters of 4 cpus
- * each, the populated aff_map_array would look like this:
+ * so, it's helper routines implement a Breadth-First-Search. At each power
+ * level the platform conveys the number of power domain instances that exist
+ * i.e. the power instance count. The algorithm populates the
+ * psci_pwr_domain_map* recursively using this information. On a platform that
+ * implements two clusters of 4 cpus each, the populated pwr_map_array would
+ * look like this:
  *
  *            <- cpus cluster0 -><- cpus cluster1 ->
  * ---------------------------------------------------
@@ -298,71 +300,72 @@ static unsigned int psci_init_aff_map(unsigned long mpidr,
  *
  * The first 2 entries are of the cluster nodes. The next 4 entries are of cpus
  * within cluster 0. The last 4 entries are of cpus within cluster 1.
- * The 'psci_aff_limits' array contains the max & min index of each affinity
- * level within the 'psci_aff_map' array. This allows restricting search of a
- * node at an affinity level between the indices in the limits array.
+ * The 'psci_pwr_lvl_limits' array contains the max & min index of each power
+ * level within the 'psci_pwr_domain_map' array. This allows restricting search
+ * of a node at a power level between the indices in the limits array.
  ******************************************************************************/
 int32_t psci_setup(void)
 {
        unsigned long mpidr = read_mpidr();
-       int afflvl, affmap_idx, max_afflvl;
-       aff_map_node_t *node;
+       int pwrlvl, pwrmap_idx, max_pwrlvl;
+       pwr_map_node_t *node;
 
        psci_plat_pm_ops = NULL;
 
-       /* Find out the maximum affinity level that the platform implements */
-       max_afflvl = PLATFORM_MAX_AFFLVL;
-       assert(max_afflvl <= MPIDR_MAX_AFFLVL);
+       /* Find out the maximum power level that the platform implements */
+       max_pwrlvl = PLAT_MAX_PWR_LVL;
+       assert(max_pwrlvl <= MPIDR_MAX_AFFLVL);
 
        /*
         * This call traverses the topology tree with help from the platform and
-        * populates the affinity map using a breadth-first-search recursively.
-        * We assume that the platform allocates affinity instance ids from 0
-        * onwards at each affinity level in the mpidr. FIRST_MPIDR = 0.0.0.0
+        * populates the power map using a breadth-first-search recursively.
+        * We assume that the platform allocates power domain instance ids from
+        * 0 onwards at each power level in the mpidr. FIRST_MPIDR = 0.0.0.0
         */
-       affmap_idx = 0;
-       for (afflvl = max_afflvl; afflvl >= MPIDR_AFFLVL0; afflvl--) {
-               affmap_idx = psci_init_aff_map(FIRST_MPIDR,
-                                              affmap_idx,
-                                              max_afflvl,
-                                              afflvl);
+       pwrmap_idx = 0;
+       for (pwrlvl = max_pwrlvl; pwrlvl >= MPIDR_AFFLVL0; pwrlvl--) {
+               pwrmap_idx = psci_init_pwr_map(FIRST_MPIDR,
+                                              pwrmap_idx,
+                                              max_pwrlvl,
+                                              pwrlvl);
        }
 
 #if !USE_COHERENT_MEM
        /*
-        * The psci_aff_map only needs flushing when it's not allocated in
-        * coherent memory.
+        * The psci_pwr_domain_map only needs flushing when it's not allocated
+        * in coherent memory.
         */
-       flush_dcache_range((uint64_t) &psci_aff_map, sizeof(psci_aff_map));
+       flush_dcache_range((uint64_t) &psci_pwr_domain_map,
+                                       sizeof(psci_pwr_domain_map));
 #endif
 
        /*
-        * Set the bounds for the affinity counts of each level in the map. Also
+        * Set the bounds for number of instances of each level in the map. Also
         * flush out the entire array so that it's visible to subsequent power
-        * management operations. The 'psci_aff_limits' array is allocated in
-        * normal memory. It will be accessed when the mmu is off e.g. after
+        * management operations. The 'psci_pwr_lvl_limits' array is allocated
+        * in normal memory. It will be accessed when the mmu is off e.g. after
         * reset. Hence it needs to be flushed.
         */
-       for (afflvl = MPIDR_AFFLVL0; afflvl < max_afflvl; afflvl++) {
-               psci_aff_limits[afflvl].min =
-                       psci_aff_limits[afflvl + 1].max + 1;
+       for (pwrlvl = MPIDR_AFFLVL0; pwrlvl < max_pwrlvl; pwrlvl++) {
+               psci_pwr_lvl_limits[pwrlvl].min =
+                       psci_pwr_lvl_limits[pwrlvl + 1].max + 1;
        }
 
-       flush_dcache_range((unsigned long) psci_aff_limits,
-                          sizeof(psci_aff_limits));
+       flush_dcache_range((unsigned long) psci_pwr_lvl_limits,
+                          sizeof(psci_pwr_lvl_limits));
 
        /*
-        * Mark the affinity instances in our mpidr as ON. No need to lock as
-        * this is the primary cpu.
+        * Mark the power domain instances in our mpidr as ON. No need to lock
+        * as this is the primary cpu.
         */
        mpidr &= MPIDR_AFFINITY_MASK;
-       for (afflvl = MPIDR_AFFLVL0; afflvl <= max_afflvl; afflvl++) {
+       for (pwrlvl = MPIDR_AFFLVL0; pwrlvl <= max_pwrlvl; pwrlvl++) {
 
-               node = psci_get_aff_map_node(mpidr, afflvl);
+               node = psci_get_pwr_map_node(mpidr, pwrlvl);
                assert(node);
 
                /* Mark each present node as ON. */
-               if (node->state & PSCI_AFF_PRESENT)
+               if (node->state & PSCI_PWR_DOMAIN_PRESENT)
                        psci_set_state(node, PSCI_STATE_ON);
        }
 
@@ -372,12 +375,13 @@ int32_t psci_setup(void)
        /* Initialize the psci capability */
        psci_caps = PSCI_GENERIC_CAP;
 
-       if (psci_plat_pm_ops->affinst_off)
+       if (psci_plat_pm_ops->pwr_domain_off)
                psci_caps |=  define_psci_cap(PSCI_CPU_OFF);
-       if (psci_plat_pm_ops->affinst_on && psci_plat_pm_ops->affinst_on_finish)
+       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->affinst_suspend &&
-                       psci_plat_pm_ops->affinst_suspend_finish) {
+       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);
diff --git a/services/std_svc/psci1.0/psci_suspend.c b/services/std_svc/psci1.0/psci_suspend.c
new file mode 100644 (file)
index 0000000..7832b82
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * 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 saves the power state parameter passed in the current PSCI
+ * cpu_suspend call in the per-cpu data array.
+ ******************************************************************************/
+void psci_set_suspend_power_state(unsigned int power_state)
+{
+       set_cpu_data(psci_svc_cpu_data.power_state, power_state);
+       flush_cpu_data(psci_svc_cpu_data.power_state);
+}
+
+/*******************************************************************************
+ * This function gets the power level till which the current cpu could be
+ * powered down during a cpu_suspend call. Returns PSCI_INVALID_DATA if the
+ * power state is invalid.
+ ******************************************************************************/
+int psci_get_suspend_pwrlvl(void)
+{
+       unsigned int power_state;
+
+       power_state = get_cpu_data(psci_svc_cpu_data.power_state);
+
+       return ((power_state == PSCI_INVALID_DATA) ?
+               power_state : psci_get_pstate_pwrlvl(power_state));
+}
+
+/*******************************************************************************
+ * This function gets the state id of the current cpu from the power state
+ * parameter saved in the per-cpu data array. Returns PSCI_INVALID_DATA if the
+ * power state saved is invalid.
+ ******************************************************************************/
+int psci_get_suspend_stateid(void)
+{
+       unsigned int power_state;
+
+       power_state = get_cpu_data(psci_svc_cpu_data.power_state);
+
+       return ((power_state == PSCI_INVALID_DATA) ?
+               power_state : psci_get_pstate_id(power_state));
+}
+
+/*******************************************************************************
+ * This function gets the state id of the cpu specified by the 'mpidr' parameter
+ * from the power state parameter saved in the per-cpu data array. Returns
+ * PSCI_INVALID_DATA if the power state saved is invalid.
+ ******************************************************************************/
+int psci_get_suspend_stateid_by_mpidr(unsigned long mpidr)
+{
+       unsigned int power_state;
+
+       power_state = get_cpu_data_by_mpidr(mpidr,
+                                           psci_svc_cpu_data.power_state);
+
+       return ((power_state == PSCI_INVALID_DATA) ?
+               power_state : psci_get_pstate_id(power_state));
+}
+
+/*******************************************************************************
+ * 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 finds the highest level where a domain has to be suspended by traversing
+ * the node information and then performs generic, architectural, platform
+ * setup and state management required to suspend that power domain and domains
+ * 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,
+                       int end_pwrlvl)
+{
+       int skip_wfi = 0;
+       mpidr_pwr_map_nodes_t mpidr_nodes;
+       unsigned int max_phys_off_pwrlvl;
+       unsigned long psci_entrypoint;
+
+       /*
+        * 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);
+
+       /*
+        * Collect the pointers to the nodes in the topology tree for
+        * each power domain instance in the mpidr. If this function does
+        * not return successfully then either the mpidr or the power
+        * levels are incorrect. Either way, this an internal TF error
+        * therefore assert.
+        */
+       if (psci_get_pwr_map_nodes(read_mpidr_el1() & MPIDR_AFFINITY_MASK,
+                  MPIDR_AFFLVL0, end_pwrlvl, mpidr_nodes) != PSCI_E_SUCCESS)
+               assert(0);
+
+       /*
+        * 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(MPIDR_AFFLVL0,
+                                 end_pwrlvl,
+                                 mpidr_nodes);
+
+       /*
+        * 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;
+       }
+
+       /*
+        * Call the cpu suspend 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)
+               psci_spd_pm->svc_suspend(0);
+
+       /*
+        * This function updates the state of each power domain instance
+        * corresponding to the mpidr in the range of power levels
+        * specified.
+        */
+       psci_do_state_coordination(MPIDR_AFFLVL0,
+                                 end_pwrlvl,
+                                 mpidr_nodes,
+                                 PSCI_STATE_SUSPEND);
+
+       max_phys_off_pwrlvl = psci_find_max_phys_off_pwrlvl(MPIDR_AFFLVL0,
+                                                           end_pwrlvl,
+                                                           mpidr_nodes);
+       assert(max_phys_off_pwrlvl != PSCI_INVALID_DATA);
+
+       /*
+        * Store the re-entry information for the non-secure world.
+        */
+       cm_init_context(read_mpidr_el1(), ep);
+
+       /* Set the secure world (EL3) re-entry point after BL1 */
+       psci_entrypoint = (unsigned long) psci_cpu_suspend_finish_entry;
+
+       /*
+        * Arch. management. Perform the necessary steps to flush all
+        * cpu caches.
+        */
+       psci_do_pwrdown_cache_maintenance(max_phys_off_pwrlvl);
+
+       /*
+        * Plat. management: Allow the platform to perform the
+        * necessary actions to turn off this cpu e.g. set the
+        * platform defined mailbox with the psci entrypoint,
+        * program the power controller etc.
+        */
+       psci_plat_pm_ops->pwr_domain_suspend(psci_entrypoint,
+                                       max_phys_off_pwrlvl);
+
+exit:
+       /*
+        * Release the locks corresponding to each power level in the
+        * reverse order to which they were acquired.
+        */
+       psci_release_pwr_domain_locks(MPIDR_AFFLVL0,
+                                 end_pwrlvl,
+                                 mpidr_nodes);
+       if (!skip_wfi)
+               psci_power_down_wfi();
+}
+
+/*******************************************************************************
+ * The following functions finish an earlier suspend request. They
+ * are called by the common finisher routine in psci_common.c.
+ ******************************************************************************/
+void psci_cpu_suspend_finish(pwr_map_node_t *node[], int pwrlvl)
+{
+       int32_t suspend_level;
+       uint64_t counter_freq;
+
+       assert(node[pwrlvl]->level == pwrlvl);
+
+       /* Ensure we have been woken up from a suspended state */
+       assert(psci_get_state(node[MPIDR_AFFLVL0]) == PSCI_STATE_SUSPEND);
+
+       /*
+        * 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(pwrlvl);
+
+       /*
+        * 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_freq();
+       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) {
+               suspend_level = psci_get_suspend_pwrlvl();
+               assert (suspend_level != PSCI_INVALID_DATA);
+               psci_spd_pm->svc_suspend_finish(suspend_level);
+       }
+
+       /* Invalidate the suspend context for the node */
+       psci_set_suspend_power_state(PSCI_INVALID_DATA);
+
+       /*
+        * 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);
+
+       /* Clean caches before re-entering normal world */
+       dcsw_op_louis(DCCSW);
+}
+
index 970d4bb50161713fac88dc3b11c4b17ada3a5f25..28315d6b594c4fb171e975be900c83187f011241 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * 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:
@@ -37,7 +37,7 @@
 
 void psci_system_off(void)
 {
-       psci_print_affinity_map();
+       psci_print_power_domain_map();
 
        assert(psci_plat_pm_ops->system_off);
 
@@ -54,7 +54,7 @@ void psci_system_off(void)
 
 void psci_system_reset(void)
 {
-       psci_print_affinity_map();
+       psci_print_power_domain_map();
 
        assert(psci_plat_pm_ops->system_reset);