cortex_a: Add support for A15 MPCore 01/1601/12
authorKamal Dasu <kdasu.kdev@gmail.com>
Thu, 29 Aug 2013 18:02:19 +0000 (14:02 -0400)
committerAndreas Fritiofson <andreas.fritiofson@gmail.com>
Sat, 10 Jan 2015 00:56:45 +0000 (00:56 +0000)
Added Cortex-A15 support for DAP AHB-AP init code as per ADI V5 spec.
Also added changes to make the APB MEM-AP to work with A15.
Made the the cortex_a target code  generic to work with A8, A9
and A15 single core or multicore implementation. Added armv7a code
for os_border calculation to work for known A8, A9 and A15
platforms based on the ARM DDI 0344H, ARM DDI 0407F, ARM DDI 0406C
ARMV7A architecture docs.

Change-Id: Ib2803ab62588bf40f1ae4b9192b619af31525a1a
Signed-off-by: Kamal Dasu <kdasu.kdev@gmail.com>
Reviewed-on: http://openocd.zylin.com/1601
Tested-by: jenkins
Reviewed-by: Andreas Fritiofson <andreas.fritiofson@gmail.com>
src/target/arm_adi_v5.c
src/target/armv7a.c
src/target/armv7a.h
src/target/cortex_a.c
src/target/cortex_a.h

