fix(cpus): workaround for Cortex-X3 erratum 2313909

Cortex-X3 erratum 2313909 is a Cat B erratum that applies to revisions
r0p0 and r1p0, and is fixed in r1p1. The workaround is to set
CPUACTLR2_EL1[36] to 1 before the power down sequence that sets
CORE_PWRDN_EN. This allows the cpu to retry the power down and prevents
the deadlock. TF-A never clears this bit even if it wakes up from the
wfi in the sequence since it is not expected to do anything but retry to
power down after and the bit is cleared on reset.

SDEN can be found here:
https://developer.arm.com/documentation/SDEN2055130/latest

Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com>
Change-Id: I5935b4bcd1e6712477c0d6eab2acc96d7964a35d
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index f4d32c9..91f712a 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -580,6 +580,12 @@
    Cortex-X2 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0
    of the CPU and is fixed in r2p1.
 
+For Cortex-X3, the following errata build flags are defined :
+
+- ``ERRATA_X3_2313909``: This applies errata 2313909 workaround to
+  Cortex-X3 CPU. This needs to be enabled only for revisions r0p0 and r1p0
+  of the CPU, it is fixed in r1p1.
+
 For Cortex-A510, the following errata build flags are defined :
 
 -  ``ERRATA_A510_1922240``: This applies errata 1922240 workaround to
diff --git a/include/lib/cpus/aarch64/cortex_x3.h b/include/lib/cpus/aarch64/cortex_x3.h
index 5fd07ff..076a87b 100644
--- a/include/lib/cpus/aarch64/cortex_x3.h
+++ b/include/lib/cpus/aarch64/cortex_x3.h
@@ -23,4 +23,10 @@
 #define CORTEX_X3_CPUPWRCTLR_EL1			S3_0_C15_C2_7
 #define CORTEX_X3_CPUPWRCTLR_EL1_CORE_PWRDN_BIT	U(1)
 
+/*******************************************************************************
+ * CPU Auxiliary Control register 2 specific definitions.
+ ******************************************************************************/
+#define CORTEX_X3_CPUACTLR2_EL1			S3_0_C15_C1_1
+#define CORTEX_X3_CPUACTLR2_EL1_BIT_36		(ULL(1) << 36)
+
 #endif /* CORTEX_X3_H */
diff --git a/lib/cpus/aarch64/cortex_x3.S b/lib/cpus/aarch64/cortex_x3.S
index 874d565..bf1b6ec 100644
--- a/lib/cpus/aarch64/cortex_x3.S
+++ b/lib/cpus/aarch64/cortex_x3.S
@@ -31,6 +31,13 @@
 	 * ----------------------------------------------------
 	 */
 func cortex_x3_core_pwr_dwn
+#if ERRATA_X3_2313909
+	mov	x15, x30
+	bl	cpu_get_rev_var
+	bl	errata_cortex_x3_2313909_wa
+	mov	x30, x15
+#endif /* ERRATA_X3_2313909 */
+
 	/* ---------------------------------------------------
 	 * Enable CPU power down bit in power control register
 	 * ---------------------------------------------------
@@ -68,6 +75,34 @@
 	ret
 endfunc cortex_x3_reset_func
 
+/* ----------------------------------------------------------------------
+ * Errata Workaround for Cortex-X3 Erratum 2313909 on power down request.
+ * This applies to revision r0p0 and r1p0 of Cortex-X3. Fixed in r1p1.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x1, x17
+ * ----------------------------------------------------------------------
+ */
+func errata_cortex_x3_2313909_wa
+	/* Check revision. */
+	mov	x17, x30
+	bl	check_errata_2313909
+	cbz	x0, 1f
+
+	/* Set bit 36 in ACTLR2_EL1 */
+	mrs	x1, CORTEX_X3_CPUACTLR2_EL1
+	orr	x1, x1, #CORTEX_X3_CPUACTLR2_EL1_BIT_36
+	msr	CORTEX_X3_CPUACTLR2_EL1, x1
+1:
+	ret	x17
+endfunc errata_cortex_x3_2313909_wa
+
+func check_errata_2313909
+	/* Applies to r0p0 and r1p0 */
+	mov	x1, #0x10
+	b	cpu_rev_var_ls
+endfunc check_errata_2313909
+
 #if REPORT_ERRATA
 	/*
 	 * Errata printing function for Cortex-X3. Must follow AAPCS.
@@ -82,6 +117,7 @@
 	 * Report all errata. The revision-variant information is passed to
 	 * checking functions of each errata.
 	 */
+	report_errata ERRATA_X3_2313909, cortex_x3, 2313909
 	report_errata WORKAROUND_CVE_2022_23960, cortex_x3, cve_2022_23960
 
 	ldp	x8, x30, [sp], #16
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 2c42ad0..dcc6fd1 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -639,6 +639,10 @@
 # to revision r0p0, r1p0 and r2p0 of the Cortex-X2 cpu and is fixed in r2p1.
 ERRATA_X2_2371105	?=0
 
+# Flag to apply erratum 2313909 workaround on powerdown. This erratum applies
+# to revisions r0p0 and r1p0 of the Cortex-X3 cpu, it is fixed in r1p1.
+ERRATA_X3_2313909	?=0
+
 # Flag to apply erratum 1922240 workaround during reset. This erratum applies
 # to revision r0p0 of the Cortex-A510 cpu and is fixed in r0p1.
 ERRATA_A510_1922240	?=0
@@ -1248,6 +1252,10 @@
 $(eval $(call assert_boolean,ERRATA_X2_2371105))
 $(eval $(call add_define,ERRATA_X2_2371105))
 
+# Process ERRATA_X3_2313909 flag
+$(eval $(call assert_boolean,ERRATA_X3_2313909))
+$(eval $(call add_define,ERRATA_X3_2313909))
+
 # Process ERRATA_A510_1922240 flag
 $(eval $(call assert_boolean,ERRATA_A510_1922240))
 $(eval $(call add_define,ERRATA_A510_1922240))