arm_adi_v5: simplify handling of AP type

The complete AP type should include 'class' and 'manufacturer'.

Cleanup the definition of AP type from AP_REG_IDR register.
Include the check of 'class', together with manufacturer and type.
Add the new MEM-AP from ARM IHI0074C.

Change-Id: Ic8db7c040108ba237b54f73b1abe24b8b853699b
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6447
Tested-by: jenkins
Reviewed-by: Tarek BOCHKATI <tarek.bouchkati@gmail.com>
Reviewed-by: Daniel Goehring <dgoehrin@os.amperecomputing.com>
This commit is contained in:
Antonio Borneo 2021-08-10 18:09:28 +02:00
parent 06d2e430db
commit ddbc13a6f2
2 changed files with 64 additions and 69 deletions

View File

@ -893,6 +893,30 @@ static const char *class_description[16] = {
[0xF] = "CoreLink, PrimeCell or System component",
};
static const struct {
enum ap_type type;
const char *description;
} ap_types[] = {
{ AP_TYPE_JTAG_AP, "JTAG-AP" },
{ AP_TYPE_COM_AP, "COM-AP" },
{ AP_TYPE_AHB3_AP, "MEM-AP AHB3" },
{ AP_TYPE_APB_AP, "MEM-AP APB2 or APB3" },
{ AP_TYPE_AXI_AP, "MEM-AP AXI3 or AXI4" },
{ AP_TYPE_AHB5_AP, "MEM-AP AHB5" },
{ AP_TYPE_APB4_AP, "MEM-AP APB4" },
{ AP_TYPE_AXI5_AP, "MEM-AP AXI5" },
{ AP_TYPE_AHB5H_AP, "MEM-AP AHB5 with enhanced HPROT" },
};
static const char *ap_type_to_description(enum ap_type type)
{
for (unsigned int i = 0; i < ARRAY_SIZE(ap_types); i++)
if (type == ap_types[i].type)
return ap_types[i].description;
return "Unknown";
}
/*
* This function checks the ID for each access port to find the requested Access Port type
*/
@ -912,29 +936,12 @@ int dap_find_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adiv5_a
retval = dap_run(dap);
/* IDR bits:
* 31-28 : Revision
* 27-24 : JEDEC bank (0x4 for ARM)
* 23-17 : JEDEC code (0x3B for ARM)
* 16-13 : Class (0b1000=Mem-AP)
* 12-8 : Reserved
* 7-4 : AP Variant (non-zero for JTAG-AP)
* 3-0 : AP Type (0=JTAG-AP 1=AHB-AP 2=APB-AP 4=AXI-AP)
*/
/* Reading register for a non-existent AP should not cause an error,
* but just to be sure, try to continue searching if an error does happen.
*/
if ((retval == ERROR_OK) && /* Register read success */
((id_val & IDR_JEP106) == IDR_JEP106_ARM) && /* Jedec codes match */
((id_val & IDR_TYPE) == type_to_find)) { /* type matches*/
if (retval == ERROR_OK && (id_val & AP_TYPE_MASK) == type_to_find) {
LOG_DEBUG("Found %s at AP index: %d (IDR=0x%08" PRIX32 ")",
(type_to_find == AP_TYPE_AHB3_AP) ? "AHB3-AP" :
(type_to_find == AP_TYPE_AHB5_AP) ? "AHB5-AP" :
(type_to_find == AP_TYPE_APB_AP) ? "APB-AP" :
(type_to_find == AP_TYPE_AXI_AP) ? "AXI-AP" :
(type_to_find == AP_TYPE_JTAG_AP) ? "JTAG-AP" : "Unknown",
ap_type_to_description(type_to_find),
ap_num, id_val);
*ap_out = &dap->ap[ap_num];
@ -942,12 +949,7 @@ int dap_find_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adiv5_a
}
}
LOG_DEBUG("No %s found",
(type_to_find == AP_TYPE_AHB3_AP) ? "AHB3-AP" :
(type_to_find == AP_TYPE_AHB5_AP) ? "AHB5-AP" :
(type_to_find == AP_TYPE_APB_AP) ? "APB-AP" :
(type_to_find == AP_TYPE_AXI_AP) ? "AXI-AP" :
(type_to_find == AP_TYPE_JTAG_AP) ? "JTAG-AP" : "Unknown");
LOG_DEBUG("No %s found", ap_type_to_description(type_to_find));
return ERROR_FAIL;
}
@ -1113,8 +1115,6 @@ static int dap_read_part_id(struct adiv5_ap *ap, target_addr_t component_base, u
#define ANY_ID 0x1000
#define ARM_ID 0x23B
static const struct {
uint16_t designer_id;
uint16_t part_num;
@ -1490,7 +1490,6 @@ int dap_info_command(struct command_invocation *cmd,
uint32_t apid;
target_addr_t dbgbase;
target_addr_t dbgaddr;
uint8_t mem_ap;
/* Now we read ROM table ID registers, ref. ARM IHI 0029B sec */
retval = dap_get_debugbase(ap, &dbgbase, &apid);
@ -1503,32 +1502,14 @@ int dap_info_command(struct command_invocation *cmd,
return ERROR_FAIL;
}
switch (apid & (IDR_JEP106 | IDR_TYPE)) {
case IDR_JEP106_ARM | AP_TYPE_JTAG_AP:
command_print(cmd, "\tType is JTAG-AP");
break;
case IDR_JEP106_ARM | AP_TYPE_AHB3_AP:
command_print(cmd, "\tType is MEM-AP AHB3");
break;
case IDR_JEP106_ARM | AP_TYPE_AHB5_AP:
command_print(cmd, "\tType is MEM-AP AHB5");
break;
case IDR_JEP106_ARM | AP_TYPE_APB_AP:
command_print(cmd, "\tType is MEM-AP APB");
break;
case IDR_JEP106_ARM | AP_TYPE_AXI_AP:
command_print(cmd, "\tType is MEM-AP AXI");
break;
default:
command_print(cmd, "\tUnknown AP type");
break;
}
command_print(cmd, "\tType is %s", ap_type_to_description(apid & AP_TYPE_MASK));
/* NOTE: a MEM-AP may have a single CoreSight component that's
* not a ROM table ... or have no such components at all.
*/
mem_ap = (apid & IDR_CLASS) == AP_CLASS_MEM_AP;
if (mem_ap) {
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))
dbgaddr = 0xFFFFFFFFFFFFFFFFull;
else

View File

@ -33,6 +33,9 @@
#include "arm_jtag.h"
#include "helper/bits.h"
/* JEP106 ID for ARM */
#define ARM_ID 0x23B
/* three-bit ACK values for SWD access (sent LSB first) */
#define SWD_ACK_OK 0x1
#define SWD_ACK_WAIT 0x2
@ -157,13 +160,28 @@
#define MEM_AP_REG_CFG_INVALID 0xFFFFFFF8
/* Fields of the MEM-AP's IDR register */
#define IDR_REV (0xFUL << 28)
#define IDR_JEP106 (0x7FFUL << 17)
#define IDR_CLASS (0xFUL << 13)
#define IDR_VARIANT (0xFUL << 4)
#define IDR_TYPE (0xFUL << 0)
#define AP_REG_IDR_REVISION_MASK (0xF0000000)
#define AP_REG_IDR_REVISION_SHIFT (28)
#define AP_REG_IDR_DESIGNER_MASK (0x0FFE0000)
#define AP_REG_IDR_DESIGNER_SHIFT (17)
#define AP_REG_IDR_CLASS_MASK (0x0001E000)
#define AP_REG_IDR_CLASS_SHIFT (13)
#define AP_REG_IDR_VARIANT_MASK (0x000000F0)
#define AP_REG_IDR_VARIANT_SHIFT (4)
#define AP_REG_IDR_TYPE_MASK (0x0000000F)
#define AP_REG_IDR_TYPE_SHIFT (0)
#define IDR_JEP106_ARM 0x04760000
#define AP_REG_IDR_CLASS_NONE (0x0)
#define AP_REG_IDR_CLASS_COM (0x1)
#define AP_REG_IDR_CLASS_MEM_AP (0x8)
#define AP_REG_IDR_VALUE(d, c, t) (\
(((d) << AP_REG_IDR_DESIGNER_SHIFT) & AP_REG_IDR_DESIGNER_MASK) | \
(((c) << AP_REG_IDR_CLASS_SHIFT) & AP_REG_IDR_CLASS_MASK) | \
(((t) << AP_REG_IDR_TYPE_SHIFT) & AP_REG_IDR_TYPE_MASK) \
)
#define AP_TYPE_MASK (AP_REG_IDR_DESIGNER_MASK | AP_REG_IDR_CLASS_MASK | AP_REG_IDR_TYPE_MASK)
/* FIXME: not SWD specific; should be renamed, e.g. adiv5_special_seq */
enum swd_special_seq {
@ -349,23 +367,19 @@ struct dap_ops {
void (*quit)(struct adiv5_dap *dap);
};
/*
* Access Port classes
*/
enum ap_class {
AP_CLASS_NONE = 0x00000, /* No class defined */
AP_CLASS_MEM_AP = 0x10000, /* MEM-AP */
};
/*
* Access Port types
*/
enum ap_type {
AP_TYPE_JTAG_AP = 0x0, /* JTAG-AP - JTAG master for controlling other JTAG devices */
AP_TYPE_AHB3_AP = 0x1, /* AHB3 Memory-AP */
AP_TYPE_APB_AP = 0x2, /* APB Memory-AP */
AP_TYPE_AXI_AP = 0x4, /* AXI Memory-AP */
AP_TYPE_AHB5_AP = 0x5, /* AHB5 Memory-AP. */
AP_TYPE_JTAG_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_NONE, 0), /* JTAG-AP */
AP_TYPE_COM_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_COM, 0), /* COM-AP */
AP_TYPE_AHB3_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 1), /* AHB3 Memory-AP */
AP_TYPE_APB_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 2), /* APB2 or APB3 Memory-AP */
AP_TYPE_AXI_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 4), /* AXI3 or AXI4 Memory-AP */
AP_TYPE_AHB5_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 5), /* AHB5 Memory-AP */
AP_TYPE_APB4_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 6), /* APB4 Memory-AP */
AP_TYPE_AXI5_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 7), /* AXI5 Memory-AP */
AP_TYPE_AHB5H_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 8), /* AHB5 with enhanced HPROT Memory-AP */
};
/* Check the ap->cfg_reg Long Address field (bit 1)