Cortex-A57: Implement workaround for erratum 859972

Erratum 855972 applies to revision r1p3 or earlier Cortex-A57 CPUs. The
recommended workaround is to disable instruction prefetch.

Change-Id: I56eeac0b753eb1432bd940083372ad6f7e93b16a
Signed-off-by: Eleanor Bonnici <Eleanor.bonnici@arm.com>
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
diff --git a/docs/cpu-specific-build-macros.rst b/docs/cpu-specific-build-macros.rst
index 5738927..6b154f0 100644
--- a/docs/cpu-specific-build-macros.rst
+++ b/docs/cpu-specific-build-macros.rst
@@ -30,7 +30,8 @@
 is for example ``A57`` for the ``Cortex_A57`` CPU.
 
 Refer to the section *CPU errata status reporting* in
-`Firmware Design guide`_ for information on to write errata workaround functions.
+`Firmware Design guide`_ for information on how to write errata workaround
+functions.
 
 All workarounds are disabled by default. The platform is responsible for
 enabling these workarounds according to its requirement by defining the
@@ -98,6 +99,9 @@
 -  ``ERRATA_A57_833471``: This applies errata 833471 workaround to Cortex-A57
    CPU. This needs to be enabled only for revision <= r1p2 of the CPU.
 
+-  ``ERRATA_A57_859972``: This applies errata 859972 workaround to Cortex-A57
+   CPU. This needs to be enabled only for revision <= r1p3 of the CPU.
+
 CPU Specific optimizations
 --------------------------
 
@@ -131,7 +135,7 @@
 
 *Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.*
 
-.. _Cortex-A53 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm048406/index.html
+.. _Cortex-A53 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm048406/Cortex_A53_MPCore_Software_Developers_Errata_Notice.pdf
 .. _Cortex-A57 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm049219/cortex_a57_mpcore_software_developers_errata_notice.pdf
 .. _Firmware Design guide: firmware-design.rst
 .. _Cortex-A57 Software Optimization Guide: http://infocenter.arm.com/help/topic/com.arm.doc.uan0015b/Cortex_A57_Software_Optimization_Guide_external.pdf
diff --git a/include/lib/cpus/aarch32/cortex_a57.h b/include/lib/cpus/aarch32/cortex_a57.h
index d3ae5b9..3fac9c7 100644
--- a/include/lib/cpus/aarch32/cortex_a57.h
+++ b/include/lib/cpus/aarch32/cortex_a57.h
@@ -49,6 +49,7 @@
 #define CORTEX_A57_CPUACTLR_NO_ALLOC_WBWA		(ULL(1) << 49)
 #define CORTEX_A57_CPUACTLR_DCC_AS_DCCI			(ULL(1) << 44)
 #define CORTEX_A57_CPUACTLR_FORCE_FPSCR_FLUSH		(ULL(1) << 38)
+#define CORTEX_A57_CPUACTLR_DIS_INSTR_PREFETCH		(ULL(1) << 32)
 #define CORTEX_A57_CPUACTLR_DIS_STREAMING		(ULL(3) << 27)
 #define CORTEX_A57_CPUACTLR_DIS_L1_STREAMING		(ULL(3) << 25)
 #define CORTEX_A57_CPUACTLR_DIS_INDIRECT_PREDICTOR	(ULL(1) << 4)
diff --git a/include/lib/cpus/aarch64/cortex_a57.h b/include/lib/cpus/aarch64/cortex_a57.h
index 070108d..6c45c06 100644
--- a/include/lib/cpus/aarch64/cortex_a57.h
+++ b/include/lib/cpus/aarch64/cortex_a57.h
@@ -49,6 +49,7 @@
 #define CORTEX_A57_CPUACTLR_EL1_NO_ALLOC_WBWA		(ULL(1) << 49)
 #define CORTEX_A57_CPUACTLR_EL1_DCC_AS_DCCI		(ULL(1) << 44)
 #define CORTEX_A57_CPUACTLR_EL1_FORCE_FPSCR_FLUSH	(ULL(1) << 38)
+#define CORTEX_A57_CPUACTLR_EL1_DIS_INSTR_PREFETCH	(ULL(1) << 32)
 #define CORTEX_A57_CPUACTLR_EL1_DIS_STREAMING		(ULL(3) << 27)
 #define CORTEX_A57_CPUACTLR_EL1_DIS_L1_STREAMING	(ULL(3) << 25)
 #define CORTEX_A57_CPUACTLR_EL1_DIS_INDIRECT_PREDICTOR	(ULL(1) << 4)
diff --git a/lib/cpus/aarch32/cortex_a57.S b/lib/cpus/aarch32/cortex_a57.S
index e4aad79..b5189e7 100644
--- a/lib/cpus/aarch32/cortex_a57.S
+++ b/lib/cpus/aarch32/cortex_a57.S
@@ -306,6 +306,32 @@
 	b	cpu_rev_var_ls
 endfunc check_errata_833471
 
