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 <[email protected]>
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
[email protected]
https://lists.berlios.de/mailman/listinfo/openocd-development