openocd: remove CamelCase symbols *xPSR*
[fw/openocd] / src / target / cortex_a.c
index 0a55a2006d4a15905118c89f75566579f7bed1b7..2e81d140cf95868c7653b9ef4645815cd1fe7c6c 100644 (file)
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
 /***************************************************************************
  *   Copyright (C) 2005 by Dominic Rath                                    *
  *   Dominic.Rath@gmx.de                                                   *
  *   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, see <http://www.gnu.org/licenses/>. *
+ *   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 "armv7a_mmu.h"
 #include "target_request.h"
 #include "target_type.h"
+#include "arm_coresight.h"
 #include "arm_opcodes.h"
 #include "arm_semihosting.h"
+#include "jtag/interface.h"
 #include "transport/transport.h"
+#include "smp.h"
+#include <helper/bits.h>
 #include <helper/time_support.h>
 
-#define foreach_smp_target(pos, head) \
-       for (pos = head; (pos != NULL); pos = pos->next)
-
 static int cortex_a_poll(struct target *target);
 static int cortex_a_debug_entry(struct target *target);
 static int cortex_a_restore_context(struct target *target, bool bpwp);
@@ -72,6 +65,8 @@ 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_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,
@@ -79,6 +74,16 @@ static int cortex_a_virt2phys(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);
 
+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)
@@ -252,21 +257,21 @@ static int cortex_a_wait_instrcmpl(struct target *target, uint32_t *dscr, bool f
         * Writes final value of DSCR into *dscr. Pass force to force always
         * reading DSCR at least once. */
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       int64_t then = timeval_ms();
-       while ((*dscr & DSCR_INSTR_COMP) == 0 || force) {
-               force = false;
-               int retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
+       int retval;
+
+       if (force) {
+               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DSCR, dscr);
                if (retval != ERROR_OK) {
                        LOG_ERROR("Could not read DSCR register");
                        return retval;
                }
-               if (timeval_ms() > then + 1000) {
-                       LOG_ERROR("Timeout waiting for InstrCompl=1");
-                       return ERROR_FAIL;
-               }
        }
-       return ERROR_OK;
+
+       retval = cortex_a_wait_dscr_bits(target, DSCR_INSTR_COMP, DSCR_INSTR_COMP, dscr);
+       if (retval != ERROR_OK)
+               LOG_ERROR("Error waiting for InstrCompl=1");
+       return retval;
 }
 
 /* To reduce needless round-trips, pass in a pointer to the current
@@ -295,19 +300,12 @@ static int cortex_a_exec_opcode(struct target *target,
        if (retval != ERROR_OK)
                return retval;
 
-       int64_t then = timeval_ms();
-       do {
-               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                               armv7a->debug_base + CPUDBG_DSCR, &dscr);
-               if (retval != ERROR_OK) {
-                       LOG_ERROR("Could not read DSCR register");
-                       return retval;
-               }
-               if (timeval_ms() > then + 1000) {
-                       LOG_ERROR("Timeout waiting for cortex_a_exec_opcode");
-                       return ERROR_FAIL;
-               }
-       } while ((dscr & DSCR_INSTR_COMP) == 0);        /* Wait for InstrCompl bit to be set */
+       /* 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_p)
                *dscr_p = dscr;
@@ -361,17 +359,11 @@ static int cortex_a_read_dcc(struct cortex_a_common *a, uint32_t *data,
                dscr = *dscr_p;
 
        /* Wait for DTRRXfull */
