refactor(psci): absorb psci_power_down_wfi() into common code

The AArch64 and AArch32 variants are not that different so there is no
need for them to be in assembly. They should also not be called from
non-PSCI code as PSCI is smart enough to handle this after platform
hooks. So absorb the functions into common code.

This allows for a tiny bit of optimisation: there will be no branch
(that can be missed or non-cached) to a non-inlineable function. Then in
the terminal case we can call wfi() directly with the application of the
erratum before the loop. And finally in the wakeup case, we don't have
to explicitly clear the errata as that will happen automatically on the
second call of prepare_cpu_pwr_dwn().

The A510 erratum requires a tsb csync before the dsb+wfi combo to turn
the core off. We can do this a little bit earlier in the cpu hook and
relieve common code from the responsibility. EL3 is always a prohibited
region so the buffer will stay empty.

Change-Id: I5f950df3fb7b0736df4ce25a21f78b29896de215
Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com>
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index 4157659..72d44ee 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -3107,13 +3107,14 @@
 the CPU power domain and its parent power domain levels.
 
 It is preferred that this function returns. The caller will invoke
-``psci_power_down_wfi()`` to powerdown the CPU, mitigate any powerdown errata,
+``wfi()`` to powerdown the CPU, mitigate any powerdown errata,
 and handle any wakeups that may arise. Previously, this function did not return
 and instead called ``wfi`` (in an infinite loop) directly. This is still
 possible on platforms where this is guaranteed to be terminal, however, it is
 strongly discouraged going forward.
 
-Previously this function was called ``pwr_domain_pwr_down_wfi()``.
+Previously this function was called ``pwr_domain_pwr_down_wfi()`` and invoked
+``psci_power_down_wfi()`` (now removed).
 
 plat_psci_ops.pwr_domain_on_finish()
 ....................................
diff --git a/include/lib/psci/psci.h b/include/lib/psci/psci.h
index 68e721a..b146d39 100644
--- a/include/lib/psci/psci.h
+++ b/include/lib/psci/psci.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2023, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -376,7 +376,6 @@
 #if PSCI_OS_INIT_MODE
 int psci_set_suspend_mode(unsigned int mode);
 #endif
-void psci_power_down_wfi(void);
 void psci_arch_setup(void);
 
 #endif /*__ASSEMBLER__*/
diff --git a/lib/cpus/aarch64/cortex_a510.S b/lib/cpus/aarch64/cortex_a510.S
index 258817f..1285034 100644
--- a/lib/cpus/aarch64/cortex_a510.S
+++ b/lib/cpus/aarch64/cortex_a510.S
@@ -187,6 +187,7 @@
 	 * ----------------------------------------------------
 	 */
 func cortex_a510_core_pwr_dwn
+	apply_erratum cortex_a510, ERRATUM(2684597), ERRATA_A510_2684597
 	/* ---------------------------------------------------
 	 * Enable CPU power down bit in power control register
 	 * ---------------------------------------------------
diff --git a/lib/psci/aarch32/psci_helpers.S b/lib/psci/aarch32/psci_helpers.S
index 4e1013c..929af8c 100644
--- a/lib/psci/aarch32/psci_helpers.S
+++ b/lib/psci/aarch32/psci_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,7 +10,6 @@
 
 	.globl	psci_do_pwrdown_cache_maintenance
 	.globl	psci_do_pwrup_cache_maintenance
-	.globl	psci_power_down_wfi
 
 /* -----------------------------------------------------------------------
  * void psci_do_pwrdown_cache_maintenance(unsigned int power level);
@@ -134,16 +133,3 @@
 
 	pop	{r4, pc}
 endfunc do_stack_maintenance
-
-/* -----------------------------------------------------------------------
- * This function is called to indicate to the power controller that it
- * is safe to power down this cpu. It should not exit the wfi and will
- * be released from reset upon power up.
- * -----------------------------------------------------------------------
- */
-func psci_power_down_wfi
-	dsb	sy		// ensure write buffer empty
-1:
-	wfi
-	b	1b
-endfunc psci_power_down_wfi
diff --git a/lib/psci/aarch64/psci_helpers.S b/lib/psci/aarch64/psci_helpers.S
index b297f9b..4da2f69 100644
--- a/lib/psci/aarch64/psci_helpers.S
+++ b/lib/psci/aarch64/psci_helpers.S
@@ -12,7 +12,6 @@
 
 	.globl	psci_do_pwrdown_cache_maintenance
 	.globl	psci_do_pwrup_cache_maintenance
