X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farm_adi_v5.c;h=2ddcfd35a157da1cb8429c4d2794463196a94a84;hp=c9254508a216e243d12c3afa7741c5c33e1b717f;hb=ca86cd6128b6b2753d4881dba2142179d56c454e;hpb=849f69b2e93d9c7330cb5a77efd1db12a450fd4c diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index c9254508a2..2ddcfd35a1 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -75,6 +75,7 @@ #include "jtag/interface.h" #include "arm.h" #include "arm_adi_v5.h" +#include #include #include @@ -739,10 +740,9 @@ static const char *class_description[16] = { "Generic IP component", "PrimeCell or System component" }; -static bool is_dap_cid_ok(uint32_t cid3, uint32_t cid2, uint32_t cid1, uint32_t cid0) +static bool is_dap_cid_ok(uint32_t cid) { - return cid3 == 0xb1 && cid2 == 0x05 - && ((cid1 & 0x0f) == 0) && cid0 == 0x0d; + return (cid & 0xffff0fff) == 0xb105000d; } /* @@ -876,6 +876,61 @@ int dap_lookup_cs_component(struct adiv5_ap *ap, return ERROR_OK; } +static int dap_read_part_id(struct adiv5_ap *ap, uint32_t component_base, uint32_t *cid, uint64_t *pid) +{ + assert((component_base & 0xFFF) == 0); + assert(ap != NULL && cid != NULL && pid != NULL); + + uint32_t cid0, cid1, cid2, cid3; + uint32_t pid0, pid1, pid2, pid3, pid4; + int retval; + + /* IDs are in last 4K section */ + retval = mem_ap_read_u32(ap, component_base + 0xFE0, &pid0); + if (retval != ERROR_OK) + return retval; + retval = mem_ap_read_u32(ap, component_base + 0xFE4, &pid1); + if (retval != ERROR_OK) + return retval; + retval = mem_ap_read_u32(ap, component_base + 0xFE8, &pid2); + if (retval != ERROR_OK) + return retval; + retval = mem_ap_read_u32(ap, component_base + 0xFEC, &pid3); + if (retval != ERROR_OK) + return retval; + retval = mem_ap_read_u32(ap, component_base + 0xFD0, &pid4); + if (retval != ERROR_OK) + return retval; + retval = mem_ap_read_u32(ap, component_base + 0xFF0, &cid0); + if (retval != ERROR_OK) + return retval; + retval = mem_ap_read_u32(ap, component_base + 0xFF4, &cid1); + if (retval != ERROR_OK) + return retval; + retval = mem_ap_read_u32(ap, component_base + 0xFF8, &cid2); + if (retval != ERROR_OK) + return retval; + retval = mem_ap_read_u32(ap, component_base + 0xFFC, &cid3); + if (retval != ERROR_OK) + return retval; + + retval = dap_run(ap->dap); + if (retval != ERROR_OK) + return retval; + + *cid = (cid3 & 0xff) << 24 + | (cid2 & 0xff) << 16 + | (cid1 & 0xff) << 8 + | (cid0 & 0xff); + *pid = (uint64_t)(pid4 & 0xff) << 32 + | (pid3 & 0xff) << 24 + | (pid2 & 0xff) << 16 + | (pid1 & 0xff) << 8 + | (pid0 & 0xff); + + return ERROR_OK; +} + /* The designer identity code is encoded as: * bits 11:8 : JEP106 Bank (number of continuation codes), only valid when bit 7 is 1. * bit 7 : Set when bits 6:0 represent a JEP106 ID and cleared when bits 6:0 represent @@ -976,10 +1031,9 @@ static const struct { static int dap_rom_display(struct command_context *cmd_ctx, struct adiv5_ap *ap, uint32_t dbgbase, int depth) { - struct adiv5_dap *dap = ap->dap; int retval; - uint32_t cid0, cid1, cid2, cid3, memtype, romentry; - uint16_t entry_offset; + uint64_t pid; + uint32_t cid; char tabs[7] = ""; if (depth > 16) { @@ -990,330 +1044,241 @@ static int dap_rom_display(struct command_context *cmd_ctx, if (depth) snprintf(tabs, sizeof(tabs), "[L%02d] ", depth); - /* bit 16 of apid indicates a memory access port */ - if (dbgbase & 0x02) - command_print(cmd_ctx, "\t%sValid ROM table present", tabs); - else - command_print(cmd_ctx, "\t%sROM table in legacy format", tabs); + uint32_t base_addr = dbgbase & 0xFFFFF000; + command_print(cmd_ctx, "\t\tComponent base address 0x%08" PRIx32, base_addr); - /* Now we read ROM table ID registers, ref. ARM IHI 0029B sec */ - retval = mem_ap_read_u32(ap, (dbgbase&0xFFFFF000) | 0xFF0, &cid0); - if (retval != ERROR_OK) - return retval; - retval = mem_ap_read_u32(ap, (dbgbase&0xFFFFF000) | 0xFF4, &cid1); - if (retval != ERROR_OK) - return retval; - retval = mem_ap_read_u32(ap, (dbgbase&0xFFFFF000) | 0xFF8, &cid2); - if (retval != ERROR_OK) - return retval; - retval = mem_ap_read_u32(ap, (dbgbase&0xFFFFF000) | 0xFFC, &cid3); - if (retval != ERROR_OK) - return retval; - retval = mem_ap_read_u32(ap, (dbgbase&0xFFFFF000) | 0xFCC, &memtype); - if (retval != ERROR_OK) - return retval; - retval = dap_run(dap); - if (retval != ERROR_OK) - return retval; + retval = dap_read_part_id(ap, base_addr, &cid, &pid); + if (retval != ERROR_OK) { + command_print(cmd_ctx, "\t\tCan't read component, the corresponding core might be turned off"); + return ERROR_OK; /* Don't abort recursion */ + } - if (!is_dap_cid_ok(cid3, cid2, cid1, cid0)) - command_print(cmd_ctx, "\t%sCID3 0x%02x" - ", CID2 0x%02x" - ", CID1 0x%02x" - ", CID0 0x%02x", - tabs, - (unsigned)cid3, (unsigned)cid2, - (unsigned)cid1, (unsigned)cid0); - if (memtype & 0x01) - command_print(cmd_ctx, "\t%sMEMTYPE system memory present on bus", tabs); - else - command_print(cmd_ctx, "\t%sMEMTYPE system memory not present: dedicated debug bus", tabs); + if (!is_dap_cid_ok(cid)) { + command_print(cmd_ctx, "\t\tInvalid CID 0x%08" PRIx32, cid); + return ERROR_OK; /* Don't abort recursion */ + } + + /* component may take multiple 4K pages */ + uint32_t size = (pid >> 36) & 0xf; + if (size > 0) + command_print(cmd_ctx, "\t\tStart address 0x%08" PRIx32, (uint32_t)(base_addr - 0x1000 * size)); + + command_print(cmd_ctx, "\t\tPeripheral ID 0x%010" PRIx64, pid); + + uint8_t class = (cid >> 12) & 0xf; + uint16_t part_num = pid & 0xfff; + uint16_t designer_id = ((pid >> 32) & 0xf) << 8 | ((pid >> 12) & 0xff); + + if (designer_id & 0x80) { + /* JEP106 code */ + command_print(cmd_ctx, "\t\tDesigner is 0x%03" PRIx16 ", %s", + designer_id, jep106_manufacturer(designer_id >> 8, designer_id & 0x7f)); + } else { + /* Legacy ASCII ID, clear invalid bits */ + designer_id &= 0x7f; + command_print(cmd_ctx, "\t\tDesigner ASCII code 0x%02" PRIx16 ", %s", + designer_id, designer_id == 0x41 ? "ARM" : ""); + } + + /* default values to be overwritten upon finding a match */ + const char *type = "Unrecognized"; + const char *full = ""; + + /* search dap_partnums[] array for a match */ + for (unsigned entry = 0; entry < ARRAY_SIZE(dap_partnums); entry++) { + + if ((dap_partnums[entry].designer_id != designer_id) && (dap_partnums[entry].designer_id != ANY_ID)) + continue; + + if (dap_partnums[entry].part_num != part_num) + continue; + + type = dap_partnums[entry].type; + full = dap_partnums[entry].full; + break; + } + + command_print(cmd_ctx, "\t\tPart is 0x%" PRIx16", %s %s", part_num, type, full); + command_print(cmd_ctx, "\t\tComponent class is 0x%" PRIx8 ", %s", class, class_description[class]); - /* Now we read ROM table entries from dbgbase&0xFFFFF000) | 0x000 until we get 0x00000000 */ - for (entry_offset = 0; ; entry_offset += 4) { - retval = mem_ap_read_atomic_u32(ap, (dbgbase&0xFFFFF000) | entry_offset, &romentry); + if (class == 1) { /* ROM Table */ + uint32_t memtype; + retval = mem_ap_read_atomic_u32(ap, base_addr | 0xFCC, &memtype); if (retval != ERROR_OK) return retval; - command_print(cmd_ctx, "\t%sROMTABLE[0x%x] = 0x%" PRIx32 "", - tabs, entry_offset, romentry); - if (romentry & 0x01) { - uint32_t c_cid0, c_cid1, c_cid2, c_cid3; - uint32_t c_pid0, c_pid1, c_pid2, c_pid3, c_pid4; - uint32_t component_base; - uint16_t part_num, designer_id; - const char *type, *full; - - component_base = (dbgbase & 0xFFFFF000) + (romentry & 0xFFFFF000); - - /* IDs are in last 4K section */ - retval = mem_ap_read_atomic_u32(ap, component_base + 0xFE0, &c_pid0); - if (retval != ERROR_OK) { - command_print(cmd_ctx, "\t%s\tCan't read component with base address 0x%" PRIx32 - ", the corresponding core might be turned off", tabs, component_base); - continue; - } - c_pid0 &= 0xff; - retval = mem_ap_read_atomic_u32(ap, component_base + 0xFE4, &c_pid1); - if (retval != ERROR_OK) - return retval; - c_pid1 &= 0xff; - retval = mem_ap_read_atomic_u32(ap, component_base + 0xFE8, &c_pid2); - if (retval != ERROR_OK) - return retval; - c_pid2 &= 0xff; - retval = mem_ap_read_atomic_u32(ap, component_base + 0xFEC, &c_pid3); - if (retval != ERROR_OK) - return retval; - c_pid3 &= 0xff; - retval = mem_ap_read_atomic_u32(ap, component_base + 0xFD0, &c_pid4); - if (retval != ERROR_OK) - return retval; - c_pid4 &= 0xff; - retval = mem_ap_read_atomic_u32(ap, component_base + 0xFF0, &c_cid0); - if (retval != ERROR_OK) - return retval; - c_cid0 &= 0xff; - retval = mem_ap_read_atomic_u32(ap, component_base + 0xFF4, &c_cid1); - if (retval != ERROR_OK) - return retval; - c_cid1 &= 0xff; - retval = mem_ap_read_atomic_u32(ap, component_base + 0xFF8, &c_cid2); - if (retval != ERROR_OK) - return retval; - c_cid2 &= 0xff; - retval = mem_ap_read_atomic_u32(ap, component_base + 0xFFC, &c_cid3); + if (memtype & 0x01) + command_print(cmd_ctx, "\t\tMEMTYPE system memory present on bus"); + else + command_print(cmd_ctx, "\t\tMEMTYPE system memory not present: dedicated debug bus"); + + /* Read ROM table entries from base address until we get 0x00000000 or reach the reserved area */ + for (uint16_t entry_offset = 0; entry_offset < 0xF00; entry_offset += 4) { + uint32_t romentry; + retval = mem_ap_read_atomic_u32(ap, base_addr | entry_offset, &romentry); if (retval != ERROR_OK) return retval; - c_cid3 &= 0xff; - - command_print(cmd_ctx, "\t\tComponent base address 0x%" PRIx32 ", " - "start address 0x%" PRIx32, component_base, - /* component may take multiple 4K pages */ - (uint32_t)(component_base - 0x1000*(c_pid4 >> 4))); - command_print(cmd_ctx, "\t\tComponent class is 0x%" PRIx8 ", %s", - (uint8_t)((c_cid1 >> 4) & 0xf), - /* See ARM IHI 0029B Table 3-3 */ - class_description[(c_cid1 >> 4) & 0xf]); - - /* CoreSight component? */ - if (((c_cid1 >> 4) & 0x0f) == 9) { - uint32_t devtype; - unsigned minor; - const char *major = "Reserved", *subtype = "Reserved"; - - retval = mem_ap_read_atomic_u32(ap, - (component_base & 0xfffff000) | 0xfcc, - &devtype); + command_print(cmd_ctx, "\t%sROMTABLE[0x%x] = 0x%" PRIx32 "", + tabs, entry_offset, romentry); + if (romentry & 0x01) { + /* Recurse */ + retval = dap_rom_display(cmd_ctx, ap, base_addr + (romentry & 0xFFFFF000), depth + 1); if (retval != ERROR_OK) return retval; - minor = (devtype >> 4) & 0x0f; - switch (devtype & 0x0f) { - 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 = "Perfomance 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_ctx, "\t\tType is 0x%02" PRIx8 ", %s, %s", - (uint8_t)(devtype & 0xff), - major, subtype); - /* REVISIT also show 0xfc8 DevId */ + } else if (romentry != 0) { + command_print(cmd_ctx, "\t\tComponent not present"); + } else { + command_print(cmd_ctx, "\t%s\tEnd of ROM table", tabs); + break; } + } + } else if (class == 9) { /* CoreSight component */ + const char *major = "Reserved", *subtype = "Reserved"; - if (!is_dap_cid_ok(cid3, cid2, cid1, cid0)) - command_print(cmd_ctx, - "\t\tCID3 0%02x" - ", CID2 0%02x" - ", CID1 0%02x" - ", CID0 0%02x", - (int)c_cid3, - (int)c_cid2, - (int)c_cid1, - (int)c_cid0); - command_print(cmd_ctx, - "\t\tPeripheral ID[4..0] = hex " - "%02x %02x %02x %02x %02x", - (int)c_pid4, (int)c_pid3, (int)c_pid2, - (int)c_pid1, (int)c_pid0); - - part_num = (c_pid0 & 0xff); - part_num |= (c_pid1 & 0x0f) << 8; - designer_id = (c_pid1 & 0xf0) >> 4; - designer_id |= (c_pid2 & 0x0f) << 4; - designer_id |= (c_pid4 & 0x0f) << 8; - if ((designer_id & 0x80) == 0) { - /* Legacy ASCII ID, clear invalid bits */ - designer_id &= 0x7f; + uint32_t devtype; + retval = mem_ap_read_atomic_u32(ap, base_addr | 0xFCC, &devtype); + if (retval != ERROR_OK) + return retval; + unsigned minor = (devtype >> 4) & 0x0f; + switch (devtype & 0x0f) { + case 0: + major = "Miscellaneous"; + switch (minor) { + case 0: + subtype = "other"; + break; + case 4: + subtype = "Validation component"; + break; } - - /* default values to be overwritten upon finding a match */ - type = NULL; - full = ""; - - /* search dap_partnums[] array for a match */ - unsigned entry; - for (entry = 0; entry < ARRAY_SIZE(dap_partnums); entry++) { - - if ((dap_partnums[entry].designer_id != designer_id) && (dap_partnums[entry].designer_id != ANY_ID)) - continue; - - if (dap_partnums[entry].part_num != part_num) - continue; - - type = dap_partnums[entry].type; - full = dap_partnums[entry].full; + 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; } - - if (type) { - command_print(cmd_ctx, "\t\tPart is %s %s", - type, full); - } else { - command_print(cmd_ctx, "\t\tUnrecognized (Part 0x%" PRIx16 ", designer 0x%" PRIx16 ")", - part_num, designer_id); + 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; } - - /* ROM Table? */ - if (((c_cid1 >> 4) & 0x0f) == 1) { - retval = dap_rom_display(cmd_ctx, ap, component_base, depth + 1); - if (retval != ERROR_OK) - return retval; + 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; } - } else { - if (romentry) - command_print(cmd_ctx, "\t\tComponent not present"); - else + 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 = "Perfomance 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_ctx, "\t\tType is 0x%02" PRIx8 ", %s, %s", + (uint8_t)(devtype & 0xff), + major, subtype); + /* REVISIT also show 0xfc8 DevId */ } - command_print(cmd_ctx, "\t%s\tEnd of ROM table", tabs); + return ERROR_OK; } @@ -1322,7 +1287,6 @@ static int dap_info_command(struct command_context *cmd_ctx, { int retval; uint32_t dbgbase, apid; - int romtable_present = 0; uint8_t mem_ap; /* Now we read ROM table ID registers, ref. ARM IHI 0029B sec */ @@ -1361,11 +1325,16 @@ static int dap_info_command(struct command_context *cmd_ctx, if (mem_ap) { command_print(cmd_ctx, "MEM-AP BASE 0x%8.8" PRIx32, dbgbase); - romtable_present = dbgbase != 0xFFFFFFFF; - if (romtable_present) - dap_rom_display(cmd_ctx, ap, dbgbase, 0); - else + if (dbgbase == 0xFFFFFFFF || (dbgbase & 0x3) == 0x2) { command_print(cmd_ctx, "\tNo ROM table present"); + } else { + if (dbgbase & 0x01) + command_print(cmd_ctx, "\tValid ROM table present"); + else + command_print(cmd_ctx, "\tROM table in legacy format"); + + dap_rom_display(cmd_ctx, ap, dbgbase & 0xFFFFF000, 0); + } } return ERROR_OK;