fix(errata): workaround for Cortex-A510 erratum 2172148

Cortex-A510 erratum 2172148 is a Cat B erratum that applies to revisions
r0p0, r0p1, r0p2, r0p3 and r1p0, and is fixed in r1p1.

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

Signed-off-by: John Powell <john.powell@arm.com>
Change-Id: I1784d643ca3d1d448340cd421facb5f229df1d22
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index ffb748f..7aa7384 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -502,6 +502,10 @@
    Cortex-A510 CPU. This needs to be enabled for revisions r0p0, r0p1, r0p2,
    r0p3 and r1p0, it is fixed in r1p1.
 
+-  ``ERRATA_A510_2172148``: This applies errata 2172148 workaround to
+   Cortex-A510 CPU. This needs to be enabled for revisions r0p0, r0p1, r0p2,
+   r0p3 and r1p0, it is fixed in r1p1.
+
 DSU Errata Workarounds
 ----------------------
 
diff --git a/include/lib/cpus/aarch64/cortex_a510.h b/include/lib/cpus/aarch64/cortex_a510.h
index fcb821f..2b8db14 100644
--- a/include/lib/cpus/aarch64/cortex_a510.h
+++ b/include/lib/cpus/aarch64/cortex_a510.h
@@ -15,6 +15,8 @@
 #define CORTEX_A510_CPUECTLR_EL1				S3_0_C15_C1_4
 #define CORTEX_A510_CPUECTLR_EL1_READPREFERUNIQUE_SHIFT		U(19)
 #define CORTEX_A510_CPUECTLR_EL1_READPREFERUNIQUE_DISABLE	U(1)
+#define CORTEX_A510_CPUECTLR_EL1_RSCTL_SHIFT			U(23)
+#define CORTEX_A510_CPUECTLR_EL1_NTCTL_SHIFT			U(46)
 
 /*******************************************************************************
  * CPU Power Control register specific definitions
diff --git a/lib/cpus/aarch64/cortex_a510.S b/lib/cpus/aarch64/cortex_a510.S
index e5f83aa..34e1082 100644
--- a/lib/cpus/aarch64/cortex_a510.S
+++ b/lib/cpus/aarch64/cortex_a510.S
@@ -230,6 +230,40 @@
 	b	cpu_rev_var_ls
 endfunc check_errata_2218950
 
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex-A510 Errata #2172148.
+	 * This applies only to revisions r0p0, r0p1, r0p2,
+	 * r0p3 and r1p0, and is fixed in r1p1.
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0, x1, x17
+	 * --------------------------------------------------
+	 */
+func errata_cortex_a510_2172148_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_2172148
+	cbz	x0, 1f
+
+	/*
+	 * Force L2 allocation of transient lines by setting
+	 * CPUECTLR_EL1.RSCTL=0b01 and CPUECTLR_EL1.NTCTL=0b01.
+	 */
+	mrs	x0, CORTEX_A510_CPUECTLR_EL1
+	mov	x1, #1
+	bfi	x0, x1, #CORTEX_A510_CPUECTLR_EL1_RSCTL_SHIFT, #2
+	bfi	x0, x1, #CORTEX_A510_CPUECTLR_EL1_NTCTL_SHIFT, #2
+	msr	CORTEX_A510_CPUECTLR_EL1, x0
+
+1:
+	ret x17
+endfunc errata_cortex_a510_2172148_wa
+
+func check_errata_2172148
+	/* Applies to r1p0 and lower */
+	mov	x1, #0x10
+	b	cpu_rev_var_ls
+endfunc check_errata_2172148
+
 	/* ----------------------------------------------------
 	 * HW will do the cache maintenance while powering down
 	 * ----------------------------------------------------
@@ -266,6 +300,7 @@
 	report_errata ERRATA_A510_2041909, cortex_a510, 2041909
 	report_errata ERRATA_A510_2250311, cortex_a510, 2250311
 	report_errata ERRATA_A510_2218950, cortex_a510, 2218950
+	report_errata ERRATA_A510_2172148, cortex_a510, 2172148
 
 	ldp	x8, x30, [sp], #16
 	ret
@@ -313,6 +348,11 @@
 	bl	errata_cortex_a510_2218950_wa
 #endif
 
+#if ERRATA_A510_2172148
+	mov	x0, x18
+	bl	errata_cortex_a510_2172148_wa
+#endif
+
 	ret	x19
 endfunc cortex_a510_reset_func
 
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 92193fb..62b67b6 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -556,6 +556,10 @@
 # to revisions r0p0, r0p1, r0p2, r0p3 and r1p0, and is fixed in r1p1.
 ERRATA_A510_2218950	?=0
 
+# Flag to apply erratum 2172148 workaround during reset. This erratum applies
+# to revisions r0p0, r0p1, r0p2, r0p3 and r1p0, and is fixed in r1p1.
+ERRATA_A510_2172148	?=0
+
 # Flag to apply DSU erratum 798953. This erratum applies to DSUs revision r0p0.
 # Applying the workaround results in higher DSU power consumption on idle.
 ERRATA_DSU_798953	?=0
@@ -1037,6 +1041,10 @@
 $(eval $(call assert_boolean,ERRATA_A510_2218950))
 $(eval $(call add_define,ERRATA_A510_2218950))
 
+# Process ERRATA_A510_2172148 flag
+$(eval $(call assert_boolean,ERRATA_A510_2172148))
+$(eval $(call add_define,ERRATA_A510_2172148))
+
 # Process ERRATA_DSU_798953 flag
 $(eval $(call assert_boolean,ERRATA_DSU_798953))
 $(eval $(call add_define,ERRATA_DSU_798953))