-	.globl	psci_power_down_wfi
 
 /* -----------------------------------------------------------------------
  * void psci_do_pwrdown_cache_maintenance(unsigned int power level);
@@ -116,26 +115,3 @@
 	ldp	x29, x30, [sp], #16
 	ret
 endfunc psci_do_pwrup_cache_maintenance
-
-/* -----------------------------------------------------------------------
- * void psci_power_down_wfi(void); This function is called to indicate to the
- * power controller that it is safe to power down this cpu. It may exit if the
- * request was denied and reset did not occur
- * -----------------------------------------------------------------------
- */
-func psci_power_down_wfi
-	apply_erratum cortex_a510, ERRATUM(2684597), ERRATA_A510_2684597
-
-	dsb	sy		// ensure write buffer empty
-	wfi
-
-	/*
-	 * in case the WFI wasn't terminal, we have to undo errata mitigations.
-	 * These will be smart enough to handle being called the same way
-	 */
-	apply_erratum cortex_a710, ERRATUM(2291219), ERRATA_A710_2291219
-	apply_erratum cortex_x3,   ERRATUM(2313909), ERRATA_X3_2313909, NO_GET_CPU_REV
-	apply_erratum neoverse_n2, ERRATUM(2326639), ERRATA_N2_2326639, NO_GET_CPU_REV
-
-	ret
-endfunc psci_power_down_wfi
diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c
index 1021ef6..7c83a79 100644
--- a/lib/psci/psci_common.c
+++ b/lib/psci/psci_common.c
@@ -14,6 +14,7 @@
 #include <common/debug.h>
 #include <context.h>
 #include <drivers/delay_timer.h>
+#include <lib/cpus/cpu_ops.h>
 #include <lib/el3_runtime/context_mgmt.h>
 #include <lib/extensions/spe.h>
 #include <lib/pmf/pmf.h>
@@ -1257,6 +1258,9 @@
 	}
 #endif /* ERRATA_SME_POWER_DOWN */
 
+	/* ensure write buffer empty */
+	dsbsy();
+
 	/*
 	 * Execute a wfi which, in most cases, will allow the power controller
 	 * to physically power down this cpu. Under some circumstances that may
@@ -1264,7 +1268,7 @@
 	 * power down.
 	 */
 	for (int i = 0; i < 32; i++)
-		psci_power_down_wfi();
+		wfi();
 
 	/* Wake up wasn't transient. System is probably in a bad state. */
 	ERROR("Could not power off CPU.\n");
@@ -1278,11 +1282,14 @@
 
 void psci_pwrdown_cpu_end_wakeup(unsigned int power_level)
 {
+	/* ensure write buffer empty */
+	dsbsy();
+
 	/*
-	 * Usually, will be terminal. In some circumstances the powerdown will
-	 * be denied and we'll need to unwind
+	 * Turn the core off. Usually, will be terminal. In some circumstances
+	 * the powerdown will be denied and we'll need to unwind.
 	 */
-	psci_power_down_wfi();
+	wfi();
 
 	/*
 	 * Waking up does not require hardware-assisted coherency, but that is
@@ -1290,7 +1297,7 @@
 	 * coherency code from powerdown is a non-trivial effort which isn't
 	 * needed for our purposes.
 	 */
-#if !FEAT_PABANDON
+#if !FEAT_PABANDON || !defined(__aarch64__)
 	ERROR("Systems without FEAT_PABANDON shouldn't wake up.\n");
 	panic();
 #else /* FEAT_PABANDON */