summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authordanh-arm <dan.handley@arm.com>2014-10-30 16:04:42 +0000
committerdanh-arm <dan.handley@arm.com>2014-10-30 16:04:42 +0000
commit82b9b2973b108e91367159f2f42dec2fc45f168d (patch)
tree13a011a9857ba598ccb96563b4b33919bb491b96 /lib
parent0f4b06347b4c2a5d018e085f7102fd3cc10ffa88 (diff)
parent5541bb3f61ae97b49203939f940931455b2f3037 (diff)
Merge pull request #218 from soby-mathew/sm/add_cpu_ops_warning
Add level specific cache operations and changes to errata workaround mechanism
Diffstat (limited to 'lib')
-rw-r--r--lib/aarch64/cache_helpers.S48
-rw-r--r--lib/cpus/aarch64/cortex_a53.S15
-rw-r--r--lib/cpus/aarch64/cortex_a57.S118
-rw-r--r--lib/cpus/aarch64/cpu_helpers.S33
-rw-r--r--lib/cpus/cpu-ops.mk (renamed from lib/cpus/cpu-errata.mk)9
5 files changed, 187 insertions, 36 deletions
diff --git a/lib/aarch64/cache_helpers.S b/lib/aarch64/cache_helpers.S
index 1c805504..dc601021 100644
--- a/lib/aarch64/cache_helpers.S
+++ b/lib/aarch64/cache_helpers.S
@@ -35,6 +35,9 @@
.globl inv_dcache_range
.globl dcsw_op_louis
.globl dcsw_op_all
+ .globl dcsw_op_level1
+ .globl dcsw_op_level2
+ .globl dcsw_op_level3
/* ------------------------------------------
* Clean+Invalidate from base address till
@@ -81,6 +84,7 @@ inv_loop:
* x0: The operation type (0-2), as defined in arch.h
* x3: The last cache level to operate on
* x9: clidr_el1
+ * x10: The cache level to begin operation from
* and will carry out the operation on each data cache from level 0
* to the level in x3 in sequence
*
@@ -93,12 +97,12 @@ inv_loop:
mrs x9, clidr_el1
ubfx x3, x9, \shift, \fw
lsl x3, x3, \ls
+ mov x10, xzr
b do_dcsw_op
.endm
func do_dcsw_op
cbz x3, exit
- mov x10, xzr
adr x14, dcsw_loop_table // compute inner loop address
add x14, x14, x0, lsl #5 // inner loop is 8x32-bit instructions
mov x0, x9
@@ -163,3 +167,45 @@ func dcsw_op_louis
func dcsw_op_all
dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
+
+ /* ---------------------------------------------------------------
+ * Helper macro for data cache operations by set/way for the
+ * level specified
+ * ---------------------------------------------------------------
+ */
+ .macro dcsw_op_level level
+ mrs x9, clidr_el1
+ mov x3, \level
+ sub x10, x3, #2
+ b do_dcsw_op
+ .endm
+
+ /* ---------------------------------------------------------------
+ * Data cache operations by set/way for level 1 cache
+ *
+ * The main function, do_dcsw_op requires:
+ * x0: The operation type (0-2), as defined in arch.h
+ * ---------------------------------------------------------------
+ */
+func dcsw_op_level1
+ dcsw_op_level #(1 << LEVEL_SHIFT)
+
+ /* ---------------------------------------------------------------
+ * Data cache operations by set/way for level 2 cache
+ *
+ * The main function, do_dcsw_op requires:
+ * x0: The operation type (0-2), as defined in arch.h
+ * ---------------------------------------------------------------
+ */
+func dcsw_op_level2
+ dcsw_op_level #(2 << LEVEL_SHIFT)
+
+ /* ---------------------------------------------------------------
+ * Data cache operations by set/way for level 3 cache
+ *
+ * The main function, do_dcsw_op requires:
+ * x0: The operation type (0-2), as defined in arch.h
+ * ---------------------------------------------------------------
+ */
+func dcsw_op_level3
+ dcsw_op_level #(3 << LEVEL_SHIFT)
diff --git a/lib/cpus/aarch64/cortex_a53.S b/lib/cpus/aarch64/cortex_a53.S
index 722ce7af..ec184641 100644
--- a/lib/cpus/aarch64/cortex_a53.S
+++ b/lib/cpus/aarch64/cortex_a53.S
@@ -77,11 +77,11 @@ func cortex_a53_core_pwr_dwn
bl cortex_a53_disable_dcache
/* ---------------------------------------------
- * Flush L1 cache to PoU.
+ * Flush L1 caches.
* ---------------------------------------------
*/
mov x0, #DCCISW
- bl dcsw_op_louis
+ bl dcsw_op_level1
/* ---------------------------------------------
* Come out of intra cluster coherency
@@ -100,17 +100,24 @@ func cortex_a53_cluster_pwr_dwn
bl cortex_a53_disable_dcache
/* ---------------------------------------------
+ * Flush L1 caches.
+ * ---------------------------------------------
+ */
+ mov x0, #DCCISW
+ bl dcsw_op_level1
+
+ /* ---------------------------------------------
* Disable the optional ACP.
* ---------------------------------------------
*/
bl plat_disable_acp
/* ---------------------------------------------
- * Flush L1 and L2 caches to PoC.
+ * Flush L2 caches.
* ---------------------------------------------
*/
mov x0, #DCCISW
- bl dcsw_op_all
+ bl dcsw_op_level2
/* ---------------------------------------------
* Come out of intra cluster coherency
diff --git a/lib/cpus/aarch64/cortex_a57.S b/lib/cpus/aarch64/cortex_a57.S
index eed1bbb9..dab16d7e 100644
--- a/lib/cpus/aarch64/cortex_a57.S
+++ b/lib/cpus/aarch64/cortex_a57.S
@@ -57,7 +57,7 @@ func cortex_a57_disable_l2_prefetch
bic x0, x0, x1
msr CPUECTLR_EL1, x0
isb
- dsb sy
+ dsb ish
ret
/* ---------------------------------------------
@@ -81,33 +81,79 @@ func cortex_a57_disable_ext_debug
dsb sy
ret
-func cortex_a57_reset_func
-#if ERRATA_A57_806969 || ERRATA_A57_813420
- /* ---------------------------------------------
- * Ensure that the following errata is only
- * applied on r0p0 parts.
- * ---------------------------------------------
+ /* --------------------------------------------------
+ * Errata Workaround for Cortex A57 Errata #806969.
+ * This applies only to revision r0p0 of Cortex A57.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * --------------------------------------------------
*/
-#if ASM_ASSERTION
- mrs x0, midr_el1
- ubfx x1, x0, #MIDR_VAR_SHIFT, #4
- ubfx x2, x0, #MIDR_REV_SHIFT, #4
- orr x0, x1, x2
- cmp x0, #0
- ASM_ASSERT(eq)
+func errata_a57_806969_wa
+ /*
+ * Compare x0 against revision r0p0
+ */
+ cbz x0, apply_806969
+#if DEBUG
+ b print_revision_warning
+#else
+ ret
#endif
- mov x1, xzr
-#if ERRATA_A57_806969
+apply_806969:
+ mrs x1, CPUACTLR_EL1
orr x1, x1, #CPUACTLR_NO_ALLOC_WBWA
+ msr CPUACTLR_EL1, x1
+ ret
+
+
+ /* ---------------------------------------------------
+ * Errata Workaround for Cortex A57 Errata #813420.
+ * This applies only to revision r0p0 of Cortex A57.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * ---------------------------------------------------
+ */
+func errata_a57_813420_wa
+ /*
+ * Compare x0 against revision r0p0
+ */
+ cbz x0, apply_813420
+#if DEBUG
+ b print_revision_warning
+#else
+ ret
#endif
-#if ERRATA_A57_813420
+apply_813420:
+ mrs x1, CPUACTLR_EL1
orr x1, x1, #CPUACTLR_DCC_AS_DCCI
-#endif
- mrs x0, CPUACTLR_EL1
- orr x0, x0, x1
- msr CPUACTLR_EL1, x0
+ msr CPUACTLR_EL1, x1
+ ret
+
+ /* -------------------------------------------------
+ * The CPU Ops reset function for Cortex-A57.
+ * -------------------------------------------------
+ */
+func cortex_a57_reset_func
+ mov x19, x30
+ mrs x0, midr_el1
+
+ /*
+ * Extract the variant[20:23] and revision[0:3] from x0
+ * and pack it in x20[0:7] as variant[4:7] and revision[0:3].
+ * First extract x0[16:23] to x20[0:7] and zero fill the rest.
+ * Then extract x0[0:3] into x20[0:3] retaining other bits.
+ */
+ ubfx x20, x0, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), #(MIDR_REV_BITS + MIDR_VAR_BITS)
+ bfxil x20, x0, #MIDR_REV_SHIFT, #MIDR_REV_BITS
+
+#if ERRATA_A57_806969
+ mov x0, x20
+ bl errata_a57_806969_wa
#endif
+#if ERRATA_A57_813420
+ mov x0, x20
+ bl errata_a57_813420_wa
+#endif
/* ---------------------------------------------
* As a bare minimum enable the SMP bit.
* ---------------------------------------------
@@ -116,8 +162,12 @@ func cortex_a57_reset_func
orr x0, x0, #CPUECTLR_SMP_BIT
msr CPUECTLR_EL1, x0
isb
- ret
+ ret x19
+ /* ----------------------------------------------------
+ * The CPU Ops core power down function for Cortex-A57.
+ * ----------------------------------------------------
+ */
func cortex_a57_core_pwr_dwn
mov x18, x30
@@ -134,11 +184,11 @@ func cortex_a57_core_pwr_dwn
bl cortex_a57_disable_l2_prefetch
/* ---------------------------------------------
- * Flush L1 cache to PoU.
+ * Flush L1 caches.
* ---------------------------------------------
*/
mov x0, #DCCISW
- bl dcsw_op_louis
+ bl dcsw_op_level1
/* ---------------------------------------------
* Come out of intra cluster coherency
@@ -153,6 +203,10 @@ func cortex_a57_core_pwr_dwn
mov x30, x18
b cortex_a57_disable_ext_debug
+ /* -------------------------------------------------------
+ * The CPU Ops cluster power down function for Cortex-A57.
+ * -------------------------------------------------------
+ */
func cortex_a57_cluster_pwr_dwn
mov x18, x30
@@ -168,18 +222,26 @@ func cortex_a57_cluster_pwr_dwn
*/
bl cortex_a57_disable_l2_prefetch
+#if !SKIP_A57_L1_FLUSH_PWR_DWN
+ /* -------------------------------------------------
+ * Flush the L1 caches.
+ * -------------------------------------------------
+ */
+ mov x0, #DCCISW
+ bl dcsw_op_level1
+#endif
/* ---------------------------------------------
* Disable the optional ACP.
* ---------------------------------------------
*/
bl plat_disable_acp
- /* ---------------------------------------------
- * Flush L1 and L2 caches to PoC.
- * ---------------------------------------------
+ /* -------------------------------------------------
+ * Flush the L2 caches.
+ * -------------------------------------------------
*/
mov x0, #DCCISW
- bl dcsw_op_all
+ bl dcsw_op_level2
/* ---------------------------------------------
* Come out of intra cluster coherency
diff --git a/lib/cpus/aarch64/cpu_helpers.S b/lib/cpus/aarch64/cpu_helpers.S
index 46584b3f..f053d44f 100644
--- a/lib/cpus/aarch64/cpu_helpers.S
+++ b/lib/cpus/aarch64/cpu_helpers.S
@@ -45,7 +45,7 @@
*/
.globl reset_handler
func reset_handler
- mov x10, x30
+ mov x19, x30
bl plat_reset_handler
@@ -58,10 +58,11 @@ func reset_handler
/* Get the cpu_ops reset handler */
ldr x2, [x0, #CPU_RESET_FUNC]
+ mov x30, x19
cbz x2, 1f
- blr x2
+ br x2
1:
- ret x10
+ ret
#endif /* IMAGE_BL1 || (IMAGE_BL31 && RESET_TO_BL31) */
@@ -191,3 +192,29 @@ func get_cpu_ops_ptr
sub x0, x4, #(CPU_OPS_SIZE + CPU_MIDR)
error_exit:
ret
+
+#if DEBUG
+ /*
+ * This function prints a warning message to the crash console
+ * if the CPU revision/part number does not match the errata
+ * workaround enabled in the build.
+ * Clobber: x30, x0 - x5
+ */
+.section .rodata.rev_warn_str, "aS"
+rev_warn_str:
+ .asciz "Warning: Skipping Errata workaround for non matching CPU revision number.\n"
+
+ .globl print_revision_warning
+func print_revision_warning
+ mov x5, x30
+ /* Ensure the console is initialized */
+ bl plat_crash_console_init
+ /* Check if the console is initialized */
+ cbz x0, 1f
+ /* The console is initialized */
+ adr x4, rev_warn_str
+ bl asm_print_str
+1:
+ ret x5
+#endif
+
diff --git a/lib/cpus/cpu-errata.mk b/lib/cpus/cpu-ops.mk
index 79f0156d..1c5512e9 100644
--- a/lib/cpus/cpu-errata.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -28,6 +28,15 @@
# POSSIBILITY OF SUCH DAMAGE.
#
+# Cortex A57 specific optimisation to skip L1 cache flush when
+# cluster is powered down.
+SKIP_A57_L1_FLUSH_PWR_DWN ?=0
+
+# Process SKIP_A57_L1_FLUSH_PWR_DWN flag
+$(eval $(call assert_boolean,SKIP_A57_L1_FLUSH_PWR_DWN))
+$(eval $(call add_define,SKIP_A57_L1_FLUSH_PWR_DWN))
+
+
# CPU Errata Build flags. These should be enabled by the
# platform if the errata needs to be applied.