-       int64_t then = timeval_ms();
-       while ((dscr & DSCR_DTR_TX_FULL) == 0) {
-               retval = mem_ap_read_atomic_u32(a->armv7a_common.debug_ap,
-                               a->armv7a_common.debug_base + CPUDBG_DSCR,
-                               &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-               if (timeval_ms() > then + 1000) {
-                       LOG_ERROR("Timeout waiting for read dcc");
-                       return ERROR_FAIL;
-               }
+       retval = cortex_a_wait_dscr_bits(a->armv7a_common.arm.target,
+                       DSCR_DTR_TX_FULL, DSCR_DTR_TX_FULL, &dscr);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error waiting for read dcc");
+               return retval;
        }
 
        retval = mem_ap_read_atomic_u32(a->armv7a_common.debug_ap,
@@ -393,19 +385,10 @@ static int cortex_a_dpm_prepare(struct arm_dpm *dpm)
        int retval;
 
        /* set up invariant:  INSTR_COMP is set after ever DPM operation */
-       int64_t then = timeval_ms();
-       for (;; ) {
-               retval = mem_ap_read_atomic_u32(a->armv7a_common.debug_ap,
-                               a->armv7a_common.debug_base + CPUDBG_DSCR,
-                               &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-               if ((dscr & DSCR_INSTR_COMP) != 0)
-                       break;
-               if (timeval_ms() > then + 1000) {
-                       LOG_ERROR("Timeout waiting for dpm prepare");
-                       return ERROR_FAIL;
-               }
+       retval = cortex_a_wait_instrcmpl(dpm->arm->target, &dscr, true);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error waiting for dpm prepare");
+               return retval;
        }
 
        /* this "should never happen" ... */
@@ -446,22 +429,35 @@ static int cortex_a_instr_write_data_dcc(struct arm_dpm *dpm,
                        &dscr);
 }
 
-static int cortex_a_instr_write_data_r0(struct arm_dpm *dpm,
-       uint32_t opcode, uint32_t data)
+static int cortex_a_instr_write_data_rt_dcc(struct arm_dpm *dpm,
+       uint8_t rt, uint32_t data)
 {
        struct cortex_a_common *a = dpm_to_a(dpm);
        uint32_t dscr = DSCR_INSTR_COMP;
        int retval;
 
+       if (rt > 15)
+               return ERROR_TARGET_INVALID;
+
        retval = cortex_a_write_dcc(a, data);
        if (retval != ERROR_OK)
                return retval;
 
-       /* DCCRX to R0, "MCR p14, 0, R0, c0, c5, 0", 0xEE000E15 */
-       retval = cortex_a_exec_opcode(
+       /* DCCRX to Rt, "MCR p14, 0, R0, c0, c5, 0", 0xEE000E15 */
+       return cortex_a_exec_opcode(
                        a->armv7a_common.arm.target,
-                       ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
+                       ARMV4_5_MRC(14, 0, rt, 0, 5, 0),
                        &dscr);
+}
+
+static int cortex_a_instr_write_data_r0(struct arm_dpm *dpm,
+       uint32_t opcode, uint32_t data)
+{
+       struct cortex_a_common *a = dpm_to_a(dpm);
+       uint32_t dscr = DSCR_INSTR_COMP;
+       int retval;
+
+       retval = cortex_a_instr_write_data_rt_dcc(dpm, 0, data);
        if (retval != ERROR_OK)
                return retval;
 
@@ -503,31 +499,43 @@ static int cortex_a_instr_read_data_dcc(struct arm_dpm *dpm,
        return cortex_a_read_dcc(a, data, &dscr);
 }
 
-
-static int cortex_a_instr_read_data_r0(struct arm_dpm *dpm,
-       uint32_t opcode, uint32_t *data)
+static int cortex_a_instr_read_data_rt_dcc(struct arm_dpm *dpm,
+       uint8_t rt, uint32_t *data)
 {
        struct cortex_a_common *a = dpm_to_a(dpm);
        uint32_t dscr = DSCR_INSTR_COMP;
        int retval;
 
-       /* the opcode, writing data to R0 */
+       if (rt > 15)
+               return ERROR_TARGET_INVALID;
+
        retval = cortex_a_exec_opcode(
                        a->armv7a_common.arm.target,
-                       opcode,
+                       ARMV4_5_MCR(14, 0, rt, 0, 5, 0),
                        &dscr);
        if (retval != ERROR_OK)
                return retval;
 
-       /* write R0 to DCC */
+       return cortex_a_read_dcc(a, data, &dscr);
+}
+
+static int cortex_a_instr_read_data_r0(struct arm_dpm *dpm,
+       uint32_t opcode, uint32_t *data)
+{
+       struct cortex_a_common *a = dpm_to_a(dpm);
+       uint32_t dscr = DSCR_INSTR_COMP;
+       int retval;
+
+       /* the opcode, writing data to R0 */
        retval = cortex_a_exec_opcode(
                        a->armv7a_common.arm.target,
-                       ARMV4_5_MCR(14, 0, 0, 0, 5, 0),
+                       opcode,
                        &dscr);
        if (retval != ERROR_OK)
                return retval;
 
-       return cortex_a_read_dcc(a, data, &dscr);
+       /* write R0 to DCC */
+       return cortex_a_instr_read_data_rt_dcc(dpm, 0, data);
 }
 
 static int cortex_a_bpwp_enable(struct arm_dpm *dpm, unsigned index_t,
@@ -620,14 +628,11 @@ static int cortex_a_dpm_setup(struct cortex_a_common *a, uint32_t didr)
 static struct target *get_cortex_a(struct target *target, int32_t coreid)
 {
        struct target_list *head;
-       struct target *curr;
 
-       head = target->head;
-       while (head != (struct target_list *)NULL) {
-               curr = head->target;
+       foreach_smp_target(head, target->smp_targets) {
+               struct target *curr = head->target;
                if ((curr->coreid == coreid) && (curr->state == TARGET_HALTED))
                        return curr;
-               head = head->next;
        }
        return target;
 }
@@ -637,14 +642,12 @@ 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;
+
+       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;
 }
@@ -665,7 +668,7 @@ static int update_halt_gdb(struct target *target)
        if (target->gdb_service)
                gdb_target = target->gdb_service->target;
 
-       foreach_smp_target(head, target->head) {
+       foreach_smp_target(head, target->smp_targets) {
                curr = head->target;
                /* skip calling context */
                if (curr == target)
@@ -686,7 +689,7 @@ static int update_halt_gdb(struct target *target)
        }
 
        /* after all targets were updated, poll the gdb serving target */
-       if (gdb_target != NULL && gdb_target != target)
+       if (gdb_target && gdb_target != target)
                cortex_a_poll(gdb_target);
        return retval;
 }
@@ -708,7 +711,7 @@ static int cortex_a_poll(struct target *target)
        /*  the next polling trigger an halt event sent to gdb */
        if ((target->state == TARGET_HALTED) && (target->smp) &&
                (target->gdb_service) &&
-               (target->gdb_service->target == NULL)) {
+               (!target->gdb_service->target)) {
                target->gdb_service->target =
                        get_cortex_a(target, target->gdb_service->core[1]);
                target_call_event_callbacks(target, TARGET_EVENT_HALTED);
@@ -725,39 +728,26 @@ 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;
-                               }
+                       }
 
+                       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;
 
                                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)
-                                       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);
-                       }
                }
        } else
                target->state = TARGET_RUNNING;
@@ -767,7 +757,7 @@ static int cortex_a_poll(struct target *target)
 
 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);
 
@@ -780,18 +770,12 @@ static int cortex_a_halt(struct target *target)
        if (retval != ERROR_OK)
                return retval;
 
-       int64_t then = timeval_ms();
-       for (;; ) {
-               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                               armv7a->debug_base + CPUDBG_DSCR, &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-               if ((dscr & DSCR_CORE_HALTED) != 0)
-                       break;
-               if (timeval_ms() > then + 1000) {
-                       LOG_ERROR("Timeout waiting for halt");
-                       return ERROR_FAIL;
-               }
+       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;
        }
 
        target->debug_reason = DBG_REASON_DBGRQ;
@@ -819,15 +803,15 @@ static int cortex_a_internal_restore(struct target *target, int current,
                 * C_MASKINTS in parallel with disabled interrupts can cause
                 * local faults to not be taken. */
                buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_PRIMASK].value, 0, 32, 1);
-               armv7m->core_cache->reg_list[ARMV7M_PRIMASK].dirty = 1;
-               armv7m->core_cache->reg_list[ARMV7M_PRIMASK].valid = 1;
+               armv7m->core_cache->reg_list[ARMV7M_PRIMASK].dirty = true;
+               armv7m->core_cache->reg_list[ARMV7M_PRIMASK].valid = true;
 
                /* Make sure we are in Thumb mode */
-               buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32,
-                       buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0,
+               buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_XPSR].value, 0, 32,
+                       buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_XPSR].value, 0,
                        32) | (1 << 24));
-               armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = 1;
-               armv7m->core_cache->reg_list[ARMV7M_xPSR].valid = 1;
+               armv7m->core_cache->reg_list[ARMV7M_XPSR].dirty = true;
+               armv7m->core_cache->reg_list[ARMV7M_XPSR].valid = true;
        }
 #endif
 
