target/riscv: support multiple DMs
Support assign DMI address of the debug module by pass -dbgbase to the target create command Change-Id: I774c3746567f6e6d77c43a62dea5e9e67bb25770 Signed-off-by: Mark Zhuang <mark.zhuang@spacemit.com>
This commit is contained in:
parent
895185caff
commit
80a8aa9e19
|
@ -123,7 +123,8 @@ typedef enum slot {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
int abs_chain_position;
|
int abs_chain_position;
|
||||||
|
/* The base address to access this DM on DMI */
|
||||||
|
uint32_t base;
|
||||||
/* The number of harts connected to this DM. */
|
/* The number of harts connected to this DM. */
|
||||||
int hart_count;
|
int hart_count;
|
||||||
/* Indicates we already reset this DM, so don't need to do it again. */
|
/* Indicates we already reset this DM, so don't need to do it again. */
|
||||||
|
@ -243,7 +244,8 @@ static dm013_info_t *get_dm(struct target *target)
|
||||||
dm013_info_t *entry;
|
dm013_info_t *entry;
|
||||||
dm013_info_t *dm = NULL;
|
dm013_info_t *dm = NULL;
|
||||||
list_for_each_entry(entry, &dm_list, list) {
|
list_for_each_entry(entry, &dm_list, list) {
|
||||||
if (entry->abs_chain_position == abs_chain_position) {
|
if (entry->abs_chain_position == abs_chain_position
|
||||||
|
&& entry->base == target->dbgbase) {
|
||||||
dm = entry;
|
dm = entry;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -255,6 +257,11 @@ static dm013_info_t *get_dm(struct target *target)
|
||||||
if (!dm)
|
if (!dm)
|
||||||
return NULL;
|
return NULL;
|
||||||
dm->abs_chain_position = abs_chain_position;
|
dm->abs_chain_position = abs_chain_position;
|
||||||
|
|
||||||
|
/* Safety check for dbgbase */
|
||||||
|
assert(target->dbgbase_set || target->dbgbase == 0);
|
||||||
|
|
||||||
|
dm->base = target->dbgbase;
|
||||||
dm->current_hartid = 0;
|
dm->current_hartid = 0;
|
||||||
dm->hart_count = -1;
|
dm->hart_count = -1;
|
||||||
INIT_LIST_HEAD(&dm->target_list);
|
INIT_LIST_HEAD(&dm->target_list);
|
||||||
|
@ -378,12 +385,15 @@ static void decode_dm(char *text, unsigned int address, unsigned int data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void decode_dmi(char *text, unsigned int address, unsigned int data)
|
static void decode_dmi(struct target *target, char *text, unsigned int address, unsigned int data)
|
||||||
{
|
{
|
||||||
decode_dm(text, address, data);
|
dm013_info_t *dm = get_dm(target);
|
||||||
|
if (!dm)
|
||||||
|
return;
|
||||||
|
decode_dm(text, address - dm->base, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_field(int idle, const struct scan_field *field)
|
static void dump_field(struct target *target, int idle, const struct scan_field *field)
|
||||||
{
|
{
|
||||||
static const char * const op_string[] = {"-", "r", "w", "?"};
|
static const char * const op_string[] = {"-", "r", "w", "?"};
|
||||||
static const char * const status_string[] = {"+", "?", "F", "b"};
|
static const char * const status_string[] = {"+", "?", "F", "b"};
|
||||||
|
@ -409,8 +419,8 @@ static void dump_field(int idle, const struct scan_field *field)
|
||||||
|
|
||||||
char out_text[500];
|
char out_text[500];
|
||||||
char in_text[500];
|
char in_text[500];
|
||||||
decode_dmi(out_text, out_address, out_data);
|
decode_dmi(target, out_text, out_address, out_data);
|
||||||
decode_dmi(in_text, in_address, in_data);
|
decode_dmi(target, in_text, in_address, in_data);
|
||||||
if (in_text[0] || out_text[0]) {
|
if (in_text[0] || out_text[0]) {
|
||||||
log_printf_lf(LOG_LVL_DEBUG, __FILE__, __LINE__, "scan", "%s -> %s",
|
log_printf_lf(LOG_LVL_DEBUG, __FILE__, __LINE__, "scan", "%s -> %s",
|
||||||
out_text, in_text);
|
out_text, in_text);
|
||||||
|
@ -549,7 +559,7 @@ static dmi_status_t dmi_scan(struct target *target, uint32_t *address_in,
|
||||||
|
|
||||||
if (address_in)
|
if (address_in)
|
||||||
*address_in = buf_get_u32(in, DTM_DMI_ADDRESS_OFFSET, info->abits);
|
*address_in = buf_get_u32(in, DTM_DMI_ADDRESS_OFFSET, info->abits);
|
||||||
dump_field(idle_count, &field);
|
dump_field(target, idle_count, &field);
|
||||||
return buf_get_u32(in, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH);
|
return buf_get_u32(in, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -698,7 +708,10 @@ static int dm_op_timeout(struct target *target, uint32_t *data_in,
|
||||||
bool *dmi_busy_encountered, int op, uint32_t address,
|
bool *dmi_busy_encountered, int op, uint32_t address,
|
||||||
uint32_t data_out, int timeout_sec, bool exec, bool ensure_success)
|
uint32_t data_out, int timeout_sec, bool exec, bool ensure_success)
|
||||||
{
|
{
|
||||||
dmi_op_timeout(target, data_in, dmi_busy_encountered, op, address,
|
dm013_info_t *dm = get_dm(target);
|
||||||
|
if (!dm)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
return dmi_op_timeout(target, data_in, dmi_busy_encountered, op, address + dm->base,
|
||||||
data_out, timeout_sec, exec, ensure_success);
|
data_out, timeout_sec, exec, ensure_success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -706,29 +719,44 @@ static int dm_op(struct target *target, uint32_t *data_in,
|
||||||
bool *dmi_busy_encountered, int op, uint32_t address,
|
bool *dmi_busy_encountered, int op, uint32_t address,
|
||||||
uint32_t data_out, bool exec, bool ensure_success)
|
uint32_t data_out, bool exec, bool ensure_success)
|
||||||
{
|
{
|
||||||
return dmi_op(target, data_in, dmi_busy_encountered, op, address,
|
dm013_info_t *dm = get_dm(target);
|
||||||
|
if (!dm)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
return dmi_op(target, data_in, dmi_busy_encountered, op, address + dm->base,
|
||||||
data_out, exec, ensure_success);
|
data_out, exec, ensure_success);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dm_read(struct target *target, uint32_t *value, uint32_t address)
|
static int dm_read(struct target *target, uint32_t *value, uint32_t address)
|
||||||
{
|
{
|
||||||
return dmi_read(target, value, address);
|
dm013_info_t *dm = get_dm(target);
|
||||||
|
if (!dm)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
return dmi_read(target, value, address + dm->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dm_read_exec(struct target *target, uint32_t *value, uint32_t address)
|
static int dm_read_exec(struct target *target, uint32_t *value, uint32_t address)
|
||||||
{
|
{
|
||||||
return dmi_read_exec(target, value, address);
|
dm013_info_t *dm = get_dm(target);
|
||||||
|
if (!dm)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
return dmi_read_exec(target, value, address + dm->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dm_write(struct target *target, uint32_t address, uint32_t value)
|
static int dm_write(struct target *target, uint32_t address, uint32_t value)
|
||||||
{
|
{
|
||||||
return dmi_write(target, address, value);
|
dm013_info_t *dm = get_dm(target);
|
||||||
|
if (!dm)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
return dmi_write(target, address + dm->base, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dm_write_exec(struct target *target, uint32_t address,
|
static int dm_write_exec(struct target *target, uint32_t address,
|
||||||
uint32_t value, bool ensure_success)
|
uint32_t value, bool ensure_success)
|
||||||
{
|
{
|
||||||
return dmi_write_exec(target, address, value, ensure_success);
|
dm013_info_t *dm = get_dm(target);
|
||||||
|
if (!dm)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
return dmi_write_exec(target, address + dm->base, value, ensure_success);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dmstatus_read_timeout(struct target *target, uint32_t *dmstatus,
|
static int dmstatus_read_timeout(struct target *target, uint32_t *dmstatus,
|
||||||
|
@ -1739,6 +1767,8 @@ static int examine(struct target *target)
|
||||||
{
|
{
|
||||||
/* Don't need to select dbus, since the first thing we do is read dtmcontrol. */
|
/* Don't need to select dbus, since the first thing we do is read dtmcontrol. */
|
||||||
|
|
||||||
|
LOG_TARGET_DEBUG(target, "dbgbase=0x%x", target->dbgbase);
|
||||||
|
|
||||||
uint32_t dtmcontrol = dtmcontrol_scan(target, 0);
|
uint32_t dtmcontrol = dtmcontrol_scan(target, 0);
|
||||||
LOG_TARGET_DEBUG(target, "dtmcontrol=0x%x", dtmcontrol);
|
LOG_TARGET_DEBUG(target, "dtmcontrol=0x%x", dtmcontrol);
|
||||||
LOG_TARGET_DEBUG(target, " dmireset=%d", get_field(dtmcontrol, DTM_DTMCS_DMIRESET));
|
LOG_TARGET_DEBUG(target, " dmireset=%d", get_field(dtmcontrol, DTM_DTMCS_DMIRESET));
|
||||||
|
@ -1757,7 +1787,7 @@ static int examine(struct target *target)
|
||||||
}
|
}
|
||||||
|
|
||||||
riscv013_info_t *info = get_info(target);
|
riscv013_info_t *info = get_info(target);
|
||||||
/* TODO: This won't be true if there are multiple DMs. */
|
|
||||||
info->index = target->coreid;
|
info->index = target->coreid;
|
||||||
info->abits = get_field(dtmcontrol, DTM_DTMCS_ABITS);
|
info->abits = get_field(dtmcontrol, DTM_DTMCS_ABITS);
|
||||||
info->dtmcs_idle = get_field(dtmcontrol, DTM_DTMCS_IDLE);
|
info->dtmcs_idle = get_field(dtmcontrol, DTM_DTMCS_IDLE);
|
||||||
|
@ -1882,7 +1912,7 @@ static int examine(struct target *target)
|
||||||
LOG_TARGET_DEBUG(target, "Detected %d harts.", dm->hart_count);
|
LOG_TARGET_DEBUG(target, "Detected %d harts.", dm->hart_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dm->hart_count == 0) {
|
if (dm->hart_count <= 0) {
|
||||||
LOG_TARGET_ERROR(target, "No harts found!");
|
LOG_TARGET_ERROR(target, "No harts found!");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -4909,12 +4939,18 @@ static int riscv013_dmi_write_u64_bits(struct target *target)
|
||||||
|
|
||||||
void riscv013_fill_dm_write_u64(struct target *target, char *buf, int a, uint64_t d)
|
void riscv013_fill_dm_write_u64(struct target *target, char *buf, int a, uint64_t d)
|
||||||
{
|
{
|
||||||
riscv013_fill_dmi_write_u64(target, buf, a, d);
|
dm013_info_t *dm = get_dm(target);
|
||||||
|
if (!dm)
|
||||||
|
return;
|
||||||
|
riscv013_fill_dmi_write_u64(target, buf, a + dm->base, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
void riscv013_fill_dm_read_u64(struct target *target, char *buf, int a)
|
void riscv013_fill_dm_read_u64(struct target *target, char *buf, int a)
|
||||||
{
|
{
|
||||||
riscv013_fill_dmi_read_u64(target, buf, a);
|
dm013_info_t *dm = get_dm(target);
|
||||||
|
if (!dm)
|
||||||
|
return;
|
||||||
|
riscv013_fill_dmi_read_u64(target, buf, a + dm->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
void riscv013_fill_dm_nop_u64(struct target *target, char *buf)
|
void riscv013_fill_dm_nop_u64(struct target *target, char *buf)
|
||||||
|
|
Loading…
Reference in New Issue