index c76cc690720255ff18ccaa3f156c3b900f62a141..7bb2a0b2d6d9174d7ec374f887eda68f1f13b4ac 100644 (file)
@@ -1339,7 +1339,12 @@ static int dap_rom_display(struct command_context *cmd_ctx,
                                type = "Cortex-A9 Debug";
                                full = "(Debug Unit)";
                                break;
+                       case 0x4af:
+                               type = "Cortex-A15 Debug";
+                               full = "(Debug Unit)";
+                               break;
                        default:
+                               LOG_DEBUG("Unrecognized Part number 0x%" PRIx32, part_num);
                                type = "-*- unrecognized -*-";
                                full = "";
                                break;
@@ -1408,9 +1413,9 @@ static int dap_info_command(struct command_context *cmd_ctx,
                command_print(cmd_ctx, "No AP found at this ap 0x%x", ap);
 
        romtable_present = ((mem_ap) && (dbgbase != 0xFFFFFFFF));
-       if (romtable_present) {
+       if (romtable_present)
                dap_rom_display(cmd_ctx, dap, ap, dbgbase, 0);
-       else
+       else
                command_print(cmd_ctx, "\tNo ROM table present");
        dap_ap_select(dap, ap_old);
 
index bf474d3a62f5ad30e1dba95e02ab749bf2829cec..57b8799f0c8f301e7b0cc3ecadd16aa89379b7b0 100644 (file)
@@ -88,11 +88,50 @@ done:
        /* (void) */ dpm->finish(dpm);
 }
 
+
+/*  retrieve main id register  */
+static int armv7a_read_midr(struct target *target)
+{
+       int retval = ERROR_FAIL;
+       struct armv7a_common *armv7a = target_to_armv7a(target);
+       struct arm_dpm *dpm = armv7a->arm.dpm;
+       uint32_t midr;
+       retval = dpm->prepare(dpm);
+       if (retval != ERROR_OK)
+               goto done;
+       /* MRC p15,0,<Rd>,c0,c0,0; read main id register*/
+
+       retval = dpm->instr_read_data_r0(dpm,
+                       ARMV4_5_MRC(15, 0, 0, 0, 0, 0),
+                       &midr);
+       if (retval != ERROR_OK)
+               goto done;
+
+       armv7a->rev = (midr & 0xf);
+       armv7a->partnum = (midr >> 4) & 0xfff;
+       armv7a->arch = (midr >> 16) & 0xf;
+       armv7a->variant = (midr >> 20) & 0xf;
+       armv7a->implementor = (midr >> 24) & 0xff;
+       LOG_INFO("%s rev %" PRIx32 ", partnum %" PRIx32 ", arch %" PRIx32
+                        ", variant %" PRIx32 ", implementor %" PRIx32,
+                target->cmd_name,
+                armv7a->rev,
+                armv7a->partnum,
+                armv7a->arch,
+                armv7a->variant,
+                armv7a->implementor);
+
+done:
+       dpm->finish(dpm);
+       return retval;
+}
+
 static int armv7a_read_ttbcr(struct target *target)
 {
        struct armv7a_common *armv7a = target_to_armv7a(target);
        struct arm_dpm *dpm = armv7a->arm.dpm;
        uint32_t ttbcr;
+       uint32_t ttbr0, ttbr1;
        int retval = dpm->prepare(dpm);
        if (retval != ERROR_OK)
                goto done;
@@ -102,27 +141,55 @@ static int armv7a_read_ttbcr(struct target *target)
                        &ttbcr);
        if (retval != ERROR_OK)
                goto done;
+
+       retval = dpm->instr_read_data_r0(dpm,
+                       ARMV4_5_MRC(15, 0, 0, 2, 0, 0),
+                       &ttbr0);
+       if (retval != ERROR_OK)
+               goto done;
+
+       retval = dpm->instr_read_data_r0(dpm,
+                       ARMV4_5_MRC(15, 0, 0, 2, 0, 1),
+                       &ttbr1);
+       if (retval != ERROR_OK)
+               goto done;
+
+       LOG_INFO("ttbcr %" PRIx32 "ttbr0 %" PRIx32 "ttbr1 %" PRIx32, ttbcr, ttbr0, ttbr1);
+
        armv7a->armv7a_mmu.ttbr1_used = ((ttbcr & 0x7) != 0) ? 1 : 0;
-       armv7a->armv7a_mmu.ttbr0_mask  = 7 << (32 - ((ttbcr & 0x7)));
-#if 0
-       LOG_INFO("ttb1 %s ,ttb0_mask %x",
-               armv7a->armv7a_mmu.ttbr1_used ? "used" : "not used",
-               armv7a->armv7a_mmu.ttbr0_mask);
-#endif
-       if (armv7a->armv7a_mmu.ttbr1_used == 1) {
-               LOG_INFO("SVC access above %" PRIx32,
-                        (uint32_t)(0xffffffff & armv7a->armv7a_mmu.ttbr0_mask));
-               armv7a->armv7a_mmu.os_border = 0xffffffff & armv7a->armv7a_mmu.ttbr0_mask;
+       armv7a->armv7a_mmu.ttbr0_mask = 0;
+
+       retval = armv7a_read_midr(target);
+       if (retval != ERROR_OK)
+               goto done;
+
+       if (armv7a->partnum & 0xf) {
+               /*
+                * ARM Architecture Reference Manual (ARMv7-A and ARMv7-Redition),
+                * document # ARM DDI 0406C
+                */
+               armv7a->armv7a_mmu.ttbr0_mask  = 1 << (14 - ((ttbcr & 0x7)));
        } else {
+               /*  ARM DDI 0344H , ARM DDI 0407F */
+               armv7a->armv7a_mmu.ttbr0_mask  = 7 << (32 - ((ttbcr & 0x7)));
                /*  fix me , default is hard coded LINUX border  */
                armv7a->armv7a_mmu.os_border = 0xc0000000;
        }
+
+       LOG_DEBUG("ttbr1 %s, ttbr0_mask %" PRIx32,
+                 armv7a->armv7a_mmu.ttbr1_used ? "used" : "not used",
+                 armv7a->armv7a_mmu.ttbr0_mask);
+
+       if (armv7a->armv7a_mmu.ttbr1_used == 1) {
+               LOG_INFO("SVC access above %" PRIx32,
+                       (0xffffffff & armv7a->armv7a_mmu.ttbr0_mask));
+               armv7a->armv7a_mmu.os_border = 0xffffffff & armv7a->armv7a_mmu.ttbr0_mask;
+       }
 done:
        dpm->finish(dpm);
        return retval;
 }
 
-
 /*  method adapted to cortex A : reused arm v4 v5 method*/
 int armv7a_mmu_translate_va(struct target *target,  uint32_t va, uint32_t *val)
 {
index 341114bcffee7b45060f264d107576c6bda37dac..4341acae414208435b32c980ea078642327714ed 100644 (file)
@@ -77,6 +77,7 @@ struct armv7a_cache_common {
 
 struct armv7a_mmu_common {
        /* following field mmu working way */
+       int32_t ttbr0_used;
        int32_t ttbr1_used; /*  -1 not initialized, 0 no ttbr1 1 ttbr1 used and  */
        uint32_t ttbr0_mask;/*  masked to be used  */
        uint32_t os_border;
@@ -105,6 +106,11 @@ struct armv7a_common {
        uint8_t cluster_id;
        uint8_t cpu_id;
        bool is_armv7r;
+       uint32_t rev;
+       uint32_t partnum;
+       uint32_t arch;
+       uint32_t variant;
+       uint32_t implementor;
 
        /* cache specific to V7 Memory Management Unit compatible with v4_5*/
        struct armv7a_mmu_common armv7a_mmu;
index 0393a442073d63ea7a65227102b25bd9b95fae3b..3075055dc925f3ecc9e3aa4846859da05951dd62 100644 (file)
@@ -20,6 +20,9 @@
  *   Copyright (C) Broadcom 2012                                           *
  *   ehunter@broadcom.com : Cortex R4 support                              *
  *                                                                         *
+ *   Copyright (C) 2013 Kamal Dasu                                         *
+ *   kdasu.kdev@gmail.com                                                  *
+ *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
  *   the Free Software Foundation; either version 2 of the License, or     *
@@ -164,12 +167,11 @@ static int cortex_a_mmu_modify(struct target *target, int enable)
 /*
  * Cortex-A Basic debug access, very low level assumes state is saved
  */
-static int cortex_a_init_debug_access(struct target *target)
+static int cortex_a8_init_debug_access(struct target *target)
 {
        struct armv7a_common *armv7a = target_to_armv7a(target);
        struct adiv5_dap *swjdp = armv7a->arm.dap;
        int retval;
-       uint32_t dummy;
 
        LOG_DEBUG(" ");
 
@@ -185,12 +187,57 @@ static int cortex_a_init_debug_access(struct target *target)
                        LOG_USER(
                                "Locking debug access failed on first, but succeeded on second try.");
        }
+
+       return retval;
+}
+
+/*
+ * Cortex-A Basic debug access, very low level assumes state is saved
+ */
+static int cortex_a_init_debug_access(struct target *target)
+{
+       struct armv7a_common *armv7a = target_to_armv7a(target);
+       struct adiv5_dap *swjdp = armv7a->arm.dap;
+       int retval;
+       uint32_t dbg_osreg;
+       uint32_t cortex_part_num;
+       struct cortex_a_common *cortex_a = target_to_cortex_a(target);
+
+       LOG_DEBUG(" ");
+       cortex_part_num = (cortex_a->cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >>
+               CORTEX_A_MIDR_PARTNUM_SHIFT;
+
+       switch (cortex_part_num) {
+       case CORTEX_A15_PARTNUM:
+               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
+                                                   armv7a->debug_base + CPUDBG_OSLSR,
+                                                   &dbg_osreg);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               LOG_DEBUG("DBGOSLSR  0x%" PRIx32, dbg_osreg);
+
+               if (dbg_osreg & CPUDBG_OSLAR_LK_MASK)
+                       /* Unlocking the DEBUG OS registers for modification */
+                       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap,
+                                                            armv7a->debug_base + CPUDBG_OSLAR,
+                                                            0);
+               break;
+
+       case CORTEX_A8_PARTNUM:
+       case CORTEX_A9_PARTNUM:
+       default:
+               retval = cortex_a8_init_debug_access(target);
+       }
+
        if (retval != ERROR_OK)
                return retval;
        /* Clear Sticky Power Down status Bit in PRSR to enable access to
           the registers in the Core Power Domain */
        retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
-                       armv7a->debug_base + CPUDBG_PRSR, &dummy);
+                       armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg);
+       LOG_DEBUG("target->coreid %d DBGPRSR  0x%x ", target->coreid, dbg_osreg);
+
        if (retval != ERROR_OK)
                return retval;
 
@@ -1799,6 +1846,7 @@ static int cortex_a_write_apb_ab_memory(struct target *target,
        uint32_t dscr;
        uint8_t *tmp_buff = NULL;
 
+
        LOG_DEBUG("Writing APB-AP memory address 0x%" PRIx32 " size %"  PRIu32 " count%"  PRIu32,
                          address, size, count);
        if (target->state != TARGET_HALTED) {
@@ -1846,7 +1894,6 @@ static int cortex_a_write_apb_ab_memory(struct target *target,
        /* If end of write is not aligned, or the write is less than 4 bytes */
        if ((end_byte != 0) ||
                ((total_u32 == 1) && (total_bytes != 4))) {
-
                /* Read the last word to avoid corruption during 32 bit write */
                int mem_offset = (total_u32-1) * 4;
                retval = cortex_a_read_apb_ab_memory(target, (address & ~0x3) + mem_offset, 4, 1, &tmp_buff[mem_offset]);
@@ -2163,7 +2210,8 @@ static int cortex_a_read_memory(struct target *target, uint32_t address,
                                  virt, phys);
                        address = phys;
                }
-               retval = cortex_a_read_phys_memory(target, address, size, count, buffer);
+               retval = cortex_a_read_phys_memory(target, address, size,
+                           count, buffer);
        } else {
                if (mmu_enabled) {
                        retval = cortex_a_check_address(target, address);
@@ -2363,7 +2411,7 @@ static int cortex_a_examine_first(struct target *target)
        struct adiv5_dap *swjdp = armv7a->arm.dap;
        int i;
        int retval = ERROR_OK;
-       uint32_t didr, ctypr, ttypr, cpuid;
+       uint32_t didr, ctypr, ttypr, cpuid, dbg_osreg;
 
        /* We do one extra read to ensure DAP is configured,
         * we call ahbap_debugport_init(swjdp) instead
@@ -2447,6 +2495,31 @@ static int cortex_a_examine_first(struct target *target)
        LOG_DEBUG("ttypr = 0x%08" PRIx32, ttypr);
        LOG_DEBUG("didr = 0x%08" PRIx32, didr);
 
+       cortex_a->cpuid = cpuid;
+       cortex_a->ctypr = ctypr;
+       cortex_a->ttypr = ttypr;
+       cortex_a->didr = didr;
+
+       /* Unlocking the debug registers */
+       if ((cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> CORTEX_A_MIDR_PARTNUM_SHIFT ==
+               CORTEX_A15_PARTNUM) {
+
+               retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap,
+                                                    armv7a->debug_base + CPUDBG_OSLAR,
+                                                    0);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+       }
+       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
+                                           armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg);
+
+       if (retval != ERROR_OK)
+               return retval;
+
+       LOG_DEBUG("target->coreid %d DBGPRSR  0x%" PRIx32, target->coreid, dbg_osreg);
+
        armv7a->arm.core_type = ARM_MODE_MON;
        retval = cortex_a_dpm_setup(cortex_a, didr);
        if (retval != ERROR_OK)
index 7b56feaf694c0e0c45c03604e22378bd9ad6ee6e..043d96f92c183b52edccea0275fab36241d3c9b6 100644 (file)
 #include "armv7a.h"
 
 #define CORTEX_A_COMMON_MAGIC 0x411fc082
+#define CORTEX_A15_COMMON_MAGIC 0x413fc0f1
+
+#define CORTEX_A8_PARTNUM 0xc08
+#define CORTEX_A9_PARTNUM 0xc09
+#define CORTEX_A15_PARTNUM 0xc0f
+#define CORTEX_A_MIDR_PARTNUM_MASK 0x0000fff0
+#define CORTEX_A_MIDR_PARTNUM_SHIFT 4
 
 #define CPUDBG_CPUID   0xD00
 #define CPUDBG_CTYPR   0xD04
 #define CPUDBG_TTYPR   0xD0C
 #define CPUDBG_LOCKACCESS 0xFB0
 #define CPUDBG_LOCKSTATUS 0xFB4
+#define CPUDBG_OSLAR_LK_MASK (1 << 1)
 
 #define BRP_NORMAL 0
 #define BRP_CONTEXT 1
@@ -76,6 +84,11 @@ struct cortex_a_common {
        /* Use cortex_a_read_regs_through_mem for fast register reads */
        int fast_reg_read;
 
+       uint32_t cpuid;
+       uint32_t ctypr;
+       uint32_t ttypr;
+       uint32_t didr;
+
        struct armv7a_common armv7a_common;
 
 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)