cortex_a: remove partnum magic from arp_examine and dbginit 13/3213/10
authorMatthias Welwarsky <matthias.welwarsky@sysgo.com>
Wed, 23 Nov 2016 09:15:50 +0000 (10:15 +0100)
committerPaul Fertser <fercerpav@gmail.com>
Thu, 8 Dec 2016 12:25:35 +0000 (12:25 +0000)
Depending on the Debug implementation the "OS Lock" feature might be
implemented or not. It is not actually depending on the part number of the
implemented ARM core but on the DBGOSLSR.OSLM bits. This patch removes
querying the part number and implements proper parsing of OSLM. Result is
a more generic approach that will work out-of-box on more devices.

Change-Id: I79e052869c2f9af1d7fdedef42faddb7292e7332
Signed-off-by: Matthias Welwarsky <matthias@welwarsky.de>
Reviewed-on: http://openocd.zylin.com/3213
Tested-by: jenkins
Reviewed-by: Paul Fertser <fercerpav@gmail.com>
src/target/arm_dpm.h
src/target/cortex_a.c
src/target/cortex_a.h

index fa87baf..bbcae78 100644 (file)
@@ -198,4 +198,25 @@ void arm_dpm_report_wfar(struct arm_dpm *, uint32_t wfar);
 
 void arm_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dcsr);
 
+/* PRCR (Device Power-down and Reset Control Register) bits */
+#define PRCR_DEBUG_NO_POWER_DOWN         (1 << 0)
+#define PRCR_WARM_RESET                  (1 << 1)
+#define PRCR_HOLD_NON_DEBUG_RESET        (1 << 2)
+
+/* PRSR (Device Power-down and Reset Status Register) bits */
+#define PRSR_POWERUP_STATUS              (1 << 0)
+#define PRSR_STICKY_POWERDOWN_STATUS     (1 << 1)
+#define PRSR_RESET_STATUS                (1 << 2)
+#define PRSR_STICKY_RESET_STATUS         (1 << 3)
+#define PRSR_HALTED                      (1 << 4)  /* v7.1 Debug only */
+#define PRSR_OSLK                        (1 << 5)  /* v7.1 Debug only */
+#define PRSR_DLK                         (1 << 6)  /* v7.1 Debug only */
+
+/* OSLSR (OS Lock Status Register) bits */
+#define OSLSR_OSLM0                      (1 << 0)
+#define OSLSR_OSLK                       (1 << 1)
+#define OSLSR_nTT                        (1 << 2)
+#define OSLSR_OSLM1                      (1 << 3)
+#define OSLSR_OSLM                       (OSLSR_OSLM0|OSLSR_OSLM1)
+
 #endif /* OPENOCD_TARGET_ARM_DPM_H */
index 256edbc..1f51c4e 100644 (file)
@@ -198,77 +198,15 @@ 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_a8_init_debug_access(struct target *target)
-{
-       struct armv7a_common *armv7a = target_to_armv7a(target);
-       int retval;
-
-       LOG_DEBUG(" ");
-
-       /* Unlocking the debug registers for modification
-        * The debugport might be uninitialised so try twice */
-       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
-                       armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
-       if (retval != ERROR_OK) {
-               /* try again */
-               retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
-                               armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
-               if (retval == ERROR_OK)
-                       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);
        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_A7_PARTNUM:
-       case CORTEX_A15_PARTNUM:
-               retval = mem_ap_read_atomic_u32(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_write_atomic_u32(armv7a->debug_ap,
-                                                            armv7a->debug_base + CPUDBG_OSLAR,
-                                                            0);
-               break;
-
-       case CORTEX_A5_PARTNUM:
-       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_read_atomic_u32(armv7a->debug_ap,
-                       armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg);
-       LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR  0x%" PRIx32, target->coreid, dbg_osreg);
 
+       /* lock memory-mapped access to debug registers to prevent
+        * software interference */
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+                       armv7a->debug_base + CPUDBG_LOCKACCESS, 0);
        if (retval != ERROR_OK)
                return retval;
 
@@ -2981,7 +2919,7 @@ static int cortex_a_examine_first(struct target *target)
 
        int i;
        int retval = ERROR_OK;
-       uint32_t didr, ctypr, ttypr, cpuid, dbg_osreg;
+       uint32_t didr, cpuid, dbg_osreg;
 
        retval = dap_dp_init(swjdp);
        if (retval != ERROR_OK) {
@@ -3043,79 +2981,69 @@ static int cortex_a_examine_first(struct target *target)
                armv7a->debug_base = target->dbgbase;
 
        retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                       armv7a->debug_base + CPUDBG_CPUID, &cpuid);
-       if (retval != ERROR_OK)
-               return retval;
-
-       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                       armv7a->debug_base + CPUDBG_CPUID, &cpuid);
-       if (retval != ERROR_OK) {
-               LOG_DEBUG("Examine %s failed", "CPUID");
-               return retval;
-       }
-
-       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                       armv7a->debug_base + CPUDBG_CTYPR, &ctypr);
-       if (retval != ERROR_OK) {
-               LOG_DEBUG("Examine %s failed", "CTYPR");
-               return retval;
-       }
-
-       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                       armv7a->debug_base + CPUDBG_TTYPR, &ttypr);
+                       armv7a->debug_base + CPUDBG_DIDR, &didr);
        if (retval != ERROR_OK) {
-               LOG_DEBUG("Examine %s failed", "TTYPR");
+               LOG_DEBUG("Examine %s failed", "DIDR");
                return retval;
        }
 
        retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                       armv7a->debug_base + CPUDBG_DIDR, &didr);
+                       armv7a->debug_base + CPUDBG_CPUID, &cpuid);
        if (retval != ERROR_OK) {
-               LOG_DEBUG("Examine %s failed", "DIDR");
+               LOG_DEBUG("Examine %s failed", "CPUID");
                return retval;
        }
 
-       LOG_DEBUG("cpuid = 0x%08" PRIx32, cpuid);
-       LOG_DEBUG("ctypr = 0x%08" PRIx32, ctypr);
-       LOG_DEBUG("ttypr = 0x%08" PRIx32, ttypr);
        LOG_DEBUG("didr = 0x%08" PRIx32, didr);
+       LOG_DEBUG("cpuid = 0x%08" PRIx32, cpuid);
 
-       cortex_a->cpuid = cpuid;
-       cortex_a->ctypr = ctypr;
-       cortex_a->ttypr = ttypr;
        cortex_a->didr = didr;
+       cortex_a->cpuid = cpuid;
 
-       /* Unlocking the debug registers */
-       if ((cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> CORTEX_A_MIDR_PARTNUM_SHIFT ==
-               CORTEX_A15_PARTNUM) {
-
-               retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
-                                                    armv7a->debug_base + CPUDBG_OSLAR,
-                                                    0);
-
-               if (retval != ERROR_OK)
-                       return retval;
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
+                                   armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg);
+       if (retval != ERROR_OK)
+               return retval;
+       LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR  0x%" PRIx32, target->coreid, dbg_osreg);
 
+       if ((dbg_osreg & PRSR_POWERUP_STATUS) == 0) {
+               LOG_ERROR("target->coreid %" PRId32 " powered down!", target->coreid);
+               target->state = TARGET_UNKNOWN; /* TARGET_NO_POWER? */
+               return ERROR_TARGET_INIT_FAILED;
        }
-       /* Unlocking the debug registers */
-       if ((cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> CORTEX_A_MIDR_PARTNUM_SHIFT ==
-               CORTEX_A7_PARTNUM) {
 
-               retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
-                                                    armv7a->debug_base + CPUDBG_OSLAR,
-                                                    0);
+       if (dbg_osreg & PRSR_STICKY_RESET_STATUS)
+               LOG_DEBUG("target->coreid %" PRId32 " was reset!", target->coreid);
 
-               if (retval != ERROR_OK)
-                       return retval;
-
-       }
+       /* Read DBGOSLSR and check if OSLK is implemented */
        retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                                           armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg);
-
+                               armv7a->debug_base + CPUDBG_OSLSR, &dbg_osreg);
        if (retval != ERROR_OK)
                return retval;
+       LOG_DEBUG("target->coreid %" PRId32 " DBGOSLSR 0x%" PRIx32, target->coreid, dbg_osreg);
 
-       LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR  0x%" PRIx32, target->coreid, dbg_osreg);
+       /* check if OS Lock is implemented */
+       if ((dbg_osreg & OSLSR_OSLM) == OSLSR_OSLM0 || (dbg_osreg & OSLSR_OSLM) == OSLSR_OSLM1) {
+               /* check if OS Lock is set */
+               if (dbg_osreg & OSLSR_OSLK) {
+                       LOG_DEBUG("target->coreid %" PRId32 " OSLock set! Trying to unlock", target->coreid);
+
+                       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+                                                       armv7a->debug_base + CPUDBG_OSLAR,
+                                                       0);
+                       if (retval == ERROR_OK)
+                               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
+                                                       armv7a->debug_base + CPUDBG_OSLSR, &dbg_osreg);
+
+                       /* if we fail to access the register or cannot reset the OSLK bit, bail out */
+                       if (retval != ERROR_OK || (dbg_osreg & OSLSR_OSLK) != 0) {
+                               LOG_ERROR("target->coreid %" PRId32 " OSLock sticky, core not powered?",
+                                               target->coreid);
+                               target->state = TARGET_UNKNOWN; /* TARGET_NO_POWER? */
+                               return ERROR_TARGET_INIT_FAILED;
+                       }
+               }
+       }
 
        armv7a->arm.core_type = ARM_MODE_MON;
 
index ea08c67..ff03432 100644 (file)
@@ -97,8 +97,6 @@ struct cortex_a_common {
        int fast_reg_read;
 
        uint32_t cpuid;
-       uint32_t ctypr;
-       uint32_t ttypr;
        uint32_t didr;
 
        enum cortex_a_isrmasking_mode isrmasking_mode;