CortexA8: Implement debug base autodetection
[openocd.git] / src / target / cortex_a8.c
index 593e89510ffc990317f1200ab48691461c342f22..3c80923fc08e7c0743bd65576303a60e6ba75ec6 100644 (file)
@@ -11,6 +11,9 @@
  *   Copyright (C) 2009 by Dirk Behme                                      *
  *   dirk.behme@gmail.com - copy from cortex_m3                            *
  *                                                                         *
+ *   Copyright (C) 2010 Ã˜yvind Harboe                                      *
+ *   oyvind.harboe@zylin.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     *
@@ -39,6 +42,7 @@
 #include "target_request.h"
 #include "target_type.h"
 #include "arm_opcodes.h"
+#include <helper/time_support.h>
 
 static int cortex_a8_poll(struct target *target);
 static int cortex_a8_debug_entry(struct target *target);
@@ -51,13 +55,24 @@ static int cortex_a8_dap_read_coreregister_u32(struct target *target,
                uint32_t *value, int regnum);
 static int cortex_a8_dap_write_coreregister_u32(struct target *target,
                uint32_t value, int regnum);
+static int cortex_a8_mmu(struct target *target, int *enabled);
+static int cortex_a8_virt2phys(struct target *target,
+                uint32_t virt, uint32_t *phys);
+static int cortex_a8_disable_mmu_caches(struct target *target, int mmu,
+                int d_u_cache, int i_cache);
+static int cortex_a8_enable_mmu_caches(struct target *target, int mmu,
+                int d_u_cache, int i_cache);
+static int cortex_a8_get_ttb(struct target *target, uint32_t *result);
+
+
 /*
  * FIXME do topology discovery using the ROM; don't
- * assume this is an OMAP3.
+ * assume this is an OMAP3.   Also, allow for multiple ARMv7-A
+ * cores, with different AP numbering ... don't use a #define
+ * for these numbers, use per-core armv7a state.
  */
 #define swjdp_memoryap 0
 #define swjdp_debugap 1
-#define OMAP3530_DEBUG_BASE 0x54011000
 
 /*
  * Cortex-A8 Basic debug access, very low level assumes state is saved
@@ -65,7 +80,7 @@ static int cortex_a8_dap_write_coreregister_u32(struct target *target,
 static int cortex_a8_init_debug_access(struct target *target)
 {
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct swjdp_common *swjdp = &armv7a->swjdp_info;
+       struct adiv5_dap *swjdp = &armv7a->dap;
 
        int retval;
        uint32_t dummy;
@@ -76,16 +91,28 @@ static int cortex_a8_init_debug_access(struct target *target)
        /* The debugport might be uninitialised so try twice */
        retval = mem_ap_write_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
        if (retval != ERROR_OK)
-               mem_ap_write_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
+       {
+               /* try again */
+               retval = mem_ap_write_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
+               if (retval == ERROR_OK)
+               {
+                       LOG_USER("Locking debug access failed on first, but succeeded on second try.");
+               }
+       }
+       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(swjdp, armv7a->debug_base + CPUDBG_PRSR, &dummy);
+       if (retval != ERROR_OK)
+               return retval;
+
        /* Enabling of instruction execution in debug mode is done in debug_entry code */
 
        /* Resync breakpoint registers */
 
-       /* Since this is likley called from init or reset, update targtet state information*/
-       cortex_a8_poll(target);
+       /* Since this is likely called from init or reset, update target state information*/
+       retval = cortex_a8_poll(target);
 
        return retval;
 }
