Merge pull request #139 from esden/pid_cid_tables
Use Product ID and Componend ID tables instead of defines.
This commit is contained in:
commit
1f9fbd2d0e
266
src/adiv5.c
266
src/adiv5.c
|
@ -32,16 +32,181 @@
|
|||
#define DO_RESET_SEQ 0
|
||||
#endif
|
||||
|
||||
/* ROM table CIDR values */
|
||||
#define CIDR_ROM_TABLE 0xb105100d
|
||||
#define CIDR_GENERIC_IP 0xb105e00d
|
||||
#define CIDR_DEBUG 0xb105900d
|
||||
/* All this should probably be defined in a dedicated ADIV5 header, so that they
|
||||
* are consistently named and accessible when needed in the codebase.
|
||||
*/
|
||||
|
||||
#define PIDR_REV_MASK 0x0FFF00000ULL
|
||||
#define PIDR_ARMv7M 0x4000BB000ULL
|
||||
#define PIDR_ARMv6M 0x4000BB008ULL
|
||||
#define PIDR_ARMv7MF 0x4000BB00CULL
|
||||
#define PIDR_ARMv7A 0x4000BBC09ULL
|
||||
/* ROM table CIDR values */
|
||||
#define CIDR0_OFFSET 0xFF0 /* DBGCID0 */
|
||||
#define CIDR1_OFFSET 0xFF4 /* DBGCID1 */
|
||||
#define CIDR2_OFFSET 0xFF8 /* DBGCID2 */
|
||||
#define CIDR3_OFFSET 0xFFC /* DBGCID3 */
|
||||
|
||||
/* Component class ID register can be broken down into the following logical
|
||||
* interpretation of the 32bit value consisting of the least significant bytes
|
||||
* of the 4 CID registers:
|
||||
* |7 ID3 reg 0|7 ID2 reg 0|7 ID1 reg 0|7 ID0 reg 0|
|
||||
* |1|0|1|1|0|0|0|1|0|0|0|0|0|1|0|1| | | | |0|0|0|0|0|0|0|0|1|1|0|1|
|
||||
* |31 24|23 16|15 12|11 | 0|
|
||||
* \_______________ ______________/\___ __/\___________ ___________/
|
||||
* V V V
|
||||
* Preamble Component Preamble
|
||||
* Class
|
||||
* \_______________________________ _______________________________/
|
||||
* V
|
||||
* Component ID
|
||||
*/
|
||||
#define CID_PREAMBLE 0xB105000D
|
||||
#define CID_CLASS_MASK 0x0000F000
|
||||
#define CID_CLASS_SHIFT 12
|
||||
/* The following enum is based on the Component Class value table 13-3 of the
|
||||
* ADIv5 standard.
|
||||
*/
|
||||
enum cid_class {
|
||||
cidc_gvc = 0x0, /* Generic verification component*/
|
||||
cidc_romtab = 0x1, /* ROM Table, std. layout (ADIv5 Chapter 14) */
|
||||
/* 0x2 - 0x8 */ /* Reserved */
|
||||
cidc_dc = 0x9, /* Debug component, std. layout (CoreSight Arch. Spec.) */
|
||||
/* 0xA */ /* Reserved */
|
||||
cidc_ptb = 0xB, /* Peripheral Test Block (PTB) */
|
||||
/* 0xC */ /* Reserved */
|
||||
cidc_dess = 0xD, /* OptimoDE Data Engine SubSystem (DESS) component */
|
||||
cidc_gipc = 0xE, /* Generic IP Component */
|
||||
cidc_pcp = 0xF, /* PrimeCell peripheral */
|
||||
cidc_unknown = 0x10
|
||||
};
|
||||
|
||||
#ifdef PLATFORM_HAS_DEBUG
|
||||
/* The reserved ones only have an R in them, to save a bit of space. */
|
||||
static const char const *cidc_debug_strings[] =
|
||||
{
|
||||
[cidc_gvc] = "Generic verification component", /* 0x0 */
|
||||
[cidc_romtab] = "ROM Table", /* 0x1 */
|
||||
[0x2 ... 0x8] = "R", /* 0x2 - 0x8 */
|
||||
[cidc_dc] = "Debug component", /* 0x9 */
|
||||
[0xA] = "R", /* 0xA */
|
||||
[cidc_ptb] = "Peripheral Test Block", /* 0xB */
|
||||
[0xC] = "R", /* 0xC */
|
||||
[cidc_dess] = "OptimoDE Data Engine SubSystem component", /* 0xD */
|
||||
[cidc_gipc] = "Generic IP component", /* 0xE */
|
||||
[cidc_pcp] = "PrimeCell peripheral", /* 0xF */
|
||||
[cidc_unknown] = "Unknown component class" /* 0x10 */
|
||||
};
|
||||
#endif
|
||||
|
||||
#define PIDR0_OFFSET 0xFE0 /* DBGPID0 */
|
||||
#define PIDR1_OFFSET 0xFE4 /* DBGPID1 */
|
||||
#define PIDR2_OFFSET 0xFE8 /* DBGPID2 */
|
||||
#define PIDR3_OFFSET 0xFEC /* DBGPID3 */
|
||||
#define PIDR4_OFFSET 0xFD0 /* DBGPID4 */
|
||||
#define PIDR5_OFFSET 0xFD4 /* DBGPID5 (Reserved) */
|
||||
#define PIDR6_OFFSET 0xFD8 /* DBGPID6 (Reserved) */
|
||||
#define PIDR7_OFFSET 0xFDC /* DBGPID7 (Reserved) */
|
||||
#define PIDR_REV_MASK 0x0FFF00000ULL /* Revision bits. */
|
||||
#define PIDR_PN_MASK 0x000000FFFULL /* Part number bits. */
|
||||
#define PIDR_ARM_BITS 0x4000BB000ULL /* These make up the ARM JEP-106 code. */
|
||||
|
||||
enum arm_arch {
|
||||
aa_nosupport,
|
||||
aa_cortexm,
|
||||
aa_cortexa,
|
||||
aa_end
|
||||
};
|
||||
|
||||
#ifdef PLATFORM_HAS_DEBUG
|
||||
#define PIDR_PN_BIT_STRINGS(...) __VA_ARGS__
|
||||
#else
|
||||
#define PIDR_PN_BIT_STRINGS(...)
|
||||
#endif
|
||||
|
||||
/* The part number list was adopted from OpenOCD:
|
||||
* https://sourceforge.net/p/openocd/code/ci/406f4/tree/src/target/arm_adi_v5.c#l932
|
||||
*
|
||||
* The product ID register consists of several parts. For a full description
|
||||
* refer to ARM Debug Interface v5 Architecture Specification. Based on the
|
||||
* document the pidr is 64 bit long and has the following interpratiation:
|
||||
* |7 ID7 reg 0|7 ID6 reg 0|7 ID5 reg 0|7 ID4 reg 0|
|
||||
* |0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0| | | | |1|0|0|0|
|
||||
* |63 56|55 48|47 40|39 36|35 32|
|
||||
* \_______________________ ______________________/\___ __/\___ ___/
|
||||
* V V V
|
||||
* Reserved, RAZ 4KB |
|
||||
* count |
|
||||
* JEP-106
|
||||
* Continuation Code
|
||||
*
|
||||
* |7 ID3 reg 0|7 ID2 reg 0|7 ID1 reg 0|7 ID0 reg 0|
|
||||
* | | | | | | | | | | | | |1|0|1|1|1|0|1|1| | | | | | | | | | | | |
|
||||
* |31 28|27 24|23 20|||18 | 12|11 | 0|
|
||||
* \___ __/\__ ___/\___ __/ |\______ _____/\___________ ___________/
|
||||
* V V V | V V
|
||||
* RevAnd | Revision | JEP-106 Part number
|
||||
* | | ID code
|
||||
* Customer 19
|
||||
* modified `- JEP-106 code is used
|
||||
*
|
||||
* JEP-106 is a JEDEC standard assigning manufacturer IDs to different
|
||||
* manufacturers in case of ARM the full code consisting of the JEP-106
|
||||
* Continuation code followed by the code used bit and the JEP-106 code itself
|
||||
* results in the code 0x4BB. These are the bits filled in the above bit table.
|
||||
*
|
||||
* We left out some of the Part numbers included in OpenOCD, we only include
|
||||
* the ones that have ARM as the designer.
|
||||
*/
|
||||
static const struct {
|
||||
uint16_t part_number;
|
||||
enum arm_arch arch;
|
||||
enum cid_class cidc;
|
||||
#ifdef PLATFORM_HAS_DEBUG
|
||||
const char *type;
|
||||
const char *full;
|
||||
#endif
|
||||
} pidr_pn_bits[] = {
|
||||
{0x000, aa_cortexm, cidc_gipc, PIDR_PN_BIT_STRINGS("Cortex-M3 SCS", "(System Control Space)")},
|
||||
{0x001, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M3 ITM", "(Instrumentation Trace Module)")},
|
||||
{0x002, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M3 DWT", "(Data Watchpoint and Trace)")},
|
||||
{0x003, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M3 FBP", "(Flash Patch and Breakpoint)")},
|
||||
{0x008, aa_cortexm, cidc_gipc, PIDR_PN_BIT_STRINGS("Cortex-M0 SCS", "(System Control Space)")},
|
||||
{0x00a, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M0 DWT", "(Data Watchpoint and Trace)")},
|
||||
{0x00b, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M0 BPU", "(Breakpoint Unit)")},
|
||||
{0x00c, aa_cortexm, cidc_gipc, PIDR_PN_BIT_STRINGS("Cortex-M4 SCS", "(System Control Space)")},
|
||||
{0x00d, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight ETM11", "(Embedded Trace)")},
|
||||
{0x490, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A15 GIC", "(Generic Interrupt Controller)")},
|
||||
{0x4c7, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M7 PPB", "(Private Peripheral Bus ROM Table)")},
|
||||
{0x906, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight CTI", "(Cross Trigger)")},
|
||||
{0x907, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight ETB", "(Trace Buffer)")},
|
||||
{0x908, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight CSTF", "(Trace Funnel)")},
|
||||
{0x910, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight ETM9", "(Embedded Trace)")},
|
||||
{0x912, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight TPIU", "(Trace Port Interface Unit)")},
|
||||
{0x913, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight ITM", "(Instrumentation Trace Macrocell)")},
|
||||
{0x914, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight SWO", "(Single Wire Output)")},
|
||||
{0x917, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight HTM", "(AHB Trace Macrocell)")},
|
||||
{0x920, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight ETM11", "(Embedded Trace)")},
|
||||
{0x921, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A8 ETM", "(Embedded Trace)")},
|
||||
{0x922, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A8 CTI", "(Cross Trigger)")},
|
||||
{0x923, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M3 TPIU", "(Trace Port Interface Unit)")},
|
||||
{0x924, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M3 ETM", "(Embedded Trace)")},
|
||||
{0x925, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M4 ETM", "(Embedded Trace)")},
|
||||
{0x930, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-R4 ETM", "(Embedded Trace)")},
|
||||
{0x941, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight TPIU-Lite", "(Trace Port Interface Unit)")},
|
||||
{0x950, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight Component", "(unidentified Cortex-A9 component)")},
|
||||
{0x955, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight Component", "(unidentified Cortex-A5 component)")},
|
||||
{0x95f, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A15 PTM", "(Program Trace Macrocell)")},
|
||||
{0x961, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight TMC", "(Trace Memory Controller)")},
|
||||
{0x962, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight STM", "(System Trace Macrocell)")},
|
||||
{0x9a0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight PMU", "(Performance Monitoring Unit)")},
|
||||
{0x9a1, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M4 TPIU", "(Trace Port Interface Unit)")},
|
||||
{0x9a5, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A5 ETM", "(Embedded Trace)")},
|
||||
{0x9a7, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A7 PMU", "(Performance Monitor Unit)")},
|
||||
{0x9af, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A15 PMU", "(Performance Monitor Unit)")},
|
||||
{0xc05, aa_cortexa, cidc_dc, PIDR_PN_BIT_STRINGS("Cortex-A5 Debug", "(Debug Unit)")},
|
||||
{0xc07, aa_cortexa, cidc_dc, PIDR_PN_BIT_STRINGS("Cortex-A7 Debug", "(Debug Unit)")},
|
||||
{0xc08, aa_cortexa, cidc_dc, PIDR_PN_BIT_STRINGS("Cortex-A8 Debug", "(Debug Unit)")},
|
||||
{0xc09, aa_cortexa, cidc_dc, PIDR_PN_BIT_STRINGS("Cortex-A9 Debug", "(Debug Unit)")},
|
||||
{0xc0f, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A15 Debug", "(Debug Unit)")}, /* support? */
|
||||
{0xc14, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-R4 Debug", "(Debug Unit)")}, /* support? */
|
||||
{0xfff, aa_end, cidc_unknown, PIDR_PN_BIT_STRINGS("end", "end")}
|
||||
};
|
||||
|
||||
extern bool cortexa_probe(ADIv5_AP_t *apb, uint32_t debug_base);
|
||||
|
||||
|
@ -86,18 +251,35 @@ static void adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr)
|
|||
addr &= ~3;
|
||||
uint64_t pidr = 0;
|
||||
uint32_t cidr = 0;
|
||||
|
||||
/* Assemble logical Product ID register value. */
|
||||
for (int i = 0; i < 4; i++) {
|
||||
uint32_t x = adiv5_mem_read32(ap, addr + 0xfe0 + 4*i);
|
||||
uint32_t x = adiv5_mem_read32(ap, addr + PIDR0_OFFSET + 4*i);
|
||||
pidr |= (x & 0xff) << (i * 8);
|
||||
}
|
||||
pidr |= (uint64_t)adiv5_mem_read32(ap, addr + 0xfd0) << 32;
|
||||
{
|
||||
uint32_t x = adiv5_mem_read32(ap, addr + PIDR4_OFFSET);
|
||||
pidr |= (uint64_t)x << 32;
|
||||
}
|
||||
|
||||
/* Assemble logical Component ID register value. */
|
||||
for (int i = 0; i < 4; i++) {
|
||||
uint32_t x = adiv5_mem_read32(ap, addr + 0xff0 + 4*i);
|
||||
uint32_t x = adiv5_mem_read32(ap, addr + CIDR0_OFFSET + 4*i);
|
||||
cidr |= ((uint64_t)(x & 0xff)) << (i * 8);
|
||||
}
|
||||
|
||||
switch (cidr) {
|
||||
case CIDR_ROM_TABLE: /* This is a ROM table, probe recursively */
|
||||
/* CIDR preamble sanity check */
|
||||
if ((cidr & ~CID_CLASS_MASK) != CID_PREAMBLE) {
|
||||
DEBUG("0x%X: 0x%X <- does not match preamble (0x%X)\n", addr, cidr, CID_PREAMBLE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Extract Component ID class nibble */
|
||||
uint32_t cid_class = (cidr & CID_CLASS_MASK) >> CID_CLASS_SHIFT;
|
||||
|
||||
DEBUG("0x%X: \"%s\"\n", addr, cidc_debug_strings[cid_class]);
|
||||
|
||||
if (cid_class == cidc_romtab) { /* ROM table, probe recursively */
|
||||
for (int i = 0; i < 256; i++) {
|
||||
uint32_t entry = adiv5_mem_read32(ap, addr + i*4);
|
||||
if (entry == 0)
|
||||
|
@ -108,23 +290,48 @@ static void adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr)
|
|||
|
||||
adiv5_component_probe(ap, addr + (entry & ~0xfff));
|
||||
}
|
||||
break;
|
||||
case CIDR_GENERIC_IP:
|
||||
switch (pidr & ~PIDR_REV_MASK) {
|
||||
case PIDR_ARMv7MF:
|
||||
case PIDR_ARMv7M:
|
||||
case PIDR_ARMv6M:
|
||||
cortexm_probe(ap);
|
||||
break;
|
||||
} else {
|
||||
/* Check if the component was designed by ARM, we currently do not support,
|
||||
* any components by other designers.
|
||||
*/
|
||||
if ((pidr & ~(PIDR_REV_MASK | PIDR_PN_MASK)) != PIDR_ARM_BITS) {
|
||||
DEBUG("0x%X: 0x%llX <- does not match ARM JEP-106\n", addr, pidr);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case CIDR_DEBUG:
|
||||
switch (pidr & ~PIDR_REV_MASK) {
|
||||
case PIDR_ARMv7A:
|
||||
cortexa_probe(ap, addr);
|
||||
break;
|
||||
|
||||
/* Extract part number from the part id register. */
|
||||
uint16_t part_number = pidr & PIDR_PN_MASK;
|
||||
/* Find the part number in our part list and run the appropriate probe
|
||||
* routine if applicable.
|
||||
*/
|
||||
for (int i = 0; pidr_pn_bits[i].arch != aa_end; i++) {
|
||||
if (pidr_pn_bits[i].part_number == part_number) {
|
||||
DEBUG("0x%X: %s %s\n", addr,
|
||||
pidr_pn_bits[i].type,
|
||||
pidr_pn_bits[i].full);
|
||||
/* Perform sanity check, if we know what to expect as component ID
|
||||
* class.
|
||||
*/
|
||||
if (cid_class != pidr_pn_bits[i].cidc) {
|
||||
DEBUG("WARNING: \"%s\" !match expected \"%s\"\n",
|
||||
cidc_debug_strings[cid_class],
|
||||
cidc_debug_strings[pidr_pn_bits[i].cidc]);
|
||||
}
|
||||
switch (pidr_pn_bits[i].arch) {
|
||||
case aa_cortexm:
|
||||
DEBUG("-> cortexm_probe\n");
|
||||
cortexm_probe(ap);
|
||||
break;
|
||||
case aa_cortexa:
|
||||
DEBUG("-> cortexa_probe\n");
|
||||
cortexa_probe(ap, addr);
|
||||
break;
|
||||
default:
|
||||
DEBUG("-> skip\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -363,4 +570,3 @@ uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr)
|
|||
ret = adiv5_dp_read(ap->dp, addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,8 @@ static struct jtag_dev_descr_s {
|
|||
{.idcode = 0x8940303F, .idmask = 0xFFFFFFFF, .descr = "ATMEL: ATMega16."},
|
||||
{.idcode = 0x0792603F, .idmask = 0xFFFFFFFF, .descr = "ATMEL: AT91SAM9261."},
|
||||
{.idcode = 0x20270013, .idmask = 0xFFFFFFFF, .descr = "Intel: i80386ex."},
|
||||
{.idcode = 0x07B7617F, .idmask = 0xFFFFFFFF, .descr = "Broadcom: BCM2835."},
|
||||
{.idcode = 0x4BA00477, .idmask = 0xFFFFFFFF, .descr = "Broadcom: BCM2836."},
|
||||
{.idcode = 0, .idmask = 0, .descr = "Unknown"},
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue