forked from auracaster/openocd
target: lakemon: implement assert_reset and deassert_reset
We're using an I/O port reset by default. The only board currently supported (Galileo) doesn't have SRST routed on the JTAG connector. When using 'reset halt', we must rely on Reset Break because our adapters don't have support for PREQ#/PRDY# signals. Tested with Intel Galileo GEN2. Change-Id: Ia406e31c156f8001717d5b6a08bd03f71de790d3 Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> Reviewed-on: http://openocd.zylin.com/4016 Tested-by: jenkins Reviewed-by: Paul Fertser <fercerpav@gmail.com>
This commit is contained in:
committed by
Paul Fertser
parent
3accbec901
commit
2b44b52478
@@ -970,6 +970,7 @@ int lakemont_poll(struct target *t)
|
||||
return target_call_event_callbacks(t, TARGET_EVENT_HALTED);
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
@@ -1115,15 +1116,137 @@ int lakemont_step(struct target *t, int current,
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* TODO - implement resetbreak fully through CLTAP registers */
|
||||
static int lakemont_reset_break(struct target *t)
|
||||
{
|
||||
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;
|
||||
|
||||
int retval = ERROR_OK;
|
||||
|
||||
LOG_DEBUG("issuing port 0xcf9 reset");
|
||||
|
||||
/* 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;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
int lakemont_reset_assert(struct target *t)
|
||||
{
|
||||
LOG_DEBUG("-");
|
||||
struct x86_32_common *x86_32 = target_to_x86_32(t);
|
||||
/* write 0x6 to I/O port 0xcf9 to cause the reset */
|
||||
uint8_t cf9_reset_val = 0x6;
|
||||
int retval;
|
||||
|
||||
LOG_DEBUG(" ");
|
||||
|
||||
if (t->state != TARGET_HALTED) {
|
||||
LOG_DEBUG("target must be halted first");
|
||||
retval = lakemont_halt(t);
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("could not halt target");
|
||||
return retval;
|
||||
}
|
||||
x86_32->forced_halt_for_reset = true;
|
||||
}
|
||||
|
||||
if (t->reset_halt) {
|
||||
retval = lakemont_reset_break(t);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = x86_32_common_write_io(t, 0xcf9, BYTE, &cf9_reset_val);
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("could not write to port 0xcf9");
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (!t->reset_halt && x86_32->forced_halt_for_reset) {
|
||||
x86_32->forced_halt_for_reset = false;
|
||||
retval = lakemont_resume(t, true, 0x00, false, true);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* remove breakpoints and watchpoints */
|
||||
x86_32_common_reset_breakpoints_watchpoints(t);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
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) {
|
||||
/* entered PM after reset, update the state */
|
||||
retval = lakemont_update_after_probemode_entry(t);
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("could not update state after probemode entry");
|
||||
return retval;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user