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 <shubhrajyoti.datta@xilinx.com>
Change-Id: Ib8f07ff7132ba5ac202b546914efb16d04820ed3
Signed-off-by: Venkatesh Yadav Abbarapu <venkatesh.abbarapu@xilinx.com>
diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c
index 4fe3553..15fe187 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 @@
uint32_t flag)
{
uint32_t payload[PAYLOAD_ARG_CNT];
+ int ret;
switch (ioctl_id) {
case IOCTL_SET_PLL_FRAC_MODE:
@@ -872,6 +875,15 @@
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 793f750..ccb2617 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 c3d28f5..87ba732 100644
--- a/plat/xilinx/versal/pm_service/pm_svc_main.c
+++ b/plat/xilinx/versal/pm_service/pm_svc_main.c
@@ -17,18 +17,58 @@
#include "pm_api_sys.h"
#include "pm_client.h"
#include "pm_ipi.h"
+#include <drivers/arm/gicv3.h>
+
+#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);
+ 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;
}
diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.h b/plat/xilinx/versal/pm_service/pm_svc_main.h
index 71329ca..4f8dc2b 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 x4, void *cookie, void *handle,
uint64_t flags);
+int pm_register_sgi(unsigned int sgi_num);
#endif /* PM_SVC_MAIN_H */