openocd: remove CamelCase symbols *xPSR*
[fw/openocd] / src / target / cortex_a.c
index 4c0d163fbc9f603c5543972b2be7f8690774ddad..2e81d140cf95868c7653b9ef4645815cd1fe7c6c 100644 (file)
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
 /***************************************************************************
  *   Copyright (C) 2005 by Dominic Rath                                    *
  *   Dominic.Rath@gmx.de                                                   *
  *   michel.jaouen@stericsson.com : smp minimum support                    *
  *                                                                         *
  *   Copyright (C) Broadcom 2012                                           *
- *   ehunter@broadcom.com : Cortex R4 support                              *
+ *   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     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
+ *   Copyright (C) 2016 Chengyu Zheng                                      *
+ *   chengyu.zheng@polimi.it : watchpoint support                          *
  *                                                                         *
  *   Cortex-A8(tm) TRM, ARM DDI 0344H                                      *
  *   Cortex-A9(tm) TRM, ARM DDI 0407F                                      *
 #include "breakpoints.h"
 #include "cortex_a.h"
 #include "register.h"
+#include "armv7a_mmu.h"
 #include "target_request.h"
 #include "target_type.h"
+#include "arm_coresight.h"
 #include "arm_opcodes.h"
+#include "arm_semihosting.h"
+#include "jtag/interface.h"
+#include "transport/transport.h"
+#include "smp.h"
+#include <helper/bits.h>
 #include <helper/time_support.h>
 
 static int cortex_a_poll(struct target *target);
@@ -68,17 +65,25 @@ static int cortex_a_set_hybrid_breakpoint(struct target *target,
        struct breakpoint *breakpoint);
 static int cortex_a_unset_breakpoint(struct target *target,
        struct breakpoint *breakpoint);
-static int cortex_a_dap_read_coreregister_u32(struct target *target,
-       uint32_t *value, int regnum);
-static int cortex_a_dap_write_coreregister_u32(struct target *target,
-       uint32_t value, int regnum);
+static int cortex_a_wait_dscr_bits(struct target *target, uint32_t mask,
+       uint32_t value, uint32_t *dscr);
 static int cortex_a_mmu(struct target *target, int *enabled);
 static int cortex_a_mmu_modify(struct target *target, int enable);
 static int cortex_a_virt2phys(struct target *target,
-       uint32_t virt, uint32_t *phys);
-static int cortex_a_read_apb_ab_memory(struct target *target,
+       target_addr_t virt, target_addr_t *phys);
+static int cortex_a_read_cpu_memory(struct target *target,
        uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
 
+static unsigned int ilog2(unsigned int x)
+{
+       unsigned int y = 0;
+       x /= 2;
+       while (x) {
+               ++y;
+               x /= 2;
+               }
+       return y;
+}
 
 /*  restore cp15_control_reg at resume */
 static int cortex_a_restore_cp15_control_reg(struct target *target)
@@ -110,7 +115,7 @@ static int cortex_a_prep_memaccess(struct target *target, int phys_access)
        int mmu_enabled = 0;
 
        if (phys_access == 0) {
-               dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC);
+               arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC);
                cortex_a_mmu(target, &mmu_enabled);
                if (mmu_enabled)
                        cortex_a_mmu_modify(target, 1);
@@ -145,7 +150,7 @@ static int cortex_a_post_memaccess(struct target *target, int phys_access)
                                        0, 0, 3, 0,
                                        cortex_a->cp15_dacr_reg);
                }
-               dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
+               arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
        } else {
                int mmu_enabled = 0;
                cortex_a_mmu(target, &mmu_enabled);
@@ -196,99 +201,52 @@ static int cortex_a_mmu_modify(struct target *target, int enable)
        return retval;
 }
 
-/*
- * 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);
+       uint32_t dscr;
        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_u32(armv7a->debug_ap,
+                       armv7a->debug_base + CPUDBG_LOCKACCESS, 0);
        if (retval != ERROR_OK)
                return retval;
 
        /* Disable cacheline fills and force cache write-through in debug state */
-       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+       retval = mem_ap_write_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCCR, 0);
        if (retval != ERROR_OK)
                return retval;
 
        /* Disable TLB lookup and refill/eviction in debug state */
-       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+       retval = mem_ap_write_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSMCR, 0);
        if (retval != ERROR_OK)
                return retval;
 
+       retval = dap_run(armv7a->debug_ap->dap);
+       if (retval != ERROR_OK)
+               return retval;
+
        /* Enabling of instruction execution in debug mode is done in debug_entry code */
 
        /* Resync breakpoint registers */
 
+       /* Enable halt for breakpoint, watchpoint and vector catch */
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
+                       armv7a->debug_base + CPUDBG_DSCR, &dscr);
+       if (retval != ERROR_OK)
+               return retval;
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+                       armv7a->debug_base + CPUDBG_DSCR, dscr | DSCR_HALT_DBG_MODE);
+       if (retval != ERROR_OK)
+               return retval;
+
        /* Since this is likely called from init or reset, update target state information*/
        return cortex_a_poll(target);
 }
@@ -299,21 +257,21 @@ static int cortex_a_wait_instrcmpl(struct target *target, uint32_t *dscr, bool f
         * Writes final value of DSCR into *dscr. Pass force to force always
         * reading DSCR at least once. */
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       int64_t then = timeval_ms();
-       while ((*dscr & DSCR_INSTR_COMP) == 0 || force) {
-               force = false;
-               int retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
+       int retval;
+
+       if (force) {
+               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DSCR, dscr);
                if (retval != ERROR_OK) {
                        LOG_ERROR("Could not read DSCR register");
                        return retval;
                }
-               if (timeval_ms() > then + 1000) {
-                       LOG_ERROR("Timeout waiting for InstrCompl=1");
-                       return ERROR_FAIL;
-               }
        }
-       return ERROR_OK;
+
+       retval = cortex_a_wait_dscr_bits(target, DSCR_INSTR_COMP, DSCR_INSTR_COMP, dscr);
+       if (retval != ERROR_OK)
+               LOG_ERROR("Error waiting for InstrCompl=1");
+       return retval;
 }
 
 /* To reduce needless round-trips, pass in a pointer to the current
@@ -342,188 +300,15 @@ static int cortex_a_exec_opcode(struct target *target,
        if (retval != ERROR_OK)
                return retval;
 
-       int64_t then = timeval_ms();
-       do {
-               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                               armv7a->debug_base + CPUDBG_DSCR, &dscr);
-               if (retval != ERROR_OK) {
-                       LOG_ERROR("Could not read DSCR register");
-                       return retval;
-               }
-               if (timeval_ms() > then + 1000) {
-                       LOG_ERROR("Timeout waiting for cortex_a_exec_opcode");
-                       return ERROR_FAIL;
-               }
-       } while ((dscr & DSCR_INSTR_COMP) == 0);        /* Wait for InstrCompl bit to be set */
-
-       if (dscr_p)
-               *dscr_p = dscr;
-
-       return retval;
-}
-
-/**************************************************************************
-Read core register with very few exec_opcode, fast but needs work_area.
-This can cause problems with MMU active.
-**************************************************************************/
-static int cortex_a_read_regs_through_mem(struct target *target, uint32_t address,
-       uint32_t *regfile)
-{
-       int retval = ERROR_OK;
-       struct armv7a_common *armv7a = target_to_armv7a(target);
-
-       retval = cortex_a_dap_read_coreregister_u32(target, regfile, 0);
-       if (retval != ERROR_OK)
-               return retval;
-       retval = cortex_a_dap_write_coreregister_u32(target, address, 0);
-       if (retval != ERROR_OK)
-               return retval;
-       retval = cortex_a_exec_opcode(target, ARMV4_5_STMIA(0, 0xFFFE, 0, 0), NULL);
-       if (retval != ERROR_OK)
-               return retval;
-
-       retval = mem_ap_read_buf(armv7a->memory_ap,
-                       (uint8_t *)(&regfile[1]), 4, 15, address);
-
-       return retval;
-}
-
-static int cortex_a_dap_read_coreregister_u32(struct target *target,
-       uint32_t *value, int regnum)
-{
-       int retval = ERROR_OK;
-       uint8_t reg = regnum&0xFF;
-       uint32_t dscr = 0;
-       struct armv7a_common *armv7a = target_to_armv7a(target);
-
-       if (reg > 17)
-               return retval;
-
-       if (reg < 15) {
-               /* Rn to DCCTX, "MCR p14, 0, Rn, c0, c5, 0"  0xEE00nE15 */
-               retval = cortex_a_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 */
-               retval = cortex_a_exec_opcode(target, 0xE1A0000F, &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-               retval = cortex_a_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
-                */
-               retval = cortex_a_exec_opcode(target, ARMV4_5_MRS(0, reg & 1), &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-               retval = cortex_a_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 */
-       int64_t then = timeval_ms();
-       while ((dscr & DSCR_DTR_TX_FULL) == 0) {
-               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                               armv7a->debug_base + CPUDBG_DSCR, &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-               if (timeval_ms() > then + 1000) {
-                       LOG_ERROR("Timeout waiting for cortex_a_exec_opcode");
-                       return ERROR_FAIL;
-               }
-       }
-
-       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                       armv7a->debug_base + CPUDBG_DTRTX, value);
-       LOG_DEBUG("read DCC 0x%08" PRIx32, *value);
-
-       return retval;
-}
-
-static int cortex_a_dap_write_coreregister_u32(struct target *target,
-       uint32_t value, int regnum)
-{
-       int retval = ERROR_OK;
-       uint8_t Rd = regnum&0xFF;
-       uint32_t dscr;
-       struct armv7a_common *armv7a = target_to_armv7a(target);
-
-       LOG_DEBUG("register %i, value 0x%08" PRIx32, regnum, value);
-
-       /* Check that DCCRX is not full */
-       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                       armv7a->debug_base + CPUDBG_DSCR, &dscr);
-       if (retval != ERROR_OK)
+       /* Wait for InstrCompl bit to be set */
+       retval = cortex_a_wait_instrcmpl(target, &dscr, true);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error waiting for cortex_a_exec_opcode");
                return retval;
-       if (dscr & DSCR_DTR_RX_FULL) {
-               LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr);
-               /* Clear DCCRX with MRC(p14, 0, Rd, c0, c5, 0), opcode  0xEE100E15 */
-               retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
-                               &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
        }
 
-       if (Rd > 17)
-               return retval;
-
-       /* Write DTRRX ... sets DSCR.DTRRXfull but exec_opcode() won't care */
-       LOG_DEBUG("write DCC 0x%08" PRIx32, value);
-       retval = mem_ap_write_u32(armv7a->debug_ap,
-                       armv7a->debug_base + CPUDBG_DTRRX, value);
-       if (retval != ERROR_OK)
-               return retval;
-
-       if (Rd < 15) {
-               /* DCCRX to Rn, "MRC p14, 0, Rn, c0, c5, 0", 0xEE10nE15 */
-               retval = cortex_a_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, "MRC p14, 0, R0, c0, c5, 0", 0xEE100E15
-                * then "mov r15, r0"
-                */
-               retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
-                               &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-               retval = cortex_a_exec_opcode(target, 0xE1A0F000, &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-       } else {
-               /* DCCRX to R0, "MRC p14, 0, R0, c0, c5, 0", 0xEE100E15
-                * then "MSR CPSR_cxsf, r0" or "MSR SPSR_cxsf, r0" (all fields)
-                */
-               retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
-                               &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-               retval = cortex_a_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) {
-                       retval = cortex_a_exec_opcode(target,
-                                       ARMV4_5_MCR(15, 0, 0, 7, 5, 4),
-                                       &dscr);
-                       if (retval != ERROR_OK)
-                               return retval;
-               }
-       }
+       if (dscr_p)
+               *dscr_p = dscr;
 
        return retval;
 }
@@ -574,17 +359,11 @@ static int cortex_a_read_dcc(struct cortex_a_common *a, uint32_t *data,
                dscr = *dscr_p;
 
        /* Wait for DTRRXfull */
-       int64_t then = timeval_ms();
-       while ((dscr & DSCR_DTR_TX_FULL) == 0) {
-               retval = mem_ap_read_atomic_u32(a->armv7a_common.debug_ap,
-                               a->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 = cortex_a_wait_dscr_bits(a->armv7a_common.arm.target,
+                       DSCR_DTR_TX_FULL, DSCR_DTR_TX_FULL, &dscr);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error waiting for read dcc");
+               return retval;
        }
 
        retval = mem_ap_read_atomic_u32(a->armv7a_common.debug_ap,
@@ -606,19 +385,10 @@ static int cortex_a_dpm_prepare(struct arm_dpm *dpm)
        int retval;
 
        /* set up invariant:  INSTR_COMP is set after ever DPM operation */
-       int64_t then = timeval_ms();
-       for (;; ) {
-               retval = mem_ap_read_atomic_u32(a->armv7a_common.debug_ap,
-                               a->armv7a_common.debug_base + CPUDBG_DSCR,
-                               &dscr);
-               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;
-               }
+       retval = cortex_a_wait_instrcmpl(dpm->arm->target, &dscr, true);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error waiting for dpm prepare");
+               return retval;
        }
 
        /* this "should never happen" ... */
@@ -659,22 +429,35 @@ static int cortex_a_instr_write_data_dcc(struct arm_dpm *dpm,
                        &dscr);
 }
 
-static int cortex_a_instr_write_data_r0(struct arm_dpm *dpm,
-       uint32_t opcode, uint32_t data)
+static int cortex_a_instr_write_data_rt_dcc(struct arm_dpm *dpm,
+       uint8_t rt, uint32_t data)
 {
        struct cortex_a_common *a = dpm_to_a(dpm);
        uint32_t dscr = DSCR_INSTR_COMP;
        int retval;
 
+       if (rt > 15)
+               return ERROR_TARGET_INVALID;
+
        retval = cortex_a_write_dcc(a, data);
        if (retval != ERROR_OK)
                return retval;
 
-       /* DCCRX to R0, "MCR p14, 0, R0, c0, c5, 0", 0xEE000E15 */
-       retval = cortex_a_exec_opcode(
+       /* DCCRX to Rt, "MCR p14, 0, R0, c0, c5, 0", 0xEE000E15 */
+       return cortex_a_exec_opcode(
                        a->armv7a_common.arm.target,
-                       ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
+                       ARMV4_5_MRC(14, 0, rt, 0, 5, 0),
                        &dscr);
+}
+
+static int cortex_a_instr_write_data_r0(struct arm_dpm *dpm,
+       uint32_t opcode, uint32_t data)
+{
+       struct cortex_a_common *a = dpm_to_a(dpm);
+       uint32_t dscr = DSCR_INSTR_COMP;
+       int retval;
+
+       retval = cortex_a_instr_write_data_rt_dcc(dpm, 0, data);
        if (retval != ERROR_OK)
                return retval;
 
@@ -716,31 +499,43 @@ static int cortex_a_instr_read_data_dcc(struct arm_dpm *dpm,
        return cortex_a_read_dcc(a, data, &dscr);
 }
 
-
-static int cortex_a_instr_read_data_r0(struct arm_dpm *dpm,
-       uint32_t opcode, uint32_t *data)
+static int cortex_a_instr_read_data_rt_dcc(struct arm_dpm *dpm,
+       uint8_t rt, uint32_t *data)
 {
        struct cortex_a_common *a = dpm_to_a(dpm);
        uint32_t dscr = DSCR_INSTR_COMP;
        int retval;
 
-       /* the opcode, writing data to R0 */
+       if (rt > 15)
+               return ERROR_TARGET_INVALID;
+
        retval = cortex_a_exec_opcode(
                        a->armv7a_common.arm.target,
-                       opcode,
+                       ARMV4_5_MCR(14, 0, rt, 0, 5, 0),
                        &dscr);
        if (retval != ERROR_OK)
                return retval;
 
-       /* write R0 to DCC */
+       return cortex_a_read_dcc(a, data, &dscr);
+}
+
+static int cortex_a_instr_read_data_r0(struct arm_dpm *dpm,
+       uint32_t opcode, uint32_t *data)
+{
+       struct cortex_a_common *a = dpm_to_a(dpm);
+       uint32_t dscr = DSCR_INSTR_COMP;
+       int retval;
+
+       /* the opcode, writing data to R0 */
        retval = cortex_a_exec_opcode(
                        a->armv7a_common.arm.target,
-                       ARMV4_5_MCR(14, 0, 0, 0, 5, 0),
+                       opcode,
                        &dscr);
        if (retval != ERROR_OK)
                return retval;
 
-       return cortex_a_read_dcc(a, data, &dscr);
+       /* write R0 to DCC */
+       return cortex_a_instr_read_data_rt_dcc(dpm, 0, data);
 }
 
 static int cortex_a_bpwp_enable(struct arm_dpm *dpm, unsigned index_t,
@@ -833,14 +628,11 @@ static int cortex_a_dpm_setup(struct cortex_a_common *a, uint32_t didr)
 static struct target *get_cortex_a(struct target *target, int32_t coreid)
 {
        struct target_list *head;
-       struct target *curr;
 
-       head = target->head;
-       while (head != (struct target_list *)NULL) {
-               curr = head->target;
+       foreach_smp_target(head, target->smp_targets) {
+               struct target *curr = head->target;
                if ((curr->coreid == coreid) && (curr->state == TARGET_HALTED))
                        return curr;
-               head = head->next;
        }
        return target;
 }
@@ -850,25 +642,55 @@ static int cortex_a_halt_smp(struct target *target)
 {
        int retval = 0;
        struct target_list *head;
-       struct target *curr;
-       head = target->head;
-       while (head != (struct target_list *)NULL) {
-               curr = head->target;
-               if ((curr != target) && (curr->state != TARGET_HALTED))
+
+       foreach_smp_target(head, target->smp_targets) {
+               struct target *curr = head->target;
+               if ((curr != target) && (curr->state != TARGET_HALTED)
+                       && target_was_examined(curr))
                        retval += cortex_a_halt(curr);
-               head = head->next;
        }
        return retval;
 }
 
 static int update_halt_gdb(struct target *target)
 {
+       struct target *gdb_target = NULL;
+       struct target_list *head;
+       struct target *curr;
        int retval = 0;
+
        if (target->gdb_service && target->gdb_service->core[0] == -1) {
                target->gdb_service->target = target;
                target->gdb_service->core[0] = target->coreid;
                retval += cortex_a_halt_smp(target);
        }
+
+       if (target->gdb_service)
+               gdb_target = target->gdb_service->target;
+
+       foreach_smp_target(head, target->smp_targets) {
+               curr = head->target;
+               /* skip calling context */
+               if (curr == target)
+                       continue;
+               if (!target_was_examined(curr))
+                       continue;
+               /* skip targets that were already halted */
+               if (curr->state == TARGET_HALTED)
+                       continue;
+               /* Skip gdb_target; it alerts GDB so has to be polled as last one */
+               if (curr == gdb_target)
+                       continue;
+
+               /* avoid recursion in cortex_a_poll() */
+               curr->smp = 0;
+               cortex_a_poll(curr);
+               curr->smp = 1;
+       }
+
+       /* after all targets were updated, poll the gdb serving target */
+       if (gdb_target && gdb_target != target)
+               cortex_a_poll(gdb_target);
        return retval;
 }
 
@@ -889,7 +711,7 @@ static int cortex_a_poll(struct target *target)
        /*  the next polling trigger an halt event sent to gdb */
        if ((target->state == TARGET_HALTED) && (target->smp) &&
                (target->gdb_service) &&
-               (target->gdb_service->target == NULL)) {
+               (!target->gdb_service->target)) {
                target->gdb_service->target =
                        get_cortex_a(target, target->gdb_service->core[1]);
                target_call_event_callbacks(target, TARGET_EVENT_HALTED);
@@ -906,49 +728,36 @@ static int cortex_a_poll(struct target *target)
                        /* We have a halting debug event */
                        LOG_DEBUG("Target halted");
                        target->state = TARGET_HALTED;
-                       if ((prev_target_state == TARGET_RUNNING)
-                               || (prev_target_state == TARGET_UNKNOWN)
-                               || (prev_target_state == TARGET_RESET)) {
-                               retval = cortex_a_debug_entry(target);
+
+                       retval = cortex_a_debug_entry(target);
+                       if (retval != ERROR_OK)
+                               return retval;
+
+                       if (target->smp) {
+                               retval = update_halt_gdb(target);
                                if (retval != ERROR_OK)
                                        return retval;
-                               if (target->smp) {
-                                       retval = update_halt_gdb(target);
-                                       if (retval != ERROR_OK)
-                                               return retval;
-                               }
-                               target_call_event_callbacks(target,
-                                       TARGET_EVENT_HALTED);
                        }
-                       if (prev_target_state == TARGET_DEBUG_RUNNING) {
-                               LOG_DEBUG(" ");
 
-                               retval = cortex_a_debug_entry(target);
-                               if (retval != ERROR_OK)
+                       if (prev_target_state == TARGET_DEBUG_RUNNING) {
+                               target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
+                       } else { /* prev_target_state is RUNNING, UNKNOWN or RESET */
+                               if (arm_semihosting(target, &retval) != 0)
                                        return retval;
-                               if (target->smp) {
-                                       retval = update_halt_gdb(target);
-                                       if (retval != ERROR_OK)
-                                               return retval;
-                               }
 
                                target_call_event_callbacks(target,
-                                       TARGET_EVENT_DEBUG_HALTED);
+                                       TARGET_EVENT_HALTED);
                        }
                }
-       } else if (DSCR_RUN_MODE(dscr) == DSCR_CORE_RESTARTED)
+       } else
                target->state = TARGET_RUNNING;
-       else {
-               LOG_DEBUG("Unknown target state dscr = 0x%08" PRIx32, dscr);
-               target->state = TARGET_UNKNOWN;
-       }
 
        return retval;
 }
 
 static int cortex_a_halt(struct target *target)
 {
-       int retval = ERROR_OK;
+       int retval;
        uint32_t dscr;
        struct armv7a_common *armv7a = target_to_armv7a(target);
 
@@ -961,31 +770,12 @@ static int cortex_a_halt(struct target *target)
        if (retval != ERROR_OK)
                return retval;
 
-       /*
-        * enter halting debug mode
-        */
-       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                       armv7a->debug_base + CPUDBG_DSCR, &dscr);
-       if (retval != ERROR_OK)
-               return retval;
-
-       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
-                       armv7a->debug_base + CPUDBG_DSCR, dscr | DSCR_HALT_DBG_MODE);
-       if (retval != ERROR_OK)
+       dscr = 0; /* force read of dscr */
+       retval = cortex_a_wait_dscr_bits(target, DSCR_CORE_HALTED,
+                       DSCR_CORE_HALTED, &dscr);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error waiting for halt");
                return retval;
-
-       int64_t then = timeval_ms();
-       for (;; ) {
-               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                               armv7a->debug_base + CPUDBG_DSCR, &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-               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;
@@ -994,7 +784,7 @@ static int cortex_a_halt(struct target *target)
 }
 
 static int cortex_a_internal_restore(struct target *target, int current,
-       uint32_t *address, int handle_breakpoints, int debug_execution)
+       target_addr_t *address, int handle_breakpoints, int debug_execution)
 {
        struct armv7a_common *armv7a = target_to_armv7a(target);
        struct arm *arm = &armv7a->arm;
@@ -1013,15 +803,15 @@ static int cortex_a_internal_restore(struct target *target, int current,
                 * C_MASKINTS in parallel with disabled interrupts can cause
                 * local faults to not be taken. */
                buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_PRIMASK].value, 0, 32, 1);
-               armv7m->core_cache->reg_list[ARMV7M_PRIMASK].dirty = 1;
-               armv7m->core_cache->reg_list[ARMV7M_PRIMASK].valid = 1;
+               armv7m->core_cache->reg_list[ARMV7M_PRIMASK].dirty = true;
+               armv7m->core_cache->reg_list[ARMV7M_PRIMASK].valid = true;
 
                /* Make sure we are in Thumb mode */
-               buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32,
-                       buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0,
+               buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_XPSR].value, 0, 32,
+                       buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_XPSR].value, 0,
                        32) | (1 << 24));
-               armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = 1;
-               armv7m->core_cache->reg_list[ARMV7M_xPSR].valid = 1;
+               armv7m->core_cache->reg_list[ARMV7M_XPSR].dirty = true;
+               armv7m->core_cache->reg_list[ARMV7M_XPSR].valid = true;
        }
 #endif
 
@@ -1049,14 +839,17 @@ static int cortex_a_internal_restore(struct target *target, int current,
                case ARM_STATE_JAZELLE:
                        LOG_ERROR("How do I resume into Jazelle state??");
                        return ERROR_FAIL;
+               case ARM_STATE_AARCH64:
+                       LOG_ERROR("Shouldn't be in AARCH64 state");
+                       return ERROR_FAIL;
        }
        LOG_DEBUG("resume pc = 0x%08" PRIx32, resume_pc);
        buf_set_u32(arm->pc->value, 0, 32, resume_pc);
-       arm->pc->dirty = 1;
-       arm->pc->valid = 1;
+       arm->pc->dirty = true;
+       arm->pc->valid = true;
 
        /* restore dpm_mode at system halt */
-       dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
+       arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
        /* called it now before restoring context because it uses cpu
         * register r0 for restoring cp15 control register */
        retval = cortex_a_restore_cp15_control_reg(target);
@@ -1121,18 +914,12 @@ static int cortex_a_internal_restart(struct target *target)
        if (retval != ERROR_OK)
                return retval;
 
-       int64_t then = timeval_ms();
-       for (;; ) {
-               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                               armv7a->debug_base + CPUDBG_DSCR, &dscr);
-               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;
-               }
+       dscr = 0; /* force read of dscr */
+       retval = cortex_a_wait_dscr_bits(target, DSCR_CORE_RESTARTED,
+                       DSCR_CORE_RESTARTED, &dscr);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error waiting for resume");
+               return retval;
        }
 
        target->debug_reason = DBG_REASON_NOTHALTED;
@@ -1148,25 +935,23 @@ static int cortex_a_restore_smp(struct target *target, int handle_breakpoints)
 {
        int retval = 0;
        struct target_list *head;
-       struct target *curr;
-       uint32_t address;
-       head = target->head;
-       while (head != (struct target_list *)NULL) {
-               curr = head->target;
-               if ((curr != target) && (curr->state != TARGET_RUNNING)) {
+       target_addr_t address;
+
+       foreach_smp_target(head, target->smp_targets) {
+               struct target *curr = head->target;
+               if ((curr != target) && (curr->state != TARGET_RUNNING)
+                       && target_was_examined(curr)) {
                        /*  resume current address , not in step mode */
                        retval += cortex_a_internal_restore(curr, 1, &address,
                                        handle_breakpoints, 0);
                        retval += cortex_a_internal_restart(curr);
                }
-               head = head->next;
-
        }
        return retval;
 }
 
 static int cortex_a_resume(struct target *target, int current,
-       uint32_t address, int handle_breakpoints, int debug_execution)
+       target_addr_t address, int handle_breakpoints, int debug_execution)
 {
        int retval = 0;
        /* dummy resume for smp toggle in order to reduce gdb impact  */
@@ -1190,11 +975,11 @@ static int cortex_a_resume(struct target *target, int current,
        if (!debug_execution) {
                target->state = TARGET_RUNNING;
                target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
-               LOG_DEBUG("target resumed at 0x%" PRIx32, address);
+               LOG_DEBUG("target resumed at " TARGET_ADDR_FMT, address);
        } else {
                target->state = TARGET_DEBUG_RUNNING;
                target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
-               LOG_DEBUG("target debug resumed at 0x%" PRIx32, address);
+               LOG_DEBUG("target debug resumed at " TARGET_ADDR_FMT, address);
        }
 
        return ERROR_OK;
@@ -1202,14 +987,11 @@ static int cortex_a_resume(struct target *target, int current,
 
 static int cortex_a_debug_entry(struct target *target)
 {
-       int i;
-       uint32_t regfile[16], cpsr, dscr;
+       uint32_t dscr;
        int retval = ERROR_OK;
-       struct working_area *regfile_working_area = NULL;
        struct cortex_a_common *cortex_a = target_to_cortex_a(target);
        struct armv7a_common *armv7a = target_to_armv7a(target);
        struct arm *arm = &armv7a->arm;
-       struct reg *reg;
 
        LOG_DEBUG("dscr = 0x%08" PRIx32, cortex_a->cpudbg_dscr);
 
@@ -1246,54 +1028,16 @@ static int cortex_a_debug_entry(struct target *target)
                arm_dpm_report_wfar(&armv7a->dpm, wfar);
        }
 
-       /* REVISIT fast_reg_read is never set ... */
-
-       /* Examine target state and mode */
-       if (cortex_a->fast_reg_read)
-               target_alloc_working_area(target, 64, &regfile_working_area);
-
-       /* First load register acessible through core debug port*/
-       if (!regfile_working_area)
-               retval = arm_dpm_read_current_registers(&armv7a->dpm);
-       else {
-               retval = cortex_a_read_regs_through_mem(target,
-                               regfile_working_area->address, regfile);
-
-               target_free_working_area(target, regfile_working_area);
-               if (retval != ERROR_OK)
-                       return retval;
+       /* First load register accessible through core debug port */
+       retval = arm_dpm_read_current_registers(&armv7a->dpm);
+       if (retval != ERROR_OK)
+               return retval;
 
-               /* read Current PSR */
-               retval = cortex_a_dap_read_coreregister_u32(target, &cpsr, 16);
-               /*  store current cpsr */
+       if (arm->spsr) {
+               /* read SPSR */
+               retval = arm_dpm_read_reg(&armv7a->dpm, arm->spsr, 17);
                if (retval != ERROR_OK)
                        return retval;
-
-               LOG_DEBUG("cpsr: %8.8" PRIx32, cpsr);
-
-               arm_set_cpsr(arm, cpsr);
-
-               /* update cache */
-               for (i = 0; i <= ARM_PC; i++) {
-                       reg = arm_reg_current(arm, i);
-
-                       buf_set_u32(reg->value, 0, 32, regfile[i]);
-                       reg->valid = 1;
-                       reg->dirty = 0;
-               }
-
-               /* Fixup PC Resume Address */
-               if (cpsr & (1 << 5)) {
-                       /* T bit set for Thumb or ThumbEE state */
-                       regfile[ARM_PC] -= 4;
-               } else {
-                       /* ARM state */
-                       regfile[ARM_PC] -= 8;
-               }
-
-               reg = arm->pc;
-               buf_set_u32(reg->value, 0, 32, regfile[ARM_PC]);
-               reg->dirty = reg->valid;
        }
 
 #if 0
@@ -1336,6 +1080,9 @@ static int cortex_a_post_debug_entry(struct target *target)
        LOG_DEBUG("cp15_control_reg: %8.8" PRIx32, cortex_a->cp15_control_reg);
        cortex_a->cp15_control_reg_curr = cortex_a->cp15_control_reg;
 
+       if (!armv7a->is_armv7r)
+               armv7a_read_ttbcr(target);
+
        if (armv7a->armv7a_mmu.armv7a_cache.info == -1)
                armv7a_identify_cache(target);
 
@@ -1352,7 +1099,7 @@ static int cortex_a_post_debug_entry(struct target *target)
        cortex_a->curr_mode = armv7a->arm.core_mode;
 
        /* switch to SVC mode to read DACR */
-       dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC);
+       arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC);
        armv7a->arm.mrc(target, 15,
                        0, 0, 3, 0,
                        &cortex_a->cp15_dacr_reg);
@@ -1360,11 +1107,12 @@ static int cortex_a_post_debug_entry(struct target *target)
        LOG_DEBUG("cp15_dacr_reg: %8.8" PRIx32,
                        cortex_a->cp15_dacr_reg);
 
-       dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
+       arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
        return ERROR_OK;
 }
 
-int cortex_a_set_dscr_bits(struct target *target, unsigned long bit_mask, unsigned long value)
+static int cortex_a_set_dscr_bits(struct target *target,
+               unsigned long bit_mask, unsigned long value)
 {
        struct armv7a_common *armv7a = target_to_armv7a(target);
        uint32_t dscr;
@@ -1372,7 +1120,7 @@ int cortex_a_set_dscr_bits(struct target *target, unsigned long bit_mask, unsign
        /* Read DSCR */
        int retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
-       if (ERROR_OK != retval)
+       if (retval != ERROR_OK)
                return retval;
 
        /* clear bitfield */
@@ -1386,7 +1134,7 @@ int cortex_a_set_dscr_bits(struct target *target, unsigned long bit_mask, unsign
        return retval;
 }
 
-static int cortex_a_step(struct target *target, int current, uint32_t address,
+static int cortex_a_step(struct target *target, int current, target_addr_t address,
        int handle_breakpoints)
 {
        struct cortex_a_common *cortex_a = target_to_cortex_a(target);
@@ -1422,15 +1170,16 @@ static int cortex_a_step(struct target *target, int current, uint32_t address,
 
        /* Setup single step breakpoint */
        stepbreakpoint.address = address;
+       stepbreakpoint.asid = 0;
        stepbreakpoint.length = (arm->core_state == ARM_STATE_THUMB)
                ? 2 : 4;
        stepbreakpoint.type = BKPT_HARD;
-       stepbreakpoint.set = 0;
+       stepbreakpoint.is_set = false;
 
        /* Disable interrupts during single step if requested */
        if (cortex_a->isrmasking_mode == CORTEX_A_ISRMASK_ON) {
                retval = cortex_a_set_dscr_bits(target, DSCR_INT_DIS, DSCR_INT_DIS);
-               if (ERROR_OK != retval)
+               if (retval != ERROR_OK)
                        return retval;
        }
 
@@ -1448,6 +1197,8 @@ static int cortex_a_step(struct target *target, int current, uint32_t address,
                retval = cortex_a_poll(target);
                if (retval != ERROR_OK)
                        return retval;
+               if (target->state == TARGET_HALTED)
+                       break;
                if (timeval_ms() > then + 1000) {
                        LOG_ERROR("timeout waiting for target halt");
                        return ERROR_FAIL;
@@ -1459,7 +1210,7 @@ static int cortex_a_step(struct target *target, int current, uint32_t address,
        /* Re-enable interrupts if they were disabled */
        if (cortex_a->isrmasking_mode == CORTEX_A_ISRMASK_ON) {
                retval = cortex_a_set_dscr_bits(target, DSCR_INT_DIS, 0);
-               if (ERROR_OK != retval)
+               if (retval != ERROR_OK)
                        return retval;
        }
 
@@ -1503,7 +1254,7 @@ static int cortex_a_set_breakpoint(struct target *target,
        struct armv7a_common *armv7a = &cortex_a->armv7a_common;
        struct cortex_a_brp *brp_list = cortex_a->brp_list;
 
-       if (breakpoint->set) {
+       if (breakpoint->is_set) {
                LOG_WARNING("breakpoint already set");
                return ERROR_OK;
        }
@@ -1515,22 +1266,22 @@ static int cortex_a_set_breakpoint(struct target *target,
                        LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
                        return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
                }
-               breakpoint->set = brp_i + 1;
+               breakpoint_hw_set(breakpoint, brp_i);
                if (breakpoint->length == 2)
                        byte_addr_select = (3 << (breakpoint->address & 0x02));
                control = ((matchmode & 0x7) << 20)
                        | (byte_addr_select << 5)
                        | (3 << 1) | 1;
-               brp_list[brp_i].used = 1;
+               brp_list[brp_i].used = true;
                brp_list[brp_i].value = (breakpoint->address & 0xFFFFFFFC);
                brp_list[brp_i].control = control;
                retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                               + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
+                               + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn,
                                brp_list[brp_i].value);
                if (retval != ERROR_OK)
                        return retval;
                retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                               + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
+                               + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn,
                                brp_list[brp_i].control);
                if (retval != ERROR_OK)
                        return retval;
@@ -1539,10 +1290,22 @@ static int cortex_a_set_breakpoint(struct target *target,
                        brp_list[brp_i].value);
        } else if (breakpoint->type == BKPT_SOFT) {
                uint8_t code[4];
+               /* length == 2: Thumb breakpoint */
                if (breakpoint->length == 2)
                        buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11));
                else
+               /* length == 3: Thumb-2 breakpoint, actual encoding is
+                * a regular Thumb BKPT instruction but we replace a
+                * 32bit Thumb-2 instruction, so fix-up the breakpoint
+                * length
+                */
+               if (breakpoint->length == 3) {
+                       buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11));
+                       breakpoint->length = 4;
+               } else
+                       /* length == 4, normal ARM breakpoint */
                        buf_set_u32(code, 0, 32, ARMV5_BKPT(0x11));
+
                retval = target_read_memory(target,
                                breakpoint->address & 0xFFFFFFFE,
                                breakpoint->length, 1,
@@ -1568,7 +1331,7 @@ static int cortex_a_set_breakpoint(struct target *target,
                armv7a_l1_i_cache_inval_virt(target, breakpoint->address,
                                                 breakpoint->length);
 
-               breakpoint->set = 0x11; /* Any nice value but 0 */
+               breakpoint->is_set = true;
        }
 
        return ERROR_OK;
@@ -1585,7 +1348,7 @@ static int cortex_a_set_context_breakpoint(struct target *target,
        struct armv7a_common *armv7a = &cortex_a->armv7a_common;
        struct cortex_a_brp *brp_list = cortex_a->brp_list;
 
-       if (breakpoint->set) {
+       if (breakpoint->is_set) {
                LOG_WARNING("breakpoint already set");
                return retval;
        }
@@ -1599,20 +1362,20 @@ static int cortex_a_set_context_breakpoint(struct target *target,
                return ERROR_FAIL;
        }
 
-       breakpoint->set = brp_i + 1;
+       breakpoint_hw_set(breakpoint, brp_i);
        control = ((matchmode & 0x7) << 20)
                | (byte_addr_select << 5)
                | (3 << 1) | 1;
-       brp_list[brp_i].used = 1;
+       brp_list[brp_i].used = true;
        brp_list[brp_i].value = (breakpoint->asid);
        brp_list[brp_i].control = control;
        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
+                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn,
                        brp_list[brp_i].value);
        if (retval != ERROR_OK)
                return retval;
        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
+                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn,
                        brp_list[brp_i].control);
        if (retval != ERROR_OK)
                return retval;
@@ -1628,16 +1391,16 @@ static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoi
        int retval = ERROR_FAIL;
        int brp_1 = 0;  /* holds the contextID pair */
        int brp_2 = 0;  /* holds the IVA pair */
-       uint32_t control_CTX, control_IVA;
-       uint8_t CTX_byte_addr_select = 0x0F;
-       uint8_t IVA_byte_addr_select = 0x0F;
-       uint8_t CTX_machmode = 0x03;
-       uint8_t IVA_machmode = 0x01;
+       uint32_t control_ctx, control_iva;
+       uint8_t ctx_byte_addr_select = 0x0F;
+       uint8_t iva_byte_addr_select = 0x0F;
+       uint8_t ctx_machmode = 0x03;
+       uint8_t iva_machmode = 0x01;
        struct cortex_a_common *cortex_a = target_to_cortex_a(target);
        struct armv7a_common *armv7a = &cortex_a->armv7a_common;
        struct cortex_a_brp *brp_list = cortex_a->brp_list;
 
-       if (breakpoint->set) {
+       if (breakpoint->is_set) {
                LOG_WARNING("breakpoint already set");
                return retval;
        }
@@ -1646,7 +1409,7 @@ static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoi
                (brp_list[brp_1].type != BRP_CONTEXT)) && (brp_1 < cortex_a->brp_num))
                brp_1++;
 
-       printf("brp(CTX) found num: %d\n", brp_1);
+       LOG_DEBUG("brp(CTX) found num: %d", brp_1);
        if (brp_1 >= cortex_a->brp_num) {
                LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
                return ERROR_FAIL;
@@ -1656,47 +1419,47 @@ static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoi
                (brp_list[brp_2].type != BRP_NORMAL)) && (brp_2 < cortex_a->brp_num))
                brp_2++;
 
-       printf("brp(IVA) found num: %d\n", brp_2);
+       LOG_DEBUG("brp(IVA) found num: %d", brp_2);
        if (brp_2 >= cortex_a->brp_num) {
                LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
                return ERROR_FAIL;
        }
 
-       breakpoint->set = brp_1 + 1;
-       breakpoint->linked_BRP = brp_2;
-       control_CTX = ((CTX_machmode & 0x7) << 20)
+       breakpoint_hw_set(breakpoint, brp_1);
+       breakpoint->linked_brp = brp_2;
+       control_ctx = ((ctx_machmode & 0x7) << 20)
                | (brp_2 << 16)
                | (0 << 14)
-               | (CTX_byte_addr_select << 5)
+               | (ctx_byte_addr_select << 5)
                | (3 << 1) | 1;
-       brp_list[brp_1].used = 1;
+       brp_list[brp_1].used = true;
        brp_list[brp_1].value = (breakpoint->asid);
-       brp_list[brp_1].control = control_CTX;
+       brp_list[brp_1].control = control_ctx;
        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_1].BRPn,
+                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_1].brpn,
                        brp_list[brp_1].value);
        if (retval != ERROR_OK)
                return retval;
        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_1].BRPn,
+                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_1].brpn,
                        brp_list[brp_1].control);
        if (retval != ERROR_OK)
                return retval;
 
-       control_IVA = ((IVA_machmode & 0x7) << 20)
+       control_iva = ((iva_machmode & 0x7) << 20)
                | (brp_1 << 16)
-               | (IVA_byte_addr_select << 5)
+               | (iva_byte_addr_select << 5)
                | (3 << 1) | 1;
-       brp_list[brp_2].used = 1;
+       brp_list[brp_2].used = true;
        brp_list[brp_2].value = (breakpoint->address & 0xFFFFFFFC);
-       brp_list[brp_2].control = control_IVA;
+       brp_list[brp_2].control = control_iva;
        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_2].BRPn,
+                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_2].brpn,
                        brp_list[brp_2].value);
        if (retval != ERROR_OK)
                return retval;
        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_2].BRPn,
+                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_2].brpn,
                        brp_list[brp_2].control);
        if (retval != ERROR_OK)
                return retval;
@@ -1711,31 +1474,31 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b
        struct armv7a_common *armv7a = &cortex_a->armv7a_common;
        struct cortex_a_brp *brp_list = cortex_a->brp_list;
 
-       if (!breakpoint->set) {
+       if (!breakpoint->is_set) {
                LOG_WARNING("breakpoint not set");
                return ERROR_OK;
        }
 
        if (breakpoint->type == BKPT_HARD) {
                if ((breakpoint->address != 0) && (breakpoint->asid != 0)) {
-                       int brp_i = breakpoint->set - 1;
-                       int brp_j = breakpoint->linked_BRP;
-                       if ((brp_i < 0) || (brp_i >= cortex_a->brp_num)) {
+                       int brp_i = breakpoint->number;
+                       int brp_j = breakpoint->linked_brp;
+                       if (brp_i >= cortex_a->brp_num) {
                                LOG_DEBUG("Invalid BRP number in breakpoint");
                                return ERROR_OK;
                        }
                        LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
                                brp_list[brp_i].control, brp_list[brp_i].value);
-                       brp_list[brp_i].used = 0;
+                       brp_list[brp_i].used = false;
                        brp_list[brp_i].value = 0;
                        brp_list[brp_i].control = 0;
                        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
+                                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn,
                                        brp_list[brp_i].control);
                        if (retval != ERROR_OK)
                                return retval;
                        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
+                                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn,
                                        brp_list[brp_i].value);
                        if (retval != ERROR_OK)
                                return retval;
@@ -1745,45 +1508,45 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b
                        }
                        LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_j,
                                brp_list[brp_j].control, brp_list[brp_j].value);
-                       brp_list[brp_j].used = 0;
+                       brp_list[brp_j].used = false;
                        brp_list[brp_j].value = 0;
                        brp_list[brp_j].control = 0;
                        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_j].BRPn,
+                                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_j].brpn,
                                        brp_list[brp_j].control);
                        if (retval != ERROR_OK)
                                return retval;
                        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_j].BRPn,
+                                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_j].brpn,
                                        brp_list[brp_j].value);
                        if (retval != ERROR_OK)
                                return retval;
-                       breakpoint->linked_BRP = 0;
-                       breakpoint->set = 0;
+                       breakpoint->linked_brp = 0;
+                       breakpoint->is_set = false;
                        return ERROR_OK;
 
                } else {
-                       int brp_i = breakpoint->set - 1;
-                       if ((brp_i < 0) || (brp_i >= cortex_a->brp_num)) {
+                       int brp_i = breakpoint->number;
+                       if (brp_i >= cortex_a->brp_num) {
                                LOG_DEBUG("Invalid BRP number in breakpoint");
                                return ERROR_OK;
                        }
                        LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
                                brp_list[brp_i].control, brp_list[brp_i].value);
-                       brp_list[brp_i].used = 0;
+                       brp_list[brp_i].used = false;
                        brp_list[brp_i].value = 0;
                        brp_list[brp_i].control = 0;
                        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
+                                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn,
                                        brp_list[brp_i].control);
                        if (retval != ERROR_OK)
                                return retval;
                        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
+                                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn,
                                        brp_list[brp_i].value);
                        if (retval != ERROR_OK)
                                return retval;
-                       breakpoint->set = 0;
+                       breakpoint->is_set = false;
                        return ERROR_OK;
                }
        } else {
@@ -1815,7 +1578,7 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b
                armv7a_l1_i_cache_inval_virt(target, breakpoint->address,
                                                 breakpoint->length);
        }
-       breakpoint->set = 0;
+       breakpoint->is_set = false;
 
        return ERROR_OK;
 }
@@ -1881,7 +1644,7 @@ static int cortex_a_remove_breakpoint(struct target *target, struct breakpoint *
        }
 #endif
 
