fix(psci): add optional pwr_domain_validate_suspend to plat_psci_ops_t

This patch adds a new optional member `pwr_domain_validate_suspend` to
the `plat_psci_ops_t` structure that allows a platform to optionally
perform platform specific validations in OS-initiated mode. This is
conditionally compiled into the build depending on the value of the
`PSCI_OS_INIT_MODE` build option.

In https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/17682,
the return type of the `pwr_domain_suspend` handler was updated from
`void` to `int` to allow a platform to optionally perform platform
specific validations in OS-initiated mode. However, when an error code
other than `PSCI_E_SUCCESS` is returned, the current exit path does not
undo the operations in `psci_suspend_to_pwrdown_start`, and as a result,
the system ends up in an unexpected state.

The fix in this patch prevents the need to undo the operations in
`psci_suspend_to_pwrdown_start`, by allowing the platform to first
perform any necessary platform specific validations before the PSCI
generic code proceeds to the point of no return where the CPU_SUSPEND
request is expected to complete successfully.

Change-Id: I05d92c7ea3f5364da09af630d44d78252185db20
Signed-off-by: Wing Li <wingers@google.com>
diff --git a/lib/psci/psci_suspend.c b/lib/psci/psci_suspend.c
index 861b875..d93e60d 100644
--- a/lib/psci/psci_suspend.c
+++ b/lib/psci/psci_suspend.c
@@ -219,6 +219,19 @@
 	}
 #endif
 
+#if PSCI_OS_INIT_MODE
+	if (psci_plat_pm_ops->pwr_domain_validate_suspend != NULL) {
+		rc = psci_plat_pm_ops->pwr_domain_validate_suspend(state_info);
+		if (rc != PSCI_E_SUCCESS) {
+			skip_wfi = true;
+			goto exit;
+		}
+	}
+#endif
+
+	/* Update the target state in the power domain nodes */
+	psci_set_target_local_pwr_states(end_pwrlvl, state_info);
+
 #if ENABLE_PSCI_STAT
 	/* Update the last cpu for each level till end_pwrlvl */
 	psci_stats_update_pwr_down(end_pwrlvl, state_info);
@@ -234,15 +247,7 @@
 	 * program the power controller etc.
 	 */
 
-#if PSCI_OS_INIT_MODE
-	rc = psci_plat_pm_ops->pwr_domain_suspend(state_info);
-	if (rc != PSCI_E_SUCCESS) {
-		skip_wfi = true;
-		goto exit;
-	}
-#else
 	psci_plat_pm_ops->pwr_domain_suspend(state_info);
-#endif
 
 #if ENABLE_PSCI_STAT
 	plat_psci_stat_accounting_start(state_info);