Workaround for Hercules erratum 1688305
Erratum 1688305 is a Cat B erratum present in r0p0, r0p1 versions
of Hercules core. The erratum can be avoided by setting bit 1 of the
implementation defined register CPUACTLR2_EL1 to 1 to prevent store-
release from being dispatched before it is the oldest.
Change-Id: I2ac04f5d9423868b6cdd4ceb3d0ffa46e570efed
Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index 891703b..7fa027f 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -227,6 +227,12 @@
- ``ERRATA_A76_1275112``: This applies errata 1275112 workaround to Cortex-A76
CPU. This needs to be enabled only for revision <= r3p0 of the CPU.
+For Hercules, the following errata build flags are defined :
+
+- ``ERRATA_HERCULES_1688305``: This applies errata 1688305 workaround to
+ Hercules CPU. This needs to be enabled only for revision r0p0 - r1p0 of
+ the CPU.
+
For Neoverse N1, the following errata build flags are defined :
- ``ERRATA_N1_1073348``: This applies errata 1073348 workaround to Neoverse-N1
diff --git a/include/lib/cpus/aarch64/cortex_hercules.h b/include/lib/cpus/aarch64/cortex_hercules.h
index b943e7a..d5ca85e 100644
--- a/include/lib/cpus/aarch64/cortex_hercules.h
+++ b/include/lib/cpus/aarch64/cortex_hercules.h
@@ -27,6 +27,9 @@
******************************************************************************/
#define CORTEX_HERCULES_ACTLR_TAM_BIT (ULL(1) << 30)
+#define CORTEX_HERCULES_ACTLR2_EL1 S3_0_C15_C1_1
+#define CORTEX_HERCULES_ACTLR2_EL1_BIT_1 (ULL(1) << 1)
+
/*******************************************************************************
* CPU Activity Monitor Unit register specific definitions.
******************************************************************************/
diff --git a/lib/cpus/aarch64/cortex_hercules.S b/lib/cpus/aarch64/cortex_hercules.S
index 4e04814..a239196 100644
--- a/lib/cpus/aarch64/cortex_hercules.S
+++ b/lib/cpus/aarch64/cortex_hercules.S
@@ -16,12 +16,49 @@
#error "cortex_hercules must be compiled with HW_ASSISTED_COHERENCY enabled"
#endif
+
+/* --------------------------------------------------
+ * Errata Workaround for Hercules Erratum 1688305.
+ * This applies to revision r0p0 and r1p0 of Hercules.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_hercules_1688305_wa
+ /* Compare x0 against revision r1p0 */
+ mov x17, x30
+ bl check_errata_1688305
+ cbz x0, 1f
+ mrs x1, CORTEX_HERCULES_ACTLR2_EL1
+ orr x1, x1, CORTEX_HERCULES_ACTLR2_EL1_BIT_1
+ msr CORTEX_HERCULES_ACTLR2_EL1, x1
+ isb
+1:
+ ret x17
+endfunc errata_hercules_1688305_wa
+
+func check_errata_1688305
+ /* Applies to r0p0 and r1p0 */
+ mov x1, #0x10
+ b cpu_rev_var_ls
+endfunc check_errata_1688305
+
/* -------------------------------------------------
* The CPU Ops reset function for Cortex-Hercules
* -------------------------------------------------
*/
-#if ENABLE_AMU
func cortex_hercules_reset_func
+ mov x19, x30
+ bl cpu_get_rev_var
+ mov x18, x0
+
+#if ERRATA_HERCULES_1688305
+ mov x0, x18
+ bl errata_hercules_1688305_wa
+#endif
+
+#if ENABLE_AMU
/* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */
mrs x0, actlr_el3
bic x0, x0, #CORTEX_HERCULES_ACTLR_TAM_BIT
@@ -39,11 +76,11 @@
/* Enable group1 counters */
mov x0, #CORTEX_HERCULES_AMU_GROUP1_MASK
msr CPUAMCNTENSET1_EL0, x0
- isb
+#endif
- ret
+ isb
+ ret x19
endfunc cortex_hercules_reset_func
-#endif
/* ---------------------------------------------
* HW will do the cache maintenance while powering down
@@ -66,6 +103,18 @@
*/
#if REPORT_ERRATA
func cortex_hercules_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_HERCULES_1688305, cortex_hercules, 1688305
+
+ ldp x8, x30, [sp], #16
ret
endfunc cortex_hercules_errata_report
#endif
@@ -89,12 +138,6 @@
ret
endfunc cortex_hercules_cpu_reg_dump
-#if ENABLE_AMU
-#define HERCULES_RESET_FUNC cortex_hercules_reset_func
-#else
-#define HERCULES_RESET_FUNC CPU_NO_RESET_FUNC
-#endif
-
declare_cpu_ops cortex_hercules, CORTEX_HERCULES_MIDR, \
- HERCULES_RESET_FUNC, \
+ cortex_hercules_reset_func, \
cortex_hercules_core_pwr_dwn
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 078888e..c9b9b38 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -234,6 +234,10 @@
# only to revision <= r3p0 of the Cortex A76 cpu.
ERRATA_A76_1286807 ?=0
+# Flag to apply erratum 1688305 workaround during reset. This erratum applies
+# to revisions r0p0 - r1p0 of the Hercules cpu.
+ERRATA_HERCULES_1688305 ?=0
+
# Flag to apply T32 CLREX workaround during reset. This erratum applies
# only to r0p0 and r1p0 of the Neoverse N1 cpu.
ERRATA_N1_1043202 ?=1
@@ -467,6 +471,10 @@
$(eval $(call assert_boolean,ERRATA_A76_1286807))
$(eval $(call add_define,ERRATA_A76_1286807))
+# Process ERRATA_HERCULES_1688305 flag
+$(eval $(call assert_boolean,ERRATA_HERCULES_1688305))
+$(eval $(call add_define,ERRATA_HERCULES_1688305))
+
# Process ERRATA_N1_1043202 flag
$(eval $(call assert_boolean,ERRATA_N1_1043202))
$(eval $(call add_define,ERRATA_N1_1043202))