From 8b48bfb89732f5295d16208f0324fbcbf297c27c Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Wed, 17 Mar 2021 23:01:17 +0530 Subject: [PATCH 1/2] plat: xilinx: Error management support Add support for the trapping the IPI in TF-A. Register handler for the irq no 62 which is the IPI interrupt. Signed-off-by: Shubhrajyoti Datta Change-Id: I9c04fdae7be3dda6a34a9b196274c0b5fdf39223 Signed-off-by: Venkatesh Yadav Abbarapu --- plat/xilinx/versal/bl31_versal_setup.c | 43 +++++++++++++++++++++ plat/xilinx/versal/include/plat_private.h | 6 +++ plat/xilinx/versal/include/platform_def.h | 5 ++- plat/xilinx/versal/pm_service/pm_api_sys.c | 1 + plat/xilinx/versal/pm_service/pm_svc_main.c | 24 ++++++++++++ 5 files changed, 78 insertions(+), 1 deletion(-) 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; } From 78c7beb49c370453ab700ccc9eb54c7b14720d19 Mon Sep 17 00:00:00 2001 From: Venkatesh Yadav Abbarapu Date: Wed, 31 Mar 2021 03:07:40 -0600 Subject: [PATCH 2/2] plat: send an sgi to communicate to linux Upon recieving the interrupt send an SGI. The sgi number is communicated by linux. Signed-off-by: Shubhrajyoti Datta Change-Id: Ib8f07ff7132ba5ac202b546914efb16d04820ed3 Signed-off-by: Venkatesh Yadav Abbarapu --- plat/xilinx/versal/pm_service/pm_api_sys.c | 12 +++++++ plat/xilinx/versal/pm_service/pm_defs.h | 1 + plat/xilinx/versal/pm_service/pm_svc_main.c | 40 +++++++++++++++++++++ plat/xilinx/versal/pm_service/pm_svc_main.h | 1 + 4 files changed, 54 insertions(+) diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index 4fe35534f..15fe187eb 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -16,6 +16,7 @@ #include "pm_client.h" #include "pm_defs.h" #include "pm_svc_main.h" +#include "../drivers/arm/gic/v3/gicv3_private.h" /********************************************************************* * Target module IDs macros @@ -23,6 +24,7 @@ #define LIBPM_MODULE_ID 0x2 #define LOADER_MODULE_ID 0x7 +#define MODE 0x80000000 /* default shutdown/reboot scope is system(2) */ static unsigned int pm_shutdown_scope = XPM_SHUTDOWN_SUBTYPE_RST_SYSTEM; @@ -862,6 +864,7 @@ enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id, uint32_t flag) { uint32_t payload[PAYLOAD_ARG_CNT]; + int ret; switch (ioctl_id) { case IOCTL_SET_PLL_FRAC_MODE: @@ -872,6 +875,15 @@ enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id, return pm_pll_set_param(arg1, PM_PLL_PARAM_DATA, arg2, flag); case IOCTL_GET_PLL_FRAC_DATA: return pm_pll_get_param(arg1, PM_PLL_PARAM_DATA, value, flag); + case IOCTL_SET_SGI: + /* Get the sgi number */ + ret = pm_register_sgi(arg1); + if (ret) { + return PM_RET_ERROR_ARGS; + } + gicd_write_irouter(gicv3_driver_data->gicd_base, + PLAT_VERSAL_IPI_IRQ, MODE); + return PM_RET_SUCCESS; default: /* Send request to the PMC */ PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_IOCTL, diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index 793f75009..ccb2617ca 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -92,6 +92,7 @@ #define IOCTL_GET_PLL_FRAC_MODE 9 #define IOCTL_SET_PLL_FRAC_DATA 10 #define IOCTL_GET_PLL_FRAC_DATA 11 +#define IOCTL_SET_SGI 25 /* Parameter ID for PLL IOCTLs */ /* Fractional data portion for PLL */ diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c index c3d28f561..87ba73278 100644 --- a/plat/xilinx/versal/pm_service/pm_svc_main.c +++ b/plat/xilinx/versal/pm_service/pm_svc_main.c @@ -17,14 +17,29 @@ #include "pm_api_sys.h" #include "pm_client.h" #include "pm_ipi.h" +#include + +#define XSCUGIC_SGIR_EL1_INITID_SHIFT 24U +#define INVALID_SGI 0xFF +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_asgi1r_el1, S3_0_C12_C11_6) /* pm_up = true - UP, pm_up = false - DOWN */ static bool pm_up; +static unsigned int sgi = INVALID_SGI; static uint64_t ipi_fiq_handler(uint32_t id, uint32_t flags, void *handle, void *cookie) { + int cpu; + unsigned int reg; + (void)plat_ic_acknowledge_interrupt(); + cpu = plat_my_core_pos() + 1; + + if (sgi != INVALID_SGI) { + reg = (cpu | (sgi << XSCUGIC_SGIR_EL1_INITID_SHIFT)); + write_icc_asgi1r_el1(reg); + } /* Clear FIQ */ plat_ic_end_of_interrupt(id); @@ -32,6 +47,31 @@ static uint64_t ipi_fiq_handler(uint32_t id, uint32_t flags, void *handle, return 0; } +/** + * pm_register_sgi() - PM register the IPI interrupt + * + * @sgi - SGI number to be used for communication. + * @return On success, the initialization function must return 0. + * Any other return value will cause the framework to ignore + * the service + * + * Update the SGI number to be used. + * + */ +int pm_register_sgi(unsigned int sgi_num) +{ + if (sgi != INVALID_SGI) { + return -EBUSY; + } + + if (sgi_num >= GICV3_MAX_SGI_TARGETS) { + return -EINVAL; + } + + sgi = sgi_num; + return 0; +} + /** * pm_setup() - PM service setup * diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.h b/plat/xilinx/versal/pm_service/pm_svc_main.h index 71329ca93..4f8dc2b7f 100644 --- a/plat/xilinx/versal/pm_service/pm_svc_main.h +++ b/plat/xilinx/versal/pm_service/pm_svc_main.h @@ -14,4 +14,5 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, void *cookie, void *handle, uint64_t flags); +int pm_register_sgi(unsigned int sgi_num); #endif /* PM_SVC_MAIN_H */