Cortex-A/R: Add missing timeout for loop polling DSCR & fix timeout types
[fw/openocd] / src / target / cortex_a.c
index 3f00511c22ffa88993c16d9c4f87fda8442cbbe8..e6e84bdaf72461b3f687293fe4bde678b4172086 100644 (file)
@@ -73,6 +73,7 @@ static int cortex_a_dap_read_coreregister_u32(struct target *target,
 static int cortex_a_dap_write_coreregister_u32(struct target *target,
        uint32_t value, int regnum);
 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,
@@ -97,33 +98,64 @@ static int cortex_a_restore_cp15_control_reg(struct target *target)
        return retval;
 }
 
-/*  check address before cortex_a_apb read write access with mmu on
- *  remove apb predictible data abort */
-static int cortex_a_check_address(struct target *target, uint32_t address)
+/*
+ * Set up ARM core for memory access.
+ * If !phys_access, switch to SVC mode and make sure MMU is on
+ * If phys_access, switch off mmu
+ */
+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);
-       uint32_t os_border = armv7a->armv7a_mmu.os_border;
-       if ((address < os_border) &&
-               (armv7a->arm.core_mode == ARM_MODE_SVC)) {
-               LOG_ERROR("%" PRIx32 " access in userspace and target in supervisor", address);
-               return ERROR_FAIL;
-       }
-       if ((address >= os_border) &&
-               (cortex_a->curr_mode != ARM_MODE_SVC)) {
+       int mmu_enabled = 0;
+
+       if (phys_access == 0) {
                dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC);
-               cortex_a->curr_mode = ARM_MODE_SVC;
-               LOG_INFO("%" PRIx32 " access in kernel space and target not in supervisor",
-                       address);
-               return ERROR_OK;
+               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)
+                       cortex_a_mmu_modify(target, 0);
        }
-       if ((address < os_border) &&
-               (cortex_a->curr_mode == ARM_MODE_SVC)) {
+       return ERROR_OK;
+}
+
+/*
+ * Restore ARM core after memory access.
+ * If !phys_access, switch to previous mode
+ * If phys_access, restore MMU setting
+ */
+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) {
+               if (cortex_a->dacrfixup_mode == CORTEX_A_DACRFIXUP_ON) {
+                       /* restore */
+                       armv7a->arm.mcr(target, 15,
+                                       0, 0, 3, 0,
+                                       cortex_a->cp15_dacr_reg);
+               }
                dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
-               cortex_a->curr_mode = ARM_MODE_ANY;
+       } else {
+               int mmu_enabled = 0;
+               cortex_a_mmu(target, &mmu_enabled);
+               if (mmu_enabled)
+                       cortex_a_mmu_modify(target, 1);
        }
        return ERROR_OK;
 }
+
+
 /*  modify cp15_control_reg in order to enable or disable mmu for :
  *  - virt2phys address conversion
  *  - read or write memory in phys or virt address */
@@ -170,18 +202,17 @@ static int cortex_a_mmu_modify(struct target *target, int enable)
 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,
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
        if (retval != ERROR_OK) {
                /* try again */
-               retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap,
+               retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
                if (retval == ERROR_OK)
                        LOG_USER(
@@ -197,7 +228,6 @@ static int cortex_a8_init_debug_access(struct target *target)
 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;
        int retval;
        uint32_t dbg_osreg;
        uint32_t cortex_part_num;
@@ -210,7 +240,7 @@ static int cortex_a_init_debug_access(struct target *target)
        switch (cortex_part_num) {
        case CORTEX_A7_PARTNUM:
        case CORTEX_A15_PARTNUM:
-               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
+               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                                    armv7a->debug_base + CPUDBG_OSLSR,
                                                    &dbg_osreg);
                if (retval != ERROR_OK)
@@ -220,7 +250,7 @@ static int cortex_a_init_debug_access(struct target *target)
 
                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,
+                       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                                                             armv7a->debug_base + CPUDBG_OSLAR,
                                                             0);
                break;
@@ -236,7 +266,7 @@ static int cortex_a_init_debug_access(struct target *target)
                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,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg);
        LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR  0x%" PRIx32, target->coreid, dbg_osreg);
 
@@ -244,13 +274,13 @@ static int cortex_a_init_debug_access(struct target *target)
                return retval;
 
        /* Disable cacheline fills and force cache write-through in debug state */
