+ const char *major = "Reserved", *subtype = "Reserved";
+ const unsigned int minor = (devtype & ARM_CS_C9_DEVTYPE_SUB_MASK) >> ARM_CS_C9_DEVTYPE_SUB_SHIFT;
+ const unsigned int devtype_major = (devtype & ARM_CS_C9_DEVTYPE_MAJOR_MASK) >> ARM_CS_C9_DEVTYPE_MAJOR_SHIFT;
+ switch (devtype_major) {
+ case 0:
+ major = "Miscellaneous";
+ switch (minor) {
+ case 0:
+ subtype = "other";
+ break;
+ case 4:
+ subtype = "Validation component";
+ break;
+ }
+ break;
+ case 1:
+ major = "Trace Sink";
+ switch (minor) {
+ case 0:
+ subtype = "other";
+ break;
+ case 1:
+ subtype = "Port";
+ break;
+ case 2:
+ subtype = "Buffer";
+ break;
+ case 3:
+ subtype = "Router";
+ break;
+ }
+ break;
+ case 2:
+ major = "Trace Link";
+ switch (minor) {
+ case 0:
+ subtype = "other";
+ break;
+ case 1:
+ subtype = "Funnel, router";
+ break;
+ case 2:
+ subtype = "Filter";
+ break;
+ case 3:
+ subtype = "FIFO, buffer";
+ break;
+ }
+ break;
+ case 3:
+ major = "Trace Source";
+ switch (minor) {
+ case 0:
+ subtype = "other";
+ break;
+ case 1:
+ subtype = "Processor";
+ break;
+ case 2:
+ subtype = "DSP";
+ break;
+ case 3:
+ subtype = "Engine/Coprocessor";
+ break;
+ case 4:
+ subtype = "Bus";
+ break;
+ case 6:
+ subtype = "Software";
+ break;
+ }
+ break;
+ case 4:
+ major = "Debug Control";
+ switch (minor) {
+ case 0:
+ subtype = "other";
+ break;
+ case 1:
+ subtype = "Trigger Matrix";
+ break;
+ case 2:
+ subtype = "Debug Auth";
+ break;
+ case 3:
+ subtype = "Power Requestor";
+ break;
+ }
+ break;
+ case 5:
+ major = "Debug Logic";
+ switch (minor) {
+ case 0:
+ subtype = "other";
+ break;
+ case 1:
+ subtype = "Processor";
+ break;
+ case 2:
+ subtype = "DSP";
+ break;
+ case 3:
+ subtype = "Engine/Coprocessor";
+ break;
+ case 4:
+ subtype = "Bus";
+ break;
+ case 5:
+ subtype = "Memory";
+ break;
+ }
+ break;
+ case 6:
+ major = "Performance Monitor";
+ switch (minor) {
+ case 0:
+ subtype = "other";
+ break;
+ case 1:
+ subtype = "Processor";
+ break;
+ case 2:
+ subtype = "DSP";
+ break;
+ case 3:
+ subtype = "Engine/Coprocessor";
+ break;
+ case 4:
+ subtype = "Bus";
+ break;
+ case 5:
+ subtype = "Memory";
+ break;
+ }
+ break;
+ }
+ command_print(cmd, "\t\tType is 0x%02x, %s, %s",
+ devtype & ARM_CS_C9_DEVTYPE_MASK,
+ major, subtype);
+ return ERROR_OK;
+}
+
+/**
+ * Actions/operations to be executed while parsing ROM tables.
+ */
+struct rtp_ops {
+ /**
+ * Executed at the start of a new AP, typically to print the AP header.
+ * @param ap Pointer to AP.
+ * @param depth The current depth level of ROM table.
+ * @param priv Pointer to private data.
+ * @return ERROR_OK on success, else a fault code.
+ */
+ int (*ap_header)(struct adiv5_ap *ap, int depth, void *priv);
+ /**
+ * Executed at the start of a new MEM-AP, typically to print the MEM-AP header.
+ * @param retval Error encountered while reading AP.
+ * @param ap Pointer to AP.
+ * @param dbgbase Value of MEM-AP Debug Base Address register.
+ * @param apid Value of MEM-AP IDR Identification Register.
+ * @param depth The current depth level of ROM table.
+ * @param priv Pointer to private data.
+ * @return ERROR_OK on success, else a fault code.
+ */
+ int (*mem_ap_header)(int retval, struct adiv5_ap *ap, uint64_t dbgbase,
+ uint32_t apid, int depth, void *priv);
+ /**
+ * Executed when a CoreSight component is parsed, typically to print
+ * information on the component.
+ * @param retval Error encountered while reading component's registers.
+ * @param v Pointer to a container of the component's registers.
+ * @param depth The current depth level of ROM table.
+ * @param priv Pointer to private data.
+ * @return ERROR_OK on success, else a fault code.
+ */
+ int (*cs_component)(int retval, struct cs_component_vals *v, int depth, void *priv);
+ /**
+ * Executed for each entry of a ROM table, typically to print the entry
+ * and information about validity or end-of-table mark.
+ * @param retval Error encountered while reading the ROM table entry.
+ * @param depth The current depth level of ROM table.
+ * @param offset The offset of the entry in the ROM table.
+ * @param romentry The value of the ROM table entry.
+ * @param priv Pointer to private data.
+ * @return ERROR_OK on success, else a fault code.
+ */
+ int (*rom_table_entry)(int retval, int depth, unsigned int offset, uint64_t romentry,
+ void *priv);
+ /**
+ * Private data
+ */
+ void *priv;
+};
+
+/**
+ * Wrapper around struct rtp_ops::ap_header.
+ */
+static int rtp_ops_ap_header(const struct rtp_ops *ops,
+ struct adiv5_ap *ap, int depth)
+{
+ if (ops->ap_header)
+ return ops->ap_header(ap, depth, ops->priv);
+
+ return ERROR_OK;
+}
+
+/**
+ * Wrapper around struct rtp_ops::mem_ap_header.
+ * Input parameter @a retval is propagated.
+ */
+static int rtp_ops_mem_ap_header(const struct rtp_ops *ops,
+ int retval, struct adiv5_ap *ap, uint64_t dbgbase, uint32_t apid, int depth)
+{
+ if (!ops->mem_ap_header)
+ return retval;
+
+ int retval1 = ops->mem_ap_header(retval, ap, dbgbase, apid, depth, ops->priv);
+ if (retval != ERROR_OK)
+ return retval;
+ return retval1;
+}
+
+/**
+ * Wrapper around struct rtp_ops::cs_component.
+ * Input parameter @a retval is propagated.
+ */
+static int rtp_ops_cs_component(const struct rtp_ops *ops,
+ int retval, struct cs_component_vals *v, int depth)
+{
+ if (!ops->cs_component)
+ return retval;
+
+ int retval1 = ops->cs_component(retval, v, depth, ops->priv);
+ if (retval != ERROR_OK)
+ return retval;
+ return retval1;
+}
+
+/**
+ * Wrapper around struct rtp_ops::rom_table_entry.
+ * Input parameter @a retval is propagated.
+ */
+static int rtp_ops_rom_table_entry(const struct rtp_ops *ops,
+ int retval, int depth, unsigned int offset, uint64_t romentry)
+{
+ if (!ops->rom_table_entry)
+ return retval;
+
+ int retval1 = ops->rom_table_entry(retval, depth, offset, romentry, ops->priv);
+ if (retval != ERROR_OK)
+ return retval;
+ return retval1;
+}
+
+/* Broken ROM tables can have circular references. Stop after a while */
+#define ROM_TABLE_MAX_DEPTH (16)
+
+/**
+ * Value used only during lookup of a CoreSight component in ROM table.
+ * Return CORESIGHT_COMPONENT_FOUND when component is found.
+ * Return ERROR_OK when component is not found yet.
+ * Return any other ERROR_* in case of error.
+ */
+#define CORESIGHT_COMPONENT_FOUND (1)
+
+static int rtp_ap(const struct rtp_ops *ops, struct adiv5_ap *ap, int depth);
+static int rtp_cs_component(enum coresight_access_mode mode, const struct rtp_ops *ops,
+ struct adiv5_ap *ap, target_addr_t dbgbase, bool *is_mem_ap, int depth);
+
+static int rtp_rom_loop(enum coresight_access_mode mode, const struct rtp_ops *ops,
+ struct adiv5_ap *ap, target_addr_t base_address, int depth,
+ unsigned int width, unsigned int max_entries)
+{
+ /* ADIv6 AP ROM table provide offset from current AP */
+ if (mode == CS_ACCESS_AP)
+ base_address = ap->ap_num;
+
+ assert(IS_ALIGNED(base_address, ARM_CS_ALIGN));
+
+ unsigned int offset = 0;
+ while (max_entries--) {
+ uint64_t romentry;
+ uint32_t romentry_low, romentry_high;
+ target_addr_t component_base;
+ unsigned int saved_offset = offset;
+
+ int retval = dap_queue_read_reg(mode, ap, base_address, offset, &romentry_low);
+ offset += 4;
+ if (retval == ERROR_OK && width == 64) {
+ retval = dap_queue_read_reg(mode, ap, base_address, offset, &romentry_high);
+ offset += 4;
+ }
+ if (retval == ERROR_OK)
+ retval = dap_run(ap->dap);
+ if (retval != ERROR_OK) {
+ LOG_DEBUG("Failed read ROM table entry");
+ return retval;
+ }
+
+ if (width == 64) {
+ romentry = (((uint64_t)romentry_high) << 32) | romentry_low;
+ component_base = base_address +
+ ((((uint64_t)romentry_high) << 32) | (romentry_low & ARM_CS_ROMENTRY_OFFSET_MASK));
+ } else {
+ romentry = romentry_low;
+ /* "romentry" is signed */
+ component_base = base_address + (int32_t)(romentry_low & ARM_CS_ROMENTRY_OFFSET_MASK);
+ if (!is_64bit_ap(ap))
+ component_base = (uint32_t)component_base;
+ }
+ retval = rtp_ops_rom_table_entry(ops, retval, depth, saved_offset, romentry);
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (romentry == 0) {
+ /* End of ROM table */
+ break;
+ }
+
+ if (!(romentry & ARM_CS_ROMENTRY_PRESENT))
+ continue;
+
+ /* Recurse */
+ if (mode == CS_ACCESS_AP) {
+ struct adiv5_ap *next_ap = dap_get_ap(ap->dap, component_base);
+ if (!next_ap) {
+ LOG_DEBUG("Wrong AP # 0x%" PRIx64, component_base);
+ continue;
+ }
+ retval = rtp_ap(ops, next_ap, depth + 1);
+ dap_put_ap(next_ap);
+ } else {
+ /* mode == CS_ACCESS_MEM_AP */
+ retval = rtp_cs_component(mode, ops, ap, component_base, NULL, depth + 1);
+ }
+ if (retval == CORESIGHT_COMPONENT_FOUND)
+ return CORESIGHT_COMPONENT_FOUND;
+ if (retval != ERROR_OK) {
+ /* TODO: do we need to send an ABORT before continuing? */
+ LOG_DEBUG("Ignore error parsing CoreSight component");
+ continue;
+ }
+ }
+
+ return ERROR_OK;
+}
+
+static int rtp_cs_component(enum coresight_access_mode mode, const struct rtp_ops *ops,
+ struct adiv5_ap *ap, target_addr_t base_address, bool *is_mem_ap, int depth)
+{
+ struct cs_component_vals v;