Cortex-A72: Implement workaround for erratum 859971

Erratum 855971 applies to revision r0p3 or earlier Cortex-A72 CPUs. The
recommended workaround is to disable instruction prefetch.

Change-Id: I7fde74ee2a8a23b2a8a1891b260f0eb909fad4bf
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 6b154f0..f74b459 100644
--- a/docs/cpu-specific-build-macros.rst
+++ b/docs/cpu-specific-build-macros.rst
@@ -21,6 +21,7 @@
 
 -  `Cortex-A53 MPCore Software Developers Errata Notice`_
 -  `Cortex-A57 MPCore Software Developers Errata Notice`_
+-  `Cortex-A72 MPCore Software Developers Errata Notice`_
 
 The errata workarounds are implemented for a particular revision or a set of
 processor revisions. This is checked by the reset handler at runtime. Each
@@ -102,6 +103,12 @@
 -  ``ERRATA_A57_859972``: This applies errata 859972 workaround to Cortex-A57
    CPU. This needs to be enabled only for revision <= r1p3 of the CPU.
 
+
+For Cortex-A72, following errata build flags are defined :
+
+-  ``ERRATA_A72_859971``: This applies errata 859971 workaround to Cortex-A72
+   CPU. This needs to be enabled only for revision <= r0p3 of the CPU.
+
 CPU Specific optimizations
 --------------------------
 
@@ -137,5 +144,6 @@
 
 .. _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
+.. _Cortex-A72 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm012079/index.html
 .. _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_a72.h b/include/lib/cpus/aarch32/cortex_a72.h
index 306253d..f7da1f0 100644
--- a/include/lib/cpus/aarch32/cortex_a72.h
+++ b/include/lib/cpus/aarch32/cortex_a72.h
@@ -34,6 +34,7 @@
 #define CORTEX_A72_CPUACTLR_DISABLE_L1_DCACHE_HW_PFTCH	(ULL(1) << 56)
 #define CORTEX_A72_CPUACTLR_NO_ALLOC_WBWA		(ULL(1) << 49)
 #define CORTEX_A72_CPUACTLR_DCC_AS_DCCI			(ULL(1) << 44)
+#define CORTEX_A72_CPUACTLR_DIS_INSTR_PREFETCH		(ULL(1) << 32)
 
 /*******************************************************************************
  * L2 Control register specific definitions.
diff --git a/include/lib/cpus/aarch64/cortex_a72.h b/include/lib/cpus/aarch64/cortex_a72.h
index aed714c..6fbb707 100644
--- a/include/lib/cpus/aarch64/cortex_a72.h
+++ b/include/lib/cpus/aarch64/cortex_a72.h
@@ -34,6 +34,7 @@
 #define CORTEX_A72_CPUACTLR_EL1_DISABLE_L1_DCACHE_HW_PFTCH	(ULL(1) << 56)
 #define CORTEX_A72_CPUACTLR_EL1_NO_ALLOC_WBWA			(ULL(1) << 49)
 #define CORTEX_A72_CPUACTLR_EL1_DCC_AS_DCCI			(ULL(1) << 44)
+#define CORTEX_A72_CPUACTLR_EL1_DIS_INSTR_PREFETCH		(ULL(1) << 32)
 
 /*******************************************************************************
  * L2 Control register specific definitions.
diff --git a/lib/cpus/aarch32/cortex_a72.S b/lib/cpus/aarch32/cortex_a72.S
index d164cfd..69cc2ea 100644
--- a/lib/cpus/aarch32/cortex_a72.S
+++ b/lib/cpus/aarch32/cortex_a72.S
@@ -61,11 +61,46 @@
 	bx	lr
 endfunc cortex_a72_disable_ext_debug
 
+	/* ---------------------------------------------------
+	 * Errata Workaround for Cortex A72 Errata #859971.
+	 * This applies only to revision <= r0p3 of Cortex A72.
+	 * Inputs:
+	 * r0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: r0-r3
+	 * ---------------------------------------------------
+	 */
+func errata_a72_859971_wa
+	mov		r2,lr
+	bl		check_errata_859971
+	mov		lr, r2
+	cmp		r0, #ERRATA_NOT_APPLIES
+	beq		1f
+	ldcopr16	r0, r1, CORTEX_A72_CPUACTLR
+	orr64_imm	r1, r1, CORTEX_A72_CPUACTLR_DIS_INSTR_PREFETCH
+	stcopr16	r0, r1, CORTEX_A72_CPUACTLR
+1:
+	bx   		lr
+endfunc errata_a72_859971_wa
+
+func check_errata_859971
+	mov		r1, #0x03
+	b		cpu_rev_var_ls
+endfunc check_errata_859971
+
+
 	/* -------------------------------------------------
 	 * The CPU Ops reset function for Cortex-A72.
 	 * -------------------------------------------------
 	 */
 func cortex_a72_reset_func
