+ assert(IS_ALIGNED(base_address, ARM_CS_ALIGN));
+
+ if (is_mem_ap)
+ *is_mem_ap = false;
+
+ if (depth > ROM_TABLE_MAX_DEPTH)
+ retval = ERROR_FAIL;
+ else
+ retval = rtp_read_cs_regs(mode, ap, base_address, &v);
+
+ retval = rtp_ops_cs_component(ops, retval, &v, depth);
+ if (retval == CORESIGHT_COMPONENT_FOUND)
+ return CORESIGHT_COMPONENT_FOUND;
+ if (retval != ERROR_OK)
+ return ERROR_OK; /* Don't abort recursion */
+
+ if (!is_valid_arm_cs_cidr(v.cid))
+ return ERROR_OK; /* Don't abort recursion */
+
+ const unsigned int class = ARM_CS_CIDR_CLASS(v.cid);
+
+ if (class == ARM_CS_CLASS_0X1_ROM_TABLE)
+ return rtp_rom_loop(mode, ops, ap, base_address, depth, 32, 960);
+
+ if (class == ARM_CS_CLASS_0X9_CS_COMPONENT) {
+ if ((v.devarch & ARM_CS_C9_DEVARCH_PRESENT) == 0)
+ return ERROR_OK;
+
+ if (is_mem_ap && (v.devarch & DEVARCH_ID_MASK) == DEVARCH_MEM_AP)
+ *is_mem_ap = true;
+
+ /* quit if not ROM table */
+ if ((v.devarch & DEVARCH_ID_MASK) != DEVARCH_ROM_C_0X9)
+ return ERROR_OK;
+
+ if ((v.devid & ARM_CS_C9_DEVID_FORMAT_MASK) == ARM_CS_C9_DEVID_FORMAT_64BIT)
+ return rtp_rom_loop(mode, ops, ap, base_address, depth, 64, 256);
+ else
+ return rtp_rom_loop(mode, ops, ap, base_address, depth, 32, 512);
+ }
+
+ /* Class other than 0x1 and 0x9 */
+ return ERROR_OK;
+}
+
+static int rtp_ap(const struct rtp_ops *ops, struct adiv5_ap *ap, int depth)
+{
+ uint32_t apid;
+ target_addr_t dbgbase, invalid_entry;
+
+ int retval = rtp_ops_ap_header(ops, ap, depth);
+ if (retval != ERROR_OK || depth > ROM_TABLE_MAX_DEPTH)
+ return ERROR_OK; /* Don't abort recursion */
+
+ if (is_adiv6(ap->dap)) {
+ bool is_mem_ap;
+ retval = rtp_cs_component(CS_ACCESS_AP, ops, ap, 0, &is_mem_ap, depth);
+ if (retval == CORESIGHT_COMPONENT_FOUND)
+ return CORESIGHT_COMPONENT_FOUND;
+ if (retval != ERROR_OK)
+ return ERROR_OK; /* Don't abort recursion */
+
+ if (!is_mem_ap)
+ return ERROR_OK;
+ /* Continue for an ADIv6 MEM-AP */
+ }
+
+ /* Now we read ROM table ID registers, ref. ARM IHI 0029B sec */
+ retval = dap_get_debugbase(ap, &dbgbase, &apid);
+ if (retval != ERROR_OK)
+ return retval;
+ retval = rtp_ops_mem_ap_header(ops, retval, ap, dbgbase, apid, depth);
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (apid == 0)
+ return ERROR_FAIL;
+
+ /* NOTE: a MEM-AP may have a single CoreSight component that's
+ * not a ROM table ... or have no such components at all.
+ */
+ const unsigned int class = (apid & AP_REG_IDR_CLASS_MASK) >> AP_REG_IDR_CLASS_SHIFT;
+
+ if (class == AP_REG_IDR_CLASS_MEM_AP) {
+ if (is_64bit_ap(ap))
+ invalid_entry = 0xFFFFFFFFFFFFFFFFull;
+ else
+ invalid_entry = 0xFFFFFFFFul;
+
+ if (dbgbase != invalid_entry && (dbgbase & 0x3) != 0x2) {
+ retval = rtp_cs_component(CS_ACCESS_MEM_AP, ops, ap,
+ dbgbase & 0xFFFFFFFFFFFFF000ull, NULL, depth);
+ if (retval == CORESIGHT_COMPONENT_FOUND)
+ return CORESIGHT_COMPONENT_FOUND;
+ }
+ }
+
+ return ERROR_OK;
+}
+
+/* Actions for command "dap info" */
+
+static int dap_info_ap_header(struct adiv5_ap *ap, int depth, void *priv)
+{
+ struct command_invocation *cmd = priv;
+
+ if (depth > ROM_TABLE_MAX_DEPTH) {
+ command_print(cmd, "\tTables too deep");
+ return ERROR_FAIL;
+ }
+
+ command_print(cmd, "%sAP # 0x%" PRIx64, (depth) ? "\t\t" : "", ap->ap_num);
+ return ERROR_OK;
+}
+
+static int dap_info_mem_ap_header(int retval, struct adiv5_ap *ap,
+ target_addr_t dbgbase, uint32_t apid, int depth, void *priv)
+{
+ struct command_invocation *cmd = priv;
+ target_addr_t invalid_entry;
+ char tabs[17] = "";
+
+ if (retval != ERROR_OK) {
+ command_print(cmd, "\t\tCan't read MEM-AP, the corresponding core might be turned off");
+ return retval;
+ }
+
+ if (depth > ROM_TABLE_MAX_DEPTH) {