mips32: add fastdata loader working area
[fw/openocd] / src / target / mips_m4k.c
index f581ddf152d50aef906c57a439d141d5e95eb72a..8afee9cd66a7a19aab138a21c27c1052430acd5a 100644 (file)
 #include "target_type.h"
 #include "register.h"
 
-int mips_m4k_examine_debug_reason(struct target *target)
+static void mips_m4k_enable_breakpoints(struct target *target);
+static void mips_m4k_enable_watchpoints(struct target *target);
+static int mips_m4k_set_breakpoint(struct target *target,
+               struct breakpoint *breakpoint);
+static int mips_m4k_unset_breakpoint(struct target *target,
+               struct breakpoint *breakpoint);
+
+static int mips_m4k_examine_debug_reason(struct target *target)
 {
        uint32_t break_status;
        int retval;
@@ -66,7 +73,7 @@ int mips_m4k_examine_debug_reason(struct target *target)
        return ERROR_OK;
 }
 
-int mips_m4k_debug_entry(struct target *target)
+static int mips_m4k_debug_entry(struct target *target)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
@@ -104,7 +111,7 @@ int mips_m4k_debug_entry(struct target *target)
        return ERROR_OK;
 }
 
-int mips_m4k_poll(struct target *target)
+static int mips_m4k_poll(struct target *target)
 {
        int retval;
        struct mips32_common *mips32 = target_to_mips32(target);
@@ -112,8 +119,7 @@ int mips_m4k_poll(struct target *target)
        uint32_t ejtag_ctrl = ejtag_info->ejtag_ctrl;
 
        /* read ejtag control reg */
-       jtag_set_end_state(TAP_IDLE);
-       mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
+       mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
        mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
 
        /* clear this bit before handling polling
@@ -122,10 +128,9 @@ int mips_m4k_poll(struct target *target)
        {
                /* we have detected a reset, clear flag
                 * otherwise ejtag will not work */
-               jtag_set_end_state(TAP_IDLE);
                ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_ROCC;
 
-               mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
+               mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
                mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
                LOG_DEBUG("Reset Detected");
        }
@@ -135,8 +140,7 @@ int mips_m4k_poll(struct target *target)
        {
                if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET))
                {
-                       jtag_set_end_state(TAP_IDLE);
-                       mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT, NULL);
+                       mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT);
 
                        target->state = TARGET_HALTED;
 
@@ -165,7 +169,7 @@ int mips_m4k_poll(struct target *target)
        return ERROR_OK;
 }
 
-int mips_m4k_halt(struct target *target)
+static int mips_m4k_halt(struct target *target)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
@@ -210,41 +214,31 @@ int mips_m4k_halt(struct target *target)
        return ERROR_OK;
 }
 
-int mips_m4k_assert_reset(struct target *target)
+static int mips_m4k_assert_reset(struct target *target)
 {
-       struct mips32_common *mips32 = target_to_mips32(target);
-       struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
+       struct mips_m4k_common *mips_m4k = target_to_m4k(target);
+       struct mips_ejtag *ejtag_info = &mips_m4k->mips32.ejtag_info;
+       int assert_srst = 1;
 
        LOG_DEBUG("target->state: %s",
                target_state_name(target));
 
        enum reset_types jtag_reset_config = jtag_get_reset_config();
+
        if (!(jtag_reset_config & RESET_HAS_SRST))
-       {
-               LOG_ERROR("Can't assert SRST");
-               return ERROR_FAIL;
-       }
+               assert_srst = 0;
 
        if (target->reset_halt)
        {
                /* use hardware to catch reset */
-               jtag_set_end_state(TAP_IDLE);
-               mips_ejtag_set_instr(ejtag_info, EJTAG_INST_EJTAGBOOT, NULL);
+               mips_ejtag_set_instr(ejtag_info, EJTAG_INST_EJTAGBOOT);
        }
        else
        {
-               jtag_set_end_state(TAP_IDLE);
-               mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT, NULL);
+               mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT);
        }
 
-       if (strcmp(target->variant, "ejtag_srst") == 0)
-       {
-               uint32_t ejtag_ctrl = ejtag_info->ejtag_ctrl | EJTAG_CTRL_PRRST | EJTAG_CTRL_PERRST;
-               LOG_DEBUG("Using EJTAG reset (PRRST) to reset processor...");
-               mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
-               mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
-       }
-       else
+       if (assert_srst)
        {
                /* here we should issue a srst only, but we may have to assert trst as well */
                if (jtag_reset_config & RESET_SRST_PULLS_TRST)
@@ -256,11 +250,38 @@ int mips_m4k_assert_reset(struct target *target)
                        jtag_add_reset(0, 1);
                }
        }
