mips: add breakpoint support for EJTAG 2.0
EJTAG 1.5, 2.0 and 2.5 have different breakpoint register addresses. This patch add support of EJTAG 2.0, which is part some broadcom SoCs. This work was testet on Broadcom BCM7401. Change-Id: I4b0ee23871fa9205f9001b7c9165e7b6ebe9ccbf Signed-off-by: Oleksij Rempel <linux@rempel-privat.de> Reviewed-on: http://openocd.zylin.com/1464 Tested-by: jenkins Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
This commit is contained in:
committed by
Spencer Oliver
parent
6a5848faeb
commit
d18807e7bc
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user