+static int cortex_a8_dpm_finish(struct arm_dpm *dpm)
+{
+ /* REVISIT what could be done here? */
+ return ERROR_OK;
+}
+
+static int cortex_a8_instr_write_data_dcc(struct arm_dpm *dpm,
+ uint32_t opcode, uint32_t data)
+{
+ struct cortex_a8_common *a8 = dpm_to_a8(dpm);
+ int retval;
+ uint32_t dscr = DSCR_INSTR_COMP;
+
+ retval = cortex_a8_write_dcc(a8, data);
+
+ return cortex_a8_exec_opcode(
+ a8->armv7a_common.armv4_5_common.target,
+ opcode,
+ &dscr);
+}
+
+static int cortex_a8_instr_write_data_r0(struct arm_dpm *dpm,
+ uint32_t opcode, uint32_t data)
+{
+ struct cortex_a8_common *a8 = dpm_to_a8(dpm);
+ uint32_t dscr = DSCR_INSTR_COMP;
+ int retval;
+
+ retval = cortex_a8_write_dcc(a8, data);
+
+ /* DCCRX to R0, "MCR p14, 0, R0, c0, c5, 0", 0xEE000E15 */
+ retval = cortex_a8_exec_opcode(
+ a8->armv7a_common.armv4_5_common.target,
+ ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
+ &dscr);
+
+ /* then the opcode, taking data from R0 */
+ retval = cortex_a8_exec_opcode(
+ a8->armv7a_common.armv4_5_common.target,
+ opcode,
+ &dscr);
+
+ return retval;
+}
+
+static int cortex_a8_instr_cpsr_sync(struct arm_dpm *dpm)
+{
+ struct target *target = dpm->arm->target;
+ uint32_t dscr = DSCR_INSTR_COMP;
+
+ /* "Prefetch flush" after modifying execution status in CPSR */
+ return cortex_a8_exec_opcode(target,
+ ARMV4_5_MCR(15, 0, 0, 7, 5, 4),
+ &dscr);
+}
+
+static int cortex_a8_instr_read_data_dcc(struct arm_dpm *dpm,
+ uint32_t opcode, uint32_t *data)
+{
+ struct cortex_a8_common *a8 = dpm_to_a8(dpm);
+ int retval;
+ uint32_t dscr = DSCR_INSTR_COMP;
+
+ /* the opcode, writing data to DCC */
+ retval = cortex_a8_exec_opcode(
+ a8->armv7a_common.armv4_5_common.target,
+ opcode,
+ &dscr);
+
+ return cortex_a8_read_dcc(a8, data, &dscr);
+}
+
+
+static int cortex_a8_instr_read_data_r0(struct arm_dpm *dpm,
+ uint32_t opcode, uint32_t *data)
+{
+ struct cortex_a8_common *a8 = dpm_to_a8(dpm);
+ uint32_t dscr = DSCR_INSTR_COMP;
+ int retval;
+
+ /* the opcode, writing data to R0 */
+ retval = cortex_a8_exec_opcode(
+ a8->armv7a_common.armv4_5_common.target,
+ opcode,
+ &dscr);
+
+ /* write R0 to DCC */
+ retval = cortex_a8_exec_opcode(
+ a8->armv7a_common.armv4_5_common.target,
+ ARMV4_5_MCR(14, 0, 0, 0, 5, 0),
+ &dscr);
+
+ return cortex_a8_read_dcc(a8, data, &dscr);
+}
+
+static int cortex_a8_bpwp_enable(struct arm_dpm *dpm, unsigned index_t,
+ uint32_t addr, uint32_t control)
+{
+ struct cortex_a8_common *a8 = dpm_to_a8(dpm);
+ uint32_t vr = a8->armv7a_common.debug_base;
+ uint32_t cr = a8->armv7a_common.debug_base;
+ int retval;
+
+ switch (index_t) {
+ case 0 ... 15: /* breakpoints */
+ vr += CPUDBG_BVR_BASE;
+ cr += CPUDBG_BCR_BASE;
+ break;
+ case 16 ... 31: /* watchpoints */
+ vr += CPUDBG_WVR_BASE;
+ cr += CPUDBG_WCR_BASE;
+ index_t -= 16;
+ break;
+ default:
+ return ERROR_FAIL;
+ }
+ vr += 4 * index_t;
+ cr += 4 * index_t;
+
+ LOG_DEBUG("A8: bpwp enable, vr %08x cr %08x",
+ (unsigned) vr, (unsigned) cr);
+
+ retval = cortex_a8_dap_write_memap_register_u32(dpm->arm->target,
+ vr, addr);
+ if (retval != ERROR_OK)
+ return retval;
+ retval = cortex_a8_dap_write_memap_register_u32(dpm->arm->target,
+ cr, control);
+ return retval;
+}
+
+static int cortex_a8_bpwp_disable(struct arm_dpm *dpm, unsigned index_t)
+{
+ struct cortex_a8_common *a8 = dpm_to_a8(dpm);
+ uint32_t cr;
+
+ switch (index_t) {
+ case 0 ... 15:
+ cr = a8->armv7a_common.debug_base + CPUDBG_BCR_BASE;
+ break;
+ case 16 ... 31:
+ cr = a8->armv7a_common.debug_base + CPUDBG_WCR_BASE;
+ index_t -= 16;
+ break;
+ default:
+ return ERROR_FAIL;
+ }
+ cr += 4 * index_t;
+
+ LOG_DEBUG("A8: bpwp disable, cr %08x", (unsigned) cr);
+
+ /* clear control register */
+ return cortex_a8_dap_write_memap_register_u32(dpm->arm->target, cr, 0);
+}
+
+static int cortex_a8_dpm_setup(struct cortex_a8_common *a8, uint32_t didr)
+{
+ struct arm_dpm *dpm = &a8->armv7a_common.dpm;
+ int retval;
+
+ dpm->arm = &a8->armv7a_common.armv4_5_common;
+ dpm->didr = didr;
+
+ dpm->prepare = cortex_a8_dpm_prepare;
+ dpm->finish = cortex_a8_dpm_finish;
+
+ dpm->instr_write_data_dcc = cortex_a8_instr_write_data_dcc;
+ dpm->instr_write_data_r0 = cortex_a8_instr_write_data_r0;
+ dpm->instr_cpsr_sync = cortex_a8_instr_cpsr_sync;
+
+ dpm->instr_read_data_dcc = cortex_a8_instr_read_data_dcc;
+ dpm->instr_read_data_r0 = cortex_a8_instr_read_data_r0;
+
+ dpm->bpwp_enable = cortex_a8_bpwp_enable;
+ dpm->bpwp_disable = cortex_a8_bpwp_disable;
+
+ retval = arm_dpm_setup(dpm);
+ if (retval == ERROR_OK)
+ retval = arm_dpm_initialize(dpm);
+
+ return retval;
+}
+
+
+/*
+ * Cortex-A8 Run control
+ */
+
+static int cortex_a8_poll(struct target *target)
+{
+ int retval = ERROR_OK;
+ uint32_t dscr;
+ struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
+ struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
+ struct adiv5_dap *swjdp = &armv7a->dap;
+ enum target_state prev_target_state = target->state;