+       else
+       {
+               if (mips_m4k->is_pic32mx)
+               {
+                       uint32_t mchip_cmd;
+
+                       LOG_DEBUG("Using MTAP reset to reset processor...");
+
+                       /* use microchip specific MTAP reset */
+                       mips_ejtag_set_instr(ejtag_info, MTAP_SW_MTAP);
+                       mips_ejtag_set_instr(ejtag_info, MTAP_COMMAND);
+
+                       mchip_cmd = MCHP_ASERT_RST;
+                       mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
+                       mchip_cmd = MCHP_DE_ASSERT_RST;
+                       mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
+                       mips_ejtag_set_instr(ejtag_info, MTAP_SW_ETAP);
+               }
+               else
+               {
+                       /* use ejtag reset - not supported by all cores */
+                       uint32_t ejtag_ctrl = ejtag_info->ejtag_ctrl | EJTAG_CTRL_PRRST | EJTAG_CTRL_PERRST;
+                       LOG_DEBUG("Using EJTAG reset (PRRST) to reset processor...");
+                       mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
+                       mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
+               }
+       }
 
        target->state = TARGET_RESET;
        jtag_add_sleep(50000);
 
-       register_cache_invalidate(mips32->core_cache);
+       register_cache_invalidate(mips_m4k->mips32.core_cache);
 
        if (target->reset_halt)
        {
@@ -272,7 +293,7 @@ int mips_m4k_assert_reset(struct target *target)
        return ERROR_OK;
 }
 
-int mips_m4k_deassert_reset(struct target *target)
+static int mips_m4k_deassert_reset(struct target *target)
 {
        LOG_DEBUG("target->state: %s",
                target_state_name(target));
@@ -283,13 +304,13 @@ int mips_m4k_deassert_reset(struct target *target)
        return ERROR_OK;
 }
 
-int mips_m4k_soft_reset_halt(struct target *target)
+static int mips_m4k_soft_reset_halt(struct target *target)
 {
        /* TODO */
        return ERROR_OK;
 }
 
-int mips_m4k_single_step_core(struct target *target)
+static int mips_m4k_single_step_core(struct target *target)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
@@ -308,7 +329,8 @@ int mips_m4k_single_step_core(struct target *target)
        return ERROR_OK;
 }
 
-int mips_m4k_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution)
+static int mips_m4k_resume(struct target *target, int current,
+               uint32_t address, int handle_breakpoints, int debug_execution)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
@@ -383,7 +405,8 @@ int mips_m4k_resume(struct target *target, int current, uint32_t address, int ha
        return ERROR_OK;
 }
 
-int mips_m4k_step(struct target *target, int current, uint32_t address, int handle_breakpoints)
+static int mips_m4k_step(struct target *target, int current,
+               uint32_t address, int handle_breakpoints)
 {
        /* get pointers to arch-specific information */
        struct mips32_common *mips32 = target_to_mips32(target);
@@ -438,7 +461,7 @@ int mips_m4k_step(struct target *target, int current, uint32_t address, int hand
        return ERROR_OK;
 }
 
-void mips_m4k_enable_breakpoints(struct target *target)
+static void mips_m4k_enable_breakpoints(struct target *target)
 {
        struct breakpoint *breakpoint = target->breakpoints;
 
@@ -451,7 +474,8 @@ void mips_m4k_enable_breakpoints(struct target *target)
        }
 }
 
-int mips_m4k_set_breakpoint(struct target *target, struct breakpoint *breakpoint)
+static int mips_m4k_set_breakpoint(struct target *target,
+               struct breakpoint *breakpoint)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips32_comparator * comparator_list = mips32->inst_break_list;
@@ -473,7 +497,7 @@ int mips_m4k_set_breakpoint(struct target *target, struct breakpoint *breakpoint
                {
                        LOG_ERROR("Can not find free FP Comparator(bpid: %d)",
                                          breakpoint->unique_id );
-                       return ERROR_FAIL;
+                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
                }
                breakpoint->set = bp_num + 1;
                comparator_list[bp_num].used = 1;
@@ -543,7 +567,8 @@ int mips_m4k_set_breakpoint(struct target *target, struct breakpoint *breakpoint
        return ERROR_OK;
 }
 
-int mips_m4k_unset_breakpoint(struct target *target, struct breakpoint *breakpoint)
+static int mips_m4k_unset_breakpoint(struct target *target,
+               struct breakpoint *breakpoint)
 {
        /* get pointers to arch-specific information */
        struct mips32_common *mips32 = target_to_mips32(target);
@@ -622,7 +647,7 @@ int mips_m4k_unset_breakpoint(struct target *target, struct breakpoint *breakpoi
        return ERROR_OK;
 }
 
-int mips_m4k_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
+static int mips_m4k_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
 
@@ -637,12 +662,11 @@ int mips_m4k_add_breakpoint(struct target *target, struct breakpoint *breakpoint
                mips32->num_inst_bpoints_avail--;
        }
 
-       mips_m4k_set_breakpoint(target, breakpoint);
-
-       return ERROR_OK;
+       return mips_m4k_set_breakpoint(target, breakpoint);
 }
 
-int mips_m4k_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
+static int mips_m4k_remove_breakpoint(struct target *target,
+               struct breakpoint *breakpoint)
 {
        /* get pointers to arch-specific information */
        struct mips32_common *mips32 = target_to_mips32(target);
@@ -664,7 +688,8 @@ int mips_m4k_remove_breakpoint(struct target *target, struct breakpoint *breakpo
        return ERROR_OK;
 }
 
-int mips_m4k_set_watchpoint(struct target *target, struct watchpoint *watchpoint)
+static int mips_m4k_set_watchpoint(struct target *target,
+               struct watchpoint *watchpoint)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips32_comparator *comparator_list = mips32->data_break_list;
@@ -731,7 +756,8 @@ int mips_m4k_set_watchpoint(struct target *target, struct watchpoint *watchpoint
        return ERROR_OK;
 }
 
-int mips_m4k_unset_watchpoint(struct target *target, struct watchpoint *watchpoint)
+static int mips_m4k_unset_watchpoint(struct target *target,
+               struct watchpoint *watchpoint)
 {
        /* get pointers to arch-specific information */
        struct mips32_common *mips32 = target_to_mips32(target);
@@ -757,7 +783,7 @@ int mips_m4k_unset_watchpoint(struct target *target, struct watchpoint *watchpoi
        return ERROR_OK;
 }
 
-int mips_m4k_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
+static int mips_m4k_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
 
@@ -773,7 +799,8 @@ int mips_m4k_add_watchpoint(struct target *target, struct watchpoint *watchpoint
        return ERROR_OK;
 }
 
-int mips_m4k_remove_watchpoint(struct target *target, struct watchpoint *watchpoint)
+static int mips_m4k_remove_watchpoint(struct target *target,
+               struct watchpoint *watchpoint)
 {
        /* get pointers to arch-specific information */
        struct mips32_common *mips32 = target_to_mips32(target);
@@ -794,7 +821,7 @@ int mips_m4k_remove_watchpoint(struct target *target, struct watchpoint *watchpo
        return ERROR_OK;
 }
 
-void mips_m4k_enable_watchpoints(struct target *target)
+static void mips_m4k_enable_watchpoints(struct target *target)
 {
        struct watchpoint *watchpoint = target->watchpoints;
 
@@ -807,7 +834,8 @@ void mips_m4k_enable_watchpoints(struct target *target)
        }
 }
 
-int mips_m4k_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+static int mips_m4k_read_memory(struct target *target, uint32_t address,
+               uint32_t size, uint32_t count, uint8_t *buffer)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
@@ -839,8 +867,8 @@ int mips_m4k_read_memory(struct target *target, uint32_t address, uint32_t size,
        return ERROR_OK;
 }
 
-int mips_m4k_write_memory(struct target *target, uint32_t address, uint32_t size,
-               uint32_t count, uint8_t *buffer)
+static int mips_m4k_write_memory(struct target *target, uint32_t address,
+               uint32_t size, uint32_t count, uint8_t *buffer)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
@@ -868,17 +896,18 @@ int mips_m4k_write_memory(struct target *target, uint32_t address, uint32_t size
                return mips32_dmaacc_write_mem(ejtag_info, address, size, count, (void *)buffer);
 }
 
-int mips_m4k_init_target(struct command_context *cmd_ctx, struct target *target)
+static int mips_m4k_init_target(struct command_context *cmd_ctx,
+               struct target *target)
 {
        mips32_build_reg_cache(target);
 
        return ERROR_OK;
 }
 
-int mips_m4k_init_arch_info(struct target *target, struct mips_m4k_common *mips_m4k,
-               struct jtag_tap *tap)
+static int mips_m4k_init_arch_info(struct target *target,
+               struct mips_m4k_common *mips_m4k, struct jtag_tap *tap)
 {
-       struct mips32_common *mips32 = &mips_m4k->mips32_common;
+       struct mips32_common *mips32 = &mips_m4k->mips32;
 
        mips_m4k->common_magic = MIPSM4K_COMMON_MAGIC;
 
@@ -889,7 +918,7 @@ int mips_m4k_init_arch_info(struct target *target, struct mips_m4k_common *mips_
        return ERROR_OK;
 }
 
-int mips_m4k_target_create(struct target *target, Jim_Interp *interp)
+static int mips_m4k_target_create(struct target *target, Jim_Interp *interp)
 {
        struct mips_m4k_common *mips_m4k = calloc(1, sizeof(struct mips_m4k_common));
 
@@ -898,11 +927,11 @@ int mips_m4k_target_create(struct target *target, Jim_Interp *interp)
        return ERROR_OK;
 }
 
-int mips_m4k_examine(struct target *target)
+static int mips_m4k_examine(struct target *target)
 {
        int retval;
-       struct mips32_common *mips32 = target_to_mips32(target);
-       struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
+       struct mips_m4k_common *mips_m4k = target_to_m4k(target);
+       struct mips_ejtag *ejtag_info = &mips_m4k->mips32.ejtag_info;
        uint32_t idcode = 0;
 
        if (!target_was_examined(target))
@@ -914,8 +943,9 @@ int mips_m4k_examine(struct target *target)
                {
                        /* we are using a pic32mx so select ejtag port
                         * as it is not selected by default */
-                       mips_ejtag_set_instr(ejtag_info, 0x05, NULL);
+                       mips_ejtag_set_instr(ejtag_info, MTAP_SW_ETAP);
                        LOG_DEBUG("PIC32MX Detected - using EJTAG Interface");
+                       mips_m4k->is_pic32mx = true;
                }
        }
 
@@ -929,14 +959,13 @@ int mips_m4k_examine(struct target *target)
        return ERROR_OK;
 }
 
-int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
+static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
                uint32_t count, uint8_t *buffer)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
-       struct working_area *source;
        int retval;
-       int write = 1;
+       int write_t = 1;
 
        LOG_DEBUG("address: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, count);
 
@@ -950,12 +979,23 @@ int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
        if (address & 0x3u)
                return ERROR_TARGET_UNALIGNED_ACCESS;
 
-       /* Get memory for block write handler */
-       retval = target_alloc_working_area(target, MIPS32_FASTDATA_HANDLER_SIZE, &source);
-       if (retval != ERROR_OK)
+       if (mips32->fast_data_area == NULL)
        {
-               LOG_WARNING("No working area available, falling back to non-bulk write");
-               return mips_m4k_write_memory(target, address, 4, count, buffer);
+               /* Get memory for block write handler
+                * we preserve this area between calls and gain a speed increase
+                * of about 3kb/sec when writing flash
+                * this will be released/nulled by the system when the target is resumed or reset */
+               retval = target_alloc_working_area(target,
+                               MIPS32_FASTDATA_HANDLER_SIZE,
+                               &mips32->fast_data_area);
+               if (retval != ERROR_OK)
+               {
+                       LOG_WARNING("No working area available, falling back to non-bulk write");
+                       return mips_m4k_write_memory(target, address, 4, count, buffer);
+               }
+
+               /* reset fastadata state so the algo get reloaded */
+               ejtag_info->fast_access_save = -1;
        }
 
        /* TAP data register is loaded LSB first (little endian) */
@@ -969,8 +1009,8 @@ int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
                }
        }
 
-       retval = mips32_pracc_fastdata_xfer(ejtag_info, source, write, address,
-                       count, (uint32_t*) buffer);
+       retval = mips32_pracc_fastdata_xfer(ejtag_info, mips32->fast_data_area, write_t, address,
+                       count, (uint32_t*) (void *)buffer);
        if (retval != ERROR_OK)
        {
                /* FASTDATA access failed, try normal memory write */
@@ -978,9 +1018,6 @@ int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
                retval = mips_m4k_write_memory(target, address, 4, count, buffer);
        }
 
-       if (source)
-               target_free_working_area(target, source);
-
        return retval;
 }