xtensa: update XDM register map for TRAX support

- Include additional debug module registers
- Add translation function for DM reg addr -> ID
- Add DM read/write commands

Signed-off-by: ianst <ianst@cadence.com>
Change-Id: If95419d24a9f27a40fa695c8c15326cdfd127ef1
Reviewed-on: https://review.openocd.org/c/openocd/+/7973
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Tested-by: jenkins
This commit is contained in:
ianst 2023-11-09 07:28:50 -08:00 committed by Antonio Borneo
parent 9ebc2a6519
commit f8096ce687
4 changed files with 123 additions and 0 deletions

View File

@ -11487,6 +11487,12 @@ Execute arbitrary instruction(s) provided as an ascii string. The string repres
number of instruction bytes, thus its length must be even. number of instruction bytes, thus its length must be even.
@end deffn @end deffn
@deffn {Command} {xtensa dm} (address) [value]
Read or write Xtensa Debug Module (DM) registers. @var{address} is required for both reads
and writes and is a 4-byte-aligned value typically between 0 and 0x3ffc. @var{value} is specified
only for write accesses.
@end deffn
@subsection Xtensa Performance Monitor Configuration @subsection Xtensa Performance Monitor Configuration
@deffn {Command} {xtensa perfmon_enable} <counter_id> <select> [mask] [kernelcnt] [tracelevel] @deffn {Command} {xtensa perfmon_enable} <counter_id> <select> [mask] [kernelcnt] [tracelevel]

View File

@ -3978,6 +3978,38 @@ COMMAND_HANDLER(xtensa_cmd_smpbreak)
get_current_target(CMD_CTX)); get_current_target(CMD_CTX));
} }
COMMAND_HELPER(xtensa_cmd_dm_rw_do, struct xtensa *xtensa)
{
if (CMD_ARGC == 1) {
// read: xtensa dm addr
uint32_t addr = strtoul(CMD_ARGV[0], NULL, 0);
uint32_t val;
int res = xtensa_dm_read(&xtensa->dbg_mod, addr, &val);
if (res == ERROR_OK)
command_print(CMD, "xtensa DM(0x%08" PRIx32 ") -> 0x%08" PRIx32, addr, val);
else
command_print(CMD, "xtensa DM(0x%08" PRIx32 ") : read ERROR %" PRId32, addr, res);
return res;
} else if (CMD_ARGC == 2) {
// write: xtensa dm addr value
uint32_t addr = strtoul(CMD_ARGV[0], NULL, 0);
uint32_t val = strtoul(CMD_ARGV[1], NULL, 0);
int res = xtensa_dm_write(&xtensa->dbg_mod, addr, val);
if (res == ERROR_OK)
command_print(CMD, "xtensa DM(0x%08" PRIx32 ") <- 0x%08" PRIx32, addr, val);
else
command_print(CMD, "xtensa DM(0x%08" PRIx32 ") : write ERROR %" PRId32, addr, res);
return res;
}
return ERROR_COMMAND_SYNTAX_ERROR;
}
COMMAND_HANDLER(xtensa_cmd_dm_rw)
{
return CALL_COMMAND_HANDLER(xtensa_cmd_dm_rw_do,
target_to_xtensa(get_current_target(CMD_CTX)));
}
COMMAND_HELPER(xtensa_cmd_tracestart_do, struct xtensa *xtensa) COMMAND_HELPER(xtensa_cmd_tracestart_do, struct xtensa *xtensa)
{ {
struct xtensa_trace_status trace_status; struct xtensa_trace_status trace_status;
@ -4234,6 +4266,13 @@ static const struct command_registration xtensa_any_command_handlers[] = {
.help = "Set the way the CPU chains OCD breaks", .help = "Set the way the CPU chains OCD breaks",
.usage = "[none|breakinout|runstall] | [BreakIn] [BreakOut] [RunStallIn] [DebugModeOut]", .usage = "[none|breakinout|runstall] | [BreakIn] [BreakOut] [RunStallIn] [DebugModeOut]",
}, },
{
.name = "dm",
.handler = xtensa_cmd_dm_rw,
.mode = COMMAND_ANY,
.help = "Xtensa DM read/write",
.usage = "addr [value]"
},
{ {
.name = "perfmon_enable", .name = "perfmon_enable",
.handler = xtensa_cmd_perfmon_enable, .handler = xtensa_cmd_perfmon_enable,

View File

@ -34,6 +34,16 @@ static const struct xtensa_dm_pwr_reg_offsets xdm_pwr_regs[XDMREG_PWRNUM] =
static const struct xtensa_dm_reg_offsets xdm_regs[XDMREG_NUM] = static const struct xtensa_dm_reg_offsets xdm_regs[XDMREG_NUM] =
XTENSA_DM_REG_OFFSETS; XTENSA_DM_REG_OFFSETS;
static enum xtensa_dm_reg xtensa_dm_regaddr_to_id(uint32_t addr)
{
enum xtensa_dm_reg id;
uint32_t addr_masked = (addr & (XTENSA_DM_APB_ALIGN - 1));
for (id = XDMREG_TRAXID; id < XDMREG_NUM; id++)
if (xdm_regs[id].apb == addr_masked)
break;
return id;
}
static void xtensa_dm_add_set_ir(struct xtensa_debug_module *dm, uint8_t value) static void xtensa_dm_add_set_ir(struct xtensa_debug_module *dm, uint8_t value)
{ {
struct scan_field field; struct scan_field field;
@ -285,6 +295,34 @@ int xtensa_dm_core_status_clear(struct xtensa_debug_module *dm, xtensa_dsr_t bit
return xtensa_dm_queue_execute(dm); return xtensa_dm_queue_execute(dm);
} }
int xtensa_dm_read(struct xtensa_debug_module *dm, uint32_t addr, uint32_t *val)
{
enum xtensa_dm_reg reg = xtensa_dm_regaddr_to_id(addr);
uint8_t buf[sizeof(uint32_t)];
if (reg < XDMREG_NUM) {
xtensa_dm_queue_enable(dm);
dm->dbg_ops->queue_reg_read(dm, reg, buf);
xtensa_dm_queue_tdi_idle(dm);
int res = xtensa_dm_queue_execute(dm);
if (res == ERROR_OK && val)
*val = buf_get_u32(buf, 0, 32);
return res;
}
return ERROR_FAIL;
}
int xtensa_dm_write(struct xtensa_debug_module *dm, uint32_t addr, uint32_t val)
{
enum xtensa_dm_reg reg = xtensa_dm_regaddr_to_id(addr);
if (reg < XDMREG_NUM) {
xtensa_dm_queue_enable(dm);
dm->dbg_ops->queue_reg_write(dm, reg, val);
xtensa_dm_queue_tdi_idle(dm);
return xtensa_dm_queue_execute(dm);
}
return ERROR_FAIL;
}
int xtensa_dm_trace_start(struct xtensa_debug_module *dm, struct xtensa_trace_start_config *cfg) int xtensa_dm_trace_start(struct xtensa_debug_module *dm, struct xtensa_trace_start_config *cfg)
{ {
/*Turn off trace unit so we can start a new trace. */ /*Turn off trace unit so we can start a new trace. */

View File

@ -75,6 +75,22 @@ enum xtensa_dm_reg {
XDMREG_DELAYCNT, XDMREG_DELAYCNT,
XDMREG_MEMADDRSTART, XDMREG_MEMADDRSTART,
XDMREG_MEMADDREND, XDMREG_MEMADDREND,
XDMREG_EXTTIMELO,
XDMREG_EXTTIMEHI,
XDMREG_TRAXRSVD48,
XDMREG_TRAXRSVD4C,
XDMREG_TRAXRSVD50,
XDMREG_TRAXRSVD54,
XDMREG_TRAXRSVD58,
XDMREG_TRAXRSVD5C,
XDMREG_TRAXRSVD60,
XDMREG_TRAXRSVD64,
XDMREG_TRAXRSVD68,
XDMREG_TRAXRSVD6C,
XDMREG_TRAXRSVD70,
XDMREG_TRAXRSVD74,
XDMREG_CONFIGID0,
XDMREG_CONFIGID1,
/* Performance Monitor Registers */ /* Performance Monitor Registers */
XDMREG_PMG, XDMREG_PMG,
@ -168,6 +184,22 @@ struct xtensa_dm_reg_offsets {
{ .nar = 0x07, .apb = 0x001c }, /* XDMREG_DELAYCNT */ \ { .nar = 0x07, .apb = 0x001c }, /* XDMREG_DELAYCNT */ \
{ .nar = 0x08, .apb = 0x0020 }, /* XDMREG_MEMADDRSTART */ \ { .nar = 0x08, .apb = 0x0020 }, /* XDMREG_MEMADDRSTART */ \
{ .nar = 0x09, .apb = 0x0024 }, /* XDMREG_MEMADDREND */ \ { .nar = 0x09, .apb = 0x0024 }, /* XDMREG_MEMADDREND */ \
{ .nar = 0x10, .apb = 0x0040 }, /* XDMREG_EXTTIMELO */ \
{ .nar = 0x11, .apb = 0x0044 }, /* XDMREG_EXTTIMEHI */ \
{ .nar = 0x12, .apb = 0x0048 }, /* XDMREG_TRAXRSVD48 */ \
{ .nar = 0x13, .apb = 0x004c }, /* XDMREG_TRAXRSVD4C */ \
{ .nar = 0x14, .apb = 0x0050 }, /* XDMREG_TRAXRSVD50 */ \
{ .nar = 0x15, .apb = 0x0054 }, /* XDMREG_TRAXRSVD54 */ \
{ .nar = 0x16, .apb = 0x0058 }, /* XDMREG_TRAXRSVD58 */ \
{ .nar = 0x17, .apb = 0x005c }, /* XDMREG_TRAXRSVD5C */ \
{ .nar = 0x18, .apb = 0x0060 }, /* XDMREG_TRAXRSVD60 */ \
{ .nar = 0x19, .apb = 0x0064 }, /* XDMREG_TRAXRSVD64 */ \
{ .nar = 0x1a, .apb = 0x0068 }, /* XDMREG_TRAXRSVD68 */ \
{ .nar = 0x1b, .apb = 0x006c }, /* XDMREG_TRAXRSVD6C */ \
{ .nar = 0x1c, .apb = 0x0070 }, /* XDMREG_TRAXRSVD70 */ \
{ .nar = 0x1d, .apb = 0x0074 }, /* XDMREG_TRAXRSVD74 */ \
{ .nar = 0x1e, .apb = 0x0078 }, /* XDMREG_CONFIGID0 */ \
{ .nar = 0x1f, .apb = 0x007c }, /* XDMREG_CONFIGID1 */ \
\ \
/* Performance Monitor Registers */ \ /* Performance Monitor Registers */ \
{ .nar = 0x20, .apb = 0x1000 }, /* XDMREG_PMG */ \ { .nar = 0x20, .apb = 0x1000 }, /* XDMREG_PMG */ \
@ -297,6 +329,11 @@ struct xtensa_dm_reg_offsets {
#define DEBUGCAUSE_DI BIT(5) /* Debug Interrupt */ #define DEBUGCAUSE_DI BIT(5) /* Debug Interrupt */
#define DEBUGCAUSE_VALID BIT(31) /* Pseudo-value to trigger reread (NX only) */ #define DEBUGCAUSE_VALID BIT(31) /* Pseudo-value to trigger reread (NX only) */
/* TRAXID */
#define TRAXID_PRODNO_TRAX 0 /* TRAXID.PRODNO value for TRAX module */
#define TRAXID_PRODNO_SHIFT 28
#define TRAXID_PRODNO_MASK 0xf
#define TRAXCTRL_TREN BIT(0) /* Trace enable. Tracing starts on 0->1 */ #define TRAXCTRL_TREN BIT(0) /* Trace enable. Tracing starts on 0->1 */
#define TRAXCTRL_TRSTP BIT(1) /* Trace Stop. Make 1 to stop trace. */ #define TRAXCTRL_TRSTP BIT(1) /* Trace Stop. Make 1 to stop trace. */
#define TRAXCTRL_PCMEN BIT(2) /* PC match enable */ #define TRAXCTRL_PCMEN BIT(2) /* PC match enable */
@ -512,6 +549,9 @@ static inline xtensa_dsr_t xtensa_dm_core_status_get(struct xtensa_debug_module
return dm->core_status.dsr; return dm->core_status.dsr;
} }
int xtensa_dm_read(struct xtensa_debug_module *dm, uint32_t addr, uint32_t *val);
int xtensa_dm_write(struct xtensa_debug_module *dm, uint32_t addr, uint32_t val);
int xtensa_dm_device_id_read(struct xtensa_debug_module *dm); int xtensa_dm_device_id_read(struct xtensa_debug_module *dm);
static inline xtensa_ocdid_t xtensa_dm_device_id_get(struct xtensa_debug_module *dm) static inline xtensa_ocdid_t xtensa_dm_device_id_get(struct xtensa_debug_module *dm)
{ {