-       if (breakpoint->set) {
+       if (breakpoint->is_set) {
                cortex_a_unset_breakpoint(target, breakpoint);
                if (breakpoint->type == BKPT_HARD)
                        cortex_a->brp_num_available++;
@@ -1891,6 +1654,200 @@ static int cortex_a_remove_breakpoint(struct target *target, struct breakpoint *
        return ERROR_OK;
 }
 
+/**
+ * Sets a watchpoint for an Cortex-A target in one of the watchpoint units.  It is
+ * considered a bug to call this function when there are no available watchpoint
+ * units.
+ *
+ * @param target Pointer to an Cortex-A target to set a watchpoint on
+ * @param watchpoint Pointer to the watchpoint to be set
+ * @return Error status if watchpoint set fails or the result of executing the
+ * JTAG queue
+ */
+static int cortex_a_set_watchpoint(struct target *target, struct watchpoint *watchpoint)
+{
+       int retval = ERROR_OK;
+       int wrp_i = 0;
+       uint32_t control;
+       uint32_t address;
+       uint8_t address_mask;
+       uint8_t byte_address_select;
+       uint8_t load_store_access_control = 0x3;
+       struct cortex_a_common *cortex_a = target_to_cortex_a(target);
+       struct armv7a_common *armv7a = &cortex_a->armv7a_common;
+       struct cortex_a_wrp *wrp_list = cortex_a->wrp_list;
+
+       if (watchpoint->is_set) {
+               LOG_WARNING("watchpoint already set");
+               return retval;
+       }
+
+       /* check available context WRPs */
+       while (wrp_list[wrp_i].used && (wrp_i < cortex_a->wrp_num))
+               wrp_i++;
+
+       if (wrp_i >= cortex_a->wrp_num) {
+               LOG_ERROR("ERROR Can not find free Watchpoint Register Pair");
+               return ERROR_FAIL;
+       }
+
+       if (watchpoint->length == 0 || watchpoint->length > 0x80000000U ||
+                       (watchpoint->length & (watchpoint->length - 1))) {
+               LOG_WARNING("watchpoint length must be a power of 2");
+               return ERROR_FAIL;
+       }
+
+       if (watchpoint->address & (watchpoint->length - 1)) {
+               LOG_WARNING("watchpoint address must be aligned at length");
+               return ERROR_FAIL;
+       }
+
+       /* FIXME: ARM DDI 0406C: address_mask is optional. What to do if it's missing?  */
+       /* handle wp length 1 and 2 through byte select */
+       switch (watchpoint->length) {
+       case 1:
+               byte_address_select = BIT(watchpoint->address & 0x3);
+               address = watchpoint->address & ~0x3;
+               address_mask = 0;
+               break;
+
+       case 2:
+               byte_address_select = 0x03 << (watchpoint->address & 0x2);
+               address = watchpoint->address & ~0x3;
+               address_mask = 0;
+               break;
+
+       case 4:
+               byte_address_select = 0x0f;
+               address = watchpoint->address;
+               address_mask = 0;
+               break;
+
+       default:
+               byte_address_select = 0xff;
+               address = watchpoint->address;
+               address_mask = ilog2(watchpoint->length);
+               break;
+       }
+
+       watchpoint_set(watchpoint, wrp_i);
+       control = (address_mask << 24) |
+               (byte_address_select << 5) |
+               (load_store_access_control << 3) |
+               (0x3 << 1) | 1;
+       wrp_list[wrp_i].used = true;
+       wrp_list[wrp_i].value = address;
+       wrp_list[wrp_i].control = control;
+
+       retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
+                       + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].wrpn,
+                       wrp_list[wrp_i].value);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
+                       + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].wrpn,
+                       wrp_list[wrp_i].control);
+       if (retval != ERROR_OK)
+               return retval;
+
+       LOG_DEBUG("wp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, wrp_i,
+                       wrp_list[wrp_i].control,
+                       wrp_list[wrp_i].value);
+
+       return ERROR_OK;
+}
+
+/**
+ * Unset an existing watchpoint and clear the used watchpoint unit.
+ *
+ * @param target Pointer to the target to have the watchpoint removed
+ * @param watchpoint Pointer to the watchpoint to be removed
+ * @return Error status while trying to unset the watchpoint or the result of
+ *         executing the JTAG queue
+ */
+static int cortex_a_unset_watchpoint(struct target *target, struct watchpoint *watchpoint)
+{
+       int retval;
+       struct cortex_a_common *cortex_a = target_to_cortex_a(target);
+       struct armv7a_common *armv7a = &cortex_a->armv7a_common;
+       struct cortex_a_wrp *wrp_list = cortex_a->wrp_list;
+
+       if (!watchpoint->is_set) {
+               LOG_WARNING("watchpoint not set");
+               return ERROR_OK;
+       }
+
+       int wrp_i = watchpoint->number;
+       if (wrp_i >= cortex_a->wrp_num) {
+               LOG_DEBUG("Invalid WRP number in watchpoint");
+               return ERROR_OK;
+       }
+       LOG_DEBUG("wrp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, wrp_i,
+                       wrp_list[wrp_i].control, wrp_list[wrp_i].value);
+       wrp_list[wrp_i].used = false;
+       wrp_list[wrp_i].value = 0;
+       wrp_list[wrp_i].control = 0;
+       retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
+                       + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].wrpn,
+                       wrp_list[wrp_i].control);
+       if (retval != ERROR_OK)
+               return retval;
+       retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
+                       + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].wrpn,
+                       wrp_list[wrp_i].value);
+       if (retval != ERROR_OK)
+               return retval;
+       watchpoint->is_set = false;
+
+       return ERROR_OK;
+}
+
+/**
+ * Add a watchpoint to an Cortex-A target.  If there are no watchpoint units
+ * available, an error response is returned.
+ *
+ * @param target Pointer to the Cortex-A target to add a watchpoint to
+ * @param watchpoint Pointer to the watchpoint to be added
+ * @return Error status while trying to add the watchpoint
+ */
+static int cortex_a_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
+{
+       struct cortex_a_common *cortex_a = target_to_cortex_a(target);
+
+       if (cortex_a->wrp_num_available < 1) {
+               LOG_INFO("no hardware watchpoint available");
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+
+       int retval = cortex_a_set_watchpoint(target, watchpoint);
+       if (retval != ERROR_OK)
+               return retval;
+
+       cortex_a->wrp_num_available--;
+       return ERROR_OK;
+}
+
+/**
+ * Remove a watchpoint from an Cortex-A target.  The watchpoint will be unset and
+ * the used watchpoint unit will be reopened.
+ *
+ * @param target Pointer to the target to remove a watchpoint from
+ * @param watchpoint Pointer to the watchpoint to be removed
+ * @return Result of trying to unset the watchpoint
+ */
+static int cortex_a_remove_watchpoint(struct target *target, struct watchpoint *watchpoint)
+{
+       struct cortex_a_common *cortex_a = target_to_cortex_a(target);
+
+       if (watchpoint->is_set) {
+               cortex_a->wrp_num_available++;
+               cortex_a_unset_watchpoint(target, watchpoint);
+       }
+       return ERROR_OK;
+}
+
+
 /*
  * Cortex-A Reset functions
  */
@@ -1912,14 +1869,23 @@ static int cortex_a_assert_reset(struct target *target)
                /* REVISIT handle "pulls" cases, if there's
                 * hardware that needs them to work.
                 */
-               jtag_add_reset(0, 1);
+
+               /*
+                * FIXME: fix reset when transport is not JTAG. This is a temporary
+                * work-around for release v0.10 that is not intended to stay!
+                */
+               if (!transport_is_jtag() ||
+                               (target->reset_halt && (jtag_get_reset_config() & RESET_SRST_NO_GATING)))
+                       adapter_assert_reset();
+
        } else {
                LOG_ERROR("%s: how to reset?", target_name(target));
                return ERROR_FAIL;
        }
 
        /* registers are now invalid */
-       register_cache_invalidate(armv7a->arm.core_cache);
+       if (target_was_examined(target))
+               register_cache_invalidate(armv7a->arm.core_cache);
 
        target->state = TARGET_RESET;
 
