diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c index de36efc0a..8b8714cb6 100644 --- a/plat/xilinx/versal/bl31_versal_setup.c +++ b/plat/xilinx/versal/bl31_versal_setup.c @@ -117,6 +117,40 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, NOTICE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc); } +static interrupt_type_handler_t type_el3_interrupt_handler; + +int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler) +{ + /* Validate 'handler'*/ + if (!handler) { + return -EINVAL; + } + + type_el3_interrupt_handler = handler; + + return 0; +} + +static uint64_t rdo_el3_interrupt_handler(uint32_t id, uint32_t flags, + void *handle, void *cookie) +{ + uint32_t intr_id; + interrupt_type_handler_t handler; + + intr_id = plat_ic_get_pending_interrupt_id(); + /* Currently we support one interrupt */ + if (intr_id != PLAT_VERSAL_IPI_IRQ) { + WARN("Unexpected interrupt call: 0x%x\n", intr_id); + return 0; + } + + handler = type_el3_interrupt_handler; + if (handler) { + return handler(intr_id, flags, handle, cookie); + } + + return 0; +} void bl31_platform_setup(void) { /* Initialize the gic cpu and distributor interfaces */ @@ -126,6 +160,15 @@ void bl31_platform_setup(void) void bl31_plat_runtime_setup(void) { + uint64_t flags = 0; + uint64_t rc; + + set_interrupt_rm_flag(flags, NON_SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_EL3, + rdo_el3_interrupt_handler, flags); + if (rc) { + panic(); + } } /* diff --git a/plat/xilinx/versal/include/plat_private.h b/plat/xilinx/versal/include/plat_private.h index e302096eb..d12d13af8 100644 --- a/plat/xilinx/versal/include/plat_private.h +++ b/plat/xilinx/versal/include/plat_private.h @@ -8,6 +8,7 @@ #define PLAT_PRIVATE_H #include +#include void versal_config_setup(void); @@ -22,5 +23,10 @@ void plat_versal_gic_save(void); void plat_versal_gic_resume(void); unsigned int versal_calc_core_pos(u_register_t mpidr); +/* + * Register handler to specific GIC entrance + * for INTR_TYPE_EL3 type of interrupt + */ +int request_intr_type_el3(uint32_t irq, interrupt_type_handler_t fiq_handler); #endif /* PLAT_PRIVATE_H */ diff --git a/plat/xilinx/versal/include/platform_def.h b/plat/xilinx/versal/include/platform_def.h index 4cdaea219..8b513ef3a 100644 --- a/plat/xilinx/versal/include/platform_def.h +++ b/plat/xilinx/versal/include/platform_def.h @@ -91,11 +91,14 @@ */ #define PLAT_VERSAL_G1S_IRQS VERSAL_IRQ_SEC_PHY_TIMER #define PLAT_VERSAL_G0_IRQS VERSAL_IRQ_SEC_PHY_TIMER +#define PLAT_VERSAL_IPI_IRQ 62 #define PLAT_VERSAL_G1S_IRQ_PROPS(grp) \ INTR_PROP_DESC(VERSAL_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ GIC_INTR_CFG_LEVEL) -#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, \ + GIC_INTR_CFG_EDGE), \ #endif /* PLATFORM_DEF_H */ diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index a57854374..4fe35534f 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -15,6 +15,7 @@ #include "pm_api_sys.h" #include "pm_client.h" #include "pm_defs.h" +#include "pm_svc_main.h" /********************************************************************* * Target module IDs macros diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c index 55a095662..c3d28f561 100644 --- a/plat/xilinx/versal/pm_service/pm_svc_main.c +++ b/plat/xilinx/versal/pm_service/pm_svc_main.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "pm_api_sys.h" #include "pm_client.h" #include "pm_ipi.h" @@ -20,6 +21,17 @@ /* pm_up = true - UP, pm_up = false - DOWN */ static bool pm_up; +static uint64_t ipi_fiq_handler(uint32_t id, uint32_t flags, void *handle, + void *cookie) +{ + (void)plat_ic_acknowledge_interrupt(); + + /* Clear FIQ */ + plat_ic_end_of_interrupt(id); + + return 0; +} + /** * pm_setup() - PM service setup * @@ -46,6 +58,18 @@ int pm_setup(void) pm_up = true; } + /* + * Enable IPI IRQ + * assume the rich OS is OK to handle callback IRQs now. + * Even if we were wrong, it would not enable the IRQ in + * the GIC. + */ + pm_ipi_irq_enable(primary_proc); + + ret = request_intr_type_el3(PLAT_VERSAL_IPI_IRQ, ipi_fiq_handler); + if (ret) { + WARN("BL31: registering IPI interrupt failed\n"); + } return ret; }