From 7986faba21f29b50341f8357baf38481dae0e58f Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 16 Oct 2015 09:57:19 +0200 Subject: [PATCH] armv7a: add d-cache virtual address range flush function This patch adds a function for cleaning & invalidating a virtual address range from the architecture caches down to the point of coherence. Change-Id: I4061ab023a3797fabc967f3a34498034841d52c6 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3026 Reviewed-by: Paul Fertser Tested-by: jenkins --- src/target/armv7a_cache.c | 35 +++++++++++++++++++++++++++++++++++ src/target/armv7a_cache.h | 2 ++ 2 files changed, 37 insertions(+) diff --git a/src/target/armv7a_cache.c b/src/target/armv7a_cache.c index 94fa09703..98474ecb4 100644 --- a/src/target/armv7a_cache.c +++ b/src/target/armv7a_cache.c @@ -223,6 +223,41 @@ done: return retval; } +int armv7a_l1_d_cache_flush_virt(struct target *target, uint32_t virt, + unsigned int size) +{ + struct armv7a_common *armv7a = target_to_armv7a(target); + struct arm_dpm *dpm = armv7a->arm.dpm; + struct armv7a_cache_common *armv7a_cache = &armv7a->armv7a_mmu.armv7a_cache; + uint32_t i, linelen = armv7a_cache->dminline; + int retval; + + retval = armv7a_l1_d_cache_sanity_check(target); + if (retval != ERROR_OK) + return retval; + + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + goto done; + + for (i = 0; i < size; i += linelen) { + uint32_t offs = virt + i; + + /* DCCIMVAC */ + retval = dpm->instr_write_data_r0(dpm, + ARMV4_5_MCR(15, 0, 0, 7, 14, 1), offs); + if (retval != ERROR_OK) + goto done; + } + return retval; + +done: + LOG_ERROR("d-cache invalidate failed"); + dpm->finish(dpm); + + return retval; +} + int armv7a_l1_i_cache_inval_all(struct target *target) { struct armv7a_common *armv7a = target_to_armv7a(target); diff --git a/src/target/armv7a_cache.h b/src/target/armv7a_cache.h index 0efdab74a..81995ac3a 100644 --- a/src/target/armv7a_cache.h +++ b/src/target/armv7a_cache.h @@ -21,6 +21,8 @@ int armv7a_l1_d_cache_clean_virt(struct target *target, uint32_t virt, unsigned int size); +int armv7a_l1_d_cache_flush_virt(struct target *target, uint32_t virt, + unsigned int size); int armv7a_l1_i_cache_inval_all(struct target *target); int armv7a_l1_i_cache_inval_virt(struct target *target, uint32_t virt, uint32_t size);