@@ -856,13 +840,13 @@ static int cortex_a_internal_restore(struct target *target, int current,
                        LOG_ERROR("How do I resume into Jazelle state??");
                        return ERROR_FAIL;
                case ARM_STATE_AARCH64:
-                       LOG_ERROR("Shoudn't be in AARCH64 state");
+                       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 */
        arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
@@ -930,18 +914,12 @@ static int cortex_a_internal_restart(struct target *target)
        if (retval != ERROR_OK)
                return retval;
 
-       int64_t then = timeval_ms();
-       for (;; ) {
-               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                               armv7a->debug_base + CPUDBG_DSCR, &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-               if ((dscr & DSCR_CORE_RESTARTED) != 0)
-                       break;
-               if (timeval_ms() > then + 1000) {
-                       LOG_ERROR("Timeout waiting for resume");
-                       return ERROR_FAIL;
-               }
+       dscr = 0; /* force read of dscr */
+       retval = cortex_a_wait_dscr_bits(target, DSCR_CORE_RESTARTED,
+                       DSCR_CORE_RESTARTED, &dscr);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error waiting for resume");
+               return retval;
        }
 
        target->debug_reason = DBG_REASON_NOTHALTED;
@@ -957,11 +935,10 @@ static int cortex_a_restore_smp(struct target *target, int handle_breakpoints)
 {
        int retval = 0;
        struct target_list *head;
-       struct target *curr;
        target_addr_t address;
-       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 != target) && (curr->state != TARGET_RUNNING)
                        && target_was_examined(curr)) {
                        /*  resume current address , not in step mode */
@@ -969,8 +946,6 @@ static int cortex_a_restore_smp(struct target *target, int handle_breakpoints)
                                        handle_breakpoints, 0);
                        retval += cortex_a_internal_restart(curr);
                }
-               head = head->next;
-
        }
        return retval;
 }
@@ -1136,7 +1111,8 @@ static int cortex_a_post_debug_entry(struct target *target)
        return ERROR_OK;
 }
 
-int cortex_a_set_dscr_bits(struct target *target, unsigned long bit_mask, unsigned long value)
+static int cortex_a_set_dscr_bits(struct target *target,
+               unsigned long bit_mask, unsigned long value)
 {
        struct armv7a_common *armv7a = target_to_armv7a(target);
        uint32_t dscr;
@@ -1144,7 +1120,7 @@ int cortex_a_set_dscr_bits(struct target *target, unsigned long bit_mask, unsign
        /* Read DSCR */
        int retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
-       if (ERROR_OK != retval)
+       if (retval != ERROR_OK)
                return retval;
 
        /* clear bitfield */
@@ -1198,12 +1174,12 @@ static int cortex_a_step(struct target *target, int current, target_addr_t addre
        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;
        }
 
@@ -1221,6 +1197,8 @@ static int cortex_a_step(struct target *target, int current, target_addr_t addre
                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;
@@ -1232,7 +1210,7 @@ static int cortex_a_step(struct target *target, int current, target_addr_t addre
        /* 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;
        }
 
@@ -1276,7 +1254,7 @@ static int cortex_a_set_breakpoint(struct target *target,
        struct armv7a_common *armv7a = &cortex_a->armv7a_common;
        struct cortex_a_brp *brp_list = cortex_a->brp_list;
 
-       if (breakpoint->set) {
+       if (breakpoint->is_set) {
                LOG_WARNING("breakpoint already set");
                return ERROR_OK;
        }
@@ -1288,22 +1266,22 @@ static int cortex_a_set_breakpoint(struct target *target,
                        LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
                        return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
                }
-               breakpoint->set = brp_i + 1;
+               breakpoint_hw_set(breakpoint, brp_i);
                if (breakpoint->length == 2)
                        byte_addr_select = (3 << (breakpoint->address & 0x02));
                control = ((matchmode & 0x7) << 20)
                        | (byte_addr_select << 5)
                        | (3 << 1) | 1;
-               brp_list[brp_i].used = 1;
+               brp_list[brp_i].used = true;
                brp_list[brp_i].value = (breakpoint->address & 0xFFFFFFFC);
                brp_list[brp_i].control = control;
                retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                               + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
+                               + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn,
                                brp_list[brp_i].value);
                if (retval != ERROR_OK)
                        return retval;
                retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                               + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
+                               + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn,
                                brp_list[brp_i].control);
                if (retval != ERROR_OK)
                        return retval;
@@ -1353,7 +1331,7 @@ static int cortex_a_set_breakpoint(struct target *target,
                armv7a_l1_i_cache_inval_virt(target, breakpoint->address,
                                                 breakpoint->length);
 
-               breakpoint->set = 0x11; /* Any nice value but 0 */
+               breakpoint->is_set = true;
        }
 
        return ERROR_OK;
@@ -1370,7 +1348,7 @@ static int cortex_a_set_context_breakpoint(struct target *target,
        struct armv7a_common *armv7a = &cortex_a->armv7a_common;
        struct cortex_a_brp *brp_list = cortex_a->brp_list;
 
-       if (breakpoint->set) {
+       if (breakpoint->is_set) {
                LOG_WARNING("breakpoint already set");
                return retval;
        }
@@ -1384,20 +1362,20 @@ static int cortex_a_set_context_breakpoint(struct target *target,
                return ERROR_FAIL;
        }
 
-       breakpoint->set = brp_i + 1;
+       breakpoint_hw_set(breakpoint, brp_i);
        control = ((matchmode & 0x7) << 20)
                | (byte_addr_select << 5)
                | (3 << 1) | 1;
-       brp_list[brp_i].used = 1;
+       brp_list[brp_i].used = true;
        brp_list[brp_i].value = (breakpoint->asid);
        brp_list[brp_i].control = control;
        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
+                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn,
                        brp_list[brp_i].value);
        if (retval != ERROR_OK)
                return retval;
        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
+                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn,
                        brp_list[brp_i].control);
        if (retval != ERROR_OK)
                return retval;
@@ -1413,16 +1391,16 @@ static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoi
        int retval = ERROR_FAIL;
        int brp_1 = 0;  /* holds the contextID pair */
        int brp_2 = 0;  /* holds the IVA pair */
-       uint32_t control_CTX, control_IVA;
-       uint8_t CTX_byte_addr_select = 0x0F;
-       uint8_t IVA_byte_addr_select = 0x0F;
-       uint8_t CTX_machmode = 0x03;
-       uint8_t IVA_machmode = 0x01;
+       uint32_t control_ctx, control_iva;
+       uint8_t ctx_byte_addr_select = 0x0F;
+       uint8_t iva_byte_addr_select = 0x0F;
+       uint8_t ctx_machmode = 0x03;
+       uint8_t iva_machmode = 0x01;
        struct cortex_a_common *cortex_a = target_to_cortex_a(target);
        struct armv7a_common *armv7a = &cortex_a->armv7a_common;
        struct cortex_a_brp *brp_list = cortex_a->brp_list;
 
-       if (breakpoint->set) {
+       if (breakpoint->is_set) {
                LOG_WARNING("breakpoint already set");
                return retval;
        }
@@ -1431,7 +1409,7 @@ static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoi
                (brp_list[brp_1].type != BRP_CONTEXT)) && (brp_1 < cortex_a->brp_num))
                brp_1++;
 
-       printf("brp(CTX) found num: %d\n", brp_1);
+       LOG_DEBUG("brp(CTX) found num: %d", brp_1);
        if (brp_1 >= cortex_a->brp_num) {
                LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
                return ERROR_FAIL;
@@ -1441,47 +1419,47 @@ static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoi
                (brp_list[brp_2].type != BRP_NORMAL)) && (brp_2 < cortex_a->brp_num))
                brp_2++;
 
-       printf("brp(IVA) found num: %d\n", brp_2);
+       LOG_DEBUG("brp(IVA) found num: %d", brp_2);
        if (brp_2 >= cortex_a->brp_num) {
                LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
                return ERROR_FAIL;
        }
 
-       breakpoint->set = brp_1 + 1;
-       breakpoint->linked_BRP = brp_2;
-       control_CTX = ((CTX_machmode & 0x7) << 20)
+       breakpoint_hw_set(breakpoint, brp_1);
+       breakpoint->linked_brp = brp_2;
+       control_ctx = ((ctx_machmode & 0x7) << 20)
                | (brp_2 << 16)
                | (0 << 14)
-               | (CTX_byte_addr_select << 5)
+               | (ctx_byte_addr_select << 5)
                | (3 << 1) | 1;
-       brp_list[brp_1].used = 1;
+       brp_list[brp_1].used = true;
        brp_list[brp_1].value = (breakpoint->asid);
-       brp_list[brp_1].control = control_CTX;
+       brp_list[brp_1].control = control_ctx;
        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_1].BRPn,
+                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_1].brpn,
                        brp_list[brp_1].value);
        if (retval != ERROR_OK)
                return retval;
        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_1].BRPn,
+                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_1].brpn,
                        brp_list[brp_1].control);
        if (retval != ERROR_OK)
                return retval;
 
-       control_IVA = ((IVA_machmode & 0x7) << 20)
+       control_iva = ((iva_machmode & 0x7) << 20)
                | (brp_1 << 16)
-               | (IVA_byte_addr_select << 5)
+               | (iva_byte_addr_select << 5)
                | (3 << 1) | 1;
-       brp_list[brp_2].used = 1;
+       brp_list[brp_2].used = true;
        brp_list[brp_2].value = (breakpoint->address & 0xFFFFFFFC);
-       brp_list[brp_2].control = control_IVA;
+       brp_list[brp_2].control = control_iva;
        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_2].BRPn,
+                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_2].brpn,
                        brp_list[brp_2].value);
        if (retval != ERROR_OK)
                return retval;
        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_2].BRPn,
+                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_2].brpn,
                        brp_list[brp_2].control);
        if (retval != ERROR_OK)
                return retval;
@@ -1496,31 +1474,31 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b
        struct armv7a_common *armv7a = &cortex_a->armv7a_common;
        struct cortex_a_brp *brp_list = cortex_a->brp_list;
 
-       if (!breakpoint->set) {
+       if (!breakpoint->is_set) {
                LOG_WARNING("breakpoint not set");
                return ERROR_OK;
        }
 
        if (breakpoint->type == BKPT_HARD) {
                if ((breakpoint->address != 0) && (breakpoint->asid != 0)) {
-                       int brp_i = breakpoint->set - 1;
-                       int brp_j = breakpoint->linked_BRP;
-                       if ((brp_i < 0) || (brp_i >= cortex_a->brp_num)) {
+                       int brp_i = breakpoint->number;
+                       int brp_j = breakpoint->linked_brp;
+                       if (brp_i >= cortex_a->brp_num) {
                                LOG_DEBUG("Invalid BRP number in breakpoint");
                                return ERROR_OK;
                        }
                        LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
                                brp_list[brp_i].control, brp_list[brp_i].value);
-                       brp_list[brp_i].used = 0;
+                       brp_list[brp_i].used = false;
                        brp_list[brp_i].value = 0;
                        brp_list[brp_i].control = 0;
                        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
+                                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn,
                                        brp_list[brp_i].control);
                        if (retval != ERROR_OK)
                                return retval;
                        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
+                                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn,
                                        brp_list[brp_i].value);
                        if (retval != ERROR_OK)
                                return retval;
@@ -1530,45 +1508,45 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b
                        }
                        LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_j,
                                brp_list[brp_j].control, brp_list[brp_j].value);
-                       brp_list[brp_j].used = 0;
+                       brp_list[brp_j].used = false;
                        brp_list[brp_j].value = 0;
                        brp_list[brp_j].control = 0;
                        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_j].BRPn,
+                                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_j].brpn,
                                        brp_list[brp_j].control);
                        if (retval != ERROR_OK)
                                return retval;
                        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_j].BRPn,
+                                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_j].brpn,
                                        brp_list[brp_j].value);
                        if (retval != ERROR_OK)
                                return retval;
-                       breakpoint->linked_BRP = 0;
-                       breakpoint->set = 0;
+                       breakpoint->linked_brp = 0;
+                       breakpoint->is_set = false;
                        return ERROR_OK;
 
                } else {
-                       int brp_i = breakpoint->set - 1;
-                       if ((brp_i < 0) || (brp_i >= cortex_a->brp_num)) {
+                       int brp_i = breakpoint->number;
+                       if (brp_i >= cortex_a->brp_num) {
                                LOG_DEBUG("Invalid BRP number in breakpoint");
                                return ERROR_OK;
                        }
                        LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
                                brp_list[brp_i].control, brp_list[brp_i].value);
-                       brp_list[brp_i].used = 0;
+                       brp_list[brp_i].used = false;
                        brp_list[brp_i].value = 0;
                        brp_list[brp_i].control = 0;
                        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
+                                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn,
                                        brp_list[brp_i].control);
                        if (retval != ERROR_OK)
                                return retval;
                        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
-                                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
+                                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn,
                                        brp_list[brp_i].value);
                        if (retval != ERROR_OK)
                                return retval;
-                       breakpoint->set = 0;
+                       breakpoint->is_set = false;
                        return ERROR_OK;
                }
        } else {
@@ -1600,7 +1578,7 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b
                armv7a_l1_i_cache_inval_virt(target, breakpoint->address,
                                                 breakpoint->length);
        }
-       breakpoint->set = 0;
+       breakpoint->is_set = false;
 
        return ERROR_OK;
 }
@@ -1666,7 +1644,7 @@ static int cortex_a_remove_breakpoint(struct target *target, struct breakpoint *
        }
 #endif
 
