From 74bfe31fd2c992d8e1e13bf396a9d5c136967ca5 Mon Sep 17 00:00:00 2001 From: Bipin Ravi Date: Tue, 29 Aug 2023 13:59:09 -0500 Subject: [PATCH] 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 Change-Id: Ic5ef58c9e795b90026af1d2b09edc0eea3ceee51 --- docs/design/cpu-specific-build-macros.rst | 3 ++ lib/cpus/aarch64/neoverse_n2.S | 20 ++++++++++- lib/cpus/cpu-ops.mk | 4 +++ services/std_svc/errata_abi/errata_abi_main.c | 35 ++++++++++--------- 4 files changed, 44 insertions(+), 18 deletions(-) diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst index bb12d7d31..c1a3cb727 100644 --- a/docs/design/cpu-specific-build-macros.rst +++ b/docs/design/cpu-specific-build-macros.rst @@ -603,6 +603,9 @@ For Neoverse N2, the following errata build flags are defined : - ``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 acf8deeb5..ead390800 100644 --- a/lib/cpus/aarch64/neoverse_n2.S +++ b/lib/cpus/aarch64/neoverse_n2.S @@ -68,6 +68,22 @@ workaround_reset_end neoverse_n2, ERRATUM(2067956) 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 @@ cpu_reset_func_end neoverse_n2 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 8df0a29c5..88ef8a7f1 100644 --- a/lib/cpus/cpu-ops.mk +++ b/lib/cpus/cpu-ops.mk @@ -615,6 +615,10 @@ CPU_FLAG_LIST += ERRATA_A710_2768515 # 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 71a907b75..559351679 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 @@ struct em_cpu_list cpu_list[] = { .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 */