-/* 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;
- uint32_t second_lvl_descriptor = 0x0;
- int retval;
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm_dpm *dpm = armv7a->arm.dpm;
- uint32_t ttbidx = 0; /* default to ttbr0 */
- uint32_t ttb_mask;
- uint32_t va_mask;
- uint32_t ttbcr;
- uint32_t ttb;
-
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- goto done;
-
- /* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
- &ttbcr);
- if (retval != ERROR_OK)
- goto done;
-
- /* if ttbcr has changed or was not read before, re-read the information */
- if ((armv7a->armv7a_mmu.cached == 0) ||
- (armv7a->armv7a_mmu.ttbcr != ttbcr)) {
- armv7a_read_ttbcr(target);
- }
-
- /* if va is above the range handled by ttbr0, select ttbr1 */
- if (va > armv7a->armv7a_mmu.ttbr_range[0]) {
- /* select ttb 1 */
- ttbidx = 1;
- }
- /* MRC p15,0,<Rt>,c2,c0,ttbidx */
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRC(15, 0, 0, 2, 0, ttbidx),
- &ttb);
- if (retval != ERROR_OK)
- return retval;
-
- ttb_mask = armv7a->armv7a_mmu.ttbr_mask[ttbidx];
- va_mask = 0xfff00000 & armv7a->armv7a_mmu.ttbr_range[ttbidx];
-
- LOG_DEBUG("ttb_mask %" PRIx32 " va_mask %" PRIx32 " ttbidx %i",
- ttb_mask, va_mask, ttbidx);
- retval = armv7a->armv7a_mmu.read_physical_memory(target,
- (ttb & ttb_mask) | ((va & va_mask) >> 18),
- 4, 1, (uint8_t *)&first_lvl_descriptor);
- if (retval != ERROR_OK)
- return retval;
- first_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)
- &first_lvl_descriptor);
- /* reuse armv4_5 piece of code, specific armv7a changes may come later */
- LOG_DEBUG("1st lvl desc: %8.8" PRIx32 "", first_lvl_descriptor);
-
- if ((first_lvl_descriptor & 0x3) == 0) {
- LOG_ERROR("Address translation failure");
- return ERROR_TARGET_TRANSLATION_FAULT;
- }
-
-
- if ((first_lvl_descriptor & 0x40002) == 2) {
- /* section descriptor */
- *val = (first_lvl_descriptor & 0xfff00000) | (va & 0x000fffff);
- return ERROR_OK;
- } else if ((first_lvl_descriptor & 0x40002) == 0x40002) {
- /* supersection descriptor */
- if (first_lvl_descriptor & 0x00f001e0) {
- LOG_ERROR("Physical address does not fit into 32 bits");
- return ERROR_TARGET_TRANSLATION_FAULT;
- }
- *val = (first_lvl_descriptor & 0xff000000) | (va & 0x00ffffff);
- return ERROR_OK;
- }
-
- /* page table */
- retval = armv7a->armv7a_mmu.read_physical_memory(target,
- (first_lvl_descriptor & 0xfffffc00) | ((va & 0x000ff000) >> 10),
- 4, 1, (uint8_t *)&second_lvl_descriptor);
- if (retval != ERROR_OK)
- return retval;
-
- second_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)
- &second_lvl_descriptor);
-
- LOG_DEBUG("2nd lvl desc: %8.8" PRIx32 "", second_lvl_descriptor);
-
- if ((second_lvl_descriptor & 0x3) == 0) {
- LOG_ERROR("Address translation failure");
- return ERROR_TARGET_TRANSLATION_FAULT;
- }
-
- if ((second_lvl_descriptor & 0x3) == 1) {
- /* large page descriptor */
- *val = (second_lvl_descriptor & 0xffff0000) | (va & 0x0000ffff);
- } else {
- /* small page descriptor */
- *val = (second_lvl_descriptor & 0xfffff000) | (va & 0x00000fff);
- }
-
- return ERROR_OK;
-
-done:
- return retval;
-}
-
-/* V7 method VA TO PA */
-int armv7a_mmu_translate_va_pa(struct target *target, uint32_t va,
- uint32_t *val, int meminfo)
-{
- int retval = ERROR_FAIL;
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm_dpm *dpm = armv7a->arm.dpm;
- uint32_t virt = va & ~0xfff;
- uint32_t NOS, NS, INNER, OUTER;
- *val = 0xdeadbeef;
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- goto done;
- /* mmu must be enable in order to get a correct translation
- * use VA to PA CP15 register for conversion */
- retval = dpm->instr_write_data_r0(dpm,
- ARMV4_5_MCR(15, 0, 0, 7, 8, 0),
- virt);
- if (retval != ERROR_OK)
- goto done;
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRC(15, 0, 0, 7, 4, 0),
- val);
- /* decode memory attribute */
- NOS = (*val >> 10) & 1; /* Not Outer shareable */
- NS = (*val >> 9) & 1; /* Non secure */
- INNER = (*val >> 4) & 0x7;
- OUTER = (*val >> 2) & 0x3;
-
- if (retval != ERROR_OK)
- goto done;
- *val = (*val & ~0xfff) + (va & 0xfff);
- if (*val == va)
- LOG_WARNING("virt = phys : MMU disable !!");
- if (meminfo) {
- LOG_INFO("%" PRIx32 " : %" PRIx32 " %s outer shareable %s secured",
- va, *val,
- NOS == 1 ? "not" : " ",
- NS == 1 ? "not" : "");
- switch (OUTER) {
- case 0:
- LOG_INFO("outer: Non-Cacheable");
- break;
- case 1:
- LOG_INFO("outer: Write-Back, Write-Allocate");
- break;
- case 2:
- LOG_INFO("outer: Write-Through, No Write-Allocate");
- break;
- case 3:
- LOG_INFO("outer: Write-Back, no Write-Allocate");
- break;
- }
- switch (INNER) {
- case 0:
- LOG_INFO("inner: Non-Cacheable");
- break;
- case 1:
- LOG_INFO("inner: Strongly-ordered");
- break;
- case 3:
- LOG_INFO("inner: Device");
- break;
- case 5:
- LOG_INFO("inner: Write-Back, Write-Allocate");
- break;
- case 6:
- LOG_INFO("inner: Write-Through");
- break;
- case 7:
- LOG_INFO("inner: Write-Back, no Write-Allocate");
-
- default:
- LOG_INFO("inner: %" PRIx32 " ???", INNER);
- }
- }
-
-done:
- dpm->finish(dpm);
-
- 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;
-}
-