fix(cpus): workaround for Neoverse N2 erratum 2009478
Neoverse N2 erratum 2009478 is a Cat B erratum that applies to
revision r0p0 and is fixed in r0p1. The workaround is to clear
the ED bit for all core error records before setting the PWRDN_EN
bit in CPUPWRCTLR_EL1 to request a power down.
SDEN documentation:
https://developer.arm.com/documentation/SDEN1982442/latest
Signed-off-by: Bipin Ravi <bipin.ravi@arm.com>
Change-Id: Ic5ef58c9e795b90026af1d2b09edc0eea3ceee51
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index bb12d7d..c1a3cb7 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -603,6 +603,9 @@
- ``ERRATA_N2_2002655``: This applies errata 2002655 workaround to Neoverse-N2
CPU. This needs to be enabled for revision r0p0 of the CPU and is fixed in r0p1.
+- ``ERRATA_N2_2009478``: This applies errata 2009478 workaround to Neoverse-N2
+ CPU. This needs to be enabled for revision r0p0 of the CPU and is fixed in r0p1.
+
- ``ERRATA_N2_2067956``: This applies errata 2067956 workaround to Neoverse-N2
CPU. This needs to be enabled for revision r0p0 of the CPU and is fixed in r0p1.
diff --git a/lib/cpus/aarch64/neoverse_n2.S b/lib/cpus/aarch64/neoverse_n2.S
index acf8dee..ead3908 100644
--- a/lib/cpus/aarch64/neoverse_n2.S
+++ b/lib/cpus/aarch64/neoverse_n2.S
@@ -68,6 +68,22 @@
check_erratum_ls neoverse_n2, ERRATUM(2067956), CPU_REV(0, 0)
+workaround_runtime_start neoverse_n2, ERRATUM(2009478), ERRATA_N2_2009478
+ /* Stash ERRSELR_EL1 in x2 */
+ mrs x2, ERRSELR_EL1
+
+ /* Select error record 0 and clear ED bit */
+ msr ERRSELR_EL1, xzr
+ mrs x1, ERXCTLR_EL1
+ bfi x1, xzr, #ERXCTLR_ED_SHIFT, #1
+ msr ERXCTLR_EL1, x1
+
+ /* Restore ERRSELR_EL1 from x2 */
+ msr ERRSELR_EL1, x2
+workaround_runtime_end neoverse_n2, ERRATUM(2009478), NO_ISB
+
+check_erratum_ls neoverse_n2, ERRATUM(2009478), CPU_REV(0, 0)
+
workaround_reset_start neoverse_n2, ERRATUM(2138953), ERRATA_N2_2138953
/* Apply instruction patching sequence */
mrs x1, NEOVERSE_N2_CPUECTLR2_EL1
@@ -233,7 +249,9 @@
func neoverse_n2_core_pwr_dwn
- apply_erratum neoverse_n2, ERRATUM(2326639), ERRATA_N2_2326639
+ apply_erratum neoverse_n2, ERRATUM(2009478), ERRATA_N2_2009478
+ apply_erratum neoverse_n2, ERRATUM(2326639), ERRATA_N2_2326639, NO_GET_CPU_REV
+
/* ---------------------------------------------------
* Enable CPU power down bit in power control register
* No need to do cache maintenance here.
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 8df0a29..88ef8a7 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -615,6 +615,10 @@
# to revisions r0p0 of the Neoverse-N2 cpu and is fixed in r0p1.
CPU_FLAG_LIST += ERRATA_N2_2002655
+# Flag to apply erratum 2009478 workaround during powerdown. This erratum
+# applies to revision r0p0 of the Neoverse N2 cpu, it is fixed in r0p1.
+CPU_FLAG_LIST += ERRATA_N2_2009478
+
# Flag to apply erratum 2067956 workaround during reset. This erratum applies
# to revision r0p0 of the Neoverse N2 cpu and is fixed in r0p1.
CPU_FLAG_LIST += ERRATA_N2_2067956
diff --git a/services/std_svc/errata_abi/errata_abi_main.c b/services/std_svc/errata_abi/errata_abi_main.c
index 71a907b..5593516 100644
--- a/services/std_svc/errata_abi/errata_abi_main.c
+++ b/services/std_svc/errata_abi/errata_abi_main.c
@@ -332,24 +332,25 @@
.cpu_partnumber = NEOVERSE_N2_MIDR,
.cpu_errata_list = {
[0] = {2002655, 0x00, 0x00, ERRATA_N2_2002655},
- [1] = {2025414, 0x00, 0x00, ERRATA_N2_2025414},
- [2] = {2067956, 0x00, 0x00, ERRATA_N2_2067956},
- [3] = {2138953, 0x00, 0x00, ERRATA_N2_2138953},
- [4] = {2138956, 0x00, 0x00, ERRATA_N2_2138956},
- [5] = {2138958, 0x00, 0x00, ERRATA_N2_2138958},
- [6] = {2189731, 0x00, 0x00, ERRATA_N2_2189731},
- [7] = {2242400, 0x00, 0x00, ERRATA_N2_2242400},
- [8] = {2242415, 0x00, 0x00, ERRATA_N2_2242415},
- [9] = {2280757, 0x00, 0x00, ERRATA_N2_2280757},
- [10] = {2326639, 0x00, 0x00, ERRATA_N2_2326639},
- [11] = {2376738, 0x00, 0x00, ERRATA_N2_2376738},
- [12] = {2388450, 0x00, 0x00, ERRATA_N2_2388450},
- [13] = {2728475, 0x00, 0x02, ERRATA_N2_2728475, \
+ [1] = {2009478, 0x00, 0x00, ERRATA_N2_2009478},
+ [2] = {2025414, 0x00, 0x00, ERRATA_N2_2025414},
+ [3] = {2067956, 0x00, 0x00, ERRATA_N2_2067956},
+ [4] = {2138953, 0x00, 0x00, ERRATA_N2_2138953},
+ [5] = {2138956, 0x00, 0x00, ERRATA_N2_2138956},
+ [6] = {2138958, 0x00, 0x00, ERRATA_N2_2138958},
+ [7] = {2189731, 0x00, 0x00, ERRATA_N2_2189731},
+ [8] = {2242400, 0x00, 0x00, ERRATA_N2_2242400},
+ [9] = {2242415, 0x00, 0x00, ERRATA_N2_2242415},
+ [10] = {2280757, 0x00, 0x00, ERRATA_N2_2280757},
+ [11] = {2326639, 0x00, 0x00, ERRATA_N2_2326639},
+ [12] = {2376738, 0x00, 0x00, ERRATA_N2_2376738},
+ [13] = {2388450, 0x00, 0x00, ERRATA_N2_2388450},
+ [14] = {2728475, 0x00, 0x02, ERRATA_N2_2728475, \
ERRATA_NON_ARM_INTERCONNECT},
- [14] = {2743014, 0x00, 0x02, ERRATA_N2_2743014},
- [15] = {2743089, 0x00, 0x02, ERRATA_N2_2743089},
- [16] = {2779511, 0x00, 0x02, ERRATA_N2_2779511},
- [17 ... ERRATA_LIST_END] = UNDEF_ERRATA,
+ [15] = {2743014, 0x00, 0x02, ERRATA_N2_2743014},
+ [16] = {2743089, 0x00, 0x02, ERRATA_N2_2743089},
+ [17] = {2779511, 0x00, 0x02, ERRATA_N2_2779511},
+ [18 ... ERRATA_LIST_END] = UNDEF_ERRATA,
}
},
#endif /* NEOVERSE_N2_H_INC */