This is an automated email from Gerrit.

Felipe Balbi ([email protected]) just uploaded a new patch set to Gerrit, which 
you can find at http://openocd.zylin.com/4016

-- gerrit

commit 067e549ed16e1291bfe7258b5294fc1859c33e09
Author: Felipe Balbi <[email protected]>
Date:   Fri Feb 24 15:26:39 2017 +0200

    target: lakemon: implement reset break support
    
    Because our adapters don't have support for PREQ#/PRDY# signals, we
    don't have means to reset the SoC. The only way of doing so is by
    using reset break via probemode which will cause the TAP to drive
    PREQ#/PRDY# accordingly inside the SoC.
    
    This patch implements that and also assumes that we rely on it. It
    makes not sense to implement support for PREQ#/PRDY# on the adapter
    until we have adapters supporting those.
    
    Tested with Intel Galileo GEN2.
    
    Change-Id: Ia406e31c156f8001717d5b6a08bd03f71de790d3
    Signed-off-by: Felipe Balbi <[email protected]>

diff --git a/src/target/lakemont.c b/src/target/lakemont.c
index 5f92f0d..3ca548c 100644
--- a/src/target/lakemont.c
+++ b/src/target/lakemont.c
@@ -1115,15 +1115,124 @@ int lakemont_step(struct target *t, int current,
        return retval;
 }
 
-/* TODO - implement resetbreak fully through CLTAP registers */
-int lakemont_reset_assert(struct target *t)
+static int lakemont_reset_break(struct target *t)
 {
-       LOG_DEBUG("-");
+       struct x86_32_common *x86_32 = target_to_x86_32(t);
+       struct jtag_tap *saved_tap = x86_32->curr_tap;
+       struct scan_field *fields = &scan.field;
+
+       /* write 0x6 to I/O port 0xcf9 to cause the reset */
+       const uint8_t cf9_reset_val[] = { 0x6 };
+
+       int retval = ERROR_OK;
+
+       LOG_DEBUG("issuing port 0xcf9 reset");
+
+       /* we can't be running when issuing an I/O port write */
+       if (t->state == TARGET_RUNNING) {
+               retval = lakemont_halt(t);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("%s could not halt target", __func__);
+                       return retval;
+               }
+       }
+
+       /* prepare resetbreak setting the proper bits in CLTAPC_CPU_VPREQ */
+       x86_32->curr_tap = jtag_tap_by_position(1);
+       if (x86_32->curr_tap == NULL) {
+               x86_32->curr_tap = saved_tap;
+               LOG_ERROR("%s could not select quark_x10xx.cltap", __func__);
+               return ERROR_FAIL;
+       }
+
+       fields->in_value  = NULL;
+       fields->num_bits  = 8;
+
+       /* select CLTAPC_CPU_VPREQ instruction*/
+       scan.out[0] = 0x51;
+       fields->out_value = ((uint8_t *)scan.out);
+       jtag_add_ir_scan(x86_32->curr_tap, fields, TAP_IDLE);
+       retval = jtag_execute_queue();
+       if (retval != ERROR_OK) {
+               x86_32->curr_tap = saved_tap;
+               LOG_ERROR("%s irscan failed to execute queue", __func__);
+               return retval;
+       }
+
+       /* set enable_preq_on_reset & enable_preq_on_reset2 bits*/
+       scan.out[0] = 0x06;
+       fields->out_value  = ((uint8_t *)scan.out);
+       jtag_add_dr_scan(x86_32->curr_tap, 1, fields, TAP_IDLE);
+       retval = jtag_execute_queue();
+       if (retval != ERROR_OK) {
+               LOG_ERROR("%s drscan failed to execute queue", __func__);
+               x86_32->curr_tap = saved_tap;
+               return retval;
+       }
+
+       /* restore current tap */
+       x86_32->curr_tap = saved_tap;
+
+       retval = x86_32_common_write_io(t, (uint32_t)0xcf9, BYTE, 
cf9_reset_val);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("%s could not write to port 0xcf9", __func__);
+               return retval;
+       }
+
+       /* entered PM after reset, update the state */
+       retval = lakemont_update_after_probemode_entry(t);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("%s could not update state after probemode entry", 
__func__);
+               return retval;
+       }
+
+       /* remove breakpoints and watchpoints */
+       x86_32_common_reset_breakpoints_watchpoints(t);
+
        return ERROR_OK;
 }
 
+int lakemont_reset_assert(struct target *t)
+{
+       LOG_DEBUG(" ");
+
+       /*
+        * If we ever get an adapter with support for PREQ# and PRDY#, we should
+        * update this function to add support for using those two signals.
+        *
+        * Meanwhile, we're assuming that we only support reset break.
+        */
+
+       return lakemont_reset_break(t);
+}
+
 int lakemont_reset_deassert(struct target *t)
 {
-       LOG_DEBUG("-");
+       int retval;
+
+       LOG_DEBUG(" ");
+
+       if (target_was_examined(t)) {
+               retval = lakemont_poll(t);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       if (t->reset_halt) {
+               if (t->state != TARGET_HALTED) {
+                       LOG_WARNING("%s: ran after reset and before halt ...",
+                               target_name(t));
+                       if (target_was_examined(t)) {
+                               retval = target_halt(t);
+                               if (retval != ERROR_OK)
+                                       return retval;
+                       } else {
+                               t->state = TARGET_UNKNOWN;
+                       }
+               }
+       } else {
+               return target_resume(t, true, 0x00, false, true);
+       }
+
        return ERROR_OK;
 }
diff --git a/src/target/x86_32_common.c b/src/target/x86_32_common.c
index 34f92ea..0d87ba5 100644
--- a/src/target/x86_32_common.c
+++ b/src/target/x86_32_common.c
@@ -1260,6 +1260,38 @@ static int unset_watchpoint(struct target *t, struct 
watchpoint *wp)
        return ERROR_OK;
 }
 
+/* after reset breakpoints and watchpoints in memory are not valid anymore and
+ * debug registers are cleared.
+ * we can't afford to remove sw breakpoints using the default methods as the
+ * memory doesn't have the same layout yet and an access might crash the 
target,
+ * so we just clear the openocd breakpoints structures.
+ */
+void x86_32_common_reset_breakpoints_watchpoints(struct target *t)
+{
+       struct x86_32_common *x86_32 = target_to_x86_32(t);
+       struct x86_32_dbg_reg *debug_reg_list = x86_32->hw_break_list;
+       struct breakpoint *next_b;
+       struct watchpoint *next_w;
+
+       while (t->breakpoints) {
+               next_b = t->breakpoints->next;
+               free(t->breakpoints->orig_instr);
+               free(t->breakpoints);
+               t->breakpoints = next_b;
+       }
+
+       while (t->watchpoints) {
+               next_w = t->watchpoints->next;
+               free(t->watchpoints);
+               t->watchpoints = next_w;
+       }
+
+       for (int i = 0; i < x86_32->num_hw_bpoints; i++) {
+               debug_reg_list[i].used = 0;
+               debug_reg_list[i].bp_value = 0;
+       }
+}
+
 static int read_hw_reg_to_cache(struct target *t, int num)
 {
        uint32_t reg_value;
diff --git a/src/target/x86_32_common.h b/src/target/x86_32_common.h
index 0aaa963..fe100ea 100644
--- a/src/target/x86_32_common.h
+++ b/src/target/x86_32_common.h
@@ -326,5 +326,6 @@ int x86_32_common_add_breakpoint(struct target *t, struct 
breakpoint *bp);
 int x86_32_common_remove_breakpoint(struct target *t, struct breakpoint *bp);
 int x86_32_common_add_watchpoint(struct target *t, struct watchpoint *wp);
 int x86_32_common_remove_watchpoint(struct target *t, struct watchpoint *wp);
+void x86_32_common_reset_breakpoints_watchpoints(struct target *t);
 
 #endif /* OPENOCD_TARGET_X86_32_COMMON_H */

-- 

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
OpenOCD-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to