diff options
Diffstat (limited to 'plat/arm')
-rw-r--r-- | plat/arm/css/common/css_common.mk | 20 | ||||
-rw-r--r-- | plat/arm/css/common/css_pm.c | 94 | ||||
-rw-r--r-- | plat/arm/css/common/css_scp_bootloader.c | 4 | ||||
-rw-r--r-- | plat/arm/css/drivers/scp/css_pm_scpi.c | 166 | ||||
-rw-r--r-- | plat/arm/css/drivers/scp/css_scp.h | 43 | ||||
-rw-r--r-- | plat/arm/css/drivers/scpi/css_mhu.c (renamed from plat/arm/css/common/css_mhu.c) | 2 | ||||
-rw-r--r-- | plat/arm/css/drivers/scpi/css_mhu.h (renamed from plat/arm/css/common/css_mhu.h) | 2 | ||||
-rw-r--r-- | plat/arm/css/drivers/scpi/css_scpi.c (renamed from plat/arm/css/common/css_scpi.c) | 17 | ||||
-rw-r--r-- | plat/arm/css/drivers/scpi/css_scpi.h (renamed from plat/arm/css/common/css_scpi.h) | 2 |
9 files changed, 243 insertions, 107 deletions
diff --git a/plat/arm/css/common/css_common.mk b/plat/arm/css/common/css_common.mk index 65e125ea..86ba6df5 100644 --- a/plat/arm/css/common/css_common.mk +++ b/plat/arm/css/common/css_common.mk @@ -41,18 +41,18 @@ PLAT_BL_COMMON_SOURCES += plat/arm/css/common/aarch64/css_helpers.S BL1_SOURCES += plat/arm/css/common/css_bl1_setup.c BL2_SOURCES += plat/arm/css/common/css_bl2_setup.c \ - plat/arm/css/common/css_mhu.c \ - plat/arm/css/common/css_scpi.c + plat/arm/css/drivers/scpi/css_mhu.c \ + plat/arm/css/drivers/scpi/css_scpi.c BL2U_SOURCES += plat/arm/css/common/css_bl2u_setup.c \ - plat/arm/css/common/css_mhu.c \ - plat/arm/css/common/css_scpi.c - -BL31_SOURCES += plat/arm/css/common/css_mhu.c \ - plat/arm/css/common/css_pm.c \ - plat/arm/css/common/css_scpi.c \ - plat/arm/css/common/css_topology.c - + plat/arm/css/drivers/scpi/css_mhu.c \ + plat/arm/css/drivers/scpi/css_scpi.c + +BL31_SOURCES += plat/arm/css/common/css_pm.c \ + plat/arm/css/common/css_topology.c \ + plat/arm/css/drivers/scp/css_pm_scpi.c \ + plat/arm/css/drivers/scpi/css_mhu.c \ + plat/arm/css/drivers/scpi/css_scpi.c ifneq (${RESET_TO_BL31},0) $(error "Using BL31 as the reset vector is not supported on CSS platforms. \ diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c index 7607f617..65d27336 100644 --- a/plat/arm/css/common/css_pm.c +++ b/plat/arm/css/common/css_pm.c @@ -37,13 +37,7 @@ #include <plat_arm.h> #include <platform.h> #include <platform_def.h> -#include "css_scpi.h" - -/* Macros to read the CSS power domain state */ -#define CSS_CORE_PWR_STATE(state) (state)->pwr_domain_state[ARM_PWR_LVL0] -#define CSS_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[ARM_PWR_LVL1] -#define CSS_SYSTEM_PWR_STATE(state) ((PLAT_MAX_PWR_LVL > ARM_PWR_LVL1) ?\ - (state)->pwr_domain_state[ARM_PWR_LVL2] : 0) +#include "../drivers/scp/css_scp.h" /* Allow CSS platforms to override `plat_arm_psci_pm_ops` */ #pragma weak plat_arm_psci_pm_ops @@ -87,12 +81,7 @@ CASSERT(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL1, ******************************************************************************/ int css_pwr_domain_on(u_register_t mpidr) { - /* - * SCP takes care of powering up parent power domains so we - * only need to care about level 0 - */ - scpi_set_css_power_state(mpidr, scpi_power_on, scpi_power_on, - scpi_power_on); + css_scp_on(mpidr); return PSCI_E_SUCCESS; } @@ -140,30 +129,12 @@ void css_pwr_domain_on_finish(const psci_power_state_t *target_state) ******************************************************************************/ static void css_power_down_common(const psci_power_state_t *target_state) { - uint32_t cluster_state = scpi_power_on; - uint32_t system_state = scpi_power_on; - /* Prevent interrupts from spuriously waking up this cpu */ plat_arm_gic_cpuif_disable(); - /* Check if power down at system power domain level is requested */ - if (CSS_SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) - system_state = scpi_power_retention; - /* Cluster is to be turned off, so disable coherency */ - if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) { + if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) plat_arm_interconnect_exit_coherency(); - cluster_state = scpi_power_off; - } - - /* - * Ask the SCP to power down the appropriate components depending upon - * their state. - */ - scpi_set_css_power_state(read_mpidr_el1(), - scpi_power_off, - cluster_state, - system_state); } /******************************************************************************* @@ -174,6 +145,7 @@ void css_pwr_domain_off(const psci_power_state_t *target_state) { assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF); css_power_down_common(target_state); + css_scp_off(target_state); } /******************************************************************************* @@ -191,6 +163,7 @@ void css_pwr_domain_suspend(const psci_power_state_t *target_state) assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF); css_power_down_common(target_state); + css_scp_suspend(target_state); } /******************************************************************************* @@ -222,34 +195,12 @@ void css_pwr_domain_suspend_finish( ******************************************************************************/ void __dead2 css_system_off(void) { - uint32_t response; - - /* Send the power down request to the SCP */ - response = scpi_sys_power_state(scpi_system_shutdown); - - if (response != SCP_OK) { - ERROR("CSS System Off: SCP error %u.\n", response); - panic(); - } - wfi(); - ERROR("CSS System Off: operation not handled.\n"); - panic(); + css_scp_sys_shutdown(); } void __dead2 css_system_reset(void) { - uint32_t response; - - /* Send the system reset request to the SCP */ - response = scpi_sys_power_state(scpi_system_reboot); - - if (response != SCP_OK) { - ERROR("CSS System Reset: SCP error %u.\n", response); - panic(); - } - wfi(); - ERROR("CSS System Reset: operation not handled.\n"); - panic(); + css_scp_sys_reboot(); } /******************************************************************************* @@ -303,36 +254,7 @@ void css_get_sys_suspend_power_state(psci_power_state_t *req_state) ******************************************************************************/ int css_node_hw_state(u_register_t mpidr, unsigned int power_level) { - int rc, element; - unsigned int cpu_state, cluster_state; - - /* - * The format of 'power_level' is implementation-defined, but 0 must - * mean a CPU. We also allow 1 to denote the cluster - */ - if (power_level != ARM_PWR_LVL0 && power_level != ARM_PWR_LVL1) - return PSCI_E_INVALID_PARAMS; - - /* Query SCP */ - rc = scpi_get_css_power_state(mpidr, &cpu_state, &cluster_state); - if (rc != 0) - return PSCI_E_INVALID_PARAMS; - - /* Map power states of CPU and cluster to expected PSCI return codes */ - if (power_level == ARM_PWR_LVL0) { - /* - * The CPU state returned by SCP is an 8-bit bit mask - * corresponding to each CPU in the cluster - */ - element = mpidr & MPIDR_AFFLVL_MASK; - return CSS_CPU_PWR_STATE(cpu_state, element) == - CSS_CPU_PWR_STATE_ON ? HW_ON : HW_OFF; - } else { - assert(cluster_state == CSS_CLUSTER_PWR_STATE_ON || - cluster_state == CSS_CLUSTER_PWR_STATE_OFF); - return cluster_state == CSS_CLUSTER_PWR_STATE_ON ? HW_ON : - HW_OFF; - } + return css_scp_get_power_state(mpidr, power_level); } /******************************************************************************* diff --git a/plat/arm/css/common/css_scp_bootloader.c b/plat/arm/css/common/css_scp_bootloader.c index d3f671e2..049afe4e 100644 --- a/plat/arm/css/common/css_scp_bootloader.c +++ b/plat/arm/css/common/css_scp_bootloader.c @@ -34,9 +34,9 @@ #include <debug.h> #include <platform.h> #include <stdint.h> -#include "css_mhu.h" +#include "../drivers/scpi/css_mhu.h" +#include "../drivers/scpi/css_scpi.h" #include "css_scp_bootloader.h" -#include "css_scpi.h" /* ID of the MHU slot used for the BOM protocol */ #define BOM_MHU_SLOT_ID 0 diff --git a/plat/arm/css/drivers/scp/css_pm_scpi.c b/plat/arm/css/drivers/scp/css_pm_scpi.c new file mode 100644 index 00000000..e22504d1 --- /dev/null +++ b/plat/arm/css/drivers/scp/css_pm_scpi.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <arch_helpers.h> +#include <assert.h> +#include <css_pm.h> +#include <debug.h> +#include "../scpi/css_scpi.h" +#include "css_scp.h" + +/* + * This file implements the SCP power management functions using SCPI protocol. + */ + +/* + * Helper function to inform power down state to SCP. + */ +void css_scp_suspend(const psci_power_state_t *target_state) +{ + uint32_t cluster_state = scpi_power_on; + uint32_t system_state = scpi_power_on; + + /* Check if power down at system power domain level is requested */ + if (CSS_SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) + system_state = scpi_power_retention; + + /* Cluster is to be turned off, so disable coherency */ + if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) + cluster_state = scpi_power_off; + + /* + * Ask the SCP to power down the appropriate components depending upon + * their state. + */ + scpi_set_css_power_state(read_mpidr_el1(), + scpi_power_off, + cluster_state, + system_state); +} + +/* + * Helper function to turn off a CPU power domain and its parent power domains + * if applicable. Since SCPI doesn't differentiate between OFF and suspend, we + * call the suspend helper here. + */ +void css_scp_off(const psci_power_state_t *target_state) +{ + css_scp_suspend(target_state); +} + +/* + * Helper function to turn ON a CPU power domain and its parent power domains + * if applicable. + */ +void css_scp_on(u_register_t mpidr) +{ + /* + * SCP takes care of powering up parent power domains so we + * only need to care about level 0 + */ + scpi_set_css_power_state(mpidr, scpi_power_on, scpi_power_on, + scpi_power_on); +} + +/* + * Helper function to get the power state of a power domain node as reported + * by the SCP. + */ +int css_scp_get_power_state(u_register_t mpidr, unsigned int power_level) +{ + int rc, element; + unsigned int cpu_state, cluster_state; + + /* + * The format of 'power_level' is implementation-defined, but 0 must + * mean a CPU. We also allow 1 to denote the cluster + */ + if (power_level != ARM_PWR_LVL0 && power_level != ARM_PWR_LVL1) + return PSCI_E_INVALID_PARAMS; + + /* Query SCP */ + rc = scpi_get_css_power_state(mpidr, &cpu_state, &cluster_state); + if (rc != 0) + return PSCI_E_INVALID_PARAMS; + + /* Map power states of CPU and cluster to expected PSCI return codes */ + if (power_level == ARM_PWR_LVL0) { + /* + * The CPU state returned by SCP is an 8-bit bit mask + * corresponding to each CPU in the cluster + */ + element = mpidr & MPIDR_AFFLVL_MASK; + return CSS_CPU_PWR_STATE(cpu_state, element) == + CSS_CPU_PWR_STATE_ON ? HW_ON : HW_OFF; + } else { + assert(cluster_state == CSS_CLUSTER_PWR_STATE_ON || + cluster_state == CSS_CLUSTER_PWR_STATE_OFF); + return cluster_state == CSS_CLUSTER_PWR_STATE_ON ? HW_ON : + HW_OFF; + } +} + +/* + * Helper function to shutdown the system via SCPI. + */ +void __dead2 css_scp_sys_shutdown(void) +{ + uint32_t response; + + /* Send the power down request to the SCP */ + response = scpi_sys_power_state(scpi_system_shutdown); + + if (response != SCP_OK) { + ERROR("CSS System Off: SCP error %u.\n", response); + panic(); + } + wfi(); + ERROR("CSS System Off: operation not handled.\n"); + panic(); +} + +/* + * Helper function to reset the system via SCPI. + */ +void __dead2 css_scp_sys_reboot(void) +{ + uint32_t response; + + /* Send the system reset request to the SCP */ + response = scpi_sys_power_state(scpi_system_reboot); + + if (response != SCP_OK) { + ERROR("CSS System Reset: SCP error %u.\n", response); + panic(); + } + wfi(); + ERROR("CSS System Reset: operation not handled.\n"); + panic(); +} diff --git a/plat/arm/css/drivers/scp/css_scp.h b/plat/arm/css/drivers/scp/css_scp.h new file mode 100644 index 00000000..a12798b6 --- /dev/null +++ b/plat/arm/css/drivers/scp/css_scp.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __CSS_SCP_H__ +#define __CSS_SCP_H__ + +#include <psci.h> + +void css_scp_suspend(const psci_power_state_t *target_state); +void css_scp_off(const psci_power_state_t *target_state); +void css_scp_on(u_register_t mpidr); +int css_scp_get_power_state(u_register_t mpidr, unsigned int power_level); +void __dead2 css_scp_sys_shutdown(void); +void __dead2 css_scp_sys_reboot(void); + +#endif /* __CSS_SCP_H__ */ diff --git a/plat/arm/css/common/css_mhu.c b/plat/arm/css/drivers/scpi/css_mhu.c index 265d6c25..302286fc 100644 --- a/plat/arm/css/common/css_mhu.c +++ b/plat/arm/css/drivers/scpi/css_mhu.c @@ -33,8 +33,8 @@ #include <bakery_lock.h> #include <css_def.h> #include <mmio.h> -#include <platform_def.h> #include <plat_arm.h> +#include <platform_def.h> #include "css_mhu.h" /* SCP MHU secure channel registers */ diff --git a/plat/arm/css/common/css_mhu.h b/plat/arm/css/drivers/scpi/css_mhu.h index 2175cdf9..6973a140 100644 --- a/plat/arm/css/common/css_mhu.h +++ b/plat/arm/css/drivers/scpi/css_mhu.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/plat/arm/css/common/css_scpi.c b/plat/arm/css/drivers/scpi/css_scpi.c index 90a8939d..f419abd0 100644 --- a/plat/arm/css/common/css_scpi.c +++ b/plat/arm/css/drivers/scpi/css_scpi.c @@ -63,9 +63,11 @@ static void scpi_secure_message_start(void) static void scpi_secure_message_send(size_t payload_size) { - /* Ensure that any write to the SCPI payload area is seen by SCP before + /* + * Ensure that any write to the SCPI payload area is seen by SCP before * we write to the MHU register. If these 2 writes were reordered by - * the CPU then SCP would read stale payload data */ + * the CPU then SCP would read stale payload data + */ dmbst(); mhu_secure_message_send(SCPI_MHU_SLOT_ID); @@ -86,9 +88,11 @@ static void scpi_secure_message_receive(scpi_cmd_t *cmd) panic(); } - /* Ensure that any read to the SCPI payload area is done after reading + /* + * Ensure that any read to the SCPI payload area is done after reading * the MHU register. If these 2 reads were reordered then the CPU would - * read invalid payload data */ + * read invalid payload data + */ dmbld(); memcpy(cmd, (void *) SCPI_SHARED_MEM_SCP_TO_AP, sizeof(*cmd)); @@ -137,8 +141,9 @@ int scpi_wait_ready(void) return status == SCP_OK ? 0 : -1; } -void scpi_set_css_power_state(unsigned mpidr, scpi_power_state_t cpu_state, - scpi_power_state_t cluster_state, scpi_power_state_t css_state) +void scpi_set_css_power_state(unsigned int mpidr, + scpi_power_state_t cpu_state, scpi_power_state_t cluster_state, + scpi_power_state_t css_state) { scpi_cmd_t *cmd; uint32_t state = 0; diff --git a/plat/arm/css/common/css_scpi.h b/plat/arm/css/drivers/scpi/css_scpi.h index 1fb55e4d..d1e7cba4 100644 --- a/plat/arm/css/common/css_scpi.h +++ b/plat/arm/css/drivers/scpi/css_scpi.h @@ -122,7 +122,7 @@ typedef enum { } scpi_system_state_t; extern int scpi_wait_ready(void); -extern void scpi_set_css_power_state(unsigned mpidr, +extern void scpi_set_css_power_state(unsigned int mpidr, scpi_power_state_t cpu_state, scpi_power_state_t cluster_state, scpi_power_state_t css_state); |