diff options
Diffstat (limited to 'plat/fvp/fvp_pm.c')
-rw-r--r-- | plat/fvp/fvp_pm.c | 370 |
1 files changed, 0 insertions, 370 deletions
diff --git a/plat/fvp/fvp_pm.c b/plat/fvp/fvp_pm.c deleted file mode 100644 index 9044e693..00000000 --- a/plat/fvp/fvp_pm.c +++ /dev/null @@ -1,370 +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_helpers.h> -#include <arm_gic.h> -#include <assert.h> -#include <bakery_lock.h> -#include <cci400.h> -#include <debug.h> -#include <mmio.h> -#include <platform.h> -#include <plat_config.h> -#include <platform_def.h> -#include <psci.h> -#include <errno.h> -#include "drivers/pwrc/fvp_pwrc.h" -#include "fvp_def.h" -#include "fvp_private.h" - -/******************************************************************************* - * Private FVP function to program the mailbox for a cpu before it is released - * from reset. - ******************************************************************************/ -static void fvp_program_mailbox(uint64_t mpidr, uint64_t address) -{ - uint64_t linear_id; - mailbox_t *fvp_mboxes; - - linear_id = platform_get_core_pos(mpidr); - fvp_mboxes = (mailbox_t *)MBOX_BASE; - fvp_mboxes[linear_id].value = address; - flush_dcache_range((unsigned long) &fvp_mboxes[linear_id], - sizeof(unsigned long)); -} - -/******************************************************************************* - * Function which implements the common FVP specific operations to power down a - * cpu in response to a CPU_OFF or CPU_SUSPEND request. - ******************************************************************************/ -static void fvp_cpu_pwrdwn_common() -{ - /* Prevent interrupts from spuriously waking up this cpu */ - arm_gic_cpuif_deactivate(); - - /* Program the power controller to power off this cpu. */ - fvp_pwrc_write_ppoffr(read_mpidr_el1()); -} - -/******************************************************************************* - * Function which implements the common FVP specific operations to power down a - * cluster in response to a CPU_OFF or CPU_SUSPEND request. - ******************************************************************************/ -static void fvp_cluster_pwrdwn_common() -{ - uint64_t mpidr = read_mpidr_el1(); - - /* Disable coherency if this cluster is to be turned off */ - if (get_plat_config()->flags & CONFIG_HAS_CCI) - cci_disable_cluster_coherency(mpidr); - - /* Program the power controller to turn the cluster off */ - fvp_pwrc_write_pcoffr(mpidr); -} - -/******************************************************************************* - * Private FVP function which is used to determine if any platform actions - * should be performed for the specified affinity instance given its - * state. Nothing needs to be done if the 'state' is not off or if this is not - * the highest affinity level which will enter the 'state'. - ******************************************************************************/ -static int32_t fvp_do_plat_actions(unsigned int afflvl, unsigned int state) -{ - unsigned int max_phys_off_afflvl; - - assert(afflvl <= MPIDR_AFFLVL1); - - if (state != PSCI_STATE_OFF) - return -EAGAIN; - - /* - * Find the highest affinity level which will be suspended and postpone - * all the platform specific actions until that level is hit. - */ - max_phys_off_afflvl = psci_get_max_phys_off_afflvl(); - assert(max_phys_off_afflvl != PSCI_INVALID_DATA); - if (afflvl != max_phys_off_afflvl) - return -EAGAIN; - - return 0; -} - -/******************************************************************************* - * FVP handler called when an affinity instance is about to enter standby. - ******************************************************************************/ -void fvp_affinst_standby(unsigned int power_state) -{ - /* - * Enter standby state - * dsb is good practice before using wfi to enter low power states - */ - dsb(); - wfi(); -} - -/******************************************************************************* - * FVP handler called when an affinity instance is about to be turned on. The - * level and mpidr determine the affinity instance. - ******************************************************************************/ -int fvp_affinst_on(unsigned long mpidr, - unsigned long sec_entrypoint, - unsigned int afflvl, - unsigned int state) -{ - int rc = PSCI_E_SUCCESS; - unsigned int psysr; - - /* - * It's possible to turn on only affinity level 0 i.e. a cpu - * on the FVP. Ignore any other affinity level. - */ - if (afflvl != MPIDR_AFFLVL0) - return rc; - - /* - * Ensure that we do not cancel an inflight power off request - * for the target cpu. That would leave it in a zombie wfi. - * Wait for it to power off, program the jump address for the - * target cpu and then program the power controller to turn - * that cpu on - */ - do { - psysr = fvp_pwrc_read_psysr(mpidr); - } while (psysr & PSYSR_AFF_L0); - - fvp_program_mailbox(mpidr, sec_entrypoint); - fvp_pwrc_write_pponr(mpidr); - - return rc; -} - -/******************************************************************************* - * FVP handler called when an affinity instance is about to be turned off. The - * level and mpidr determine the affinity instance. The 'state' arg. allows the - * platform to decide whether the cluster is being turned off and take apt - * actions. - * - * CAUTION: There is no guarantee that caches will remain turned on across calls - * to this function as each affinity level is dealt with. So do not write & read - * global variables across calls. It will be wise to do flush a write to the - * global to prevent unpredictable results. - ******************************************************************************/ -void fvp_affinst_off(unsigned int afflvl, - unsigned int state) -{ - /* Determine if any platform actions need to be executed */ - if (fvp_do_plat_actions(afflvl, state) == -EAGAIN) - return; - - /* - * If execution reaches this stage then this affinity level will be - * suspended. Perform at least the cpu specific actions followed the - * cluster specific operations if applicable. - */ - fvp_cpu_pwrdwn_common(); - - if (afflvl != MPIDR_AFFLVL0) - fvp_cluster_pwrdwn_common(); - -} - -/******************************************************************************* - * FVP handler called when an affinity instance is about to be suspended. The - * level and mpidr determine the affinity instance. The 'state' arg. allows the - * platform to decide whether the cluster is being turned off and take apt - * actions. - * - * CAUTION: There is no guarantee that caches will remain turned on across calls - * to this function as each affinity level is dealt with. So do not write & read - * global variables across calls. It will be wise to do flush a write to the - * global to prevent unpredictable results. - ******************************************************************************/ -void fvp_affinst_suspend(unsigned long sec_entrypoint, - unsigned int afflvl, - unsigned int state) -{ - unsigned long mpidr; - - /* Determine if any platform actions need to be executed. */ - if (fvp_do_plat_actions(afflvl, state) == -EAGAIN) - return; - - /* Get the mpidr for this cpu */ - mpidr = read_mpidr_el1(); - - /* Program the jump address for the this cpu */ - fvp_program_mailbox(mpidr, sec_entrypoint); - - /* Program the power controller to enable wakeup interrupts. */ - fvp_pwrc_set_wen(mpidr); - - /* Perform the common cpu specific operations */ - fvp_cpu_pwrdwn_common(); - - /* Perform the common cluster specific operations */ - if (afflvl != MPIDR_AFFLVL0) - fvp_cluster_pwrdwn_common(); -} - -/******************************************************************************* - * FVP handler called when an affinity instance has just been powered on after - * being turned off earlier. The level and mpidr determine the affinity - * instance. The 'state' arg. allows the platform to decide whether the cluster - * was turned off prior to wakeup and do what's necessary to setup it up - * correctly. - ******************************************************************************/ -void fvp_affinst_on_finish(unsigned int afflvl, - unsigned int state) -{ - unsigned long mpidr; - - /* Determine if any platform actions need to be executed. */ - if (fvp_do_plat_actions(afflvl, state) == -EAGAIN) - return; - - /* Get the mpidr for this cpu */ - mpidr = read_mpidr_el1(); - - /* Perform the common cluster specific operations */ - if (afflvl != MPIDR_AFFLVL0) { - /* - * This CPU might have woken up whilst the cluster was - * attempting to power down. In this case the FVP power - * controller will have a pending cluster power off request - * which needs to be cleared by writing to the PPONR register. - * This prevents the power controller from interpreting a - * subsequent entry of this cpu into a simple wfi as a power - * down request. - */ - fvp_pwrc_write_pponr(mpidr); - - /* Enable coherency if this cluster was off */ - fvp_cci_enable(); - } - - /* - * Clear PWKUPR.WEN bit to ensure interrupts do not interfere - * with a cpu power down unless the bit is set again - */ - fvp_pwrc_clr_wen(mpidr); - - /* Zero the jump address in the mailbox for this cpu */ - fvp_program_mailbox(mpidr, 0); - - /* Enable the gic cpu interface */ - arm_gic_cpuif_setup(); - - /* TODO: This setup is needed only after a cold boot */ - arm_gic_pcpu_distif_setup(); -} - -/******************************************************************************* - * FVP handler called when an affinity instance has just been powered on after - * having been suspended earlier. The level and mpidr determine the affinity - * instance. - * TODO: At the moment we reuse the on finisher and reinitialize the secure - * context. Need to implement a separate suspend finisher. - ******************************************************************************/ -void fvp_affinst_suspend_finish(unsigned int afflvl, - unsigned int state) -{ - fvp_affinst_on_finish(afflvl, state); -} - -/******************************************************************************* - * FVP handlers to shutdown/reboot the system - ******************************************************************************/ -static void __dead2 fvp_system_off(void) -{ - /* Write the System Configuration Control Register */ - mmio_write_32(VE_SYSREGS_BASE + V2M_SYS_CFGCTRL, - CFGCTRL_START | CFGCTRL_RW | CFGCTRL_FUNC(FUNC_SHUTDOWN)); - wfi(); - ERROR("FVP System Off: operation not handled.\n"); - panic(); -} - -static void __dead2 fvp_system_reset(void) -{ - /* Write the System Configuration Control Register */ - mmio_write_32(VE_SYSREGS_BASE + V2M_SYS_CFGCTRL, - CFGCTRL_START | CFGCTRL_RW | CFGCTRL_FUNC(FUNC_REBOOT)); - wfi(); - ERROR("FVP System Reset: operation not handled.\n"); - panic(); -} - -/******************************************************************************* - * FVP handler called to check the validity of the power state parameter. - ******************************************************************************/ -int fvp_validate_power_state(unsigned int power_state) -{ - /* Sanity check the requested state */ - if (psci_get_pstate_type(power_state) == PSTATE_TYPE_STANDBY) { - /* - * It's possible to enter standby only on affinity level 0 - * i.e. a cpu on the fvp. Ignore any other affinity level. - */ - if (psci_get_pstate_afflvl(power_state) != MPIDR_AFFLVL0) - return PSCI_E_INVALID_PARAMS; - } - - /* - * We expect the 'state id' to be zero. - */ - if (psci_get_pstate_id(power_state)) - return PSCI_E_INVALID_PARAMS; - - return PSCI_E_SUCCESS; -} - -/******************************************************************************* - * Export the platform handlers to enable psci to invoke them - ******************************************************************************/ -static const plat_pm_ops_t fvp_plat_pm_ops = { - .affinst_standby = fvp_affinst_standby, - .affinst_on = fvp_affinst_on, - .affinst_off = fvp_affinst_off, - .affinst_suspend = fvp_affinst_suspend, - .affinst_on_finish = fvp_affinst_on_finish, - .affinst_suspend_finish = fvp_affinst_suspend_finish, - .system_off = fvp_system_off, - .system_reset = fvp_system_reset, - .validate_power_state = fvp_validate_power_state -}; - -/******************************************************************************* - * Export the platform specific power ops & initialize the fvp power controller - ******************************************************************************/ -int platform_setup_pm(const plat_pm_ops_t **plat_ops) -{ - *plat_ops = &fvp_plat_pm_ops; - return 0; -} |