diff options
Diffstat (limited to 'services/std_svc/psci/psci_afflvl_off.c')
-rw-r--r-- | services/std_svc/psci/psci_afflvl_off.c | 51 |
1 files changed, 30 insertions, 21 deletions
diff --git a/services/std_svc/psci/psci_afflvl_off.c b/services/std_svc/psci/psci_afflvl_off.c index 7e05789..f0f4234 100644 --- a/services/std_svc/psci/psci_afflvl_off.c +++ b/services/std_svc/psci/psci_afflvl_off.c @@ -62,12 +62,6 @@ static int psci_afflvl0_off(aff_map_node_t *cpu_node) return rc; } - /* - * Arch. management. Perform the necessary steps to flush all - * cpu caches. - */ - psci_do_pwrdown_cache_maintenance(MPIDR_AFFLVL0); - if (!psci_plat_pm_ops->affinst_off) return PSCI_E_SUCCESS; @@ -75,22 +69,25 @@ static int psci_afflvl0_off(aff_map_node_t *cpu_node) * Plat. management: Perform platform specific actions to turn this * cpu off e.g. exit cpu coherency, program the power controller etc. */ - return psci_plat_pm_ops->affinst_off(read_mpidr_el1(), + rc = psci_plat_pm_ops->affinst_off(read_mpidr_el1(), cpu_node->level, psci_get_phys_state(cpu_node)); + /* + * Arch. management. Perform the necessary steps to flush all + * cpu caches. + */ + psci_do_pwrdown_cache_maintenance(MPIDR_AFFLVL0); + + return rc; } static int psci_afflvl1_off(aff_map_node_t *cluster_node) { + int rc; + /* Sanity check the cluster level */ assert(cluster_node->level == MPIDR_AFFLVL1); - /* - * Arch. Management. Flush all levels of caches to PoC if - * the cluster is to be shutdown. - */ - psci_do_pwrdown_cache_maintenance(MPIDR_AFFLVL1); - if (!psci_plat_pm_ops->affinst_off) return PSCI_E_SUCCESS; @@ -99,13 +96,23 @@ static int psci_afflvl1_off(aff_map_node_t *cluster_node) * specific bookeeping e.g. turn off interconnect coherency, * program the power controller etc. */ - return psci_plat_pm_ops->affinst_off(read_mpidr_el1(), + rc = psci_plat_pm_ops->affinst_off(read_mpidr_el1(), cluster_node->level, psci_get_phys_state(cluster_node)); + + /* + * Arch. Management. Flush all levels of caches to PoC if + * the cluster is to be shutdown. + */ + psci_do_pwrdown_cache_maintenance(MPIDR_AFFLVL1); + + return rc; } static int psci_afflvl2_off(aff_map_node_t *system_node) { + int rc; + /* Cannot go beyond this level */ assert(system_node->level == MPIDR_AFFLVL2); @@ -114,12 +121,6 @@ static int psci_afflvl2_off(aff_map_node_t *system_node) * action needs to be taken */ - /* - * Arch. Management. Flush all levels of caches to PoC if - * the system is to be shutdown. - */ - psci_do_pwrdown_cache_maintenance(MPIDR_AFFLVL2); - if (!psci_plat_pm_ops->affinst_off) return PSCI_E_SUCCESS; @@ -127,9 +128,17 @@ static int psci_afflvl2_off(aff_map_node_t *system_node) * Plat. Management : Allow the platform to do its bookeeping * at this affinity level */ - return psci_plat_pm_ops->affinst_off(read_mpidr_el1(), + rc = psci_plat_pm_ops->affinst_off(read_mpidr_el1(), system_node->level, psci_get_phys_state(system_node)); + + /* + * Arch. Management. Flush all levels of caches to PoC if + * the system is to be shutdown. + */ + psci_do_pwrdown_cache_maintenance(MPIDR_AFFLVL2); + + return rc; } static const afflvl_off_handler_t psci_afflvl_off_handlers[] = { |