feat(xilinx): request cpu power down from reset

Send subsystem restart notification to firmware when TF-A receives
system reset PSCI call. On receiving subsystem restart call, firmware
will send CPU idle callback to TF-A for powering down all cores. Wait
for CPU idle callback from firmware and raise power down request to
all cores after it receives CPU idle callback to power down core.

Signed-off-by: Jay Buddhabhatti <jay.buddhabhatti@amd.com>
Change-Id: I50f417ae228017f38b648740dc90b2e8f1872620
diff --git a/plat/xilinx/common/include/pm_svc_main.h b/plat/xilinx/common/include/pm_svc_main.h
index 4cf7727..67fbeae 100644
--- a/plat/xilinx/common/include/pm_svc_main.h
+++ b/plat/xilinx/common/include/pm_svc_main.h
@@ -10,6 +10,8 @@
 
 #include <pm_common.h>
 
+extern bool pwrdwn_req_received;
+
 /******************************************************************************/
 /**
  * SECURE_REDUNDANT_CALL() - Adds redundancy to the function call. This is to
@@ -30,6 +32,7 @@
 		status_tmp = function(__VA_ARGS__); \
 	}
 
+void request_cpu_pwrdwn(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 x4, const void *cookie, void *handle,
diff --git a/plat/xilinx/common/pm_service/pm_svc_main.c b/plat/xilinx/common/pm_service/pm_svc_main.c
index 3a01dd2..9df9eb2 100644
--- a/plat/xilinx/common/pm_service/pm_svc_main.c
+++ b/plat/xilinx/common/pm_service/pm_svc_main.c
@@ -41,7 +41,7 @@
 /* pm_up = true - UP, pm_up = false - DOWN */
 static bool pm_up;
 static uint32_t sgi = (uint32_t)INVALID_SGI;
-static bool pwrdwn_req_received;
+bool pwrdwn_req_received;
 
 static void notify_os(void)
 {
@@ -79,7 +79,7 @@
 	plat_ic_raise_el3_sgi(CPU_PWR_DOWN_REQ_INTR, mpidr);
 }
 
-static void request_cpu_pwrdwn(void)
+void request_cpu_pwrdwn(void)
 {
 	enum pm_ret_status ret;
 
diff --git a/plat/xilinx/versal/plat_psci.c b/plat/xilinx/versal/plat_psci.c
index 56d98f7..9c34d0d 100644
--- a/plat/xilinx/versal/plat_psci.c
+++ b/plat/xilinx/versal/plat_psci.c
@@ -14,10 +14,13 @@
 #include <plat/common/platform.h>
 #include <plat_arm.h>
 
+#include "drivers/delay_timer.h"
 #include <plat_private.h>
 #include "pm_api_sys.h"
 #include "pm_client.h"
 #include <pm_common.h>
+#include "pm_ipi.h"
+#include "pm_svc_main.h"
 
 static uintptr_t versal_sec_entry;
 
@@ -145,9 +148,31 @@
  */
 static void __dead2 versal_system_reset(void)
 {
-	/* Send the system reset request to the PMC */
-	(void)pm_system_shutdown(XPM_SHUTDOWN_TYPE_RESET,
-				 pm_get_shutdown_scope(), SECURE_FLAG);
+	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,
+					 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) {
 		wfi();
diff --git a/plat/xilinx/versal_net/plat_psci_pm.c b/plat/xilinx/versal_net/plat_psci_pm.c
index 219fb68..2cf3bf2 100644
--- a/plat/xilinx/versal_net/plat_psci_pm.c
+++ b/plat/xilinx/versal_net/plat_psci_pm.c
@@ -14,10 +14,12 @@
 #include <plat/common/platform.h>
 #include <plat_arm.h>
 
+#include <drivers/delay_timer.h>
 #include <plat_private.h>
 #include "pm_api_sys.h"
 #include "pm_client.h"
 #include <pm_common.h>
+#include "pm_ipi.h"
 #include "pm_svc_main.h"
 #include "versal_net_def.h"
 
@@ -88,9 +90,31 @@
  */
 static void __dead2 versal_net_system_reset(void)
 {
-	/* Send the system reset request to the PMC */
-	pm_system_shutdown(XPM_SHUTDOWN_TYPE_RESET,
-			  pm_get_shutdown_scope(), SECURE_FLAG);
+	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,
+					 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) {
 		wfi();