-       if (breakpoint->set) {
+       if (breakpoint->is_set) {
                cortex_a_unset_breakpoint(target, breakpoint);
                if (breakpoint->type == BKPT_HARD)
                        cortex_a->brp_num_available++;
@@ -1676,6 +1654,200 @@ static int cortex_a_remove_breakpoint(struct target *target, struct breakpoint *
        return ERROR_OK;
 }
 
+/**
+ * Sets a watchpoint for an Cortex-A target in one of the watchpoint units.  It is
+ * considered a bug to call this function when there are no available watchpoint
+ * units.
+ *
+ * @param target Pointer to an Cortex-A target to set a watchpoint on
+ * @param watchpoint Pointer to the watchpoint to be set
+ * @return Error status if watchpoint set fails or the result of executing the
+ * JTAG queue
+ */
+static int cortex_a_set_watchpoint(struct target *target, struct watchpoint *watchpoint)
+{
+       int retval = ERROR_OK;
+       int wrp_i = 0;
+       uint32_t control;
+       uint32_t address;
+       uint8_t address_mask;
+       uint8_t byte_address_select;
+       uint8_t load_store_access_control = 0x3;
+       struct cortex_a_common *cortex_a = target_to_cortex_a(target);
+       struct armv7a_common *armv7a = &cortex_a->armv7a_common;
+       struct cortex_a_wrp *wrp_list = cortex_a->wrp_list;
+
+       if (watchpoint->is_set) {
+               LOG_WARNING("watchpoint already set");
+               return retval;
+       }
+
+       /* check available context WRPs */
+       while (wrp_list[wrp_i].used && (wrp_i < cortex_a->wrp_num))
+               wrp_i++;
+
+       if (wrp_i >= cortex_a->wrp_num) {
+               LOG_ERROR("ERROR Can not find free Watchpoint Register Pair");
+               return ERROR_FAIL;
+       }
+
+       if (watchpoint->length == 0 || watchpoint->length > 0x80000000U ||
+                       (watchpoint->length & (watchpoint->length - 1))) {
+               LOG_WARNING("watchpoint length must be a power of 2");
+               return ERROR_FAIL;
+       }
+
+       if (watchpoint->address & (watchpoint->length - 1)) {
+               LOG_WARNING("watchpoint address must be aligned at length");
+               return ERROR_FAIL;
+       }
+
+       /* FIXME: ARM DDI 0406C: address_mask is optional. What to do if it's missing?  */
+       /* handle wp length 1 and 2 through byte select */
+       switch (watchpoint->length) {
+       case 1:
+               byte_address_select = BIT(watchpoint->address & 0x3);
+               address = watchpoint->address & ~0x3;
+               address_mask = 0;
+               break;
+
+       case 2:
+               byte_address_select = 0x03 << (watchpoint->address & 0x2);
+               address = watchpoint->address & ~0x3;
+               address_mask = 0;
+               break;
+
+       case 4:
+               byte_address_select = 0x0f;
+               address = watchpoint->address;
+               address_mask = 0;
+               break;
+
+       default:
+               byte_address_select = 0xff;
+               address = watchpoint->address;
+               address_mask = ilog2(watchpoint->length);
+               break;
+       }
+
+       watchpoint_set(watchpoint, wrp_i);
+       control = (address_mask << 24) |
+               (byte_address_select << 5) |
+               (load_store_access_control << 3) |
+               (0x3 << 1) | 1;
+       wrp_list[wrp_i].used = true;
+       wrp_list[wrp_i].value = address;
+       wrp_list[wrp_i].control = control;
+
+       retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
+                       + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].wrpn,
+                       wrp_list[wrp_i].value);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
+                       + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].wrpn,
+                       wrp_list[wrp_i].control);
+       if (retval != ERROR_OK)
+               return retval;
+
+       LOG_DEBUG("wp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, wrp_i,
+                       wrp_list[wrp_i].control,
+                       wrp_list[wrp_i].value);
+
+       return ERROR_OK;
+}
+
+/**
+ * Unset an existing watchpoint and clear the used watchpoint unit.
+ *
+ * @param target Pointer to the target to have the watchpoint removed
+ * @param watchpoint Pointer to the watchpoint to be removed
+ * @return Error status while trying to unset the watchpoint or the result of
+ *         executing the JTAG queue
+ */
+static int cortex_a_unset_watchpoint(struct target *target, struct watchpoint *watchpoint)
+{
+       int retval;
+       struct cortex_a_common *cortex_a = target_to_cortex_a(target);
+       struct armv7a_common *armv7a = &cortex_a->armv7a_common;
+       struct cortex_a_wrp *wrp_list = cortex_a->wrp_list;
+
+       if (!watchpoint->is_set) {
+               LOG_WARNING("watchpoint not set");
+               return ERROR_OK;
+       }
+
+       int wrp_i = watchpoint->number;
+       if (wrp_i >= cortex_a->wrp_num) {
+               LOG_DEBUG("Invalid WRP number in watchpoint");
+               return ERROR_OK;
+       }
+       LOG_DEBUG("wrp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, wrp_i,
+                       wrp_list[wrp_i].control, wrp_list[wrp_i].value);
+       wrp_list[wrp_i].used = false;
+       wrp_list[wrp_i].value = 0;
+       wrp_list[wrp_i].control = 0;
+       retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
+                       + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].wrpn,
+                       wrp_list[wrp_i].control);
+       if (retval != ERROR_OK)
+               return retval;
+       retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
+                       + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].wrpn,
+                       wrp_list[wrp_i].value);
+       if (retval != ERROR_OK)
+               return retval;
+       watchpoint->is_set = false;
+
+       return ERROR_OK;
+}
+
+/**
+ * Add a watchpoint to an Cortex-A target.  If there are no watchpoint units
+ * available, an error response is returned.
+ *
+ * @param target Pointer to the Cortex-A target to add a watchpoint to
+ * @param watchpoint Pointer to the watchpoint to be added
+ * @return Error status while trying to add the watchpoint
+ */
+static int cortex_a_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
+{
+       struct cortex_a_common *cortex_a = target_to_cortex_a(target);
+
+       if (cortex_a->wrp_num_available < 1) {
+               LOG_INFO("no hardware watchpoint available");
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+
+       int retval = cortex_a_set_watchpoint(target, watchpoint);
+       if (retval != ERROR_OK)
+               return retval;
+
+       cortex_a->wrp_num_available--;
+       return ERROR_OK;
+}
+
+/**
+ * Remove a watchpoint from an Cortex-A target.  The watchpoint will be unset and
+ * the used watchpoint unit will be reopened.
+ *
+ * @param target Pointer to the target to remove a watchpoint from
+ * @param watchpoint Pointer to the watchpoint to be removed
+ * @return Result of trying to unset the watchpoint
+ */
+static int cortex_a_remove_watchpoint(struct target *target, struct watchpoint *watchpoint)
+{
+       struct cortex_a_common *cortex_a = target_to_cortex_a(target);
+
+       if (watchpoint->is_set) {
+               cortex_a->wrp_num_available++;
+               cortex_a_unset_watchpoint(target, watchpoint);
+       }
+       return ERROR_OK;
+}
+
+
 /*
  * Cortex-A Reset functions
  */
@@ -1699,12 +1871,12 @@ static int cortex_a_assert_reset(struct target *target)
                 */
 
                /*
-                * FIXME: fix reset when transport is SWD. This is a temporary
+                * 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_swd() ||
+               if (!transport_is_jtag() ||
                                (target->reset_halt && (jtag_get_reset_config() & RESET_SRST_NO_GATING)))
-                       jtag_add_reset(0, 1);
+                       adapter_assert_reset();
 
        } else {
                LOG_ERROR("%s: how to reset?", target_name(target));
@@ -1722,12 +1894,13 @@ 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();
 
        if (target_was_examined(target)) {
                retval = cortex_a_poll(target);
@@ -1740,7 +1913,8 @@ static int cortex_a_deassert_reset(struct target *target)
                        LOG_WARNING("%s: ran after reset and before halt ...",
                                target_name(target));
                        if (target_was_examined(target)) {
-                               retval = target_halt(target);
+                               retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+                                               armv7a->debug_base + CPUDBG_DRCR, DRCR_HALT);
                                if (retval != ERROR_OK)
                                        return retval;
                        } else
@@ -1778,14 +1952,22 @@ static int cortex_a_wait_dscr_bits(struct target *target, uint32_t mask,
 {
        /* Waits until the specified bit(s) of DSCR take on a specified value. */
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       int64_t then = timeval_ms();
+       int64_t then;
        int retval;
 
-       while ((*dscr & mask) != value) {
+       if ((*dscr & mask) == value)
+               return ERROR_OK;
+
+       then = timeval_ms();
+       while (1) {
                retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DSCR, dscr);
-               if (retval != ERROR_OK)
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("Could not read DSCR register");
                        return retval;
+               }
+               if ((*dscr & mask) == value)
+                       break;
                if (timeval_ms() > then + 1000) {
                        LOG_ERROR("timeout waiting for DSCR bit change");
                        return ERROR_FAIL;
@@ -1929,7 +2111,8 @@ static int cortex_a_write_cpu_memory_slow(struct target *target,
 {
        /* 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
+        * 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:
@@ -2086,7 +2269,22 @@ static int cortex_a_write_cpu_memory(struct target *target,
                /* We are doing a word-aligned transfer, so use fast mode. */
                retval = cortex_a_write_cpu_memory_fast(target, count, buffer, &dscr);
        } else {
-               /* Use slow path. */
+               /* 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);
        }
 
@@ -2172,7 +2370,8 @@ static int cortex_a_read_cpu_memory_slow(struct target *target,
 {
        /* 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
+        * 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:
@@ -2388,7 +2587,23 @@ static int cortex_a_read_cpu_memory(struct target *target,
                /* We are doing a word-aligned transfer, so use fast mode. */
                retval = cortex_a_read_cpu_memory_fast(target, count, buffer, &dscr);
        } else {
-               /* Use slow path. */
+               /* 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);
        }
 
@@ -2474,7 +2689,7 @@ static int cortex_a_read_phys_memory(struct target *target,
        if (!count || !buffer)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       LOG_DEBUG("Reading memory at real address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32,
+       LOG_DEBUG("Reading memory at real address " TARGET_ADDR_FMT "; size %" PRIu32 "; count %" PRIu32,
                address, size, count);
 
        /* read memory through the CPU */
@@ -2491,7 +2706,7 @@ static int cortex_a_read_memory(struct target *target, target_addr_t address,
        int retval;
 
        /* cortex_a handles unaligned memory access */
-       LOG_DEBUG("Reading memory at address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32,
+       LOG_DEBUG("Reading memory at address " TARGET_ADDR_FMT "; size %" PRIu32 "; count %" PRIu32,
                address, size, count);
 
        cortex_a_prep_memaccess(target, 0);
@@ -2510,7 +2725,7 @@ static int cortex_a_write_phys_memory(struct target *target,
        if (!count || !buffer)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       LOG_DEBUG("Writing memory to real address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32,
+       LOG_DEBUG("Writing memory to real address " TARGET_ADDR_FMT "; size %" PRIu32 "; count %" PRIu32,
                address, size, count);
 
        /* write memory through the CPU */
@@ -2527,7 +2742,7 @@ static int cortex_a_write_memory(struct target *target, target_addr_t address,
        int retval;
 
        /* cortex_a handles unaligned memory access */
-       LOG_DEBUG("Writing memory at address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32,
+       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 */
@@ -2653,16 +2868,30 @@ static int cortex_a_examine_first(struct target *target)
        struct cortex_a_common *cortex_a = target_to_cortex_a(target);
        struct armv7a_common *armv7a = &cortex_a->armv7a_common;
        struct adiv5_dap *swjdp = armv7a->arm.dap;
+       struct adiv5_private_config *pc = target->private_config;
 
        int i;
        int retval = ERROR_OK;
-       uint32_t didr, cpuid, dbg_osreg;
+       uint32_t didr, cpuid, dbg_osreg, dbg_idpfr1;
 
-       /* Search for the APB-AP - it is needed for access to debug registers */
-       retval = dap_find_ap(swjdp, AP_TYPE_APB_AP, &armv7a->debug_ap);
-       if (retval != ERROR_OK) {
-               LOG_ERROR("Could not find APB-AP for debug access");
-               return retval;
+       if (armv7a->debug_ap) {
+               dap_put_ap(armv7a->debug_ap);
+               armv7a->debug_ap = NULL;
+       }
+
+       if (pc->ap_num == DP_APSEL_INVALID) {
+               /* Search for the APB-AP - it is needed for access to debug registers */
+               retval = dap_find_get_ap(swjdp, AP_TYPE_APB_AP, &armv7a->debug_ap);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("Could not find APB-AP for debug access");
+                       return retval;
+               }
+       } else {
+               armv7a->debug_ap = dap_get_ap(swjdp, pc->ap_num);
+               if (!armv7a->debug_ap) {
+                       LOG_ERROR("Cannot get AP");
+                       return ERROR_FAIL;
+               }
        }
 
        retval = mem_ap_init(armv7a->debug_ap);
@@ -2674,28 +2903,25 @@ static int cortex_a_examine_first(struct target *target)
        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(armv7a->debug_ap, &dbgbase, &apid);
-               if (retval != ERROR_OK)
-                       return retval;
-               /* Lookup 0x15 -- Processor DAP */
-               retval = dap_lookup_cs_component(armv7a->debug_ap, dbgbase, 0x15,
-                               &armv7a->debug_base, &coreidx);
+               /* Lookup Processor DAP */
+               retval = dap_lookup_cs_component(armv7a->debug_ap, ARM_CS_C9_DEVTYPE_CORE_DEBUG,
+                               &armv7a->debug_base, target->coreid);
                if (retval != ERROR_OK) {
                        LOG_ERROR("Can't detect %s's dbgbase from the ROM table; you need to specify it explicitly.",
                                  target->cmd_name);
                        return retval;
                }
-               LOG_DEBUG("Detected core %" PRId32 " dbgbase: %08" PRIx32,
+               LOG_DEBUG("Detected core %" PRId32 " dbgbase: " TARGET_ADDR_FMT,
                          target->coreid, armv7a->debug_base);
        } else
                armv7a->debug_base = target->dbgbase;
 
+       if ((armv7a->debug_base & (1UL<<31)) == 0)
+               LOG_WARNING("Debug base address for target %s has bit 31 set to 0. Access to debug registers will likely fail!\n"
+                           "Please fix the target configuration.", target_name(target));
+
        retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DIDR, &didr);
        if (retval != ERROR_OK) {
@@ -2761,7 +2987,25 @@ static int cortex_a_examine_first(struct target *target)
                }
        }
 
-       armv7a->arm.core_type = ARM_MODE_MON;
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
+                                armv7a->debug_base + CPUDBG_ID_PFR1, &dbg_idpfr1);
+       if (retval != ERROR_OK)
+               return retval;
+
+       if (dbg_idpfr1 & 0x000000f0) {
+               LOG_DEBUG("target->coreid %" PRId32 " has security extensions",
+                               target->coreid);
+               armv7a->arm.core_type = ARM_CORE_TYPE_SEC_EXT;
+       }
+       if (dbg_idpfr1 & 0x0000f000) {
+               LOG_DEBUG("target->coreid %" PRId32 " has virtualization extensions",
+                               target->coreid);
+               /*
+                * overwrite and simplify the checks.
+                * virtualization extensions require implementation of security extension
+                */
+               armv7a->arm.core_type = ARM_CORE_TYPE_VIRT_EXT;
+       }
 
        /* Avoid recreating the registers cache */
        if (!target_was_examined(target)) {
@@ -2778,18 +3022,32 @@ static int cortex_a_examine_first(struct target *target)
        cortex_a->brp_list = calloc(cortex_a->brp_num, sizeof(struct cortex_a_brp));
 /*     cortex_a->brb_enabled = ????; */
        for (i = 0; i < cortex_a->brp_num; i++) {
-               cortex_a->brp_list[i].used = 0;
+               cortex_a->brp_list[i].used = false;
                if (i < (cortex_a->brp_num-cortex_a->brp_num_context))
                        cortex_a->brp_list[i].type = BRP_NORMAL;
                else
                        cortex_a->brp_list[i].type = BRP_CONTEXT;
                cortex_a->brp_list[i].value = 0;
                cortex_a->brp_list[i].control = 0;
-               cortex_a->brp_list[i].BRPn = i;
+               cortex_a->brp_list[i].brpn = i;
        }
 
        LOG_DEBUG("Configured %i hw breakpoints", cortex_a->brp_num);
 
+       /* Setup Watchpoint Register Pairs */
+       cortex_a->wrp_num = ((didr >> 28) & 0x0F) + 1;
+       cortex_a->wrp_num_available = cortex_a->wrp_num;
+       free(cortex_a->wrp_list);
+       cortex_a->wrp_list = calloc(cortex_a->wrp_num, sizeof(struct cortex_a_wrp));
+       for (i = 0; i < cortex_a->wrp_num; i++) {
+               cortex_a->wrp_list[i].used = false;
+               cortex_a->wrp_list[i].value = 0;
+               cortex_a->wrp_list[i].control = 0;
+               cortex_a->wrp_list[i].wrpn = i;
+       }
+
+       LOG_DEBUG("Configured %i hw watchpoints", cortex_a->wrp_num);
+
        /* select debug_ap as default */
        swjdp->apsel = armv7a->debug_ap->ap_num;
 
@@ -2846,24 +3104,29 @@ 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));
-       cortex_a->common_magic = CORTEX_A_COMMON_MAGIC;
+       struct cortex_a_common *cortex_a;
        struct adiv5_private_config *pc;
 
-       if (target->private_config == NULL)
+       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, pc->dap);
@@ -2871,14 +3134,19 @@ static int cortex_a_target_create(struct target *target, Jim_Interp *interp)
 
 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));
-       cortex_a->common_magic = CORTEX_A_COMMON_MAGIC;
+       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, pc->dap);
@@ -2902,7 +3170,12 @@ static void cortex_a_deinit_target(struct target *target)
                                        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);
@@ -2949,7 +3222,7 @@ static int cortex_a_virt2phys(struct target *target,
        if (retval != ERROR_OK)
                return retval;
        return armv7a_mmu_translate_va_pa(target, (uint32_t)virt,
-                                                   (uint32_t *)phys, 1);
+                                                   phys, 1);
 }
 
 COMMAND_HANDLER(cortex_a_handle_cache_info_command)
