X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farm_adi_v5.c;h=134168e2934cd13afa0614f10a2e9a3f5782ee09;hp=a28bc154485e568fb5eadb8b9c938e73e9732f4d;hb=9ad6ebc89a702a3af8947605800b2eeb816e9ba7;hpb=e7d165f3dbff0fbe11f458becdccbb3d4fa8ccc4 diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index a28bc15448..134168e293 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -75,7 +75,9 @@ #include "jtag/interface.h" #include "arm.h" #include "arm_adi_v5.h" +#include #include +#include /* ARM ADI Specification requires at least 10 bits used for TAR autoincrement */ @@ -94,28 +96,6 @@ static uint32_t max_tar_block_size(uint32_t tar_autoincr_block, uint32_t address * * ***************************************************************************/ -/** - * Select one of the APs connected to the specified DAP. The - * selection is implicitly used with future AP transactions. - * This is a NOP if the specified AP is already selected. - * - * @param dap The DAP - * @param apsel Number of the AP to (implicitly) use with further - * transactions. This normally identifies a MEM-AP. - */ -void dap_ap_select(struct adiv5_dap *dap, uint8_t ap) -{ - uint32_t new_ap = (ap << 24) & 0xFF000000; - - if (new_ap != dap->ap_current) { - dap->ap_current = new_ap; - /* Switching AP invalidates cached values. - * Values MUST BE UPDATED BEFORE AP ACCESS. - */ - dap->ap_bank_value = -1; - } -} - static int mem_ap_setup_csw(struct adiv5_ap *ap, uint32_t csw) { csw = csw | CSW_DBGSWENABLE | CSW_MASTER_DEBUG | CSW_HPROT | @@ -123,7 +103,7 @@ static int mem_ap_setup_csw(struct adiv5_ap *ap, uint32_t csw) if (csw != ap->csw_value) { /* LOG_DEBUG("DAP: Set CSW %x",csw); */ - int retval = dap_queue_ap_write(ap->dap, MEM_AP_REG_CSW, csw); + int retval = dap_queue_ap_write(ap, MEM_AP_REG_CSW, csw); if (retval != ERROR_OK) return retval; ap->csw_value = csw; @@ -136,7 +116,7 @@ static int mem_ap_setup_tar(struct adiv5_ap *ap, uint32_t tar) if (tar != ap->tar_value || (ap->csw_value & CSW_ADDRINC_MASK)) { /* LOG_DEBUG("DAP: Set TAR %x",tar); */ - int retval = dap_queue_ap_write(ap->dap, MEM_AP_REG_TAR, tar); + int retval = dap_queue_ap_write(ap, MEM_AP_REG_TAR, tar); if (retval != ERROR_OK) return retval; ap->tar_value = tar; @@ -189,8 +169,6 @@ int mem_ap_read_u32(struct adiv5_ap *ap, uint32_t address, { int retval; - dap_ap_select(ap->dap, ap->ap_num); - /* Use banked addressing (REG_BDx) to avoid some link traffic * (updating TAR) when reading several consecutive addresses. */ @@ -199,7 +177,7 @@ int mem_ap_read_u32(struct adiv5_ap *ap, uint32_t address, if (retval != ERROR_OK) return retval; - return dap_queue_ap_read(ap->dap, MEM_AP_REG_BD0 | (address & 0xC), value); + return dap_queue_ap_read(ap, MEM_AP_REG_BD0 | (address & 0xC), value); } /** @@ -242,8 +220,6 @@ int mem_ap_write_u32(struct adiv5_ap *ap, uint32_t address, { int retval; - dap_ap_select(ap->dap, ap->ap_num); - /* Use banked addressing (REG_BDx) to avoid some link traffic * (updating TAR) when writing several consecutive addresses. */ @@ -252,7 +228,7 @@ int mem_ap_write_u32(struct adiv5_ap *ap, uint32_t address, if (retval != ERROR_OK) return retval; - return dap_queue_ap_write(ap->dap, MEM_AP_REG_BD0 | (address & 0xC), + return dap_queue_ap_write(ap, MEM_AP_REG_BD0 | (address & 0xC), value); } @@ -329,8 +305,6 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz if (ap->unaligned_access_bad && (address % size != 0)) return ERROR_TARGET_UNALIGNED_ACCESS; - dap_ap_select(ap->dap, ap->ap_num); - retval = mem_ap_setup_tar(ap, address ^ addr_xor); if (retval != ERROR_OK) return retval; @@ -383,7 +357,7 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz nbytes -= this_size; - retval = dap_queue_ap_write(dap, MEM_AP_REG_DRW, outvalue); + retval = dap_queue_ap_write(ap, MEM_AP_REG_DRW, outvalue); if (retval != ERROR_OK) break; @@ -401,7 +375,7 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz if (retval != ERROR_OK) { uint32_t tar; - if (dap_queue_ap_read(dap, MEM_AP_REG_TAR, &tar) == ERROR_OK + if (dap_queue_ap_read(ap, MEM_AP_REG_TAR, &tar) == ERROR_OK && dap_run(dap) == ERROR_OK) LOG_ERROR("Failed to write memory at 0x%08"PRIx32, tar); else @@ -462,8 +436,6 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint return ERROR_FAIL; } - dap_ap_select(ap->dap, ap->ap_num); - retval = mem_ap_setup_tar(ap, address); if (retval != ERROR_OK) { free(read_buf); @@ -487,7 +459,7 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint if (retval != ERROR_OK) break; - retval = dap_queue_ap_read(dap, MEM_AP_REG_DRW, read_ptr++); + retval = dap_queue_ap_read(ap, MEM_AP_REG_DRW, read_ptr++); if (retval != ERROR_OK) break; @@ -514,7 +486,7 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint * at least give the caller what we have. */ if (retval != ERROR_OK) { uint32_t tar; - if (dap_queue_ap_read(dap, MEM_AP_REG_TAR, &tar) == ERROR_OK + if (dap_queue_ap_read(ap, MEM_AP_REG_TAR, &tar) == ERROR_OK && dap_run(dap) == ERROR_OK) { LOG_ERROR("Failed to read memory at 0x%08"PRIx32, tar); if (nbytes > tar - address) @@ -616,9 +588,7 @@ struct adiv5_dap *dap_init(void) /* Number of bits for tar autoincrement, impl. dep. at least 10 */ dap->ap[i].tar_autoincr_block = (1<<10); } - dap->ap_current = -1; - dap->ap_bank_value = -1; - dap->dp_bank_value = -1; + INIT_LIST_HEAD(&dap->cmd_journal); return dap; } @@ -641,15 +611,12 @@ int dap_dp_init(struct adiv5_dap *dap) if (!dap->ops) dap->ops = &jtag_dp_ops; - dap->ap_current = -1; - dap->ap_bank_value = -1; + dap->select = DP_SELECT_INVALID; dap->last_read = NULL; for (size_t i = 0; i < 10; i++) { /* DP initialization */ - dap->dp_bank_value = 0; - retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); if (retval != ERROR_OK) continue; @@ -719,17 +686,15 @@ int mem_ap_init(struct adiv5_ap *ap) int retval; struct adiv5_dap *dap = ap->dap; - dap_ap_select(dap, ap->ap_num); - retval = mem_ap_setup_transfer(ap, CSW_8BIT | CSW_ADDRINC_PACKED, 0); if (retval != ERROR_OK) return retval; - retval = dap_queue_ap_read(dap, MEM_AP_REG_CSW, &csw); + retval = dap_queue_ap_read(ap, MEM_AP_REG_CSW, &csw); if (retval != ERROR_OK) return retval; - retval = dap_queue_ap_read(dap, MEM_AP_REG_CFG, &cfg); + retval = dap_queue_ap_read(ap, MEM_AP_REG_CFG, &cfg); if (retval != ERROR_OK) return retval; @@ -775,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; } /* @@ -793,9 +757,8 @@ int dap_find_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adiv5_a /* read the IDR register of the Access Port */ uint32_t id_val = 0; - dap_ap_select(dap, ap_num); - int retval = dap_queue_ap_read(dap, AP_REG_IDR, &id_val); + int retval = dap_queue_ap_read(dap_ap(dap, ap_num), AP_REG_IDR, &id_val); if (retval != ERROR_OK) return retval; @@ -844,12 +807,10 @@ int dap_get_debugbase(struct adiv5_ap *ap, struct adiv5_dap *dap = ap->dap; int retval; - dap_ap_select(dap, ap->ap_num); - - retval = dap_queue_ap_read(dap, MEM_AP_REG_BASE, dbgbase); + retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE, dbgbase); if (retval != ERROR_OK) return retval; - retval = dap_queue_ap_read(dap, AP_REG_IDR, apid); + retval = dap_queue_ap_read(ap, AP_REG_IDR, apid); if (retval != ERROR_OK) return retval; retval = dap_run(dap); @@ -915,473 +876,428 @@ int dap_lookup_cs_component(struct adiv5_ap *ap, return ERROR_OK; } -static int dap_rom_display(struct command_context *cmd_ctx, - struct adiv5_ap *ap, uint32_t dbgbase, int depth) +static int dap_read_part_id(struct adiv5_ap *ap, uint32_t component_base, uint32_t *cid, uint64_t *pid) { - struct adiv5_dap *dap = ap->dap; - int retval; - uint32_t cid0, cid1, cid2, cid3, memtype, romentry; - uint16_t entry_offset; - char tabs[7] = ""; + assert((component_base & 0xFFF) == 0); + assert(ap != NULL && cid != NULL && pid != NULL); - if (depth > 16) { - command_print(cmd_ctx, "\tTables too deep"); - return ERROR_FAIL; - } - - 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 cid0, cid1, cid2, cid3; + uint32_t pid0, pid1, pid2, pid3, pid4; + int retval; - /* Now we read ROM table ID registers, ref. ARM IHI 0029B sec */ - retval = mem_ap_read_u32(ap, (dbgbase&0xFFFFF000) | 0xFF0, &cid0); + /* 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, (dbgbase&0xFFFFF000) | 0xFF4, &cid1); + retval = mem_ap_read_u32(ap, component_base + 0xFE4, &pid1); if (retval != ERROR_OK) return retval; - retval = mem_ap_read_u32(ap, (dbgbase&0xFFFFF000) | 0xFF8, &cid2); + retval = mem_ap_read_u32(ap, component_base + 0xFE8, &pid2); if (retval != ERROR_OK) return retval; - retval = mem_ap_read_u32(ap, (dbgbase&0xFFFFF000) | 0xFFC, &cid3); + retval = mem_ap_read_u32(ap, component_base + 0xFEC, &pid3); if (retval != ERROR_OK) return retval; - retval = mem_ap_read_u32(ap, (dbgbase&0xFFFFF000) | 0xFCC, &memtype); + retval = mem_ap_read_u32(ap, component_base + 0xFD0, &pid4); if (retval != ERROR_OK) return retval; - retval = dap_run(dap); + 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; - 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); + 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 + * a legacy ASCII Identity Code. + * bits 6:0 : JEP106 Identity Code (without parity) or legacy ASCII code according to bit 7. + * JEP106 is a standard available from jedec.org + */ + +/* Part number interpretations are from Cortex + * core specs, the CoreSight components TRM + * (ARM DDI 0314H), CoreSight System Design + * Guide (ARM DGI 0012D) and ETM specs; also + * from chip observation (e.g. TI SDTI). + */ + +/* The legacy code only used the part number field to identify CoreSight peripherals. + * This meant that the same part number from two different manufacturers looked the same. + * It is desirable for all future additions to identify with both part number and JEP106. + * "ANY_ID" is a wildcard (any JEP106) only to preserve legacy behavior for legacy entries. + */ + +#define ANY_ID 0x1000 + +#define ARM_ID 0x4BB + +static const struct { + uint16_t designer_id; + uint16_t part_num; + const char *type; + const char *full; +} dap_partnums[] = { + { ARM_ID, 0x000, "Cortex-M3 SCS", "(System Control Space)", }, + { ARM_ID, 0x001, "Cortex-M3 ITM", "(Instrumentation Trace Module)", }, + { ARM_ID, 0x002, "Cortex-M3 DWT", "(Data Watchpoint and Trace)", }, + { ARM_ID, 0x003, "Cortex-M3 FPB", "(Flash Patch and Breakpoint)", }, + { ARM_ID, 0x008, "Cortex-M0 SCS", "(System Control Space)", }, + { ARM_ID, 0x00a, "Cortex-M0 DWT", "(Data Watchpoint and Trace)", }, + { ARM_ID, 0x00b, "Cortex-M0 BPU", "(Breakpoint Unit)", }, + { ARM_ID, 0x00c, "Cortex-M4 SCS", "(System Control Space)", }, + { ARM_ID, 0x00d, "CoreSight ETM11", "(Embedded Trace)", }, + { ARM_ID, 0x00e, "Cortex-M7 FPB", "(Flash Patch and Breakpoint)", }, + { ARM_ID, 0x490, "Cortex-A15 GIC", "(Generic Interrupt Controller)", }, + { ARM_ID, 0x4a1, "Cortex-A53 ROM", "(v8 Memory Map ROM Table)", }, + { ARM_ID, 0x4a2, "Cortex-A57 ROM", "(ROM Table)", }, + { ARM_ID, 0x4a3, "Cortex-A53 ROM", "(v7 Memory Map ROM Table)", }, + { ARM_ID, 0x4a4, "Cortex-A72 ROM", "(ROM Table)", }, + { ARM_ID, 0x4af, "Cortex-A15 ROM", "(ROM Table)", }, + { ARM_ID, 0x4c0, "Cortex-M0+ ROM", "(ROM Table)", }, + { ARM_ID, 0x4c3, "Cortex-M3 ROM", "(ROM Table)", }, + { ARM_ID, 0x4c4, "Cortex-M4 ROM", "(ROM Table)", }, + { ARM_ID, 0x4c7, "Cortex-M7 PPB ROM", "(Private Peripheral Bus ROM Table)", }, + { ARM_ID, 0x4c8, "Cortex-M7 ROM", "(ROM Table)", }, + { ARM_ID, 0x470, "Cortex-M1 ROM", "(ROM Table)", }, + { ARM_ID, 0x471, "Cortex-M0 ROM", "(ROM Table)", }, + { ARM_ID, 0x906, "CoreSight CTI", "(Cross Trigger)", }, + { ARM_ID, 0x907, "CoreSight ETB", "(Trace Buffer)", }, + { ARM_ID, 0x908, "CoreSight CSTF", "(Trace Funnel)", }, + { ARM_ID, 0x909, "CoreSight ATBR", "(Advanced Trace Bus Replicator)", }, + { ARM_ID, 0x910, "CoreSight ETM9", "(Embedded Trace)", }, + { ARM_ID, 0x912, "CoreSight TPIU", "(Trace Port Interface Unit)", }, + { ARM_ID, 0x913, "CoreSight ITM", "(Instrumentation Trace Macrocell)", }, + { ARM_ID, 0x914, "CoreSight SWO", "(Single Wire Output)", }, + { ARM_ID, 0x917, "CoreSight HTM", "(AHB Trace Macrocell)", }, + { ARM_ID, 0x920, "CoreSight ETM11", "(Embedded Trace)", }, + { ARM_ID, 0x921, "Cortex-A8 ETM", "(Embedded Trace)", }, + { ARM_ID, 0x922, "Cortex-A8 CTI", "(Cross Trigger)", }, + { ARM_ID, 0x923, "Cortex-M3 TPIU", "(Trace Port Interface Unit)", }, + { ARM_ID, 0x924, "Cortex-M3 ETM", "(Embedded Trace)", }, + { ARM_ID, 0x925, "Cortex-M4 ETM", "(Embedded Trace)", }, + { ARM_ID, 0x930, "Cortex-R4 ETM", "(Embedded Trace)", }, + { ARM_ID, 0x931, "Cortex-R5 ETM", "(Embedded Trace)", }, + { ARM_ID, 0x932, "CoreSight MTB-M0+", "(Micro Trace Buffer)", }, + { ARM_ID, 0x941, "CoreSight TPIU-Lite", "(Trace Port Interface Unit)", }, + { ARM_ID, 0x950, "Cortex-A9 PTM", "(Program Trace Macrocell)", }, + { ARM_ID, 0x955, "Cortex-A5 ETM", "(Embedded Trace)", }, + { ARM_ID, 0x95a, "Cortex-A72 ETM", "(Embedded Trace)", }, + { ARM_ID, 0x95b, "Cortex-A17 PTM", "(Program Trace Macrocell)", }, + { ARM_ID, 0x95d, "Cortex-A53 ETM", "(Embedded Trace)", }, + { ARM_ID, 0x95e, "Cortex-A57 ETM", "(Embedded Trace)", }, + { ARM_ID, 0x95f, "Cortex-A15 PTM", "(Program Trace Macrocell)", }, + { ARM_ID, 0x961, "CoreSight TMC", "(Trace Memory Controller)", }, + { ARM_ID, 0x962, "CoreSight STM", "(System Trace Macrocell)", }, + { ARM_ID, 0x975, "Cortex-M7 ETM", "(Embedded Trace)", }, + { ARM_ID, 0x9a0, "CoreSight PMU", "(Performance Monitoring Unit)", }, + { ARM_ID, 0x9a1, "Cortex-M4 TPIU", "(Trace Port Interface Unit)", }, + { ARM_ID, 0x9a4, "CoreSight GPR", "(Granular Power Requester)", }, + { ARM_ID, 0x9a5, "Cortex-A5 PMU", "(Performance Monitor Unit)", }, + { ARM_ID, 0x9a7, "Cortex-A7 PMU", "(Performance Monitor Unit)", }, + { ARM_ID, 0x9a8, "Cortex-A53 CTI", "(Cross Trigger)", }, + { ARM_ID, 0x9a9, "Cortex-M7 TPIU", "(Trace Port Interface Unit)", }, + { ARM_ID, 0x9ae, "Cortex-A17 PMU", "(Performance Monitor Unit)", }, + { ARM_ID, 0x9af, "Cortex-A15 PMU", "(Performance Monitor Unit)", }, + { ARM_ID, 0x9b7, "Cortex-R7 PMU", "(Performance Monitoring Unit)", }, + { ARM_ID, 0x9d3, "Cortex-A53 PMU", "(Performance Monitor Unit)", }, + { ARM_ID, 0x9d7, "Cortex-A57 PMU", "(Performance Monitor Unit)", }, + { ARM_ID, 0x9d8, "Cortex-A72 PMU", "(Performance Monitor Unit)", }, + { ARM_ID, 0xc05, "Cortex-A5 Debug", "(Debug Unit)", }, + { ARM_ID, 0xc07, "Cortex-A7 Debug", "(Debug Unit)", }, + { ARM_ID, 0xc08, "Cortex-A8 Debug", "(Debug Unit)", }, + { ARM_ID, 0xc09, "Cortex-A9 Debug", "(Debug Unit)", }, + { ARM_ID, 0xc0e, "Cortex-A17 Debug", "(Debug Unit)", }, + { ARM_ID, 0xc0f, "Cortex-A15 Debug", "(Debug Unit)", }, + { ARM_ID, 0xc14, "Cortex-R4 Debug", "(Debug Unit)", }, + { ARM_ID, 0xc15, "Cortex-R5 Debug", "(Debug Unit)", }, + { ARM_ID, 0xc17, "Cortex-R7 Debug", "(Debug Unit)", }, + { ARM_ID, 0xd03, "Cortex-A53 Debug", "(Debug Unit)", }, + { ARM_ID, 0xd07, "Cortex-A57 Debug", "(Debug Unit)", }, + { ARM_ID, 0xd08, "Cortex-A72 Debug", "(Debug Unit)", }, + { 0x09f, 0xcd0, "Atmel CPU with DSU", "(CPU)" }, + { 0x0E5, 0x000, "SHARC+/Blackfin+", "", }, + { 0x0F0, 0x440, "Qualcomm QDSS Component v1", "(Qualcomm Designed CoreSight Component v1)", }, + /* legacy comment: 0x113: what? */ + { ANY_ID, 0x120, "TI SDTI", "(System Debug Trace Interface)", }, /* from OMAP3 memmap */ + { ANY_ID, 0x343, "TI DAPCTL", "", }, /* from OMAP3 memmap */ +}; + +static int dap_rom_display(struct command_context *cmd_ctx, + struct adiv5_ap *ap, uint32_t dbgbase, int depth) +{ + int retval; + uint64_t pid; + uint32_t cid; + char tabs[7] = ""; + + if (depth > 16) { + command_print(cmd_ctx, "\tTables too deep"); + return ERROR_FAIL; + } + + if (depth) + snprintf(tabs, sizeof(tabs), "[L%02d] ", depth); + + uint32_t base_addr = dbgbase & 0xFFFFF000; + command_print(cmd_ctx, "\t\tComponent base address 0x%08" PRIx32, base_addr); + + 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(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; - /* 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); + 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]); + + 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; - uint32_t part_num; - 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 number interpretations are from Cortex - * core specs, the CoreSight components TRM - * (ARM DDI 0314H), CoreSight System Design - * Guide (ARM DGI 0012D) and ETM specs; also - * from chip observation (e.g. TI SDTI). - */ - part_num = (c_pid0 & 0xff); - part_num |= (c_pid1 & 0x0f) << 8; - switch (part_num) { - case 0x000: - type = "Cortex-M3 NVIC"; - full = "(Interrupt Controller)"; - break; - case 0x001: - type = "Cortex-M3 ITM"; - full = "(Instrumentation Trace Module)"; - break; - case 0x002: - type = "Cortex-M3 DWT"; - full = "(Data Watchpoint and Trace)"; - break; - case 0x003: - type = "Cortex-M3 FBP"; - full = "(Flash Patch and Breakpoint)"; - break; - case 0x008: - type = "Cortex-M0 SCS"; - full = "(System Control Space)"; - break; - case 0x00a: - type = "Cortex-M0 DWT"; - full = "(Data Watchpoint and Trace)"; + 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 0x00b: - type = "Cortex-M0 BPU"; - full = "(Breakpoint Unit)"; + case 4: + subtype = "Validation component"; break; - case 0x00c: - type = "Cortex-M4 SCS"; - full = "(System Control Space)"; + } + break; + case 1: + major = "Trace Sink"; + switch (minor) { + case 0: + subtype = "other"; break; - case 0x00d: - type = "CoreSight ETM11"; - full = "(Embedded Trace)"; + case 1: + subtype = "Port"; break; - /* case 0x113: what? */ - case 0x120: /* from OMAP3 memmap */ - type = "TI SDTI"; - full = "(System Debug Trace Interface)"; + case 2: + subtype = "Buffer"; break; - case 0x343: /* from OMAP3 memmap */ - type = "TI DAPCTL"; - full = ""; + case 3: + subtype = "Router"; break; - case 0x906: - type = "Coresight CTI"; - full = "(Cross Trigger)"; + } + break; + case 2: + major = "Trace Link"; + switch (minor) { + case 0: + subtype = "other"; break; - case 0x907: - type = "Coresight ETB"; - full = "(Trace Buffer)"; + case 1: + subtype = "Funnel, router"; break; - case 0x908: - type = "Coresight CSTF"; - full = "(Trace Funnel)"; + case 2: + subtype = "Filter"; break; - case 0x910: - type = "CoreSight ETM9"; - full = "(Embedded Trace)"; + case 3: + subtype = "FIFO, buffer"; break; - case 0x912: - type = "Coresight TPIU"; - full = "(Trace Port Interface Unit)"; + } + break; + case 3: + major = "Trace Source"; + switch (minor) { + case 0: + subtype = "other"; break; - case 0x913: - type = "Coresight ITM"; - full = "(Instrumentation Trace Macrocell)"; + case 1: + subtype = "Processor"; break; - case 0x914: - type = "Coresight SWO"; - full = "(Single Wire Output)"; + case 2: + subtype = "DSP"; break; - case 0x917: - type = "Coresight HTM"; - full = "(AHB Trace Macrocell)"; + case 3: + subtype = "Engine/Coprocessor"; break; - case 0x920: - type = "CoreSight ETM11"; - full = "(Embedded Trace)"; + case 4: + subtype = "Bus"; break; - case 0x921: - type = "Cortex-A8 ETM"; - full = "(Embedded Trace)"; + case 6: + subtype = "Software"; break; - case 0x922: - type = "Cortex-A8 CTI"; - full = "(Cross Trigger)"; + } + break; + case 4: + major = "Debug Control"; + switch (minor) { + case 0: + subtype = "other"; break; - case 0x923: - type = "Cortex-M3 TPIU"; - full = "(Trace Port Interface Unit)"; + case 1: + subtype = "Trigger Matrix"; break; - case 0x924: - type = "Cortex-M3 ETM"; - full = "(Embedded Trace)"; + case 2: + subtype = "Debug Auth"; break; - case 0x925: - type = "Cortex-M4 ETM"; - full = "(Embedded Trace)"; + case 3: + subtype = "Power Requestor"; break; - case 0x930: - type = "Cortex-R4 ETM"; - full = "(Embedded Trace)"; + } + break; + case 5: + major = "Debug Logic"; + switch (minor) { + case 0: + subtype = "other"; break; - case 0x950: - type = "CoreSight Component"; - full = "(unidentified Cortex-A9 component)"; + case 1: + subtype = "Processor"; break; - case 0x961: - type = "CoreSight TMC"; - full = "(Trace Memory Controller)"; + case 2: + subtype = "DSP"; break; - case 0x962: - type = "CoreSight STM"; - full = "(System Trace Macrocell)"; + case 3: + subtype = "Engine/Coprocessor"; break; - case 0x9a0: - type = "CoreSight PMU"; - full = "(Performance Monitoring Unit)"; + case 4: + subtype = "Bus"; break; - case 0x9a1: - type = "Cortex-M4 TPUI"; - full = "(Trace Port Interface Unit)"; + case 5: + subtype = "Memory"; break; - case 0x9a5: - type = "Cortex-A5 ETM"; - full = "(Embedded Trace)"; + } + break; + case 6: + major = "Perfomance Monitor"; + switch (minor) { + case 0: + subtype = "other"; break; - case 0xc05: - type = "Cortex-A5 Debug"; - full = "(Debug Unit)"; + case 1: + subtype = "Processor"; break; - case 0xc08: - type = "Cortex-A8 Debug"; - full = "(Debug Unit)"; + case 2: + subtype = "DSP"; break; - case 0xc09: - type = "Cortex-A9 Debug"; - full = "(Debug Unit)"; + case 3: + subtype = "Engine/Coprocessor"; break; - case 0x4af: - type = "Cortex-A15 Debug"; - full = "(Debug Unit)"; + case 4: + subtype = "Bus"; break; - default: - LOG_DEBUG("Unrecognized Part number 0x%" PRIx32, part_num); - type = "-*- unrecognized -*-"; - full = ""; + case 5: + subtype = "Memory"; break; } - command_print(cmd_ctx, "\t\tPart is %s %s", - type, full); - - /* 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; - } - } else { - if (romentry) - command_print(cmd_ctx, "\t\tComponent not present"); - else - 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; } @@ -1390,7 +1306,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 */ @@ -1429,11 +1344,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; @@ -1485,14 +1405,12 @@ COMMAND_HANDLER(dap_baseaddr_command) return ERROR_COMMAND_SYNTAX_ERROR; } - dap_ap_select(dap, apsel); - /* NOTE: assumes we're talking to a MEM-AP, which * has a base address. There are other kinds of AP, * though they're not common for now. This should * use the ID register to verify it's a MEM-AP. */ - retval = dap_queue_ap_read(dap, MEM_AP_REG_BASE, &baseaddr); + retval = dap_queue_ap_read(dap_ap(dap, apsel), MEM_AP_REG_BASE, &baseaddr); if (retval != ERROR_OK) return retval; retval = dap_run(dap); @@ -1541,7 +1459,7 @@ COMMAND_HANDLER(dap_apsel_command) switch (CMD_ARGC) { case 0: - apsel = 0; + apsel = dap->apsel; break; case 1: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel); @@ -1554,9 +1472,8 @@ COMMAND_HANDLER(dap_apsel_command) } dap->apsel = apsel; - dap_ap_select(dap, apsel); - retval = dap_queue_ap_read(dap, AP_REG_IDR, &apid); + retval = dap_queue_ap_read(dap_ap(dap, apsel), AP_REG_IDR, &apid); if (retval != ERROR_OK) return retval; retval = dap_run(dap); @@ -1625,9 +1542,7 @@ COMMAND_HANDLER(dap_apid_command) return ERROR_COMMAND_SYNTAX_ERROR; } - dap_ap_select(dap, apsel); - - retval = dap_queue_ap_read(dap, AP_REG_IDR, &apid); + retval = dap_queue_ap_read(dap_ap(dap, apsel), AP_REG_IDR, &apid); if (retval != ERROR_OK) return retval; retval = dap_run(dap);