mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-16 09:34:18 +00:00
psci: utility api to invoke stop for other cores
The API can be used to invoke a 'stop_func' callback for all other cores from any initiating core. Optionally it can also wait for other cores to power down. There may be various use of such API by platform. Ex: Platform may use this to power down all other cores from a crashed core. Signed-off-by: Sandeep Tripathy <sandeep.tripathy@broadcom.com> Change-Id: I4f9dc8a38d419f299c021535d5f1bcc6883106f9
This commit is contained in:
parent
a41ca4c344
commit
2274490945
2 changed files with 49 additions and 0 deletions
|
@ -89,6 +89,8 @@ void psci_warmboot_entrypoint(void);
|
|||
void psci_register_spd_pm_hook(const spd_pm_ops_t *pm);
|
||||
void psci_prepare_next_non_secure_ctx(
|
||||
entry_point_info_t *next_image_info);
|
||||
int psci_stop_other_cores(unsigned int wait_ms,
|
||||
void (*stop_func)(u_register_t mpidr));
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#endif /* PSCI_LIB_H */
|
||||
|
|
|
@ -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>
|
||||
|
@ -973,3 +974,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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue