jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / target / cortex_a.c
index 266c372a318feee11e5720a5b359360cfc3638f2..7fa0c4e8b72a51cfa6b526151b21a05d3620482b 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/nvp.h>
 #include <helper/time_support.h>
 
 static int cortex_a_poll(struct target *target);
@@ -68,17 +66,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)
@@ -106,13 +112,20 @@ static int cortex_a_restore_cp15_control_reg(struct target *target)
 static int cortex_a_prep_memaccess(struct target *target, int phys_access)
 {
        struct armv7a_common *armv7a = target_to_armv7a(target);
+       struct cortex_a_common *cortex_a = target_to_cortex_a(target);
        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);
+               if (cortex_a->dacrfixup_mode == CORTEX_A_DACRFIXUP_ON) {
+                       /* overwrite DACR to all-manager */
+                       armv7a->arm.mcr(target, 15,
+                                       0, 0, 3, 0,
+                                       0xFFFFFFFF);
+               }
        } else {
                cortex_a_mmu(target, &mmu_enabled);
                if (mmu_enabled)
@@ -129,9 +142,16 @@ static int cortex_a_prep_memaccess(struct target *target, int phys_access)
 static int cortex_a_post_memaccess(struct target *target, int phys_access)
 {
        struct armv7a_common *armv7a = target_to_armv7a(target);
+       struct cortex_a_common *cortex_a = target_to_cortex_a(target);
 
        if (phys_access == 0) {
-               dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
+               if (cortex_a->dacrfixup_mode == CORTEX_A_DACRFIXUP_ON) {
+                       /* restore */
+                       armv7a->arm.mcr(target, 15,
+                                       0, 0, 3, 0,
+                                       cortex_a->cp15_dacr_reg);
+               }
+               arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
        } else {
                int mmu_enabled = 0;
                cortex_a_mmu(target, &mmu_enabled);
@@ -182,101 +202,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);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
-       int retval;
-
-       LOG_DEBUG(" ");
-
-       /* Unlocking the debug registers for modification
-        * The debugport might be uninitialised so try twice */
-       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
-                       armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
-       if (retval != ERROR_OK) {
-               /* try again */
-               retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
-                               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);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
+       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_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
-                                                   armv7a->debug_base + CPUDBG_OSLSR,
-                                                   &dbg_osreg);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               LOG_DEBUG("DBGOSLSR  0x%" PRIx32, dbg_osreg);
-
-               if (dbg_osreg & CPUDBG_OSLAR_LK_MASK)
-                       /* Unlocking the DEBUG OS registers for modification */
-                       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
-                                                            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_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
-                       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_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       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_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       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);
 }
@@ -287,22 +258,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);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
-       long long then = timeval_ms();
-       while ((*dscr & DSCR_INSTR_COMP) == 0 || force) {
-               force = false;
-               int retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       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
@@ -316,7 +286,6 @@ static int cortex_a_exec_opcode(struct target *target,
        uint32_t dscr;
        int retval;
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
 
        dscr = dscr_p ? *dscr_p : 0;
 
@@ -327,196 +296,20 @@ static int cortex_a_exec_opcode(struct target *target,
        if (retval != ERROR_OK)
                return retval;
 
-       retval = mem_ap_sel_write_u32(swjdp, armv7a->debug_ap->ap_num,
+       retval = mem_ap_write_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_ITR, opcode);
        if (retval != ERROR_OK)
                return retval;
 
-       long long then = timeval_ms();
-       do {
-               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
-                               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);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
-
-       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_sel_read_buf(swjdp, armv7a->memory_ap->ap_num,
-                       (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);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
-
-       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 */
-       long long then = timeval_ms();
-       while ((dscr & DSCR_DTR_TX_FULL) == 0) {
-               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
-                               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_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
-                       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);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
-
-       LOG_DEBUG("register %i, value 0x%08" PRIx32, regnum, value);
-
-       /* Check that DCCRX is not full */
-       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
-                       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_sel_write_u32(swjdp, armv7a->debug_ap->ap_num,
-                       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;
 }
@@ -528,9 +321,8 @@ static int cortex_a_dap_write_memap_register_u32(struct target *target,
 {
        int retval;
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
 
-       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num, address, value);
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap, address, value);
 
        return retval;
 }
@@ -554,14 +346,13 @@ static inline struct cortex_a_common *dpm_to_a(struct arm_dpm *dpm)
 static int cortex_a_write_dcc(struct cortex_a_common *a, uint32_t data)
 {
        LOG_DEBUG("write DCC 0x%08" PRIx32, data);
-       return mem_ap_sel_write_u32(a->armv7a_common.arm.dap,
-               a->armv7a_common.debug_ap->ap_num, a->armv7a_common.debug_base + CPUDBG_DTRRX, data);
+       return mem_ap_write_u32(a->armv7a_common.debug_ap,
+                       a->armv7a_common.debug_base + CPUDBG_DTRRX, data);
 }
 
 static int cortex_a_read_dcc(struct cortex_a_common *a, uint32_t *data,
        uint32_t *dscr_p)
 {
-       struct adiv5_dap *swjdp = a->armv7a_common.arm.dap;
        uint32_t dscr = DSCR_INSTR_COMP;
        int retval;
 
@@ -569,20 +360,14 @@ static int cortex_a_read_dcc(struct cortex_a_common *a, uint32_t *data,
                dscr = *dscr_p;
 
        /* Wait for DTRRXfull */
-       long long then = timeval_ms();
-       while ((dscr & DSCR_DTR_TX_FULL) == 0) {
-               retval = mem_ap_sel_read_atomic_u32(swjdp, a->armv7a_common.debug_ap->ap_num,
-                               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_sel_read_atomic_u32(swjdp, a->armv7a_common.debug_ap->ap_num,
+       retval = mem_ap_read_atomic_u32(a->armv7a_common.debug_ap,
                        a->armv7a_common.debug_base + CPUDBG_DTRTX, data);
        if (retval != ERROR_OK)
                return retval;
@@ -597,24 +382,14 @@ static int cortex_a_read_dcc(struct cortex_a_common *a, uint32_t *data,
 static int cortex_a_dpm_prepare(struct arm_dpm *dpm)
 {
        struct cortex_a_common *a = dpm_to_a(dpm);
-       struct adiv5_dap *swjdp = a->armv7a_common.arm.dap;
        uint32_t dscr;
        int retval;
 
        /* set up invariant:  INSTR_COMP is set after ever DPM operation */
-       long long then = timeval_ms();
-       for (;; ) {
-               retval = mem_ap_sel_read_atomic_u32(swjdp, a->armv7a_common.debug_ap->ap_num,
-                               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" ... */
@@ -655,22 +430,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;
 
@@ -683,6 +471,28 @@ static int cortex_a_instr_write_data_r0(struct arm_dpm *dpm,
        return retval;
 }
 
+static int cortex_a_instr_write_data_r0_r1(struct arm_dpm *dpm,
+       uint32_t opcode, uint64_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 & 0xffffffffULL);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = cortex_a_instr_write_data_rt_dcc(dpm, 1, data >> 32);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* then the opcode, taking data from R0, R1 */
+       retval = cortex_a_exec_opcode(a->armv7a_common.arm.target,
+                       opcode,
+                       &dscr);
+       return retval;
+}
+
 static int cortex_a_instr_cpsr_sync(struct arm_dpm *dpm)
 {
        struct target *target = dpm->arm->target;
@@ -712,6 +522,25 @@ 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_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_exec_opcode(
+                       a->armv7a_common.arm.target,
+                       ARMV4_5_MCR(14, 0, rt, 0, 5, 0),
+                       &dscr);
+       if (retval != ERROR_OK)
+               return retval;
+
+       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)
@@ -729,14 +558,30 @@ static int cortex_a_instr_read_data_r0(struct arm_dpm *dpm,
                return retval;
 
        /* write R0 to DCC */
-       retval = cortex_a_exec_opcode(
-                       a->armv7a_common.arm.target,
-                       ARMV4_5_MCR(14, 0, 0, 0, 5, 0),
-                       &dscr);
+       return cortex_a_instr_read_data_rt_dcc(dpm, 0, data);
+}
+
+static int cortex_a_instr_read_data_r0_r1(struct arm_dpm *dpm,
+       uint32_t opcode, uint64_t *data)
+{
+       uint32_t lo, hi;
+       int retval;
+
+       /* the opcode, writing data to RO, R1 */
+       retval = cortex_a_instr_read_data_r0(dpm, opcode, &lo);
        if (retval != ERROR_OK)
                return retval;
 
-       return cortex_a_read_dcc(a, data, &dscr);
+       *data = lo;
+
+       /* write R1 to DCC */
+       retval = cortex_a_instr_read_data_rt_dcc(dpm, 1, &hi);
+       if (retval != ERROR_OK)
+               return retval;
+
+       *data |= (uint64_t)hi << 32;
+
+       return retval;
 }
 
 static int cortex_a_bpwp_enable(struct arm_dpm *dpm, unsigned index_t,
@@ -812,10 +657,12 @@ static int cortex_a_dpm_setup(struct cortex_a_common *a, uint32_t didr)
 
        dpm->instr_write_data_dcc = cortex_a_instr_write_data_dcc;
        dpm->instr_write_data_r0 = cortex_a_instr_write_data_r0;
+       dpm->instr_write_data_r0_r1 = cortex_a_instr_write_data_r0_r1;
        dpm->instr_cpsr_sync = cortex_a_instr_cpsr_sync;
 
        dpm->instr_read_data_dcc = cortex_a_instr_read_data_dcc;
        dpm->instr_read_data_r0 = cortex_a_instr_read_data_r0;
+       dpm->instr_read_data_r0_r1 = cortex_a_instr_read_data_r0_r1;
 
        dpm->bpwp_enable = cortex_a_bpwp_enable;
        dpm->bpwp_disable = cortex_a_bpwp_disable;
@@ -829,14 +676,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;
 }
@@ -846,25 +690,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;
 }
 
@@ -878,7 +752,6 @@ static int cortex_a_poll(struct target *target)
        uint32_t dscr;
        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;
        enum target_state prev_target_state = target->state;
        /*  toggle to another core is done by gdb as follow */
        /*  maint packet J core_id */
@@ -886,13 +759,13 @@ 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);
                return retval;
        }
-       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
        if (retval != ERROR_OK)
                return retval;
@@ -903,87 +776,54 @@ 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);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
 
        /*
         * Tell the core to be halted by writing DRCR with 0x1
         * and then wait for the core to be halted.
         */
-       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DRCR, DRCR_HALT);
        if (retval != ERROR_OK)
                return retval;
 
-       /*
-        * enter halting debug mode
-        */
-       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
-                       armv7a->debug_base + CPUDBG_DSCR, &dscr);
-       if (retval != ERROR_OK)
-               return retval;
-
-       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
-                       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;
-
-       long long then = timeval_ms();
-       for (;; ) {
-               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
-                               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;
@@ -992,7 +832,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;
@@ -1011,15 +851,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
 
@@ -1047,13 +887,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);
@@ -1089,7 +933,6 @@ static int cortex_a_internal_restart(struct target *target)
 {
        struct armv7a_common *armv7a = target_to_armv7a(target);
        struct arm *arm = &armv7a->arm;
-       struct adiv5_dap *swjdp = arm->dap;
        int retval;
        uint32_t dscr;
        /*
@@ -1100,7 +943,7 @@ static int cortex_a_internal_restart(struct target *target)
         * disable IRQs by default, with optional override...
         */
 
-       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
        if (retval != ERROR_OK)
                return retval;
@@ -1108,29 +951,23 @@ static int cortex_a_internal_restart(struct target *target)
        if ((dscr & DSCR_INSTR_COMP) == 0)
                LOG_ERROR("DSCR InstrCompl must be set before leaving debug!");
 
-       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, dscr & ~DSCR_ITR_EN);
        if (retval != ERROR_OK)
                return retval;
 
-       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DRCR, DRCR_RESTART |
                        DRCR_CLEAR_EXCEPTIONS);
        if (retval != ERROR_OK)
                return retval;
 
-       long long then = timeval_ms();
-       for (;; ) {
-               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
-                               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;
@@ -1146,25 +983,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  */
@@ -1188,11 +1023,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;
@@ -1200,20 +1035,16 @@ 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 adiv5_dap *swjdp = armv7a->arm.dap;
-       struct reg *reg;
 
        LOG_DEBUG("dscr = 0x%08" PRIx32, cortex_a->cpudbg_dscr);
 
        /* REVISIT surely we should not re-read DSCR !! */
-       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
        if (retval != ERROR_OK)
                return retval;
@@ -1225,7 +1056,7 @@ static int cortex_a_debug_entry(struct target *target)
 
        /* Enable the ITR execution once we are in debug mode */
        dscr |= DSCR_ITR_EN;
-       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, dscr);
        if (retval != ERROR_OK)
                return retval;
@@ -1237,7 +1068,7 @@ static int cortex_a_debug_entry(struct target *target)
        if (target->debug_reason == DBG_REASON_WATCHPOINT) {
                uint32_t wfar;
 
-               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_WFAR,
                                &wfar);
                if (retval != ERROR_OK)
@@ -1245,54 +1076,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
@@ -1335,6 +1128,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);
 
@@ -1350,19 +1146,29 @@ static int cortex_a_post_debug_entry(struct target *target)
                (cortex_a->cp15_control_reg & 0x1000U) ? 1 : 0;
        cortex_a->curr_mode = armv7a->arm.core_mode;
 
+       /* switch to SVC mode to read DACR */
+       arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC);
+       armv7a->arm.mrc(target, 15,
+                       0, 0, 3, 0,
+                       &cortex_a->cp15_dacr_reg);
+
+       LOG_DEBUG("cp15_dacr_reg: %8.8" PRIx32,
+                       cortex_a->cp15_dacr_reg);
+
+       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);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
        uint32_t dscr;
 
        /* Read DSCR */
-       int retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       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 */
@@ -1371,12 +1177,12 @@ int cortex_a_set_dscr_bits(struct target *target, unsigned long bit_mask, unsign
        dscr |= value & bit_mask;
 
        /* write new DSCR */
-       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, dscr);
        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);
@@ -1388,7 +1194,7 @@ static int cortex_a_step(struct target *target, int current, uint32_t address,
        int retval;
 
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target not halted");
+               LOG_TARGET_ERROR(target, "not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
@@ -1412,15 +1218,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;
        }
 
@@ -1433,11 +1240,13 @@ static int cortex_a_step(struct target *target, int current, uint32_t address,
        if (retval != ERROR_OK)
                return retval;
 
-       long long then = timeval_ms();
+       int64_t then = timeval_ms();
        while (target->state != TARGET_HALTED) {
                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;
@@ -1449,7 +1258,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;
        }
 
@@ -1493,7 +1302,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;
        }
@@ -1505,22 +1314,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;
@@ -1529,10 +1338,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,
@@ -1558,7 +1379,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;
@@ -1575,7 +1396,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;
        }
@@ -1589,20 +1410,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;
@@ -1618,16 +1439,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;
        }
@@ -1636,7 +1457,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;
@@ -1646,47 +1467,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;
@@ -1701,31 +1522,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;
@@ -1735,45 +1556,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 {
@@ -1805,7 +1626,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;
 }
@@ -1871,7 +1692,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++;
@@ -1881,6 +1702,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
  */
@@ -1893,6 +1908,8 @@ static int cortex_a_assert_reset(struct target *target)
 
        /* FIXME when halt is requested, make it work somehow... */
 
+       /* This function can be called in "target not examined" state */
+
        /* Issue some kind of warm reset. */
        if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT))
                target_handle_event(target, TARGET_EVENT_RESET_ASSERT);
@@ -1900,14 +1917,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;
 
@@ -1916,24 +1942,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;
                }
        }
 
@@ -1952,8 +1985,8 @@ static int cortex_a_set_dcc_mode(struct target *target, uint32_t mode, uint32_t
        uint32_t new_dscr = (*dscr & ~DSCR_EXT_DCC_MASK) | mode;
        if (new_dscr != *dscr) {
                struct armv7a_common *armv7a = target_to_armv7a(target);
-               int retval = mem_ap_sel_write_atomic_u32(armv7a->arm.dap,
-                               armv7a->debug_ap->ap_num, armv7a->debug_base + CPUDBG_DSCR, new_dscr);
+               int retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+                               armv7a->debug_base + CPUDBG_DSCR, new_dscr);
                if (retval == ERROR_OK)
                        *dscr = new_dscr;
                return retval;
@@ -1967,15 +2000,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);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
-       long long then = timeval_ms();
+       int64_t then;
        int retval;
 
-       while ((*dscr & mask) != value) {
-               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       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;
@@ -1989,7 +2029,6 @@ static int cortex_a_read_copro(struct target *target, uint32_t opcode,
 {
        int retval;
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
 
        /* Move from coprocessor to R0. */
        retval = cortex_a_exec_opcode(target, opcode, dscr);
@@ -2011,7 +2050,7 @@ static int cortex_a_read_copro(struct target *target, uint32_t opcode,
                return retval;
 
        /* Read the value transferred to DTRTX. */
-       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DTRTX, data);
        if (retval != ERROR_OK)
                return retval;
@@ -2044,10 +2083,9 @@ static int cortex_a_write_copro(struct target *target, uint32_t opcode,
 {
        int retval;
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
 
        /* Write the value into DTRRX. */
-       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DTRRX, data);
        if (retval != ERROR_OK)
                return retval;
@@ -2116,20 +2154,20 @@ 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.
         * - R0 is marked dirty.
         */
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
        struct arm *arm = &armv7a->arm;
        int retval;
 
@@ -2151,7 +2189,7 @@ static int cortex_a_write_apb_ab_memory_slow(struct target *target,
                        data = target_buffer_get_u16(target, buffer);
                else
                        data = target_buffer_get_u32(target, buffer);
-               retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+               retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DTRRX, data);
                if (retval != ERROR_OK)
                        return retval;
@@ -2192,7 +2230,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
@@ -2203,7 +2241,6 @@ static int cortex_a_write_apb_ab_memory_fast(struct target *target,
         * - R0 is marked dirty.
         */
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
        int retval;
 
        /* Switch to fast mode if not already in that mode. */
@@ -2212,31 +2249,30 @@ static int cortex_a_write_apb_ab_memory_fast(struct target *target,
                return retval;
 
        /* Latch STC instruction. */
-       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_ITR, ARMV4_5_STC(0, 1, 0, 1, 14, 5, 0, 4));
        if (retval != ERROR_OK)
                return retval;
 
        /* Transfer all the data and issue all the instructions. */
-       return mem_ap_sel_write_buf_noincr(swjdp, armv7a->debug_ap->ap_num, buffer,
+       return mem_ap_write_buf_noincr(armv7a->debug_ap, buffer,
                        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 adiv5_dap *swjdp = armv7a->arm.dap;
        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");
+               LOG_TARGET_ERROR(target, "not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
@@ -2244,13 +2280,13 @@ static int cortex_a_write_apb_ab_memory(struct target *target,
                return ERROR_OK;
 
        /* Clear any abort. */
-       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DRCR, DRCR_CLEAR_EXCEPTIONS);
        if (retval != ERROR_OK)
                return retval;
 
        /* Read DSCR. */
-       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
        if (retval != ERROR_OK)
                return retval;
@@ -2258,7 +2294,7 @@ static int cortex_a_write_apb_ab_memory(struct target *target,
        /* Switch to non-blocking mode if not already in that mode. */
        retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_NON_BLOCKING, &dscr);
        if (retval != ERROR_OK)
-               goto out;
+               return retval;
 
        /* Mark R0 as dirty. */
        arm_reg_current(arm, 0)->dirty = true;
@@ -2266,26 +2302,40 @@ static int cortex_a_write_apb_ab_memory(struct target *target,
        /* Read DFAR and DFSR, as they will be modified in the event of a fault. */
        retval = cortex_a_read_dfar_dfsr(target, &orig_dfar, &orig_dfsr, &dscr);
        if (retval != ERROR_OK)
-               goto out;
+               return retval;
 
        /* Get the memory address into R0. */
-       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DTRRX, address);
        if (retval != ERROR_OK)
-               goto out;
+               return retval;
        retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), &dscr);
        if (retval != ERROR_OK)
-               goto out;
+               return retval;
 
        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:
        final_retval = retval;
 
        /* Switch to non-blocking mode if not already in that mode. */
@@ -2301,7 +2351,7 @@ out:
        /* Wait until DTRRX is empty (according to ARMv7-A/-R architecture manual
         * section C8.4.3, checking InstrCmpl_l is not sufficient; one must also
         * check RXfull_l). Most of the time this will be free because RXfull_l
-        * will be cleared immediately and cached in dscr. However, don’t do this
+        * will be cleared immediately and cached in dscr. However, don't do this
         * if there is fault, because then the instruction might not have completed
         * successfully. */
        if (!(dscr & DSCR_STICKY_ABORT_PRECISE)) {
@@ -2313,7 +2363,7 @@ out:
        /* If there were any sticky abort flags, clear them. */
        if (dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE)) {
                fault_dscr = dscr;
-               mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+               mem_ap_write_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DRCR, DRCR_CLEAR_EXCEPTIONS);
                dscr &= ~(DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE);
        } else {
@@ -2347,7 +2397,7 @@ out:
        /* If the DCC is nonempty, clear it. */
        if (dscr & DSCR_DTRTX_FULL_LATCHED) {
                uint32_t dummy;
-               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DTRTX, &dummy);
                if (final_retval == ERROR_OK)
                        final_retval = retval;
@@ -2362,20 +2412,20 @@ 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.
         * - R0 is marked dirty.
         */
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
        struct arm *arm = &armv7a->arm;
        int retval;
 
@@ -2420,7 +2470,7 @@ static int cortex_a_read_apb_ab_memory_slow(struct target *target,
                        return retval;
 
                /* Read the value transferred to DTRTX into the buffer. */
-               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DTRTX, &data);
                if (retval != ERROR_OK)
                        return retval;
@@ -2439,7 +2489,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
@@ -2450,7 +2500,6 @@ static int cortex_a_read_apb_ab_memory_fast(struct target *target,
         * - R0 is marked dirty.
         */
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
        uint32_t u32;
        int retval;
 
@@ -2473,7 +2522,7 @@ static int cortex_a_read_apb_ab_memory_fast(struct target *target,
                        return retval;
 
                /* Latch LDC instruction. */
-               retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+               retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_ITR, ARMV4_5_LDC(0, 1, 0, 1, 14, 5, 0, 4));
                if (retval != ERROR_OK)
                        return retval;
@@ -2484,7 +2533,7 @@ static int cortex_a_read_apb_ab_memory_fast(struct target *target,
                 * memory. The last read of DTRTX in this call reads the second-to-last
                 * word from memory and issues the read instruction for the last word.
                 */
-               retval = mem_ap_sel_read_buf_noincr(swjdp, armv7a->debug_ap->ap_num, buffer,
+               retval = mem_ap_read_buf_noincr(armv7a->debug_ap, buffer,
                                4, count, armv7a->debug_base + CPUDBG_DTRTX);
                if (retval != ERROR_OK)
                        return retval;
@@ -2518,7 +2567,7 @@ static int cortex_a_read_apb_ab_memory_fast(struct target *target,
 
        /* Read the value transferred to DTRTX into the buffer. This is the last
         * word. */
-       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DTRTX, &u32);
        if (retval != ERROR_OK)
                return retval;
@@ -2527,21 +2576,20 @@ 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 adiv5_dap *swjdp = armv7a->arm.dap;
        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");
+               LOG_TARGET_ERROR(target, "not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
@@ -2549,13 +2597,13 @@ static int cortex_a_read_apb_ab_memory(struct target *target,
                return ERROR_OK;
 
        /* Clear any abort. */
-       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DRCR, DRCR_CLEAR_EXCEPTIONS);
        if (retval != ERROR_OK)
                return retval;
 
        /* Read DSCR */
-       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
        if (retval != ERROR_OK)
                return retval;
@@ -2563,7 +2611,7 @@ static int cortex_a_read_apb_ab_memory(struct target *target,
        /* Switch to non-blocking mode if not already in that mode. */
        retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_NON_BLOCKING, &dscr);
        if (retval != ERROR_OK)
-               goto out;
+               return retval;
 
        /* Mark R0 as dirty. */
        arm_reg_current(arm, 0)->dirty = true;
@@ -2571,26 +2619,41 @@ static int cortex_a_read_apb_ab_memory(struct target *target,
        /* Read DFAR and DFSR, as they will be modified in the event of a fault. */
        retval = cortex_a_read_dfar_dfsr(target, &orig_dfar, &orig_dfsr, &dscr);
        if (retval != ERROR_OK)
-               goto out;
+               return retval;
 
        /* Get the memory address into R0. */
-       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DTRRX, address);
        if (retval != ERROR_OK)
-               goto out;
+               return retval;
        retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), &dscr);
        if (retval != ERROR_OK)
-               goto out;
+               return retval;
 
        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:
        final_retval = retval;
 
        /* Switch to non-blocking mode if not already in that mode. */
@@ -2606,7 +2669,7 @@ out:
        /* If there were any sticky abort flags, clear them. */
        if (dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE)) {
                fault_dscr = dscr;
-               mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+               mem_ap_write_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DRCR, DRCR_CLEAR_EXCEPTIONS);
                dscr &= ~(DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE);
        } else {
@@ -2640,7 +2703,7 @@ out:
        /* If the DCC is nonempty, clear it. */
        if (dscr & DSCR_DTRTX_FULL_LATCHED) {
                uint32_t dummy;
-               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DTRTX, &dummy);
                if (final_retval == ERROR_OK)
                        final_retval = retval;
@@ -2659,169 +2722,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)
 {
-       int retval = ERROR_COMMAND_SYNTAX_ERROR;
+       int retval;
 
-       LOG_DEBUG("Reading memory at real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32,
+       if (!count || !buffer)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       LOG_DEBUG("Reading memory at real address " TARGET_ADDR_FMT "; size %" PRIu32 "; count %" PRIu32,
                address, size, count);
 
-       if (count && buffer) {
-               /* read memory through APB-AP */
-               cortex_a_prep_memaccess(target, 1);
-               retval = cortex_a_read_apb_ab_memory(target, address, size, count, buffer);
-               cortex_a_post_memaccess(target, 1);
-       }
+       /* read memory through the CPU */
+       cortex_a_prep_memaccess(target, 1);
+       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)
+static int cortex_a_write_phys_memory(struct target *target,
+       target_addr_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_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_sel_read_buf(swjdp, armv7a->memory_ap->ap_num, buffer, size, count, address);
-
-       return retval;
-}
-
-static int cortex_a_write_phys_memory(struct target *target,
-       uint32_t address, uint32_t size,
-       uint32_t count, const uint8_t *buffer)
-{
-       int retval = ERROR_COMMAND_SYNTAX_ERROR;
-
-       LOG_DEBUG("Writing memory to real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address,
-               size, count);
+       LOG_DEBUG("Writing memory to real address " TARGET_ADDR_FMT "; size %" PRIu32 "; count %" PRIu32,
+               address, size, count);
 
-       if (count && buffer) {
-               /* write memory through APB-AP */
-               cortex_a_prep_memaccess(target, 1);
-               retval = cortex_a_write_apb_ab_memory(target, address, size, count, buffer);
-               cortex_a_post_memaccess(target, 1);
-       }
+       /* write memory through the CPU */
+       cortex_a_prep_memaccess(target, 1);
+       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_sel_write_buf(swjdp, armv7a->memory_ap->ap_num, 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;
@@ -2830,7 +2809,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;
@@ -2843,7 +2822,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;
@@ -2855,7 +2834,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;
@@ -2864,7 +2843,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;
@@ -2877,7 +2856,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;
@@ -2893,7 +2872,6 @@ static int cortex_a_handle_target_request(void *priv)
 {
        struct target *target = priv;
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
        int retval;
 
        if (!target_was_examined(target))
@@ -2904,18 +2882,23 @@ static int cortex_a_handle_target_request(void *priv)
        if (target->state == TARGET_RUNNING) {
                uint32_t request;
                uint32_t dscr;
-               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DSCR, &dscr);
 
                /* check if we have data */
+               int64_t then = timeval_ms();
                while ((dscr & DSCR_DTR_TX_FULL) && (retval == ERROR_OK)) {
-                       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+                       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                        armv7a->debug_base + CPUDBG_DTRTX, &request);
                        if (retval == ERROR_OK) {
                                target_request(target, request);
-                               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
+                               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                                armv7a->debug_base + CPUDBG_DSCR, &dscr);
                        }
+                       if (timeval_ms() > then + 1000) {
+                               LOG_ERROR("Timeout waiting for dtr tx full");
+                               return ERROR_FAIL;
+                       }
                }
        }
 
@@ -2931,134 +2914,138 @@ 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;
-
-       /* 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;
+       uint32_t didr, cpuid, dbg_osreg, dbg_idpfr1;
+
+       if (!armv7a->debug_ap) {
+               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;
+                       }
+               }
        }
 
-       /* We do one extra read to ensure DAP is configured,
-        * we call ahbap_debugport_init(swjdp) instead
-        */
-       retval = ahbap_debugport_init(swjdp, armv7a->debug_ap->ap_num);
-       if (retval != ERROR_OK)
-               return retval;
-
-       /* Search for the AHB-AB */
-       retval = dap_find_ap(swjdp, AP_TYPE_AHB_AP, &armv7a->memory_ap);
+       retval = mem_ap_init(armv7a->debug_ap);
        if (retval != ERROR_OK) {
-               /* AHB-AP not found - use APB-AP */
-               LOG_DEBUG("Could not find AHB-AP - using APB-AP for memory access");
-               armv7a->memory_ap_available = false;
-       } else {
-               armv7a->memory_ap_available = true;
+               LOG_ERROR("Could not initialize the APB-AP");
+               return retval;
        }
 
+       armv7a->debug_ap->memaccess_tck = 80;
 
        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(swjdp, armv7a->debug_ap->ap_num, &dbgbase, &apid);
-               if (retval != ERROR_OK)
-                       return retval;
-               /* Lookup 0x15 -- Processor DAP */
-               retval = dap_lookup_cs_component(swjdp, armv7a->debug_ap->ap_num, 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_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
-                       armv7a->debug_base + CPUDBG_CPUID, &cpuid);
-       if (retval != ERROR_OK)
-               return retval;
-
-       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
-                       armv7a->debug_base + CPUDBG_CPUID, &cpuid);
-       if (retval != ERROR_OK) {
-               LOG_DEBUG("Examine %s failed", "CPUID");
-               return retval;
-       }
-
-       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
-                       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_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
-                       armv7a->debug_base + CPUDBG_TTYPR, &ttypr);
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
+                       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_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
-                       armv7a->debug_base + CPUDBG_DIDR, &didr);
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
+                       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_read_atomic_u32(armv7a->debug_ap,
+                                   armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg);
+       if (retval != ERROR_OK)
+               return retval;
+       LOG_TARGET_DEBUG(target, "DBGPRSR  0x%" PRIx32, dbg_osreg);
 
-               retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
-                                                    armv7a->debug_base + CPUDBG_OSLAR,
-                                                    0);
+       if ((dbg_osreg & PRSR_POWERUP_STATUS) == 0) {
+               LOG_TARGET_ERROR(target, "powered down!");
+               target->state = TARGET_UNKNOWN; /* TARGET_NO_POWER? */
+               return ERROR_TARGET_INIT_FAILED;
+       }
 
-               if (retval != ERROR_OK)
-                       return retval;
+       if (dbg_osreg & PRSR_STICKY_RESET_STATUS)
+               LOG_TARGET_DEBUG(target, "was reset!");
 
-       }
-       /* Unlocking the debug registers */
-       if ((cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> CORTEX_A_MIDR_PARTNUM_SHIFT ==
-               CORTEX_A7_PARTNUM) {
+       /* 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_TARGET_DEBUG(target, "DBGOSLSR 0x%" PRIx32, dbg_osreg);
 
-               retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
-                                                    armv7a->debug_base + CPUDBG_OSLAR,
-                                                    0);
+       /* 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_TARGET_DEBUG(target, "OSLock set! Trying to unlock");
 
-               if (retval != ERROR_OK)
-                       return retval;
+                       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_TARGET_ERROR(target, "OSLock sticky, core not powered?");
+                               target->state = TARGET_UNKNOWN; /* TARGET_NO_POWER? */
+                               return ERROR_TARGET_INIT_FAILED;
+                       }
+               }
        }
-       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap->ap_num,
-                                           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_TARGET_DEBUG(target, "has security extensions");
+               armv7a->arm.core_type = ARM_CORE_TYPE_SEC_EXT;
+       }
+       if (dbg_idpfr1 & 0x0000f000) {
+               LOG_TARGET_DEBUG(target, "has virtualization extensions");
+               /*
+                * 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)) {
@@ -3075,18 +3062,35 @@ 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;
+
        target_set_examined(target);
        return ERROR_OK;
 }
@@ -3113,29 +3117,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;
-       }
-
-       tap->dap->ap[dap_ap_get_select(tap->dap)].memaccess_tck = 80;
-       armv7a->arm.dap = tap->dap;
-
-       cortex_a->fast_reg_read = 0;
+       armv7a->arm.dap = dap;
 
        /* register arch-specific functions */
        armv7a->examine_debug_reason = NULL;
@@ -3151,37 +3144,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);
 }
 
@@ -3190,8 +3227,8 @@ static int cortex_a_mmu(struct target *target, int *enabled)
        struct armv7a_common *armv7a = target_to_armv7a(target);
 
        if (target->state != TARGET_HALTED) {
-               LOG_ERROR("%s: target not halted", __func__);
-               return ERROR_TARGET_INVALID;
+               LOG_TARGET_ERROR(target, "not halted");
+               return ERROR_TARGET_NOT_HALTED;
        }
 
        if (armv7a->is_armv7r)
@@ -3203,28 +3240,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)
@@ -3232,7 +3270,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);
 }
 
@@ -3247,91 +3285,57 @@ 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)
+COMMAND_HANDLER(handle_cortex_a_mask_interrupts_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;
-}
+       struct cortex_a_common *cortex_a = target_to_cortex_a(target);
 
-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;
+       static const struct nvp nvp_maskisr_modes[] = {
+               { .name = "off", .value = CORTEX_A_ISRMASK_OFF },
+               { .name = "on", .value = CORTEX_A_ISRMASK_ON },
+               { .name = NULL, .value = -1 },
+       };
+       const struct nvp *n;
 
+       if (CMD_ARGC > 0) {
+               n = nvp_name2value(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;
                }
-               command_print(CMD_CTX, "gdb coreid  %" PRId32 " -> %" PRId32, target->gdb_service->core[0]
-                       , target->gdb_service->core[1]);
+
+               cortex_a->isrmasking_mode = n->value;
        }
+
+       n = nvp_value2name(nvp_maskisr_modes, cortex_a->isrmasking_mode);
+       command_print(CMD, "cortex_a interrupt mask %s", n->name);
+
        return ERROR_OK;
 }
 
-COMMAND_HANDLER(handle_cortex_a_mask_interrupts_command)
+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_maskisr_modes[] = {
-               { .name = "off", .value = CORTEX_A_ISRMASK_OFF },
-               { .name = "on", .value = CORTEX_A_ISRMASK_ON },
+       static const struct 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;
-
-       if (target->state != TARGET_HALTED) {
-               command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
-               return ERROR_OK;
-       }
+       const struct nvp *n;
 
        if (CMD_ARGC > 0) {
-               n = Jim_Nvp_name2value_simple(nvp_maskisr_modes, CMD_ARGV[0]);
-               if (n->name == NULL)
+               n = nvp_name2value(nvp_dacrfixup_modes, CMD_ARGV[0]);
+               if (!n->name)
                        return ERROR_COMMAND_SYNTAX_ERROR;
-               cortex_a->isrmasking_mode = n->value;
+               cortex_a->dacrfixup_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 = nvp_value2name(nvp_dacrfixup_modes, cortex_a->dacrfixup_mode);
+       command_print(CMD, "cortex_a domain access control fixup %s", n->name);
 
        return ERROR_OK;
 }
@@ -3351,33 +3355,27 @@ 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,
-               .mode = COMMAND_EXEC,
+               .mode = COMMAND_ANY,
                .help = "mask cortex_a interrupts",
                .usage = "['on'|'off']",
        },
-
+       {
+               .name = "dacrfixup",
+               .handler = handle_cortex_a_dacrfixup_command,
+               .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
 };
@@ -3400,7 +3398,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,
@@ -3413,6 +3410,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,
@@ -3430,11 +3428,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,
@@ -3446,13 +3445,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,
@@ -3474,9 +3466,6 @@ static const struct command_registration cortex_r4_command_handlers[] = {
        {
                .chain = arm_command_handlers,
        },
-       {
-               .chain = armv7a_command_handlers,
-       },
        {
                .name = "cortex_r4",
                .mode = COMMAND_ANY,
@@ -3501,10 +3490,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,
@@ -3515,11 +3505,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,

Linking to existing account procedure

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

SSH host keys fingerprints

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