-       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap,
+       retval = mem_ap_write_atomic_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,
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSMCR, 0);
        if (retval != ERROR_OK)
                return retval;
@@ -269,11 +299,10 @@ 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();
+       int64_t then = timeval_ms();
        while ((*dscr & DSCR_INSTR_COMP) == 0 || force) {
                force = false;
-               int retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
+               int 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");
@@ -298,7 +327,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;
 
@@ -309,14 +337,14 @@ 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,
+       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();
+       int64_t then = timeval_ms();
        do {
-               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
+               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");
@@ -343,7 +371,6 @@ static int cortex_a_read_regs_through_mem(struct target *target, uint32_t addres
 {
        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)
@@ -355,7 +382,7 @@ static int cortex_a_read_regs_through_mem(struct target *target, uint32_t addres
        if (retval != ERROR_OK)
                return retval;
 
-       retval = mem_ap_sel_read_buf(swjdp, armv7a->memory_ap,
+       retval = mem_ap_read_buf(armv7a->memory_ap,
                        (uint8_t *)(&regfile[1]), 4, 15, address);
 
        return retval;
@@ -368,7 +395,6 @@ static int cortex_a_dap_read_coreregister_u32(struct target *target,
        uint8_t reg = regnum&0xFF;
        uint32_t dscr = 0;
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct adiv5_dap *swjdp = armv7a->arm.dap;
 
        if (reg > 17)
                return retval;
@@ -405,9 +431,9 @@ static int cortex_a_dap_read_coreregister_u32(struct target *target,
        }
 
        /* Wait for DTRRXfull then read DTRRTX */
-       long long then = timeval_ms();
+       int64_t then = timeval_ms();
        while ((dscr & DSCR_DTR_TX_FULL) == 0) {
-               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
+               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DSCR, &dscr);
                if (retval != ERROR_OK)
                        return retval;
@@ -417,7 +443,7 @@ static int cortex_a_dap_read_coreregister_u32(struct target *target,
                }
        }
 
-       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DTRTX, value);
        LOG_DEBUG("read DCC 0x%08" PRIx32, *value);
 
@@ -431,12 +457,11 @@ static int cortex_a_dap_write_coreregister_u32(struct target *target,
        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,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
        if (retval != ERROR_OK)
                return retval;
@@ -454,7 +479,7 @@ static int cortex_a_dap_write_coreregister_u32(struct target *target,
 
        /* 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,
+       retval = mem_ap_write_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DTRRX, value);
        if (retval != ERROR_OK)
                return retval;
@@ -510,9 +535,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, address, value);
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap, address, value);
 
        return retval;
 }
@@ -536,14 +560,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, 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;
 
@@ -551,9 +574,9 @@ 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();
+       int64_t then = timeval_ms();
        while ((dscr & DSCR_DTR_TX_FULL) == 0) {
-               retval = mem_ap_sel_read_atomic_u32(swjdp, a->armv7a_common.debug_ap,
+               retval = mem_ap_read_atomic_u32(a->armv7a_common.debug_ap,
                                a->armv7a_common.debug_base + CPUDBG_DSCR,
                                &dscr);
                if (retval != ERROR_OK)
@@ -564,7 +587,7 @@ static int cortex_a_read_dcc(struct cortex_a_common *a, uint32_t *data,
                }
        }
 
-       retval = mem_ap_sel_read_atomic_u32(swjdp, a->armv7a_common.debug_ap,
+       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;
@@ -579,14 +602,13 @@ 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();
+       int64_t then = timeval_ms();
        for (;; ) {
-               retval = mem_ap_sel_read_atomic_u32(swjdp, a->armv7a_common.debug_ap,
+               retval = mem_ap_read_atomic_u32(a->armv7a_common.debug_ap,
                                a->armv7a_common.debug_base + CPUDBG_DSCR,
                                &dscr);
                if (retval != ERROR_OK)
@@ -860,7 +882,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 */
@@ -874,7 +895,7 @@ static int cortex_a_poll(struct target *target)
                target_call_event_callbacks(target, TARGET_EVENT_HALTED);
                return retval;
        }
-       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
        if (retval != ERROR_OK)
                return retval;
@@ -930,13 +951,12 @@ static int cortex_a_halt(struct target *target)
        int retval = ERROR_OK;
        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,
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DRCR, DRCR_HALT);
        if (retval != ERROR_OK)
                return retval;
@@ -944,19 +964,19 @@ static int cortex_a_halt(struct target *target)
        /*
         * enter halting debug mode
         */
-       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
        if (retval != ERROR_OK)
                return retval;
 
-       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap,
+       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;
 
-       long long then = timeval_ms();
+       int64_t then = timeval_ms();
        for (;; ) {
-               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
+               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DSCR, &dscr);
                if (retval != ERROR_OK)
                        return retval;
@@ -1034,6 +1054,7 @@ static int cortex_a_internal_restore(struct target *target, int current,
        buf_set_u32(arm->pc->value, 0, 32, resume_pc);
        arm->pc->dirty = 1;
        arm->pc->valid = 1;
+
        /* restore dpm_mode at system halt */
        dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
        /* called it now before restoring context because it uses cpu
@@ -1071,7 +1092,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;
        /*
@@ -1082,7 +1102,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,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
        if (retval != ERROR_OK)
                return retval;
@@ -1090,20 +1110,20 @@ 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,
+       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,
+       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();
+       int64_t then = timeval_ms();
        for (;; ) {
-               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
+               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DSCR, &dscr);
                if (retval != ERROR_OK)
                        return retval;
@@ -1189,13 +1209,12 @@ static int cortex_a_debug_entry(struct target *target)
        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,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
        if (retval != ERROR_OK)
                return retval;
@@ -1207,7 +1226,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,
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, dscr);
        if (retval != ERROR_OK)
                return retval;
@@ -1219,7 +1238,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,
+               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_WFAR,
                                &wfar);
                if (retval != ERROR_OK)
@@ -1332,17 +1351,26 @@ 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 */
+       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);
+
+       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)
 {
        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,
+       int retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
        if (ERROR_OK != retval)
                return retval;
@@ -1353,7 +1381,7 @@ 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,
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, dscr);
        return retval;
 }
@@ -1415,7 +1443,7 @@ 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)
@@ -1934,8 +1962,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, 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;
@@ -1949,12 +1977,11 @@ 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 = timeval_ms();
        int retval;
 
        while ((*dscr & mask) != value) {
-               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
+               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DSCR, dscr);
                if (retval != ERROR_OK)
                        return retval;
@@ -1971,7 +1998,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);
@@ -1993,7 +2019,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,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DTRTX, data);
        if (retval != ERROR_OK)
                return retval;
