Hi!

What about implementing more generic access to ADIv5 and APB-AP?
I see it like this but what gurus have in mind?
From 5e3072d911f89184d159232c0f410c0252161a25 Mon Sep 17 00:00:00 2001
From: Yauheni Kaliuta <y.kali...@gmail.com>
Date: Tue, 13 Oct 2009 12:47:05 +0300
Subject: [PATCH] More abstract interface to access ADIv5 debug components

Analyse romtables and access using addresses from rom tables
---
 src/target/arm_adi_v5.c |  426 ++++++++++++++++++++++++++++++++++++++++++++++-
 src/target/arm_adi_v5.h |   62 +++++++-
 src/target/cortex_a8.c  |    2 +-
 src/target/cortex_m3.c  |    2 +-
 4 files changed, 478 insertions(+), 14 deletions(-)

diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c
index 90423f4..0384422 100644
--- a/src/target/arm_adi_v5.c
+++ b/src/target/arm_adi_v5.c
@@ -244,7 +244,7 @@ int swjdp_transaction_endcheck(swjdp_common_t *swjdp)
 		/* Check power to debug regions */
 		if ((ctrlstat & 0xf0000000) != 0xf0000000)
 		{
-			 ahbap_debugport_init(swjdp);
+			 adiv5_debugport_init(swjdp);
 		}
 		else
 		{
@@ -950,18 +950,343 @@ int mem_ap_read_buf_u8(swjdp_common_t *swjdp, uint8_t *buffer, int count, uint32
 	return retval;
 }
 
-int ahbap_debugport_init(swjdp_common_t *swjdp)
+static struct adiv5_component *new_adiv5_component(void)
 {
-	uint32_t idreg, romaddr, dummy;
+	struct adiv5_component *comp;
+
+	comp = malloc(sizeof(*comp));
+	if (comp == NULL)
+		return NULL;
+
+	memset(comp, 0, sizeof(*comp));
+
+	return comp;
+}
+
+static void free_adiv5_component(struct adiv5_component *comp)
+{
+	free(comp);
+}
+
+static void list_add_tail_comp(struct adiv5_component **comps,
+			       struct adiv5_component *comp)
+{
+	struct adiv5_component *tmp;
+
+	if (*comps == NULL)
+	{
+		*comps = comp;
+		return;
+	}
+
+	for (tmp = *comps; tmp->next; tmp = tmp->next)
+		;
+
+	tmp->next = comp;
+}
+
+static void free_list_comp(struct adiv5_component **comps)
+{
+	struct adiv5_component *tmp, *tmp1;
+
+	for (tmp = *comps; tmp;)
+	{
+		tmp1 = tmp;
+		tmp = tmp->next;
+
+		free_adiv5_component(tmp1);
+	}
+	*comps = NULL;
+}
+
+static void show_component(struct adiv5_component *comp)
+{
+	LOG_DEBUG("Component %s, base 0x%08x, start 0x%08x, class %x, part %x",
+		  comp->name, comp->base, comp->start, comp->class, comp->part_num);
+
+}
+
+static void show_ap_components(struct adiv5_ap *ap)
+{
+	struct adiv5_component *comp;
+
+	comp = ap->components;
+
+	for(; comp; comp = comp->next)
+		show_component(comp);
+}
+
+static void show_ap(struct adiv5_ap *ap)
+{
+
+	LOG_DEBUG("AP number %d, %s ID Register 0x%" PRIx32
+		  ", Debug ROM Address 0x%" PRIx32 "",
+		  ap->num, ap->name, ap->id, ap->debugbase);
+	show_ap_components(ap);
+}
+
+static int romtable_read_entry(struct adiv5_ap *ap, uint32_t base, int bit32,
+			       int *offset, uint32_t *entry)
+{
+	uint32_t tmp;
+	int r;
+	int i;
+
+	r = adiv5_ap_read_atomic_u32(ap, (base & 0xFFFFF000) | *offset, &tmp);
+	if (r < 0)
+		return ERROR_FAIL;
+
+	*offset += 4;
+
+	if (bit32) {
+		*entry = tmp;
+		return ERROR_OK;
+	}
+
+	*entry = tmp & 0x000000FF;
+	for (i = 1; i < 4; i++)
+	{
+		r = adiv5_ap_read_atomic_u32(ap, (base & 0xFFFFF000) | *offset, &tmp);
+		if (r < 0)
+			return ERROR_FAIL;
+		*entry |= (tmp & 0x000000FF) << (8 * i);
+		offset += 4;
+	}
+	return ERROR_OK;
+}
+
+static int scan_memap_component(struct adiv5_ap *ap,
+				struct adiv5_component **comps,
+				uint32_t base);
+
+static int scan_memap_romtable(struct adiv5_ap *ap,
+				struct adiv5_component *comp,
+				struct adiv5_component **out_comps,
+				uint32_t base)
+{
+	uint32_t tmp, entry, compbase;
+	int bit32;
+
+	int r;
+	int offset = 0;
+
+	r = adiv5_ap_read_atomic_u32(ap, (base & 0xFFFFF000), &tmp);
+	if (r < 0)
+		return ERROR_FAIL;
+
+	if (tmp == 0)
+	{
+		LOG_DEBUG("Blank first romtable entry?");
+		return ERROR_OK;
+	}
+
+	/* IHI 0031A 14.2 ROM Entries */
+	bit32 = tmp & (1 << 1);
+
+	r = romtable_read_entry(ap, base, bit32, &offset, &entry);
+	if (r < 0)
+		return ERROR_FAIL;
+
+	comp->name = "ROMTable entry";
+	comp->start = base;
+
+	for (; entry; r = romtable_read_entry(ap, base, bit32, &offset, &entry))
+	{
+		if (r < 0)
+			return ERROR_FAIL;
+
+		if (! (entry & (1 << 0))) /* check presense */
+			continue;
+
+		compbase = (base & 0xFFFFF000) + (entry & 0xFFFFF000);
+		r = scan_memap_component(ap, out_comps, compbase);
+		if (r < 0)
+			return ERROR_FAIL;
+	}
+
+	return ERROR_OK;
+}
+
+static int scan_memap_debugcomp(struct adiv5_ap *ap,
+				struct adiv5_component *comp,
+				 uint32_t base)
+{
+	comp->start = base - 0x1000 * (comp->pid[4] >> 4);
+	comp->name = "Coresight component";
+
+	return ERROR_OK;
+}
+
+static int scan_memap_component(struct adiv5_ap *ap,
+				struct adiv5_component **comps,
+				uint32_t base)
+{
+	struct adiv5_component *comp, *tablecomps = NULL;
+	int i, r;
+
+	uint32_t tmp;
+
+	comp = new_adiv5_component();
+	if (comp == NULL)
+	{
+		LOG_ERROR("No memory");
+		return ERROR_FAIL;
+	}
+
+	comp->base = base;
+	comp->ap = ap;
+
+	for (i = 0; i < 4; i++)
+	{
+		r = adiv5_comp_base_read_atomic_u32(comp, 0xFF0 + (i * 4), &tmp);
+		if (r < 0)
+			goto err1;
+
+		comp->cid[i] = tmp & 0x000000FF;
+	}
+	for (i = 0; i < 4; i++)
+	{
+		r = adiv5_comp_base_read_atomic_u32(comp, 0xFE0 + (i * 4), &tmp);
+		if (r < 0)
+			goto err1;
+
+		comp->pid[i] = tmp & 0x000000FF;
+	}
+
+	for (i = 0; i < 4; i++)
+	{
+		r = adiv5_comp_base_read_atomic_u32(comp, 0xFD0 + (i * 4), &tmp);
+		if (r < 0)
+			goto err1;
+
+		comp->pid[i + 4] = tmp & 0x000000FF;
+	}
+
+	/* IHI 0031A 13.2 The Component ID Registers */
+	comp->class = (comp->cid[1] & 0xF0) >> 4;
+	comp->part_num = ((uint32_t)comp->pid[1] & 0x0F) << 8 | comp->pid[0];
+
+	if (comp->class == COMP_CLASS_ROMTABLE)
+		r = scan_memap_romtable(ap, comp, &tablecomps, base);
+	else
+		r = scan_memap_debugcomp(ap, comp, base);
+
+	if (r < 0)
+		goto err1;
+
+	list_add_tail_comp(comps, comp);
+	if (tablecomps)
+		list_add_tail_comp(comps, tablecomps);
+
+	return ERROR_OK;
+err1:
+	free_adiv5_component(comp);
+	return ERROR_FAIL;
+}
+
+static void init_ap_struct(struct adiv5_ap *ap)
+{
+	ap->type = AP_TYPE_NONE;
+	ap->id = 0;
+	ap->debugbase = 0xFFFFFFFF;
+	ap->name = "NONE";
+	ap->components = NULL;
+}
+
+static int scan_ap(swjdp_common_t *swjdp, struct adiv5_ap *ap, int n)
+{
+	uint32_t idreg, romaddr;
+	int r;
+
+	init_ap_struct(ap);
+	ap->num = n;
+	ap->swjdp = swjdp;
+
+	swjdp->apsel = n;
+	dap_ap_select(swjdp, swjdp->apsel);
+
+	dap_ap_read_reg_u32(swjdp, AP_REG_IDR, &idreg);
+	dap_ap_read_reg_u32(swjdp, AP_REG_DBGROMA, &romaddr);
+
+	r = swjdp_transaction_endcheck(swjdp);
+	if (r < 0) {
+		LOG_DEBUG("swjdp_transaction_endcheck failed");
+		return ERROR_FAIL;
+	}
+
+	if (idreg == 0) /* non-existing AP */
+		return ERROR_OK;
+
+	ap->id = idreg;
+	ap->debugbase = romaddr;
+
+	/* IHI 0031A 10.2.2, IDR */
+	if (idreg & (1 << 16))
+		ap->type = AP_TYPE_MEM;
+
+	switch (idreg & 0x0F)
+	{
+	case 0:
+		ap->type = AP_TYPE_JTAG;
+		ap->name = "JTAG-AP";
+		break;
+	case 1:
+		ap->name = "AHB-AP";
+		break;
+	case 2:
+		ap->name = "APB-AP";
+		break;
+	default:
+		ap->type = AP_TYPE_UNKNOWN;
+		ap->name = "Unknown";
+		break;
+	}
+
+	if ((ap->type == AP_TYPE_MEM) && (ap->debugbase != 0xFFFFFFFF))
+		r = scan_memap_component(ap, &ap->components, ap->debugbase);
+
+	if (r < 0) {
+		free_list_comp(&ap->components);
+		return ERROR_FAIL;
+	}
+
+	show_ap(ap);
+
+	return ERROR_OK;
+}
+
+static int scan_swjdp(swjdp_common_t *swjdp)
+{
+	int i, r;
+
+	int max_ap = sizeof(swjdp->ap) / sizeof(swjdp->ap[0]);
+
+	for (i = 0; i < max_ap; i++)
+	{
+		r = scan_ap(swjdp, &swjdp->ap[i], i);
+		if (r < 0)
+			return ERROR_FAIL;
+		/* To speedup assume all APs are in the beginning */
+		if (swjdp->ap[i].type == AP_TYPE_NONE)
+			break;
+	}
+
+	swjdp->apsel = 0;
+	swjdp->ap_csw_value = -1;
+	swjdp->ap_tar_value = -1;
+
+	return ERROR_OK;
+}
+
+int adiv5_debugport_init(swjdp_common_t *swjdp)
+{
+	uint32_t dummy;
 	uint32_t ctrlstat;
 	int cnt = 0;
 	int retval;
 
 	LOG_DEBUG(" ");
 
-	swjdp->apsel = 0;
-	swjdp->ap_csw_value = -1;
-	swjdp->ap_tar_value = -1;
 	swjdp->trans_mode = TRANS_MODE_ATOMIC;
 	dap_dp_read_reg(swjdp, &dummy, DP_CTRL_STAT);
 	dap_dp_write_reg(swjdp, SSTICKYERR, DP_CTRL_STAT);
@@ -999,10 +1324,10 @@ int ahbap_debugport_init(swjdp_common_t *swjdp)
 	dap_dp_write_reg(swjdp, swjdp->dp_ctrl_stat, DP_CTRL_STAT);
 	dap_dp_read_reg(swjdp, &dummy, DP_CTRL_STAT);
 
-	dap_ap_read_reg_u32(swjdp, 0xFC, &idreg);
-	dap_ap_read_reg_u32(swjdp, 0xF8, &romaddr);
 
-	LOG_DEBUG("AHB-AP ID Register 0x%" PRIx32 ", Debug ROM Address 0x%" PRIx32 "", idreg, romaddr);
+	retval = scan_swjdp(swjdp);
+	if (retval < 0)
+		return ERROR_FAIL;
 
 	return ERROR_OK;
 }
@@ -1211,3 +1536,86 @@ int dap_apid_command(struct command_context_s *cmd_ctx,
 }
 
 
+struct adiv5_component *adiv5_find_component(struct adiv5_ap *ap, int part_num)
+{
+	struct adiv5_component *comp;
+
+	comp = ap->components;
+
+	for(; comp; comp = comp->next)
+		if (comp->part_num == part_num)
+			return comp;
+	return NULL;
+}
+
+int adiv5_ap_read_atomic_u32(struct adiv5_ap *ap, uint32_t reg, uint32_t *val)
+{
+	swjdp_common_t *swjdp = ap->swjdp;
+	int r;
+
+	if (ap->type != AP_TYPE_MEM)
+	{
+		LOG_ERROR("%s is called for non-mem AP", __FUNCTION__);
+		return ERROR_FAIL;
+	}
+
+	dap_ap_select(swjdp, ap->num);
+	r = mem_ap_read_atomic_u32(swjdp, reg, val);
+	return r;
+}
+
+int adiv5_ap_write_atomic_u32(struct adiv5_ap *ap, uint32_t reg, uint32_t val)
+{
+	swjdp_common_t *swjdp = ap->swjdp;
+	int r;
+
+	if (ap->type != AP_TYPE_MEM)
+	{
+		LOG_ERROR("%s is called for non-mem AP", __FUNCTION__);
+		return ERROR_FAIL;
+	}
+
+	dap_ap_select(swjdp, ap->num);
+	r = mem_ap_write_atomic_u32(swjdp, reg, val);
+	return r;
+}
+
+int adiv5_comp_read_atomic_u32(struct adiv5_component *comp,
+			       uint32_t reg, uint32_t *val)
+{
+	uint32_t base = comp->start;
+	int r;
+
+	r = adiv5_ap_read_atomic_u32(comp->ap, base + reg, val);
+	return r;
+}
+
+int adiv5_comp_write_atomic_u32(struct adiv5_component *comp,
+				uint32_t reg, uint32_t val)
+{
+	uint32_t base = comp->start;
+	int r;
+
+	r = adiv5_ap_write_atomic_u32(comp->ap, base + reg, val);
+	return r;
+}
+
+int adiv5_comp_base_read_atomic_u32(struct adiv5_component *comp,
+				    uint32_t reg, uint32_t *val)
+{
+	uint32_t base = comp->base & 0xFFFFF000;
+	int r;
+
+	r = adiv5_ap_read_atomic_u32(comp->ap, base + (reg & 0x00000FFF), val);
+	return r;
+}
+
+int adiv5_comp_base_write_atomic_u32(struct adiv5_component *comp,
+				     uint32_t reg, uint32_t val)
+{
+	uint32_t base = comp->base & 0xFFFFF000;
+	int r;
+
+	r = adiv5_ap_write_atomic_u32(comp->ap, base + (reg & 0x00000FFF), val);
+	return r;
+}
diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h
index 3ff883a..4bafbcb 100644
--- a/src/target/arm_adi_v5.h
+++ b/src/target/arm_adi_v5.h
@@ -57,6 +57,11 @@
 #define AP_REG_DBGROMA	0xF8
 #define AP_REG_IDR		0xFC
 
+#define AP_TYPE_UNKNOWN		0x00
+#define AP_TYPE_JTAG		0x01
+#define AP_TYPE_MEM		0x02
+#define AP_TYPE_NONE		0xFF
+
 #define CSW_8BIT		0
 #define CSW_16BIT		1
 #define CSW_32BIT		2
@@ -76,6 +81,44 @@
 /* Freerunning transactions with delays and overrun checking */
 #define TRANS_MODE_COMPOSITE	2
 
+
+#define COMP_CLASS_ROMTABLE	0x01
+#define COMP_CLASS_DEBUG	0x09
+
+
+struct adiv5_component;
+struct swjdp_common_s;
+
+struct adiv5_ap
+{
+	struct swjdp_common_s *swjdp;
+
+	int type;
+	int num;
+	uint32_t id;
+	uint32_t debugbase;
+	const char *name;
+
+	struct adiv5_component *components;
+};
+
+struct adiv5_component
+{
+	struct adiv5_component *next;
+
+	struct adiv5_ap *ap;
+
+	int class;
+	int part_num;
+	const char *name;
+
+	uint32_t base;
+	uint32_t start;
+
+	uint8_t cid[4];
+	uint8_t pid[8];
+};
+
 typedef struct swjdp_reg_s
 {
 	int addr;
@@ -101,7 +144,8 @@ typedef struct swjdp_common_s
 	uint32_t	memaccess_tck;
 	/* Size of TAR autoincrement block, ARM ADI Specification requires at least 10 bits */
 	uint32_t tar_autoincr_block;
-
+	/* connected APs, 8 bits, ARM IHI 0031A */
+	struct adiv5_ap ap[256];
 } swjdp_common_t;
 
 /* Accessor function for currently selected DAP-AP number */
@@ -143,8 +187,20 @@ extern int mem_ap_write_buf_u16(swjdp_common_t *swjdp, uint8_t *buffer, int coun
 extern int mem_ap_write_buf_u32(swjdp_common_t *swjdp, uint8_t *buffer, int count, uint32_t address);
 
 /* Initialisation of the debug system, power domains and registers */
-extern int ahbap_debugport_init(swjdp_common_t *swjdp);
-
+extern int adiv5_debugport_init(swjdp_common_t *swjdp);
+
+/* Access to ADIv5 parts */
+extern struct adiv5_component *adiv5_find_component(struct adiv5_ap *ap, int part_num);
+extern int adiv5_ap_read_atomic_u32(struct adiv5_ap *ap, uint32_t reg, uint32_t *val);
+extern int adiv5_ap_write_atomic_u32(struct adiv5_ap *ap, uint32_t reg, uint32_t val);
+extern int adiv5_comp_read_atomic_u32(struct adiv5_component *comp,
+				      uint32_t reg, uint32_t *val);
+extern int adiv5_comp_write_atomic_u32(struct adiv5_component *comp,
+				       uint32_t reg, uint32_t val);
+extern int adiv5_comp_base_read_atomic_u32(struct adiv5_component *comp,
+					   uint32_t reg, uint32_t *val);
+extern int adiv5_comp_base_write_atomic_u32(struct adiv5_component *comp,
+					    uint32_t reg, uint32_t val);
 
 /* Commands for user dap access */
 int dap_info_command(struct command_context_s *cmd_ctx,
diff --git a/src/target/cortex_a8.c b/src/target/cortex_a8.c
index 846d90c..a1e791b 100644
--- a/src/target/cortex_a8.c
+++ b/src/target/cortex_a8.c
@@ -1451,7 +1451,7 @@ int cortex_a8_examine(struct target_s *target)
 	/* We do one extra read to ensure DAP is configured,
 	 * we call ahbap_debugport_init(swjdp) instead
 	 */
-	ahbap_debugport_init(swjdp);
+	adiv5_debugport_init(swjdp);
 	mem_ap_read_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_CPUID, &cpuid);
 	if ((retval = mem_ap_read_atomic_u32(swjdp,
 			armv7a->debug_base + CPUDBG_CPUID, &cpuid)) != ERROR_OK)
diff --git a/src/target/cortex_m3.c b/src/target/cortex_m3.c
index 5f5287a..33dccfd 100644
--- a/src/target/cortex_m3.c
+++ b/src/target/cortex_m3.c
@@ -1507,7 +1507,7 @@ int cortex_m3_examine(struct target_s *target)
 	cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
 	swjdp_common_t *swjdp = &armv7m->swjdp_info;
 
-	if ((retval = ahbap_debugport_init(swjdp)) != ERROR_OK)
+	if ((retval = adiv5_debugport_init(swjdp)) != ERROR_OK)
 		return retval;
 
 	if (!target_was_examined(target))
-- 
1.6.4.3

_______________________________________________
Openocd-development mailing list
Openocd-development@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/openocd-development

Reply via email to