xilinx: versal: Implement power down/restart related EEMI API

Add power down/restart related below API
 - Force power down
 - System shutdown

Signed-off-by: Tejas Patel <tejas.patel@xilinx.com>
Signed-off-by: Jolly Shah <jolly.shah@xilinx.com>
Change-Id: Icd4a922923b1fd50eca1f5361f1e604aedcdb529
diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c
index 1b32e4b..be28a41 100644
--- a/plat/xilinx/versal/pm_service/pm_api_sys.c
+++ b/plat/xilinx/versal/pm_service/pm_api_sys.c
@@ -572,3 +572,43 @@
 
 	return pm_ipi_send_sync(primary_proc, payload, mode, 1);
 }
+
+/**
+ * pm_force_powerdown() - PM call to request for another PU or subsystem to
+ *			  be powered down forcefully
+ * @target	Device ID of the PU node to be forced powered down.
+ * @ack		Flag to specify whether acknowledge is requested
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMC */
+	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_FORCE_POWERDOWN, target,
+			 ack);
+
+	if (ack == IPI_BLOCKING)
+		return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+	else
+		return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_system_shutdown() - PM call to request a system shutdown or restart
+ * @type	Shutdown or restart? 0=shutdown, 1=restart
+ * @subtype	Scope: 0=APU-subsystem, 1=PS, 2=system
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMC */
+	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_SYSTEM_SHUTDOWN, type,
+			 subtype);
+
+	return pm_ipi_send_non_blocking(primary_proc, payload);
+}
diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h
index 025255b..3751995 100644
--- a/plat/xilinx/versal/pm_service/pm_api_sys.h
+++ b/plat/xilinx/versal/pm_service/pm_api_sys.h
@@ -53,5 +53,7 @@
 				    uint32_t *value);
 enum pm_ret_status pm_pll_set_mode(uint32_t clk_id, uint32_t mode);
 enum pm_ret_status pm_pll_get_mode(uint32_t clk_id, uint32_t *mode);
+enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack);
+enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype);
 
 #endif /* PM_API_SYS_H */
diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h
index ce2605a..248c715 100644
--- a/plat/xilinx/versal/pm_service/pm_defs.h
+++ b/plat/xilinx/versal/pm_service/pm_defs.h
@@ -27,7 +27,9 @@
 #define PM_GET_DEVICE_STATUS		3U
 #define PM_REQ_SUSPEND			6U
 #define PM_SELF_SUSPEND			7U
+#define PM_FORCE_POWERDOWN		8U
 #define PM_ABORT_SUSPEND		9U
+#define PM_SYSTEM_SHUTDOWN		12U
 #define PM_REQUEST_DEVICE		13U
 #define PM_RELEASE_DEVICE		14U
 #define PM_SET_REQUIREMENT		15U
diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c
index 5dd3157..aa008ac 100644
--- a/plat/xilinx/versal/pm_service/pm_svc_main.c
+++ b/plat/xilinx/versal/pm_service/pm_svc_main.c
@@ -88,6 +88,10 @@
 				      pm_arg[3]);
 		SMC_RET1(handle, (uint64_t)ret);
 
+	case PM_FORCE_POWERDOWN:
+		ret = pm_force_powerdown(pm_arg[0], pm_arg[1]);
+		SMC_RET1(handle, (uint64_t)ret);
+
 	case PM_REQ_SUSPEND:
 		ret = pm_req_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
 				     pm_arg[3]);
@@ -97,6 +101,10 @@
 		ret = pm_abort_suspend(pm_arg[0]);
 		SMC_RET1(handle, (uint64_t)ret);
 
+	case PM_SYSTEM_SHUTDOWN:
+		ret = pm_system_shutdown(pm_arg[0], pm_arg[1]);
+		SMC_RET1(handle, (uint64_t)ret);
+
 	case PM_REQUEST_DEVICE:
 		ret = pm_request_device(pm_arg[0], pm_arg[1], pm_arg[2],
 					pm_arg[3]);