PSCI: Add pwr_domain_pwr_down_wfi() hook in plat_psci_ops

This patch adds a new optional platform hook `pwr_domain_pwr_down_wfi()` in
the plat_psci_ops structure. This hook allows the platform to perform platform
specific actions including the wfi invocation to enter powerdown. This hook
is invoked by both psci_do_cpu_off() and psci_cpu_suspend_start() functions.
The porting-guide.md is also updated for the same.

This patch also modifies the `psci_power_down_wfi()` function to invoke
`plat_panic_handler` incase of panic instead of the busy while loop.

Fixes ARM-Software/tf-issues#375

Change-Id: Iba104469a1445ee8d59fb3a6fdd0a98e7f24dfa3
diff --git a/services/std_svc/psci/psci_entry.S b/services/std_svc/psci/psci_entry.S
index 5f4f91c..f8c0afa 100644
--- a/services/std_svc/psci/psci_entry.S
+++ b/services/std_svc/psci/psci_entry.S
@@ -106,7 +106,6 @@
 func psci_power_down_wfi
 	dsb	sy		// ensure write buffer empty
 	wfi
-wfi_spill:
-	b	wfi_spill
+	bl	plat_panic_handler
 endfunc psci_power_down_wfi
 
diff --git a/services/std_svc/psci/psci_off.c b/services/std_svc/psci/psci_off.c
index cef6668..686666d 100644
--- a/services/std_svc/psci/psci_off.c
+++ b/services/std_svc/psci/psci_off.c
@@ -138,11 +138,16 @@
 		dsbish();
 		inv_cpu_data(psci_svc_cpu_data.aff_info_state);
 
-		/*
-		 * Enter a wfi loop which will allow the power controller to
-		 * physically power down this cpu.
-		 */
-		psci_power_down_wfi();
+		if (psci_plat_pm_ops->pwr_domain_pwr_down_wfi) {
+			/* This function must not return */
+			psci_plat_pm_ops->pwr_domain_pwr_down_wfi(&state_info);
+		} else {
+			/*
+			 * Enter a wfi loop which will allow the power
+			 * controller to physically power down this cpu.
+			 */
+			psci_power_down_wfi();
+		}
 	}
 
 	return rc;
diff --git a/services/std_svc/psci/psci_suspend.c b/services/std_svc/psci/psci_suspend.c
index 367bb32..8c6ab6b 100644
--- a/services/std_svc/psci/psci_suspend.c
+++ b/services/std_svc/psci/psci_suspend.c
@@ -189,8 +189,13 @@
 	if (skip_wfi)
 		return;
 
-	if (is_power_down_state)
-		psci_power_down_wfi();
+	if (is_power_down_state) {
+		/* The function calls below must not return */
+		if (psci_plat_pm_ops->pwr_domain_pwr_down_wfi)
+			psci_plat_pm_ops->pwr_domain_pwr_down_wfi(state_info);
+		else
+			psci_power_down_wfi();
+	}
 
 	/*
 	 * We will reach here if only retention/standby states have been