mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-22 20:38:03 +00:00
Merge changes from topic "idling-during-subsystem-restart" into integration
* changes: fix(xilinx): add console_flush() before shutdown fix(xilinx): fix sending sgi to linux feat(xilinx): add new state to identify cpu power down feat(xilinx): request cpu power down from reset feat(xilinx): power down all cores on receiving cpu pwrdwn req feat(xilinx): add handler for power down req sgi irq feat(xilinx): add wrapper to handle cpu power down req fix(versal-net): use arm common GIC handlers fix(xilinx): rename macros to align with ARM
This commit is contained in:
commit
1064bc6c8c
20 changed files with 238 additions and 229 deletions
|
@ -40,3 +40,16 @@ Xilinx Versal NET platform specific build options
|
||||||
* `TFA_NO_PM` : Platform Management support.
|
* `TFA_NO_PM` : Platform Management support.
|
||||||
- 0 : Enable Platform Management (Default)
|
- 0 : Enable Platform Management (Default)
|
||||||
- 1 : Disable Platform Management
|
- 1 : Disable Platform Management
|
||||||
|
|
||||||
|
* `CPU_PWRDWN_SGI`: Select the SGI for triggering CPU power down request to
|
||||||
|
secondary cores on receiving power down callback from
|
||||||
|
firmware. Options:
|
||||||
|
|
||||||
|
- `0` : SGI 0
|
||||||
|
- `1` : SGI 1
|
||||||
|
- `2` : SGI 2
|
||||||
|
- `3` : SGI 3
|
||||||
|
- `4` : SGI 4
|
||||||
|
- `5` : SGI 5
|
||||||
|
- `6` : SGI 6 (Default)
|
||||||
|
- `7` : SGI 7
|
||||||
|
|
|
@ -56,6 +56,19 @@ Xilinx Versal platform specific build options
|
||||||
- `spp_itr6` : SPP ITR6
|
- `spp_itr6` : SPP ITR6
|
||||||
- `emu_itr6` : EMU ITR6
|
- `emu_itr6` : EMU ITR6
|
||||||
|
|
||||||
|
* `CPU_PWRDWN_SGI`: Select the SGI for triggering CPU power down request to
|
||||||
|
secondary cores on receiving power down callback from
|
||||||
|
firmware. Options:
|
||||||
|
|
||||||
|
- `0` : SGI 0
|
||||||
|
- `1` : SGI 1
|
||||||
|
- `2` : SGI 2
|
||||||
|
- `3` : SGI 3
|
||||||
|
- `4` : SGI 4
|
||||||
|
- `5` : SGI 5
|
||||||
|
- `6` : SGI 6 (Default)
|
||||||
|
- `7` : SGI 7
|
||||||
|
|
||||||
# PLM->TF-A Parameter Passing
|
# PLM->TF-A Parameter Passing
|
||||||
------------------------------
|
------------------------------
|
||||||
The PLM populates a data structure with image information for the TF-A. The TF-A
|
The PLM populates a data structure with image information for the TF-A. The TF-A
|
||||||
|
|
|
@ -14,4 +14,16 @@
|
||||||
(typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \
|
(typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* interrupt handling related constants
|
||||||
|
******************************************************************************/
|
||||||
|
#define ARM_IRQ_SEC_SGI_0 8U
|
||||||
|
#define ARM_IRQ_SEC_SGI_1 9U
|
||||||
|
#define ARM_IRQ_SEC_SGI_2 10U
|
||||||
|
#define ARM_IRQ_SEC_SGI_3 11U
|
||||||
|
#define ARM_IRQ_SEC_SGI_4 12U
|
||||||
|
#define ARM_IRQ_SEC_SGI_5 13U
|
||||||
|
#define ARM_IRQ_SEC_SGI_6 14U
|
||||||
|
#define ARM_IRQ_SEC_SGI_7 15U
|
||||||
|
|
||||||
#endif /* PLAT_COMMON_H */
|
#endif /* PLAT_COMMON_H */
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
/* State arguments of the self suspend */
|
/* State arguments of the self suspend */
|
||||||
#define PM_STATE_CPU_IDLE 0x0U
|
#define PM_STATE_CPU_IDLE 0x0U
|
||||||
|
#define PM_STATE_CPU_OFF 0x1U
|
||||||
#define PM_STATE_SUSPEND_TO_RAM 0xFU
|
#define PM_STATE_SUSPEND_TO_RAM 0xFU
|
||||||
|
|
||||||
#define MAX_LATENCY (~0U)
|
#define MAX_LATENCY (~0U)
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
#include <pm_common.h>
|
#include <pm_common.h>
|
||||||
|
|
||||||
|
extern bool pwrdwn_req_received;
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/**
|
/**
|
||||||
* SECURE_REDUNDANT_CALL() - Adds redundancy to the function call. This is to
|
* SECURE_REDUNDANT_CALL() - Adds redundancy to the function call. This is to
|
||||||
|
@ -30,6 +32,7 @@
|
||||||
status_tmp = function(__VA_ARGS__); \
|
status_tmp = function(__VA_ARGS__); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void request_cpu_pwrdwn(void);
|
||||||
int32_t pm_setup(void);
|
int32_t pm_setup(void);
|
||||||
uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
|
uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
|
||||||
uint64_t x4, const void *cookie, void *handle,
|
uint64_t x4, const void *cookie, void *handle,
|
||||||
|
|
|
@ -50,7 +50,7 @@ void pm_client_set_wakeup_sources(uint32_t node_id)
|
||||||
{
|
{
|
||||||
uint32_t reg_num, device_id;
|
uint32_t reg_num, device_id;
|
||||||
uint8_t pm_wakeup_nodes_set[XPM_NODEIDX_DEV_MAX] = {0U};
|
uint8_t pm_wakeup_nodes_set[XPM_NODEIDX_DEV_MAX] = {0U};
|
||||||
uint32_t isenabler1 = PLAT_GICD_BASE_VALUE + GICD_ISENABLER + 4U;
|
uint32_t isenabler1 = PLAT_ARM_GICD_BASE + GICD_ISENABLER + 4U;
|
||||||
|
|
||||||
zeromem(&pm_wakeup_nodes_set, (u_register_t)sizeof(pm_wakeup_nodes_set));
|
zeromem(&pm_wakeup_nodes_set, (u_register_t)sizeof(pm_wakeup_nodes_set));
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
#include <common/runtime_svc.h>
|
#include <common/runtime_svc.h>
|
||||||
#include <drivers/arm/gicv3.h>
|
#include <drivers/arm/gicv3.h>
|
||||||
|
#include <lib/psci/psci.h>
|
||||||
|
#include <plat/arm/common/plat_arm.h>
|
||||||
#include <plat/common/platform.h>
|
#include <plat/common/platform.h>
|
||||||
|
|
||||||
#include <plat_private.h>
|
#include <plat_private.h>
|
||||||
|
@ -31,21 +33,63 @@
|
||||||
#define INVALID_SGI 0xFFU
|
#define INVALID_SGI 0xFFU
|
||||||
#define PM_INIT_SUSPEND_CB (30U)
|
#define PM_INIT_SUSPEND_CB (30U)
|
||||||
#define PM_NOTIFY_CB (32U)
|
#define PM_NOTIFY_CB (32U)
|
||||||
|
#define EVENT_CPU_PWRDWN (4U)
|
||||||
|
/* 1 sec of wait timeout for secondary core down */
|
||||||
|
#define PWRDWN_WAIT_TIMEOUT (1000U)
|
||||||
DEFINE_RENAME_SYSREG_RW_FUNCS(icc_asgi1r_el1, S3_0_C12_C11_6)
|
DEFINE_RENAME_SYSREG_RW_FUNCS(icc_asgi1r_el1, S3_0_C12_C11_6)
|
||||||
|
|
||||||
/* pm_up = true - UP, pm_up = false - DOWN */
|
/* pm_up = true - UP, pm_up = false - DOWN */
|
||||||
static bool pm_up;
|
static bool pm_up;
|
||||||
static uint32_t sgi = (uint32_t)INVALID_SGI;
|
static uint32_t sgi = (uint32_t)INVALID_SGI;
|
||||||
|
bool pwrdwn_req_received;
|
||||||
|
|
||||||
static void notify_os(void)
|
static void notify_os(void)
|
||||||
{
|
{
|
||||||
int32_t cpu;
|
plat_ic_raise_ns_sgi(sgi, read_mpidr_el1());
|
||||||
uint32_t reg;
|
}
|
||||||
|
|
||||||
cpu = plat_my_core_pos() + 1U;
|
static uint64_t cpu_pwrdwn_req_handler(uint32_t id, uint32_t flags,
|
||||||
|
void *handle, void *cookie)
|
||||||
|
{
|
||||||
|
uint32_t cpu_id = plat_my_core_pos();
|
||||||
|
|
||||||
reg = (cpu | (sgi << XSCUGIC_SGIR_EL1_INITID_SHIFT));
|
VERBOSE("Powering down CPU %d\n", cpu_id);
|
||||||
write_icc_asgi1r_el1(reg);
|
|
||||||
|
/* Deactivate CPU power down SGI */
|
||||||
|
plat_ic_end_of_interrupt(CPU_PWR_DOWN_REQ_INTR);
|
||||||
|
|
||||||
|
return psci_cpu_off();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* raise_pwr_down_interrupt() - Callback function to raise SGI.
|
||||||
|
* @mpidr: MPIDR for the target CPU.
|
||||||
|
*
|
||||||
|
* Raise SGI interrupt to trigger the CPU power down sequence on all the
|
||||||
|
* online secondary cores.
|
||||||
|
*/
|
||||||
|
static void raise_pwr_down_interrupt(u_register_t mpidr)
|
||||||
|
{
|
||||||
|
plat_ic_raise_el3_sgi(CPU_PWR_DOWN_REQ_INTR, mpidr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void request_cpu_pwrdwn(void)
|
||||||
|
{
|
||||||
|
enum pm_ret_status ret;
|
||||||
|
|
||||||
|
VERBOSE("CPU power down request received\n");
|
||||||
|
|
||||||
|
/* Send powerdown request to online secondary core(s) */
|
||||||
|
ret = psci_stop_other_cores(PWRDWN_WAIT_TIMEOUT, raise_pwr_down_interrupt);
|
||||||
|
if (ret != PSCI_E_SUCCESS) {
|
||||||
|
ERROR("Failed to powerdown secondary core(s)\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear IPI IRQ */
|
||||||
|
pm_ipi_irq_clear(primary_proc);
|
||||||
|
|
||||||
|
/* Deactivate IPI IRQ */
|
||||||
|
plat_ic_end_of_interrupt(PLAT_VERSAL_IPI_IRQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t ipi_fiq_handler(uint32_t id, uint32_t flags, void *handle,
|
static uint64_t ipi_fiq_handler(uint32_t id, uint32_t flags, void *handle,
|
||||||
|
@ -56,6 +100,7 @@ static uint64_t ipi_fiq_handler(uint32_t id, uint32_t flags, void *handle,
|
||||||
|
|
||||||
VERBOSE("Received IPI FIQ from firmware\n");
|
VERBOSE("Received IPI FIQ from firmware\n");
|
||||||
|
|
||||||
|
console_flush();
|
||||||
(void)plat_ic_acknowledge_interrupt();
|
(void)plat_ic_acknowledge_interrupt();
|
||||||
|
|
||||||
ret = pm_get_callbackdata(payload, ARRAY_SIZE(payload), 0, 0);
|
ret = pm_get_callbackdata(payload, ARRAY_SIZE(payload), 0, 0);
|
||||||
|
@ -65,8 +110,22 @@ static uint64_t ipi_fiq_handler(uint32_t id, uint32_t flags, void *handle,
|
||||||
|
|
||||||
switch (payload[0]) {
|
switch (payload[0]) {
|
||||||
case PM_INIT_SUSPEND_CB:
|
case PM_INIT_SUSPEND_CB:
|
||||||
|
if (sgi != INVALID_SGI) {
|
||||||
|
notify_os();
|
||||||
|
}
|
||||||
|
break;
|
||||||
case PM_NOTIFY_CB:
|
case PM_NOTIFY_CB:
|
||||||
if (sgi != INVALID_SGI) {
|
if (sgi != INVALID_SGI) {
|
||||||
|
if (payload[2] == EVENT_CPU_PWRDWN) {
|
||||||
|
if (pwrdwn_req_received) {
|
||||||
|
pwrdwn_req_received = false;
|
||||||
|
request_cpu_pwrdwn();
|
||||||
|
(void)psci_cpu_off();
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
pwrdwn_req_received = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
notify_os();
|
notify_os();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -139,6 +198,12 @@ int32_t pm_setup(void)
|
||||||
pm_ipi_init(primary_proc);
|
pm_ipi_init(primary_proc);
|
||||||
pm_up = true;
|
pm_up = true;
|
||||||
|
|
||||||
|
/* register SGI handler for CPU power down request */
|
||||||
|
ret = request_intr_type_el3(CPU_PWR_DOWN_REQ_INTR, cpu_pwrdwn_req_handler);
|
||||||
|
if (ret != 0) {
|
||||||
|
WARN("BL31: registering SGI interrupt failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enable IPI IRQ
|
* Enable IPI IRQ
|
||||||
* assume the rich OS is OK to handle callback IRQs now.
|
* assume the rich OS is OK to handle callback IRQs now.
|
||||||
|
|
|
@ -103,8 +103,8 @@ exit_print_gic_regs:
|
||||||
* ---------------------------------------------
|
* ---------------------------------------------
|
||||||
*/
|
*/
|
||||||
.macro plat_crash_print_regs
|
.macro plat_crash_print_regs
|
||||||
mov_imm x17, PLAT_GICD_BASE_VALUE
|
mov_imm x17, PLAT_ARM_GICD_BASE
|
||||||
mov_imm x16, PLAT_GICR_BASE_VALUE
|
mov_imm x16, PLAT_ARM_GICR_BASE
|
||||||
versal_print_gic_regs
|
versal_print_gic_regs
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#define PLATFORM_DEF_H
|
#define PLATFORM_DEF_H
|
||||||
|
|
||||||
#include <arch.h>
|
#include <arch.h>
|
||||||
|
#include <plat_common.h>
|
||||||
#include "versal_def.h"
|
#include "versal_def.h"
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
@ -112,8 +113,8 @@
|
||||||
#define CACHE_WRITEBACK_SHIFT 6
|
#define CACHE_WRITEBACK_SHIFT 6
|
||||||
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
|
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
|
||||||
|
|
||||||
#define PLAT_GICD_BASE_VALUE U(0xF9000000)
|
#define PLAT_ARM_GICD_BASE U(0xF9000000)
|
||||||
#define PLAT_GICR_BASE_VALUE U(0xF9080000)
|
#define PLAT_ARM_GICR_BASE U(0xF9080000)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
|
* Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
|
||||||
|
@ -131,6 +132,8 @@
|
||||||
#define PLAT_VERSAL_G0_IRQ_PROPS(grp) \
|
#define PLAT_VERSAL_G0_IRQ_PROPS(grp) \
|
||||||
INTR_PROP_DESC(PLAT_VERSAL_IPI_IRQ, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
INTR_PROP_DESC(PLAT_VERSAL_IPI_IRQ, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||||
GIC_INTR_CFG_EDGE), \
|
GIC_INTR_CFG_EDGE), \
|
||||||
|
INTR_PROP_DESC(CPU_PWR_DOWN_REQ_INTR, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||||
|
GIC_INTR_CFG_EDGE)
|
||||||
|
|
||||||
#define IRQ_MAX 142U
|
#define IRQ_MAX 142U
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,13 @@
|
||||||
#include <plat/common/platform.h>
|
#include <plat/common/platform.h>
|
||||||
#include <plat_arm.h>
|
#include <plat_arm.h>
|
||||||
|
|
||||||
|
#include "drivers/delay_timer.h"
|
||||||
#include <plat_private.h>
|
#include <plat_private.h>
|
||||||
#include "pm_api_sys.h"
|
#include "pm_api_sys.h"
|
||||||
#include "pm_client.h"
|
#include "pm_client.h"
|
||||||
#include <pm_common.h>
|
#include <pm_common.h>
|
||||||
|
#include "pm_ipi.h"
|
||||||
|
#include "pm_svc_main.h"
|
||||||
|
|
||||||
static uintptr_t versal_sec_entry;
|
static uintptr_t versal_sec_entry;
|
||||||
|
|
||||||
|
@ -145,10 +148,32 @@ static void __dead2 versal_system_off(void)
|
||||||
*/
|
*/
|
||||||
static void __dead2 versal_system_reset(void)
|
static void __dead2 versal_system_reset(void)
|
||||||
{
|
{
|
||||||
/* Send the system reset request to the PMC */
|
uint32_t ret, timeout = 10000U;
|
||||||
|
|
||||||
|
request_cpu_pwrdwn();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send the system reset request to the firmware if power down request
|
||||||
|
* is not received from firmware.
|
||||||
|
*/
|
||||||
|
if (!pwrdwn_req_received) {
|
||||||
(void)pm_system_shutdown(XPM_SHUTDOWN_TYPE_RESET,
|
(void)pm_system_shutdown(XPM_SHUTDOWN_TYPE_RESET,
|
||||||
pm_get_shutdown_scope(), SECURE_FLAG);
|
pm_get_shutdown_scope(), SECURE_FLAG);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for system shutdown request completed and idle callback
|
||||||
|
* not received.
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
ret = ipi_mb_enquire_status(primary_proc->ipi->local_ipi_id,
|
||||||
|
primary_proc->ipi->remote_ipi_id);
|
||||||
|
udelay(100);
|
||||||
|
timeout--;
|
||||||
|
} while ((ret != IPI_MB_STATUS_RECV_PENDING) && (timeout > 0U));
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)psci_cpu_off();
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
wfi();
|
wfi();
|
||||||
}
|
}
|
||||||
|
@ -161,6 +186,7 @@ static void __dead2 versal_system_reset(void)
|
||||||
*/
|
*/
|
||||||
static void versal_pwr_domain_off(const psci_power_state_t *target_state)
|
static void versal_pwr_domain_off(const psci_power_state_t *target_state)
|
||||||
{
|
{
|
||||||
|
uint32_t ret, fw_api_version, version[PAYLOAD_ARG_CNT] = {0U};
|
||||||
uint32_t cpu_id = plat_my_core_pos();
|
uint32_t cpu_id = plat_my_core_pos();
|
||||||
const struct pm_proc *proc = pm_get_proc(cpu_id);
|
const struct pm_proc *proc = pm_get_proc(cpu_id);
|
||||||
|
|
||||||
|
@ -180,8 +206,17 @@ static void versal_pwr_domain_off(const psci_power_state_t *target_state)
|
||||||
* invoking CPU_on function, during which resume address will
|
* invoking CPU_on function, during which resume address will
|
||||||
* be set.
|
* be set.
|
||||||
*/
|
*/
|
||||||
|
ret = pm_feature_check((uint32_t)PM_SELF_SUSPEND, &version[0], SECURE_FLAG);
|
||||||
|
if (ret == PM_RET_SUCCESS) {
|
||||||
|
fw_api_version = version[0] & 0xFFFFU;
|
||||||
|
if (fw_api_version >= 3U) {
|
||||||
|
(void)pm_self_suspend(proc->node_id, MAX_LATENCY, PM_STATE_CPU_OFF, 0,
|
||||||
|
SECURE_FLAG);
|
||||||
|
} else {
|
||||||
(void)pm_self_suspend(proc->node_id, MAX_LATENCY, PM_STATE_CPU_IDLE, 0,
|
(void)pm_self_suspend(proc->node_id, MAX_LATENCY, PM_STATE_CPU_IDLE, 0,
|
||||||
SECURE_FLAG);
|
SECURE_FLAG);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -11,6 +11,8 @@ override RESET_TO_BL31 := 1
|
||||||
PL011_GENERIC_UART := 1
|
PL011_GENERIC_UART := 1
|
||||||
IPI_CRC_CHECK := 0
|
IPI_CRC_CHECK := 0
|
||||||
HARDEN_SLS_ALL := 0
|
HARDEN_SLS_ALL := 0
|
||||||
|
CPU_PWRDWN_SGI ?= 6
|
||||||
|
$(eval $(call add_define_val,CPU_PWR_DOWN_REQ_INTR,ARM_IRQ_SEC_SGI_${CPU_PWRDWN_SGI}))
|
||||||
|
|
||||||
# A72 Erratum for SoC
|
# A72 Erratum for SoC
|
||||||
ERRATA_A72_859971 := 1
|
ERRATA_A72_859971 := 1
|
||||||
|
|
|
@ -62,8 +62,8 @@ static uint32_t versal_gicv3_mpidr_hash(u_register_t mpidr)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const gicv3_driver_data_t versal_gic_data __unused = {
|
static const gicv3_driver_data_t versal_gic_data __unused = {
|
||||||
.gicd_base = PLAT_GICD_BASE_VALUE,
|
.gicd_base = PLAT_ARM_GICD_BASE,
|
||||||
.gicr_base = PLAT_GICR_BASE_VALUE,
|
.gicr_base = PLAT_ARM_GICR_BASE,
|
||||||
.interrupt_props = versal_interrupt_props,
|
.interrupt_props = versal_interrupt_props,
|
||||||
.interrupt_props_num = ARRAY_SIZE(versal_interrupt_props),
|
.interrupt_props_num = ARRAY_SIZE(versal_interrupt_props),
|
||||||
.rdistif_num = PLATFORM_CORE_COUNT,
|
.rdistif_num = PLATFORM_CORE_COUNT,
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include <platform_def.h>
|
#include <platform_def.h>
|
||||||
|
|
||||||
|
.globl plat_arm_calc_core_pos
|
||||||
.globl plat_secondary_cold_boot_setup
|
.globl plat_secondary_cold_boot_setup
|
||||||
.globl plat_is_my_cpu_primary
|
.globl plat_is_my_cpu_primary
|
||||||
.globl platform_mem_init
|
.globl platform_mem_init
|
||||||
|
@ -58,6 +59,16 @@ func plat_my_core_pos
|
||||||
b plat_core_pos_by_mpidr
|
b plat_core_pos_by_mpidr
|
||||||
endfunc plat_my_core_pos
|
endfunc plat_my_core_pos
|
||||||
|
|
||||||
|
/* -----------------------------------------------------
|
||||||
|
* unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
|
||||||
|
* This function uses the plat_core_pos_by_mpidr()
|
||||||
|
* definition to get the index of the calling CPU.
|
||||||
|
* -----------------------------------------------------
|
||||||
|
*/
|
||||||
|
func plat_arm_calc_core_pos
|
||||||
|
b plat_core_pos_by_mpidr
|
||||||
|
endfunc plat_arm_calc_core_pos
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------
|
/* ---------------------------------------------------------------------
|
||||||
* We don't need to carry out any memory initialization on Versal NET
|
* We don't need to carry out any memory initialization on Versal NET
|
||||||
* platform. The Secure RAM is accessible straight away.
|
* platform. The Secure RAM is accessible straight away.
|
||||||
|
|
|
@ -216,8 +216,8 @@ void bl31_platform_setup(void)
|
||||||
prepare_dtb();
|
prepare_dtb();
|
||||||
|
|
||||||
/* Initialize the gic cpu and distributor interfaces */
|
/* Initialize the gic cpu and distributor interfaces */
|
||||||
plat_versal_net_gic_driver_init();
|
plat_arm_gic_driver_init();
|
||||||
plat_versal_net_gic_init();
|
plat_arm_gic_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void bl31_plat_runtime_setup(void)
|
void bl31_plat_runtime_setup(void)
|
||||||
|
|
|
@ -109,8 +109,8 @@ exit_print_gic_regs:
|
||||||
* Uncomment it when versions are stable
|
* Uncomment it when versions are stable
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
mov_imm x17, PLAT_GICD_BASE_VALUE
|
mov_imm x17, PLAT_ARM_GICD_BASE
|
||||||
mov_imm x16, PLAT_GICR_BASE_VALUE
|
mov_imm x16, PLAT_ARM_GICR_BASE
|
||||||
versal_net_print_gic_regs
|
versal_net_print_gic_regs
|
||||||
*/
|
*/
|
||||||
.endm
|
.endm
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#define PLATFORM_DEF_H
|
#define PLATFORM_DEF_H
|
||||||
|
|
||||||
#include <arch.h>
|
#include <arch.h>
|
||||||
|
#include <plat_common.h>
|
||||||
#include "versal_net_def.h"
|
#include "versal_net_def.h"
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
@ -107,8 +108,8 @@
|
||||||
#define CACHE_WRITEBACK_SHIFT U(6)
|
#define CACHE_WRITEBACK_SHIFT U(6)
|
||||||
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
|
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
|
||||||
|
|
||||||
#define PLAT_GICD_BASE_VALUE U(0xE2000000)
|
#define PLAT_ARM_GICD_BASE U(0xE2000000)
|
||||||
#define PLAT_GICR_BASE_VALUE U(0xE2060000)
|
#define PLAT_ARM_GICR_BASE U(0xE2060000)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
|
* Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
|
||||||
|
@ -118,13 +119,15 @@
|
||||||
#define PLAT_VERSAL_NET_IPI_IRQ 89
|
#define PLAT_VERSAL_NET_IPI_IRQ 89
|
||||||
#define PLAT_VERSAL_IPI_IRQ PLAT_VERSAL_NET_IPI_IRQ
|
#define PLAT_VERSAL_IPI_IRQ PLAT_VERSAL_NET_IPI_IRQ
|
||||||
|
|
||||||
#define PLAT_VERSAL_NET_G1S_IRQ_PROPS(grp) \
|
#define PLAT_ARM_G1S_IRQ_PROPS(grp) \
|
||||||
INTR_PROP_DESC(VERSAL_NET_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
INTR_PROP_DESC(VERSAL_NET_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||||
GIC_INTR_CFG_LEVEL)
|
GIC_INTR_CFG_LEVEL)
|
||||||
|
|
||||||
#define PLAT_VERSAL_NET_G0_IRQ_PROPS(grp) \
|
#define PLAT_ARM_G0_IRQ_PROPS(grp) \
|
||||||
INTR_PROP_DESC(PLAT_VERSAL_IPI_IRQ, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
INTR_PROP_DESC(PLAT_VERSAL_IPI_IRQ, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||||
GIC_INTR_CFG_EDGE), \
|
GIC_INTR_CFG_EDGE), \
|
||||||
|
INTR_PROP_DESC(CPU_PWR_DOWN_REQ_INTR, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||||
|
GIC_INTR_CFG_EDGE)
|
||||||
|
|
||||||
#define IRQ_MAX 200U
|
#define IRQ_MAX 200U
|
||||||
|
|
||||||
|
|
|
@ -108,8 +108,8 @@ static void zynqmp_pwr_domain_suspend(const psci_power_state_t *target_state)
|
||||||
|
|
||||||
static void zynqmp_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
static void zynqmp_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
||||||
{
|
{
|
||||||
plat_versal_net_gic_pcpu_init();
|
plat_arm_gic_pcpu_init();
|
||||||
plat_versal_net_gic_cpuif_enable();
|
plat_arm_gic_cpuif_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void zynqmp_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
|
static void zynqmp_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
|
||||||
|
|
|
@ -14,10 +14,12 @@
|
||||||
#include <plat/common/platform.h>
|
#include <plat/common/platform.h>
|
||||||
#include <plat_arm.h>
|
#include <plat_arm.h>
|
||||||
|
|
||||||
|
#include <drivers/delay_timer.h>
|
||||||
#include <plat_private.h>
|
#include <plat_private.h>
|
||||||
#include "pm_api_sys.h"
|
#include "pm_api_sys.h"
|
||||||
#include "pm_client.h"
|
#include "pm_client.h"
|
||||||
#include <pm_common.h>
|
#include <pm_common.h>
|
||||||
|
#include "pm_ipi.h"
|
||||||
#include "pm_svc_main.h"
|
#include "pm_svc_main.h"
|
||||||
#include "versal_net_def.h"
|
#include "versal_net_def.h"
|
||||||
|
|
||||||
|
@ -57,6 +59,7 @@ static int32_t versal_net_pwr_domain_on(u_register_t mpidr)
|
||||||
*/
|
*/
|
||||||
static void versal_net_pwr_domain_off(const psci_power_state_t *target_state)
|
static void versal_net_pwr_domain_off(const psci_power_state_t *target_state)
|
||||||
{
|
{
|
||||||
|
uint32_t ret, fw_api_version, version[PAYLOAD_ARG_CNT] = {0U};
|
||||||
uint32_t cpu_id = plat_my_core_pos();
|
uint32_t cpu_id = plat_my_core_pos();
|
||||||
const struct pm_proc *proc = pm_get_proc(cpu_id);
|
const struct pm_proc *proc = pm_get_proc(cpu_id);
|
||||||
|
|
||||||
|
@ -66,7 +69,7 @@ static void versal_net_pwr_domain_off(const psci_power_state_t *target_state)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prevent interrupts from spuriously waking up this cpu */
|
/* Prevent interrupts from spuriously waking up this cpu */
|
||||||
plat_versal_net_gic_cpuif_disable();
|
plat_arm_gic_cpuif_disable();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send request to PMC to power down the appropriate APU CPU
|
* Send request to PMC to power down the appropriate APU CPU
|
||||||
|
@ -76,8 +79,17 @@ static void versal_net_pwr_domain_off(const psci_power_state_t *target_state)
|
||||||
* invoking CPU_on function, during which resume address will
|
* invoking CPU_on function, during which resume address will
|
||||||
* be set.
|
* be set.
|
||||||
*/
|
*/
|
||||||
pm_self_suspend(proc->node_id, MAX_LATENCY, PM_STATE_CPU_IDLE, 0,
|
ret = pm_feature_check((uint32_t)PM_SELF_SUSPEND, &version[0], SECURE_FLAG);
|
||||||
|
if (ret == PM_RET_SUCCESS) {
|
||||||
|
fw_api_version = version[0] & 0xFFFFU;
|
||||||
|
if (fw_api_version >= 3U) {
|
||||||
|
(void)pm_self_suspend(proc->node_id, MAX_LATENCY, PM_STATE_CPU_OFF, 0,
|
||||||
SECURE_FLAG);
|
SECURE_FLAG);
|
||||||
|
} else {
|
||||||
|
(void)pm_self_suspend(proc->node_id, MAX_LATENCY, PM_STATE_CPU_IDLE, 0,
|
||||||
|
SECURE_FLAG);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,10 +100,32 @@ static void versal_net_pwr_domain_off(const psci_power_state_t *target_state)
|
||||||
*/
|
*/
|
||||||
static void __dead2 versal_net_system_reset(void)
|
static void __dead2 versal_net_system_reset(void)
|
||||||
{
|
{
|
||||||
/* Send the system reset request to the PMC */
|
uint32_t ret, timeout = 10000U;
|
||||||
pm_system_shutdown(XPM_SHUTDOWN_TYPE_RESET,
|
|
||||||
|
request_cpu_pwrdwn();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send the system reset request to the firmware if power down request
|
||||||
|
* is not received from firmware.
|
||||||
|
*/
|
||||||
|
if (!pwrdwn_req_received) {
|
||||||
|
(void)pm_system_shutdown(XPM_SHUTDOWN_TYPE_RESET,
|
||||||
pm_get_shutdown_scope(), SECURE_FLAG);
|
pm_get_shutdown_scope(), SECURE_FLAG);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for system shutdown request completed and idle callback
|
||||||
|
* not received.
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
ret = ipi_mb_enquire_status(primary_proc->ipi->local_ipi_id,
|
||||||
|
primary_proc->ipi->remote_ipi_id);
|
||||||
|
udelay(100);
|
||||||
|
timeout--;
|
||||||
|
} while ((ret != IPI_MB_STATUS_RECV_PENDING) && (timeout > 0U));
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)psci_cpu_off();
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
wfi();
|
wfi();
|
||||||
}
|
}
|
||||||
|
@ -114,10 +148,10 @@ static void versal_net_pwr_domain_suspend(const psci_power_state_t *target_state
|
||||||
__func__, i, target_state->pwr_domain_state[i]);
|
__func__, i, target_state->pwr_domain_state[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
plat_versal_net_gic_cpuif_disable();
|
plat_arm_gic_cpuif_disable();
|
||||||
|
|
||||||
if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
|
if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
|
||||||
plat_versal_net_gic_save();
|
plat_arm_gic_save();
|
||||||
}
|
}
|
||||||
|
|
||||||
state = target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE ?
|
state = target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE ?
|
||||||
|
@ -135,10 +169,10 @@ static void versal_net_pwr_domain_on_finish(const psci_power_state_t *target_sta
|
||||||
(void)target_state;
|
(void)target_state;
|
||||||
|
|
||||||
/* Enable the gic cpu interface */
|
/* Enable the gic cpu interface */
|
||||||
plat_versal_net_gic_pcpu_init();
|
plat_arm_gic_pcpu_init();
|
||||||
|
|
||||||
/* Program the gic per-cpu distributor or re-distributor interface */
|
/* Program the gic per-cpu distributor or re-distributor interface */
|
||||||
plat_versal_net_gic_cpuif_enable();
|
plat_arm_gic_cpuif_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -163,10 +197,10 @@ static void versal_net_pwr_domain_suspend_finish(const psci_power_state_t *targe
|
||||||
|
|
||||||
/* APU was turned off, so restore GIC context */
|
/* APU was turned off, so restore GIC context */
|
||||||
if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
|
if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
|
||||||
plat_versal_net_gic_resume();
|
plat_arm_gic_resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
plat_versal_net_gic_cpuif_enable();
|
plat_arm_gic_cpuif_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,6 +21,8 @@ IPI_CRC_CHECK := 0
|
||||||
GIC_ENABLE_V4_EXTN := 0
|
GIC_ENABLE_V4_EXTN := 0
|
||||||
GICV3_SUPPORT_GIC600 := 1
|
GICV3_SUPPORT_GIC600 := 1
|
||||||
TFA_NO_PM := 0
|
TFA_NO_PM := 0
|
||||||
|
CPU_PWRDWN_SGI ?= 6
|
||||||
|
$(eval $(call add_define_val,CPU_PWR_DOWN_REQ_INTR,ARM_IRQ_SEC_SGI_${CPU_PWRDWN_SGI}))
|
||||||
|
|
||||||
override CTX_INCLUDE_AARCH32_REGS := 0
|
override CTX_INCLUDE_AARCH32_REGS := 0
|
||||||
|
|
||||||
|
@ -121,6 +123,7 @@ BL31_SOURCES += plat/xilinx/common/plat_fdt.c \
|
||||||
${PLAT_PATH}/bl31_versal_net_setup.c \
|
${PLAT_PATH}/bl31_versal_net_setup.c \
|
||||||
common/fdt_fixup.c \
|
common/fdt_fixup.c \
|
||||||
common/fdt_wrappers.c \
|
common/fdt_wrappers.c \
|
||||||
|
plat/arm/common/arm_gicv3.c \
|
||||||
${LIBFDT_SRCS} \
|
${LIBFDT_SRCS} \
|
||||||
${PLAT_PATH}/sip_svc_setup.c \
|
${PLAT_PATH}/sip_svc_setup.c \
|
||||||
${PLAT_PATH}/versal_net_gicv3.c
|
${XLAT_TABLES_LIB_SRCS}
|
||||||
|
|
|
@ -1,189 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.
|
|
||||||
* Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
|
|
||||||
* Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <common/debug.h>
|
|
||||||
#include <common/interrupt_props.h>
|
|
||||||
#include <drivers/arm/gicv3.h>
|
|
||||||
#include <lib/utils.h>
|
|
||||||
#include <plat/common/platform.h>
|
|
||||||
|
|
||||||
#include <plat_private.h>
|
|
||||||
#include <platform_def.h>
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* The following functions are defined as weak to allow a platform to override
|
|
||||||
* the way the GICv3 driver is initialised and used.
|
|
||||||
*****************************************************************************/
|
|
||||||
#pragma weak plat_versal_net_gic_driver_init
|
|
||||||
#pragma weak plat_versal_net_gic_init
|
|
||||||
#pragma weak plat_versal_net_gic_cpuif_enable
|
|
||||||
#pragma weak plat_versal_net_gic_cpuif_disable
|
|
||||||
#pragma weak plat_versal_net_gic_pcpu_init
|
|
||||||
#pragma weak plat_versal_net_gic_redistif_on
|
|
||||||
#pragma weak plat_versal_net_gic_redistif_off
|
|
||||||
|
|
||||||
/* The GICv3 driver only needs to be initialized in EL3 */
|
|
||||||
static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
|
|
||||||
|
|
||||||
static const interrupt_prop_t versal_net_interrupt_props[] = {
|
|
||||||
PLAT_VERSAL_NET_G1S_IRQ_PROPS(INTR_GROUP1S),
|
|
||||||
PLAT_VERSAL_NET_G0_IRQ_PROPS(INTR_GROUP0)
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We save and restore the GICv3 context on system suspend. Allocate the
|
|
||||||
* data in the designated EL3 Secure carve-out memory.
|
|
||||||
*/
|
|
||||||
static gicv3_redist_ctx_t rdist_ctx __section(".versal_net_el3_tzc_dram");
|
|
||||||
static gicv3_dist_ctx_t dist_ctx __section(".versal_net_el3_tzc_dram");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
|
|
||||||
* to core position.
|
|
||||||
*
|
|
||||||
* Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity
|
|
||||||
* values read from GICR_TYPER don't have an MT field. To reuse the same
|
|
||||||
* translation used for CPUs, we insert MT bit read from the PE's MPIDR into
|
|
||||||
* that read from GICR_TYPER.
|
|
||||||
*
|
|
||||||
* Assumptions:
|
|
||||||
*
|
|
||||||
* - All CPUs implemented in the system have MPIDR_EL1.MT bit set;
|
|
||||||
* - No CPUs implemented in the system use affinity level 3.
|
|
||||||
*/
|
|
||||||
static uint32_t versal_net_gicv3_mpidr_hash(u_register_t mpidr)
|
|
||||||
{
|
|
||||||
mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
|
|
||||||
return plat_core_pos_by_mpidr(mpidr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const gicv3_driver_data_t versal_net_gic_data __unused = {
|
|
||||||
.gicd_base = PLAT_GICD_BASE_VALUE,
|
|
||||||
.gicr_base = PLAT_GICR_BASE_VALUE,
|
|
||||||
.interrupt_props = versal_net_interrupt_props,
|
|
||||||
.interrupt_props_num = ARRAY_SIZE(versal_net_interrupt_props),
|
|
||||||
.rdistif_num = PLATFORM_CORE_COUNT,
|
|
||||||
.rdistif_base_addrs = rdistif_base_addrs,
|
|
||||||
.mpidr_to_core_pos = versal_net_gicv3_mpidr_hash
|
|
||||||
};
|
|
||||||
|
|
||||||
void __init plat_versal_net_gic_driver_init(void)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* The GICv3 driver is initialized in EL3 and does not need
|
|
||||||
* to be initialized again in SEL1. This is because the S-EL1
|
|
||||||
* can use GIC system registers to manage interrupts and does
|
|
||||||
* not need GIC interface base addresses to be configured.
|
|
||||||
*/
|
|
||||||
#if IMAGE_BL31
|
|
||||||
gicv3_driver_init(&versal_net_gic_data);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Versal NET common helper to initialize the GIC. Only invoked by BL31
|
|
||||||
*****************************************************************************/
|
|
||||||
void __init plat_versal_net_gic_init(void)
|
|
||||||
{
|
|
||||||
gicv3_distif_init();
|
|
||||||
gicv3_rdistif_init(plat_my_core_pos());
|
|
||||||
gicv3_cpuif_enable(plat_my_core_pos());
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Versal NET common helper to enable the GIC CPU interface
|
|
||||||
*****************************************************************************/
|
|
||||||
void plat_versal_net_gic_cpuif_enable(void)
|
|
||||||
{
|
|
||||||
gicv3_cpuif_enable(plat_my_core_pos());
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Versal NET common helper to disable the GIC CPU interface
|
|
||||||
*****************************************************************************/
|
|
||||||
void plat_versal_net_gic_cpuif_disable(void)
|
|
||||||
{
|
|
||||||
gicv3_cpuif_disable(plat_my_core_pos());
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Versal NET common helper to initialize the per-cpu redistributor interface in
|
|
||||||
* GICv3
|
|
||||||
*****************************************************************************/
|
|
||||||
void plat_versal_net_gic_pcpu_init(void)
|
|
||||||
{
|
|
||||||
gicv3_rdistif_init(plat_my_core_pos());
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Versal NET common helpers to power GIC redistributor interface
|
|
||||||
*****************************************************************************/
|
|
||||||
void plat_versal_net_gic_redistif_on(void)
|
|
||||||
{
|
|
||||||
gicv3_rdistif_on(plat_my_core_pos());
|
|
||||||
}
|
|
||||||
|
|
||||||
void plat_versal_net_gic_redistif_off(void)
|
|
||||||
{
|
|
||||||
gicv3_rdistif_off(plat_my_core_pos());
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Versal NET common helper to save & restore the GICv3 on resume from system
|
|
||||||
* suspend
|
|
||||||
*****************************************************************************/
|
|
||||||
void plat_versal_net_gic_save(void)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* If an ITS is available, save its context before
|
|
||||||
* the Redistributor using:
|
|
||||||
* gicv3_its_save_disable(gits_base, &its_ctx[i])
|
|
||||||
* Additionnaly, an implementation-defined sequence may
|
|
||||||
* be required to save the whole ITS state.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Save the GIC Redistributors and ITS contexts before the
|
|
||||||
* Distributor context. As we only handle SYSTEM SUSPEND API,
|
|
||||||
* we only need to save the context of the CPU that is issuing
|
|
||||||
* the SYSTEM SUSPEND call, i.e. the current CPU.
|
|
||||||
*/
|
|
||||||
gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx);
|
|
||||||
|
|
||||||
/* Save the GIC Distributor context */
|
|
||||||
gicv3_distif_save(&dist_ctx);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* From here, all the components of the GIC can be safely powered down
|
|
||||||
* as long as there is an alternate way to handle wakeup interrupt
|
|
||||||
* sources.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
void plat_versal_net_gic_resume(void)
|
|
||||||
{
|
|
||||||
/* Restore the GIC Distributor context */
|
|
||||||
gicv3_distif_init_restore(&dist_ctx);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Restore the GIC Redistributor and ITS contexts after the
|
|
||||||
* Distributor context. As we only handle SYSTEM SUSPEND API,
|
|
||||||
* we only need to restore the context of the CPU that issued
|
|
||||||
* the SYSTEM SUSPEND call.
|
|
||||||
*/
|
|
||||||
gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If an ITS is available, restore its context after
|
|
||||||
* the Redistributor using:
|
|
||||||
* gicv3_its_restore(gits_base, &its_ctx[i])
|
|
||||||
* An implementation-defined sequence may be required to
|
|
||||||
* restore the whole ITS state. The ITS must also be
|
|
||||||
* re-enabled after this sequence has been executed.
|
|
||||||
*/
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue