diff options
author | Alistair Delva <adelva@google.com> | 2021-02-16 21:01:22 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2021-02-16 21:01:22 +0000 |
commit | efb2826bb8160e2d8e0fcec85133a7468484f9fd (patch) | |
tree | 37a21c69306801ee7cdda5167a30896c8740155b /lib/psci/psci_common.c | |
parent | b00a71fc312c9781fa6f404dccfb55b062b2ccac (diff) | |
parent | faa476c0caaa598afa5a6109d17102db5fe35ec6 (diff) | |
download | platform_external_arm-trusted-firmware-master.tar.gz platform_external_arm-trusted-firmware-master.tar.bz2 platform_external_arm-trusted-firmware-master.zip |
Merge branch 'aosp/upstream-master' into HEAD am: faa476c0caHEADandroid-s-beta-5android-s-beta-4android-s-beta-3android-s-beta-2android-s-beta-1mastermain-cg-testing-releaseandroid-s-beta-5android-s-beta-4
Original change: https://android-review.googlesource.com/c/platform/external/arm-trusted-firmware/+/1589611
MUST ONLY BE SUBMITTED BY AUTOMERGER
Change-Id: I3a25534ceed4f8e188510641080d8b8ed49b8f62
Diffstat (limited to 'lib/psci/psci_common.c')
-rw-r--r-- | lib/psci/psci_common.c | 57 |
1 files changed, 53 insertions, 4 deletions
diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c index 5ab15c6ee..9f8a08abb 100644 --- a/lib/psci/psci_common.c +++ b/lib/psci/psci_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -12,6 +12,7 @@ #include <common/bl_common.h> #include <common/debug.h> #include <context.h> +#include <drivers/delay_timer.h> #include <lib/el3_runtime/context_mgmt.h> #include <lib/utils.h> #include <plat/common/platform.h> @@ -601,7 +602,7 @@ void psci_release_pwr_domain_locks(unsigned int end_pwrlvl, unsigned int level; /* Unlock top down. No unlocking required for level 0. */ - for (level = end_pwrlvl; level >= PSCI_CPU_PWR_LVL + 1U; level--) { + for (level = end_pwrlvl; level >= (PSCI_CPU_PWR_LVL + 1U); level--) { parent_idx = parent_nodes[level - 1U]; psci_lock_release(&psci_non_cpu_pd_nodes[parent_idx]); } @@ -662,7 +663,8 @@ static int psci_get_ns_ep_info(entry_point_info_t *ep, mode = ((ns_scr_el3 & SCR_HCE_BIT) != 0U) ? MODE_EL2 : MODE_EL1; - ep->spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + ep->spsr = SPSR_64((uint64_t)mode, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); } else { mode = ((ns_scr_el3 & SCR_HCE_BIT) != 0U) ? @@ -674,7 +676,8 @@ static int psci_get_ns_ep_info(entry_point_info_t *ep, */ daif = DAIF_ABT_BIT | DAIF_IRQ_BIT | DAIF_FIQ_BIT; - ep->spsr = SPSR_MODE32(mode, entrypoint & 0x1, ee, daif); + ep->spsr = SPSR_MODE32((uint64_t)mode, entrypoint & 0x1, ee, + daif); } return PSCI_E_SUCCESS; @@ -973,3 +976,49 @@ void psci_do_pwrdown_sequence(unsigned int power_level) psci_do_pwrdown_cache_maintenance(power_level); #endif } + +/******************************************************************************* + * This function invokes the callback 'stop_func()' with the 'mpidr' of each + * online PE. Caller can pass suitable method to stop a remote core. + * + * 'wait_ms' is the timeout value in milliseconds for the other cores to + * transition to power down state. Passing '0' makes it non-blocking. + * + * The function returns 'PSCI_E_DENIED' if some cores failed to stop within the + * given timeout. + ******************************************************************************/ +int psci_stop_other_cores(unsigned int wait_ms, + void (*stop_func)(u_register_t mpidr)) +{ + unsigned int idx, this_cpu_idx; + + this_cpu_idx = plat_my_core_pos(); + + /* Invoke stop_func for each core */ + for (idx = 0U; idx < psci_plat_core_count; idx++) { + /* skip current CPU */ + if (idx == this_cpu_idx) { + continue; + } + + /* Check if the CPU is ON */ + if (psci_get_aff_info_state_by_idx(idx) == AFF_STATE_ON) { + (*stop_func)(psci_cpu_pd_nodes[idx].mpidr); + } + } + + /* Need to wait for other cores to shutdown */ + if (wait_ms != 0U) { + while ((wait_ms-- != 0U) && (psci_is_last_on_cpu() != 0U)) { + mdelay(1U); + } + + if (psci_is_last_on_cpu() != 0U) { + WARN("Failed to stop all cores!\n"); + psci_print_power_domain_map(); + return PSCI_E_DENIED; + } + } + + return PSCI_E_SUCCESS; +} |