+	/* ---------------------------------------------------
+	 * Errata Workaround for Cortex A57 Errata #859972.
+	 * This applies only to revision <= r1p3 of Cortex A57.
+	 * Inputs:
+	 * r0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: r0-r3
+	 * ---------------------------------------------------
+	 */
+func errata_a57_859972_wa
+	mov		r2, lr
+	bl		check_errata_859972
+	mov		lr, r2
+	cmp		r0, #ERRATA_NOT_APPLIES
+	beq		1f
+	ldcopr16	r0, r1, CORTEX_A57_CPUACTLR
+	orr64_imm	r1, r1, CORTEX_A57_CPUACTLR_DIS_INSTR_PREFETCH
+	stcopr16	r0, r1, CORTEX_A57_CPUACTLR
+1:
+	bx		lr
+endfunc errata_a57_859972_wa
+
+func check_errata_859972
+	mov	r1, #0x13
+	b	cpu_rev_var_ls
+endfunc check_errata_859972
+
 	/* -------------------------------------------------
 	 * The CPU Ops reset function for Cortex-A57.
 	 * Shall clobber: r0-r6
@@ -356,6 +382,11 @@
 	bl	errata_a57_833471_wa
 #endif
 
+#if ERRATA_A57_859972
+	mov	r0, r4
+	bl	errata_a57_859972_wa
+#endif
+
 	/* ---------------------------------------------
 	 * Enable the SMP bit.
 	 * ---------------------------------------------
@@ -487,6 +518,7 @@
 	report_errata ERRATA_A57_828024, cortex_a57, 828024
 	report_errata ERRATA_A57_829520, cortex_a57, 829520
 	report_errata ERRATA_A57_833471, cortex_a57, 833471
+	report_errata ERRATA_A57_859972, cortex_a57, 859972
 
 	pop	{r12, lr}
 	bx	lr
diff --git a/lib/cpus/aarch64/cortex_a57.S b/lib/cpus/aarch64/cortex_a57.S
index 289d0d4..a720e98 100644
--- a/lib/cpus/aarch64/cortex_a57.S
+++ b/lib/cpus/aarch64/cortex_a57.S
@@ -304,6 +304,30 @@
 	b	cpu_rev_var_ls
 endfunc check_errata_833471
 
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex A57 Errata #859972.
+	 * This applies only to revision <= r1p3 of Cortex A57.
+	 * Inputs:
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber:
+	 * --------------------------------------------------
+	 */
+func errata_a57_859972_wa
+	mov	x17, x30
+	bl	check_errata_859972
+	cbz	x0, 1f
+	mrs	x1, CORTEX_A57_CPUACTLR_EL1
+	orr	x1, x1, #CORTEX_A57_CPUACTLR_EL1_DIS_INSTR_PREFETCH
+	msr	CORTEX_A57_CPUACTLR_EL1, x1
+1:
+	ret	x17
+endfunc errata_a57_859972_wa
+
+func check_errata_859972
+	mov	x1, #0x13
+	b	cpu_rev_var_ls
+endfunc check_errata_859972
+
 	/* -------------------------------------------------
 	 * The CPU Ops reset function for Cortex-A57.
 	 * Shall clobber: x0-x19
@@ -354,6 +378,11 @@
 	bl	errata_a57_833471_wa
 #endif
 
+#if ERRATA_A57_859972
+	mov	x0, x18
+	bl	errata_a57_859972_wa
+#endif
+
 	/* ---------------------------------------------
 	 * Enable the SMP bit.
 	 * ---------------------------------------------
@@ -483,6 +512,8 @@
 	report_errata ERRATA_A57_828024, cortex_a57, 828024
 	report_errata ERRATA_A57_829520, cortex_a57, 829520
 	report_errata ERRATA_A57_833471, cortex_a57, 833471
+	report_errata ERRATA_A57_859972, cortex_a57, 859972
+
 
 	ldp	x8, x30, [sp], #16
 	ret
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index ad32971..198a32e 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -91,6 +91,10 @@
 # only to revision <= r1p2 of the Cortex A57 cpu.
 ERRATA_A57_833471	?=0
 
+# Flag to apply erratum 855972 workaround during reset. This erratum applies
+# only to revision <= r1p3 of the Cortex A57 cpu.
+ERRATA_A57_859972	?=0
+
 # Process ERRATA_A53_826319 flag
 $(eval $(call assert_boolean,ERRATA_A53_826319))
 $(eval $(call add_define,ERRATA_A53_826319))
@@ -143,6 +147,10 @@
 $(eval $(call assert_boolean,ERRATA_A57_833471))
 $(eval $(call add_define,ERRATA_A57_833471))
 
+# Process ERRATA_A57_859972 flag
+$(eval $(call assert_boolean,ERRATA_A57_859972))
+$(eval $(call add_define,ERRATA_A57_859972))
+
 # Errata build flags
 ifneq (${ERRATA_A53_843419},0)
 TF_LDFLAGS_aarch64	+= --fix-cortex-a53-843419