X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Fmips_ejtag.c;h=2a16193f887e3aa28760cd838a7f416bd72fd6cb;hp=44345455251ecd421110e524dbb38a59568fb848;hb=5387d616a3d1b4550f9acecda26ead380d37dedf;hpb=9695564e6321b24edfc03cac555a914dcc7154f6 diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c index 4434545525..2a16193f88 100644 --- a/src/target/mips_ejtag.c +++ b/src/target/mips_ejtag.c @@ -19,7 +19,7 @@ * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -28,6 +28,7 @@ #include "mips32.h" #include "mips_ejtag.h" +#include "mips32_dmaacc.h" void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, int new_instr) { @@ -237,11 +238,41 @@ exit: return ctx.retval; } +/* + * Disable memory protection for 0xFF20.0000–0xFF3F.FFFF + * It is needed by EJTAG 1.5-2.0, especially for BMIPS CPUs + * For example bcm7401 and others. At leas on some + * CPUs, DebugMode wont start if this bit is not removed. + */ +static int disable_dcr_mp(struct mips_ejtag *ejtag_info) +{ + uint32_t dcr; + int retval; + + retval = mips32_dmaacc_read_mem(ejtag_info, EJTAG_DCR, 4, 1, &dcr); + if (retval != ERROR_OK) + goto error; + + dcr &= ~EJTAG_DCR_MP; + retval = mips32_dmaacc_write_mem(ejtag_info, EJTAG_DCR, 4, 1, &dcr); + if (retval != ERROR_OK) + goto error; + return ERROR_OK; +error: + LOG_ERROR("Failed to remove DCR MPbit!"); + return retval; +} + int mips_ejtag_enter_debug(struct mips_ejtag *ejtag_info) { uint32_t ejtag_ctrl; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); + if (ejtag_info->ejtag_version == EJTAG_VERSION_20) { + if (disable_dcr_mp(ejtag_info) != ERROR_OK) + goto error; + } + /* set debug break bit */ ejtag_ctrl = ejtag_info->ejtag_ctrl | EJTAG_CTRL_JTAGBRK; mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); @@ -250,18 +281,19 @@ int mips_ejtag_enter_debug(struct mips_ejtag *ejtag_info) ejtag_ctrl = ejtag_info->ejtag_ctrl; mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); LOG_DEBUG("ejtag_ctrl: 0x%8.8" PRIx32 "", ejtag_ctrl); - if ((ejtag_ctrl & EJTAG_CTRL_BRKST) == 0) { - LOG_ERROR("Failed to enter Debug Mode!"); - return ERROR_FAIL; - } + if ((ejtag_ctrl & EJTAG_CTRL_BRKST) == 0) + goto error; return ERROR_OK; +error: + LOG_ERROR("Failed to enter Debug Mode!"); + return ERROR_FAIL; } int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info) { - uint32_t instr = MIPS32_DRET; - struct pracc_queue_info ctx = {.max_code = 1, .pracc_list = &instr, .code_count = 1, .store_count = 0}; + uint32_t pracc_list[] = {MIPS32_DRET, 0}; + struct pracc_queue_info ctx = {.max_code = 1, .pracc_list = pracc_list, .code_count = 1, .store_count = 0}; /* execute our dret instruction */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); @@ -271,9 +303,94 @@ 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; + } +} + +static void ejtag_v20_print_imp(struct mips_ejtag *ejtag_info) +{ + LOG_DEBUG("EJTAG v2.0: features:%s%s%s%s%s%s%s%s", + EJTAG_IMP_HAS(EJTAG_V20_IMP_SDBBP) ? " SDBBP_SPECIAL2" : " SDBBP", + EJTAG_IMP_HAS(EJTAG_V20_IMP_EADDR_NO32BIT) ? " EADDR>32bit" : " EADDR=32bit", + EJTAG_IMP_HAS(EJTAG_V20_IMP_COMPLEX_BREAK) ? " COMPLEX_BREAK" : "", + EJTAG_IMP_HAS(EJTAG_V20_IMP_DCACHE_COH) ? " DCACHE_COH" : " DCACHE_NOT_COH", + EJTAG_IMP_HAS(EJTAG_V20_IMP_ICACHE_COH) ? " ICACHE_COH" : " ICACHE_NOT_COH", + EJTAG_IMP_HAS(EJTAG_V20_IMP_NOPB) ? " noPB" : " PB", + EJTAG_IMP_HAS(EJTAG_V20_IMP_NODB) ? " noDB" : " DB", + EJTAG_IMP_HAS(EJTAG_V20_IMP_NOIB) ? " noIB" : " IB"); + LOG_DEBUG("EJTAG v2.0: Break Channels: %" PRIu8, + (uint8_t)((ejtag_info->impcode >> EJTAG_V20_IMP_BCHANNELS_SHIFT) & + EJTAG_V20_IMP_BCHANNELS_MASK)); +} + +static void ejtag_v26_print_imp(struct mips_ejtag *ejtag_info) +{ + LOG_DEBUG("EJTAG v2.6: features:%s%s", + EJTAG_IMP_HAS(EJTAG_V26_IMP_R3K) ? " R3k" : " R4k", + EJTAG_IMP_HAS(EJTAG_V26_IMP_DINT) ? " DINT" : ""); +} + +static void ejtag_main_print_imp(struct mips_ejtag *ejtag_info) +{ + LOG_DEBUG("EJTAG main: features:%s%s%s%s%s", + EJTAG_IMP_HAS(EJTAG_IMP_ASID8) ? " ASID_8" : "", + EJTAG_IMP_HAS(EJTAG_IMP_ASID6) ? " ASID_6" : "", + EJTAG_IMP_HAS(EJTAG_IMP_MIPS16) ? " MIPS16" : "", + EJTAG_IMP_HAS(EJTAG_IMP_NODMA) ? " noDMA" : " DMA", + EJTAG_IMP_HAS(EJTAG_DCR_MIPS64) ? " MIPS64" : " MIPS32"); + + switch (ejtag_info->ejtag_version) { + case EJTAG_VERSION_20: + ejtag_v20_print_imp(ejtag_info); + break; + case EJTAG_VERSION_25: + case EJTAG_VERSION_26: + case EJTAG_VERSION_31: + case EJTAG_VERSION_41: + case EJTAG_VERSION_51: + ejtag_v26_print_imp(ejtag_info); + break; + default: + break; + } +} + int mips_ejtag_init(struct mips_ejtag *ejtag_info) { - uint32_t ejtag_version; int retval; retval = mips_ejtag_get_impcode(ejtag_info, &ejtag_info->impcode); @@ -282,47 +399,48 @@ int mips_ejtag_init(struct mips_ejtag *ejtag_info) LOG_DEBUG("impcode: 0x%8.8" PRIx32 "", ejtag_info->impcode); /* get ejtag version */ - ejtag_version = ((ejtag_info->impcode >> 29) & 0x07); + ejtag_info->ejtag_version = ((ejtag_info->impcode >> 29) & 0x07); - switch (ejtag_version) { - case 0: + switch (ejtag_info->ejtag_version) { + case EJTAG_VERSION_20: LOG_DEBUG("EJTAG: Version 1 or 2.0 Detected"); break; - case 1: + case EJTAG_VERSION_25: LOG_DEBUG("EJTAG: Version 2.5 Detected"); break; - case 2: + case EJTAG_VERSION_26: LOG_DEBUG("EJTAG: Version 2.6 Detected"); break; - case 3: + case EJTAG_VERSION_31: LOG_DEBUG("EJTAG: Version 3.1 Detected"); break; - case 4: + case EJTAG_VERSION_41: LOG_DEBUG("EJTAG: Version 4.1 Detected"); break; - case 5: + case EJTAG_VERSION_51: LOG_DEBUG("EJTAG: Version 5.1 Detected"); break; default: LOG_DEBUG("EJTAG: Unknown Version Detected"); break; } - LOG_DEBUG("EJTAG: features:%s%s%s%s%s%s%s", - ejtag_info->impcode & EJTAG_IMP_R3K ? " R3k" : " R4k", - ejtag_info->impcode & EJTAG_IMP_DINT ? " DINT" : "", - ejtag_info->impcode & (1 << 22) ? " ASID_8" : "", - ejtag_info->impcode & (1 << 21) ? " ASID_6" : "", - ejtag_info->impcode & EJTAG_IMP_MIPS16 ? " MIPS16" : "", - ejtag_info->impcode & EJTAG_IMP_NODMA ? " noDMA" : " DMA", - ejtag_info->impcode & EJTAG_DCR_MIPS64 ? " MIPS64" : " MIPS32"); - - if ((ejtag_info->impcode & EJTAG_IMP_NODMA) == 0) - LOG_DEBUG("EJTAG: DMA Access Mode Support Enabled"); - - /* set initial state for ejtag control reg */ - ejtag_info->ejtag_ctrl = EJTAG_CTRL_ROCC | EJTAG_CTRL_PRACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_SETDEV; + ejtag_main_print_imp(ejtag_info); + + if ((ejtag_info->impcode & EJTAG_IMP_NODMA) == 0) { + LOG_DEBUG("EJTAG: DMA Access Mode detected. Disabling to " + "workaround current broken code."); + ejtag_info->impcode |= EJTAG_IMP_NODMA; + } + + ejtag_info->ejtag_ctrl = EJTAG_CTRL_PRACC | EJTAG_CTRL_PROBEN; + + if (ejtag_info->ejtag_version != EJTAG_VERSION_20) + ejtag_info->ejtag_ctrl |= EJTAG_CTRL_ROCC | EJTAG_CTRL_SETDEV; + ejtag_info->fast_access_save = -1; + mips_ejtag_init_mmr(ejtag_info); + return ERROR_OK; } @@ -350,7 +468,7 @@ int mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint32_ fields[1].in_value = NULL; buf_set_u32(t, 0, 32, *data); } else - fields[1].in_value = (void *) data; + fields[1].in_value = (uint8_t *) data; jtag_add_dr_scan(tap, 2, fields, TAP_IDLE);