Merge pull request #857 from Andre-ARM/a53-855873

ARM Cortex-A53 erratum 855873 workaround
diff --git a/docs/cpu-specific-build-macros.md b/docs/cpu-specific-build-macros.md
index 0a575f7..eb23bcd 100644
--- a/docs/cpu-specific-build-macros.md
+++ b/docs/cpu-specific-build-macros.md
@@ -60,6 +60,13 @@
      CPU. This needs to be enabled only for revision <= r0p3 of the CPU. From
      r0p4 and onwards, this errata is enabled by default in hardware.
 
+*   `ERRATA_A53_855873`: This applies errata 855873 workaround to Cortex-A53
+     CPUs. Though the erratum is present in every revision of the CPU,
+     this workaround is only applied to CPUs from r0p3 onwards, which feature
+     a chicken bit in CPUACTLR_EL1 to enable a hardware workaround.
+     Earlier revisions of the CPU have other errata which require the same
+     workaround in software, so they should be covered anyway.
+
 For Cortex-A57, following errata build flags are defined :
 
 *   `ERRATA_A57_806969`: This applies errata 806969 workaround to Cortex-A57
diff --git a/include/lib/cpus/aarch64/cortex_a53.h b/include/lib/cpus/aarch64/cortex_a53.h
index 6976b80..484eb63 100644
--- a/include/lib/cpus/aarch64/cortex_a53.h
+++ b/include/lib/cpus/aarch64/cortex_a53.h
@@ -67,6 +67,7 @@
 #define CPUACTLR_EL1			S3_1_C15_C2_0	/* Instruction def. */
 
 #define CPUACTLR_DTAH			(1 << 24)
+#define CPUACTLR_ENDCCASCI		(1 << 44)
 
 /*******************************************************************************
  * L2 Auxiliary Control register specific definitions.
diff --git a/lib/cpus/aarch64/cortex_a53.S b/lib/cpus/aarch64/cortex_a53.S
index 1dd8a86..a36666b 100644
--- a/lib/cpus/aarch64/cortex_a53.S
+++ b/lib/cpus/aarch64/cortex_a53.S
@@ -129,6 +129,39 @@
 	b	cpu_rev_var_ls
 endfunc check_errata_disable_non_temporal_hint
 
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex A53 Errata #855873.
+	 *
+	 * This applies only to revisions >= r0p3 of Cortex A53.
+	 * Earlier revisions of the core are affected as well, but don't
+	 * have the chicken bit in the CPUACTLR register. It is expected that
+	 * the rich OS takes care of that, especially as the workaround is
+	 * shared with other erratas in those revisions of the CPU.
+	 * Inputs:
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x17
+	 * --------------------------------------------------
+	 */
+func errata_a53_855873_wa
+	/*
+	 * Compare x0 against revision r0p3 and higher
+	 */
+        mov     x17, x30
+        bl      check_errata_855873
+        cbz     x0, 1f
+
+	mrs	x1, CPUACTLR_EL1
+	orr	x1, x1, #CPUACTLR_ENDCCASCI
+	msr	CPUACTLR_EL1, x1
+1:
+	ret	x17
+endfunc errata_a53_855873_wa
+
+func check_errata_855873
+	mov	x1, #0x03
+	b	cpu_rev_var_hs
+endfunc check_errata_855873
+
 	/* -------------------------------------------------
 	 * The CPU Ops reset function for Cortex-A53.
 	 * Shall clobber: x0-x19
@@ -150,6 +183,11 @@
 	bl	a53_disable_non_temporal_hint
 #endif
 
+#if ERRATA_A53_855873
+	mov	x0, x18
+	bl	errata_a53_855873_wa
+#endif
+
 	/* ---------------------------------------------
 	 * Enable the SMP bit.
 	 * ---------------------------------------------
@@ -238,6 +276,7 @@
 	 */
 	report_errata ERRATA_A53_826319, cortex_a53, 826319
 	report_errata ERRATA_A53_836870, cortex_a53, disable_non_temporal_hint
+	report_errata ERRATA_A53_855873, cortex_a53, 855873
 
 	ldp	x8, x30, [sp], #16
 	ret
@@ -255,13 +294,15 @@
 	 */
 .section .rodata.cortex_a53_regs, "aS"
 cortex_a53_regs:  /* The ascii list of register names to be reported */