@@ -101,13 +128,14 @@ static int cortex_a8_exec_opcode(struct target *target,
        uint32_t dscr;
        int retval;
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct swjdp_common *swjdp = &armv7a->swjdp_info;
+       struct adiv5_dap *swjdp = &armv7a->dap;
 
        dscr = dscr_p ? *dscr_p : 0;
 
        LOG_DEBUG("exec opcode 0x%08" PRIx32, opcode);
 
        /* Wait for InstrCompl bit to be set */
+       long long then = timeval_ms();
        while ((dscr & DSCR_INSTR_COMP) == 0)
        {
                retval = mem_ap_read_atomic_u32(swjdp,
@@ -117,10 +145,18 @@ static int cortex_a8_exec_opcode(struct target *target,
                        LOG_ERROR("Could not read DSCR register, opcode = 0x%08" PRIx32, opcode);
                        return retval;
                }
+               if (timeval_ms() > then + 1000)
+               {
+                       LOG_ERROR("Timeout waiting for cortex_a8_exec_opcode");
+                       return ERROR_FAIL;
+               }
        }
 
-       mem_ap_write_u32(swjdp, armv7a->debug_base + CPUDBG_ITR, opcode);
+       retval = mem_ap_write_u32(swjdp, armv7a->debug_base + CPUDBG_ITR, opcode);
+       if (retval != ERROR_OK)
+               return retval;
 
+       then = timeval_ms();
        do
        {
                retval = mem_ap_read_atomic_u32(swjdp,
@@ -130,6 +166,11 @@ static int cortex_a8_exec_opcode(struct target *target,
                        LOG_ERROR("Could not read DSCR register");
                        return retval;
                }
+               if (timeval_ms() > then + 1000)
+               {
+                       LOG_ERROR("Timeout waiting for cortex_a8_exec_opcode");
+                       return ERROR_FAIL;
+               }
        }
        while ((dscr & DSCR_INSTR_COMP) == 0); /* Wait for InstrCompl bit to be set */
 
@@ -148,13 +189,22 @@ static int cortex_a8_read_regs_through_mem(struct target *target, uint32_t addre
 {
        int retval = ERROR_OK;
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct swjdp_common *swjdp = &armv7a->swjdp_info;
+       struct adiv5_dap *swjdp = &armv7a->dap;
+
+       retval = cortex_a8_dap_read_coreregister_u32(target, regfile, 0);
+       if (retval != ERROR_OK)
+               return retval;
+       retval = cortex_a8_dap_write_coreregister_u32(target, address, 0);
+       if (retval != ERROR_OK)
+               return retval;
+       retval = cortex_a8_exec_opcode(target, ARMV4_5_STMIA(0, 0xFFFE, 0, 0), NULL);
+       if (retval != ERROR_OK)
+               return retval;
 
-       cortex_a8_dap_read_coreregister_u32(target, regfile, 0);
-       cortex_a8_dap_write_coreregister_u32(target, address, 0);
-       cortex_a8_exec_opcode(target, ARMV4_5_STMIA(0, 0xFFFE, 0, 0), NULL);
        dap_ap_select(swjdp, swjdp_memoryap);
-       mem_ap_read_buf_u32(swjdp, (uint8_t *)(&regfile[1]), 4*15, address);
+       retval = mem_ap_read_buf_u32(swjdp, (uint8_t *)(&regfile[1]), 4*15, address);
+       if (retval != ERROR_OK)
+               return retval;
        dap_ap_select(swjdp, swjdp_debugap);
 
        return retval;
@@ -167,7 +217,7 @@ static int cortex_a8_dap_read_coreregister_u32(struct target *target,
        uint8_t reg = regnum&0xFF;
        uint32_t dscr = 0;
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct swjdp_common *swjdp = &armv7a->swjdp_info;
+       struct adiv5_dap *swjdp = &armv7a->dap;
 
        if (reg > 17)
                return retval;
@@ -175,34 +225,52 @@ static int cortex_a8_dap_read_coreregister_u32(struct target *target,
        if (reg < 15)
        {
                /* Rn to DCCTX, "MCR p14, 0, Rn, c0, c5, 0"  0xEE00nE15 */
-               cortex_a8_exec_opcode(target,
+               retval = cortex_a8_exec_opcode(target,
                                ARMV4_5_MCR(14, 0, reg, 0, 5, 0),
                                &dscr);
+               if (retval != ERROR_OK)
+                       return retval;
        }
        else if (reg == 15)
        {
                /* "MOV r0, r15"; then move r0 to DCCTX */
-               cortex_a8_exec_opcode(target, 0xE1A0000F, &dscr);
-               cortex_a8_exec_opcode(target,
+               retval = cortex_a8_exec_opcode(target, 0xE1A0000F, &dscr);
+               if (retval != ERROR_OK)
+                       return retval;
+               retval = cortex_a8_exec_opcode(target,
                                ARMV4_5_MCR(14, 0, 0, 0, 5, 0),
                                &dscr);
+               if (retval != ERROR_OK)
+                       return retval;
        }
        else
        {
                /* "MRS r0, CPSR" or "MRS r0, SPSR"
                 * then move r0 to DCCTX
                 */
-               cortex_a8_exec_opcode(target, ARMV4_5_MRS(0, reg & 1), &dscr);
-               cortex_a8_exec_opcode(target,
+               retval = cortex_a8_exec_opcode(target, ARMV4_5_MRS(0, reg & 1), &dscr);
+               if (retval != ERROR_OK)
+                       return retval;
+               retval = cortex_a8_exec_opcode(target,
                                ARMV4_5_MCR(14, 0, 0, 0, 5, 0),
                                &dscr);
+               if (retval != ERROR_OK)
+                       return retval;
        }
 
        /* Wait for DTRRXfull then read DTRRTX */
+       long long then = timeval_ms();
        while ((dscr & DSCR_DTR_TX_FULL) == 0)
        {
                retval = mem_ap_read_atomic_u32(swjdp,
                                armv7a->debug_base + CPUDBG_DSCR, &dscr);
+               if (retval != ERROR_OK)
+                       return retval;
+               if (timeval_ms() > then + 1000)
+               {
+                       LOG_ERROR("Timeout waiting for cortex_a8_exec_opcode");
+                       return ERROR_FAIL;
+               }
        }
 
        retval = mem_ap_read_atomic_u32(swjdp,
@@ -219,19 +287,23 @@ static int cortex_a8_dap_write_coreregister_u32(struct target *target,
        uint8_t Rd = regnum&0xFF;
        uint32_t dscr;
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct swjdp_common *swjdp = &armv7a->swjdp_info;
+       struct adiv5_dap *swjdp = &armv7a->dap;
 
        LOG_DEBUG("register %i, value 0x%08" PRIx32, regnum, value);
 
        /* Check that DCCRX is not full */
        retval = mem_ap_read_atomic_u32(swjdp,
                                armv7a->debug_base + CPUDBG_DSCR, &dscr);
+       if (retval != ERROR_OK)
+               return retval;
        if (dscr & DSCR_DTR_RX_FULL)
        {
                LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr);
                /* Clear DCCRX with MCR(p14, 0, Rd, c0, c5, 0), opcode  0xEE000E15 */
-               cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
+               retval = cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
                                &dscr);
+               if (retval != ERROR_OK)
+                       return retval;
        }
 
        if (Rd > 17)
@@ -241,37 +313,53 @@ static int cortex_a8_dap_write_coreregister_u32(struct target *target,
        LOG_DEBUG("write DCC 0x%08" PRIx32, value);
        retval = mem_ap_write_u32(swjdp,
                        armv7a->debug_base + CPUDBG_DTRRX, value);
+       if (retval != ERROR_OK)
+               return retval;
 
        if (Rd < 15)
        {
                /* DCCRX to Rn, "MCR p14, 0, Rn, c0, c5, 0", 0xEE00nE15 */
-               cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, Rd, 0, 5, 0),
+               retval = cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, Rd, 0, 5, 0),
                                &dscr);
+               if (retval != ERROR_OK)
+                       return retval;
        }
        else if (Rd == 15)
        {
                /* DCCRX to R0, "MCR p14, 0, R0, c0, c5, 0", 0xEE000E15
                 * then "mov r15, r0"
                 */
-               cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
+               retval = cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
                                &dscr);
-               cortex_a8_exec_opcode(target, 0xE1A0F000, &dscr);
+               if (retval != ERROR_OK)
+                       return retval;
+               retval = cortex_a8_exec_opcode(target, 0xE1A0F000, &dscr);
+               if (retval != ERROR_OK)
+                       return retval;
        }
        else
        {
                /* DCCRX to R0, "MCR p14, 0, R0, c0, c5, 0", 0xEE000E15
                 * then "MSR CPSR_cxsf, r0" or "MSR SPSR_cxsf, r0" (all fields)
                 */
-               cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
+               retval = cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
                                &dscr);
-               cortex_a8_exec_opcode(target, ARMV4_5_MSR_GP(0, 0xF, Rd & 1),
+               if (retval != ERROR_OK)
+                       return retval;
+               retval = cortex_a8_exec_opcode(target, ARMV4_5_MSR_GP(0, 0xF, Rd & 1),
                                &dscr);
+               if (retval != ERROR_OK)
+                       return retval;
 
                /* "Prefetch flush" after modifying execution status in CPSR */
                if (Rd == 16)
-                       cortex_a8_exec_opcode(target,
+               {
+                       retval = cortex_a8_exec_opcode(target,
                                        ARMV4_5_MCR(15, 0, 0, 7, 5, 4),
                                        &dscr);
+                       if (retval != ERROR_OK)
+                               return retval;
+               }
        }
 
        return retval;
@@ -282,7 +370,7 @@ static int cortex_a8_dap_write_memap_register_u32(struct target *target, uint32_
 {
        int retval;
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct swjdp_common *swjdp = &armv7a->swjdp_info;
+       struct adiv5_dap *swjdp = &armv7a->dap;
 
        retval = mem_ap_write_atomic_u32(swjdp, address, value);
 
@@ -308,14 +396,14 @@ static inline struct cortex_a8_common *dpm_to_a8(struct arm_dpm *dpm)
 static int cortex_a8_write_dcc(struct cortex_a8_common *a8, uint32_t data)
 {
        LOG_DEBUG("write DCC 0x%08" PRIx32, data);
-       return mem_ap_write_u32(&a8->armv7a_common.swjdp_info,
+       return mem_ap_write_u32(&a8->armv7a_common.dap,
                        a8->armv7a_common.debug_base + CPUDBG_DTRRX, data);
 }
 
 static int cortex_a8_read_dcc(struct cortex_a8_common *a8, uint32_t *data,
                uint32_t *dscr_p)
 {
-       struct swjdp_common *swjdp = &a8->armv7a_common.swjdp_info;
+       struct adiv5_dap *swjdp = &a8->armv7a_common.dap;
        uint32_t dscr = DSCR_INSTR_COMP;
        int retval;
 
@@ -323,14 +411,24 @@ static int cortex_a8_read_dcc(struct cortex_a8_common *a8, uint32_t *data,
                dscr = *dscr_p;
 
        /* Wait for DTRRXfull */
+       long long then = timeval_ms();
        while ((dscr & DSCR_DTR_TX_FULL) == 0) {
                retval = mem_ap_read_atomic_u32(swjdp,
                                a8->armv7a_common.debug_base + CPUDBG_DSCR,
                                &dscr);
+               if (retval != ERROR_OK)
+                       return retval;
+               if (timeval_ms() > then + 1000)
+               {
+                       LOG_ERROR("Timeout waiting for read dcc");
+                       return ERROR_FAIL;
+               }
        }
 
        retval = mem_ap_read_atomic_u32(swjdp,
                        a8->armv7a_common.debug_base + CPUDBG_DTRTX, data);
+       if (retval != ERROR_OK)
+               return retval;
        //LOG_DEBUG("read DCC 0x%08" PRIx32, *data);
 
        if (dscr_p)
@@ -342,16 +440,27 @@ static int cortex_a8_read_dcc(struct cortex_a8_common *a8, uint32_t *data,
 static int cortex_a8_dpm_prepare(struct arm_dpm *dpm)
 {
        struct cortex_a8_common *a8 = dpm_to_a8(dpm);
-       struct swjdp_common *swjdp = &a8->armv7a_common.swjdp_info;
+       struct adiv5_dap *swjdp = &a8->armv7a_common.dap;
        uint32_t dscr;
        int retval;
 
        /* set up invariant:  INSTR_COMP is set after ever DPM operation */
-       do {
+       long long then = timeval_ms();
+       for (;;)
+       {
                retval = mem_ap_read_atomic_u32(swjdp,
                                a8->armv7a_common.debug_base + CPUDBG_DSCR,
                                &dscr);
-       } while ((dscr & DSCR_INSTR_COMP) == 0);
+               if (retval != ERROR_OK)
+                       return retval;
+               if ((dscr & DSCR_INSTR_COMP) != 0)
+                       break;
+               if (timeval_ms() > then + 1000)
+               {
+                       LOG_ERROR("Timeout waiting for dpm prepare");
+                       return ERROR_FAIL;
+               }
+       }
 
        /* this "should never happen" ... */
        if (dscr & DSCR_DTR_RX_FULL) {
@@ -361,6 +470,8 @@ static int cortex_a8_dpm_prepare(struct arm_dpm *dpm)
                                a8->armv7a_common.armv4_5_common.target,
                                ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
                                &dscr);
+               if (retval != ERROR_OK)
+                       return retval;
        }
 
        return retval;
@@ -380,6 +491,8 @@ static int cortex_a8_instr_write_data_dcc(struct arm_dpm *dpm,
        uint32_t dscr = DSCR_INSTR_COMP;
 
        retval = cortex_a8_write_dcc(a8, data);
+       if (retval != ERROR_OK)
+               return retval;
 
        return cortex_a8_exec_opcode(
                        a8->armv7a_common.armv4_5_common.target,
@@ -395,12 +508,16 @@ static int cortex_a8_instr_write_data_r0(struct arm_dpm *dpm,
        int retval;
 
        retval = cortex_a8_write_dcc(a8, data);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* DCCRX to R0, "MCR p14, 0, R0, c0, c5, 0", 0xEE000E15 */
        retval = cortex_a8_exec_opcode(
                        a8->armv7a_common.armv4_5_common.target,
                        ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
                        &dscr);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* then the opcode, taking data from R0 */
        retval = cortex_a8_exec_opcode(
@@ -434,6 +551,8 @@ static int cortex_a8_instr_read_data_dcc(struct arm_dpm *dpm,
                        a8->armv7a_common.armv4_5_common.target,
                        opcode,
                        &dscr);
+       if (retval != ERROR_OK)
+               return retval;
 
        return cortex_a8_read_dcc(a8, data, &dscr);
 }
@@ -451,17 +570,21 @@ static int cortex_a8_instr_read_data_r0(struct arm_dpm *dpm,
                        a8->armv7a_common.armv4_5_common.target,
                        opcode,
                        &dscr);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* write R0 to DCC */
        retval = cortex_a8_exec_opcode(
                        a8->armv7a_common.armv4_5_common.target,
                        ARMV4_5_MCR(14, 0, 0, 0, 5, 0),
                        &dscr);
+       if (retval != ERROR_OK)
+               return retval;
 
        return cortex_a8_read_dcc(a8, data, &dscr);
 }
 
-static int cortex_a8_bpwp_enable(struct arm_dpm *dpm, unsigned index,
+static int cortex_a8_bpwp_enable(struct arm_dpm *dpm, unsigned index_t,
                uint32_t addr, uint32_t control)
 {
        struct cortex_a8_common *a8 = dpm_to_a8(dpm);
@@ -469,7 +592,7 @@ static int cortex_a8_bpwp_enable(struct arm_dpm *dpm, unsigned index,
        uint32_t cr = a8->armv7a_common.debug_base;
        int retval;
 
-       switch (index) {
+       switch (index_t) {
        case 0 ... 15:          /* breakpoints */
                vr += CPUDBG_BVR_BASE;
                cr += CPUDBG_BCR_BASE;
@@ -477,13 +600,13 @@ static int cortex_a8_bpwp_enable(struct arm_dpm *dpm, unsigned index,
        case 16 ... 31:         /* watchpoints */
                vr += CPUDBG_WVR_BASE;
                cr += CPUDBG_WCR_BASE;
-               index -= 16;
+               index_t -= 16;
                break;
        default:
                return ERROR_FAIL;
        }
-       vr += 4 * index;
-       cr += 4 * index;
+       vr += 4 * index_t;
+       cr += 4 * index_t;
 
        LOG_DEBUG("A8: bpwp enable, vr %08x cr %08x",
                        (unsigned) vr, (unsigned) cr);
@@ -497,23 +620,23 @@ static int cortex_a8_bpwp_enable(struct arm_dpm *dpm, unsigned index,
        return retval;
 }
 
-static int cortex_a8_bpwp_disable(struct arm_dpm *dpm, unsigned index)
+static int cortex_a8_bpwp_disable(struct arm_dpm *dpm, unsigned index_t)
 {
        struct cortex_a8_common *a8 = dpm_to_a8(dpm);
        uint32_t cr;
 
-       switch (index) {
+       switch (index_t) {
        case 0 ... 15:
                cr = a8->armv7a_common.debug_base + CPUDBG_BCR_BASE;
                break;
        case 16 ... 31:
                cr = a8->armv7a_common.debug_base + CPUDBG_WCR_BASE;
-               index -= 16;
+               index_t -= 16;
                break;
        default:
                return ERROR_FAIL;
        }
-       cr += 4 * index;
+       cr += 4 * index_t;
 
        LOG_DEBUG("A8: bpwp disable, cr %08x", (unsigned) cr);
 
@@ -560,7 +683,7 @@ static int cortex_a8_poll(struct target *target)
        uint32_t dscr;
        struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
        struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
-       struct swjdp_common *swjdp = &armv7a->swjdp_info;
+       struct adiv5_dap *swjdp = &armv7a->dap;
        enum target_state prev_target_state = target->state;
        uint8_t saved_apsel = dap_ap_get_select(swjdp);
 
@@ -624,7 +747,7 @@ static int cortex_a8_halt(struct target *target)
        int retval = ERROR_OK;
        uint32_t dscr;
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct swjdp_common *swjdp = &armv7a->swjdp_info;
+       struct adiv5_dap *swjdp = &armv7a->dap;
        uint8_t saved_apsel = dap_ap_get_select(swjdp);
        dap_ap_select(swjdp, swjdp_debugap);
 
@@ -634,21 +757,38 @@ static int cortex_a8_halt(struct target *target)
         */
        retval = mem_ap_write_atomic_u32(swjdp,
                        armv7a->debug_base + CPUDBG_DRCR, 0x1);
+       if (retval != ERROR_OK)
+               goto out;
 
        /*
         * enter halting debug mode
         */
-       mem_ap_read_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_DSCR, &dscr);
+       retval = mem_ap_read_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_DSCR, &dscr);
+       if (retval != ERROR_OK)
+               goto out;
+
        retval = mem_ap_write_atomic_u32(swjdp,
                armv7a->debug_base + CPUDBG_DSCR, dscr | DSCR_HALT_DBG_MODE);
-
        if (retval != ERROR_OK)
                goto out;
 
-       do {
-               mem_ap_read_atomic_u32(swjdp,
+       long long then = timeval_ms();
+       for (;;)
+       {
+               retval = mem_ap_read_atomic_u32(swjdp,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
-       } while ((dscr & DSCR_CORE_HALTED) == 0);
+               if (retval != ERROR_OK)
+                       goto out;
+               if ((dscr & DSCR_CORE_HALTED) != 0)
+               {
+                       break;
+               }
+               if (timeval_ms() > then + 1000)
+               {
+                       LOG_ERROR("Timeout waiting for halt");
+                       return ERROR_FAIL;
+               }
+       }
 
        target->debug_reason = DBG_REASON_DBGRQ;
 
@@ -662,7 +802,8 @@ static int cortex_a8_resume(struct target *target, int current,
 {
        struct armv7a_common *armv7a = target_to_armv7a(target);
        struct arm *armv4_5 = &armv7a->armv4_5_common;
-       struct swjdp_common *swjdp = &armv7a->swjdp_info;
+       struct adiv5_dap *swjdp = &armv7a->dap;
+       int retval;
 
 //     struct breakpoint *breakpoint = NULL;
        uint32_t resume_pc, dscr;
@@ -695,9 +836,7 @@ static int cortex_a8_resume(struct target *target, int current,
 #endif
 
        /* current = 1: continue on current pc, otherwise continue at <address> */
-       resume_pc = buf_get_u32(
-                       armv4_5->core_cache->reg_list[15].value,
-                       0, 32);
+       resume_pc = buf_get_u32(armv4_5->pc->value, 0, 32);
        if (!current)
                resume_pc = address;
 
@@ -721,12 +860,13 @@ static int cortex_a8_resume(struct target *target, int current,
                return ERROR_FAIL;
        }
        LOG_DEBUG("resume pc = 0x%08" PRIx32, resume_pc);
-       buf_set_u32(armv4_5->core_cache->reg_list[15].value,
-                       0, 32, resume_pc);
-       armv4_5->core_cache->reg_list[15].dirty = 1;
-       armv4_5->core_cache->reg_list[15].valid = 1;
+       buf_set_u32(armv4_5->pc->value, 0, 32, resume_pc);
+       armv4_5->pc->dirty = 1;
+       armv4_5->pc->valid = 1;
 
-       cortex_a8_restore_context(target, handle_breakpoints);
+       retval = cortex_a8_restore_context(target, handle_breakpoints);
+       if (retval != ERROR_OK)
+               return retval;
 
 #if 0
        /* the front-end may request us not to handle breakpoints */
@@ -749,12 +889,25 @@ static int cortex_a8_resume(struct target *target, int current,
         * REVISIT: for single stepping, we probably want to
         * disable IRQs by default, with optional override...
         */
-       mem_ap_write_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_DRCR, 0x2);
+       retval = mem_ap_write_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_DRCR, 0x2);
+       if (retval != ERROR_OK)
+               return retval;
 
-       do {
-               mem_ap_read_atomic_u32(swjdp,
+       long long then = timeval_ms();
+       for (;;)
+       {
+               retval = mem_ap_read_atomic_u32(swjdp,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
-       } while ((dscr & DSCR_CORE_RESTARTED) == 0);
+               if (retval != ERROR_OK)
+                       return retval;
+               if ((dscr & DSCR_CORE_RESTARTED) != 0)
+                       break;
+               if (timeval_ms() > then + 1000)
+               {
+                       LOG_ERROR("Timeout waiting for resume");
+                       return ERROR_FAIL;
+               }
+       }
 
        target->debug_reason = DBG_REASON_NOTHALTED;
        target->state = TARGET_RUNNING;
@@ -789,14 +942,16 @@ static int cortex_a8_debug_entry(struct target *target)
        struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
        struct armv7a_common *armv7a = target_to_armv7a(target);
        struct arm *armv4_5 = &armv7a->armv4_5_common;
-       struct swjdp_common *swjdp = &armv7a->swjdp_info;
+       struct adiv5_dap *swjdp = &armv7a->dap;
        struct reg *reg;
 
        LOG_DEBUG("dscr = 0x%08" PRIx32, cortex_a8->cpudbg_dscr);
 
        /* REVISIT surely we should not re-read DSCR !! */
-       mem_ap_read_atomic_u32(swjdp,
+       retval = mem_ap_read_atomic_u32(swjdp,
                                armv7a->debug_base + CPUDBG_DSCR, &dscr);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* REVISIT see A8 TRM 12.11.4 steps 2..3 -- make sure that any
         * imprecise data aborts get discarded by issuing a Data
@@ -807,6 +962,8 @@ static int cortex_a8_debug_entry(struct target *target)
        dscr |= DSCR_ITR_EN;
        retval = mem_ap_write_atomic_u32(swjdp,
                        armv7a->debug_base + CPUDBG_DSCR, dscr);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* Examine debug reason */
        arm_dpm_report_dscr(&armv7a->dpm, cortex_a8->cpudbg_dscr);
@@ -818,6 +975,8 @@ static int cortex_a8_debug_entry(struct target *target)
                retval = mem_ap_read_atomic_u32(swjdp,
                                armv7a->debug_base + CPUDBG_WFAR,
                                &wfar);
+               if (retval != ERROR_OK)
+                       return retval;
                arm_dpm_report_wfar(&armv7a->dpm, wfar);
        }
 
@@ -835,13 +994,19 @@ static int cortex_a8_debug_entry(struct target *target)
        else
        {
                dap_ap_select(swjdp, swjdp_memoryap);
-               cortex_a8_read_regs_through_mem(target,
+               retval = cortex_a8_read_regs_through_mem(target,
                                regfile_working_area->address, regfile);
                dap_ap_select(swjdp, swjdp_memoryap);
                target_free_working_area(target, regfile_working_area);
+               if (retval != ERROR_OK)
+               {
+                       return retval;
+               }
 
                /* read Current PSR */
-               cortex_a8_dap_read_coreregister_u32(target, &cpsr, 16);
+               retval = cortex_a8_dap_read_coreregister_u32(target, &cpsr, 16);
+               if (retval != ERROR_OK)
+                       return retval;
                dap_ap_select(swjdp, swjdp_debugap);
                LOG_DEBUG("cpsr: %8.8" PRIx32, cpsr);
 
@@ -869,7 +1034,7 @@ static int cortex_a8_debug_entry(struct target *target)
                        regfile[ARM_PC] -= 8;
                }
 
-               reg = armv4_5->core_cache->reg_list + 15;
+               reg = armv4_5->pc;
                buf_set_u32(reg->value, 0, 32, regfile[ARM_PC]);
                reg->dirty = reg->valid;
        }
@@ -890,12 +1055,16 @@ static int cortex_a8_debug_entry(struct target *target)
        /* Are we in an exception handler */
 //     armv4_5->exception_number = 0;
        if (armv7a->post_debug_entry)
-               armv7a->post_debug_entry(target);
+       {
+               retval = armv7a->post_debug_entry(target);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
 
        return retval;
 }
 
-static void cortex_a8_post_debug_entry(struct target *target)
+static int cortex_a8_post_debug_entry(struct target *target)
 {
        struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
        struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
@@ -906,6 +1075,8 @@ static void cortex_a8_post_debug_entry(struct target *target)
                        0, 0,   /* op1, op2 */
                        1, 0,   /* CRn, CRm */
                        &cortex_a8->cp15_control_reg);
+       if (retval != ERROR_OK)
+               return retval;
        LOG_DEBUG("cp15_control_reg: %8.8" PRIx32, cortex_a8->cp15_control_reg);
 
        if (armv7a->armv4_5_mmu.armv4_5_cache.ctype == -1)
@@ -917,6 +1088,8 @@ static void cortex_a8_post_debug_entry(struct target *target)
                                0, 1,   /* op1, op2 */
                                0, 0,   /* CRn, CRm */
                                &cache_type_reg);
+               if (retval != ERROR_OK)
+                       return retval;
                LOG_DEBUG("cp15 cache type: %8.8x", (unsigned) cache_type_reg);
 
                /* FIXME the armv4_4 cache info DOES NOT APPLY to Cortex-A8 */
@@ -931,7 +1104,7 @@ static void cortex_a8_post_debug_entry(struct target *target)
        armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled =
                        (cortex_a8->cp15_control_reg & 0x1000U) ? 1 : 0;
 
-
+       return ERROR_OK;
 }
 
 static int cortex_a8_step(struct target *target, int current, uint32_t address,
@@ -942,8 +1115,7 @@ static int cortex_a8_step(struct target *target, int current, uint32_t address,
        struct breakpoint *breakpoint = NULL;
        struct breakpoint stepbreakpoint;
        struct reg *r;
-
-       int timeout = 100;
+       int retval;
 
        if (target->state != TARGET_HALTED)
        {
@@ -952,7 +1124,7 @@ static int cortex_a8_step(struct target *target, int current, uint32_t address,
        }
 
        /* current = 1: continue on current pc, otherwise continue at <address> */
-       r = armv4_5->core_cache->reg_list + 15;
+       r = armv4_5->pc;
        if (!current)
        {
                buf_set_u32(r->value, 0, 32, address);
@@ -985,21 +1157,26 @@ static int cortex_a8_step(struct target *target, int current, uint32_t address,
 
        target->debug_reason = DBG_REASON_SINGLESTEP;
 
-       cortex_a8_resume(target, 1, address, 0, 0);
+       retval = cortex_a8_resume(target, 1, address, 0, 0);
+       if (retval != ERROR_OK)
+               return retval;
 
+       long long then = timeval_ms();
        while (target->state != TARGET_HALTED)
        {
-               cortex_a8_poll(target);
-               if (--timeout == 0)
+               retval = cortex_a8_poll(target);
+               if (retval != ERROR_OK)
+                       return retval;
+               if (timeval_ms() > then + 1000)
                {
-                       LOG_WARNING("timeout waiting for target halt");
-                       break;
+                       LOG_ERROR("timeout waiting for target halt");
+                       return ERROR_FAIL;
                }
        }
 
        cortex_a8_unset_breakpoint(target, &stepbreakpoint);
-       if (timeout > 0)
-               target->debug_reason = DBG_REASON_BREAKPOINT;
+
+       target->debug_reason = DBG_REASON_BREAKPOINT;
 
        if (breakpoint)
                cortex_a8_set_breakpoint(target, breakpoint, 0);
@@ -1019,17 +1196,12 @@ static int cortex_a8_restore_context(struct target *target, bool bpwp)
        if (armv7a->pre_restore_context)
                armv7a->pre_restore_context(target);
 
-       arm_dpm_write_dirty_registers(&armv7a->dpm, bpwp);
-
-       if (armv7a->post_restore_context)
-               armv7a->post_restore_context(target);
-
-       return ERROR_OK;
+       return arm_dpm_write_dirty_registers(&armv7a->dpm, bpwp);
 }
 
 
 /*
- * Cortex-A8 Breakpoint and watchpoint fuctions
+ * Cortex-A8 Breakpoint and watchpoint functions
  */
 
 /* Setup hardware Breakpoint Register Pair */
@@ -1057,7 +1229,7 @@ static int cortex_a8_set_breakpoint(struct target *target,
                if (brp_i >= cortex_a8->brp_num)
                {
                        LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
-                       return ERROR_FAIL;
+                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
                }
                breakpoint->set = brp_i + 1;
                if (breakpoint->length == 2)
@@ -1070,12 +1242,16 @@ static int cortex_a8_set_breakpoint(struct target *target,
                brp_list[brp_i].used = 1;
                brp_list[brp_i].value = (breakpoint->address & 0xFFFFFFFC);
                brp_list[brp_i].control = control;
-               cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
+               retval = cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
                                + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
                                brp_list[brp_i].value);
-               cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
+               if (retval != ERROR_OK)
+                       return retval;
+               retval = cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
                                + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
                                brp_list[brp_i].control);
+               if (retval != ERROR_OK)
+                       return retval;
                LOG_DEBUG("brp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
                                brp_list[brp_i].control,
                                brp_list[brp_i].value);
@@ -1134,12 +1310,16 @@ static int cortex_a8_unset_breakpoint(struct target *target, struct breakpoint *
                brp_list[brp_i].used = 0;
                brp_list[brp_i].value = 0;
                brp_list[brp_i].control = 0;
-               cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
+               retval = cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
                                + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
                                brp_list[brp_i].control);
-               cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
+               if (retval != ERROR_OK)
+                       return retval;
+               retval = cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
                                + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
                                brp_list[brp_i].value);
+               if (retval != ERROR_OK)
+                       return retval;
        }
        else
        {
@@ -1179,9 +1359,8 @@ static int cortex_a8_add_breakpoint(struct target *target,
 
        if (breakpoint->type == BKPT_HARD)
                cortex_a8->brp_num_available--;
-       cortex_a8_set_breakpoint(target, breakpoint, 0x00); /* Exact match */
 
-       return ERROR_OK;
+       return cortex_a8_set_breakpoint(target, breakpoint, 0x00); /* Exact match */
 }
 
 static int cortex_a8_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
@@ -1189,7 +1368,7 @@ static int cortex_a8_remove_breakpoint(struct target *target, struct breakpoint
        struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
 
 #if 0
-/* It is perfectly possible to remove brakpoints while the taget is running */
+/* It is perfectly possible to remove breakpoints while the target is running */
        if (target->state != TARGET_HALTED)
        {
                LOG_WARNING("target not halted");
@@ -1211,7 +1390,7 @@ static int cortex_a8_remove_breakpoint(struct target *target, struct breakpoint
 
 
 /*
- * Cortex-A8 Reset fuctions
+ * Cortex-A8 Reset functions
  */
 
 static int cortex_a8_assert_reset(struct target *target)
@@ -1253,6 +1432,8 @@ static int cortex_a8_deassert_reset(struct target *target)
        jtag_add_reset(0, 0);
 
        retval = cortex_a8_poll(target);
+       if (retval != ERROR_OK)
+               return retval;
 
        if (target->reset_halt) {
                if (target->state != TARGET_HALTED) {
@@ -1273,111 +1454,174 @@ static int cortex_a8_deassert_reset(struct target *target)
  * ap number for every access.
  */
 
+static int cortex_a8_read_phys_memory(struct target *target,
+                uint32_t address, uint32_t size,
+                uint32_t count, uint8_t *buffer)
+{
+        struct armv7a_common *armv7a = target_to_armv7a(target);
+        struct adiv5_dap *swjdp = &armv7a->dap;
+        int retval = ERROR_INVALID_ARGUMENTS;
+
+        /* cortex_a8 handles unaligned memory access */
+
+// ???  dap_ap_select(swjdp, swjdp_memoryap);
+        LOG_DEBUG("Reading memory at real address 0x%x; size %d; count %d", address, size, count);
+        if (count && buffer) {
+                switch (size) {
+                case 4:
+                        retval = mem_ap_read_buf_u32(swjdp, buffer, 4 * count, address);
+                        break;
+                case 2:
+                        retval = mem_ap_read_buf_u16(swjdp, buffer, 2 * count, address);
+                        break;
+                case 1:
+                        retval = mem_ap_read_buf_u8(swjdp, buffer, count, address);
+                        break;
+                }
+        }
+
+        return retval;
+}
+
 static int cortex_a8_read_memory(struct target *target, uint32_t address,
                uint32_t size, uint32_t count, uint8_t *buffer)
 {
-       struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct swjdp_common *swjdp = &armv7a->swjdp_info;
-       int retval = ERROR_INVALID_ARGUMENTS;
+        int enabled = 0;
+        uint32_t virt, phys;
+        int retval;
 
        /* cortex_a8 handles unaligned memory access */
 
 // ??? dap_ap_select(swjdp, swjdp_memoryap);
+        LOG_DEBUG("Reading memory at address 0x%x; size %d; count %d", address, size, count);
+        retval = cortex_a8_mmu(target, &enabled);
+        if (retval != ERROR_OK)
+               return retval;
+
+        if(enabled)
+        {
+            virt = address;
+            retval = cortex_a8_virt2phys(target, virt, &phys);
+            if (retval != ERROR_OK)
+               return retval;
+
+            LOG_DEBUG("Reading at virtual address. Translating v:0x%x to r:0x%x", virt, phys);
+            address = phys;
+        }
+
+        return cortex_a8_read_phys_memory(target, address, size, count, buffer);
+}
 
-       if (count && buffer) {
-               switch (size) {
-               case 4:
-                       retval = mem_ap_read_buf_u32(swjdp, buffer, 4 * count, address);
-                       break;
-               case 2:
-                       retval = mem_ap_read_buf_u16(swjdp, buffer, 2 * count, address);
-                       break;
-               case 1:
-                       retval = mem_ap_read_buf_u8(swjdp, buffer, count, address);
-                       break;
-               }
-       }
-
-       return retval;
+static int cortex_a8_write_phys_memory(struct target *target,
+                uint32_t address, uint32_t size,
+                uint32_t count, uint8_t *buffer)
+{
+        struct armv7a_common *armv7a = target_to_armv7a(target);
+        struct adiv5_dap *swjdp = &armv7a->dap;
+        int retval = ERROR_INVALID_ARGUMENTS;
+
+// ???  dap_ap_select(swjdp, swjdp_memoryap);
+
+        LOG_DEBUG("Writing memory to real address 0x%x; size %d; count %d", address, size, count);
+        if (count && buffer) {
+                switch (size) {
+                case 4:
+                        retval = mem_ap_write_buf_u32(swjdp, buffer, 4 * count, address);
+                        break;
+                case 2:
+                        retval = mem_ap_write_buf_u16(swjdp, buffer, 2 * count, address);
+                        break;
+                case 1:
+                        retval = mem_ap_write_buf_u8(swjdp, buffer, count, address);
+                        break;
+                }
+        }
+
+        /* REVISIT this op is generic ARMv7-A/R stuff */
+        if (retval == ERROR_OK && target->state == TARGET_HALTED)
+        {
+                struct arm_dpm *dpm = armv7a->armv4_5_common.dpm;
+
+                retval = dpm->prepare(dpm);
+                if (retval != ERROR_OK)
+                        return retval;
+
+                /* The Cache handling will NOT work with MMU active, the
+                 * wrong addresses will be invalidated!
+                 *
+                 * For both ICache and DCache, walk all cache lines in the
+                 * address range. Cortex-A8 has fixed 64 byte line length.
+                 *
+                 * REVISIT per ARMv7, these may trigger watchpoints ...
+                 */
+
+                /* invalidate I-Cache */
+                if (armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
+                {
+                        /* ICIMVAU - Invalidate Cache single entry
+                         * with MVA to PoU
+                         *      MCR p15, 0, r0, c7, c5, 1
+                         */
+                        for (uint32_t cacheline = address;
+                                        cacheline < address + size * count;
+                                        cacheline += 64) {
+                                retval = dpm->instr_write_data_r0(dpm,
+                                        ARMV4_5_MCR(15, 0, 0, 7, 5, 1),
+                                        cacheline);
+                                if (retval != ERROR_OK)
+                                       return retval;
+                        }
+                }
+
+                /* invalidate D-Cache */
+                if (armv7a->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
+                {
+                        /* DCIMVAC - Invalidate data Cache line
+                         * with MVA to PoC
+                         *      MCR p15, 0, r0, c7, c6, 1
+                         */
+                        for (uint32_t cacheline = address;
+                                        cacheline < address + size * count;
+                                        cacheline += 64) {
+                                retval = dpm->instr_write_data_r0(dpm,
+                                        ARMV4_5_MCR(15, 0, 0, 7, 6, 1),
+                                        cacheline);
+                                if (retval != ERROR_OK)
+                                       return retval;
+                        }
+                }
+
+                /* (void) */ dpm->finish(dpm);
+        }
+
+        return retval;
 }
 
 static int cortex_a8_write_memory(struct target *target, uint32_t address,
-               uint32_t size, uint32_t count, uint8_t *buffer)
+                uint32_t size, uint32_t count, uint8_t *buffer)
 {
-       struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct swjdp_common *swjdp = &armv7a->swjdp_info;
-       int retval = ERROR_INVALID_ARGUMENTS;
-
-// ??? dap_ap_select(swjdp, swjdp_memoryap);
-
-       if (count && buffer) {
-               switch (size) {
-               case 4:
-                       retval = mem_ap_write_buf_u32(swjdp, buffer, 4 * count, address);
-                       break;
-               case 2:
-                       retval = mem_ap_write_buf_u16(swjdp, buffer, 2 * count, address);
-                       break;
-               case 1:
-                       retval = mem_ap_write_buf_u8(swjdp, buffer, count, address);
-                       break;
-               }
-       }
-
-       /* REVISIT this op is generic ARMv7-A/R stuff */
-       if (retval == ERROR_OK && target->state == TARGET_HALTED)
-       {
-               struct arm_dpm *dpm = armv7a->armv4_5_common.dpm;
-
-               retval = dpm->prepare(dpm);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               /* The Cache handling will NOT work with MMU active, the
-                * wrong addresses will be invalidated!
-                *
-                * For both ICache and DCache, walk all cache lines in the
-                * address range. Cortex-A8 has fixed 64 byte line length.
-                *
-                * REVISIT per ARMv7, these may trigger watchpoints ...
-                */
-
-               /* invalidate I-Cache */
-               if (armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
-               {
-                       /* ICIMVAU - Invalidate Cache single entry
-                        * with MVA to PoU
-                        *      MCR p15, 0, r0, c7, c5, 1
-                        */
-                       for (uint32_t cacheline = address;
-                                       cacheline < address + size * count;
-                                       cacheline += 64) {
-                               retval = dpm->instr_write_data_r0(dpm,
-                                       ARMV4_5_MCR(15, 0, 0, 7, 5, 1),
-                                       cacheline);
-                       }
-               }
-
-               /* invalidate D-Cache */
-               if (armv7a->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
-               {
-                       /* DCIMVAC - Invalidate data Cache line
-                        * with MVA to PoC
-                        *      MCR p15, 0, r0, c7, c6, 1
-                        */
-                       for (uint32_t cacheline = address;
-                                       cacheline < address + size * count;
-                                       cacheline += 64) {
-                               retval = dpm->instr_write_data_r0(dpm,
-                                       ARMV4_5_MCR(15, 0, 0, 7, 6, 1),
-                                       cacheline);
-                       }
-               }
-
-               /* (void) */ dpm->finish(dpm);
-       }
-
-       return retval;
+        int enabled = 0;
+        uint32_t virt, phys;
+        int retval;
+
+// ???  dap_ap_select(swjdp, swjdp_memoryap);
+
+        LOG_DEBUG("Writing memory to address 0x%x; size %d; count %d", address, size, count);
+        retval = cortex_a8_mmu(target, &enabled);
+        if (retval != ERROR_OK)
+               return retval;
+        if(enabled)
+        {
+            virt = address;
+            retval = cortex_a8_virt2phys(target, virt, &phys);
+            if (retval != ERROR_OK)
+               return retval;
+            LOG_DEBUG("Writing to virtual address. Translating v:0x%x to r:0x%x", virt, phys);
+            address = phys;
+        }
+
+        return cortex_a8_write_phys_memory(target, address, size, 
+                count, buffer);
 }
 
 static int cortex_a8_bulk_write_memory(struct target *target, uint32_t address,
@@ -1387,7 +1631,7 @@ static int cortex_a8_bulk_write_memory(struct target *target, uint32_t address,
 }
 
 
-static int cortex_a8_dcc_read(struct swjdp_common *swjdp, uint8_t *value, uint8_t *ctrl)
+static int cortex_a8_dcc_read(struct adiv5_dap *swjdp, uint8_t *value, uint8_t *ctrl)
 {
 #if 0
        u16 dcrdr;
@@ -1414,7 +1658,8 @@ static int cortex_a8_handle_target_request(void *priv)
 {
        struct target *target = priv;
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct swjdp_common *swjdp = &armv7a->swjdp_info;
+       struct adiv5_dap *swjdp = &armv7a->dap;
+       int retval;
 
        if (!target_was_examined(target))
                return ERROR_OK;
@@ -1426,7 +1671,9 @@ static int cortex_a8_handle_target_request(void *priv)
                uint8_t data = 0;
                uint8_t ctrl = 0;
 
-               cortex_a8_dcc_read(swjdp, &data, &ctrl);
+               retval = cortex_a8_dcc_read(swjdp, &data, &ctrl);
+               if (retval != ERROR_OK)
+                       return retval;
 
                /* check if we have data */
                if (ctrl & (1 << 0))
@@ -1435,11 +1682,17 @@ static int cortex_a8_handle_target_request(void *priv)
 
                        /* we assume target is quick enough */
                        request = data;
-                       cortex_a8_dcc_read(swjdp, &data, &ctrl);
+                       retval = cortex_a8_dcc_read(swjdp, &data, &ctrl);
+                       if (retval != ERROR_OK)
+                               return retval;
                        request |= (data << 8);
-                       cortex_a8_dcc_read(swjdp, &data, &ctrl);
+                       retval = cortex_a8_dcc_read(swjdp, &data, &ctrl);
+                       if (retval != ERROR_OK)
+                               return retval;
                        request |= (data << 16);
-                       cortex_a8_dcc_read(swjdp, &data, &ctrl);
+                       retval = cortex_a8_dcc_read(swjdp, &data, &ctrl);
+                       if (retval != ERROR_OK)
+                               return retval;
                        request |= (data << 24);
                        target_request(target, request);
                }
@@ -1456,46 +1709,59 @@ static int cortex_a8_examine_first(struct target *target)
 {
        struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
        struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
-       struct swjdp_common *swjdp = &armv7a->swjdp_info;
+       struct adiv5_dap *swjdp = &armv7a->dap;
        int i;
        int retval = ERROR_OK;
        uint32_t didr, ctypr, ttypr, cpuid;
-
-       LOG_DEBUG("TODO");
-
-       /* Here we shall insert a proper ROM Table scan */
-       armv7a->debug_base = OMAP3530_DEBUG_BASE;
+       uint32_t dbgbase, apid;
 
        /* We do one extra read to ensure DAP is configured,
         * we call ahbap_debugport_init(swjdp) instead
         */
-       ahbap_debugport_init(swjdp);
-       mem_ap_read_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_CPUID, &cpuid);
+       retval = ahbap_debugport_init(swjdp);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* Get ROM Table base */
+       retval = dap_get_debugbase(swjdp, 1, &dbgbase, &apid);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* Lookup 0x15 -- Processor DAP */
+       retval = dap_lookup_cs_component(swjdp, 1, dbgbase, 0x15,
+                                       &armv7a->debug_base);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = mem_ap_read_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_CPUID, &cpuid);
+       if (retval != ERROR_OK)
+               return retval;
+
        if ((retval = mem_ap_read_atomic_u32(swjdp,
                        armv7a->debug_base + CPUDBG_CPUID, &cpuid)) != ERROR_OK)
        {
-               LOG_DEBUG("Examine failed");
+               LOG_DEBUG("Examine %s failed", "CPUID");
                return retval;
        }
 
        if ((retval = mem_ap_read_atomic_u32(swjdp,
                        armv7a->debug_base + CPUDBG_CTYPR, &ctypr)) != ERROR_OK)
        {
-               LOG_DEBUG("Examine failed");
+               LOG_DEBUG("Examine %s failed", "CTYPR");
                return retval;
        }
 
        if ((retval = mem_ap_read_atomic_u32(swjdp,
                        armv7a->debug_base + CPUDBG_TTYPR, &ttypr)) != ERROR_OK)
        {
-               LOG_DEBUG("Examine failed");
+               LOG_DEBUG("Examine %s failed", "TTYPR");
                return retval;
        }
 
        if ((retval = mem_ap_read_atomic_u32(swjdp,
                        armv7a->debug_base + CPUDBG_DIDR, &didr)) != ERROR_OK)
        {
-               LOG_DEBUG("Examine failed");
+               LOG_DEBUG("Examine %s failed", "DIDR");
                return retval;
        }
 
@@ -1505,7 +1771,9 @@ static int cortex_a8_examine_first(struct target *target)
        LOG_DEBUG("didr = 0x%08" PRIx32, didr);
 
        armv7a->armv4_5_common.core_type = ARM_MODE_MON;
-       cortex_a8_dpm_setup(cortex_a8, didr);
+       retval = cortex_a8_dpm_setup(cortex_a8, didr);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* Setup Breakpoint Register Pairs */
        cortex_a8->brp_num = ((didr >> 24) & 0x0F) + 1;
@@ -1562,7 +1830,9 @@ static int cortex_a8_init_arch_info(struct target *target,
 {
        struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
        struct arm *armv4_5 = &armv7a->armv4_5_common;
-       struct swjdp_common *swjdp = &armv7a->swjdp_info;
+       struct adiv5_dap *dap = &armv7a->dap;
+
+       armv7a->armv4_5_common.dap = dap;
 
        /* Setup struct cortex_a8_common */
        cortex_a8->common_magic = CORTEX_A8_COMMON_MAGIC;
@@ -1572,30 +1842,30 @@ static int cortex_a8_init_arch_info(struct target *target,
        cortex_a8->jtag_info.tap = tap;
        cortex_a8->jtag_info.scann_size = 4;
 
-       swjdp->dp_select_value = -1;
-       swjdp->ap_csw_value = -1;
-       swjdp->ap_tar_value = -1;
-       swjdp->jtag_info = &cortex_a8->jtag_info;
-       swjdp->memaccess_tck = 80;
+       /* Leave (only) generic DAP stuff for debugport_init() */
+       dap->jtag_info = &cortex_a8->jtag_info;
+       dap->memaccess_tck = 80;
 
        /* Number of bits for tar autoincrement, impl. dep. at least 10 */
-       swjdp->tar_autoincr_block = (1 << 10);
+       dap->tar_autoincr_block = (1 << 10);
 
        cortex_a8->fast_reg_read = 0;
 
+       /* Set default value */
+       cortex_a8->current_address_mode = ARM_MODE_ANY;
+
        /* register arch-specific functions */
        armv7a->examine_debug_reason = NULL;
 
        armv7a->post_debug_entry = cortex_a8_post_debug_entry;
 
        armv7a->pre_restore_context = NULL;
-       armv7a->post_restore_context = NULL;
        armv7a->armv4_5_mmu.armv4_5_cache.ctype = -1;
-//     armv7a->armv4_5_mmu.get_ttb = armv7a_get_ttb;
-       armv7a->armv4_5_mmu.read_memory = cortex_a8_read_memory;
-       armv7a->armv4_5_mmu.write_memory = cortex_a8_write_memory;
-//     armv7a->armv4_5_mmu.disable_mmu_caches = armv7a_disable_mmu_caches;
-//     armv7a->armv4_5_mmu.enable_mmu_caches = armv7a_enable_mmu_caches;
+       armv7a->armv4_5_mmu.get_ttb = cortex_a8_get_ttb;
+       armv7a->armv4_5_mmu.read_memory = cortex_a8_read_phys_memory;
+       armv7a->armv4_5_mmu.write_memory = cortex_a8_write_phys_memory;
+       armv7a->armv4_5_mmu.disable_mmu_caches = cortex_a8_disable_mmu_caches;
+       armv7a->armv4_5_mmu.enable_mmu_caches = cortex_a8_enable_mmu_caches;
        armv7a->armv4_5_mmu.has_tiny_pages = 1;
        armv7a->armv4_5_mmu.mmu_enabled = 0;
 
@@ -1615,8 +1885,174 @@ static int cortex_a8_target_create(struct target *target, Jim_Interp *interp)
 {
        struct cortex_a8_common *cortex_a8 = calloc(1, sizeof(struct cortex_a8_common));
 
-       cortex_a8_init_arch_info(target, cortex_a8, target->tap);
+       return cortex_a8_init_arch_info(target, cortex_a8, target->tap);
+}
+
+static int cortex_a8_get_ttb(struct target *target, uint32_t *result)
+{
+       struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
+    struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
+    uint32_t ttb = 0, retval = ERROR_OK;
+
+    /* current_address_mode is set inside cortex_a8_virt2phys()
+       where we can determine if address belongs to user or kernel */
+    if(cortex_a8->current_address_mode == ARM_MODE_SVC)
+    {
+        /* MRC p15,0,<Rt>,c1,c0,0 ; Read CP15 System Control Register */
+        retval = armv7a->armv4_5_common.mrc(target, 15,
+                    0, 1,   /* op1, op2 */
+                    2, 0,   /* CRn, CRm */
+                    &ttb);
+               if (retval != ERROR_OK)
+                       return retval;
+    }
+    else if(cortex_a8->current_address_mode == ARM_MODE_USR)
+    {
+        /* MRC p15,0,<Rt>,c1,c0,0 ; Read CP15 System Control Register */
+        retval = armv7a->armv4_5_common.mrc(target, 15,
+                    0, 0,   /* op1, op2 */
+                    2, 0,   /* CRn, CRm */
+                    &ttb);
+               if (retval != ERROR_OK)
+                       return retval;
+    }
+    /* we don't know whose address is: user or kernel
+       we assume that if we are in kernel mode then
+       address belongs to kernel else if in user mode
+       - to user */
+    else if(armv7a->armv4_5_common.core_mode == ARM_MODE_SVC)
+    {
+        /* MRC p15,0,<Rt>,c1,c0,0 ; Read CP15 System Control Register */
+        retval = armv7a->armv4_5_common.mrc(target, 15,
+                    0, 1,   /* op1, op2 */
+                    2, 0,   /* CRn, CRm */
+                    &ttb);
+               if (retval != ERROR_OK)
+                       return retval;
+    }
+    else if(armv7a->armv4_5_common.core_mode == ARM_MODE_USR)
+    {
+        /* MRC p15,0,<Rt>,c1,c0,0 ; Read CP15 System Control Register */
+        retval = armv7a->armv4_5_common.mrc(target, 15,
+                    0, 0,   /* op1, op2 */
+                    2, 0,   /* CRn, CRm */
+                    &ttb);
+               if (retval != ERROR_OK)
+                       return retval;
+    }
+    /* finally we don't know whose ttb to use: user or kernel */
+    else
+        LOG_ERROR("Don't know how to get ttb for current mode!!!");
+
+    ttb &= 0xffffc000;
+
+    *result = ttb;
+
+    return ERROR_OK;
+}
+
+static int cortex_a8_disable_mmu_caches(struct target *target, int mmu,
+                int d_u_cache, int i_cache)
+{
+    struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
+    struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
+    uint32_t cp15_control;
+    int retval;
+
+    /* read cp15 control register */
+    retval = armv7a->armv4_5_common.mrc(target, 15,
+                    0, 0,   /* op1, op2 */
+                    1, 0,   /* CRn, CRm */
+                    &cp15_control);
+    if (retval != ERROR_OK)
+       return retval;
+
+
+    if (mmu)
+            cp15_control &= ~0x1U;
+
+    if (d_u_cache)
+            cp15_control &= ~0x4U;
+
+    if (i_cache)
+            cp15_control &= ~0x1000U;
+
+    retval = armv7a->armv4_5_common.mcr(target, 15,
+                    0, 0,   /* op1, op2 */
+                    1, 0,   /* CRn, CRm */
+                    cp15_control);
+       return retval;
+}
+
+static int cortex_a8_enable_mmu_caches(struct target *target, int mmu,
+                int d_u_cache, int i_cache)
+{
+    struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
+    struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
+    uint32_t cp15_control;
+    int retval;
+
+    /* read cp15 control register */
+    retval = armv7a->armv4_5_common.mrc(target, 15,
+                    0, 0,   /* op1, op2 */
+                    1, 0,   /* CRn, CRm */
+                    &cp15_control);
+    if (retval != ERROR_OK)
+       return retval;
+
+    if (mmu)
+            cp15_control |= 0x1U;
+
+    if (d_u_cache)
+            cp15_control |= 0x4U;
+
+    if (i_cache)
+            cp15_control |= 0x1000U;
+
+    retval = armv7a->armv4_5_common.mcr(target, 15,
+                    0, 0,   /* op1, op2 */
+                    1, 0,   /* CRn, CRm */
+                    cp15_control);
+       return retval;
+}
+
+
+static int cortex_a8_mmu(struct target *target, int *enabled)
+{
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("%s: target not halted", __func__);
+               return ERROR_TARGET_INVALID;
+       }
 
+       *enabled = target_to_cortex_a8(target)->armv7a_common.armv4_5_mmu.mmu_enabled;
+       return ERROR_OK;
+}
+
+static int cortex_a8_virt2phys(struct target *target,
+               uint32_t virt, uint32_t *phys)
+{
+       uint32_t cb;
+       struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
+       // struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
+       struct armv7a_common *armv7a = target_to_armv7a(target);
+
+    /* We assume that virtual address is separated
+       between user and kernel in Linux style:
+       0x00000000-0xbfffffff - User space
+       0xc0000000-0xffffffff - Kernel space */
+    if( virt < 0xc0000000 ) /* Linux user space */
+        cortex_a8->current_address_mode = ARM_MODE_USR;
+    else /* Linux kernel */
+        cortex_a8->current_address_mode = ARM_MODE_SVC;
+       uint32_t ret;
+       int retval = armv4_5_mmu_translate_va(target,
+                       &armv7a->armv4_5_mmu, virt, &cb, &ret);
+       if (retval != ERROR_OK)
+               return retval;
+    /* Reset the flag. We don't want someone else to use it by error */
+    cortex_a8->current_address_mode = ARM_MODE_ANY;
+
+       *phys = ret;
        return ERROR_OK;
 }
 
@@ -1633,22 +2069,25 @@ COMMAND_HANDLER(cortex_a8_handle_cache_info_command)
 COMMAND_HANDLER(cortex_a8_handle_dbginit_command)
 {
        struct target *target = get_current_target(CMD_CTX);
+       if (!target_was_examined(target))
+       {
+               LOG_ERROR("target not examined yet");
+               return ERROR_FAIL;
+       }
 
-       cortex_a8_init_debug_access(target);
-
-       return ERROR_OK;
+       return cortex_a8_init_debug_access(target);
 }
 
 static const struct command_registration cortex_a8_exec_command_handlers[] = {
        {
                .name = "cache_info",
-               .handler = &cortex_a8_handle_cache_info_command,
+               .handler = cortex_a8_handle_cache_info_command,
                .mode = COMMAND_EXEC,
                .help = "display information about target caches",
        },
        {
                .name = "dbginit",
-               .handler = &cortex_a8_handle_dbginit_command,
+               .handler = cortex_a8_handle_dbginit_command,
                .mode = COMMAND_EXEC,
                .help = "Initialize core debug",
        },
@@ -1686,6 +2125,7 @@ struct target_type cortexa8_target = {
        .deassert_reset = cortex_a8_deassert_reset,
        .soft_reset_halt = NULL,
 
+       /* REVISIT allow exporting VFP3 registers ... */
        .get_gdb_reg_list = arm_get_gdb_reg_list,
 
        .read_memory = cortex_a8_read_memory,
@@ -1706,4 +2146,10 @@ struct target_type cortexa8_target = {
        .target_create = cortex_a8_target_create,
        .init_target = cortex_a8_init_target,
        .examine = cortex_a8_examine,
+
+       .read_phys_memory = cortex_a8_read_phys_memory,
+       .write_phys_memory = cortex_a8_write_phys_memory,
+       .mmu = cortex_a8_mmu,
+       .virt2phys = cortex_a8_virt2phys,
+
 };

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)