aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/target/mips32.c22
-rw-r--r--src/target/mips_ejtag.c41
-rw-r--r--src/target/mips_ejtag.h51
-rw-r--r--src/target/mips_m4k.c61
4 files changed, 152 insertions, 23 deletions
diff --git a/src/target/mips32.c b/src/target/mips32.c
index 16988b5..1067f7b 100644
--- a/src/target/mips32.c
+++ b/src/target/mips32.c
@@ -472,11 +472,12 @@ int mips32_examine(struct target *target)
static int mips32_configure_ibs(struct target *target)
{
struct mips32_common *mips32 = target_to_mips32(target);
+ struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
int retval, i;
uint32_t bpinfo;
/* get number of inst breakpoints */
- retval = target_read_u32(target, EJTAG_IBS, &bpinfo);
+ retval = target_read_u32(target, ejtag_info->ejtag_ibs_addr, &bpinfo);
if (retval != ERROR_OK)
return retval;
@@ -487,21 +488,23 @@ static int mips32_configure_ibs(struct target *target)
for (i = 0; i < mips32->num_inst_bpoints; i++)
mips32->inst_break_list[i].reg_address =
- EJTAG_IBA1 + (0x100 * i);
+ ejtag_info->ejtag_iba0_addr +
+ (ejtag_info->ejtag_iba_step_size * i);
/* clear IBIS reg */
- retval = target_write_u32(target, EJTAG_IBS, 0);
+ retval = target_write_u32(target, ejtag_info->ejtag_ibs_addr, 0);
return retval;
}
static int mips32_configure_dbs(struct target *target)
{
struct mips32_common *mips32 = target_to_mips32(target);
+ struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
int retval, i;
uint32_t bpinfo;
/* get number of data breakpoints */
- retval = target_read_u32(target, EJTAG_DBS, &bpinfo);
+ retval = target_read_u32(target, ejtag_info->ejtag_dbs_addr, &bpinfo);
if (retval != ERROR_OK)
return retval;
@@ -512,10 +515,11 @@ static int mips32_configure_dbs(struct target *target)
for (i = 0; i < mips32->num_data_bpoints; i++)
mips32->data_break_list[i].reg_address =
- EJTAG_DBA1 + (0x100 * i);
+ ejtag_info->ejtag_dba0_addr +
+ (ejtag_info->ejtag_dba_step_size * i);
/* clear DBIS reg */
- retval = target_write_u32(target, EJTAG_DBS, 0);
+ retval = target_write_u32(target, ejtag_info->ejtag_dbs_addr, 0);
return retval;
}
@@ -523,6 +527,7 @@ int mips32_configure_break_unit(struct target *target)
{
/* get pointers to arch-specific information */
struct mips32_common *mips32 = target_to_mips32(target);
+ struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
int retval;
uint32_t dcr;
@@ -534,6 +539,11 @@ int mips32_configure_break_unit(struct target *target)
if (retval != ERROR_OK)
return retval;
+ /* EJTAG 2.0 does not specify EJTAG_DCR_IB and EJTAG_DCR_DB bits,
+ * assume IB and DB registers are always present. */
+ if (ejtag_info->ejtag_version == EJTAG_VERSION_20)
+ dcr |= EJTAG_DCR_IB | EJTAG_DCR_DB;
+
if (dcr & EJTAG_DCR_IB) {
retval = mips32_configure_ibs(target);
if (retval != ERROR_OK)
diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c
index 8574814..3457b78 100644
--- a/src/target/mips_ejtag.c
+++ b/src/target/mips_ejtag.c
@@ -303,6 +303,45 @@ int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info)
return ctx.retval;
}
+/* mips_ejtag_init_mmr - asign Memory-Mapped Registers depending
+ * on EJTAG version.
+ */
+static void mips_ejtag_init_mmr(struct mips_ejtag *ejtag_info)
+{
+ if (ejtag_info->ejtag_version == EJTAG_VERSION_20) {
+ ejtag_info->ejtag_ibs_addr = EJTAG_V20_IBS;
+ ejtag_info->ejtag_iba0_addr = EJTAG_V20_IBA0;
+ ejtag_info->ejtag_ibc_offs = EJTAG_V20_IBC_OFFS;
+ ejtag_info->ejtag_ibm_offs = EJTAG_V20_IBM_OFFS;
+
+ ejtag_info->ejtag_dbs_addr = EJTAG_V20_DBS;
+ ejtag_info->ejtag_dba0_addr = EJTAG_V20_DBA0;
+ ejtag_info->ejtag_dbc_offs = EJTAG_V20_DBC_OFFS;
+ ejtag_info->ejtag_dbm_offs = EJTAG_V20_DBM_OFFS;
+ ejtag_info->ejtag_dbv_offs = EJTAG_V20_DBV_OFFS;
+
+ ejtag_info->ejtag_iba_step_size = EJTAG_V20_IBAn_STEP;
+ ejtag_info->ejtag_dba_step_size = EJTAG_V20_DBAn_STEP;
+ } else {
+ ejtag_info->ejtag_ibs_addr = EJTAG_V25_IBS;
+ ejtag_info->ejtag_iba0_addr = EJTAG_V25_IBA0;
+ ejtag_info->ejtag_ibm_offs = EJTAG_V25_IBM_OFFS;
+ ejtag_info->ejtag_ibasid_offs = EJTAG_V25_IBASID_OFFS;
+ ejtag_info->ejtag_ibc_offs = EJTAG_V25_IBC_OFFS;
+
+ ejtag_info->ejtag_dbs_addr = EJTAG_V25_DBS;
+ ejtag_info->ejtag_dba0_addr = EJTAG_V25_DBA0;
+ ejtag_info->ejtag_dbm_offs = EJTAG_V25_DBM_OFFS;
+ ejtag_info->ejtag_dbasid_offs = EJTAG_V25_DBASID_OFFS;
+ ejtag_info->ejtag_dbc_offs = EJTAG_V25_DBC_OFFS;
+ ejtag_info->ejtag_dbv_offs = EJTAG_V25_DBV_OFFS;
+
+ ejtag_info->ejtag_iba_step_size = EJTAG_V25_IBAn_STEP;
+ ejtag_info->ejtag_dba_step_size = EJTAG_V25_DBAn_STEP;
+ }
+}
+
+
int mips_ejtag_init(struct mips_ejtag *ejtag_info)
{
int retval;
@@ -354,6 +393,8 @@ int mips_ejtag_init(struct mips_ejtag *ejtag_info)
ejtag_info->ejtag_ctrl = EJTAG_CTRL_ROCC | EJTAG_CTRL_PRACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_SETDEV;
ejtag_info->fast_access_save = -1;
+ mips_ejtag_init_mmr(ejtag_info);
+
return ERROR_OK;
}
diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h
index 760a7c5..db20e9d 100644
--- a/src/target/mips_ejtag.h
+++ b/src/target/mips_ejtag.h
@@ -113,10 +113,34 @@
#define EJTAG_DCR_MP (1 << 2)
/* breakpoint support */
-#define EJTAG_IBS 0xFF301000
-#define EJTAG_IBA1 0xFF301100
-#define EJTAG_DBS 0xFF302000
-#define EJTAG_DBA1 0xFF302100
+/* EJTAG_V20_* was tested on Broadcom BCM7401
+ * and may or will differ with other hardware. For example EZ4021-FC. */
+#define EJTAG_V20_IBS 0xFF300004
+#define EJTAG_V20_IBA0 0xFF300100
+#define EJTAG_V20_IBC_OFFS 0x4 /* IBC Offset */
+#define EJTAG_V20_IBM_OFFS 0x8
+#define EJTAG_V20_IBAn_STEP 0x10 /* Offset for next channel */
+#define EJTAG_V20_DBS 0xFF30008
+#define EJTAG_V20_DBA0 0xFF300200
+#define EJTAG_V20_DBC_OFFS 0x4
+#define EJTAG_V20_DBM_OFFS 0x8
+#define EJTAG_V20_DBV_OFFS 0xc
+#define EJTAG_V20_DBAn_STEP 0x10
+
+#define EJTAG_V25_IBS 0xFF301000
+#define EJTAG_V25_IBA0 0xFF301100
+#define EJTAG_V25_IBM_OFFS 0x8
+#define EJTAG_V25_IBASID_OFFS 0x10
+#define EJTAG_V25_IBC_OFFS 0x18
+#define EJTAG_V25_IBAn_STEP 0x100
+#define EJTAG_V25_DBS 0xFF302000
+#define EJTAG_V25_DBA0 0xFF302100
+#define EJTAG_V25_DBM_OFFS 0x8
+#define EJTAG_V25_DBASID_OFFS 0x10
+#define EJTAG_V25_DBC_OFFS 0x18
+#define EJTAG_V25_DBV_OFFS 0x20
+#define EJTAG_V25_DBAn_STEP 0x100
+
#define EJTAG_DBCn_NOSB (1 << 13)
#define EJTAG_DBCn_NOLB (1 << 12)
#define EJTAG_DBCn_BLM_MASK 0xff
@@ -141,6 +165,25 @@ struct mips_ejtag {
unsigned scan_delay;
int mode;
unsigned int ejtag_version;
+
+ /* Memory-Mapped Registers. This addresses are not same on different
+ * EJTAG versions. */
+ uint32_t ejtag_ibs_addr; /* Instruction Address Break Status */
+ uint32_t ejtag_iba0_addr; /* IAB channel 0 */
+ uint32_t ejtag_ibc_offs; /* IAB Control offset */
+ uint32_t ejtag_ibm_offs; /* IAB Mask offset */
+ uint32_t ejtag_ibasid_offs; /* IAB ASID (4Kc) */
+
+ uint32_t ejtag_dbs_addr; /* Data Address Break Status Register */
+ uint32_t ejtag_dba0_addr; /* DAB channel 0 */
+ uint32_t ejtag_dbc_offs; /* DAB Control offset */
+ uint32_t ejtag_dbm_offs; /* DAB Mask offset */
+ uint32_t ejtag_dbv_offs; /* DAB Value offset */
+ uint32_t ejtag_dbasid_offs; /* DAB ASID (4Kc) */
+
+ uint32_t ejtag_iba_step_size;
+ uint32_t ejtag_dba_step_size; /* siez of step till next
+ * *DBAn register. */
};
void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info,
diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c
index fc2a3f8..49edad1 100644
--- a/src/target/mips_m4k.c
+++ b/src/target/mips_m4k.c
@@ -51,30 +51,36 @@ static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
static int mips_m4k_examine_debug_reason(struct target *target)
{
+ struct mips32_common *mips32 = target_to_mips32(target);
+ struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
uint32_t break_status;
int retval;
if ((target->debug_reason != DBG_REASON_DBGRQ)
&& (target->debug_reason != DBG_REASON_SINGLESTEP)) {
/* get info about inst breakpoint support */
- retval = target_read_u32(target, EJTAG_IBS, &break_status);
+ retval = target_read_u32(target,
+ ejtag_info->ejtag_ibs_addr, &break_status);
if (retval != ERROR_OK)
return retval;
if (break_status & 0x1f) {
/* we have halted on a breakpoint */
- retval = target_write_u32(target, EJTAG_IBS, 0);
+ retval = target_write_u32(target,
+ ejtag_info->ejtag_ibs_addr, 0);
if (retval != ERROR_OK)
return retval;
target->debug_reason = DBG_REASON_BREAKPOINT;
}
/* get info about data breakpoint support */
- retval = target_read_u32(target, EJTAG_DBS, &break_status);
+ retval = target_read_u32(target,
+ ejtag_info->ejtag_dbs_addr, &break_status);
if (retval != ERROR_OK)
return retval;
if (break_status & 0x1f) {
/* we have halted on a breakpoint */
- retval = target_write_u32(target, EJTAG_DBS, 0);
+ retval = target_write_u32(target,
+ ejtag_info->ejtag_dbs_addr, 0);
if (retval != ERROR_OK)
return retval;
target->debug_reason = DBG_REASON_WATCHPOINT;
@@ -587,6 +593,7 @@ static int mips_m4k_set_breakpoint(struct target *target,
struct breakpoint *breakpoint)
{
struct mips32_common *mips32 = target_to_mips32(target);
+ struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
struct mips32_comparator *comparator_list = mips32->inst_break_list;
int retval;
@@ -608,10 +615,19 @@ static int mips_m4k_set_breakpoint(struct target *target,
breakpoint->set = bp_num + 1;
comparator_list[bp_num].used = 1;
comparator_list[bp_num].bp_value = breakpoint->address;
+
+ /* EJTAG 2.0 uses 30bit IBA. First 2 bits are reserved.
+ * Warning: there is no IB ASID registers in 2.0.
+ * Do not set it! :) */
+ if (ejtag_info->ejtag_version == EJTAG_VERSION_20)
+ comparator_list[bp_num].bp_value &= 0xFFFFFFFC;
+
target_write_u32(target, comparator_list[bp_num].reg_address,
comparator_list[bp_num].bp_value);
- target_write_u32(target, comparator_list[bp_num].reg_address + 0x08, 0x00000000);
- target_write_u32(target, comparator_list[bp_num].reg_address + 0x18, 1);
+ target_write_u32(target, comparator_list[bp_num].reg_address +
+ ejtag_info->ejtag_ibm_offs, 0x00000000);
+ target_write_u32(target, comparator_list[bp_num].reg_address +
+ ejtag_info->ejtag_ibc_offs, 1);
LOG_DEBUG("bpid: %d, bp_num %i bp_value 0x%" PRIx32 "",
breakpoint->unique_id,
bp_num, comparator_list[bp_num].bp_value);
@@ -668,6 +684,7 @@ static int mips_m4k_unset_breakpoint(struct target *target,
{
/* get pointers to arch-specific information */
struct mips32_common *mips32 = target_to_mips32(target);
+ struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
struct mips32_comparator *comparator_list = mips32->inst_break_list;
int retval;
@@ -688,7 +705,8 @@ static int mips_m4k_unset_breakpoint(struct target *target,
bp_num);
comparator_list[bp_num].used = 0;
comparator_list[bp_num].bp_value = 0;
- target_write_u32(target, comparator_list[bp_num].reg_address + 0x18, 0);
+ target_write_u32(target, comparator_list[bp_num].reg_address +
+ ejtag_info->ejtag_ibc_offs, 0);
} else {
/* restore original instruction (kept in target endianness) */
@@ -777,6 +795,7 @@ static int mips_m4k_set_watchpoint(struct target *target,
struct watchpoint *watchpoint)
{
struct mips32_common *mips32 = target_to_mips32(target);
+ struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
struct mips32_comparator *comparator_list = mips32->data_break_list;
int wp_num = 0;
/*
@@ -826,11 +845,25 @@ static int mips_m4k_set_watchpoint(struct target *target,
watchpoint->set = wp_num + 1;
comparator_list[wp_num].used = 1;
comparator_list[wp_num].bp_value = watchpoint->address;
- target_write_u32(target, comparator_list[wp_num].reg_address, comparator_list[wp_num].bp_value);
- target_write_u32(target, comparator_list[wp_num].reg_address + 0x08, 0x00000000);
- target_write_u32(target, comparator_list[wp_num].reg_address + 0x10, 0x00000000);
- target_write_u32(target, comparator_list[wp_num].reg_address + 0x18, enable);
- target_write_u32(target, comparator_list[wp_num].reg_address + 0x20, 0);
+
+ /* EJTAG 2.0 uses 29bit DBA. First 3 bits are reserved.
+ * There is as well no ASID register support. */
+ if (ejtag_info->ejtag_version == EJTAG_VERSION_20)
+ comparator_list[wp_num].bp_value &= 0xFFFFFFF8;
+ else
+ target_write_u32(target, comparator_list[wp_num].reg_address +
+ ejtag_info->ejtag_dbasid_offs, 0x00000000);
+
+ target_write_u32(target, comparator_list[wp_num].reg_address,
+ comparator_list[wp_num].bp_value);
+ target_write_u32(target, comparator_list[wp_num].reg_address +
+ ejtag_info->ejtag_dbm_offs, 0x00000000);
+
+ target_write_u32(target, comparator_list[wp_num].reg_address +
+ ejtag_info->ejtag_dbc_offs, enable);
+ /* TODO: probably this value is ignored on 2.0 */
+ target_write_u32(target, comparator_list[wp_num].reg_address +
+ ejtag_info->ejtag_dbv_offs, 0);
LOG_DEBUG("wp_num %i bp_value 0x%" PRIx32 "", wp_num, comparator_list[wp_num].bp_value);
return ERROR_OK;
@@ -841,6 +874,7 @@ static int mips_m4k_unset_watchpoint(struct target *target,
{
/* get pointers to arch-specific information */
struct mips32_common *mips32 = target_to_mips32(target);
+ struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
struct mips32_comparator *comparator_list = mips32->data_break_list;
if (!watchpoint->set) {
@@ -855,7 +889,8 @@ static int mips_m4k_unset_watchpoint(struct target *target,
}
comparator_list[wp_num].used = 0;
comparator_list[wp_num].bp_value = 0;
- target_write_u32(target, comparator_list[wp_num].reg_address + 0x18, 0);
+ target_write_u32(target, comparator_list[wp_num].reg_address +
+ ejtag_info->ejtag_dbc_offs, 0);
watchpoint->set = 0;
return ERROR_OK;