@@ -2026,10 +2052,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,
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DTRRX, data);
        if (retval != ERROR_OK)
                return retval;
@@ -2111,7 +2136,6 @@ static int cortex_a_write_apb_ab_memory_slow(struct target *target,
         * - 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;
 
@@ -2133,7 +2157,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,
+               retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DTRRX, data);
                if (retval != ERROR_OK)
                        return retval;
@@ -2185,7 +2209,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. */
@@ -2194,13 +2217,13 @@ 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,
+       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, buffer,
+       return mem_ap_write_buf_noincr(armv7a->debug_ap, buffer,
                        4, count, armv7a->debug_base + CPUDBG_DTRRX);
 }
 
@@ -2211,7 +2234,6 @@ static int cortex_a_write_apb_ab_memory(struct target *target,
        /* Write memory through APB-AP. */
        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;
 
@@ -2226,13 +2248,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,
+       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,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
        if (retval != ERROR_OK)
                return retval;
@@ -2251,7 +2273,7 @@ static int cortex_a_write_apb_ab_memory(struct target *target,
                goto out;
 
        /* Get the memory address into R0. */
-       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap,
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DTRRX, address);
        if (retval != ERROR_OK)
                goto out;
@@ -2283,7 +2305,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)) {
@@ -2295,7 +2317,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,
+               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 {
@@ -2329,7 +2351,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,
+               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DTRTX, &dummy);
                if (final_retval == ERROR_OK)
                        final_retval = retval;
@@ -2357,7 +2379,6 @@ static int cortex_a_read_apb_ab_memory_slow(struct target *target,
         * - 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;
 
@@ -2402,7 +2423,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,
+               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DTRTX, &data);
                if (retval != ERROR_OK)
                        return retval;
@@ -2432,8 +2453,7 @@ 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 new_dscr, u32;
+       uint32_t u32;
        int retval;
 
        /* Switch to non-blocking mode if not already in that mode. */
@@ -2441,19 +2461,24 @@ static int cortex_a_read_apb_ab_memory_fast(struct target *target,
        if (retval != ERROR_OK)
                return retval;
 
-       if (count > 1) {
-               /* Consecutively issue the LDC instruction via a write to ITR and
-                * change to fast mode, in a single bulk copy since DSCR == ITR + 4.
-                * The instruction is issued into the core before the mode switch. */
-               uint8_t command[8];
-               target_buffer_set_u32(target, command, ARMV4_5_LDC(0, 1, 0, 1, 14, 5, 0, 4));
-               new_dscr = (*dscr & ~DSCR_EXT_DCC_MASK) | DSCR_EXT_DCC_FAST_MODE;
-               target_buffer_set_u32(target, command + 4, new_dscr);
-               retval = mem_ap_sel_write_buf(swjdp, armv7a->debug_ap, command, 4, 2,
-                               armv7a->debug_base + CPUDBG_ITR);
+       /* Issue the LDC instruction via a write to ITR. */
+       retval = cortex_a_exec_opcode(target, ARMV4_5_LDC(0, 1, 0, 1, 14, 5, 0, 4), dscr);
+       if (retval != ERROR_OK)
+               return retval;
+
+       count--;
+
+       if (count > 0) {
+               /* Switch to fast mode if not already in that mode. */
+               retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_FAST_MODE, dscr);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               /* Latch LDC instruction. */
+               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;
-               *dscr = new_dscr;
 
                /* Read the value transferred to DTRTX into the buffer. Due to fast
                 * mode rules, this blocks until the instruction finishes executing and
@@ -2461,27 +2486,22 @@ 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, buffer,
-                               4, count - 1, armv7a->debug_base + CPUDBG_DTRTX);
+               retval = mem_ap_read_buf_noincr(armv7a->debug_ap, buffer,
+                               4, count, armv7a->debug_base + CPUDBG_DTRTX);
                if (retval != ERROR_OK)
                        return retval;
 
                /* Advance. */
-               buffer += (count - 1) * 4;
-       } else {
-               /* Issue the LDC instruction via a write to ITR. */
-               retval = cortex_a_exec_opcode(target, ARMV4_5_LDC(0, 1, 0, 1, 14, 5, 0, 4), dscr);
-               if (retval != ERROR_OK)
-                       return retval;
+               buffer += count * 4;
        }
 
-       /* Switch to non-blocking mode if not already in that mode. */
-       retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_NON_BLOCKING, dscr);
+       /* Wait for last issued instruction to complete. */
+       retval = cortex_a_wait_instrcmpl(target, dscr, false);
        if (retval != ERROR_OK)
                return retval;
 
-       /* Wait for last issued instruction to complete. */
-       retval = cortex_a_wait_instrcmpl(target, dscr, false);
+       /* 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)
                return retval;
 
@@ -2500,7 +2520,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,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DTRTX, &u32);
        if (retval != ERROR_OK)
                return retval;
@@ -2516,7 +2536,6 @@ static int cortex_a_read_apb_ab_memory(struct target *target,
        /* Read memory through APB-AP. */
        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;
 
@@ -2531,13 +2550,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,
+       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,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
        if (retval != ERROR_OK)
                return retval;
@@ -2556,7 +2575,7 @@ static int cortex_a_read_apb_ab_memory(struct target *target,
                goto out;
 
        /* Get the memory address into R0. */
-       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap,
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DTRRX, address);
        if (retval != ERROR_OK)
                goto out;
@@ -2588,7 +2607,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,
+               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 {
@@ -2622,7 +2641,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,
+               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DTRTX, &dummy);
                if (final_retval == ERROR_OK)
                        final_retval = retval;
@@ -2649,7 +2668,6 @@ static int cortex_a_read_phys_memory(struct target *target,
        uint32_t address, uint32_t size,
        uint32_t count, uint8_t *buffer)
 {
-       struct armv7a_common *armv7a = target_to_armv7a(target);
        int retval = ERROR_COMMAND_SYNTAX_ERROR;
 
        LOG_DEBUG("Reading memory at real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32,
@@ -2657,13 +2675,9 @@ static int cortex_a_read_phys_memory(struct target *target,
 
        if (count && buffer) {
                /* read memory through APB-AP */
-               if (!armv7a->is_armv7r) {
-                       /*  disable mmu */
-                       retval = cortex_a_mmu_modify(target, 0);
-                       if (retval != ERROR_OK)
-                               return retval;
-               }
+               cortex_a_prep_memaccess(target, 1);
                retval = cortex_a_read_apb_ab_memory(target, address, size, count, buffer);
+               cortex_a_post_memaccess(target, 1);
        }
        return retval;
 }
@@ -2671,31 +2685,15 @@ static int cortex_a_read_phys_memory(struct target *target,
 static int cortex_a_read_memory(struct target *target, uint32_t address,
        uint32_t size, uint32_t count, uint8_t *buffer)
 {
-       int mmu_enabled = 0;
        int retval;
-       struct armv7a_common *armv7a = target_to_armv7a(target);
 
        /* 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) {
-               retval = cortex_a_check_address(target, address);
-               if (retval != ERROR_OK)
-                       return retval;
-               /* enable MMU as we could have disabled it for phys access */
-               retval = cortex_a_mmu_modify(target, 1);
-               if (retval != ERROR_OK)
-                       return retval;
-       }
+       cortex_a_prep_memaccess(target, 0);
        retval = cortex_a_read_apb_ab_memory(target, address, size, count, buffer);
+       cortex_a_post_memaccess(target, 0);
 
        return retval;
 }
@@ -2710,7 +2708,7 @@ static int cortex_a_read_memory_ahb(struct target *target, uint32_t address,
        struct adiv5_dap *swjdp = armv7a->arm.dap;
        uint8_t apsel = swjdp->apsel;
 
-       if (!armv7a->memory_ap_available || (apsel != armv7a->memory_ap))
+       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 */
@@ -2738,7 +2736,7 @@ static int cortex_a_read_memory_ahb(struct target *target, uint32_t address,
        if (!count || !buffer)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       retval = mem_ap_sel_read_buf(swjdp, armv7a->memory_ap, buffer, size, count, address);
+       retval = mem_ap_read_buf(armv7a->memory_ap, buffer, size, count, address);
 
        return retval;
 }
@@ -2747,7 +2745,6 @@ static int cortex_a_write_phys_memory(struct target *target,
        uint32_t address, uint32_t size,
        uint32_t count, const uint8_t *buffer)
 {
-       struct armv7a_common *armv7a = target_to_armv7a(target);
        int retval = ERROR_COMMAND_SYNTAX_ERROR;
 
        LOG_DEBUG("Writing memory to real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address,
@@ -2755,12 +2752,9 @@ static int cortex_a_write_phys_memory(struct target *target,
 
        if (count && buffer) {
                /* write memory through APB-AP */
-               if (!armv7a->is_armv7r) {
-                       retval = cortex_a_mmu_modify(target, 0);
-                       if (retval != ERROR_OK)
-                               return retval;
-               }
-               return cortex_a_write_apb_ab_memory(target, address, size, count, buffer);
+               cortex_a_prep_memaccess(target, 1);
+               retval = cortex_a_write_apb_ab_memory(target, address, size, count, buffer);
+               cortex_a_post_memaccess(target, 1);
        }
 
        return retval;
@@ -2769,36 +2763,18 @@ static int cortex_a_write_phys_memory(struct target *target,
 static int cortex_a_write_memory(struct target *target, uint32_t address,
        uint32_t size, uint32_t count, const uint8_t *buffer)
 {
-       int mmu_enabled = 0;
        int retval;
-       struct armv7a_common *armv7a = target_to_armv7a(target);
 
        /* 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) {
-               retval = cortex_a_check_address(target, address);
-               if (retval != ERROR_OK)
-                       return retval;
-               /* enable MMU as we could have disabled it for phys access */
-               retval = cortex_a_mmu_modify(target, 1);
-               if (retval != ERROR_OK)
-                       return retval;
-       }
-
        /* 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);
-
+       cortex_a_post_memaccess(target, 0);
        return retval;
 }
 
@@ -2812,7 +2788,7 @@ static int cortex_a_write_memory_ahb(struct target *target, uint32_t address,
        struct adiv5_dap *swjdp = armv7a->arm.dap;
        uint8_t apsel = swjdp->apsel;
 
-       if (!armv7a->memory_ap_available || (apsel != armv7a->memory_ap))
+       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 */
@@ -2841,7 +2817,7 @@ static int cortex_a_write_memory_ahb(struct target *target, uint32_t address,
        if (!count || !buffer)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       retval = mem_ap_sel_write_buf(swjdp, armv7a->memory_ap, buffer, size, count, address);
+       retval = mem_ap_write_buf(armv7a->memory_ap, buffer, size, count, address);
 
        return retval;
 }
@@ -2918,7 +2894,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))
@@ -2929,18 +2904,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,
+               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,
+                       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,
+                               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;
+                       }
                }
        }
 
@@ -2960,12 +2940,11 @@ static int cortex_a_examine_first(struct target *target)
        int retval = ERROR_OK;
        uint32_t didr, ctypr, ttypr, cpuid, dbg_osreg;
 
-       /* We do one extra read to ensure DAP is configured,
-        * we call ahbap_debugport_init(swjdp) instead
-        */
-       retval = ahbap_debugport_init(swjdp);
-       if (retval != ERROR_OK)
+       retval = dap_dp_init(swjdp);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Could not initialize the debug port");
                return retval;
+       }
 
        /* 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);
@@ -2973,17 +2952,31 @@ static int cortex_a_examine_first(struct target *target)
                LOG_ERROR("Could not find APB-AP for debug access");
                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) {
+               LOG_ERROR("Could not initialize the APB-AP");
+               return retval;
+       }
+
+       armv7a->debug_ap->memaccess_tck = 80;
+
+       /* Search for the AHB-AB.
+        * REVISIT: We should search for AXI-AP as well and make sure the AP's MEMTYPE says it
+        * can access system memory. */
+       armv7a->memory_ap_available = false;
+       retval = dap_find_ap(swjdp, AP_TYPE_AHB_AP, &armv7a->memory_ap);
+       if (retval == ERROR_OK) {
+               retval = mem_ap_init(armv7a->memory_ap);
+               if (retval == ERROR_OK)
+                       armv7a->memory_ap_available = true;
+               else
+                       LOG_WARNING("Could not initialize AHB-AP for memory access - using APB-AP");
+       } else {
                /* AHB-AP not found - use APB-AP */
                LOG_DEBUG("Could not find AHB-AP - using APB-AP for memory access");
-               armv7a->memory_ap_available = false;
-       } else {
-               armv7a->memory_ap_available = true;
        }
 
-
        if (!target->dbgbase_set) {
                uint32_t dbgbase;
                /* Get ROM Table base */
@@ -2991,11 +2984,11 @@ static int cortex_a_examine_first(struct target *target)
                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, 1, &dbgbase, &apid);
+               retval = dap_get_debugbase(armv7a->debug_ap, &dbgbase, &apid);
                if (retval != ERROR_OK)
                        return retval;
                /* Lookup 0x15 -- Processor DAP */
-               retval = dap_lookup_cs_component(swjdp, 1, dbgbase, 0x15,
+               retval = dap_lookup_cs_component(armv7a->debug_ap, dbgbase, 0x15,
                                &armv7a->debug_base, &coreidx);
                if (retval != ERROR_OK) {
                        LOG_ERROR("Can't detect %s's dbgbase from the ROM table; you need to specify it explicitly.",
@@ -3003,37 +2996,37 @@ static int cortex_a_examine_first(struct target *target)
                        return retval;
                }
                LOG_DEBUG("Detected core %" PRId32 " dbgbase: %08" PRIx32,
-                         coreidx, armv7a->debug_base);
+                         target->coreid, armv7a->debug_base);
        } else
                armv7a->debug_base = target->dbgbase;
 
-       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_CPUID, &cpuid);
        if (retval != ERROR_OK)
                return retval;
 
-       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_CPUID, &cpuid);
        if (retval != ERROR_OK) {
                LOG_DEBUG("Examine %s failed", "CPUID");
                return retval;
        }
 
-       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_CTYPR, &ctypr);
        if (retval != ERROR_OK) {
                LOG_DEBUG("Examine %s failed", "CTYPR");
                return retval;
        }
 
-       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_TTYPR, &ttypr);
        if (retval != ERROR_OK) {
                LOG_DEBUG("Examine %s failed", "TTYPR");
                return retval;
        }
 
-       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DIDR, &didr);
        if (retval != ERROR_OK) {
                LOG_DEBUG("Examine %s failed", "DIDR");
@@ -3054,7 +3047,7 @@ static int cortex_a_examine_first(struct target *target)
        if ((cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> CORTEX_A_MIDR_PARTNUM_SHIFT ==
                CORTEX_A15_PARTNUM) {
 
-               retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap,
+               retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                                                     armv7a->debug_base + CPUDBG_OSLAR,
                                                     0);
 
@@ -3066,7 +3059,7 @@ static int cortex_a_examine_first(struct target *target)
        if ((cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> CORTEX_A_MIDR_PARTNUM_SHIFT ==
                CORTEX_A7_PARTNUM) {
 
-               retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap,
+               retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
                                                     armv7a->debug_base + CPUDBG_OSLAR,
                                                     0);
 
@@ -3074,7 +3067,7 @@ static int cortex_a_examine_first(struct target *target)
                        return retval;
 
        }
-       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                            armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg);
 
        if (retval != ERROR_OK)
@@ -3111,6 +3104,9 @@ static int cortex_a_examine_first(struct target *target)
 
        LOG_DEBUG("Configured %i hw breakpoints", cortex_a->brp_num);
 
+       /* select debug_ap as default */
+       swjdp->apsel = armv7a->debug_ap->ap_num;
+
        target_set_examined(target);
        return ERROR_OK;
 }
