cortex_a: do not try to use MMU for translation if it wasn't enabled on target stop
[fw/openocd] / src / target / cortex_a.c
index cc1552d61a43c0889107cd1dc9669c4d04964f03..5e37e2a3323cd42c70d703c9f1f5b7390777a5b6 100644 (file)
@@ -17,6 +17,9 @@
  *   Copyright (C) ST-Ericsson SA 2011                                     *
  *   michel.jaouen@stericsson.com : smp minimum support                    *
  *                                                                         *
+ *   Copyright (C) Broadcom 2012                                           *
+ *   ehunter@broadcom.com : Cortex R4 support                              *
+ *                                                                         *
  *   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     *
  *   You should have received a copy of the GNU General Public License     *
  *   along with this program; if not, write to the                         *
  *   Free Software Foundation, Inc.,                                       *
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
  *                                                                         *
  *   Cortex-A8(tm) TRM, ARM DDI 0344H                                      *
  *   Cortex-A9(tm) TRM, ARM DDI 0407F                                      *
+ *   Cortex-A4(tm) TRM, ARM DDI 0363E                                      *
  *                                                                         *
  ***************************************************************************/
 
@@ -70,14 +74,6 @@ static int cortex_a8_virt2phys(struct target *target,
 static int cortex_a8_read_apb_ab_memory(struct target *target,
        uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
 
-/*
- * FIXME do topology discovery using the ROM; don't
- * assume this is an OMAP3.   Also, allow for multiple ARMv7-A
- * cores, with different AP numbering ... don't use a #define
- * for these numbers, use per-core armv7a state.
- */
-#define swjdp_memoryap 0
-#define swjdp_debugap 1
 
 /*  restore cp15_control_reg at resume */
 static int cortex_a8_restore_cp15_control_reg(struct target *target)
@@ -106,14 +102,14 @@ static int cortex_a8_check_address(struct target *target, uint32_t address)
        uint32_t os_border = armv7a->armv7a_mmu.os_border;
        if ((address < os_border) &&
                (armv7a->arm.core_mode == ARM_MODE_SVC)) {
-               LOG_ERROR("%x access in userspace and target in supervisor", address);
+               LOG_ERROR("%" PRIx32 " access in userspace and target in supervisor", address);
                return ERROR_FAIL;
        }
        if ((address >= os_border) &&
                (cortex_a8->curr_mode != ARM_MODE_SVC)) {
                dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC);
                cortex_a8->curr_mode = ARM_MODE_SVC;
-               LOG_INFO("%x access in kernel space and target not in supervisor",
+               LOG_INFO("%" PRIx32 " access in kernel space and target not in supervisor",
                        address);
                return ERROR_OK;
        }
@@ -178,11 +174,11 @@ static int cortex_a8_init_debug_access(struct target *target)
 
        /* Unlocking the debug registers for modification
         * The debugport might be uninitialised so try twice */
-       retval = mem_ap_sel_write_atomic_u32(swjdp, swjdp_debugap,
+       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
        if (retval != ERROR_OK) {
                /* try again */
-               retval = mem_ap_sel_write_atomic_u32(swjdp, swjdp_debugap,
+               retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
                if (retval == ERROR_OK)
                        LOG_USER(
@@ -192,7 +188,7 @@ static int cortex_a8_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, swjdp_debugap,
+       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_PRSR, &dummy);
        if (retval != ERROR_OK)
                return retval;
@@ -225,7 +221,7 @@ static int cortex_a8_exec_opcode(struct target *target,
        /* Wait for InstrCompl bit to be set */
        long long then = timeval_ms();
        while ((dscr & DSCR_INSTR_COMP) == 0) {
-               retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
+               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DSCR, &dscr);
                if (retval != ERROR_OK) {
                        LOG_ERROR("Could not read DSCR register, opcode = 0x%08" PRIx32, opcode);
@@ -237,14 +233,14 @@ static int cortex_a8_exec_opcode(struct target *target,
                }
        }
 
-       retval = mem_ap_sel_write_u32(swjdp, swjdp_debugap,
+       retval = mem_ap_sel_write_u32(swjdp, armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_ITR, opcode);
        if (retval != ERROR_OK)
                return retval;
 
        then = timeval_ms();
        do {
-               retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
+               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DSCR, &dscr);
                if (retval != ERROR_OK) {
                        LOG_ERROR("Could not read DSCR register");
@@ -283,8 +279,8 @@ static int cortex_a8_read_regs_through_mem(struct target *target, uint32_t addre
        if (retval != ERROR_OK)
                return retval;
 
-       retval = mem_ap_sel_read_buf_u32(swjdp, swjdp_memoryap,
-                       (uint8_t *)(&regfile[1]), 4*15, address);
+       retval = mem_ap_sel_read_buf(swjdp, armv7a->memory_ap,
+                       (uint8_t *)(&regfile[1]), 415, address);
 
        return retval;
 }
@@ -335,7 +331,7 @@ static int cortex_a8_dap_read_coreregister_u32(struct target *target,
        /* Wait for DTRRXfull then read DTRRTX */
        long long then = timeval_ms();
        while ((dscr & DSCR_DTR_TX_FULL) == 0) {
-               retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
+               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DSCR, &dscr);
                if (retval != ERROR_OK)
                        return retval;
@@ -345,7 +341,7 @@ static int cortex_a8_dap_read_coreregister_u32(struct target *target,
                }
        }
 
-       retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
+       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DTRTX, value);
        LOG_DEBUG("read DCC 0x%08" PRIx32, *value);
 
@@ -364,7 +360,7 @@ static int cortex_a8_dap_write_coreregister_u32(struct target *target,
        LOG_DEBUG("register %i, value 0x%08" PRIx32, regnum, value);
 
        /* Check that DCCRX is not full */
-       retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
+       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
        if (retval != ERROR_OK)
                return retval;
@@ -382,7 +378,7 @@ static int cortex_a8_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, swjdp_debugap,
+       retval = mem_ap_sel_write_u32(swjdp, armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DTRRX, value);
        if (retval != ERROR_OK)
                return retval;
@@ -440,7 +436,7 @@ static int cortex_a8_dap_write_memap_register_u32(struct target *target,
        struct armv7a_common *armv7a = target_to_armv7a(target);
        struct adiv5_dap *swjdp = armv7a->arm.dap;
 
-       retval = mem_ap_sel_write_atomic_u32(swjdp, swjdp_debugap, address, value);
+       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, address, value);
 
        return retval;
 }
@@ -465,7 +461,7 @@ static int cortex_a8_write_dcc(struct cortex_a8_common *a8, uint32_t data)
 {
        LOG_DEBUG("write DCC 0x%08" PRIx32, data);
        return mem_ap_sel_write_u32(a8->armv7a_common.arm.dap,
-                       swjdp_debugap, a8->armv7a_common.debug_base + CPUDBG_DTRRX, data);
+               a8->armv7a_common.debug_ap, a8->armv7a_common.debug_base + CPUDBG_DTRRX, data);
 }
 
 static int cortex_a8_read_dcc(struct cortex_a8_common *a8, uint32_t *data,
@@ -481,7 +477,7 @@ static int cortex_a8_read_dcc(struct cortex_a8_common *a8, uint32_t *data,
        /* Wait for DTRRXfull */
        long long then = timeval_ms();
        while ((dscr & DSCR_DTR_TX_FULL) == 0) {
-               retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
+               retval = mem_ap_sel_read_atomic_u32(swjdp, a8->armv7a_common.debug_ap,
                                a8->armv7a_common.debug_base + CPUDBG_DSCR,
                                &dscr);
                if (retval != ERROR_OK)
@@ -492,7 +488,7 @@ static int cortex_a8_read_dcc(struct cortex_a8_common *a8, uint32_t *data,
                }
        }
 
-       retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
+       retval = mem_ap_sel_read_atomic_u32(swjdp, a8->armv7a_common.debug_ap,
                        a8->armv7a_common.debug_base + CPUDBG_DTRTX, data);
        if (retval != ERROR_OK)
                return retval;
@@ -514,7 +510,7 @@ static int cortex_a8_dpm_prepare(struct arm_dpm *dpm)
        /* set up invariant:  INSTR_COMP is set after ever DPM operation */
        long long then = timeval_ms();
        for (;; ) {
-               retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
+               retval = mem_ap_sel_read_atomic_u32(swjdp, a8->armv7a_common.debug_ap,
                                a8->armv7a_common.debug_base + CPUDBG_DSCR,
                                &dscr);
                if (retval != ERROR_OK)
@@ -802,7 +798,7 @@ static int cortex_a8_poll(struct target *target)
                target_call_event_callbacks(target, TARGET_EVENT_HALTED);
                return retval;
        }
-       retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
+       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
        if (retval != ERROR_OK)
                return retval;
@@ -864,7 +860,7 @@ static int cortex_a8_halt(struct target *target)
         * 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, swjdp_debugap,
+       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DRCR, DRCR_HALT);
        if (retval != ERROR_OK)
                return retval;
@@ -872,19 +868,19 @@ static int cortex_a8_halt(struct target *target)
        /*
         * enter halting debug mode
         */
-       retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
+       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
        if (retval != ERROR_OK)
                return retval;
 
-       retval = mem_ap_sel_write_atomic_u32(swjdp, swjdp_debugap,
+       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, dscr | DSCR_HALT_DBG_MODE);
        if (retval != ERROR_OK)
                return retval;
 
        long long then = timeval_ms();
        for (;; ) {
-               retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
+               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DSCR, &dscr);
                if (retval != ERROR_OK)
                        return retval;
@@ -1010,7 +1006,7 @@ static int cortex_a8_internal_restart(struct target *target)
         * disable IRQs by default, with optional override...
         */
 
-       retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
+       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
        if (retval != ERROR_OK)
                return retval;
@@ -1018,12 +1014,12 @@ static int cortex_a8_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, swjdp_debugap,
+       retval = mem_ap_sel_write_atomic_u32(swjdp, 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, swjdp_debugap,
+       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DRCR, DRCR_RESTART |
                        DRCR_CLEAR_EXCEPTIONS);
        if (retval != ERROR_OK)
@@ -1031,7 +1027,7 @@ static int cortex_a8_internal_restart(struct target *target)
 
        long long then = timeval_ms();
        for (;; ) {
-               retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
+               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DSCR, &dscr);
                if (retval != ERROR_OK)
                        return retval;
@@ -1123,7 +1119,7 @@ static int cortex_a8_debug_entry(struct target *target)
        LOG_DEBUG("dscr = 0x%08" PRIx32, cortex_a8->cpudbg_dscr);
 
        /* REVISIT surely we should not re-read DSCR !! */
-       retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
+       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
        if (retval != ERROR_OK)
                return retval;
@@ -1135,7 +1131,7 @@ static int cortex_a8_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, swjdp_debugap,
+       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DSCR, dscr);
        if (retval != ERROR_OK)
                return retval;
@@ -1147,7 +1143,7 @@ static int cortex_a8_debug_entry(struct target *target)
        if (target->debug_reason == DBG_REASON_WATCHPOINT) {
                uint32_t wfar;
 
-               retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
+               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_WFAR,
                                &wfar);
                if (retval != ERROR_OK)
@@ -1248,8 +1244,12 @@ static int cortex_a8_post_debug_entry(struct target *target)
        if (armv7a->armv7a_mmu.armv7a_cache.ctype == -1)
                armv7a_identify_cache(target);
 
-       armv7a->armv7a_mmu.mmu_enabled =
-               (cortex_a8->cp15_control_reg & 0x1U) ? 1 : 0;
+       if (armv7a->is_armv7r) {
+               armv7a->armv7a_mmu.mmu_enabled = 0;
+       } else {
+               armv7a->armv7a_mmu.mmu_enabled =
+                       (cortex_a8->cp15_control_reg & 0x1U) ? 1 : 0;
+       }
        armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled =
                (cortex_a8->cp15_control_reg & 0x4U) ? 1 : 0;
        armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled =
@@ -1891,8 +1891,8 @@ static int cortex_a8_write_apb_ab_memory(struct target *target,
                goto error_unset_dtr_w;
 
        /* Do the write */
-       retval = mem_ap_sel_write_buf_u32_noincr(swjdp, armv7a->debug_ap,
-                                       tmp_buff, (total_u32)<<2, armv7a->debug_base + CPUDBG_DTRRX);
+       retval = mem_ap_sel_write_buf_noincr(swjdp, armv7a->debug_ap,
+                                       tmp_buff, 4, total_u32, armv7a->debug_base + CPUDBG_DTRRX);
        if (retval != ERROR_OK)
                goto error_unset_dtr_w;
 
@@ -1911,7 +1911,7 @@ static int cortex_a8_write_apb_ab_memory(struct target *target,
                goto error_free_buff_w;
        if (dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE)) {
                /* Abort occurred - clear it and exit */
-               LOG_ERROR("abort occurred - dscr = 0x%08x", dscr);
+               LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr);
                mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap,
                                        armv7a->debug_base + CPUDBG_DRCR, 1<<2);
                goto error_free_buff_w;
@@ -1949,7 +1949,7 @@ static int cortex_a8_read_apb_ab_memory(struct target *target,
        int start_byte = address & 0x3;
        struct reg *reg;
        uint32_t dscr;
-       char *tmp_buff = NULL;
+       uint32_t *tmp_buff;
        uint32_t buff32[2];
        if (target->state != TARGET_HALTED) {
                LOG_WARNING("target not halted");
@@ -1958,6 +1958,14 @@ static int cortex_a8_read_apb_ab_memory(struct target *target,
 
        total_u32 = DIV_ROUND_UP((address & 3) + total_bytes, 4);
 
+       /* Due to offset word alignment, the  buffer may not have space
+        * to read the full first and last int32 words,
+        * hence, malloc space to read into, then copy and align into the buffer.
+        */
+       tmp_buff = malloc(total_u32 * 4);
+       if (tmp_buff == NULL)
+               return ERROR_FAIL;
+
        /* Mark register R0 as dirty, as it will be used
         * for transferring the data.
         * It will be restored automatically when exiting
@@ -1970,7 +1978,7 @@ static int cortex_a8_read_apb_ab_memory(struct target *target,
        retval =
                mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DRCR, 1<<2);
        if (retval != ERROR_OK)
-               return retval;
+               goto error_free_buff_r;
 
        /* Read DSCR */
        retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
@@ -2003,18 +2011,12 @@ static int cortex_a8_read_apb_ab_memory(struct target *target,
        dscr = (dscr & ~DSCR_EXT_DCC_MASK) | DSCR_EXT_DCC_FAST_MODE;
        buff32[1] = dscr;
        /*  group the 2 access CPUDBG_ITR 0x84 and CPUDBG_DSCR 0x88 */
-       retval += mem_ap_sel_write_buf_u32(swjdp, armv7a->debug_ap, (uint8_t *)buff32, 8,
+       retval += mem_ap_sel_write_buf(swjdp, armv7a->debug_ap, (uint8_t *)buff32, 4, 2,
                        armv7a->debug_base + CPUDBG_ITR);
        if (retval != ERROR_OK)
                goto error_unset_dtr_r;
 
 
-       /* Due to offset word alignment, the  buffer may not have space
-        * to read the full first and last int32 words,
-        * hence, malloc space to read into, then copy and align into the buffer.
-        */
-       tmp_buff = (char *) malloc(total_u32<<2);
-
        /* The last word needs to be handled separately - read all other words in one go.
         */
        if (total_u32 > 1) {
@@ -2023,7 +2025,7 @@ static int cortex_a8_read_apb_ab_memory(struct target *target,
                 *
                 * This data is read in aligned to 32 bit boundary, hence may need shifting later.
                 */
-               retval = mem_ap_sel_read_buf_u32_noincr(swjdp, armv7a->debug_ap, (uint8_t *)tmp_buff, (total_u32-1)<<2,
+               retval = mem_ap_sel_read_buf_noincr(swjdp, armv7a->debug_ap, (uint8_t *)tmp_buff, 4, total_u32 - 1,
                                                                        armv7a->debug_base + CPUDBG_DTRTX);
                if (retval != ERROR_OK)
                        goto error_unset_dtr_r;
@@ -2052,7 +2054,7 @@ static int cortex_a8_read_apb_ab_memory(struct target *target,
                goto error_free_buff_r;
        if (dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE)) {
                /* Abort occurred - clear it and exit */
-               LOG_ERROR("abort occurred - dscr = 0x%08x", dscr);
+               LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr);
                mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap,
                                        armv7a->debug_base + CPUDBG_DRCR, 1<<2);
                goto error_free_buff_r;
@@ -2060,12 +2062,12 @@ static int cortex_a8_read_apb_ab_memory(struct target *target,
 
        /* Read the last word */
        retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
-                               armv7a->debug_base + CPUDBG_DTRTX, (uint32_t *)&tmp_buff[(total_u32-1)<<2]);
+                               armv7a->debug_base + CPUDBG_DTRTX, &tmp_buff[total_u32 - 1]);
        if (retval != ERROR_OK)
                goto error_free_buff_r;
 
        /* Copy and align the data into the output buffer */
-       memcpy(buffer, &tmp_buff[start_byte], total_bytes);
+       memcpy(buffer, (uint8_t *)tmp_buff + start_byte, total_bytes);
 
        free(tmp_buff);
 
@@ -2102,36 +2104,24 @@ static int cortex_a8_read_phys_memory(struct target *target,
        struct adiv5_dap *swjdp = armv7a->arm.dap;
        int retval = ERROR_COMMAND_SYNTAX_ERROR;
        uint8_t apsel = swjdp->apsel;
-       LOG_DEBUG("Reading memory at real address 0x%x; size %d; count %d",
+       LOG_DEBUG("Reading memory at real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32,
                address, size, count);
 
        if (count && buffer) {
 
-               if (apsel == swjdp_memoryap) {
+               if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) {
 
                        /* read memory through AHB-AP */
-
-                       switch (size) {
-                               case 4:
-                                       retval = mem_ap_sel_read_buf_u32(swjdp, swjdp_memoryap,
-                                               buffer, 4 * count, address);
-                                       break;
-                               case 2:
-                                       retval = mem_ap_sel_read_buf_u16(swjdp, swjdp_memoryap,
-                                               buffer, 2 * count, address);
-                                       break;
-                               case 1:
-                                       retval = mem_ap_sel_read_buf_u8(swjdp, swjdp_memoryap,
-                                               buffer, count, address);
-                                       break;
-                       }
+                       retval = mem_ap_sel_read_buf(swjdp, armv7a->memory_ap, buffer, size, count, address);
                } else {
 
-                       /* read memory through APB-AP
-                        *  disable mmu */
-                       retval = cortex_a8_mmu_modify(target, 0);
-                       if (retval != ERROR_OK)
-                               return retval;
+                       /* read memory through APB-AP */
+                       if (!armv7a->is_armv7r) {
+                               /*  disable mmu */
+                               retval = cortex_a8_mmu_modify(target, 0);
+                               if (retval != ERROR_OK)
+                                       return retval;
+                       }
                        retval = cortex_a8_read_apb_ab_memory(target, address, size, count, buffer);
                }
        }
@@ -2141,7 +2131,7 @@ static int cortex_a8_read_phys_memory(struct target *target,
 static int cortex_a8_read_memory(struct target *target, uint32_t address,
        uint32_t size, uint32_t count, uint8_t *buffer)
 {
-       int enabled = 0;
+       int mmu_enabled = 0;
        uint32_t virt, phys;
        int retval;
        struct armv7a_common *armv7a = target_to_armv7a(target);
@@ -2149,33 +2139,38 @@ static int cortex_a8_read_memory(struct target *target, uint32_t address,
        uint8_t apsel = swjdp->apsel;
 
        /* cortex_a8 handles unaligned memory access */
-       LOG_DEBUG("Reading memory at address 0x%x; size %d; count %d", address,
+       LOG_DEBUG("Reading memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address,
                size, count);
-       if (apsel == swjdp_memoryap) {
-               retval = cortex_a8_mmu(target, &enabled);
+
+       /* determine if MMU was enabled on target stop */
+       if (!armv7a->is_armv7r) {
+               retval = cortex_a8_mmu(target, &mmu_enabled);
                if (retval != ERROR_OK)
                        return retval;
+       }
 
-
-               if (enabled) {
+       if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) {
+               if (mmu_enabled) {
                        virt = address;
                        retval = cortex_a8_virt2phys(target, virt, &phys);
                        if (retval != ERROR_OK)
                                return retval;
 
-                       LOG_DEBUG("Reading at virtual address. Translating v:0x%x to r:0x%x",
-                               virt, phys);
+                       LOG_DEBUG("Reading at virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32,
+                                 virt, phys);
                        address = phys;
                }
                retval = cortex_a8_read_phys_memory(target, address, size, count, buffer);
        } else {
-               retval = cortex_a8_check_address(target, address);
-               if (retval != ERROR_OK)
-                       return retval;
-               /*  enable mmu */
-               retval = cortex_a8_mmu_modify(target, 1);
-               if (retval != ERROR_OK)
-                       return retval;
+               if (mmu_enabled) {
+                       retval = cortex_a8_check_address(target, address);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       /* enable MMU as we could have disabled it for phys access */
+                       retval = cortex_a8_mmu_modify(target, 1);
+                       if (retval != ERROR_OK)
+                               return retval;
+               }
                retval = cortex_a8_read_apb_ab_memory(target, address, size, count, buffer);
        }
        return retval;
@@ -2190,36 +2185,23 @@ static int cortex_a8_write_phys_memory(struct target *target,
        int retval = ERROR_COMMAND_SYNTAX_ERROR;
        uint8_t apsel = swjdp->apsel;
 
-       LOG_DEBUG("Writing memory to real address 0x%x; size %d; count %d", address,
+       LOG_DEBUG("Writing memory to real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address,
                size, count);
 
        if (count && buffer) {
 
-               if (apsel == swjdp_memoryap) {
+               if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) {
 
                        /* write memory through AHB-AP */
-
-                       switch (size) {
-                               case 4:
-                                       retval = mem_ap_sel_write_buf_u32(swjdp, swjdp_memoryap,
-                                               buffer, 4 * count, address);
-                                       break;
-                               case 2:
-                                       retval = mem_ap_sel_write_buf_u16(swjdp, swjdp_memoryap,
-                                               buffer, 2 * count, address);
-                                       break;
-                               case 1:
-                                       retval = mem_ap_sel_write_buf_u8(swjdp, swjdp_memoryap,
-                                               buffer, count, address);
-                                       break;
-                       }
-
+                       retval = mem_ap_sel_write_buf(swjdp, armv7a->memory_ap, buffer, size, count, address);
                } else {
 
                        /* write memory through APB-AP */
-                       retval = cortex_a8_mmu_modify(target, 0);
-                       if (retval != ERROR_OK)
-                               return retval;
+                       if (!armv7a->is_armv7r) {
+                               retval = cortex_a8_mmu_modify(target, 0);
+                               if (retval != ERROR_OK)
+                                       return retval;
+                       }
                        return cortex_a8_write_apb_ab_memory(target, address, size, count, buffer);
                }
        }
@@ -2285,55 +2267,55 @@ static int cortex_a8_write_phys_memory(struct target *target,
 static int cortex_a8_write_memory(struct target *target, uint32_t address,
        uint32_t size, uint32_t count, const uint8_t *buffer)
 {
-       int enabled = 0;
+       int mmu_enabled = 0;
        uint32_t virt, phys;
        int retval;
        struct armv7a_common *armv7a = target_to_armv7a(target);
        struct adiv5_dap *swjdp = armv7a->arm.dap;
        uint8_t apsel = swjdp->apsel;
+
        /* cortex_a8 handles unaligned memory access */
-       LOG_DEBUG("Reading memory at address 0x%x; size %d; count %d", address,
+       LOG_DEBUG("Writing memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address,
                size, count);
-       if (apsel == swjdp_memoryap) {
 
-               LOG_DEBUG("Writing memory to address 0x%x; size %d; count %d", address, size,
-                       count);
-               retval = cortex_a8_mmu(target, &enabled);
+       /* determine if MMU was enabled on target stop */
+       if (!armv7a->is_armv7r) {
+               retval = cortex_a8_mmu(target, &mmu_enabled);
                if (retval != ERROR_OK)
                        return retval;
+       }
 
-               if (enabled) {
+       if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) {
+               LOG_DEBUG("Writing memory to address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, size,
+                       count);
+               if (mmu_enabled) {
                        virt = address;
                        retval = cortex_a8_virt2phys(target, virt, &phys);
                        if (retval != ERROR_OK)
                                return retval;
-                       LOG_DEBUG("Writing to virtual address. Translating v:0x%x to r:0x%x",
-                               virt,
-                               phys);
+
+                       LOG_DEBUG("Writing to virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32,
+                                 virt,
+                                 phys);
                        address = phys;
                }
-
                retval = cortex_a8_write_phys_memory(target, address, size,
                                count, buffer);
        } else {
-               retval = cortex_a8_check_address(target, address);
-               if (retval != ERROR_OK)
-                       return retval;
-               /*  enable mmu  */
-               retval = cortex_a8_mmu_modify(target, 1);
-               if (retval != ERROR_OK)
-                       return retval;
+               if (mmu_enabled) {
+                       retval = cortex_a8_check_address(target, address);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       /* enable MMU as we could have disabled it for phys access */
+                       retval = cortex_a8_mmu_modify(target, 1);
+                       if (retval != ERROR_OK)
+                               return retval;
+               }
                retval = cortex_a8_write_apb_ab_memory(target, address, size, count, buffer);
        }
        return retval;
 }
 
-static int cortex_a8_bulk_write_memory(struct target *target, uint32_t address,
-       uint32_t count, const uint8_t *buffer)
-{
-       return cortex_a8_write_memory(target, address, 4, count, buffer);
-}
-
 static int cortex_a8_handle_target_request(void *priv)
 {
        struct target *target = priv;
@@ -2349,16 +2331,16 @@ static int cortex_a8_handle_target_request(void *priv)
        if (target->state == TARGET_RUNNING) {
                uint32_t request;
                uint32_t dscr;
-               retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
+               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DSCR, &dscr);
 
                /* check if we have data */
                while ((dscr & DSCR_DTR_TX_FULL) && (retval == ERROR_OK)) {
-                       retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
+                       retval = mem_ap_sel_read_atomic_u32(swjdp, 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, swjdp_debugap,
+                               retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
                                                armv7a->debug_base + CPUDBG_DSCR, &dscr);
                        }
                }
@@ -2387,6 +2369,23 @@ static int cortex_a8_examine_first(struct target *target)
        if (retval != ERROR_OK)
                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);
+       if (retval != ERROR_OK) {
+               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);
+       if (retval != ERROR_OK) {
+               /* AHB-AP not found - use APB-AP */
+               LOG_DEBUG("Could not find AHB-AP - using APB-AP for memory access");
+               armv7a->memory_ap_available = false;
+       } else {
+               armv7a->memory_ap_available = true;
+       }
+
+
        if (!target->dbgbase_set) {
                uint32_t dbgbase;
                /* Get ROM Table base */
@@ -2402,33 +2401,33 @@ static int cortex_a8_examine_first(struct target *target)
        } else
                armv7a->debug_base = target->dbgbase;
 
-       retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
+       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_CPUID, &cpuid);
        if (retval != ERROR_OK)
                return retval;
 
-       retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
+       retval = mem_ap_sel_read_atomic_u32(swjdp, 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, swjdp_debugap,
+       retval = mem_ap_sel_read_atomic_u32(swjdp, 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, swjdp_debugap,
+       retval = mem_ap_sel_read_atomic_u32(swjdp, 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, swjdp_debugap,
+       retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DIDR, &didr);
        if (retval != ERROR_OK) {
                LOG_DEBUG("Examine %s failed", "DIDR");
@@ -2548,9 +2547,19 @@ static int cortex_a8_target_create(struct target *target, Jim_Interp *interp)
 {
        struct cortex_a8_common *cortex_a8 = calloc(1, sizeof(struct cortex_a8_common));
 
+       cortex_a8->armv7a_common.is_armv7r = false;
+
        return cortex_a8_init_arch_info(target, cortex_a8, target->tap);
 }
 
+static int cortex_r4_target_create(struct target *target, Jim_Interp *interp)
+{
+       struct cortex_a8_common *cortex_a8 = calloc(1, sizeof(struct cortex_a8_common));
+
+       cortex_a8->armv7a_common.is_armv7r = true;
+
+       return cortex_a8_init_arch_info(target, cortex_a8, target->tap);
+}
 
 
 static int cortex_a8_mmu(struct target *target, int *enabled)
@@ -2571,14 +2580,14 @@ static int cortex_a8_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 (apsel == swjdp_memoryap) {
+       if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) {
                uint32_t ret;
                retval = armv7a_mmu_translate_va(target,
                                virt, &ret);
                if (retval != ERROR_OK)
                        goto done;
                *phys = ret;
-       } else {/*  use this method if swjdp_memoryap not selected
+       } else {/*  use this method if armv7a->memory_ap not selected
                 *  mmu must be enable in order to get a correct translation */
                retval = cortex_a8_mmu_modify(target, 1);
                if (retval != ERROR_OK)
@@ -2661,7 +2670,7 @@ COMMAND_HANDLER(cortex_a8_handle_smp_gdb_command)
                        target->gdb_service->core[1] = coreid;
 
                }
-               command_print(CMD_CTX, "gdb coreid  %d -> %d", target->gdb_service->core[0]
+               command_print(CMD_CTX, "gdb coreid  %" PRId32 " -> %" PRId32, target->gdb_service->core[0]
                        , target->gdb_service->core[1]);
        }
        return ERROR_OK;
@@ -2713,9 +2722,9 @@ static const struct command_registration cortex_a8_command_handlers[] = {
                .chain = armv7a_command_handlers,
        },
        {
-               .name = "cortex_a8",
+               .name = "cortex_a",
                .mode = COMMAND_ANY,
-               .help = "Cortex-A8 command group",
+               .help = "Cortex-A command group",
                .usage = "",
                .chain = cortex_a8_exec_command_handlers,
        },
@@ -2723,27 +2732,24 @@ static const struct command_registration cortex_a8_command_handlers[] = {
 };
 
 struct target_type cortexa8_target = {
-       .name = "cortex_a8",
+       .name = "cortex_a",
+       .deprecated_name = "cortex_a8",
 
        .poll = cortex_a8_poll,
        .arch_state = armv7a_arch_state,
 
-       .target_request_data = NULL,
-
        .halt = cortex_a8_halt,
        .resume = cortex_a8_resume,
        .step = cortex_a8_step,
 
        .assert_reset = cortex_a8_assert_reset,
        .deassert_reset = cortex_a8_deassert_reset,
-       .soft_reset_halt = NULL,
 
        /* REVISIT allow exporting VFP3 registers ... */
        .get_gdb_reg_list = arm_get_gdb_reg_list,
 
        .read_memory = cortex_a8_read_memory,
        .write_memory = cortex_a8_write_memory,
-       .bulk_write_memory = cortex_a8_bulk_write_memory,
 
        .checksum_memory = arm_checksum_memory,
        .blank_check_memory = arm_blank_check_memory,
@@ -2767,3 +2773,75 @@ struct target_type cortexa8_target = {
        .mmu = cortex_a8_mmu,
        .virt2phys = cortex_a8_virt2phys,
 };
+
+static const struct command_registration cortex_r4_exec_command_handlers[] = {
+       {
+               .name = "cache_info",
+               .handler = cortex_a8_handle_cache_info_command,
+               .mode = COMMAND_EXEC,
+               .help = "display information about target caches",
+               .usage = "",
+       },
+       {
+               .name = "dbginit",
+               .handler = cortex_a8_handle_dbginit_command,
+               .mode = COMMAND_EXEC,
+               .help = "Initialize core debug",
+               .usage = "",
+       },
+
+       COMMAND_REGISTRATION_DONE
+};
+static const struct command_registration cortex_r4_command_handlers[] = {
+       {
+               .chain = arm_command_handlers,
+       },
+       {
+               .chain = armv7a_command_handlers,
+       },
+       {
+               .name = "cortex_r4",
+               .mode = COMMAND_ANY,
+               .help = "Cortex-R4 command group",
+               .usage = "",
+               .chain = cortex_r4_exec_command_handlers,
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+struct target_type cortexr4_target = {
+       .name = "cortex_r4",
+
+       .poll = cortex_a8_poll,
+       .arch_state = armv7a_arch_state,
+
+       .halt = cortex_a8_halt,
+       .resume = cortex_a8_resume,
+       .step = cortex_a8_step,
+
+       .assert_reset = cortex_a8_assert_reset,
+       .deassert_reset = cortex_a8_deassert_reset,
+
+       /* REVISIT allow exporting VFP3 registers ... */
+       .get_gdb_reg_list = arm_get_gdb_reg_list,
+
+       .read_memory = cortex_a8_read_memory,
+       .write_memory = cortex_a8_write_memory,
+
+       .checksum_memory = arm_checksum_memory,
+       .blank_check_memory = arm_blank_check_memory,
+
+       .run_algorithm = armv4_5_run_algorithm,
+
+       .add_breakpoint = cortex_a8_add_breakpoint,
+       .add_context_breakpoint = cortex_a8_add_context_breakpoint,
+       .add_hybrid_breakpoint = cortex_a8_add_hybrid_breakpoint,
+       .remove_breakpoint = cortex_a8_remove_breakpoint,
+       .add_watchpoint = NULL,
+       .remove_watchpoint = NULL,
+
+       .commands = cortex_r4_command_handlers,
+       .target_create = cortex_r4_target_create,
+       .init_target = cortex_a8_init_target,
+       .examine = cortex_a8_examine,
+};