mips_ejtag.c: disable DMA for all platforms
[fw/openocd] / src / target / mips_ejtag.c
index 3726191273b78ad1aafd1e47a1f5ecf79aa3f156..c24cea3d45250014f898b8fd3ca11766e35311fa 100644 (file)
@@ -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,12 +281,13 @@ 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)
@@ -271,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;
@@ -315,13 +386,18 @@ int mips_ejtag_init(struct mips_ejtag *ejtag_info)
                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");
+       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;
+       }
 
        /* set initial state for ejtag control reg */
        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;
 }
 
@@ -349,7 +425,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);