@@ -3144,30 +3140,19 @@ static int cortex_a_init_arch_info(struct target *target,
        struct cortex_a_common *cortex_a, struct jtag_tap *tap)
 {
        struct armv7a_common *armv7a = &cortex_a->armv7a_common;
-       struct adiv5_dap *dap = &armv7a->dap;
-
-       armv7a->arm.dap = dap;
 
        /* Setup struct cortex_a_common */
        cortex_a->common_magic = CORTEX_A_COMMON_MAGIC;
+
        /*  tap has no dap initialized */
        if (!tap->dap) {
-               armv7a->arm.dap = dap;
-               /* Setup struct cortex_a_common */
-
-               /* prepare JTAG information for the new target */
-               cortex_a->jtag_info.tap = tap;
-               cortex_a->jtag_info.scann_size = 4;
+               tap->dap = dap_init();
 
                /* Leave (only) generic DAP stuff for debugport_init() */
-               dap->jtag_info = &cortex_a->jtag_info;
+               tap->dap->tap = tap;
+       }
 
-               /* Number of bits for tar autoincrement, impl. dep. at least 10 */
-               dap->tar_autoincr_block = (1 << 10);
-               dap->memaccess_tck = 80;
-               tap->dap = dap;
-       } else
-               armv7a->arm.dap = tap->dap;
+       armv7a->arm.dap = tap->dap;
 
        cortex_a->fast_reg_read = 0;
 
