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/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();