Workaround for Cortex A76 erratum 1946160

Cortex A76 erratum 1946160 is a Cat B erratum, present in some revisions
of the A76 processor core.  The workaround is to insert a DMB ST before
acquire atomic instructions without release semantics.  This issue is
present in revisions r0p0 - r4p1  but this workaround only applies to
revisions r3p0 - r4p1, there is no workaround for older versions.

SDEN can be found here:
https://documentation-service.arm.com/static/5fbb77d7d77dd807b9a80cc1

Signed-off-by: John Powell <john.powell@arm.com>
Change-Id: Ief33779ee76a89ce2649812ae5214b86a139e327
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index e901e0c..d859cc5 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -249,6 +249,9 @@
 -  ``ERRATA_A76_1868343``: This applies errata 1868343 workaround to Cortex-A76
    CPU. This needs to be enabled only for revision <= r4p0 of the CPU.
 
+-  ``ERRATA_A76_1946160``: This applies errata 1946160 workaround to Cortex-A76
+   CPU. This needs to be enabled only for revisions r3p0 - r4p1 of the CPU.
+
 For Cortex-A77, the following errata build flags are defined :
 
 -  ``ERRATA_A77_1508412``: This applies errata 1508412 workaround to Cortex-A77
diff --git a/lib/cpus/aarch64/cortex_a76.S b/lib/cpus/aarch64/cortex_a76.S
index 2c99cdc..4f7f4bb 100644
--- a/lib/cpus/aarch64/cortex_a76.S
+++ b/lib/cpus/aarch64/cortex_a76.S
@@ -430,6 +430,61 @@
 	b	cpu_rev_var_ls
 endfunc check_errata_1868343
 
+/* --------------------------------------------------
+ * Errata Workaround for A76 Erratum 1946160.
+ * This applies to revisions r3p0 - r4p1 of A76.
+ * It also exists in r0p0 - r2p0 but there is no fix
+ * in those revisions.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_a76_1946160_wa
+	/* Compare x0 against revisions r3p0 - r4p1 */
+	mov	x17, x30
+	bl	check_errata_1946160
+	cbz	x0, 1f
+
+	mov	x0, #3
+	msr	S3_6_C15_C8_0, x0
+	ldr	x0, =0x10E3900002
+	msr	S3_6_C15_C8_2, x0
+	ldr	x0, =0x10FFF00083
+	msr	S3_6_C15_C8_3, x0
+	ldr	x0, =0x2001003FF
+	msr	S3_6_C15_C8_1, x0
+
+	mov	x0, #4
+	msr	S3_6_C15_C8_0, x0
+	ldr	x0, =0x10E3800082
+	msr	S3_6_C15_C8_2, x0
+	ldr	x0, =0x10FFF00083
+	msr	S3_6_C15_C8_3, x0
+	ldr	x0, =0x2001003FF
+	msr	S3_6_C15_C8_1, x0
+
+	mov	x0, #5
+	msr	S3_6_C15_C8_0, x0
+	ldr	x0, =0x10E3800200
+	msr	S3_6_C15_C8_2, x0
+	ldr	x0, =0x10FFF003E0
+	msr	S3_6_C15_C8_3, x0
+	ldr	x0, =0x2001003FF
+	msr	S3_6_C15_C8_1, x0
+
+	isb
+1:
+	ret	x17
+endfunc errata_a76_1946160_wa
+
+func check_errata_1946160
+	/* Applies to revisions r3p0 - r4p1. */
+	mov	x1, #0x30
+	mov	x2, #0x41
+	b	cpu_rev_var_range
+endfunc check_errata_1946160
+
 func check_errata_cve_2018_3639
 #if WORKAROUND_CVE_2018_3639
 	mov	x0, #ERRATA_APPLIES
@@ -509,6 +564,11 @@
 	bl	errata_a76_1791580_wa
 #endif
 
+#if ERRATA_A76_1946160
+	mov	x0, x18
+	bl	errata_a76_1946160_wa
+#endif
+
 #if WORKAROUND_CVE_2018_3639
 	/* If the PE implements SSBS, we don't need the dynamic workaround */
 	mrs	x0, id_aa64pfr1_el1
@@ -592,6 +652,7 @@
 	report_errata ERRATA_A76_1791580, cortex_a76, 1791580
 	report_errata ERRATA_A76_1165522, cortex_a76, 1165522
 	report_errata ERRATA_A76_1868343, cortex_a76, 1868343
+	report_errata ERRATA_A76_1946160, cortex_a76, 1946160
 	report_errata WORKAROUND_CVE_2018_3639, cortex_a76, cve_2018_3639
 	report_errata ERRATA_DSU_798953, cortex_a76, dsu_798953
 	report_errata ERRATA_DSU_936184, cortex_a76, dsu_936184
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 084e6e7..da0157f 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -278,6 +278,10 @@
 # only to revision <= r4p0 of the Cortex A76 cpu.
 ERRATA_A76_1868343	?=0
 
+# Flag to apply erratum 1946160 workaround during reset. This erratum applies
+# only to revisions r3p0 - r4p1 of the Cortex A76 cpu.
+ERRATA_A76_1946160	?=0
+
 # Flag to apply erratum 1508412 workaround during reset. This erratum applies
 # only to revision <= r1p0 of the Cortex A77 cpu.
 ERRATA_A77_1508412	?=0
@@ -555,6 +559,10 @@
 $(eval $(call assert_boolean,ERRATA_A76_1868343))
 $(eval $(call add_define,ERRATA_A76_1868343))
 
+# Process ERRATA_A76_1946160 flag
+$(eval $(call assert_boolean,ERRATA_A76_1946160))
+$(eval $(call add_define,ERRATA_A76_1946160))
+
 # Process ERRATA_A77_1508412 flag
 $(eval $(call assert_boolean,ERRATA_A77_1508412))
 $(eval $(call add_define,ERRATA_A77_1508412))