@@ -3221,12 +3206,18 @@ static void cortex_a_deinit_target(struct target *target)
 
 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;
        }
 
-       *enabled = target_to_cortex_a(target)->armv7a_common.armv7a_mmu.mmu_enabled;
+       if (armv7a->is_armv7r)
+               *enabled = 0;
+       else
+               *enabled = target_to_cortex_a(target)->armv7a_common.armv7a_mmu.mmu_enabled;
+
        return ERROR_OK;
 }
 
@@ -3237,7 +3228,7 @@ static int cortex_a_virt2phys(struct target *target,
        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)) {
+       if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap->ap_num)) {
                uint32_t ret;
                retval = armv7a_mmu_translate_va(target,
                                virt, &ret);
@@ -3364,6 +3355,32 @@ COMMAND_HANDLER(handle_cortex_a_mask_interrupts_command)
        return ERROR_OK;
 }
 
+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[] = {
+               { .name = "off", .value = CORTEX_A_DACRFIXUP_OFF },
+               { .name = "on", .value = CORTEX_A_DACRFIXUP_ON },
+               { .name = NULL, .value = -1 },
+       };
+       const Jim_Nvp *n;
+
+       if (CMD_ARGC > 0) {
+               n = Jim_Nvp_name2value_simple(nvp_dacrfixup_modes, CMD_ARGV[0]);
+               if (n->name == NULL)
+                       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);
+
+       return ERROR_OK;
+}
+
 static const struct command_registration cortex_a_exec_command_handlers[] = {
        {
                .name = "cache_info",
@@ -3405,7 +3422,14 @@ static const struct command_registration cortex_a_exec_command_handlers[] = {
                .help = "mask cortex_a interrupts",
                .usage = "['on'|'off']",
        },
-
+       {
+               .name = "dacrfixup",
+               .handler = handle_cortex_a_dacrfixup_command,
+               .mode = COMMAND_EXEC,
+               .help = "set domain access control (DACR) to all-manager "
+                       "on memory access",
+               .usage = "['on'|'off']",
+       },
 
        COMMAND_REGISTRATION_DONE
 };