Skip to content

Commit 545f69d

Browse files
committed
adi: Moved all the AP component probe logic from adiv5.c to adi.c and adjusted nomenclature
1 parent 1efbff5 commit 545f69d

File tree

4 files changed

+208
-203
lines changed

4 files changed

+208
-203
lines changed

src/target/adi.c

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,16 @@
3636
#include "target_internal.h"
3737
#include "jep106.h"
3838
#include "adi.h"
39+
#include "adiv5.h"
3940
#include "cortex.h"
4041
#include "cortex_internal.h"
4142

43+
/* Used to probe for a protected SAMX5X device */
44+
#define SAMX5X_DSU_CTRLSTAT 0x41002100U
45+
#define SAMX5X_STATUSB_PROT (1U << 16U)
46+
47+
#define ID_SAMx5x 0xcd0U
48+
4249
#if ENABLE_DEBUG == 1
4350
#define ARM_COMPONENT_STR(...) __VA_ARGS__
4451
#else
@@ -460,3 +467,193 @@ void adi_ap_resume_cores(adiv5_access_port_s *const ap)
460467
}
461468
}
462469
}
470+
471+
static uint32_t adi_ap_read_id(adiv5_access_port_s *ap, uint32_t addr)
472+
{
473+
uint32_t res = 0;
474+
uint8_t data[16];
475+
adiv5_mem_read(ap, data, addr, sizeof(data));
476+
for (size_t i = 0; i < 4U; ++i)
477+
res |= (uint32_t)data[4U * i] << (i * 8U);
478+
return res;
479+
}
480+
481+
static uint64_t adi_ap_read_pidr(adiv5_access_port_s *ap, uint32_t addr)
482+
{
483+
const uint32_t pidr_upper = adi_ap_read_id(ap, addr + PIDR4_OFFSET);
484+
const uint32_t pidr_lower = adi_ap_read_id(ap, addr + PIDR0_OFFSET);
485+
return ((uint64_t)pidr_upper << 32U) | (uint64_t)pidr_lower;
486+
}
487+
488+
uint32_t adi_mem_read32(adiv5_access_port_s *const ap, const target_addr32_t addr)
489+
{
490+
uint32_t ret;
491+
adiv5_mem_read(ap, &ret, addr, sizeof(ret));
492+
return ret;
493+
}
494+
495+
static void adi_parse_adi_rom_table(adiv5_access_port_s *const ap, const target_addr32_t base_address,
496+
const size_t recursion_depth, const char *const indent, const uint64_t pidr)
497+
{
498+
#if defined(DEBUG_WARN_IS_NOOP) && defined(DEBUG_ERROR_IS_NOOP)
499+
(void)indent;
500+
#endif
501+
502+
/* Extract the designer code and part number from the part ID register */
503+
const uint16_t designer_code = adi_designer_from_pidr(pidr);
504+
const uint16_t part_number = pidr & PIDR_PN_MASK;
505+
506+
if (recursion_depth == 0U) {
507+
ap->designer_code = designer_code;
508+
ap->partno = part_number;
509+
510+
if (ap->designer_code == JEP106_MANUFACTURER_ATMEL && ap->partno == ID_SAMx5x) {
511+
uint32_t ctrlstat = adi_mem_read32(ap, SAMX5X_DSU_CTRLSTAT);
512+
if (ctrlstat & SAMX5X_STATUSB_PROT) {
513+
/* A protected SAMx5x device is found.
514+
* Handle it here, as access only to limited memory region
515+
* is allowed
516+
*/
517+
cortexm_probe(ap);
518+
return;
519+
}
520+
}
521+
}
522+
523+
/* Check SYSMEM bit */
524+
const bool memtype = adi_mem_read32(ap, base_address + ADIV5_ROM_MEMTYPE) & ADIV5_ROM_MEMTYPE_SYSMEM;
525+
if (adiv5_dp_error(ap->dp))
526+
DEBUG_ERROR("Fault reading ROM table entry\n");
527+
else if (memtype)
528+
ap->flags |= ADIV5_AP_FLAGS_HAS_MEM;
529+
DEBUG_INFO("ROM Table: BASE=0x%" PRIx32 " SYSMEM=%u, Manufacturer %03x Partno %03x (PIDR = 0x%02" PRIx32
530+
"%08" PRIx32 ")\n",
531+
base_address, memtype, designer_code, part_number, (uint32_t)(pidr >> 32U), (uint32_t)pidr);
532+
533+
for (uint32_t i = 0; i < 960U; i++) {
534+
adiv5_dp_error(ap->dp);
535+
536+
uint32_t entry = adi_mem_read32(ap, base_address + i * 4U);
537+
if (adiv5_dp_error(ap->dp)) {
538+
DEBUG_ERROR("%sFault reading ROM table entry %" PRIu32 "\n", indent, i);
539+
break;
540+
}
541+
542+
if (entry == 0)
543+
break;
544+
545+
if (!(entry & ADIV5_ROM_ROMENTRY_PRESENT)) {
546+
DEBUG_INFO("%s%" PRIu32 " Entry 0x%08" PRIx32 " -> Not present\n", indent, i, entry);
547+
continue;
548+
}
549+
550+
/* Probe recursively */
551+
adi_ap_component_probe(ap, base_address + (entry & ADIV5_ROM_ROMENTRY_OFFSET), recursion_depth + 1U, i);
552+
}
553+
DEBUG_INFO("%sROM Table: END\n", indent);
554+
}
555+
556+
/* Return true if we find a debuggable device. */
557+
void adi_ap_component_probe(
558+
adiv5_access_port_s *ap, target_addr64_t base_address, const size_t recursion, const uint32_t entry_number)
559+
{
560+
#ifdef DEBUG_WARN_IS_NOOP
561+
(void)entry_number;
562+
#endif
563+
564+
const uint32_t cidr = adi_ap_read_id(ap, base_address + CIDR0_OFFSET);
565+
if (ap->dp->fault) {
566+
DEBUG_ERROR("Error reading CIDR on AP%u: %u\n", ap->apsel, ap->dp->fault);
567+
return;
568+
}
569+
570+
#if ENABLE_DEBUG == 1
571+
char *const indent = alloca(recursion + 1U);
572+
573+
for (size_t i = 0; i < recursion; i++)
574+
indent[i] = ' ';
575+
indent[recursion] = 0;
576+
#else
577+
const char *const indent = " ";
578+
#endif
579+
580+
if (adiv5_dp_error(ap->dp)) {
581+
DEBUG_ERROR("%sFault reading ID registers\n", indent);
582+
return;
583+
}
584+
585+
/* CIDR preamble sanity check */
586+
if ((cidr & ~CID_CLASS_MASK) != CID_PREAMBLE) {
587+
DEBUG_WARN("%s%" PRIu32 " 0x%0" PRIx32 "%08" PRIx32 ": 0x%08" PRIx32 " <- does not match preamble (0x%08" PRIx32
588+
")\n",
589+
indent, entry_number, (uint32_t)(base_address >> 32U), (uint32_t)base_address, cidr, CID_PREAMBLE);
590+
return;
591+
}
592+
593+
/* Extract Component ID class nibble */
594+
const uint8_t cid_class = (cidr & CID_CLASS_MASK) >> CID_CLASS_SHIFT;
595+
596+
/* Read out the peripheral ID register */
597+
const uint64_t pidr = adi_ap_read_pidr(ap, base_address);
598+
599+
/* ROM table */
600+
if (cid_class == cidc_romtab) {
601+
/* Validate that the SIZE field is 0 per the spec */
602+
if (pidr & PIDR_SIZE_MASK) {
603+
DEBUG_ERROR("Fault reading ROM table\n");
604+
return;
605+
}
606+
adi_parse_adi_rom_table(ap, base_address, recursion, indent, pidr);
607+
} else {
608+
/* Extract the designer code from the part ID register */
609+
const uint16_t designer_code = adi_designer_from_pidr(pidr);
610+
611+
if (designer_code != JEP106_MANUFACTURER_ARM && designer_code != JEP106_MANUFACTURER_ARM_CHINA) {
612+
#ifndef DEBUG_TARGET_IS_NOOP
613+
const uint16_t part_number = pidr & PIDR_PN_MASK;
614+
#endif
615+
/* non-ARM components are not supported currently */
616+
DEBUG_WARN("%s%" PRIu32 " 0x%0" PRIx32 "%08" PRIx32 ": 0x%02" PRIx32 "%08" PRIx32 " Non-ARM component "
617+
"ignored\n",
618+
indent + 1, entry_number, (uint32_t)(base_address >> 32U), (uint32_t)base_address,
619+
(uint32_t)(pidr >> 32U), (uint32_t)pidr);
620+
DEBUG_TARGET("%s -> designer: %x, part no: %x\n", indent, designer_code, part_number);
621+
return;
622+
}
623+
624+
/* Check if this is a CoreSight component */
625+
uint8_t dev_type = 0;
626+
uint16_t arch_id = 0;
627+
if (cid_class == cidc_dc) {
628+
/* Read out the component's identification information */
629+
const uint32_t devarch = adi_mem_read32(ap, base_address + DEVARCH_OFFSET);
630+
dev_type = adi_mem_read32(ap, base_address + DEVTYPE_OFFSET) & DEVTYPE_MASK;
631+
632+
if (devarch & DEVARCH_PRESENT)
633+
arch_id = devarch & DEVARCH_ARCHID_MASK;
634+
}
635+
636+
/* Look the component up and dispatch to a probe routine accordingly */
637+
const arm_coresight_component_s *const component =
638+
adi_lookup_component(base_address, entry_number, indent, cid_class, pidr, dev_type, arch_id);
639+
640+
if (component) {
641+
switch (component->arch) {
642+
case aa_cortexm:
643+
DEBUG_INFO("%s-> cortexm_probe\n", indent + 1);
644+
cortexm_probe(ap);
645+
break;
646+
case aa_cortexa:
647+
DEBUG_INFO("%s-> cortexa_probe\n", indent + 1);
648+
cortexa_probe(ap, base_address);
649+
break;
650+
case aa_cortexr:
651+
DEBUG_INFO("%s-> cortexr_probe\n", indent + 1);
652+
cortexr_probe(ap, base_address);
653+
break;
654+
default:
655+
break;
656+
}
657+
}
658+
}
659+
}

src/target/adi.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ const arm_coresight_component_s *adi_lookup_component(target_addr64_t base_addre
3434
const char *indent, uint8_t cid_class, uint64_t pidr, uint8_t dev_type, uint16_t arch_id);
3535
/* Helper for figuring out what an AP is and configuring it for use */
3636
bool adi_configure_ap(adiv5_access_port_s *ap);
37+
/* Helper for reading 32-bit registers from an AP's MMIO space */
38+
uint32_t adi_mem_read32(adiv5_access_port_s *ap, target_addr32_t addr);
3739
/* Helper for probing a CoreSight debug component */
38-
void adiv5_component_probe(
40+
void adi_ap_component_probe(
3941
adiv5_access_port_s *ap, target_addr64_t base_address, size_t recursion, uint32_t entry_number);
4042
/* Helper for resuming all cores halted on an AP during probe */
4143
void adi_ap_resume_cores(adiv5_access_port_s *ap);

0 commit comments

Comments
 (0)