X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Farmv7a.c;h=6021def4e577656ff6967402eabf78faacf8eac8;hb=99db18a995c8ef2913f1397dcc94d0533331e598;hp=6a2393970979164b5c95a2a0aafc60a665ef97aa;hpb=4ba83e1c9b3ed9bc09ff13a680db9a4f9478fa92;p=openocd.git
diff --git a/src/target/armv7a.c b/src/target/armv7a.c
index 6a23939709..6021def4e5 100644
--- a/src/target/armv7a.c
+++ b/src/target/armv7a.c
@@ -14,9 +14,7 @@
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
+ * along with this program. If not, see . *
***************************************************************************/
#ifdef HAVE_CONFIG_H
@@ -172,19 +170,12 @@ static int armv7a_read_ttbcr(struct target *target)
armv7a->armv7a_mmu.ttbr_mask[0],
armv7a->armv7a_mmu.ttbr_mask[1]);
- /* FIXME: default is hard coded LINUX border */
- armv7a->armv7a_mmu.os_border = 0xc0000000;
- if (ttbcr_n != 0) {
- LOG_INFO("SVC access above %" PRIx32,
- armv7a->armv7a_mmu.ttbr_range[0] + 1);
- armv7a->armv7a_mmu.os_border = armv7a->armv7a_mmu.ttbr_range[0] + 1;
- }
done:
dpm->finish(dpm);
return retval;
}
-/* method adapted to cortex A : reused arm v4 v5 method*/
+/* method adapted to Cortex-A : reused ARM v4 v5 method */
int armv7a_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val)
{
uint32_t first_lvl_descriptor = 0x0;
@@ -376,86 +367,6 @@ done:
return retval;
}
-static int armv7a_handle_inner_cache_info_command(struct command_context *cmd_ctx,
- struct armv7a_cache_common *armv7a_cache)
-{
- if (armv7a_cache->ctype == -1) {
- command_print(cmd_ctx, "cache not yet identified");
- return ERROR_OK;
- }
-
- command_print(cmd_ctx,
- "D-Cache: linelen %" PRIi32 ", associativity %" PRIi32 ", nsets %" PRIi32 ", cachesize %" PRId32 " KBytes",
- armv7a_cache->d_u_size.linelen,
- armv7a_cache->d_u_size.associativity,
- armv7a_cache->d_u_size.nsets,
- armv7a_cache->d_u_size.cachesize);
-
- command_print(cmd_ctx,
- "I-Cache: linelen %" PRIi32 ", associativity %" PRIi32 ", nsets %" PRIi32 ", cachesize %" PRId32 " KBytes",
- armv7a_cache->i_size.linelen,
- armv7a_cache->i_size.associativity,
- armv7a_cache->i_size.nsets,
- armv7a_cache->i_size.cachesize);
-
- return ERROR_OK;
-}
-
-/* L2 is not specific to armv7a a specific file is needed */
-static int armv7a_l2x_flush_all_data(struct target *target)
-{
-
-#define L2X0_CLEAN_INV_WAY 0x7FC
- int retval = ERROR_FAIL;
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *)
- (armv7a->armv7a_mmu.armv7a_cache.outer_cache);
- uint32_t base = l2x_cache->base;
- uint32_t l2_way = l2x_cache->way;
- uint32_t l2_way_val = (1 << l2_way) - 1;
- retval = armv7a_cache_auto_flush_all_data(target);
- if (retval != ERROR_OK)
- return retval;
- retval = target->type->write_phys_memory(target,
- (uint32_t)(base+(uint32_t)L2X0_CLEAN_INV_WAY),
- (uint32_t)4,
- (uint32_t)1,
- (uint8_t *)&l2_way_val);
- return retval;
-}
-
-static int armv7a_handle_l2x_cache_info_command(struct command_context *cmd_ctx,
- struct armv7a_cache_common *armv7a_cache)
-{
-
- struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *)
- (armv7a_cache->outer_cache);
-
- if (armv7a_cache->ctype == -1) {
- command_print(cmd_ctx, "cache not yet identified");
- return ERROR_OK;
- }
-
- command_print(cmd_ctx,
- "L1 D-Cache: linelen %" PRIi32 ", associativity %" PRIi32 ", nsets %" PRIi32 ", cachesize %" PRId32 " KBytes",
- armv7a_cache->d_u_size.linelen,
- armv7a_cache->d_u_size.associativity,
- armv7a_cache->d_u_size.nsets,
- armv7a_cache->d_u_size.cachesize);
-
- command_print(cmd_ctx,
- "L1 I-Cache: linelen %" PRIi32 ", associativity %" PRIi32 ", nsets %" PRIi32 ", cachesize %" PRId32 " KBytes",
- armv7a_cache->i_size.linelen,
- armv7a_cache->i_size.associativity,
- armv7a_cache->i_size.nsets,
- armv7a_cache->i_size.cachesize);
- command_print(cmd_ctx, "L2 unified cache Base Address 0x%" PRIx32 ", %" PRId32 " ways",
- l2x_cache->base, l2x_cache->way);
-
-
- return ERROR_OK;
-}
-
/* FIXME: remove it */
static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t way)
{
@@ -472,11 +383,6 @@ static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t
if (armv7a->armv7a_mmu.armv7a_cache.outer_cache)
LOG_INFO("outer cache already initialized\n");
armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache;
- /* initialize l1 / l2x cache function */
- armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache
- = armv7a_l2x_flush_all_data;
- armv7a->armv7a_mmu.armv7a_cache.display_cache_info =
- armv7a_handle_l2x_cache_info_command;
/* initialize all target in this cluster (smp target)
* l2 cache must be configured after smp declaration */
while (head != (struct target_list *)NULL) {
@@ -486,10 +392,6 @@ static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t
if (armv7a->armv7a_mmu.armv7a_cache.outer_cache)
LOG_ERROR("smp target : outer cache already initialized\n");
armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache;
- armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache =
- armv7a_l2x_flush_all_data;
- armv7a->armv7a_mmu.armv7a_cache.display_cache_info =
- armv7a_handle_l2x_cache_info_command;
}
head = head->next;
}
@@ -518,13 +420,50 @@ COMMAND_HANDLER(handle_cache_l2x)
int armv7a_handle_cache_info_command(struct command_context *cmd_ctx,
struct armv7a_cache_common *armv7a_cache)
{
- if (armv7a_cache->ctype == -1) {
+ struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *)
+ (armv7a_cache->outer_cache);
+
+ int cl;
+
+ if (armv7a_cache->info == -1) {
command_print(cmd_ctx, "cache not yet identified");
return ERROR_OK;
}
- if (armv7a_cache->display_cache_info)
- armv7a_cache->display_cache_info(cmd_ctx, armv7a_cache);
+ for (cl = 0; cl < armv7a_cache->loc; cl++) {
+ struct armv7a_arch_cache *arch = &(armv7a_cache->arch[cl]);
+
+ if (arch->ctype & 1) {
+ command_print(cmd_ctx,
+ "L%d I-Cache: linelen %" PRIi32
+ ", associativity %" PRIi32
+ ", nsets %" PRIi32
+ ", cachesize %" PRId32 " KBytes",
+ cl+1,
+ arch->i_size.linelen,
+ arch->i_size.associativity,
+ arch->i_size.nsets,
+ arch->i_size.cachesize);
+ }
+
+ if (arch->ctype >= 2) {
+ command_print(cmd_ctx,
+ "L%d D-Cache: linelen %" PRIi32
+ ", associativity %" PRIi32
+ ", nsets %" PRIi32
+ ", cachesize %" PRId32 " KBytes",
+ cl+1,
+ arch->d_u_size.linelen,
+ arch->d_u_size.associativity,
+ arch->d_u_size.nsets,
+ arch->d_u_size.cachesize);
+ }
+ }
+
+ if (l2x_cache != NULL)
+ command_print(cmd_ctx, "Outer unified cache Base Address 0x%" PRIx32 ", %" PRId32 " ways",
+ l2x_cache->base, l2x_cache->way);
+
return ERROR_OK;
}
@@ -574,17 +513,61 @@ done:
}
+static int get_cache_info(struct arm_dpm *dpm, int cl, int ct, uint32_t *cache_reg)
+{
+ int retval = ERROR_OK;
+
+ /* select cache level */
+ retval = dpm->instr_write_data_r0(dpm,
+ ARMV4_5_MCR(15, 2, 0, 0, 0, 0),
+ (cl << 1) | (ct == 1 ? 1 : 0));
+ if (retval != ERROR_OK)
+ goto done;
+
+ retval = dpm->instr_read_data_r0(dpm,
+ ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
+ cache_reg);
+ done:
+ return retval;
+}
+
+static struct armv7a_cachesize decode_cache_reg(uint32_t cache_reg)
+{
+ struct armv7a_cachesize size;
+ int i = 0;
+
+ size.linelen = 16 << (cache_reg & 0x7);
+ size.associativity = ((cache_reg >> 3) & 0x3ff) + 1;
+ size.nsets = ((cache_reg >> 13) & 0x7fff) + 1;
+ size.cachesize = size.linelen * size.associativity * size.nsets / 1024;
+
+ /* compute info for set way operation on cache */
+ size.index_shift = (cache_reg & 0x7) + 4;
+ size.index = (cache_reg >> 13) & 0x7fff;
+ size.way = ((cache_reg >> 3) & 0x3ff);
+
+ while (((size.way << i) & 0x80000000) == 0)
+ i++;
+ size.way_shift = i;
+
+ return size;
+}
+
int armv7a_identify_cache(struct target *target)
{
/* read cache descriptor */
int retval = ERROR_FAIL;
struct armv7a_common *armv7a = target_to_armv7a(target);
struct arm_dpm *dpm = armv7a->arm.dpm;
- uint32_t cache_selected, clidr, ctr;
- uint32_t cache_i_reg, cache_d_reg;
- struct armv7a_cache_common *cache = &(armv7a->armv7a_mmu.armv7a_cache);
+ uint32_t csselr, clidr, ctr;
+ uint32_t cache_reg;
+ int cl, ctype;
+ struct armv7a_cache_common *cache =
+ &(armv7a->armv7a_mmu.armv7a_cache);
+
if (!armv7a->is_armv7r)
armv7a_read_ttbcr(target);
+
retval = dpm->prepare(dpm);
if (retval != ERROR_OK)
goto done;
@@ -609,129 +592,86 @@ int armv7a_identify_cache(struct target *target)
&clidr);
if (retval != ERROR_OK)
goto done;
- clidr = (clidr & 0x7000000) >> 23;
- LOG_INFO("number of cache level %" PRIx32, (uint32_t)(clidr / 2));
- if ((clidr / 2) > 1) {
- /* FIXME not supported present in cortex A8 and later */
- /* in cortex A7, A15 */
- LOG_ERROR("cache l2 present :not supported");
- }
- /* retrieve selected cache
+
+ cache->loc = (clidr & 0x7000000) >> 24;
+ LOG_DEBUG("Number of cache levels to PoC %" PRId32, cache->loc);
+
+ /* retrieve selected cache for later restore
* MRC p15, 2,, c0, c0, 0; Read CSSELR */
retval = dpm->instr_read_data_r0(dpm,
ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
- &cache_selected);
- if (retval != ERROR_OK)
- goto done;
-
- retval = armv7a->arm.mrc(target, 15,
- 2, 0, /* op1, op2 */
- 0, 0, /* CRn, CRm */
- &cache_selected);
- if (retval != ERROR_OK)
- goto done;
- /* select instruction cache
- * MCR p15, 2,, c0, c0, 0; Write CSSELR
- * [0] : 1 instruction cache selection , 0 data cache selection */
- retval = dpm->instr_write_data_r0(dpm,
- ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
- 1);
+ &csselr);
if (retval != ERROR_OK)
goto done;
- /* read CCSIDR
- * MRC P15,1,