+	mov	r5, lr
+	bl	cpu_get_rev_var
+	mov	r4, r0
+
+#if ERRATA_A72_859971
+	mov	r0, r4
+	bl	errata_a72_859971_wa
+#endif
 	/* ---------------------------------------------
 	 * Enable the SMP bit.
 	 * ---------------------------------------------
@@ -186,6 +221,27 @@
 	b	cortex_a72_disable_ext_debug
 endfunc cortex_a72_cluster_pwr_dwn
 
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Cortex A72. Must follow AAPCS.
+ */
+func cortex_a72_errata_report
+	push	{r12, lr}
+
+	bl	cpu_get_rev_var
+	mov	r4, r0
+
+	/*
+	 * Report all errata. The revision-variant information is passed to
+	 * checking functions of each errata.
+	 */
+	report_errata ERRATA_A72_859971, cortex_a72, 859971
+
+	pop	{r12, lr}
+	bx	lr
+endfunc cortex_a72_errata_report
+#endif
+
 declare_cpu_ops cortex_a72, CORTEX_A72_MIDR, \
 	cortex_a72_reset_func, \
 	cortex_a72_core_pwr_dwn, \
diff --git a/lib/cpus/aarch64/cortex_a72.S b/lib/cpus/aarch64/cortex_a72.S
index 5de2bf0..b034125 100644
--- a/lib/cpus/aarch64/cortex_a72.S
+++ b/lib/cpus/aarch64/cortex_a72.S
@@ -73,20 +73,52 @@
 	ret
 endfunc cortex_a72_disable_ext_debug
 
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex A72 Errata #859971.
+	 * This applies only to revision <= r0p3 of Cortex A72.
+	 * Inputs:
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber:
+	 * --------------------------------------------------
+	 */
+func errata_a72_859971_wa
+	mov	x17,x30
+	bl	check_errata_859971
+	cbz	x0, 1f
+	mrs	x1, CORTEX_A72_CPUACTLR_EL1
+	orr	x1, x1, #CORTEX_A72_CPUACTLR_EL1_DIS_INSTR_PREFETCH
+	msr	CORTEX_A72_CPUACTLR_EL1, x1
+1:
+	ret	x17
+endfunc errata_a72_859971_wa
+
+func check_errata_859971
+	mov	x1, #0x03
+	b	cpu_rev_var_ls
+endfunc check_errata_859971
+
 	/* -------------------------------------------------
 	 * The CPU Ops reset function for Cortex-A72.
 	 * -------------------------------------------------
 	 */
 func cortex_a72_reset_func
+	mov	x19, x30
+	bl	cpu_get_rev_var
+	mov	x18, x0
+
+#if ERRATA_A72_859971
+	mov	x0, x18
+	bl	errata_a72_859971_wa
+#endif
 	/* ---------------------------------------------
-	 * As a bare minimum enable the SMP bit.
+	 * Enable the SMP bit.
 	 * ---------------------------------------------
 	 */
 	mrs	x0, CORTEX_A72_ECTLR_EL1
 	orr	x0, x0, #CORTEX_A72_ECTLR_SMP_BIT
 	msr	CORTEX_A72_ECTLR_EL1, x0
 	isb
-	ret
+	ret x19
 endfunc cortex_a72_reset_func
 
 	/* ----------------------------------------------------
@@ -196,6 +228,27 @@
 	b	cortex_a72_disable_ext_debug
 endfunc cortex_a72_cluster_pwr_dwn
 
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Cortex A72. Must follow AAPCS.
+ */
+func cortex_a72_errata_report
+	stp	x8, x30, [sp, #-16]!
+
+	bl	cpu_get_rev_var
+	mov	x8, x0
+
+	/*
+	 * Report all errata. The revision-variant information is passed to
+	 * checking functions of each errata.
+	 */
+	report_errata ERRATA_A72_859971, cortex_a72, 859971
+
+	ldp	x8, x30, [sp], #16
+	ret
+endfunc cortex_a72_errata_report
+#endif
+
 	/* ---------------------------------------------
 	 * This function provides cortex_a72 specific
 	 * register information for crash reporting.
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 198a32e..31adfb4 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -95,6 +95,10 @@
 # only to revision <= r1p3 of the Cortex A57 cpu.
 ERRATA_A57_859972	?=0
 
+# Flag to apply erratum 855971 workaround during reset. This erratum applies
+# only to revision <= r0p3 of the Cortex A72 cpu.
+ERRATA_A72_859971	?=0
+
 # Process ERRATA_A53_826319 flag
 $(eval $(call assert_boolean,ERRATA_A53_826319))
 $(eval $(call add_define,ERRATA_A53_826319))
@@ -151,6 +155,10 @@
 $(eval $(call assert_boolean,ERRATA_A57_859972))
 $(eval $(call add_define,ERRATA_A57_859972))
 
+# Process ERRATA_A72_859971 flag
+$(eval $(call assert_boolean,ERRATA_A72_859971))
+$(eval $(call add_define,ERRATA_A72_859971))
+
 # Errata build flags
 ifneq (${ERRATA_A53_843419},0)
 TF_LDFLAGS_aarch64	+= --fix-cortex-a53-843419