-	.asciz	"cpuectlr_el1", "cpumerrsr_el1", "l2merrsr_el1", ""
+	.asciz	"cpuectlr_el1", "cpumerrsr_el1", "l2merrsr_el1", \
+		"cpuactlr_el1", ""
 
 func cortex_a53_cpu_reg_dump
 	adr	x6, cortex_a53_regs
 	mrs	x8, CPUECTLR_EL1
 	mrs	x9, CPUMERRSR_EL1
 	mrs	x10, L2MERRSR_EL1
+	mrs	x11, CPUACTLR_EL1
 	ret
 endfunc cortex_a53_cpu_reg_dump
 
diff --git a/lib/cpus/aarch64/cpu_helpers.S b/lib/cpus/aarch64/cpu_helpers.S
index 6a3669d..47cb6a2 100644
--- a/lib/cpus/aarch64/cpu_helpers.S
+++ b/lib/cpus/aarch64/cpu_helpers.S
@@ -234,6 +234,20 @@
 	ret
 endfunc cpu_rev_var_ls
 
+/*
+ * Compare the CPU's revision-variant (x0) with a given value (x1), for errata
+ * application purposes. If the revision-variant is higher than or same as a
+ * given value, indicates that errata applies; otherwise not.
+ */
+	.globl	cpu_rev_var_hs
+func cpu_rev_var_hs
+	mov	x2, #ERRATA_APPLIES
+	mov	x3, #ERRATA_NOT_APPLIES
+	cmp	x0, x1
+	csel	x0, x2, x3, hs
+	ret
+endfunc cpu_rev_var_hs
+
 #if REPORT_ERRATA
 /*
  * void print_errata_status(void);
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 7d7db20..132ab6f 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -66,6 +66,12 @@
 # erratum workaround is enabled by default in hardware.
 ERRATA_A53_836870	?=0
 
+# Flag to apply errata 855873 during reset. This errata applies to all
+# revisions of the Cortex A53 CPU, but this firmware workaround only works
+# for revisions r0p3 and higher. Earlier revisions are taken care
+# of by the rich OS.
+ERRATA_A53_855873	?=0
+
 # Flag to apply erratum 806969 workaround during reset. This erratum applies
 # only to revision r0p0 of the Cortex A57 cpu.
 ERRATA_A57_806969	?=0
@@ -106,6 +112,10 @@
 $(eval $(call assert_boolean,ERRATA_A53_836870))
 $(eval $(call add_define,ERRATA_A53_836870))
 
+# Process ERRATA_A53_855873 flag
+$(eval $(call assert_boolean,ERRATA_A53_855873))
+$(eval $(call add_define,ERRATA_A53_855873))
+
 # Process ERRATA_A57_806969 flag
 $(eval $(call assert_boolean,ERRATA_A57_806969))
 $(eval $(call add_define,ERRATA_A57_806969))
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index 5ba1698..7571582 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -67,7 +67,8 @@
 				${JUNO_INTERCONNECT_SOURCES}		\
 				${JUNO_SECURITY_SOURCES}
 
-# Enable workarounds for selected Cortex-A57 erratas.
+# Enable workarounds for selected Cortex-A53 and A57 erratas.
+ERRATA_A53_855873		:=	1
 ERRATA_A57_806969		:=	0
 ERRATA_A57_813419		:=	1
 ERRATA_A57_813420		:=	1
diff --git a/plat/mediatek/mt8173/platform.mk b/plat/mediatek/mt8173/platform.mk
index e59125a..9583efe 100644
--- a/plat/mediatek/mt8173/platform.mk
+++ b/plat/mediatek/mt8173/platform.mk
@@ -90,6 +90,7 @@
 # Enable workarounds for selected Cortex-A53 erratas.
 ERRATA_A53_826319	:=	1
 ERRATA_A53_836870	:=	1
+ERRATA_A53_855873	:=	1
 
 # indicate the reset vector address can be programmed
 PROGRAMMABLE_RESET_ADDRESS	:=	1
diff --git a/plat/nvidia/tegra/soc/t210/platform_t210.mk b/plat/nvidia/tegra/soc/t210/platform_t210.mk
index 822240f..8946869 100644
--- a/plat/nvidia/tegra/soc/t210/platform_t210.mk
+++ b/plat/nvidia/tegra/soc/t210/platform_t210.mk
@@ -66,3 +66,4 @@
 A53_DISABLE_NON_TEMPORAL_HINT	:=	1
 ERRATA_A53_826319		:=	1
 ERRATA_A53_836870		:=	1
+ERRATA_A53_855873		:=	1