@@ -1928,24 +1894,31 @@ static int cortex_a_assert_reset(struct target *target)
 
 static int cortex_a_deassert_reset(struct target *target)
 {
+       struct armv7a_common *armv7a = target_to_armv7a(target);
        int retval;
 
        LOG_DEBUG(" ");
 
        /* be certain SRST is off */
-       jtag_add_reset(0, 0);
+       adapter_deassert_reset();
 
-       retval = cortex_a_poll(target);
-       if (retval != ERROR_OK)
-               return retval;
+       if (target_was_examined(target)) {
+               retval = cortex_a_poll(target);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
 
        if (target->reset_halt) {
                if (target->state != TARGET_HALTED) {
                        LOG_WARNING("%s: ran after reset and before halt ...",
                                target_name(target));
-                       retval = target_halt(target);
-                       if (retval != ERROR_OK)
-                               return retval;
+                       if (target_was_examined(target)) {
+                               retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+                                               armv7a->debug_base + CPUDBG_DRCR, DRCR_HALT);
+                               if (retval != ERROR_OK)
+                                       return retval;
+                       } else
+                               target->state = TARGET_UNKNOWN;
                }
        }
 
@@ -1979,14 +1952,22 @@ static int cortex_a_wait_dscr_bits(struct target *target, uint32_t mask,
 {
        /* Waits until the specified bit(s) of DSCR take on a specified value. */
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       int64_t then = timeval_ms();
+       int64_t then;
        int retval;
 
-       while ((*dscr & mask) != value) {
+       if ((*dscr & mask) == value)
+               return ERROR_OK;
+
+       then = timeval_ms();
+       while (1) {
                retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DSCR, dscr);
-               if (retval != ERROR_OK)
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("Could not read DSCR register");
                        return retval;
+               }
+               if ((*dscr & mask) == value)
+                       break;
                if (timeval_ms() > then + 1000) {
                        LOG_ERROR("timeout waiting for DSCR bit change");
                        return ERROR_FAIL;
@@ -2125,13 +2106,14 @@ static int cortex_a_dfsr_to_error_code(uint32_t dfsr)
        }
 }
 
-static int cortex_a_write_apb_ab_memory_slow(struct target *target,
+static int cortex_a_write_cpu_memory_slow(struct target *target,
        uint32_t size, uint32_t count, const uint8_t *buffer, uint32_t *dscr)
 {
        /* Writes count objects of size size from *buffer. Old value of DSCR must
         * be in *dscr; updated to new value. This is slow because it works for
-        * non-word-sized objects and (maybe) unaligned accesses. If size == 4 and
-        * the address is aligned, cortex_a_write_apb_ab_memory_fast should be
+        * non-word-sized objects. Avoid unaligned accesses as they do not work
+        * on memory address space without "Normal" attribute. If size == 4 and
+        * the address is aligned, cortex_a_write_cpu_memory_fast should be
         * preferred.
         * Preconditions:
         * - Address is in R0.
@@ -2200,7 +2182,7 @@ static int cortex_a_write_apb_ab_memory_slow(struct target *target,
        return ERROR_OK;
 }
 
-static int cortex_a_write_apb_ab_memory_fast(struct target *target,
+static int cortex_a_write_cpu_memory_fast(struct target *target,
        uint32_t count, const uint8_t *buffer, uint32_t *dscr)
 {
        /* Writes count objects of size 4 from *buffer. Old value of DSCR must be
@@ -2229,17 +2211,17 @@ static int cortex_a_write_apb_ab_memory_fast(struct target *target,
                        4, count, armv7a->debug_base + CPUDBG_DTRRX);
 }
 
-static int cortex_a_write_apb_ab_memory(struct target *target,
+static int cortex_a_write_cpu_memory(struct target *target,
        uint32_t address, uint32_t size,
        uint32_t count, const uint8_t *buffer)
 {
-       /* Write memory through APB-AP. */
+       /* Write memory through the CPU. */
        int retval, final_retval;
        struct armv7a_common *armv7a = target_to_armv7a(target);
        struct arm *arm = &armv7a->arm;
        uint32_t dscr, orig_dfar, orig_dfsr, fault_dscr, fault_dfar, fault_dfsr;
 
-       LOG_DEBUG("Writing APB-AP memory address 0x%" PRIx32 " size %"  PRIu32 " count %"  PRIu32,
+       LOG_DEBUG("Writing CPU memory address 0x%" PRIx32 " size %"  PRIu32 " count %"  PRIu32,
                          address, size, count);
        if (target->state != TARGET_HALTED) {
                LOG_WARNING("target not halted");
@@ -2285,10 +2267,25 @@ static int cortex_a_write_apb_ab_memory(struct target *target,
 
        if (size == 4 && (address % 4) == 0) {
                /* We are doing a word-aligned transfer, so use fast mode. */
-               retval = cortex_a_write_apb_ab_memory_fast(target, count, buffer, &dscr);
+               retval = cortex_a_write_cpu_memory_fast(target, count, buffer, &dscr);
        } else {
-               /* Use slow path. */
-               retval = cortex_a_write_apb_ab_memory_slow(target, size, count, buffer, &dscr);
+               /* Use slow path. Adjust size for aligned accesses */
+               switch (address % 4) {
+                       case 1:
+                       case 3:
+                               count *= size;
+                               size = 1;
+                               break;
+                       case 2:
+                               if (size == 4) {
+                                       count *= 2;
+                                       size = 2;
+                               }
+                       case 0:
+                       default:
+                               break;
+               }
+               retval = cortex_a_write_cpu_memory_slow(target, size, count, buffer, &dscr);
        }
 
 out:
@@ -2368,13 +2365,14 @@ out:
        return final_retval;
 }
 
-static int cortex_a_read_apb_ab_memory_slow(struct target *target,
+static int cortex_a_read_cpu_memory_slow(struct target *target,
        uint32_t size, uint32_t count, uint8_t *buffer, uint32_t *dscr)
 {
        /* Reads count objects of size size into *buffer. Old value of DSCR must be
         * in *dscr; updated to new value. This is slow because it works for
-        * non-word-sized objects and (maybe) unaligned accesses. If size == 4 and
-        * the address is aligned, cortex_a_read_apb_ab_memory_fast should be
+        * non-word-sized objects. Avoid unaligned accesses as they do not work
+        * on memory address space without "Normal" attribute. If size == 4 and
+        * the address is aligned, cortex_a_read_cpu_memory_fast should be
         * preferred.
         * Preconditions:
         * - Address is in R0.
@@ -2444,7 +2442,7 @@ static int cortex_a_read_apb_ab_memory_slow(struct target *target,
        return ERROR_OK;
 }
 
-static int cortex_a_read_apb_ab_memory_fast(struct target *target,
+static int cortex_a_read_cpu_memory_fast(struct target *target,
        uint32_t count, uint8_t *buffer, uint32_t *dscr)
 {
        /* Reads count objects of size 4 into *buffer. Old value of DSCR must be in
@@ -2531,17 +2529,17 @@ static int cortex_a_read_apb_ab_memory_fast(struct target *target,
        return ERROR_OK;
 }
 
-static int cortex_a_read_apb_ab_memory(struct target *target,
+static int cortex_a_read_cpu_memory(struct target *target,
        uint32_t address, uint32_t size,
        uint32_t count, uint8_t *buffer)
 {
-       /* Read memory through APB-AP. */
+       /* Read memory through the CPU. */
        int retval, final_retval;
        struct armv7a_common *armv7a = target_to_armv7a(target);
        struct arm *arm = &armv7a->arm;
        uint32_t dscr, orig_dfar, orig_dfsr, fault_dscr, fault_dfar, fault_dfsr;
 
-       LOG_DEBUG("Reading APB-AP memory address 0x%" PRIx32 " size %"  PRIu32 " count %"  PRIu32,
+       LOG_DEBUG("Reading CPU memory address 0x%" PRIx32 " size %"  PRIu32 " count %"  PRIu32,
                          address, size, count);
        if (target->state != TARGET_HALTED) {
                LOG_WARNING("target not halted");
@@ -2587,10 +2585,26 @@ static int cortex_a_read_apb_ab_memory(struct target *target,
 
        if (size == 4 && (address % 4) == 0) {
                /* We are doing a word-aligned transfer, so use fast mode. */
-               retval = cortex_a_read_apb_ab_memory_fast(target, count, buffer, &dscr);
+               retval = cortex_a_read_cpu_memory_fast(target, count, buffer, &dscr);
        } else {
-               /* Use slow path. */
-               retval = cortex_a_read_apb_ab_memory_slow(target, size, count, buffer, &dscr);
+               /* Use slow path. Adjust size for aligned accesses */
+               switch (address % 4) {
+                       case 1:
+                       case 3:
+                               count *= size;
+                               size = 1;
+                               break;
+                       case 2:
+                               if (size == 4) {
+                                       count *= 2;
+                                       size = 2;
+                               }
+                               break;
+                       case 0:
+                       default:
+                               break;
+               }
+               retval = cortex_a_read_cpu_memory_slow(target, size, count, buffer, &dscr);
        }
 
 out:
@@ -2662,184 +2676,85 @@ out:
 /*
  * Cortex-A Memory access
  *
- * This is same Cortex M3 but we must also use the correct
+ * This is same Cortex-M3 but we must also use the correct
  * ap number for every access.
  */
 
 static int cortex_a_read_phys_memory(struct target *target,
-       uint32_t address, uint32_t size,
+       target_addr_t address, uint32_t size,
        uint32_t count, uint8_t *buffer)
 {
-       struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
-       uint8_t apsel = swjdp->apsel;
        int retval;
 
        if (!count || !buffer)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       LOG_DEBUG("Reading memory at real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32,
+       LOG_DEBUG("Reading memory at real address " TARGET_ADDR_FMT "; size %" PRIu32 "; count %" PRIu32,
                address, size, count);
 
-       if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap->ap_num))
-               return mem_ap_read_buf(armv7a->memory_ap, buffer, size, count, address);
-
-       /* read memory through APB-AP */
+       /* read memory through the CPU */
        cortex_a_prep_memaccess(target, 1);
-       retval = cortex_a_read_apb_ab_memory(target, address, size, count, buffer);
+       retval = cortex_a_read_cpu_memory(target, address, size, count, buffer);
        cortex_a_post_memaccess(target, 1);
 
        return retval;
 }
 
-static int cortex_a_read_memory(struct target *target, uint32_t address,
+static int cortex_a_read_memory(struct target *target, target_addr_t address,
        uint32_t size, uint32_t count, uint8_t *buffer)
 {
        int retval;
 
        /* cortex_a handles unaligned memory access */
-       LOG_DEBUG("Reading memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address,
-               size, count);
+       LOG_DEBUG("Reading memory at address " TARGET_ADDR_FMT "; size %" PRIu32 "; count %" PRIu32,
+               address, size, count);
 
        cortex_a_prep_memaccess(target, 0);
-       retval = cortex_a_read_apb_ab_memory(target, address, size, count, buffer);
+       retval = cortex_a_read_cpu_memory(target, address, size, count, buffer);
        cortex_a_post_memaccess(target, 0);
 
        return retval;
 }
 
-static int cortex_a_read_memory_ahb(struct target *target, uint32_t address,
-       uint32_t size, uint32_t count, uint8_t *buffer)
-{
-       int mmu_enabled = 0;
-       uint32_t virt, phys;
-       int retval;
-       struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
-       uint8_t apsel = swjdp->apsel;
-
-       if (!armv7a->memory_ap_available || (apsel != armv7a->memory_ap->ap_num))
-               return target_read_memory(target, address, size, count, buffer);
-
-       /* cortex_a handles unaligned memory access */
-       LOG_DEBUG("Reading memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address,
-               size, count);
-
-       /* determine if MMU was enabled on target stop */
-       if (!armv7a->is_armv7r) {
-               retval = cortex_a_mmu(target, &mmu_enabled);
-               if (retval != ERROR_OK)
-                       return retval;
-       }
-
-       if (mmu_enabled) {
-               virt = address;
-               retval = cortex_a_virt2phys(target, virt, &phys);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               LOG_DEBUG("Reading at virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32,
-                         virt, phys);
-               address = phys;
-       }
-
-       if (!count || !buffer)
-               return ERROR_COMMAND_SYNTAX_ERROR;
-
-       retval = mem_ap_read_buf(armv7a->memory_ap, buffer, size, count, address);
-
-       return retval;
-}
-
 static int cortex_a_write_phys_memory(struct target *target,
-       uint32_t address, uint32_t size,
+       target_addr_t address, uint32_t size,
        uint32_t count, const uint8_t *buffer)
 {
-       struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
-       uint8_t apsel = swjdp->apsel;
        int retval;
 
        if (!count || !buffer)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       LOG_DEBUG("Writing memory to real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address,
-               size, count);
-
-       if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap->ap_num))
-               return mem_ap_write_buf(armv7a->memory_ap, buffer, size, count, address);
+       LOG_DEBUG("Writing memory to real address " TARGET_ADDR_FMT "; size %" PRIu32 "; count %" PRIu32,
+               address, size, count);
 
-       /* write memory through APB-AP */
+       /* write memory through the CPU */
        cortex_a_prep_memaccess(target, 1);
-       retval = cortex_a_write_apb_ab_memory(target, address, size, count, buffer);
+       retval = cortex_a_write_cpu_memory(target, address, size, count, buffer);
        cortex_a_post_memaccess(target, 1);
 
        return retval;
 }
 
-static int cortex_a_write_memory(struct target *target, uint32_t address,
+static int cortex_a_write_memory(struct target *target, target_addr_t address,
        uint32_t size, uint32_t count, const uint8_t *buffer)
 {
        int retval;
 
        /* cortex_a handles unaligned memory access */
-       LOG_DEBUG("Writing memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address,
-               size, count);
+       LOG_DEBUG("Writing memory at address " TARGET_ADDR_FMT "; size %" PRIu32 "; count %" PRIu32,
+               address, size, count);
 
        /* memory writes bypass the caches, must flush before writing */
        armv7a_cache_auto_flush_on_write(target, address, size * count);
 
        cortex_a_prep_memaccess(target, 0);
-       retval = cortex_a_write_apb_ab_memory(target, address, size, count, buffer);
+       retval = cortex_a_write_cpu_memory(target, address, size, count, buffer);
        cortex_a_post_memaccess(target, 0);
        return retval;
 }
 
-static int cortex_a_write_memory_ahb(struct target *target, uint32_t address,
-       uint32_t size, uint32_t count, const uint8_t *buffer)
-{
-       int mmu_enabled = 0;
-       uint32_t virt, phys;
-       int retval;
-       struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
-       uint8_t apsel = swjdp->apsel;
-
-       if (!armv7a->memory_ap_available || (apsel != armv7a->memory_ap->ap_num))
-               return target_write_memory(target, address, size, count, buffer);
-
-       /* cortex_a handles unaligned memory access */
-       LOG_DEBUG("Writing memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address,
-               size, count);
-
-       /* determine if MMU was enabled on target stop */
-       if (!armv7a->is_armv7r) {
-               retval = cortex_a_mmu(target, &mmu_enabled);
-               if (retval != ERROR_OK)
-                       return retval;
-       }
-
-       if (mmu_enabled) {
-               virt = address;
-               retval = cortex_a_virt2phys(target, virt, &phys);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               LOG_DEBUG("Writing to virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32,
-                         virt,
-                         phys);
-               address = phys;
-       }
-
-       if (!count || !buffer)
-               return ERROR_COMMAND_SYNTAX_ERROR;
-
-       retval = mem_ap_write_buf(armv7a->memory_ap, buffer, size, count, address);
-
-       return retval;
-}
-
-static int cortex_a_read_buffer(struct target *target, uint32_t address,
+static int cortex_a_read_buffer(struct target *target, target_addr_t address,
                                uint32_t count, uint8_t *buffer)
 {
        uint32_t size;
@@ -2848,7 +2763,7 @@ static int cortex_a_read_buffer(struct target *target, uint32_t address,
         * will have something to do with the size we leave to it. */
        for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) {
                if (address & size) {
-                       int retval = cortex_a_read_memory_ahb(target, address, size, 1, buffer);
+                       int retval = target_read_memory(target, address, size, 1, buffer);
                        if (retval != ERROR_OK)
                                return retval;
                        address += size;
@@ -2861,7 +2776,7 @@ static int cortex_a_read_buffer(struct target *target, uint32_t address,
        for (; size > 0; size /= 2) {
                uint32_t aligned = count - count % size;
                if (aligned > 0) {
-                       int retval = cortex_a_read_memory_ahb(target, address, size, aligned / size, buffer);
+                       int retval = target_read_memory(target, address, size, aligned / size, buffer);
                        if (retval != ERROR_OK)
                                return retval;
                        address += aligned;
@@ -2873,7 +2788,7 @@ static int cortex_a_read_buffer(struct target *target, uint32_t address,
        return ERROR_OK;
 }
 
-static int cortex_a_write_buffer(struct target *target, uint32_t address,
+static int cortex_a_write_buffer(struct target *target, target_addr_t address,
                                 uint32_t count, const uint8_t *buffer)
 {
        uint32_t size;
@@ -2882,7 +2797,7 @@ static int cortex_a_write_buffer(struct target *target, uint32_t address,
         * will have something to do with the size we leave to it. */
        for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) {
                if (address & size) {
-                       int retval = cortex_a_write_memory_ahb(target, address, size, 1, buffer);
+                       int retval = target_write_memory(target, address, size, 1, buffer);
                        if (retval != ERROR_OK)
                                return retval;
                        address += size;
@@ -2895,7 +2810,7 @@ static int cortex_a_write_buffer(struct target *target, uint32_t address,
        for (; size > 0; size /= 2) {
                uint32_t aligned = count - count % size;
                if (aligned > 0) {
-                       int retval = cortex_a_write_memory_ahb(target, address, size, aligned / size, buffer);
+                       int retval = target_write_memory(target, address, size, aligned / size, buffer);
                        if (retval != ERROR_OK)
                                return retval;
                        address += aligned;
@@ -2953,21 +2868,30 @@ static int cortex_a_examine_first(struct target *target)
        struct cortex_a_common *cortex_a = target_to_cortex_a(target);
        struct armv7a_common *armv7a = &cortex_a->armv7a_common;
        struct adiv5_dap *swjdp = armv7a->arm.dap;
+       struct adiv5_private_config *pc = target->private_config;
+
        int i;
        int retval = ERROR_OK;
-       uint32_t didr, ctypr, ttypr, cpuid, dbg_osreg;
+       uint32_t didr, cpuid, dbg_osreg, dbg_idpfr1;
 
-       retval = dap_dp_init(swjdp);
-       if (retval != ERROR_OK) {
-               LOG_ERROR("Could not initialize the debug port");
-               return retval;
+       if (armv7a->debug_ap) {
+               dap_put_ap(armv7a->debug_ap);
+               armv7a->debug_ap = NULL;
        }
 
-       /* Search for the APB-AB - it is needed for access to debug registers */
-       retval = dap_find_ap(swjdp, AP_TYPE_APB_AP, &armv7a->debug_ap);
-       if (retval != ERROR_OK) {
-               LOG_ERROR("Could not find APB-AP for debug access");
-               return retval;
+       if (pc->ap_num == DP_APSEL_INVALID) {
+               /* Search for the APB-AP - it is needed for access to debug registers */
+               retval = dap_find_get_ap(swjdp, AP_TYPE_APB_AP, &armv7a->debug_ap);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("Could not find APB-AP for debug access");
+                       return retval;
+               }
+       } else {
+               armv7a->debug_ap = dap_get_ap(swjdp, pc->ap_num);
+               if (!armv7a->debug_ap) {
+                       LOG_ERROR("Cannot get AP");
+                       return ERROR_FAIL;
+               }
        }
 
        retval = mem_ap_init(armv7a->debug_ap);
@@ -2978,121 +2902,110 @@ static int cortex_a_examine_first(struct target *target)
 
        armv7a->debug_ap->memaccess_tck = 80;
 
-       /* Search for the AHB-AB.
-        * REVISIT: We should search for AXI-AP as well and make sure the AP's MEMTYPE says it
-        * can access system memory. */
-       armv7a->memory_ap_available = false;
-       retval = dap_find_ap(swjdp, AP_TYPE_AHB_AP, &armv7a->memory_ap);
-       if (retval == ERROR_OK) {
-               retval = mem_ap_init(armv7a->memory_ap);
-               if (retval == ERROR_OK)
-                       armv7a->memory_ap_available = true;
-               else
-                       LOG_WARNING("Could not initialize AHB-AP for memory access - using APB-AP");
-       } else {
-               /* AHB-AP not found - use APB-AP */
-               LOG_DEBUG("Could not find AHB-AP - using APB-AP for memory access");
-       }
-
        if (!target->dbgbase_set) {
-               uint32_t dbgbase;
-               /* Get ROM Table base */
-               uint32_t apid;
-               int32_t coreidx = target->coreid;
                LOG_DEBUG("%s's dbgbase is not set, trying to detect using the ROM table",
                          target->cmd_name);
-               retval = dap_get_debugbase(armv7a->debug_ap, &dbgbase, &apid);
-               if (retval != ERROR_OK)
-                       return retval;
-               /* Lookup 0x15 -- Processor DAP */
-               retval = dap_lookup_cs_component(armv7a->debug_ap, dbgbase, 0x15,
-                               &armv7a->debug_base, &coreidx);
+               /* Lookup Processor DAP */
+               retval = dap_lookup_cs_component(armv7a->debug_ap, ARM_CS_C9_DEVTYPE_CORE_DEBUG,
+                               &armv7a->debug_base, target->coreid);
                if (retval != ERROR_OK) {
                        LOG_ERROR("Can't detect %s's dbgbase from the ROM table; you need to specify it explicitly.",
                                  target->cmd_name);
                        return retval;
                }
-               LOG_DEBUG("Detected core %" PRId32 " dbgbase: %08" PRIx32,
+               LOG_DEBUG("Detected core %" PRId32 " dbgbase: " TARGET_ADDR_FMT,
                          target->coreid, armv7a->debug_base);
        } else
                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;
-       }
+       if ((armv7a->debug_base & (1UL<<31)) == 0)
+               LOG_WARNING("Debug base address for target %s has bit 31 set to 0. Access to debug registers will likely fail!\n"
+                           "Please fix the target configuration.", target_name(target));
 
        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_OSLSR, &dbg_osreg);
+       if (retval != ERROR_OK)
+               return retval;
+       LOG_DEBUG("target->coreid %" PRId32 " DBGOSLSR 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;
+                       }
+               }
        }
-       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                                           armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg);
 
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
+                                armv7a->debug_base + CPUDBG_ID_PFR1, &dbg_idpfr1);
        if (retval != ERROR_OK)
                return retval;
 
-       LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR  0x%" PRIx32, target->coreid, dbg_osreg);
-
-       armv7a->arm.core_type = ARM_MODE_MON;
+       if (dbg_idpfr1 & 0x000000f0) {
+               LOG_DEBUG("target->coreid %" PRId32 " has security extensions",
+                               target->coreid);
+               armv7a->arm.core_type = ARM_CORE_TYPE_SEC_EXT;
+       }
+       if (dbg_idpfr1 & 0x0000f000) {
+               LOG_DEBUG("target->coreid %" PRId32 " has virtualization extensions",
+                               target->coreid);
+               /*
+                * overwrite and simplify the checks.
+                * virtualization extensions require implementation of security extension
+                */
+               armv7a->arm.core_type = ARM_CORE_TYPE_VIRT_EXT;
+       }
 
        /* Avoid recreating the registers cache */
        if (!target_was_examined(target)) {
@@ -3109,18 +3022,32 @@ static int cortex_a_examine_first(struct target *target)
        cortex_a->brp_list = calloc(cortex_a->brp_num, sizeof(struct cortex_a_brp));
 /*     cortex_a->brb_enabled = ????; */
        for (i = 0; i < cortex_a->brp_num; i++) {
-               cortex_a->brp_list[i].used = 0;
+               cortex_a->brp_list[i].used = false;
                if (i < (cortex_a->brp_num-cortex_a->brp_num_context))
                        cortex_a->brp_list[i].type = BRP_NORMAL;
                else
                        cortex_a->brp_list[i].type = BRP_CONTEXT;
                cortex_a->brp_list[i].value = 0;
                cortex_a->brp_list[i].control = 0;
-               cortex_a->brp_list[i].BRPn = i;
+               cortex_a->brp_list[i].brpn = i;
        }
 
        LOG_DEBUG("Configured %i hw breakpoints", cortex_a->brp_num);
 
+       /* Setup Watchpoint Register Pairs */
+       cortex_a->wrp_num = ((didr >> 28) & 0x0F) + 1;
+       cortex_a->wrp_num_available = cortex_a->wrp_num;
+       free(cortex_a->wrp_list);
+       cortex_a->wrp_list = calloc(cortex_a->wrp_num, sizeof(struct cortex_a_wrp));
+       for (i = 0; i < cortex_a->wrp_num; i++) {
+               cortex_a->wrp_list[i].used = false;
+               cortex_a->wrp_list[i].value = 0;
+               cortex_a->wrp_list[i].control = 0;
+               cortex_a->wrp_list[i].wrpn = i;
+       }
+
+       LOG_DEBUG("Configured %i hw watchpoints", cortex_a->wrp_num);
+
        /* select debug_ap as default */
        swjdp->apsel = armv7a->debug_ap->ap_num;
 
@@ -3150,28 +3077,18 @@ static int cortex_a_init_target(struct command_context *cmd_ctx,
        struct target *target)
 {
        /* examine_first() does a bunch of this */
+       arm_semihosting_init(target);
        return ERROR_OK;
 }
 
 static int cortex_a_init_arch_info(struct target *target,
-       struct cortex_a_common *cortex_a, struct jtag_tap *tap)
+       struct cortex_a_common *cortex_a, struct adiv5_dap *dap)
 {
        struct armv7a_common *armv7a = &cortex_a->armv7a_common;
 
        /* Setup struct cortex_a_common */
        cortex_a->common_magic = CORTEX_A_COMMON_MAGIC;
-
-       /*  tap has no dap initialized */
-       if (!tap->dap) {
-               tap->dap = dap_init();
-
-               /* Leave (only) generic DAP stuff for debugport_init() */
-               tap->dap->tap = tap;
-       }
-
-       armv7a->arm.dap = tap->dap;
-
-       cortex_a->fast_reg_read = 0;
+       armv7a->arm.dap = dap;
 
        /* register arch-specific functions */
        armv7a->examine_debug_reason = NULL;
@@ -3187,37 +3104,81 @@ static int cortex_a_init_arch_info(struct target *target,
 
        /* REVISIT v7a setup should be in a v7a-specific routine */
        armv7a_init_arch_info(target, armv7a);
-       target_register_timer_callback(cortex_a_handle_target_request, 1, 1, target);
+       target_register_timer_callback(cortex_a_handle_target_request, 1,
+               TARGET_TIMER_TYPE_PERIODIC, target);
 
        return ERROR_OK;
 }
 
 static int cortex_a_target_create(struct target *target, Jim_Interp *interp)
 {
-       struct cortex_a_common *cortex_a = calloc(1, sizeof(struct cortex_a_common));
+       struct cortex_a_common *cortex_a;
+       struct adiv5_private_config *pc;
+
+       if (!target->private_config)
+               return ERROR_FAIL;
 
+       pc = (struct adiv5_private_config *)target->private_config;
+
+       cortex_a = calloc(1, sizeof(struct cortex_a_common));
+       if (!cortex_a) {
+               LOG_ERROR("Out of memory");
+               return ERROR_FAIL;
+       }
+       cortex_a->common_magic = CORTEX_A_COMMON_MAGIC;
        cortex_a->armv7a_common.is_armv7r = false;
+       cortex_a->armv7a_common.arm.arm_vfp_version = ARM_VFP_V3;
 
-       return cortex_a_init_arch_info(target, cortex_a, target->tap);
+       return cortex_a_init_arch_info(target, cortex_a, pc->dap);
 }
 
 static int cortex_r4_target_create(struct target *target, Jim_Interp *interp)
 {
-       struct cortex_a_common *cortex_a = calloc(1, sizeof(struct cortex_a_common));
+       struct cortex_a_common *cortex_a;
+       struct adiv5_private_config *pc;
 
+       pc = (struct adiv5_private_config *)target->private_config;
+       if (adiv5_verify_config(pc) != ERROR_OK)
+               return ERROR_FAIL;
+
+       cortex_a = calloc(1, sizeof(struct cortex_a_common));
+       if (!cortex_a) {
+               LOG_ERROR("Out of memory");
+               return ERROR_FAIL;
+       }
+       cortex_a->common_magic = CORTEX_A_COMMON_MAGIC;
        cortex_a->armv7a_common.is_armv7r = true;
 
-       return cortex_a_init_arch_info(target, cortex_a, target->tap);
+       return cortex_a_init_arch_info(target, cortex_a, pc->dap);
 }
 
 static void cortex_a_deinit_target(struct target *target)
 {
        struct cortex_a_common *cortex_a = target_to_cortex_a(target);
-       struct arm_dpm *dpm = &cortex_a->armv7a_common.dpm;
+       struct armv7a_common *armv7a = &cortex_a->armv7a_common;
+       struct arm_dpm *dpm = &armv7a->dpm;
+       uint32_t dscr;
+       int retval;
+
+       if (target_was_examined(target)) {
+               /* Disable halt for breakpoint, watchpoint and vector catch */
+               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
+                               armv7a->debug_base + CPUDBG_DSCR, &dscr);
+               if (retval == ERROR_OK)
+                       mem_ap_write_atomic_u32(armv7a->debug_ap,
+                                       armv7a->debug_base + CPUDBG_DSCR,
+                                       dscr & ~DSCR_HALT_DBG_MODE);
+       }
+
+       if (armv7a->debug_ap)
+               dap_put_ap(armv7a->debug_ap);
 
+       free(cortex_a->wrp_list);
        free(cortex_a->brp_list);
+       arm_free_reg_cache(dpm->arm);
        free(dpm->dbp);
        free(dpm->dwp);
+       free(target->private_config);
        free(cortex_a);
 }
 
@@ -3239,28 +3200,29 @@ static int cortex_a_mmu(struct target *target, int *enabled)
 }
 
 static int cortex_a_virt2phys(struct target *target,
-       uint32_t virt, uint32_t *phys)
+       target_addr_t virt, target_addr_t *phys)
 {
-       int retval = ERROR_FAIL;
-       struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
-       uint8_t apsel = swjdp->apsel;
-       if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap->ap_num)) {
-               uint32_t ret;
-               retval = armv7a_mmu_translate_va(target,
-                               virt, &ret);
-               if (retval != ERROR_OK)
-                       goto done;
-               *phys = ret;
-       } else {/*  use this method if armv7a->memory_ap not selected
-                *  mmu must be enable in order to get a correct translation */
-               retval = cortex_a_mmu_modify(target, 1);
-               if (retval != ERROR_OK)
-                       goto done;
-               retval = armv7a_mmu_translate_va_pa(target, virt,  phys, 1);
+       int retval;
+       int mmu_enabled = 0;
+
+       /*
+        * If the MMU was not enabled at debug entry, there is no
+        * way of knowing if there was ever a valid configuration
+        * for it and thus it's not safe to enable it. In this case,
+        * just return the virtual address as physical.
+        */
+       cortex_a_mmu(target, &mmu_enabled);
+       if (!mmu_enabled) {
+               *phys = virt;
+               return ERROR_OK;
        }
-done:
-       return retval;
+
+       /* mmu must be enable in order to get a correct translation */
+       retval = cortex_a_mmu_modify(target, 1);
+       if (retval != ERROR_OK)
+               return retval;
+       return armv7a_mmu_translate_va_pa(target, (uint32_t)virt,
+                                                   phys, 1);
 }
 
 COMMAND_HANDLER(cortex_a_handle_cache_info_command)
@@ -3268,7 +3230,7 @@ COMMAND_HANDLER(cortex_a_handle_cache_info_command)
        struct target *target = get_current_target(CMD_CTX);
        struct armv7a_common *armv7a = target_to_armv7a(target);
 
-       return armv7a_handle_cache_info_command(CMD_CTX,
+       return armv7a_handle_cache_info_command(CMD,
                        &armv7a->armv7a_mmu.armv7a_cache);
 }
 
@@ -3283,79 +3245,22 @@ COMMAND_HANDLER(cortex_a_handle_dbginit_command)
 
        return cortex_a_init_debug_access(target);
 }
-COMMAND_HANDLER(cortex_a_handle_smp_off_command)
-{
-       struct target *target = get_current_target(CMD_CTX);
-       /* check target is an smp target */
-       struct target_list *head;
-       struct target *curr;
-       head = target->head;
-       target->smp = 0;
-       if (head != (struct target_list *)NULL) {
-               while (head != (struct target_list *)NULL) {
-                       curr = head->target;
-                       curr->smp = 0;
-                       head = head->next;
-               }
-               /*  fixes the target display to the debugger */
-               target->gdb_service->target = target;
-       }
-       return ERROR_OK;
-}
-
-COMMAND_HANDLER(cortex_a_handle_smp_on_command)
-{
-       struct target *target = get_current_target(CMD_CTX);
-       struct target_list *head;
-       struct target *curr;
-       head = target->head;
-       if (head != (struct target_list *)NULL) {
-               target->smp = 1;
-               while (head != (struct target_list *)NULL) {
-                       curr = head->target;
-                       curr->smp = 1;
-                       head = head->next;
-               }
-       }
-       return ERROR_OK;
-}
-
-COMMAND_HANDLER(cortex_a_handle_smp_gdb_command)
-{
-       struct target *target = get_current_target(CMD_CTX);
-       int retval = ERROR_OK;
-       struct target_list *head;
-       head = target->head;
-       if (head != (struct target_list *)NULL) {
-               if (CMD_ARGC == 1) {
-                       int coreid = 0;
-                       COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], coreid);
-                       if (ERROR_OK != retval)
-                               return retval;
-                       target->gdb_service->core[1] = coreid;
-
-               }
-               command_print(CMD_CTX, "gdb coreid  %" PRId32 " -> %" PRId32, target->gdb_service->core[0]
-                       , target->gdb_service->core[1]);
-       }
-       return ERROR_OK;
-}
 
 COMMAND_HANDLER(handle_cortex_a_mask_interrupts_command)
 {
        struct target *target = get_current_target(CMD_CTX);
        struct cortex_a_common *cortex_a = target_to_cortex_a(target);
 
-       static const Jim_Nvp nvp_maskisr_modes[] = {
+       static const struct jim_nvp nvp_maskisr_modes[] = {
                { .name = "off", .value = CORTEX_A_ISRMASK_OFF },
                { .name = "on", .value = CORTEX_A_ISRMASK_ON },
                { .name = NULL, .value = -1 },
        };
-       const Jim_Nvp *n;
+       const struct jim_nvp *n;
 
        if (CMD_ARGC > 0) {
-               n = Jim_Nvp_name2value_simple(nvp_maskisr_modes, CMD_ARGV[0]);
-               if (n->name == NULL) {
+               n = jim_nvp_name2value_simple(nvp_maskisr_modes, CMD_ARGV[0]);
+               if (!n->name) {
                        LOG_ERROR("Unknown parameter: %s - should be off or on", CMD_ARGV[0]);
                        return ERROR_COMMAND_SYNTAX_ERROR;
                }
@@ -3363,8 +3268,8 @@ COMMAND_HANDLER(handle_cortex_a_mask_interrupts_command)
                cortex_a->isrmasking_mode = n->value;
        }
 
-       n = Jim_Nvp_value2name_simple(nvp_maskisr_modes, cortex_a->isrmasking_mode);
-       command_print(CMD_CTX, "cortex_a interrupt mask %s", n->name);
+       n = jim_nvp_value2name_simple(nvp_maskisr_modes, cortex_a->isrmasking_mode);
+       command_print(CMD, "cortex_a interrupt mask %s", n->name);
 
        return ERROR_OK;
 }
@@ -3374,23 +3279,23 @@ COMMAND_HANDLER(handle_cortex_a_dacrfixup_command)
        struct target *target = get_current_target(CMD_CTX);
        struct cortex_a_common *cortex_a = target_to_cortex_a(target);
 
-       static const Jim_Nvp nvp_dacrfixup_modes[] = {
+       static const struct jim_nvp nvp_dacrfixup_modes[] = {
                { .name = "off", .value = CORTEX_A_DACRFIXUP_OFF },
                { .name = "on", .value = CORTEX_A_DACRFIXUP_ON },
                { .name = NULL, .value = -1 },
        };
-       const Jim_Nvp *n;
+       const struct jim_nvp *n;
 
        if (CMD_ARGC > 0) {
-               n = Jim_Nvp_name2value_simple(nvp_dacrfixup_modes, CMD_ARGV[0]);
-               if (n->name == NULL)
+               n = jim_nvp_name2value_simple(nvp_dacrfixup_modes, CMD_ARGV[0]);
+               if (!n->name)
                        return ERROR_COMMAND_SYNTAX_ERROR;
                cortex_a->dacrfixup_mode = n->value;
 
        }
 
-       n = Jim_Nvp_value2name_simple(nvp_dacrfixup_modes, cortex_a->dacrfixup_mode);
-       command_print(CMD_CTX, "cortex_a domain access control fixup %s", n->name);
+       n = jim_nvp_value2name_simple(nvp_dacrfixup_modes, cortex_a->dacrfixup_mode);
+       command_print(CMD, "cortex_a domain access control fixup %s", n->name);
 
        return ERROR_OK;
 }
@@ -3410,25 +3315,6 @@ static const struct command_registration cortex_a_exec_command_handlers[] = {
                .help = "Initialize core debug",
                .usage = "",
        },
-       {   .name = "smp_off",
-           .handler = cortex_a_handle_smp_off_command,
-           .mode = COMMAND_EXEC,
-           .help = "Stop smp handling",
-           .usage = "",},
-       {
-               .name = "smp_on",
-               .handler = cortex_a_handle_smp_on_command,
-               .mode = COMMAND_EXEC,
-               .help = "Restart smp handling",
-               .usage = "",
-       },
-       {
-               .name = "smp_gdb",
-               .handler = cortex_a_handle_smp_gdb_command,
-               .mode = COMMAND_EXEC,
-               .help = "display/fix current core played to gdb",
-               .usage = "",
-       },
        {
                .name = "maskisr",
                .handler = handle_cortex_a_mask_interrupts_command,
@@ -3439,11 +3325,17 @@ static const struct command_registration cortex_a_exec_command_handlers[] = {
        {
                .name = "dacrfixup",
                .handler = handle_cortex_a_dacrfixup_command,
-               .mode = COMMAND_EXEC,
+               .mode = COMMAND_ANY,
                .help = "set domain access control (DACR) to all-manager "
                        "on memory access",
                .usage = "['on'|'off']",
        },
+       {
+               .chain = armv7a_mmu_command_handlers,
+       },
+       {
+               .chain = smp_command_handlers,
+       },
 
        COMMAND_REGISTRATION_DONE
 };
@@ -3466,7 +3358,6 @@ static const struct command_registration cortex_a_command_handlers[] = {
 
 struct target_type cortexa_target = {
        .name = "cortex_a",
-       .deprecated_name = "cortex_a8",
 
        .poll = cortex_a_poll,
        .arch_state = armv7a_arch_state,
@@ -3479,6 +3370,7 @@ struct target_type cortexa_target = {
        .deassert_reset = cortex_a_deassert_reset,
 
        /* REVISIT allow exporting VFP3 registers ... */
+       .get_gdb_arch = arm_get_gdb_arch,
        .get_gdb_reg_list = arm_get_gdb_reg_list,
 
        .read_memory = cortex_a_read_memory,
@@ -3496,11 +3388,12 @@ struct target_type cortexa_target = {
        .add_context_breakpoint = cortex_a_add_context_breakpoint,
        .add_hybrid_breakpoint = cortex_a_add_hybrid_breakpoint,
        .remove_breakpoint = cortex_a_remove_breakpoint,
-       .add_watchpoint = NULL,
-       .remove_watchpoint = NULL,
+       .add_watchpoint = cortex_a_add_watchpoint,
+       .remove_watchpoint = cortex_a_remove_watchpoint,
 
        .commands = cortex_a_command_handlers,
        .target_create = cortex_a_target_create,
+       .target_jim_configure = adiv5_jim_configure,
        .init_target = cortex_a_init_target,
        .examine = cortex_a_examine,
        .deinit_target = cortex_a_deinit_target,
@@ -3512,13 +3405,6 @@ struct target_type cortexa_target = {
 };
 
 static const struct command_registration cortex_r4_exec_command_handlers[] = {
-       {
-               .name = "cache_info",
-               .handler = cortex_a_handle_cache_info_command,
-               .mode = COMMAND_EXEC,
-               .help = "display information about target caches",
-               .usage = "",
-       },
        {
                .name = "dbginit",
                .handler = cortex_a_handle_dbginit_command,
@@ -3540,9 +3426,6 @@ static const struct command_registration cortex_r4_command_handlers[] = {
        {
                .chain = arm_command_handlers,
        },
-       {
-               .chain = armv7a_command_handlers,
-       },
        {
                .name = "cortex_r4",
                .mode = COMMAND_ANY,
@@ -3567,10 +3450,11 @@ struct target_type cortexr4_target = {
        .deassert_reset = cortex_a_deassert_reset,
 
        /* REVISIT allow exporting VFP3 registers ... */
+       .get_gdb_arch = arm_get_gdb_arch,
        .get_gdb_reg_list = arm_get_gdb_reg_list,
 
-       .read_memory = cortex_a_read_memory,
-       .write_memory = cortex_a_write_memory,
+       .read_memory = cortex_a_read_phys_memory,
+       .write_memory = cortex_a_write_phys_memory,
 
        .checksum_memory = arm_checksum_memory,
        .blank_check_memory = arm_blank_check_memory,
@@ -3581,11 +3465,12 @@ struct target_type cortexr4_target = {
        .add_context_breakpoint = cortex_a_add_context_breakpoint,
        .add_hybrid_breakpoint = cortex_a_add_hybrid_breakpoint,
        .remove_breakpoint = cortex_a_remove_breakpoint,
-       .add_watchpoint = NULL,
-       .remove_watchpoint = NULL,
+       .add_watchpoint = cortex_a_add_watchpoint,
+       .remove_watchpoint = cortex_a_remove_watchpoint,
 
        .commands = cortex_r4_command_handlers,
        .target_create = cortex_r4_target_create,
+       .target_jim_configure = adiv5_jim_configure,
        .init_target = cortex_a_init_target,
        .examine = cortex_a_examine,
        .deinit_target = cortex_a_deinit_target,