Cortex-A8: implement DPM
[openocd.git] / src / target / cortex_a8.c
index f549fb394dffa6a1ad3468e1f042f01a570187a3..28c75b591da3f6dc4b9f2dd24bc3843cb8dd3bae 100644 (file)
@@ -351,6 +351,173 @@ static int cortex_a8_dap_write_memap_register_u32(struct target *target, uint32_
        return retval;
 }
 
+/*
+ * Cortex-A8 implementation of Debug Programmer's Model
+ *
+ * NOTE that in several of these cases the "stall" mode might be useful.
+ * It'd let us queue a few operations together... prepare/finish might
+ * be the places to enable/disable that mode.
+ */
+
+static inline struct cortex_a8_common *dpm_to_a8(struct arm_dpm *dpm)
+{
+       return container_of(dpm, struct cortex_a8_common, armv7a_common.dpm);
+}
+
+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_write_u32(&a8->armv7a_common.swjdp_info,
+                       a8->armv7a_common.debug_base + CPUDBG_DTRRX, data);
+}
+
+static int cortex_a8_read_dcc(struct cortex_a8_common *a8, uint32_t *data)
+{
+       struct swjdp_common *swjdp = &a8->armv7a_common.swjdp_info;
+       uint32_t dscr;
+       int retval;
+
+       /* Wait for DTRRXfull */
+       do {
+               retval = mem_ap_read_atomic_u32(swjdp,
+                               a8->armv7a_common.debug_base + CPUDBG_DSCR,
+                               &dscr);
+       } while ((dscr & (1 << DSCR_DTR_TX_FULL)) == 0);
+
+       retval = mem_ap_read_atomic_u32(swjdp,
+                       a8->armv7a_common.debug_base + CPUDBG_DTRTX, data);
+       LOG_DEBUG("read DCC 0x%08" PRIx32, *data);
+
+       return retval;
+}
+
+static int cortex_a8_dpm_prepare(struct arm_dpm *dpm)
+{
+       struct cortex_a8_common *a8 = dpm_to_a8(dpm);
+       struct swjdp_common *swjdp = &a8->armv7a_common.swjdp_info;
+       uint32_t dscr;
+       int retval;
+
+       retval = mem_ap_read_atomic_u32(swjdp,
+                       a8->armv7a_common.debug_base + CPUDBG_DSCR,
+                       &dscr);
+
+       /* this "should never happen" ... */
+       if (dscr & (1 << DSCR_DTR_RX_FULL)) {
+               LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr);
+               /* Clear DCCRX */
+               retval = cortex_a8_exec_opcode(
+                               a8->armv7a_common.armv4_5_common.target,
+                               ARMV4_5_MRC(14, 0, 0, 0, 5, 0));
+       }
+
+       return retval;
+}
+
+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;
+
+       retval = cortex_a8_write_dcc(a8, data);
+
+       return cortex_a8_exec_opcode(
+                       a8->armv7a_common.armv4_5_common.target,
+                       opcode);
+}
+
+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);
+       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));
+
+       /* then the opcode, taking data from R0 */
+       retval = cortex_a8_exec_opcode(
+                       a8->armv7a_common.armv4_5_common.target,
+                       opcode);
+
+       return retval;
+}
+
+static int cortex_a8_instr_cpsr_sync(struct arm_dpm *dpm)
+{
+       struct target *target = dpm->arm->target;
+
+       /* "Prefetch flush" after modifying execution status in CPSR */
+       return cortex_a8_exec_opcode(target, ARMV4_5_MCR(15, 0, 0, 7, 5, 4));
+}
+
+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;
+
+       /* the opcode, writing data to DCC */
+       retval = cortex_a8_exec_opcode(
+                       a8->armv7a_common.armv4_5_common.target,
+                       opcode);
+
+       return cortex_a8_read_dcc(a8, data);
+}
+
+
+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);
+       int retval;
+
+       /* the opcode, writing data to R0 */
+       retval = cortex_a8_exec_opcode(
+                       a8->armv7a_common.armv4_5_common.target,
+                       opcode);
+
+       /* 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));
+
+       return cortex_a8_read_dcc(a8, data);
+}
+
+// static
+int cortex_a8_dpm_setup(struct cortex_a8_common *a8, uint32_t didr)
+{
+       struct arm_dpm *dpm = &a8->armv7a_common.dpm;
+
+       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;
+
+       return arm_dpm_setup(dpm);
+}
+
+
 /*
  * Cortex-A8 Run control
  */

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)