Merge branch 'master' of ssh://dbrownell@openocd.git.sourceforge.net/gitroot/openocd...
[fw/openocd] / src / target / cortex_a8.c
index 829bf3dca32f45f980281007c8ffd687847fe334..846d90c343360367317ed2267c8e1ec42bd4c3f3 100644 (file)
@@ -67,6 +67,8 @@ int cortex_a8_dap_read_coreregister_u32(target_t *target,
                uint32_t *value, int regnum);
 int cortex_a8_dap_write_coreregister_u32(target_t *target,
                uint32_t value, int regnum);
+int cortex_a8_assert_reset(target_t *target);
+int cortex_a8_deassert_reset(target_t *target);
 
 target_type_t cortexa8_target =
 {
@@ -81,11 +83,10 @@ target_type_t cortexa8_target =
        .resume = cortex_a8_resume,
        .step = cortex_a8_step,
 
-       .assert_reset = NULL,
-       .deassert_reset = NULL,
+       .assert_reset = cortex_a8_assert_reset,
+       .deassert_reset = cortex_a8_deassert_reset,
        .soft_reset_halt = NULL,
 
-//     .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
        .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
 
        .read_memory = cortex_a8_read_memory,
@@ -121,40 +122,38 @@ target_type_t cortexa8_target =
  */
 int cortex_a8_init_debug_access(target_t *target)
 {
-#if 0
-# Unlocking the debug registers for modification
-mww 0x54011FB0 0xC5ACCE55 4
-
-# Clear Sticky Power Down status Bit to enable access to
-# the registers in the Core Power Domain
-mdw 0x54011314
-# Check that it is cleared
-mdw 0x54011314
-# Now we can read Core Debug Registers at offset 0x080
-mdw 0x54011080 4
-# We can also read RAM.
-mdw 0x80000000 32
-
-mdw 0x5401d030
-mdw 0x54011FB8
-
-# Set DBGEN line for hardware debug (OMAP35xx)
-mww 0x5401d030 0x00002000
-
-#Check AUTHSTATUS
-mdw 0x54011FB8
-
-# Instr enable
-mww 0x54011088 0x2000
-mdw 0x54011080 4
-#endif
-       return ERROR_OK;
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       armv7a_common_t *armv7a = armv4_5->arch_info;
+       swjdp_common_t *swjdp = &armv7a->swjdp_info;
+
+       int retval;
+       uint32_t dummy;
+
+       LOG_DEBUG(" ");
+
+       /* Unlocking the debug registers for modification */
+       /* The debugport might be uninitialised so try twice */
+       retval = mem_ap_write_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
+       if (retval != ERROR_OK)
+               mem_ap_write_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
+       /* Clear Sticky Power Down status Bit in PRSR to enable access to
+          the registers in the Core Power Domain */
+       retval = mem_ap_read_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_PRSR, &dummy);
+       /* Enabling of instruction execution in debug mode is done in debug_entry code */ 
+       
+       /* Resync breakpoint registers */
+       
+       /* Since this is likley called from init or reset, update targtet state information*/
+       cortex_a8_poll(target);
+       
+       return retval;
 }
 
 int cortex_a8_exec_opcode(target_t *target, uint32_t opcode)
 {
        uint32_t dscr;
-       int retvalue;
+       int retval;
        /* get pointers to arch-specific information */
        armv4_5_common_t *armv4_5 = target->arch_info;
        armv7a_common_t *armv7a = armv4_5->arch_info;
@@ -163,21 +162,31 @@ int cortex_a8_exec_opcode(target_t *target, uint32_t opcode)
        LOG_DEBUG("exec opcode 0x%08" PRIx32, opcode);
        do
        {
-               retvalue = mem_ap_read_atomic_u32(swjdp,
-                               OMAP3530_DEBUG_BASE + CPUDBG_DSCR, &dscr);
+               retval = mem_ap_read_atomic_u32(swjdp,
+                               armv7a->debug_base + CPUDBG_DSCR, &dscr);
+               if (retval != ERROR_OK)
+               {
+                       LOG_ERROR("Could not read DSCR register, opcode = 0x%08" PRIx32, opcode);
+                       return retval;
+               }
        }
-       while ((dscr & (1 << 24)) == 0); /* Wait for InstrCompl bit to be set */
+       while ((dscr & (1 << DSCR_INSTR_COMP)) == 0); /* Wait for InstrCompl bit to be set */
 
-       mem_ap_write_u32(swjdp, OMAP3530_DEBUG_BASE + CPUDBG_ITR, opcode);
+       mem_ap_write_u32(swjdp, armv7a->debug_base + CPUDBG_ITR, opcode);
 
        do
        {
-               retvalue = mem_ap_read_atomic_u32(swjdp,
-                               OMAP3530_DEBUG_BASE + CPUDBG_DSCR, &dscr);
+               retval = mem_ap_read_atomic_u32(swjdp,
+                               armv7a->debug_base + CPUDBG_DSCR, &dscr);
+               if (retval != ERROR_OK)
+               {
+                       LOG_ERROR("Could not read DSCR register");
+                       return retval;
+               }
        }
-       while ((dscr & (1 << 24)) == 0); /* Wait for InstrCompl bit to be set */
+       while ((dscr & (1 << DSCR_INSTR_COMP)) == 0); /* Wait for InstrCompl bit to be set */
 
-       return retvalue;
+       return retval;
 }
 
 /**************************************************************************
@@ -218,27 +227,40 @@ int cortex_a8_read_cp(target_t *target, uint32_t *value, uint8_t CP,
 
        /* Read DCCTX */
        retval = mem_ap_read_atomic_u32(swjdp,
-                       OMAP3530_DEBUG_BASE + CPUDBG_DTRTX, value);
+                       armv7a->debug_base + CPUDBG_DTRTX, value);
 
        return retval;
 }
 
 int cortex_a8_write_cp(target_t *target, uint32_t value,
        uint8_t CP, uint8_t op1, uint8_t CRn, uint8_t CRm, uint8_t op2)
-/* TODO Fix this */
 {
        int retval;
+       uint32_t dscr;
+
        /* get pointers to arch-specific information */
        armv4_5_common_t *armv4_5 = target->arch_info;
        armv7a_common_t *armv7a = armv4_5->arch_info;
        swjdp_common_t *swjdp = &armv7a->swjdp_info;
 
+       LOG_DEBUG("CP%i, CRn %i, value 0x%08" PRIx32, CP, CRn, value);
+
+       /* Check that DCCRX is not full */
+       retval = mem_ap_read_atomic_u32(swjdp,
+                               armv7a->debug_base + CPUDBG_DSCR, &dscr);
+       if (dscr & (1 << DSCR_DTR_RX_FULL))
+       {
+               LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr);
+               /* Clear DCCRX with MCR(p14, 0, Rd, c0, c5, 0), opcode  0xEE000E15 */
+               cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0));
+       }
+       
        retval = mem_ap_write_u32(swjdp,
-                       OMAP3530_DEBUG_BASE + CPUDBG_DTRRX, value);
+                       armv7a->debug_base + CPUDBG_DTRRX, value);
        /* Move DTRRX to r0 */
        cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0));
 
-       cortex_a8_exec_opcode(target, ARMV4_5_MCR(CP, 0, 0, 0, 5, 0));
+       cortex_a8_exec_opcode(target, ARMV4_5_MCR(CP, op1, 0, CRn, CRm, op2));
        return retval;
 }
 
@@ -289,12 +311,12 @@ int cortex_a8_dap_read_coreregister_u32(target_t *target,
        do
        {
                retval = mem_ap_read_atomic_u32(swjdp,
-                               OMAP3530_DEBUG_BASE + CPUDBG_DSCR, &dscr);
+                               armv7a->debug_base + CPUDBG_DSCR, &dscr);
        }
-       while ((dscr & (1 << 29)) == 0); /* Wait for DTRRXfull */
+       while ((dscr & (1 << DSCR_DTR_TX_FULL)) == 0); /* Wait for DTRRXfull */
 
        retval = mem_ap_read_atomic_u32(swjdp,
-                       OMAP3530_DEBUG_BASE + CPUDBG_DTRTX, value);
+                       armv7a->debug_base + CPUDBG_DTRTX, value);
 
        return retval;
 }
@@ -303,18 +325,31 @@ int cortex_a8_dap_write_coreregister_u32(target_t *target, uint32_t value, int r
 {
        int retval = ERROR_OK;
        uint8_t Rd = regnum&0xFF;
+       uint32_t dscr;
 
        /* get pointers to arch-specific information */
        armv4_5_common_t *armv4_5 = target->arch_info;
        armv7a_common_t *armv7a = armv4_5->arch_info;
        swjdp_common_t *swjdp = &armv7a->swjdp_info;
+       
+       LOG_DEBUG("register %i, value 0x%08" PRIx32, regnum, value);
 
+       /* Check that DCCRX is not full */
+       retval = mem_ap_read_atomic_u32(swjdp,
+                               armv7a->debug_base + CPUDBG_DSCR, &dscr);
+       if (dscr & (1 << DSCR_DTR_RX_FULL))
+       {
+               LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr);
+               /* Clear DCCRX with MCR(p14, 0, Rd, c0, c5, 0), opcode  0xEE000E15 */
+               cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0));
+       }
+       
        if (Rd > 16)
                return retval;
 
        /* Write to DCCRX */
        retval = mem_ap_write_u32(swjdp,
-                       OMAP3530_DEBUG_BASE + CPUDBG_DTRRX, value);
+                       armv7a->debug_base + CPUDBG_DTRRX, value);
 
        if (Rd < 15)
        {
@@ -337,6 +372,21 @@ int cortex_a8_dap_write_coreregister_u32(target_t *target, uint32_t value, int r
        return retval;
 }
 
+/* Write to memory mapped registers directly with no cache or mmu handling */
+int cortex_a8_dap_write_memap_register_u32(target_t *target, uint32_t address, uint32_t value)
+{
+       int retval;
+
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       armv7a_common_t *armv7a = armv4_5->arch_info;
+       swjdp_common_t *swjdp = &armv7a->swjdp_info;
+
+       retval = mem_ap_write_atomic_u32(swjdp, address, value);
+
+       return retval;
+}
+
 /*
  * Cortex-A8 Run control
  */
@@ -357,7 +407,7 @@ int cortex_a8_poll(target_t *target)
        uint8_t saved_apsel = dap_ap_get_select(swjdp);
        dap_ap_select(swjdp, swjdp_debugap);
        retval = mem_ap_read_atomic_u32(swjdp,
-                       OMAP3530_DEBUG_BASE + CPUDBG_DSCR, &dscr);
+                       armv7a->debug_base + CPUDBG_DSCR, &dscr);
        if (retval != ERROR_OK)
        {
                dap_ap_select(swjdp, saved_apsel);
@@ -428,15 +478,22 @@ int cortex_a8_halt(target_t *target)
         * and then wait for the core to be halted.
         */
        retval = mem_ap_write_atomic_u32(swjdp,
-                       OMAP3530_DEBUG_BASE + CPUDBG_DRCR, 0x1);
+                       armv7a->debug_base + CPUDBG_DRCR, 0x1);
+
+       /*
+        * enter halting debug mode
+        */
+       mem_ap_read_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_DSCR, &dscr);
+       retval = mem_ap_write_atomic_u32(swjdp,
+               armv7a->debug_base + CPUDBG_DSCR, dscr | (1 << DSCR_HALT_DBG_MODE));
 
        if (retval != ERROR_OK)
                goto out;
 
        do {
                mem_ap_read_atomic_u32(swjdp,
-                       OMAP3530_DEBUG_BASE + CPUDBG_DSCR, &dscr);
-       } while ((dscr & (1 << 0)) == 0);
+                       armv7a->debug_base + CPUDBG_DSCR, &dscr);
+       } while ((dscr & (1 << DSCR_CORE_HALTED)) == 0);
 
        target->debug_reason = DBG_REASON_DBGRQ;
 
@@ -451,7 +508,6 @@ int cortex_a8_resume(struct target_s *target, int current,
        /* get pointers to arch-specific information */
        armv4_5_common_t *armv4_5 = target->arch_info;
        armv7a_common_t *armv7a = armv4_5->arch_info;
-       cortex_a8_common_t *cortex_a8 = armv7a->arch_info;
        swjdp_common_t *swjdp = &armv7a->swjdp_info;
 
 //     breakpoint_t *breakpoint = NULL;
@@ -499,10 +555,17 @@ int cortex_a8_resume(struct target_s *target, int current,
        /* Make sure that the Armv7 gdb thumb fixups does not
         * kill the return address
         */
-       if (!(cortex_a8->cpudbg_dscr & (1 << 5)))
+       if (armv7a->core_state == ARMV7A_STATE_ARM)
        {
                resume_pc &= 0xFFFFFFFC;
        }
+       /* When the return address is loaded into PC
+        * bit 0 must be 1 to stay in Thumb state
+        */
+       if (armv7a->core_state == ARMV7A_STATE_THUMB)
+       {
+               resume_pc |= 0x1;
+       }
        LOG_DEBUG("resume pc = 0x%08" PRIx32, resume_pc);
        buf_set_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
                                armv4_5->core_mode, 15).value,
@@ -530,12 +593,12 @@ int cortex_a8_resume(struct target_s *target, int current,
 
 #endif
        /* Restart core and wait for it to be started */
-       mem_ap_write_atomic_u32(swjdp, OMAP3530_DEBUG_BASE + CPUDBG_DRCR, 0x2);
+       mem_ap_write_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_DRCR, 0x2);
 
        do {
                mem_ap_read_atomic_u32(swjdp,
-                       OMAP3530_DEBUG_BASE + CPUDBG_DSCR, &dscr);
-       } while ((dscr & (1 << 1)) == 0);
+                       armv7a->debug_base + CPUDBG_DSCR, &dscr);
+       } while ((dscr & (1 << DSCR_CORE_RESTARTED)) == 0);
 
        target->debug_reason = DBG_REASON_NOTHALTED;
        target->state = TARGET_RUNNING;
@@ -581,11 +644,10 @@ int cortex_a8_debug_entry(target_t *target)
 
        /* Enable the ITR execution once we are in debug mode */
        mem_ap_read_atomic_u32(swjdp,
-                               OMAP3530_DEBUG_BASE + CPUDBG_DSCR, &dscr);
-       dscr |= (1 << 13);
+                               armv7a->debug_base + CPUDBG_DSCR, &dscr);
+       dscr |= (1 << DSCR_EXT_INT_EN);
        retval = mem_ap_write_atomic_u32(swjdp,
-                       OMAP3530_DEBUG_BASE + CPUDBG_DSCR, dscr);
-
+                       armv7a->debug_base + CPUDBG_DSCR, dscr);
 
        /* Examine debug reason */
        switch ((cortex_a8->cpudbg_dscr >> 2)&0xF)
@@ -631,7 +693,8 @@ int cortex_a8_debug_entry(target_t *target)
        dap_ap_select(swjdp, swjdp_debugap);
        LOG_DEBUG("cpsr: %8.8" PRIx32, cpsr);
 
-       armv4_5->core_mode = cpsr & 0x3F;
+       armv4_5->core_mode = cpsr & 0x1F;
+       armv7a->core_state = (cpsr & 0x20)?ARMV7A_STATE_THUMB:ARMV7A_STATE_ARM;
 
        for (i = 0; i <= ARM_PC; i++)
        {
@@ -650,8 +713,7 @@ int cortex_a8_debug_entry(target_t *target)
        ARMV7A_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).dirty = 0;
 
        /* Fixup PC Resume Address */
