From a4ce9a2c719b1f7536ada1c9fa8f1eb672b04897 Mon Sep 17 00:00:00 2001 From: Ivan De Cesaris Date: Tue, 12 Jan 2016 16:30:18 +0100 Subject: [PATCH] quark: add Intel Quark mcu D2000 support Add support for the Intel Quark mcu D2000 using the new quark_d2xx target. Changes to the lakemont part are needed for the D2000 core and backwards compatible with the X1000 one. Change-Id: I6e1ef5a5d116344942f08e413965abd3945235fa Signed-off-by: Ivan De Cesaris Reviewed-on: http://openocd.zylin.com/3199 Tested-by: jenkins Reviewed-by: Spencer Oliver --- src/target/Makefile.am | 1 + src/target/lakemont.c | 35 ++++++++++----- src/target/lakemont.h | 3 +- src/target/{quark_x10xx.c => quark_d20xx.c} | 66 +++++++++++++++++------------ src/target/quark_x10xx.c | 3 +- src/target/target.c | 2 + src/target/x86_32_common.h | 8 +++- tcl/board/quark_d2000_refboard.cfg | 15 +++++++ tcl/target/quark_d20xx.cfg | 50 ++++++++++++++++++++++ 9 files changed, 143 insertions(+), 40 deletions(-) copy src/target/{quark_x10xx.c => quark_d20xx.c} (58%) create mode 100644 tcl/board/quark_d2000_refboard.cfg create mode 100644 tcl/target/quark_d20xx.cfg diff --git a/src/target/Makefile.am b/src/target/Makefile.am index 9f47b1fd8..1f4cbba42 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -129,6 +129,7 @@ NDS32_SRC = \ INTEL_IA32_SRC = \ quark_x10xx.c \ + quark_d20xx.c \ lakemont.c \ x86_32_common.c diff --git a/src/target/lakemont.c b/src/target/lakemont.c index 055d94340..151f4abe8 100644 --- a/src/target/lakemont.c +++ b/src/target/lakemont.c @@ -1,11 +1,12 @@ /* - * Copyright(c) 2013 Intel Corporation. + * Copyright(c) 2013-2016 Intel Corporation. * * Adrian Burns (adrian.burns@intel.com) * Thomas Faust (thomas.faust@intel.com) * Ivan De Cesaris (ivan.de.cesaris@intel.com) * Julien Carreno (julien.carreno@intel.com) * Jeffrey Maxwell (jeffrey.r.maxwell@intel.com) + * Jessica Gomez (jessica.gomez.hernandez@intel.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -498,6 +499,12 @@ static int halt_prep(struct target *t) if (write_hw_reg(t, DSAR, PM_DSAR, 0) != ERROR_OK) return ERROR_FAIL; LOG_DEBUG("write DSAR 0x%08" PRIx32, PM_DSAR); + if (write_hw_reg(t, CSB, PM_DSB, 0) != ERROR_OK) + return ERROR_FAIL; + LOG_DEBUG("write %s 0x%08" PRIx32, regs[CSB].name, PM_DSB); + if (write_hw_reg(t, CSL, PM_DSL, 0) != ERROR_OK) + return ERROR_FAIL; + LOG_DEBUG("write %s 0x%08" PRIx32, regs[CSL].name, PM_DSL); if (write_hw_reg(t, DR7, PM_DR7, 0) != ERROR_OK) return ERROR_FAIL; LOG_DEBUG("write DR7 0x%08" PRIx32, PM_DR7); @@ -511,8 +518,7 @@ static int halt_prep(struct target *t) LOG_DEBUG("EFLAGS = 0x%08" PRIx32 ", VM86 = %d, IF = %d", eflags, eflags & EFLAGS_VM86 ? 1 : 0, eflags & EFLAGS_IF ? 1 : 0); - if (eflags & EFLAGS_VM86 - || eflags & EFLAGS_IF) { + if ((eflags & EFLAGS_VM86) || (eflags & EFLAGS_IF)) { x86_32->pm_regs[I(EFLAGS)] = eflags & ~(EFLAGS_VM86 | EFLAGS_IF); if (write_hw_reg(t, EFLAGS, x86_32->pm_regs[I(EFLAGS)], 0) != ERROR_OK) return ERROR_FAIL; @@ -530,14 +536,14 @@ static int halt_prep(struct target *t) LOG_DEBUG("write CSAR_CPL to 0 0x%08" PRIx32, x86_32->pm_regs[I(CSAR)]); } if (ssar & SSAR_DPL) { - x86_32->pm_regs[I(SSAR)] = ssar & ~CSAR_DPL; + x86_32->pm_regs[I(SSAR)] = ssar & ~SSAR_DPL; if (write_hw_reg(t, SSAR, x86_32->pm_regs[I(SSAR)], 0) != ERROR_OK) return ERROR_FAIL; LOG_DEBUG("write SSAR_CPL to 0 0x%08" PRIx32, x86_32->pm_regs[I(SSAR)]); } - /* if cache's are enabled, disable and flush */ - if (!(cr0 & CR0_CD)) { + /* if cache's are enabled, disable and flush, depending on the core version */ + if (!(x86_32->core_type == LMT3_5) && !(cr0 & CR0_CD)) { LOG_DEBUG("caching enabled CR0 = 0x%08" PRIx32, cr0); if (cr0 & CR0_PG) { x86_32->pm_regs[I(CR0)] = cr0 & ~CR0_PG; @@ -563,6 +569,13 @@ static int do_halt(struct target *t) t->state = TARGET_DEBUG_RUNNING; if (enter_probemode(t) != ERROR_OK) return ERROR_FAIL; + + return lakemont_update_after_probemode_entry(t); +} + +/* we need to expose the update to be able to complete the reset at SoC level */ +int lakemont_update_after_probemode_entry(struct target *t) +{ if (save_context(t) != ERROR_OK) return ERROR_FAIL; if (halt_prep(t) != ERROR_OK) @@ -677,16 +690,16 @@ static int write_hw_reg(struct target *t, int reg, uint32_t regval, uint8_t cach arch_info->op, regval); - scan.out[0] = RDWRPDR; x86_32->flush = 0; /* dont flush scans till we have a batch */ - if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK) - return ERROR_FAIL; - if (drscan(t, reg_buf, scan.out, PDR_SIZE) != ERROR_OK) - return ERROR_FAIL; if (submit_reg_pir(t, reg) != ERROR_OK) return ERROR_FAIL; if (submit_instruction_pir(t, SRAMACCESS) != ERROR_OK) return ERROR_FAIL; + scan.out[0] = RDWRPDR; + if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK) + return ERROR_FAIL; + if (drscan(t, reg_buf, scan.out, PDR_SIZE) != ERROR_OK) + return ERROR_FAIL; x86_32->flush = 1; if (submit_instruction_pir(t, PDR2SRAM) != ERROR_OK) return ERROR_FAIL; diff --git a/src/target/lakemont.h b/src/target/lakemont.h index 30b34b3f2..1075ad31d 100644 --- a/src/target/lakemont.h +++ b/src/target/lakemont.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2013 Intel Corporation. + * Copyright(c) 2013-2016 Intel Corporation. * * Adrian Burns (adrian.burns@intel.com) * Thomas Faust (thomas.faust@intel.com) @@ -101,5 +101,6 @@ int lakemont_step(struct target *t, int current, uint32_t address, int handle_breakpoints); int lakemont_reset_assert(struct target *t); int lakemont_reset_deassert(struct target *t); +int lakemont_update_after_probemode_entry(struct target *t); #endif /* LAKEMONT_H */ diff --git a/src/target/quark_x10xx.c b/src/target/quark_d20xx.c similarity index 58% copy from src/target/quark_x10xx.c copy to src/target/quark_d20xx.c index 9a1ccb65d..f79721417 100644 --- a/src/target/quark_x10xx.c +++ b/src/target/quark_d20xx.c @@ -1,11 +1,8 @@ /* - * Copyright(c) 2013 Intel Corporation. + * Copyright(c) 2015-2016 Intel Corporation. * - * Adrian Burns (adrian.burns@intel.com) - * Thomas Faust (thomas.faust@intel.com) + * Jessica Gomez (jessica.gomez.hernandez@intel.com) * Ivan De Cesaris (ivan.de.cesaris@intel.com) - * Julien Carreno (julien.carreno@intel.com) - * Jeffrey Maxwell (jeffrey.r.maxwell@intel.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,28 +14,18 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * 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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * * Contact Information: * Intel Corporation */ /* * @file - * Debugger for Intel Quark SoC X1000 - * Intel Quark X10xx is the first product in the Quark family of SoCs. - * It is an IA-32 (Pentium x86 ISA) compatible SoC. The core CPU in the - * X10xx is codenamed Lakemont. Lakemont version 1 (LMT1) is used in X10xx. + * Debugger for Intel Quark D20xx * The CPU TAP (Lakemont TAP) is used for software debug and the CLTAP is * used for SoC level operations. - * Useful docs are here: https://communities.intel.com/community/makers/documentation - * Intel Quark SoC X1000 OpenOCD/GDB/Eclipse App Note (web search for doc num 330015) - * Intel Quark SoC X1000 Debug Operations User Guide (web search for doc num 329866) - * Intel Quark SoC X1000 Datasheet (web search for doc num 329676) * - * This file implements any Quark SoC specific features such as resetbreak (TODO) + * Reference document: + * Intel Quark microcontroller D2000 Debug Operations (web search for doc num 333241) */ #ifdef HAVE_CONFIG_H @@ -49,10 +36,11 @@ #include "target.h" #include "target_type.h" +#include "breakpoints.h" #include "lakemont.h" #include "x86_32_common.h" -int quark_x10xx_target_create(struct target *t, Jim_Interp *interp) +int quark_d20xx_target_create(struct target *t, Jim_Interp *interp) { struct x86_32_common *x86_32 = calloc(1, sizeof(struct x86_32_common)); if (x86_32 == NULL) { @@ -61,19 +49,45 @@ int quark_x10xx_target_create(struct target *t, Jim_Interp *interp) } x86_32_common_init_arch_info(t, x86_32); lakemont_init_arch_info(t, x86_32); + x86_32->core_type = LMT3_5; return ERROR_OK; } -int quark_x10xx_init_target(struct command_context *cmd_ctx, struct target *t) +int quark_d20xx_init_target(struct command_context *cmd_ctx, struct target *t) { return lakemont_init_target(cmd_ctx, t); } -struct target_type quark_x10xx_target = { - .name = "quark_x10xx", - /* Quark X1000 SoC */ - .target_create = quark_x10xx_target_create, - .init_target = quark_x10xx_init_target, +static int quark_d20xx_reset_deassert(struct target *t) +{ + int retval; + + /* Can't detect if a warm reset happened while halted but we can make the + * openocd and target state consistent here if in probe mode already + */ + if (!check_not_halted(t)) { + retval = lakemont_update_after_probemode_entry(t); + if (retval != ERROR_OK) { + LOG_ERROR("%s core state update fail", __func__); + return retval; + } + /* resume target if reset mode is run */ + if (!t->reset_halt) { + retval = lakemont_resume(t, 1, 0, 0, 0); + if (retval != ERROR_OK) { + LOG_ERROR("%s could not resume target", __func__); + return retval; + } + } + } + + return ERROR_OK; +} + +struct target_type quark_d20xx_target = { + .name = "quark_d20xx", + .target_create = quark_d20xx_target_create, + .init_target = quark_d20xx_init_target, /* lakemont probemode specific code */ .poll = lakemont_poll, .arch_state = lakemont_arch_state, @@ -81,7 +95,7 @@ struct target_type quark_x10xx_target = { .resume = lakemont_resume, .step = lakemont_step, .assert_reset = lakemont_reset_assert, - .deassert_reset = lakemont_reset_deassert, + .deassert_reset = quark_d20xx_reset_deassert, /* common x86 code */ .commands = x86_32_command_handlers, .get_gdb_reg_list = x86_32_get_gdb_reg_list, diff --git a/src/target/quark_x10xx.c b/src/target/quark_x10xx.c index 9a1ccb65d..a3b8a266d 100644 --- a/src/target/quark_x10xx.c +++ b/src/target/quark_x10xx.c @@ -1,5 +1,5 @@ /* - * Copyright(c) 2013 Intel Corporation. + * Copyright(c) 2013-2016 Intel Corporation. * * Adrian Burns (adrian.burns@intel.com) * Thomas Faust (thomas.faust@intel.com) @@ -61,6 +61,7 @@ int quark_x10xx_target_create(struct target *t, Jim_Interp *interp) } x86_32_common_init_arch_info(t, x86_32); lakemont_init_arch_info(t, x86_32); + x86_32->core_type = LMT1; return ERROR_OK; } diff --git a/src/target/target.c b/src/target/target.c index 598d7d5a8..6df8d8b97 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -104,6 +104,7 @@ extern struct target_type nds32_v3_target; extern struct target_type nds32_v3m_target; extern struct target_type or1k_target; extern struct target_type quark_x10xx_target; +extern struct target_type quark_d20xx_target; static struct target_type *target_types[] = { &arm7tdmi_target, @@ -133,6 +134,7 @@ static struct target_type *target_types[] = { &nds32_v3m_target, &or1k_target, &quark_x10xx_target, + &quark_d20xx_target, NULL, }; diff --git a/src/target/x86_32_common.h b/src/target/x86_32_common.h index af57a5f7e..c9cb389b5 100644 --- a/src/target/x86_32_common.h +++ b/src/target/x86_32_common.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2013 Intel Corporation. + * Copyright(c) 2013-2016 Intel Corporation. * * Adrian Burns (adrian.burns@intel.com) * Thomas Faust (thomas.faust@intel.com) @@ -196,6 +196,11 @@ enum { WBINVD, }; +enum x86_core_type { + LMT1, + LMT3_5 +}; + struct swbp_mem_patch { uint8_t orig_byte; uint32_t swbp_unique_id; @@ -209,6 +214,7 @@ struct swbp_mem_patch { struct x86_32_common { uint32_t common_magic; void *arch_info; + enum x86_core_type core_type; struct reg_cache *cache; struct jtag_tap *curr_tap; uint32_t stored_pc; diff --git a/tcl/board/quark_d2000_refboard.cfg b/tcl/board/quark_d2000_refboard.cfg new file mode 100644 index 000000000..d1388bbaa --- /dev/null +++ b/tcl/board/quark_d2000_refboard.cfg @@ -0,0 +1,15 @@ +# Intel Quark microcontroller D2000 Reference Board (web search for doc num 333582) + +# the board has an onboard FTDI FT232H chip +interface ftdi +ftdi_vid_pid 0x0403 0x6014 +ftdi_channel 0 + +ftdi_layout_init 0x0000 0x030b +ftdi_layout_signal nTRST -data 0x0100 -noe 0x0100 + +source [find target/quark_d20xx.cfg] + +adapter_khz 1000 + +reset_config trst_only diff --git a/tcl/target/quark_d20xx.cfg b/tcl/target/quark_d20xx.cfg new file mode 100644 index 000000000..419f9dc4d --- /dev/null +++ b/tcl/target/quark_d20xx.cfg @@ -0,0 +1,50 @@ +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + set _CPUTAPID 0x38289013 +} + +jtag newtap quark_d20xx quark -irlen 8 -irmask 0xff -expected-id $_CPUTAPID -disable +jtag newtap quark_d20xx cltap -irlen 8 -irmask 0xff -expected-id 0x0e786013 -enable + +proc quark_d20xx_tapenable {} { + echo "enabling quark core tap" + irscan quark_d20xx.cltap 0x11 + drscan quark_d20xx.cltap 12 1 + runtest 10 +} + +proc quark_d20xx_tapdisable {} { + echo "disabling quark core tap" + irscan quark_d20xx.cltap 0x11 + drscan quark_d20xx.cltap 12 0 + runtest 10 +} + +proc quark_d20xx_setup {} { + jtag tapenable quark_d20xx.quark +} + +jtag configure quark_d20xx.quark -event tap-enable \ + "quark_d20xx_tapenable" + +jtag configure quark_d20xx.quark -event tap-disable \ + "quark_d20xx_tapdisable" + +target create quark_d20xx.quark quark_d20xx -endian little -chain-position quark_d20xx.quark + +quark_d20xx.quark configure -event gdb-attach { halt } + +quark_d20xx.quark configure -event reset-start { + # need to halt the target to write to memory + if {[quark_d20xx.quark curstate] ne "halted"} { halt } + # set resetbreak via the core tap + irscan quark_d20xx.quark 0x35 ; drscan quark_d20xx.quark 1 0x1 + # trigger a warm reset + mww 0xb0800570 0x2 + # clear resetbreak + irscan quark_d20xx.quark 0x35 ; drscan quark_d20xx.quark 1 0x0 +} + +jtag configure quark_d20xx.quark -event setup \ + "quark_d20xx_setup" -- 2.11.4.GIT