@@ -2957,7 +3230,7 @@ COMMAND_HANDLER(cortex_a_handle_cache_info_command)
        struct target *target = get_current_target(CMD_CTX);
        struct armv7a_common *armv7a = target_to_armv7a(target);
 
-       return armv7a_handle_cache_info_command(CMD_CTX,
+       return armv7a_handle_cache_info_command(CMD,
                        &armv7a->armv7a_mmu.armv7a_cache);
 }
 
@@ -2972,79 +3245,22 @@ COMMAND_HANDLER(cortex_a_handle_dbginit_command)
 
        return cortex_a_init_debug_access(target);
 }
-COMMAND_HANDLER(cortex_a_handle_smp_off_command)
-{
-       struct target *target = get_current_target(CMD_CTX);
-       /* check target is an smp target */
-       struct target_list *head;
-       struct target *curr;
-       head = target->head;
-       target->smp = 0;
-       if (head != (struct target_list *)NULL) {
-               while (head != (struct target_list *)NULL) {
-                       curr = head->target;
-                       curr->smp = 0;
-                       head = head->next;
-               }
-               /*  fixes the target display to the debugger */
-               target->gdb_service->target = target;
-       }
-       return ERROR_OK;
-}
-
-COMMAND_HANDLER(cortex_a_handle_smp_on_command)
-{
-       struct target *target = get_current_target(CMD_CTX);
-       struct target_list *head;
-       struct target *curr;
-       head = target->head;
-       if (head != (struct target_list *)NULL) {
-               target->smp = 1;
-               while (head != (struct target_list *)NULL) {
-                       curr = head->target;
-                       curr->smp = 1;
-                       head = head->next;
-               }
-       }
-       return ERROR_OK;
-}
-
-COMMAND_HANDLER(cortex_a_handle_smp_gdb_command)
-{
-       struct target *target = get_current_target(CMD_CTX);
-       int retval = ERROR_OK;
-       struct target_list *head;
-       head = target->head;
-       if (head != (struct target_list *)NULL) {
-               if (CMD_ARGC == 1) {
-                       int coreid = 0;
-                       COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], coreid);
-                       if (ERROR_OK != retval)
-                               return retval;
-                       target->gdb_service->core[1] = coreid;
-
-               }
-               command_print(CMD_CTX, "gdb coreid  %" PRId32 " -> %" PRId32, target->gdb_service->core[0]
-                       , target->gdb_service->core[1]);
-       }
-       return ERROR_OK;
-}
 
 COMMAND_HANDLER(handle_cortex_a_mask_interrupts_command)
 {
        struct target *target = get_current_target(CMD_CTX);
        struct cortex_a_common *cortex_a = target_to_cortex_a(target);
 
-       static const Jim_Nvp nvp_maskisr_modes[] = {
+       static const struct jim_nvp nvp_maskisr_modes[] = {
                { .name = "off", .value = CORTEX_A_ISRMASK_OFF },
                { .name = "on", .value = CORTEX_A_ISRMASK_ON },
                { .name = NULL, .value = -1 },
        };
-       const Jim_Nvp *n;
+       const struct jim_nvp *n;
 
        if (CMD_ARGC > 0) {
-               n = Jim_Nvp_name2value_simple(nvp_maskisr_modes, CMD_ARGV[0]);
-               if (n->name == NULL) {
+               n = jim_nvp_name2value_simple(nvp_maskisr_modes, CMD_ARGV[0]);
+               if (!n->name) {
                        LOG_ERROR("Unknown parameter: %s - should be off or on", CMD_ARGV[0]);
                        return ERROR_COMMAND_SYNTAX_ERROR;
                }
@@ -3052,8 +3268,8 @@ COMMAND_HANDLER(handle_cortex_a_mask_interrupts_command)
                cortex_a->isrmasking_mode = n->value;
        }
 
-       n = Jim_Nvp_value2name_simple(nvp_maskisr_modes, cortex_a->isrmasking_mode);
-       command_print(CMD_CTX, "cortex_a interrupt mask %s", n->name);
+       n = jim_nvp_value2name_simple(nvp_maskisr_modes, cortex_a->isrmasking_mode);
+       command_print(CMD, "cortex_a interrupt mask %s", n->name);
 
        return ERROR_OK;
 }
@@ -3063,23 +3279,23 @@ COMMAND_HANDLER(handle_cortex_a_dacrfixup_command)
        struct target *target = get_current_target(CMD_CTX);
        struct cortex_a_common *cortex_a = target_to_cortex_a(target);
 
-       static const Jim_Nvp nvp_dacrfixup_modes[] = {
+       static const struct jim_nvp nvp_dacrfixup_modes[] = {
                { .name = "off", .value = CORTEX_A_DACRFIXUP_OFF },
                { .name = "on", .value = CORTEX_A_DACRFIXUP_ON },
                { .name = NULL, .value = -1 },
        };
-       const Jim_Nvp *n;
+       const struct jim_nvp *n;
 
        if (CMD_ARGC > 0) {
-               n = Jim_Nvp_name2value_simple(nvp_dacrfixup_modes, CMD_ARGV[0]);
-               if (n->name == NULL)
+               n = jim_nvp_name2value_simple(nvp_dacrfixup_modes, CMD_ARGV[0]);
+               if (!n->name)
                        return ERROR_COMMAND_SYNTAX_ERROR;
                cortex_a->dacrfixup_mode = n->value;
 
        }
 
-       n = Jim_Nvp_value2name_simple(nvp_dacrfixup_modes, cortex_a->dacrfixup_mode);
-       command_print(CMD_CTX, "cortex_a domain access control fixup %s", n->name);
+       n = jim_nvp_value2name_simple(nvp_dacrfixup_modes, cortex_a->dacrfixup_mode);
+       command_print(CMD, "cortex_a domain access control fixup %s", n->name);
 
        return ERROR_OK;
 }
@@ -3099,25 +3315,6 @@ static const struct command_registration cortex_a_exec_command_handlers[] = {
                .help = "Initialize core debug",
                .usage = "",
        },
-       {   .name = "smp_off",
-           .handler = cortex_a_handle_smp_off_command,
-           .mode = COMMAND_EXEC,
-           .help = "Stop smp handling",
-           .usage = "",},
-       {
-               .name = "smp_on",
-               .handler = cortex_a_handle_smp_on_command,
-               .mode = COMMAND_EXEC,
-               .help = "Restart smp handling",
-               .usage = "",
-       },
-       {
-               .name = "smp_gdb",
-               .handler = cortex_a_handle_smp_gdb_command,
-               .mode = COMMAND_EXEC,
-               .help = "display/fix current core played to gdb",
-               .usage = "",
-       },
        {
                .name = "maskisr",
                .handler = handle_cortex_a_mask_interrupts_command,
@@ -3136,6 +3333,9 @@ static const struct command_registration cortex_a_exec_command_handlers[] = {
        {
                .chain = armv7a_mmu_command_handlers,
        },
+       {
+               .chain = smp_command_handlers,
+       },
 
        COMMAND_REGISTRATION_DONE
 };
@@ -3158,7 +3358,6 @@ static const struct command_registration cortex_a_command_handlers[] = {
 
 struct target_type cortexa_target = {
        .name = "cortex_a",
-       .deprecated_name = "cortex_a8",
 
        .poll = cortex_a_poll,
        .arch_state = armv7a_arch_state,
@@ -3171,6 +3370,7 @@ struct target_type cortexa_target = {
        .deassert_reset = cortex_a_deassert_reset,
 
        /* REVISIT allow exporting VFP3 registers ... */
+       .get_gdb_arch = arm_get_gdb_arch,
        .get_gdb_reg_list = arm_get_gdb_reg_list,
 
        .read_memory = cortex_a_read_memory,
@@ -3188,8 +3388,8 @@ 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,
@@ -3250,6 +3450,7 @@ 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_phys_memory,
@@ -3264,8 +3465,8 @@ 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,