-       /* TODO Her we should use arch->core_state */
-       if (cortex_a8->cpudbg_dscr & (1 << 5))
+       if (armv7a->core_state == ARMV7A_STATE_THUMB)
        {
                // T bit set for Thumb or ThumbEE state
                regfile[ARM_PC] -= 4;
@@ -736,7 +798,6 @@ int cortex_a8_step(struct target_s *target, int current, uint32_t address,
        /* get pointers to arch-specific information */
        armv4_5_common_t *armv4_5 = target->arch_info;
        armv7a_common_t *armv7a = armv4_5->arch_info;
-       cortex_a8_common_t *cortex_a8 = armv7a->arch_info;
        breakpoint_t *breakpoint = NULL;
        breakpoint_t stepbreakpoint;
 
@@ -778,7 +839,7 @@ int cortex_a8_step(struct target_s *target, int current, uint32_t address,
 
        /* Setup single step breakpoint */
        stepbreakpoint.address = address;
-       stepbreakpoint.length = (cortex_a8->cpudbg_dscr & (1 << 5)) ? 2 : 4;
+       stepbreakpoint.length = (armv7a->core_state == ARMV7A_STATE_THUMB) ? 2 : 4;
        stepbreakpoint.type = BKPT_HARD;
        stepbreakpoint.set = 0;
 
@@ -1016,10 +1077,10 @@ int cortex_a8_set_breakpoint(struct target_s *target,
                brp_list[brp_i].used = 1;
                brp_list[brp_i].value = (breakpoint->address & 0xFFFFFFFC);
                brp_list[brp_i].control = control;
-               target_write_u32(target, OMAP3530_DEBUG_BASE
+               cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
                                + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
                                brp_list[brp_i].value);
-               target_write_u32(target, OMAP3530_DEBUG_BASE
+               cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
                                + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
                                brp_list[brp_i].control);
                LOG_DEBUG("brp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
@@ -1082,10 +1143,10 @@ int cortex_a8_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint
                brp_list[brp_i].used = 0;
                brp_list[brp_i].value = 0;
                brp_list[brp_i].control = 0;
-               target_write_u32(target, OMAP3530_DEBUG_BASE
+               cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
                                + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
                                brp_list[brp_i].control);
-               target_write_u32(target, OMAP3530_DEBUG_BASE
+               cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
                                + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
                                brp_list[brp_i].value);
        }
@@ -1167,6 +1228,33 @@ int cortex_a8_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoin
  * Cortex-A8 Reset fuctions
  */
 
+int cortex_a8_assert_reset(target_t *target)
+{
+
+       LOG_DEBUG(" ");
+
+       /* registers are now invalid */
+       armv4_5_invalidate_core_regs(target);
+
+       target->state = TARGET_RESET;
+       
+       return ERROR_OK;
+}
+
+int cortex_a8_deassert_reset(target_t *target)
+{
+
+       LOG_DEBUG(" ");
+
+       if (target->reset_halt)
+       {
+               int retval;
+               if ((retval = target_halt(target)) != ERROR_OK)
+                       return retval;
+       }
+
+       return ERROR_OK;
+}
 
 /*
  * Cortex-A8 Memory access
@@ -1244,6 +1332,27 @@ int cortex_a8_write_memory(struct target_s *target, uint32_t address,
                        exit(-1);
        }
 
+       if (target->state == TARGET_HALTED)
+       {
+               /* The Cache handling will NOT work with MMU active, the wrong addresses will be invalidated */
+               /* invalidate I-Cache */
+               if (armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
+               {
+                       /* Invalidate ICache single entry with MVA, repeat this for all cache
+                          lines in the address range, Cortex-A8 has fixed 64 byte line length */
+                       /* Invalidate Cache single entry with MVA to PoU */
+                       for (uint32_t cacheline=address; cacheline<address+size*count; cacheline+=64)
+                               armv7a->write_cp15(target, 0, 1, 7, 5, cacheline); /* I-Cache to PoU */
+               }
+               /* invalidate D-Cache */
+               if (armv7a->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
+               {
+                       /* Invalidate Cache single entry with MVA to PoC */
+                       for (uint32_t cacheline=address; cacheline<address+size*count; cacheline+=64)
+                               armv7a->write_cp15(target, 0, 1, 7, 6, cacheline); /* U/D cache to PoC */
+               }
+       }
+
        return retval;
 }
 
@@ -1335,35 +1444,38 @@ int cortex_a8_examine(struct target_s *target)
        uint32_t didr, ctypr, ttypr, cpuid;
 
        LOG_DEBUG("TODO");
+       
+       /* Here we shall insert a proper ROM Table scan */
+       armv7a->debug_base = OMAP3530_DEBUG_BASE;
 
        /* We do one extra read to ensure DAP is configured,
         * we call ahbap_debugport_init(swjdp) instead
         */
        ahbap_debugport_init(swjdp);
-       mem_ap_read_atomic_u32(swjdp, OMAP3530_DEBUG_BASE + CPUDBG_CPUID, &cpuid);
+       mem_ap_read_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_CPUID, &cpuid);
        if ((retval = mem_ap_read_atomic_u32(swjdp,
-                       OMAP3530_DEBUG_BASE + CPUDBG_CPUID, &cpuid)) != ERROR_OK)
+                       armv7a->debug_base + CPUDBG_CPUID, &cpuid)) != ERROR_OK)
        {
                LOG_DEBUG("Examine failed");
                return retval;
        }
 
        if ((retval = mem_ap_read_atomic_u32(swjdp,
-                       OMAP3530_DEBUG_BASE + CPUDBG_CTYPR, &ctypr)) != ERROR_OK)
+                       armv7a->debug_base + CPUDBG_CTYPR, &ctypr)) != ERROR_OK)
        {
                LOG_DEBUG("Examine failed");
                return retval;
        }
 
        if ((retval = mem_ap_read_atomic_u32(swjdp,
-                       OMAP3530_DEBUG_BASE + CPUDBG_TTYPR, &ttypr)) != ERROR_OK)
+                       armv7a->debug_base + CPUDBG_TTYPR, &ttypr)) != ERROR_OK)
        {
                LOG_DEBUG("Examine failed");
                return retval;
        }
 
        if ((retval = mem_ap_read_atomic_u32(swjdp,
-                       OMAP3530_DEBUG_BASE + CPUDBG_DIDR, &didr)) != ERROR_OK)
+                       armv7a->debug_base + CPUDBG_DIDR, &didr)) != ERROR_OK)
        {
                LOG_DEBUG("Examine failed");
                return retval;
@@ -1407,6 +1519,9 @@ int cortex_a8_examine(struct target_s *target)
        LOG_DEBUG("Configured %i hw breakpoint pairs and %i hw watchpoint pairs",
                        cortex_a8->brp_num , cortex_a8->wrp_num);
 
+       /* Configure core debug access */
+       cortex_a8_init_debug_access(target);
+       
        target->type->examined = 1;
 
        return retval;
@@ -1525,6 +1640,17 @@ static int cortex_a8_handle_cache_info_command(struct command_context_s *cmd_ctx
 }
 
 
+static int cortex_a8_handle_dbginit_command(struct command_context_s *cmd_ctx,
+               char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+
+       cortex_a8_init_debug_access(target);
+
+       return ERROR_OK;
+}
+
+
 int cortex_a8_register_commands(struct command_context_s *cmd_ctx)
 {
        command_t *cortex_a8_cmd;
@@ -1541,5 +1667,9 @@ int cortex_a8_register_commands(struct command_context_s *cmd_ctx)
                        cortex_a8_handle_cache_info_command, COMMAND_EXEC,
                        "display information about target caches");
 
+       register_command(cmd_ctx, cortex_a8_cmd, "dbginit",
+                       cortex_a8_handle_dbginit_command, COMMAND_EXEC,
+                       "Initialize core debug");
+
        return retval;
 }