From f4b52e1ceb2818d7a388c7aa0a3a7ab9b78f68be Mon Sep 17 00:00:00 2001
From: David Brownell <dbrownell@users.sourceforge.net>
Date: Tue, 1 Dec 2009 21:47:45 -0800
Subject: Cortex-A8: basic watchpoint support

Actually this should handle both breakpoints and watchpoints ... but
the DPM framework only handles watchpoints for now.  Works on Beagle.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
---
 src/target/cortex_a8.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

(limited to 'src')

diff --git a/src/target/cortex_a8.c b/src/target/cortex_a8.c
index 81402d79..a289d96a 100644
--- a/src/target/cortex_a8.c
+++ b/src/target/cortex_a8.c
@@ -460,6 +460,66 @@ static int cortex_a8_instr_read_data_r0(struct arm_dpm *dpm,
 	return cortex_a8_read_dcc(a8, data, &dscr);
 }
 
+static int cortex_a8_bpwp_enable(struct arm_dpm *dpm, unsigned index,
+		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) {
+	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 -= 16;
+		break;
+	default:
+		return ERROR_FAIL;
+	}
+	vr += 4 * index;
+	cr += 4 * index;
+
+	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)
+{
+	struct cortex_a8_common *a8 = dpm_to_a8(dpm);
+	uint32_t cr;
+
+	switch (index) {
+	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 -= 16;
+		break;
+	default:
+		return ERROR_FAIL;
+	}
+	cr += 4 * index;
+
+	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;
@@ -477,6 +537,9 @@ static int cortex_a8_dpm_setup(struct cortex_a8_common *a8, uint32_t didr)
 	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;
+
 	return arm_dpm_setup(dpm);
 }
 
@@ -745,6 +808,7 @@ static int cortex_a8_debug_entry(struct target *target)
 		case 5:		/* vector catch */
 			target->debug_reason = DBG_REASON_BREAKPOINT;
 			break;
+		case 2:		/* asynch watchpoint */
 		case 10:	/* precise watchpoint */
 			target->debug_reason = DBG_REASON_WATCHPOINT;
 			/* REVISIT could collect WFAR later, to see just
@@ -1276,6 +1340,8 @@ static int cortex_a8_write_memory(struct target *target, uint32_t address,
 		 *
 		 * For both ICache and DCache, walk all cache lines in the
 		 * address range. Cortex-A8 has fixed 64 byte line length.
+		 *
+		 * REVISIT per ARMv7, these may trigger watchpoints ...
 		 */
 
 		/* invalidate I-Cache */
-- 
cgit v1.2.3