diff options
author | Tim Newsome <tim@sifive.com> | 2017-06-13 11:52:50 -0700 |
---|---|---|
committer | Tim Newsome <tim@sifive.com> | 2017-06-13 11:52:50 -0700 |
commit | 845c2f6b692736d3f6ee113908b98cb60ec60119 (patch) | |
tree | 32b9315ff67d97c397184dfe98b7523fed95dcb1 /src/jtag | |
parent | 7af58e6283c8e7d350b6b55c93a1d326326ed831 (diff) | |
parent | 1025be363e2bf42f1613083223a2322cc3a9bd4c (diff) | |
download | riscv-openocd-845c2f6b692736d3f6ee113908b98cb60ec60119.zip riscv-openocd-845c2f6b692736d3f6ee113908b98cb60ec60119.tar.gz riscv-openocd-845c2f6b692736d3f6ee113908b98cb60ec60119.tar.bz2 |
Merge branch 'remotes/openocd/master' into riscv64
Merged 1025be363e2bf42f1613083223a2322cc3a9bd4c
Conflicts:
src/flash/nor/Makefile.am
src/rtos/Makefile.am
src/rtos/rtos.c
src/target/Makefile.am
src/target/target.c
src/target/target_type.h
Doesn't build yet, but I fixed the conflicts that git pointed out.
Diffstat (limited to 'src/jtag')
32 files changed, 2284 insertions, 5261 deletions
diff --git a/src/jtag/Makefile.am b/src/jtag/Makefile.am index db3e6ff..50ee263 100644 --- a/src/jtag/Makefile.am +++ b/src/jtag/Makefile.am @@ -1,86 +1,72 @@ -include $(top_srcdir)/common.mk +noinst_LTLIBRARIES += %D%/libjtag.la -METASOURCES = AUTO -noinst_LTLIBRARIES = libjtag.la +JTAG_SRCS = +%C%_libjtag_la_LIBADD = -SUBDIRS = -DRIVERFILES = -libjtag_la_LIBADD = - -CLEANFILES = - -BUILT_SOURCES = - -BUILT_SOURCES += minidriver_imp.h -CLEANFILES += minidriver_imp.h +BUILT_SOURCES += %D%/minidriver_imp.h +CLEANFILES += %D%/minidriver_imp.h if MINIDRIVER if ZY1000 -DRIVERFILES += zy1000/zy1000.c -JTAG_MINIDRIVER_DIR = $(srcdir)/zy1000 +JTAG_SRCS += %D%/zy1000/zy1000.c +JTAG_MINIDRIVER_DIR = %D%/zy1000 endif if MINIDRIVER_DUMMY -DRIVERFILES += minidummy/minidummy.c commands.c -JTAG_MINIDRIVER_DIR = $(srcdir)/minidummy +JTAG_SRCS += %D%/minidummy/minidummy.c %D%/commands.c +JTAG_MINIDRIVER_DIR = %D%/minidummy endif -MINIDRIVER_IMP_DIR = $(srcdir)/minidriver +MINIDRIVER_IMP_DIR = %D%/minidriver -jtag_minidriver.h: $(JTAG_MINIDRIVER_DIR)/jtag_minidriver.h +%D%/jtag_minidriver.h: $(JTAG_MINIDRIVER_DIR)/jtag_minidriver.h cp $< $@ -BUILT_SOURCES += jtag_minidriver.h +BUILT_SOURCES += %D%/jtag_minidriver.h -CLEANFILES += jtag_minidriver.h +CLEANFILES += %D%/jtag_minidriver.h else -MINIDRIVER_IMP_DIR = $(srcdir)/drivers -DRIVERFILES += commands.c +MINIDRIVER_IMP_DIR = %D%/drivers +JTAG_SRCS += %D%/commands.c if HLADAPTER -SUBDIRS += hla -libjtag_la_LIBADD += $(top_builddir)/src/jtag/hla/libocdhla.la +include %D%/hla/Makefile.am +%C%_libjtag_la_LIBADD += $(top_builddir)/%D%/hla/libocdhla.la endif if AICE -SUBDIRS += aice -libjtag_la_LIBADD += $(top_builddir)/src/jtag/aice/libocdaice.la +include %D%/aice/Makefile.am +%C%_libjtag_la_LIBADD += $(top_builddir)/%D%/aice/libocdaice.la endif -SUBDIRS += drivers -libjtag_la_LIBADD += $(top_builddir)/src/jtag/drivers/libocdjtagdrivers.la - +include %D%/drivers/Makefile.am +%C%_libjtag_la_LIBADD += $(top_builddir)/%D%/drivers/libocdjtagdrivers.la endif - # endif // MINIDRIVER -minidriver_imp.h: $(MINIDRIVER_IMP_DIR)/minidriver_imp.h +%D%/minidriver_imp.h: $(MINIDRIVER_IMP_DIR)/minidriver_imp.h cp $< $@ -libjtag_la_SOURCES = \ - adapter.c \ - core.c \ - interface.c \ - interfaces.c \ - tcl.c \ - $(DRIVERFILES) - -noinst_HEADERS = \ - commands.h \ - driver.h \ - interface.h \ - interfaces.h \ - minidriver.h \ - jtag.h \ - minidriver/minidriver_imp.h \ - minidummy/jtag_minidriver.h \ - swd.h \ - tcl.h - -EXTRA_DIST = startup.tcl - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +%C%_libjtag_la_SOURCES = \ + %D%/adapter.c \ + %D%/core.c \ + %D%/interface.c \ + %D%/interfaces.c \ + %D%/tcl.c \ + %D%/commands.h \ + %D%/driver.h \ + %D%/interface.h \ + %D%/interfaces.h \ + %D%/minidriver.h \ + %D%/jtag.h \ + %D%/minidriver/minidriver_imp.h \ + %D%/minidummy/jtag_minidriver.h \ + %D%/swd.h \ + %D%/tcl.h \ + $(JTAG_SRCS) + +STARTUP_TCL_SRCS += %D%/startup.tcl diff --git a/src/jtag/aice/Makefile.am b/src/jtag/aice/Makefile.am index 7b9469d..97e3825 100644 --- a/src/jtag/aice/Makefile.am +++ b/src/jtag/aice/Makefile.am @@ -1,27 +1,14 @@ -include $(top_srcdir)/common.mk - -AM_CPPFLAGS += -I$(top_srcdir)/src/jtag/drivers $(LIBUSB1_CFLAGS) $(LIBUSB0_CFLAGS) - -noinst_LTLIBRARIES = libocdaice.la - -libocdaice_la_SOURCES = \ - $(AICEFILES) - -AICEFILES = - -if AICE -AICEFILES += aice_transport.c -AICEFILES += aice_interface.c -AICEFILES += aice_port.c -AICEFILES += aice_usb.c -AICEFILES += aice_pipe.c -endif - -noinst_HEADERS = \ - aice_transport.h \ - aice_interface.h \ - aice_port.h \ - aice_usb.h \ - aice_pipe.h - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +noinst_LTLIBRARIES += %D%/libocdaice.la + +%C%_libocdaice_la_CPPFLAGS = -I$(top_srcdir)/src/jtag/drivers $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) $(LIBUSB0_CFLAGS) +%C%_libocdaice_la_SOURCES = \ + %D%/aice_transport.c \ + %D%/aice_interface.c \ + %D%/aice_port.c \ + %D%/aice_usb.c \ + %D%/aice_pipe.c \ + %D%/aice_transport.h \ + %D%/aice_interface.h \ + %D%/aice_port.h \ + %D%/aice_usb.h \ + %D%/aice_pipe.h diff --git a/src/jtag/aice/aice_pipe.c b/src/jtag/aice/aice_pipe.c index 18ad40e..bdc8c09 100644 --- a/src/jtag/aice/aice_pipe.c +++ b/src/jtag/aice/aice_pipe.c @@ -786,8 +786,8 @@ static int aice_pipe_memory_mode(uint32_t coreid, enum nds_memory_select mem_sel return ERROR_FAIL; } -static int aice_pipe_read_tlb(uint32_t coreid, uint32_t virtual_address, - uint32_t *physical_address) +static int aice_pipe_read_tlb(uint32_t coreid, target_addr_t virtual_address, + target_addr_t *physical_address) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; diff --git a/src/jtag/aice/aice_port.h b/src/jtag/aice/aice_port.h index 4568ce1..d3d6a1a 100644 --- a/src/jtag/aice/aice_port.h +++ b/src/jtag/aice/aice_port.h @@ -180,7 +180,7 @@ struct aice_port_api_s { int (*memory_mode)(uint32_t coreid, enum nds_memory_select mem_select); /** */ - int (*read_tlb)(uint32_t coreid, uint32_t virtual_address, uint32_t *physical_address); + int (*read_tlb)(uint32_t coreid, target_addr_t virtual_address, target_addr_t *physical_address); /** */ int (*cache_ctl)(uint32_t coreid, uint32_t subtype, uint32_t address); diff --git a/src/jtag/aice/aice_usb.c b/src/jtag/aice/aice_usb.c index b27f720..50468f3 100644 --- a/src/jtag/aice/aice_usb.c +++ b/src/jtag/aice/aice_usb.c @@ -2135,10 +2135,16 @@ static int aice_usb_open(struct aice_port_param_s *param) /* usb_set_configuration required under win32 */ jtag_libusb_set_configuration(devh, 0); + jtag_libusb_claim_interface(devh, 0); unsigned int aice_read_ep; unsigned int aice_write_ep; - jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1); +#ifdef HAVE_LIBUSB1 + jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1, LIBUSB_TRANSFER_TYPE_BULK); +#else + jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1, USB_ENDPOINT_TYPE_BULK); +#endif + LOG_DEBUG("aice_read_ep=0x%x, aice_write_ep=0x%x", aice_read_ep, aice_write_ep); aice_handler.usb_read_ep = aice_read_ep; aice_handler.usb_write_ep = aice_write_ep; @@ -3424,10 +3430,10 @@ static int aice_usb_memory_mode(uint32_t coreid, enum nds_memory_select mem_sele return ERROR_OK; } -static int aice_usb_read_tlb(uint32_t coreid, uint32_t virtual_address, - uint32_t *physical_address) +static int aice_usb_read_tlb(uint32_t coreid, target_addr_t virtual_address, + target_addr_t *physical_address) { - LOG_DEBUG("aice_usb_read_tlb, virtual address: 0x%08" PRIx32, virtual_address); + LOG_DEBUG("aice_usb_read_tlb, virtual address: 0x%08" TARGET_PRIxADDR, virtual_address); uint32_t instructions[4]; uint32_t probe_result; diff --git a/src/jtag/core.c b/src/jtag/core.c index 3da69ff..e21d476 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -1831,11 +1831,11 @@ void jtag_set_reset_config(enum reset_types type) int jtag_get_trst(void) { - return jtag_trst; + return jtag_trst == 1; } int jtag_get_srst(void) { - return jtag_srst; + return jtag_srst == 1; } void jtag_set_nsrst_delay(unsigned delay) diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index 2aaf8fd..3e5974d 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -1,173 +1,179 @@ -include $(top_srcdir)/common.mk +noinst_LTLIBRARIES += %D%/libocdjtagdrivers.la +%C%_libocdjtagdrivers_la_LIBADD = -noinst_LTLIBRARIES = libocdjtagdrivers.la -libocdjtagdrivers_la_LIBADD = +%C%_libocdjtagdrivers_la_SOURCES = \ + $(DRIVERFILES) \ + $(DRIVERHEADERS) -libocdjtagdrivers_la_SOURCES = \ - $(DRIVERFILES) +%C%_libocdjtagdrivers_la_CPPFLAGS = $(AM_CPPFLAGS) -libocdjtagdrivers_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) \ - $(LIBUSB0_CFLAGS) $(HIDAPI_CFLAGS) $(LIBFTDI_CFLAGS) +ULINK_FIRMWARE = %D%/OpenULINK -ULINK_FIRMWARE = $(srcdir)/OpenULINK - -EXTRA_DIST = $(ULINK_FIRMWARE) \ - usb_blaster/README.CheapClone \ - Makefile.rlink \ - rlink_call.m4 \ - rlink_init.m4 +EXTRA_DIST += $(ULINK_FIRMWARE) \ + %D%/usb_blaster/README.CheapClone \ + %D%/Makefile.rlink \ + %D%/rlink_call.m4 \ + %D%/rlink_init.m4 DRIVERFILES = -SUBDIRS= -if JLINK -if INTERNAL_LIBJAYLINK -SUBDIRS += libjaylink +# Standard Driver: common files +DRIVERFILES += %D%/driver.c -libjaylink_internal_la_SOURCES = jlink.c -libjaylink_internal_la_LIBADD = libjaylink/libjaylink/libjaylink.la -libjaylink_internal_la_CPPFLAGS = -I$(builddir)/libjaylink/libjaylink \ - -I$(srcdir)/libjaylink $(AM_CPPFLAGS) +if USE_LIBUSB1 +DRIVERFILES += %D%/libusb1_common.c +%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBUSB1_CFLAGS) +%C%_libocdjtagdrivers_la_LIBADD += $(LIBUSB1_LIBS) +endif -noinst_LTLIBRARIES += libjaylink_internal.la -libocdjtagdrivers_la_LIBADD += libjaylink_internal.la -else -DRIVERFILES += jlink.c +if USE_LIBUSB0 +DRIVERFILES += %D%/usb_common.c +%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBUSB0_CFLAGS) +%C%_libocdjtagdrivers_la_LIBADD += $(LIBUSB0_LIBS) +if !USE_LIBUSB1 +DRIVERFILES += %D%/libusb0_common.c endif endif -# Standard Driver: common files -DRIVERFILES += driver.c +if USE_LIBFTDI +%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBFTDI_CFLAGS) +%C%_libocdjtagdrivers_la_LIBADD += $(LIBFTDI_LIBS) +endif -if USE_LIBUSB1 -DRIVERFILES += libusb1_common.c +if USE_HIDAPI +%C%_libocdjtagdrivers_la_CPPFLAGS += $(HIDAPI_CFLAGS) +%C%_libocdjtagdrivers_la_LIBADD += $(HIDAPI_LIBS) endif -if USE_LIBUSB0 -DRIVERFILES += usb_common.c -if !USE_LIBUSB1 -DRIVERFILES += libusb0_common.c +if USE_LIBJAYLINK +%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBJAYLINK_CFLAGS) +%C%_libocdjtagdrivers_la_LIBADD += $(LIBJAYLINK_LIBS) +endif + +if JLINK +DRIVERFILES += %D%/jlink.c +if INTERNAL_LIBJAYLINK +SUBDIRS += %D%/libjaylink +DIST_SUBDIRS += %D%/libjaylink + +%C%_libocdjtagdrivers_la_LIBADD += %D%/libjaylink/libjaylink/libjaylink.la +%C%_libocdjtagdrivers_la_CPPFLAGS += -I$(builddir)/%D%/libjaylink/libjaylink -I$(srcdir)/%D%/libjaylink endif endif if BITBANG -DRIVERFILES += bitbang.c +DRIVERFILES += %D%/bitbang.c endif if PARPORT -DRIVERFILES += parport.c +DRIVERFILES += %D%/parport.c endif if DUMMY -DRIVERFILES += dummy.c -endif -if FT2232_DRIVER -DRIVERFILES += ft2232.c +DRIVERFILES += %D%/dummy.c endif if FTDI -DRIVERFILES += ftdi.c mpsse.c +DRIVERFILES += %D%/ftdi.c %D%/mpsse.c endif if JTAG_VPI -DRIVERFILES += jtag_vpi.c +DRIVERFILES += %D%/jtag_vpi.c endif if USB_BLASTER_DRIVER -SUBDIRS += usb_blaster -libocdjtagdrivers_la_LIBADD += $(top_builddir)/src/jtag/drivers/usb_blaster/libocdusbblaster.la +%C%_libocdjtagdrivers_la_LIBADD += %D%/usb_blaster/libocdusbblaster.la +include %D%/usb_blaster/Makefile.am endif if AMTJTAGACCEL -DRIVERFILES += amt_jtagaccel.c +DRIVERFILES += %D%/amt_jtagaccel.c endif if EP93XX -DRIVERFILES += ep93xx.c +DRIVERFILES += %D%/ep93xx.c endif if AT91RM9200 -DRIVERFILES += at91rm9200.c +DRIVERFILES += %D%/at91rm9200.c endif if GW16012 -DRIVERFILES += gw16012.c +DRIVERFILES += %D%/gw16012.c endif if BITQ -DRIVERFILES += bitq.c +DRIVERFILES += %D%/bitq.c endif -if PRESTO_DRIVER -DRIVERFILES += presto.c +if PRESTO +DRIVERFILES += %D%/presto.c endif if USBPROG -DRIVERFILES += usbprog.c +DRIVERFILES += %D%/usbprog.c endif if RLINK -DRIVERFILES += rlink.c rlink_speed_table.c +DRIVERFILES += %D%/rlink.c %D%/rlink_speed_table.c endif if ULINK -DRIVERFILES += ulink.c +DRIVERFILES += %D%/ulink.c ulinkdir = $(pkgdatadir)/OpenULINK dist_ulink_DATA = $(ULINK_FIRMWARE)/ulink_firmware.hex +%C%_libocdjtagdrivers_la_LIBADD += -lm endif if VSLLINK -DRIVERFILES += versaloon/usbtoxxx/usbtogpio.c -DRIVERFILES += versaloon/usbtoxxx/usbtojtagraw.c -DRIVERFILES += versaloon/usbtoxxx/usbtoswd.c -DRIVERFILES += versaloon/usbtoxxx/usbtopwr.c -DRIVERFILES += versaloon/usbtoxxx/usbtoxxx.c -DRIVERFILES += versaloon/versaloon.c -DRIVERFILES += vsllink.c +DRIVERFILES += %D%/versaloon/usbtoxxx/usbtogpio.c +DRIVERFILES += %D%/versaloon/usbtoxxx/usbtojtagraw.c +DRIVERFILES += %D%/versaloon/usbtoxxx/usbtoswd.c +DRIVERFILES += %D%/versaloon/usbtoxxx/usbtopwr.c +DRIVERFILES += %D%/versaloon/usbtoxxx/usbtoxxx.c +DRIVERFILES += %D%/versaloon/versaloon.c +DRIVERFILES += %D%/vsllink.c endif if ARMJTAGEW -DRIVERFILES += arm-jtag-ew.c +DRIVERFILES += %D%/arm-jtag-ew.c endif if BUSPIRATE -DRIVERFILES += buspirate.c +DRIVERFILES += %D%/buspirate.c endif if REMOTE_BITBANG -DRIVERFILES += remote_bitbang.c +DRIVERFILES += %D%/remote_bitbang.c endif if HLADAPTER -DRIVERFILES += stlink_usb.c -DRIVERFILES += ti_icdi_usb.c +DRIVERFILES += %D%/stlink_usb.c +DRIVERFILES += %D%/ti_icdi_usb.c endif if OSBDM -DRIVERFILES += osbdm.c +DRIVERFILES += %D%/osbdm.c endif if OPENDOUS -DRIVERFILES += opendous.c +DRIVERFILES += %D%/opendous.c endif if SYSFSGPIO -DRIVERFILES += sysfsgpio.c +DRIVERFILES += %D%/sysfsgpio.c endif if BCM2835GPIO -DRIVERFILES += bcm2835gpio.c +DRIVERFILES += %D%/bcm2835gpio.c endif - if OPENJTAG -DRIVERFILES += openjtag.c +DRIVERFILES += %D%/openjtag.c endif - if CMSIS_DAP -DRIVERFILES += cmsis_dap_usb.c -endif - -noinst_HEADERS = \ - bitbang.h \ - bitq.h \ - ftd2xx_common.h \ - libusb0_common.h \ - libusb1_common.h \ - libusb_common.h \ - minidriver_imp.h \ - mpsse.h \ - rlink.h \ - rlink_dtc_cmd.h \ - rlink_ep1_cmd.h \ - rlink_st7.h \ - usb_common.h \ - versaloon/usbtoxxx/usbtoxxx.h \ - versaloon/usbtoxxx/usbtoxxx_internal.h \ - versaloon/versaloon.h \ - versaloon/versaloon_include.h \ - versaloon/versaloon_internal.h - -DIST_SUBDIRS = usb_blaster - -if INTERNAL_LIBJAYLINK -DIST_SUBDIRS += libjaylink -endif +DRIVERFILES += %D%/cmsis_dap_usb.c +endif +if IMX_GPIO +DRIVERFILES += %D%/imx_gpio.c +endif + +if KITPROG +DRIVERFILES += %D%/kitprog.c +endif + +DRIVERHEADERS = \ + %D%/bitbang.h \ + %D%/bitq.h \ + %D%/libusb0_common.h \ + %D%/libusb1_common.h \ + %D%/libusb_common.h \ + %D%/minidriver_imp.h \ + %D%/mpsse.h \ + %D%/rlink.h \ + %D%/rlink_dtc_cmd.h \ + %D%/rlink_ep1_cmd.h \ + %D%/rlink_st7.h \ + %D%/usb_common.h \ + %D%/versaloon/usbtoxxx/usbtoxxx.h \ + %D%/versaloon/usbtoxxx/usbtoxxx_internal.h \ + %D%/versaloon/versaloon.h \ + %D%/versaloon/versaloon_include.h \ + %D%/versaloon/versaloon_internal.h -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c index 1622b22..a41caf0 100644 --- a/src/jtag/drivers/bcm2835gpio.c +++ b/src/jtag/drivers/bcm2835gpio.c @@ -468,8 +468,8 @@ static int bcm2835gpio_init(void) return ERROR_JTAG_INIT_FAILED; } - /* set 16mA drive strength */ - pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5a000018 + 7; + /* set 4mA drive strength, slew rate limited, hysteresis on */ + pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5a000008 + 1; tdo_gpio_mode = MODE_GPIO(tdo_gpio); tdi_gpio_mode = MODE_GPIO(tdi_gpio); diff --git a/src/jtag/drivers/cmsis_dap_usb.c b/src/jtag/drivers/cmsis_dap_usb.c index a07064b..86f7968 100644 --- a/src/jtag/drivers/cmsis_dap_usb.c +++ b/src/jtag/drivers/cmsis_dap_usb.c @@ -118,6 +118,13 @@ static bool swd_mode; * Bit 7: nRESET */ +#define SWJ_PIN_TCK (1<<0) +#define SWJ_PIN_TMS (1<<1) +#define SWJ_PIN_TDI (1<<2) +#define SWJ_PIN_TDO (1<<3) +#define SWJ_PIN_TRST (1<<5) +#define SWJ_PIN_SRST (1<<7) + /* CMSIS-DAP SWD Commands */ #define CMD_DAP_SWD_CONFIGURE 0x13 @@ -309,9 +316,11 @@ static int cmsis_dap_usb_open(void) int packet_size = PACKET_SIZE; /* atmel cmsis-dap uses 512 byte reports */ + /* except when it doesn't e.g. with mEDBG on SAMD10 Xplained + * board */ /* TODO: HID report descriptor should be parsed instead of * hardcoding a match by VID */ - if (target_vid == 0x03eb) + if (target_vid == 0x03eb && target_pid != 0x2145) packet_size = 512 + 1; cmsis_dap_handle->packet_buffer = malloc(packet_size); @@ -764,12 +773,12 @@ static int cmsis_dap_get_status(void) if (retval == ERROR_OK) { LOG_INFO("SWCLK/TCK = %d SWDIO/TMS = %d TDI = %d TDO = %d nTRST = %d nRESET = %d", - (d & (0x01 << 0)) ? 1 : 0, /* Bit 0: SWCLK/TCK */ - (d & (0x01 << 1)) ? 1 : 0, /* Bit 1: SWDIO/TMS */ - (d & (0x01 << 2)) ? 1 : 0, /* Bit 2: TDI */ - (d & (0x01 << 3)) ? 1 : 0, /* Bit 3: TDO */ - (d & (0x01 << 5)) ? 1 : 0, /* Bit 5: nTRST */ - (d & (0x01 << 7)) ? 1 : 0); /* Bit 7: nRESET */ + (d & SWJ_PIN_TCK) ? 1 : 0, + (d & SWJ_PIN_TMS) ? 1 : 0, + (d & SWJ_PIN_TDI) ? 1 : 0, + (d & SWJ_PIN_TDO) ? 1 : 0, + (d & SWJ_PIN_TRST) ? 1 : 0, + (d & SWJ_PIN_SRST) ? 1 : 0); } return retval; @@ -812,7 +821,13 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq) return ERROR_FAIL; } - return cmsis_dap_cmd_DAP_SWJ_Sequence(s_len, s); + retval = cmsis_dap_cmd_DAP_SWJ_Sequence(s_len, s); + if (retval != ERROR_OK) + return retval; + + /* Atmel EDBG needs renew clock setting after SWJ_Sequence + * otherwise default frequency is used */ + return cmsis_dap_cmd_DAP_SWJ_Clock(jtag_get_speed_khz()); } static int cmsis_dap_swd_open(void) @@ -990,8 +1005,17 @@ static int cmsis_dap_quit(void) static void cmsis_dap_execute_reset(struct jtag_command *cmd) { - int retval = cmsis_dap_cmd_DAP_SWJ_Pins(cmd->cmd.reset->srst ? 0 : (1 << 7), \ - (1 << 7), 0, NULL); + /* Set both TRST and SRST even if they're not enabled as + * there's no way to tristate them */ + uint8_t pins = 0; + + if (!cmd->cmd.reset->srst) + pins |= SWJ_PIN_SRST; + if (!cmd->cmd.reset->trst) + pins |= SWJ_PIN_TRST; + + int retval = cmsis_dap_cmd_DAP_SWJ_Pins(pins, + SWJ_PIN_TRST | SWJ_PIN_SRST, 0, NULL); if (retval != ERROR_OK) LOG_ERROR("CMSIS-DAP: Interface reset failed"); } @@ -1475,13 +1499,11 @@ static int cmsis_dap_execute_queue(void) static int cmsis_dap_speed(int speed) { - if (speed > DAP_MAX_CLOCK) { - LOG_INFO("reduce speed request: %dkHz to %dkHz maximum", speed, DAP_MAX_CLOCK); - speed = DAP_MAX_CLOCK; - } + if (speed > DAP_MAX_CLOCK) + LOG_INFO("High speed (adapter_khz %d) may be limited by adapter firmware.", speed); if (speed == 0) { - LOG_INFO("RTCK not supported"); + LOG_ERROR("RTCK not supported. Set nonzero adapter_khz."); return ERROR_JTAG_NOT_IMPLEMENTED; } diff --git a/src/jtag/drivers/ft2232.c b/src/jtag/drivers/ft2232.c deleted file mode 100644 index 621da8e..0000000 --- a/src/jtag/drivers/ft2232.c +++ /dev/null @@ -1,4308 +0,0 @@ -/*************************************************************************** -* Copyright (C) 2009 by Øyvind Harboe * -* Øyvind Harboe <oyvind.harboe@zylin.com> * -* * -* Copyright (C) 2009 by SoftPLC Corporation. http://softplc.com * -* Dick Hollenbeck <dick@softplc.com> * -* * -* Copyright (C) 2004, 2006 by Dominic Rath * -* Dominic.Rath@gmx.de * -* * -* Copyright (C) 2008 by Spencer Oliver * -* spen@spen-soft.co.uk * -* * -* 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 * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -* This program is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* 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, see <http://www.gnu.org/licenses/>. * -***************************************************************************/ - -/** - * @file - * JTAG adapters based on the FT2232 full and high speed USB parts are - * popular low cost JTAG debug solutions. Many FT2232 based JTAG adapters - * are discrete, but development boards may integrate them as alternatives - * to more capable (and expensive) third party JTAG pods. - * - * JTAG uses only one of the two communications channels ("MPSSE engines") - * on these devices. Adapters based on FT4232 parts have four ports/channels - * (A/B/C/D), instead of just two (A/B). - * - * Especially on development boards integrating one of these chips (as - * opposed to discrete pods/dongles), the additional channels can be used - * for a variety of purposes, but OpenOCD only uses one channel at a time. - * - * - As a USB-to-serial adapter for the target's console UART ... - * which may be able to support ROM boot loaders that load initial - * firmware images to flash (or SRAM). - * - * - On systems which support ARM's SWD in addition to JTAG, or instead - * of it, that second port can be used for reading SWV/SWO trace data. - * - * - Additional JTAG links, e.g. to a CPLD or * FPGA. - * - * FT2232 based JTAG adapters are "dumb" not "smart", because most JTAG - * request/response interactions involve round trips over the USB link. - * A "smart" JTAG adapter has intelligence close to the scan chain, so it - * can for example poll quickly for a status change (usually taking on the - * order of microseconds not milliseconds) before beginning a queued - * transaction which require the previous one to have completed. - * - * There are dozens of adapters of this type, differing in details which - * this driver needs to understand. Those "layout" details are required - * as part of FT2232 driver configuration. - * - * This code uses information contained in the MPSSE specification which was - * found here: - * http://www.ftdichip.com/Documents/AppNotes/AN2232C-01_MPSSE_Cmnd.pdf - * Hereafter this is called the "MPSSE Spec". - * - * The datasheet for the ftdichip.com's FT2232D part is here: - * http://www.ftdichip.com/Documents/DataSheets/DS_FT2232D.pdf - * - * Also note the issue with code 0x4b (clock data to TMS) noted in - * http://developer.intra2net.com/mailarchive/html/libftdi/2009/msg00292.html - * which can affect longer JTAG state paths. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* project specific includes */ -#include <jtag/interface.h> -#include <transport/transport.h> -#include <helper/time_support.h> - -#if IS_CYGWIN == 1 -#include <windows.h> -#endif - -#include <assert.h> - -#if (BUILD_FT2232_FTD2XX == 1 && BUILD_FT2232_LIBFTDI == 1) -#error "BUILD_FT2232_FTD2XX && BUILD_FT2232_LIBFTDI are mutually exclusive" -#elif (BUILD_FT2232_FTD2XX != 1 && BUILD_FT2232_LIBFTDI != 1) -#error "BUILD_FT2232_FTD2XX || BUILD_FT2232_LIBFTDI must be chosen" -#endif - -/* FT2232 access library includes */ -#if BUILD_FT2232_FTD2XX == 1 -#include <ftd2xx.h> -#include "ftd2xx_common.h" - -enum ftdi_interface { - INTERFACE_ANY = 0, - INTERFACE_A = 1, - INTERFACE_B = 2, - INTERFACE_C = 3, - INTERFACE_D = 4 -}; - -#elif BUILD_FT2232_LIBFTDI == 1 -#include <ftdi.h> -#endif - -/* max TCK for the high speed devices 30000 kHz */ -#define FTDI_x232H_MAX_TCK 30000 -/* max TCK for the full speed devices 6000 kHz */ -#define FTDI_2232C_MAX_TCK 6000 -/* this speed value tells that RTCK is requested */ -#define RTCK_SPEED -1 - -/* - * On my Athlon XP 1900+ EHCI host with FT2232H JTAG dongle I get read timeout - * errors with a retry count of 100. Increasing it solves the problem for me. - * - Dimitar - * - * FIXME There's likely an issue with the usb_read_timeout from libftdi. - * Fix that (libusb? kernel? libftdi? here?) and restore the retry count - * to something sane. - */ -#define LIBFTDI_READ_RETRY_COUNT 2000 - -#ifndef BUILD_FT2232_HIGHSPEED - #if BUILD_FT2232_FTD2XX == 1 - enum { FT_DEVICE_2232H = 6, FT_DEVICE_4232H, FT_DEVICE_232H }; - #elif BUILD_FT2232_LIBFTDI == 1 - enum ftdi_chip_type { TYPE_2232H = 4, TYPE_4232H = 5, TYPE_232H = 6 }; - #endif -#endif - -/** - * Send out \a num_cycles on the TCK line while the TAP(s) are in a - * stable state. Calling code must ensure that current state is stable, - * that verification is not done in here. - * - * @param num_cycles The number of clocks cycles to send. - * @param cmd The command to send. - * - * @returns ERROR_OK on success, or ERROR_JTAG_QUEUE_FAILED on failure. - */ -static int ft2232_stableclocks(int num_cycles, struct jtag_command *cmd); - -static char *ft2232_device_desc_A; -static char *ft2232_device_desc; -static char *ft2232_serial; -static uint8_t ft2232_latency = 2; -static unsigned ft2232_max_tck = FTDI_2232C_MAX_TCK; -static int ft2232_channel = INTERFACE_ANY; - -#define MAX_USB_IDS 8 -/* vid = pid = 0 marks the end of the list */ -static uint16_t ft2232_vid[MAX_USB_IDS + 1] = { 0x0403, 0 }; -static uint16_t ft2232_pid[MAX_USB_IDS + 1] = { 0x6010, 0 }; - -struct ft2232_layout { - const char *name; - int (*init)(void); - void (*reset)(int trst, int srst); - void (*blink)(void); - int channel; -}; - -/* init procedures for supported layouts */ -static int usbjtag_init(void); -static int jtagkey_init(void); -static int lm3s811_jtag_init(void); -static int icdi_jtag_init(void); -static int olimex_jtag_init(void); -static int flyswatter1_init(void); -static int flyswatter2_init(void); -static int minimodule_init(void); -static int turtle_init(void); -static int comstick_init(void); -static int stm32stick_init(void); -static int axm0432_jtag_init(void); -static int sheevaplug_init(void); -static int icebear_jtag_init(void); -static int cortino_jtag_init(void); -static int signalyzer_init(void); -static int signalyzer_h_init(void); -static int ktlink_init(void); -static int redbee_init(void); -static int lisa_l_init(void); -static int flossjtag_init(void); -static int xds100v2_init(void); -static int digilent_hs1_init(void); - -/* reset procedures for supported layouts */ -static void ftx23_reset(int trst, int srst); -static void jtagkey_reset(int trst, int srst); -static void olimex_jtag_reset(int trst, int srst); -static void flyswatter1_reset(int trst, int srst); -static void flyswatter2_reset(int trst, int srst); -static void minimodule_reset(int trst, int srst); -static void turtle_reset(int trst, int srst); -static void comstick_reset(int trst, int srst); -static void stm32stick_reset(int trst, int srst); -static void axm0432_jtag_reset(int trst, int srst); -static void sheevaplug_reset(int trst, int srst); -static void icebear_jtag_reset(int trst, int srst); -static void signalyzer_h_reset(int trst, int srst); -static void ktlink_reset(int trst, int srst); -static void redbee_reset(int trst, int srst); -static void xds100v2_reset(int trst, int srst); -static void digilent_hs1_reset(int trst, int srst); - -/* blink procedures for layouts that support a blinking led */ -static void olimex_jtag_blink(void); -static void flyswatter1_jtag_blink(void); -static void flyswatter2_jtag_blink(void); -static void turtle_jtag_blink(void); -static void signalyzer_h_blink(void); -static void ktlink_blink(void); -static void lisa_l_blink(void); -static void flossjtag_blink(void); - -/* common transport support options */ - -/* static const char *jtag_and_swd[] = { "jtag", "swd", NULL }; */ - -static const struct ft2232_layout ft2232_layouts[] = { - { .name = "usbjtag", - .init = usbjtag_init, - .reset = ftx23_reset, - }, - { .name = "jtagkey", - .init = jtagkey_init, - .reset = jtagkey_reset, - }, - { .name = "jtagkey_prototype_v1", - .init = jtagkey_init, - .reset = jtagkey_reset, - }, - { .name = "oocdlink", - .init = jtagkey_init, - .reset = jtagkey_reset, - }, - { .name = "signalyzer", - .init = signalyzer_init, - .reset = ftx23_reset, - }, - { .name = "evb_lm3s811", - .init = lm3s811_jtag_init, - .reset = ftx23_reset, - }, - { .name = "luminary_icdi", - .init = icdi_jtag_init, - .reset = ftx23_reset, - }, - { .name = "olimex-jtag", - .init = olimex_jtag_init, - .reset = olimex_jtag_reset, - .blink = olimex_jtag_blink - }, - { .name = "flyswatter", - .init = flyswatter1_init, - .reset = flyswatter1_reset, - .blink = flyswatter1_jtag_blink - }, - { .name = "flyswatter2", - .init = flyswatter2_init, - .reset = flyswatter2_reset, - .blink = flyswatter2_jtag_blink - }, - { .name = "minimodule", - .init = minimodule_init, - .reset = minimodule_reset, - }, - { .name = "turtelizer2", - .init = turtle_init, - .reset = turtle_reset, - .blink = turtle_jtag_blink - }, - { .name = "comstick", - .init = comstick_init, - .reset = comstick_reset, - }, - { .name = "stm32stick", - .init = stm32stick_init, - .reset = stm32stick_reset, - }, - { .name = "axm0432_jtag", - .init = axm0432_jtag_init, - .reset = axm0432_jtag_reset, - }, - { .name = "sheevaplug", - .init = sheevaplug_init, - .reset = sheevaplug_reset, - }, - { .name = "icebear", - .init = icebear_jtag_init, - .reset = icebear_jtag_reset, - }, - { .name = "cortino", - .init = cortino_jtag_init, - .reset = comstick_reset, - }, - { .name = "signalyzer-h", - .init = signalyzer_h_init, - .reset = signalyzer_h_reset, - .blink = signalyzer_h_blink - }, - { .name = "ktlink", - .init = ktlink_init, - .reset = ktlink_reset, - .blink = ktlink_blink - }, - { .name = "redbee-econotag", - .init = redbee_init, - .reset = redbee_reset, - }, - { .name = "redbee-usb", - .init = redbee_init, - .reset = redbee_reset, - .channel = INTERFACE_B, - }, - { .name = "lisa-l", - .init = lisa_l_init, - .reset = ftx23_reset, - .blink = lisa_l_blink, - .channel = INTERFACE_B, - }, - { .name = "flossjtag", - .init = flossjtag_init, - .reset = ftx23_reset, - .blink = flossjtag_blink, - }, - { .name = "xds100v2", - .init = xds100v2_init, - .reset = xds100v2_reset, - }, - { .name = "digilent-hs1", - .init = digilent_hs1_init, - .reset = digilent_hs1_reset, - .channel = INTERFACE_A, - }, - { .name = NULL, /* END OF TABLE */ }, -}; - -/* bitmask used to drive nTRST; usually a GPIOLx signal */ -static uint8_t nTRST; -static uint8_t nTRSTnOE; -/* bitmask used to drive nSRST; usually a GPIOLx signal */ -static uint8_t nSRST; -static uint8_t nSRSTnOE; - -/** the layout being used with this debug session */ -static const struct ft2232_layout *layout; - -/** default bitmask values driven on DBUS: TCK/TDI/TDO/TMS and GPIOL(0..4) */ -static uint8_t low_output; - -/* note that direction bit == 1 means that signal is an output */ - -/** default direction bitmask for DBUS: TCK/TDI/TDO/TMS and GPIOL(0..4) */ -static uint8_t low_direction; -/** default value bitmask for CBUS GPIOH(0..4) */ -static uint8_t high_output; -/** default direction bitmask for CBUS GPIOH(0..4) */ -static uint8_t high_direction; - -#if BUILD_FT2232_FTD2XX == 1 -static FT_HANDLE ftdih; -static FT_DEVICE ftdi_device; -#elif BUILD_FT2232_LIBFTDI == 1 -static struct ftdi_context ftdic; -static enum ftdi_chip_type ftdi_device; -#endif - -static struct jtag_command *first_unsent; /* next command that has to be sent */ -static int require_send; - -/* http://urjtag.wiki.sourceforge.net/Cable + FT2232 says: - - "There is a significant difference between libftdi and libftd2xx. The latter - one allows to schedule up to 64*64 bytes of result data while libftdi fails - with more than 4*64. As a consequence, the FT2232 driver is forced to - perform around 16x more USB transactions for long command streams with TDO - capture when running with libftdi." - - No idea how we get - #define FT2232_BUFFER_SIZE 131072 - a comment would have been nice. -*/ - -#if BUILD_FT2232_FTD2XX == 1 -#define FT2232_BUFFER_READ_QUEUE_SIZE (64*64) -#else -#define FT2232_BUFFER_READ_QUEUE_SIZE (64*4) -#endif - -#define FT2232_BUFFER_SIZE 131072 - -static uint8_t *ft2232_buffer; -static int ft2232_buffer_size; -static int ft2232_read_pointer; -static int ft2232_expect_read; - -/** - * Function buffer_write - * writes a byte into the byte buffer, "ft2232_buffer", which must be sent later. - * @param val is the byte to send. - */ -static inline void buffer_write(uint8_t val) -{ - assert(ft2232_buffer); - assert((unsigned) ft2232_buffer_size < (unsigned) FT2232_BUFFER_SIZE); - ft2232_buffer[ft2232_buffer_size++] = val; -} - -/** - * Function buffer_read - * returns a byte from the byte buffer. - */ -static inline uint8_t buffer_read(void) -{ - assert(ft2232_buffer); - assert(ft2232_read_pointer < ft2232_buffer_size); - return ft2232_buffer[ft2232_read_pointer++]; -} - -/** - * Clocks out \a bit_count bits on the TMS line, starting with the least - * significant bit of tms_bits and progressing to more significant bits. - * Rigorous state transition logging is done here via tap_set_state(). - * - * @param mpsse_cmd One of the MPSSE TMS oriented commands such as - * 0x4b or 0x6b. See the MPSSE spec referenced above for their - * functionality. The MPSSE command "Clock Data to TMS/CS Pin (no Read)" - * is often used for this, 0x4b. - * - * @param tms_bits Holds the sequence of bits to send. - * @param tms_count Tells how many bits in the sequence. - * @param tdi_bit A single bit to pass on to TDI before the first TCK - * cycle and held static for the duration of TMS clocking. - * - * See the MPSSE spec referenced above. - */ -static void clock_tms(uint8_t mpsse_cmd, int tms_bits, int tms_count, bool tdi_bit) -{ - uint8_t tms_byte; - int i; - int tms_ndx; /* bit index into tms_byte */ - - assert(tms_count > 0); - - DEBUG_JTAG_IO("mpsse cmd=%02x, tms_bits = 0x%08x, bit_count=%d", - mpsse_cmd, tms_bits, tms_count); - - for (tms_byte = tms_ndx = i = 0; i < tms_count; ++i, tms_bits >>= 1) { - bool bit = tms_bits & 1; - - if (bit) - tms_byte |= (1 << tms_ndx); - - /* always do state transitions in public view */ - tap_set_state(tap_state_transition(tap_get_state(), bit)); - - /* we wrote a bit to tms_byte just above, increment bit index. if bit was zero - * also increment. - */ - ++tms_ndx; - - if (tms_ndx == 7 || i == tms_count-1) { - buffer_write(mpsse_cmd); - buffer_write(tms_ndx - 1); - - /* Bit 7 of the byte is passed on to TDI/DO before the first TCK/SK of - * TMS/CS and is held static for the duration of TMS/CS clocking. - */ - buffer_write(tms_byte | (tdi_bit << 7)); - } - } -} - -/** - * Function get_tms_buffer_requirements - * returns what clock_tms() will consume if called with - * same \a bit_count. - */ -static inline int get_tms_buffer_requirements(int bit_count) -{ - return ((bit_count + 6)/7) * 3; -} - -/** - * Function move_to_state - * moves the TAP controller from the current state to a - * \a goal_state through a path given by tap_get_tms_path(). State transition - * logging is performed by delegation to clock_tms(). - * - * @param goal_state is the destination state for the move. - */ -static void move_to_state(tap_state_t goal_state) -{ - tap_state_t start_state = tap_get_state(); - - /* goal_state is 1/2 of a tuple/pair of states which allow convenient - * lookup of the required TMS pattern to move to this state from the start state. - */ - - /* do the 2 lookups */ - int tms_bits = tap_get_tms_path(start_state, goal_state); - int tms_count = tap_get_tms_path_len(start_state, goal_state); - - DEBUG_JTAG_IO("start=%s goal=%s", tap_state_name(start_state), tap_state_name(goal_state)); - - clock_tms(0x4b, tms_bits, tms_count, 0); -} - -static int ft2232_write(uint8_t *buf, int size, uint32_t *bytes_written) -{ -#if BUILD_FT2232_FTD2XX == 1 - FT_STATUS status; - DWORD dw_bytes_written = 0; - status = FT_Write(ftdih, buf, size, &dw_bytes_written); - if (status != FT_OK) { - *bytes_written = dw_bytes_written; - LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } else - *bytes_written = dw_bytes_written; - -#elif BUILD_FT2232_LIBFTDI == 1 - int retval = ftdi_write_data(&ftdic, buf, size); - if (retval < 0) { - *bytes_written = 0; - LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&ftdic)); - return ERROR_JTAG_DEVICE_ERROR; - } else - *bytes_written = retval; - -#endif - - if (*bytes_written != (uint32_t)size) - return ERROR_JTAG_DEVICE_ERROR; - - return ERROR_OK; -} - -static int ft2232_read(uint8_t *buf, uint32_t size, uint32_t *bytes_read) -{ -#if BUILD_FT2232_FTD2XX == 1 - DWORD dw_bytes_read; - FT_STATUS status; - int timeout = 5; - *bytes_read = 0; - - while ((*bytes_read < size) && timeout--) { - status = FT_Read(ftdih, buf + *bytes_read, size - - *bytes_read, &dw_bytes_read); - if (status != FT_OK) { - *bytes_read = 0; - LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - *bytes_read += dw_bytes_read; - } - -#elif BUILD_FT2232_LIBFTDI == 1 - int retval; - int timeout = LIBFTDI_READ_RETRY_COUNT; - *bytes_read = 0; - - while ((*bytes_read < size) && timeout--) { - retval = ftdi_read_data(&ftdic, buf + *bytes_read, size - *bytes_read); - if (retval < 0) { - *bytes_read = 0; - LOG_ERROR("ftdi_read_data: %s", ftdi_get_error_string(&ftdic)); - return ERROR_JTAG_DEVICE_ERROR; - } - *bytes_read += retval; - } - -#endif - - if (*bytes_read < size) { - LOG_ERROR("couldn't read enough bytes from " - "FT2232 device (%i < %i)", - (unsigned)*bytes_read, - (unsigned)size); - return ERROR_JTAG_DEVICE_ERROR; - } - - return ERROR_OK; -} - -static bool ft2232_device_is_highspeed(void) -{ -#if BUILD_FT2232_FTD2XX == 1 - return (ftdi_device == FT_DEVICE_2232H) || (ftdi_device == FT_DEVICE_4232H) - #ifdef HAS_ENUM_FT232H - || (ftdi_device == FT_DEVICE_232H) - #endif - ; -#elif BUILD_FT2232_LIBFTDI == 1 - return (ftdi_device == TYPE_2232H || ftdi_device == TYPE_4232H - #ifdef HAS_ENUM_FT232H - || ftdi_device == TYPE_232H - #endif - ); -#endif -} - -/* - * Commands that only apply to the highspeed FTx232H devices (FT2232H, FT4232H, FT232H). - * See chapter 6 in http://www.ftdichip.com/Documents/AppNotes/ - * AN_108_Command_Processor_for_MPSSE_and_MCU_Host_Bus_Emulation_Modes.pdf - */ - -static int ftx232h_adaptive_clocking(bool enable) -{ - uint8_t buf = enable ? 0x96 : 0x97; - LOG_DEBUG("%2.2x", buf); - - uint32_t bytes_written; - int retval; - - retval = ft2232_write(&buf, sizeof(buf), &bytes_written); - if (retval != ERROR_OK) { - LOG_ERROR("couldn't write command to %s adaptive clocking" - , enable ? "enable" : "disable"); - return retval; - } - - return ERROR_OK; -} - -/** - * Enable/disable the clk divide by 5 of the 60MHz master clock. - * This result in a JTAG clock speed range of 91.553Hz-6MHz - * respective 457.763Hz-30MHz. - */ -static int ftx232h_clk_divide_by_5(bool enable) -{ - uint32_t bytes_written; - uint8_t buf = enable ? 0x8b : 0x8a; - - if (ft2232_write(&buf, sizeof(buf), &bytes_written) != ERROR_OK) { - LOG_ERROR("couldn't write command to %s clk divide by 5" - , enable ? "enable" : "disable"); - return ERROR_JTAG_INIT_FAILED; - } - ft2232_max_tck = enable ? FTDI_2232C_MAX_TCK : FTDI_x232H_MAX_TCK; - LOG_INFO("max TCK change to: %u kHz", ft2232_max_tck); - - return ERROR_OK; -} - -static int ft2232_speed(int speed) -{ - uint8_t buf[3]; - int retval; - uint32_t bytes_written; - - retval = ERROR_OK; - bool enable_adaptive_clocking = (RTCK_SPEED == speed); - if (ft2232_device_is_highspeed()) - retval = ftx232h_adaptive_clocking(enable_adaptive_clocking); - else if (enable_adaptive_clocking) { - LOG_ERROR("ft2232 device %lu does not support RTCK" - , (long unsigned int)ftdi_device); - return ERROR_FAIL; - } - - if ((enable_adaptive_clocking) || (ERROR_OK != retval)) - return retval; - - buf[0] = 0x86; /* command "set divisor" */ - buf[1] = speed & 0xff; /* valueL (0 = 6MHz, 1 = 3MHz, 2 = 2.0MHz, ...*/ - buf[2] = (speed >> 8) & 0xff; /* valueH */ - - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - retval = ft2232_write(buf, sizeof(buf), &bytes_written); - if (retval != ERROR_OK) { - LOG_ERROR("couldn't set FT2232 TCK speed"); - return retval; - } - - return ERROR_OK; -} - -static int ft2232_speed_div(int speed, int *khz) -{ - /* Take a look in the FT2232 manual, - * AN2232C-01 Command Processor for - * MPSSE and MCU Host Bus. Chapter 3.8 */ - - *khz = (RTCK_SPEED == speed) ? 0 : ft2232_max_tck / (1 + speed); - - return ERROR_OK; -} - -static int ft2232_khz(int khz, int *jtag_speed) -{ - if (khz == 0) { - if (ft2232_device_is_highspeed()) { - *jtag_speed = RTCK_SPEED; - return ERROR_OK; - } else { - LOG_DEBUG("RCLK not supported"); - return ERROR_FAIL; - } - } - - /* Take a look in the FT2232 manual, - * AN2232C-01 Command Processor for - * MPSSE and MCU Host Bus. Chapter 3.8 - * - * We will calc here with a multiplier - * of 10 for better rounding later. */ - - /* Calc speed, (ft2232_max_tck / khz) - 1 - * Use 65000 for better rounding */ - *jtag_speed = ((ft2232_max_tck*10) / khz) - 10; - - /* Add 0.9 for rounding */ - *jtag_speed += 9; - - /* Calc real speed */ - *jtag_speed = *jtag_speed / 10; - - /* Check if speed is greater than 0 */ - if (*jtag_speed < 0) - *jtag_speed = 0; - - /* Check max value */ - if (*jtag_speed > 0xFFFF) - *jtag_speed = 0xFFFF; - - return ERROR_OK; -} - -static void ft2232_end_state(tap_state_t state) -{ - if (tap_is_state_stable(state)) - tap_set_end_state(state); - else { - LOG_ERROR("BUG: %s is not a stable end state", tap_state_name(state)); - exit(-1); - } -} - -static void ft2232_read_scan(enum scan_type type, uint8_t *buffer, int scan_size) -{ - int num_bytes = (scan_size + 7) / 8; - int bits_left = scan_size; - int cur_byte = 0; - - while (num_bytes-- > 1) { - buffer[cur_byte++] = buffer_read(); - bits_left -= 8; - } - - buffer[cur_byte] = 0x0; - - /* There is one more partial byte left from the clock data in/out instructions */ - if (bits_left > 1) - buffer[cur_byte] = buffer_read() >> 1; - /* This shift depends on the length of the - *clock data to tms instruction, insterted - *at end of the scan, now fixed to a two - *step transition in ft2232_add_scan */ - buffer[cur_byte] = (buffer[cur_byte] | (((buffer_read()) << 1) & 0x80)) >> (8 - bits_left); -} - -static void ft2232_debug_dump_buffer(void) -{ - int i; - char line[256]; - char *line_p = line; - - for (i = 0; i < ft2232_buffer_size; i++) { - line_p += snprintf(line_p, - sizeof(line) - (line_p - line), - "%2.2x ", - ft2232_buffer[i]); - if (i % 16 == 15) { - LOG_DEBUG("%s", line); - line_p = line; - } - } - - if (line_p != line) - LOG_DEBUG("%s", line); -} - -static int ft2232_send_and_recv(struct jtag_command *first, struct jtag_command *last) -{ - struct jtag_command *cmd; - uint8_t *buffer; - int scan_size; - enum scan_type type; - int retval; - uint32_t bytes_written = 0; - uint32_t bytes_read = 0; - -#ifdef _DEBUG_USB_IO_ - struct timeval start, inter, inter2, end; - struct timeval d_inter, d_inter2, d_end; -#endif - -#ifdef _DEBUG_USB_COMMS_ - LOG_DEBUG("write buffer (size %i):", ft2232_buffer_size); - ft2232_debug_dump_buffer(); -#endif - -#ifdef _DEBUG_USB_IO_ - gettimeofday(&start, NULL); -#endif - - retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written); - if (retval != ERROR_OK) { - LOG_ERROR("couldn't write MPSSE commands to FT2232"); - return retval; - } - -#ifdef _DEBUG_USB_IO_ - gettimeofday(&inter, NULL); -#endif - - if (ft2232_expect_read) { - /* FIXME this "timeout" is never changed ... */ - int timeout = LIBFTDI_READ_RETRY_COUNT; - ft2232_buffer_size = 0; - -#ifdef _DEBUG_USB_IO_ - gettimeofday(&inter2, NULL); -#endif - - retval = ft2232_read(ft2232_buffer, ft2232_expect_read, &bytes_read); - if (retval != ERROR_OK) { - LOG_ERROR("couldn't read from FT2232"); - return retval; - } - -#ifdef _DEBUG_USB_IO_ - gettimeofday(&end, NULL); - - timeval_subtract(&d_inter, &inter, &start); - timeval_subtract(&d_inter2, &inter2, &start); - timeval_subtract(&d_end, &end, &start); - - LOG_INFO("inter: %u.%06u, inter2: %u.%06u end: %u.%06u", - (unsigned)d_inter.tv_sec, (unsigned)d_inter.tv_usec, - (unsigned)d_inter2.tv_sec, (unsigned)d_inter2.tv_usec, - (unsigned)d_end.tv_sec, (unsigned)d_end.tv_usec); -#endif - - ft2232_buffer_size = bytes_read; - - if (ft2232_expect_read != ft2232_buffer_size) { - LOG_ERROR("ft2232_expect_read (%i) != " - "ft2232_buffer_size (%i) " - "(%i retries)", - ft2232_expect_read, - ft2232_buffer_size, - LIBFTDI_READ_RETRY_COUNT - timeout); - ft2232_debug_dump_buffer(); - - exit(-1); - } - -#ifdef _DEBUG_USB_COMMS_ - LOG_DEBUG("read buffer (%i retries): %i bytes", - LIBFTDI_READ_RETRY_COUNT - timeout, - ft2232_buffer_size); - ft2232_debug_dump_buffer(); -#endif - } - - ft2232_expect_read = 0; - ft2232_read_pointer = 0; - - /* return ERROR_OK, unless a jtag_read_buffer returns a failed check - * that wasn't handled by a caller-provided error handler - */ - retval = ERROR_OK; - - cmd = first; - while (cmd != last) { - switch (cmd->type) { - case JTAG_SCAN: - type = jtag_scan_type(cmd->cmd.scan); - if (type != SCAN_OUT) { - scan_size = jtag_scan_size(cmd->cmd.scan); - buffer = calloc(DIV_ROUND_UP(scan_size, 8), 1); - ft2232_read_scan(type, buffer, scan_size); - if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - free(buffer); - } - break; - - default: - break; - } - - cmd = cmd->next; - } - - ft2232_buffer_size = 0; - - return retval; -} - -/** - * Function ft2232_add_pathmove - * moves the TAP controller from the current state to a new state through the - * given path, where path is an array of tap_state_t's. - * - * @param path is an array of tap_stat_t which gives the states to traverse through - * ending with the last state at path[num_states-1] - * @param num_states is the count of state steps to move through - */ -static void ft2232_add_pathmove(tap_state_t *path, int num_states) -{ - int state_count = 0; - - assert((unsigned) num_states <= 32u); /* tms_bits only holds 32 bits */ - - DEBUG_JTAG_IO("-"); - - /* this loop verifies that the path is legal and logs each state in the path */ - while (num_states) { - unsigned char tms_byte = 0; /* zero this on each MPSSE batch */ - int bit_count = 0; - int num_states_batch = num_states > 7 ? 7 : num_states; - - /* command "Clock Data to TMS/CS Pin (no Read)" */ - buffer_write(0x4b); - - /* number of states remaining */ - buffer_write(num_states_batch - 1); - - while (num_states_batch--) { - /* either TMS=0 or TMS=1 must work ... */ - if (tap_state_transition(tap_get_state(), false) == path[state_count]) - buf_set_u32(&tms_byte, bit_count++, 1, 0x0); - else if (tap_state_transition(tap_get_state(), true) == path[state_count]) - buf_set_u32(&tms_byte, bit_count++, 1, 0x1); - - /* ... or else the caller goofed BADLY */ - else { - LOG_ERROR("BUG: %s -> %s isn't a valid " - "TAP state transition", - tap_state_name(tap_get_state()), - tap_state_name(path[state_count])); - exit(-1); - } - - tap_set_state(path[state_count]); - state_count++; - num_states--; - } - - buffer_write(tms_byte); - } - tap_set_end_state(tap_get_state()); -} - -static void ft2232_add_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size) -{ - int num_bytes = (scan_size + 7) / 8; - int bits_left = scan_size; - int cur_byte = 0; - int last_bit; - - if (!ir_scan) { - if (tap_get_state() != TAP_DRSHIFT) - move_to_state(TAP_DRSHIFT); - } else { - if (tap_get_state() != TAP_IRSHIFT) - move_to_state(TAP_IRSHIFT); - } - - /* add command for complete bytes */ - while (num_bytes > 1) { - int thisrun_bytes; - if (type == SCAN_IO) { - /* Clock Data Bytes In and Out LSB First */ - buffer_write(0x39); - /* LOG_DEBUG("added TDI bytes (io %i)", num_bytes); */ - } else if (type == SCAN_OUT) { - /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */ - buffer_write(0x19); - /* LOG_DEBUG("added TDI bytes (o)"); */ - } else if (type == SCAN_IN) { - /* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */ - buffer_write(0x28); - /* LOG_DEBUG("added TDI bytes (i %i)", num_bytes); */ - } - - thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1); - num_bytes -= thisrun_bytes; - - buffer_write((uint8_t) (thisrun_bytes - 1)); - buffer_write((uint8_t) ((thisrun_bytes - 1) >> 8)); - - if (type != SCAN_IN) { - /* add complete bytes */ - while (thisrun_bytes-- > 0) { - buffer_write(buffer[cur_byte++]); - bits_left -= 8; - } - } else /* (type == SCAN_IN) */ - bits_left -= 8 * (thisrun_bytes); - } - - /* the most signifcant bit is scanned during TAP movement */ - if (type != SCAN_IN) - last_bit = (buffer[cur_byte] >> (bits_left - 1)) & 0x1; - else - last_bit = 0; - - /* process remaining bits but the last one */ - if (bits_left > 1) { - if (type == SCAN_IO) { - /* Clock Data Bits In and Out LSB First */ - buffer_write(0x3b); - /* LOG_DEBUG("added TDI bits (io) %i", bits_left - 1); */ - } else if (type == SCAN_OUT) { - /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */ - buffer_write(0x1b); - /* LOG_DEBUG("added TDI bits (o)"); */ - } else if (type == SCAN_IN) { - /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */ - buffer_write(0x2a); - /* LOG_DEBUG("added TDI bits (i %i)", bits_left - 1); */ - } - - buffer_write(bits_left - 2); - if (type != SCAN_IN) - buffer_write(buffer[cur_byte]); - } - - if ((ir_scan && (tap_get_end_state() == TAP_IRSHIFT)) - || (!ir_scan && (tap_get_end_state() == TAP_DRSHIFT))) { - if (type == SCAN_IO) { - /* Clock Data Bits In and Out LSB First */ - buffer_write(0x3b); - /* LOG_DEBUG("added TDI bits (io) %i", bits_left - 1); */ - } else if (type == SCAN_OUT) { - /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */ - buffer_write(0x1b); - /* LOG_DEBUG("added TDI bits (o)"); */ - } else if (type == SCAN_IN) { - /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */ - buffer_write(0x2a); - /* LOG_DEBUG("added TDI bits (i %i)", bits_left - 1); */ - } - buffer_write(0x0); - if (type != SCAN_IN) - buffer_write(last_bit); - } else { - int tms_bits; - int tms_count; - uint8_t mpsse_cmd; - - /* move from Shift-IR/DR to end state */ - if (type != SCAN_OUT) { - /* We always go to the PAUSE state in two step at the end of an IN or IO - *scan - * This must be coordinated with the bit shifts in ft2232_read_scan */ - tms_bits = 0x01; - tms_count = 2; - /* Clock Data to TMS/CS Pin with Read */ - mpsse_cmd = 0x6b; - } else { - tms_bits = tap_get_tms_path(tap_get_state(), tap_get_end_state()); - tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); - /* Clock Data to TMS/CS Pin (no Read) */ - mpsse_cmd = 0x4b; - } - - DEBUG_JTAG_IO("finish %s", (type == SCAN_OUT) ? "without read" : "via PAUSE"); - clock_tms(mpsse_cmd, tms_bits, tms_count, last_bit); - } - - if (tap_get_state() != tap_get_end_state()) - move_to_state(tap_get_end_state()); -} - -static int ft2232_large_scan(struct scan_command *cmd, - enum scan_type type, - uint8_t *buffer, - int scan_size) -{ - int num_bytes = (scan_size + 7) / 8; - int bits_left = scan_size; - int cur_byte = 0; - int last_bit; - uint8_t *receive_buffer = malloc(DIV_ROUND_UP(scan_size, 8)); - uint8_t *receive_pointer = receive_buffer; - uint32_t bytes_written; - uint32_t bytes_read; - int retval; - int thisrun_read = 0; - - if (!receive_buffer) { - LOG_ERROR("failed to allocate memory"); - exit(-1); - } - - if (cmd->ir_scan) { - LOG_ERROR("BUG: large IR scans are not supported"); - exit(-1); - } - - if (tap_get_state() != TAP_DRSHIFT) - move_to_state(TAP_DRSHIFT); - - retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written); - if (retval != ERROR_OK) { - LOG_ERROR("couldn't write MPSSE commands to FT2232"); - exit(-1); - } - LOG_DEBUG("ft2232_buffer_size: %i, bytes_written: %i", - ft2232_buffer_size, (int)bytes_written); - ft2232_buffer_size = 0; - - /* add command for complete bytes */ - while (num_bytes > 1) { - int thisrun_bytes; - - if (type == SCAN_IO) { - /* Clock Data Bytes In and Out LSB First */ - buffer_write(0x39); - /* LOG_DEBUG("added TDI bytes (io %i)", num_bytes); */ - } else if (type == SCAN_OUT) { - /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */ - buffer_write(0x19); - /* LOG_DEBUG("added TDI bytes (o)"); */ - } else if (type == SCAN_IN) { - /* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */ - buffer_write(0x28); - /* LOG_DEBUG("added TDI bytes (i %i)", num_bytes); */ - } - - thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1); - thisrun_read = thisrun_bytes; - num_bytes -= thisrun_bytes; - buffer_write((uint8_t) (thisrun_bytes - 1)); - buffer_write((uint8_t) ((thisrun_bytes - 1) >> 8)); - - if (type != SCAN_IN) { - /* add complete bytes */ - while (thisrun_bytes-- > 0) { - buffer_write(buffer[cur_byte]); - cur_byte++; - bits_left -= 8; - } - } else /* (type == SCAN_IN) */ - bits_left -= 8 * (thisrun_bytes); - - retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written); - if (retval != ERROR_OK) { - LOG_ERROR("couldn't write MPSSE commands to FT2232"); - exit(-1); - } - LOG_DEBUG("ft2232_buffer_size: %i, bytes_written: %i", - ft2232_buffer_size, - (int)bytes_written); - ft2232_buffer_size = 0; - - if (type != SCAN_OUT) { - retval = ft2232_read(receive_pointer, thisrun_read, &bytes_read); - if (retval != ERROR_OK) { - LOG_ERROR("couldn't read from FT2232"); - exit(-1); - } - LOG_DEBUG("thisrun_read: %i, bytes_read: %i", - thisrun_read, - (int)bytes_read); - receive_pointer += bytes_read; - } - } - - thisrun_read = 0; - - /* the most signifcant bit is scanned during TAP movement */ - if (type != SCAN_IN) - last_bit = (buffer[cur_byte] >> (bits_left - 1)) & 0x1; - else - last_bit = 0; - - /* process remaining bits but the last one */ - if (bits_left > 1) { - if (type == SCAN_IO) { - /* Clock Data Bits In and Out LSB First */ - buffer_write(0x3b); - /* LOG_DEBUG("added TDI bits (io) %i", bits_left - 1); */ - } else if (type == SCAN_OUT) { - /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */ - buffer_write(0x1b); - /* LOG_DEBUG("added TDI bits (o)"); */ - } else if (type == SCAN_IN) { - /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */ - buffer_write(0x2a); - /* LOG_DEBUG("added TDI bits (i %i)", bits_left - 1); */ - } - buffer_write(bits_left - 2); - if (type != SCAN_IN) - buffer_write(buffer[cur_byte]); - - if (type != SCAN_OUT) - thisrun_read += 2; - } - - if (tap_get_end_state() == TAP_DRSHIFT) { - if (type == SCAN_IO) { - /* Clock Data Bits In and Out LSB First */ - buffer_write(0x3b); - /* LOG_DEBUG("added TDI bits (io) %i", bits_left - 1); */ - } else if (type == SCAN_OUT) { - /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */ - buffer_write(0x1b); - /* LOG_DEBUG("added TDI bits (o)"); */ - } else if (type == SCAN_IN) { - /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */ - buffer_write(0x2a); - /* LOG_DEBUG("added TDI bits (i %i)", bits_left - 1); */ - } - buffer_write(0x0); - buffer_write(last_bit); - } else { - int tms_bits = tap_get_tms_path(tap_get_state(), tap_get_end_state()); - int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); - uint8_t mpsse_cmd; - - /* move from Shift-IR/DR to end state */ - if (type != SCAN_OUT) { - /* Clock Data to TMS/CS Pin with Read */ - mpsse_cmd = 0x6b; - /* LOG_DEBUG("added TMS scan (read)"); */ - } else { - /* Clock Data to TMS/CS Pin (no Read) */ - mpsse_cmd = 0x4b; - /* LOG_DEBUG("added TMS scan (no read)"); */ - } - - DEBUG_JTAG_IO("finish, %s", (type == SCAN_OUT) ? "no read" : "read"); - clock_tms(mpsse_cmd, tms_bits, tms_count, last_bit); - } - - if (type != SCAN_OUT) - thisrun_read += 1; - - retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written); - if (retval != ERROR_OK) { - LOG_ERROR("couldn't write MPSSE commands to FT2232"); - exit(-1); - } - LOG_DEBUG("ft2232_buffer_size: %i, bytes_written: %i", - ft2232_buffer_size, - (int)bytes_written); - ft2232_buffer_size = 0; - - if (type != SCAN_OUT) { - retval = ft2232_read(receive_pointer, thisrun_read, &bytes_read); - if (retval != ERROR_OK) { - LOG_ERROR("couldn't read from FT2232"); - exit(-1); - } - LOG_DEBUG("thisrun_read: %i, bytes_read: %i", - thisrun_read, - (int)bytes_read); - } - - free(receive_buffer); - - return ERROR_OK; -} - -static int ft2232_predict_scan_out(int scan_size, enum scan_type type) -{ - int predicted_size = 3; - int num_bytes = (scan_size - 1) / 8; - - if (tap_get_state() != TAP_DRSHIFT) - predicted_size += get_tms_buffer_requirements( - tap_get_tms_path_len(tap_get_state(), TAP_DRSHIFT)); - - if (type == SCAN_IN) { /* only from device to host */ - /* complete bytes */ - predicted_size += DIV_ROUND_UP(num_bytes, 65536) * 3; - - /* remaining bits - 1 (up to 7) */ - predicted_size += ((scan_size - 1) % 8) ? 2 : 0; - } else {/* host to device, or bidirectional - * complete bytes */ - predicted_size += num_bytes + DIV_ROUND_UP(num_bytes, 65536) * 3; - - /* remaining bits -1 (up to 7) */ - predicted_size += ((scan_size - 1) % 8) ? 3 : 0; - } - - return predicted_size; -} - -static int ft2232_predict_scan_in(int scan_size, enum scan_type type) -{ - int predicted_size = 0; - - if (type != SCAN_OUT) { - /* complete bytes */ - predicted_size += - (DIV_ROUND_UP(scan_size, 8) > 1) ? (DIV_ROUND_UP(scan_size, 8) - 1) : 0; - - /* remaining bits - 1 */ - predicted_size += ((scan_size - 1) % 8) ? 1 : 0; - - /* last bit (from TMS scan) */ - predicted_size += 1; - } - - /* LOG_DEBUG("scan_size: %i, predicted_size: %i", scan_size, predicted_size); */ - - return predicted_size; -} - -/* semi-generic FT2232/FT4232 reset code */ -static void ftx23_reset(int trst, int srst) -{ - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if (trst == 1) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - low_direction |= nTRSTnOE; /* switch to output pin (output is low) */ - else - low_output &= ~nTRST; /* switch output low */ - } else if (trst == 0) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - low_direction &= ~nTRSTnOE; /* switch to input pin (high-Z + internal - *and external pullup) */ - else - low_output |= nTRST; /* switch output high */ - } - - if (srst == 1) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - low_output &= ~nSRST; /* switch output low */ - else - low_direction |= nSRSTnOE; /* switch to output pin (output is low) */ - } else if (srst == 0) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - low_output |= nSRST; /* switch output high */ - else - low_direction &= ~nSRSTnOE; /* switch to input pin (high-Z) */ - } - - /* command "set data bits low byte" */ - buffer_write(0x80); - buffer_write(low_output); - buffer_write(low_direction); -} - -static void jtagkey_reset(int trst, int srst) -{ - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if (trst == 1) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - high_output &= ~nTRSTnOE; - else - high_output &= ~nTRST; - } else if (trst == 0) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - high_output |= nTRSTnOE; - else - high_output |= nTRST; - } - - if (srst == 1) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - high_output &= ~nSRST; - else - high_output &= ~nSRSTnOE; - } else if (srst == 0) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - high_output |= nSRST; - else - high_output |= nSRSTnOE; - } - - /* command "set data bits high byte" */ - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); - LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", - trst, - srst, - high_output, - high_direction); -} - -static void olimex_jtag_reset(int trst, int srst) -{ - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if (trst == 1) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - high_output &= ~nTRSTnOE; - else - high_output &= ~nTRST; - } else if (trst == 0) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - high_output |= nTRSTnOE; - else - high_output |= nTRST; - } - - if (srst == 1) - high_output |= nSRST; - else if (srst == 0) - high_output &= ~nSRST; - - /* command "set data bits high byte" */ - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); - LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", - trst, - srst, - high_output, - high_direction); -} - -static void axm0432_jtag_reset(int trst, int srst) -{ - if (trst == 1) { - tap_set_state(TAP_RESET); - high_output &= ~nTRST; - } else if (trst == 0) - high_output |= nTRST; - - if (srst == 1) - high_output &= ~nSRST; - else if (srst == 0) - high_output |= nSRST; - - /* command "set data bits low byte" */ - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); - LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", - trst, - srst, - high_output, - high_direction); -} - -static void flyswatter_reset(int trst, int srst) -{ - if (trst == 1) - low_output &= ~nTRST; - else if (trst == 0) - low_output |= nTRST; - - if (srst == 1) - low_output |= nSRST; - else if (srst == 0) - low_output &= ~nSRST; - - /* command "set data bits low byte" */ - buffer_write(0x80); - buffer_write(low_output); - buffer_write(low_direction); - LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", - trst, - srst, - low_output, - low_direction); -} - -static void flyswatter1_reset(int trst, int srst) -{ - flyswatter_reset(trst, srst); -} - -static void flyswatter2_reset(int trst, int srst) -{ - flyswatter_reset(trst, !srst); -} - -static void minimodule_reset(int trst, int srst) -{ - if (srst == 1) - low_output &= ~nSRST; - else if (srst == 0) - low_output |= nSRST; - - /* command "set data bits low byte" */ - buffer_write(0x80); - buffer_write(low_output); - buffer_write(low_direction); - LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", - trst, - srst, - low_output, - low_direction); -} - -static void turtle_reset(int trst, int srst) -{ - if (trst == 1) - LOG_ERROR("Can't assert TRST: the adapter lacks this signal"); - - if (srst == 1) - low_output |= nSRST; - else if (srst == 0) - low_output &= ~nSRST; - - /* command "set data bits low byte" */ - buffer_write(0x80); - buffer_write(low_output); - buffer_write(low_direction); - LOG_DEBUG("srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", - srst, - low_output, - low_direction); -} - -static void comstick_reset(int trst, int srst) -{ - if (trst == 1) - high_output &= ~nTRST; - else if (trst == 0) - high_output |= nTRST; - - if (srst == 1) - high_output &= ~nSRST; - else if (srst == 0) - high_output |= nSRST; - - /* command "set data bits high byte" */ - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); - LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", - trst, - srst, - high_output, - high_direction); -} - -static void stm32stick_reset(int trst, int srst) -{ - if (trst == 1) - high_output &= ~nTRST; - else if (trst == 0) - high_output |= nTRST; - - if (srst == 1) - low_output &= ~nSRST; - else if (srst == 0) - low_output |= nSRST; - - /* command "set data bits low byte" */ - buffer_write(0x80); - buffer_write(low_output); - buffer_write(low_direction); - - /* command "set data bits high byte" */ - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); - LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", - trst, - srst, - high_output, - high_direction); -} - -static void sheevaplug_reset(int trst, int srst) -{ - if (trst == 1) - high_output &= ~nTRST; - else if (trst == 0) - high_output |= nTRST; - - if (srst == 1) - high_output &= ~nSRSTnOE; - else if (srst == 0) - high_output |= nSRSTnOE; - - /* command "set data bits high byte" */ - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); - LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", - trst, - srst, - high_output, - high_direction); -} - -static void redbee_reset(int trst, int srst) -{ - if (trst == 1) { - tap_set_state(TAP_RESET); - high_output &= ~nTRST; - } else if (trst == 0) - high_output |= nTRST; - - if (srst == 1) - high_output &= ~nSRST; - else if (srst == 0) - high_output |= nSRST; - - /* command "set data bits low byte" */ - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); - LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, " - "high_direction: 0x%2.2x", trst, srst, high_output, - high_direction); -} - -static void xds100v2_reset(int trst, int srst) -{ - if (trst == 1) { - tap_set_state(TAP_RESET); - high_output &= ~nTRST; - } else if (trst == 0) - high_output |= nTRST; - - if (srst == 1) - high_output |= nSRST; - else if (srst == 0) - high_output &= ~nSRST; - - /* command "set data bits low byte" */ - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); - LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, " - "high_direction: 0x%2.2x", trst, srst, high_output, - high_direction); -} - -static int ft2232_execute_runtest(struct jtag_command *cmd) -{ - int retval; - int i; - int predicted_size = 0; - retval = ERROR_OK; - - DEBUG_JTAG_IO("runtest %i cycles, end in %s", - cmd->cmd.runtest->num_cycles, - tap_state_name(cmd->cmd.runtest->end_state)); - - /* only send the maximum buffer size that FT2232C can handle */ - predicted_size = 0; - if (tap_get_state() != TAP_IDLE) - predicted_size += 3; - predicted_size += 3 * DIV_ROUND_UP(cmd->cmd.runtest->num_cycles, 7); - if (cmd->cmd.runtest->end_state != TAP_IDLE) - predicted_size += 3; - if (tap_get_end_state() != TAP_IDLE) - predicted_size += 3; - if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) { - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - require_send = 0; - first_unsent = cmd; - } - if (tap_get_state() != TAP_IDLE) { - move_to_state(TAP_IDLE); - require_send = 1; - } - i = cmd->cmd.runtest->num_cycles; - while (i > 0) { - /* there are no state transitions in this code, so omit state tracking */ - - /* command "Clock Data to TMS/CS Pin (no Read)" */ - buffer_write(0x4b); - - /* scan 7 bits */ - buffer_write((i > 7) ? 6 : (i - 1)); - - /* TMS data bits */ - buffer_write(0x0); - - i -= (i > 7) ? 7 : i; - /* LOG_DEBUG("added TMS scan (no read)"); */ - } - - ft2232_end_state(cmd->cmd.runtest->end_state); - - if (tap_get_state() != tap_get_end_state()) - move_to_state(tap_get_end_state()); - - require_send = 1; - DEBUG_JTAG_IO("runtest: %i, end in %s", - cmd->cmd.runtest->num_cycles, - tap_state_name(tap_get_end_state())); - return retval; -} - -static int ft2232_execute_statemove(struct jtag_command *cmd) -{ - int predicted_size = 0; - int retval = ERROR_OK; - - DEBUG_JTAG_IO("statemove end in %s", - tap_state_name(cmd->cmd.statemove->end_state)); - - /* only send the maximum buffer size that FT2232C can handle */ - predicted_size = 3; - if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) { - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - require_send = 0; - first_unsent = cmd; - } - ft2232_end_state(cmd->cmd.statemove->end_state); - - /* For TAP_RESET, ignore the current recorded state. It's often - * wrong at server startup, and this transation is critical whenever - * it's requested. - */ - if (tap_get_end_state() == TAP_RESET) { - clock_tms(0x4b, 0xff, 5, 0); - require_send = 1; - - /* shortest-path move to desired end state */ - } else if (tap_get_state() != tap_get_end_state()) { - move_to_state(tap_get_end_state()); - require_send = 1; - } - - return retval; -} - -/** - * Clock a bunch of TMS (or SWDIO) transitions, to change the JTAG - * (or SWD) state machine. - */ -static int ft2232_execute_tms(struct jtag_command *cmd) -{ - int retval = ERROR_OK; - unsigned num_bits = cmd->cmd.tms->num_bits; - const uint8_t *bits = cmd->cmd.tms->bits; - unsigned count; - - DEBUG_JTAG_IO("TMS: %d bits", num_bits); - - /* only send the maximum buffer size that FT2232C can handle */ - count = 3 * DIV_ROUND_UP(num_bits, 4); - if (ft2232_buffer_size + 3*count + 1 > FT2232_BUFFER_SIZE) { - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - - require_send = 0; - first_unsent = cmd; - } - - /* Shift out in batches of at most 6 bits; there's a report of an - * FT2232 bug in this area, where shifting exactly 7 bits can make - * problems with TMS signaling for the last clock cycle: - * - * http://developer.intra2net.com/mailarchive/html/ - * libftdi/2009/msg00292.html - * - * Command 0x4b is: "Clock Data to TMS/CS Pin (no Read)" - * - * Note that pathmoves in JTAG are not often seven bits, so that - * isn't a particularly likely situation outside of "special" - * signaling such as switching between JTAG and SWD modes. - */ - while (num_bits) { - if (num_bits <= 6) { - buffer_write(0x4b); - buffer_write(num_bits - 1); - buffer_write(*bits & 0x3f); - break; - } - - /* Yes, this is lazy ... we COULD shift out more data - * bits per operation, but doing it in nybbles is easy - */ - buffer_write(0x4b); - buffer_write(3); - buffer_write(*bits & 0xf); - num_bits -= 4; - - count = (num_bits > 4) ? 4 : num_bits; - - buffer_write(0x4b); - buffer_write(count - 1); - buffer_write((*bits >> 4) & 0xf); - num_bits -= count; - - bits++; - } - - require_send = 1; - return retval; -} - -static int ft2232_execute_pathmove(struct jtag_command *cmd) -{ - int predicted_size = 0; - int retval = ERROR_OK; - - tap_state_t *path = cmd->cmd.pathmove->path; - int num_states = cmd->cmd.pathmove->num_states; - - DEBUG_JTAG_IO("pathmove: %i states, current: %s end: %s", num_states, - tap_state_name(tap_get_state()), - tap_state_name(path[num_states-1])); - - /* only send the maximum buffer size that FT2232C can handle */ - predicted_size = 3 * DIV_ROUND_UP(num_states, 7); - if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) { - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - - require_send = 0; - first_unsent = cmd; - } - - ft2232_add_pathmove(path, num_states); - require_send = 1; - - return retval; -} - -static int ft2232_execute_scan(struct jtag_command *cmd) -{ - uint8_t *buffer; - int scan_size; /* size of IR or DR scan */ - int predicted_size = 0; - int retval = ERROR_OK; - - enum scan_type type = jtag_scan_type(cmd->cmd.scan); - - DEBUG_JTAG_IO("%s type:%d", cmd->cmd.scan->ir_scan ? "IRSCAN" : "DRSCAN", type); - - scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); - - predicted_size = ft2232_predict_scan_out(scan_size, type); - if ((predicted_size + 1) > FT2232_BUFFER_SIZE) { - LOG_DEBUG("oversized ft2232 scan (predicted_size > FT2232_BUFFER_SIZE)"); - /* unsent commands before this */ - if (first_unsent != cmd) - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - - /* current command */ - ft2232_end_state(cmd->cmd.scan->end_state); - ft2232_large_scan(cmd->cmd.scan, type, buffer, scan_size); - require_send = 0; - first_unsent = cmd->next; - if (buffer) - free(buffer); - return retval; - } else if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) { - LOG_DEBUG( - "ft2232 buffer size reached, sending queued commands (first_unsent: %p, cmd: %p)", - first_unsent, - cmd); - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - require_send = 0; - first_unsent = cmd; - } - ft2232_expect_read += ft2232_predict_scan_in(scan_size, type); - /* LOG_DEBUG("new read size: %i", ft2232_expect_read); */ - ft2232_end_state(cmd->cmd.scan->end_state); - ft2232_add_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size); - require_send = 1; - if (buffer) - free(buffer); - DEBUG_JTAG_IO("%s scan, %i bits, end in %s", - (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size, - tap_state_name(tap_get_end_state())); - return retval; - -} - -static int ft2232_execute_reset(struct jtag_command *cmd) -{ - int retval; - int predicted_size = 0; - retval = ERROR_OK; - - DEBUG_JTAG_IO("reset trst: %i srst %i", - cmd->cmd.reset->trst, cmd->cmd.reset->srst); - - /* only send the maximum buffer size that FT2232C can handle */ - predicted_size = 3; - if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) { - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - require_send = 0; - first_unsent = cmd; - } - - if ((cmd->cmd.reset->trst == 1) || - (cmd->cmd.reset->srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST))) - tap_set_state(TAP_RESET); - - layout->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); - require_send = 1; - - DEBUG_JTAG_IO("trst: %i, srst: %i", - cmd->cmd.reset->trst, cmd->cmd.reset->srst); - return retval; -} - -static int ft2232_execute_sleep(struct jtag_command *cmd) -{ - int retval; - retval = ERROR_OK; - - DEBUG_JTAG_IO("sleep %" PRIi32, cmd->cmd.sleep->us); - - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - first_unsent = cmd->next; - jtag_sleep(cmd->cmd.sleep->us); - DEBUG_JTAG_IO("sleep %" PRIi32 " usec while in %s", - cmd->cmd.sleep->us, - tap_state_name(tap_get_state())); - return retval; -} - -static int ft2232_execute_stableclocks(struct jtag_command *cmd) -{ - int retval; - retval = ERROR_OK; - - /* this is only allowed while in a stable state. A check for a stable - * state was done in jtag_add_clocks() - */ - if (ft2232_stableclocks(cmd->cmd.stableclocks->num_cycles, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - DEBUG_JTAG_IO("clocks %i while in %s", - cmd->cmd.stableclocks->num_cycles, - tap_state_name(tap_get_state())); - return retval; -} - -static int ft2232_execute_command(struct jtag_command *cmd) -{ - int retval; - - switch (cmd->type) { - case JTAG_RESET: - retval = ft2232_execute_reset(cmd); - break; - case JTAG_RUNTEST: - retval = ft2232_execute_runtest(cmd); - break; - case JTAG_TLR_RESET: - retval = ft2232_execute_statemove(cmd); - break; - case JTAG_PATHMOVE: - retval = ft2232_execute_pathmove(cmd); - break; - case JTAG_SCAN: - retval = ft2232_execute_scan(cmd); - break; - case JTAG_SLEEP: - retval = ft2232_execute_sleep(cmd); - break; - case JTAG_STABLECLOCKS: - retval = ft2232_execute_stableclocks(cmd); - break; - case JTAG_TMS: - retval = ft2232_execute_tms(cmd); - break; - default: - LOG_ERROR("BUG: unknown JTAG command type encountered"); - retval = ERROR_JTAG_QUEUE_FAILED; - break; - } - return retval; -} - -static int ft2232_execute_queue(void) -{ - struct jtag_command *cmd = jtag_command_queue; /* currently processed command */ - int retval; - - first_unsent = cmd; /* next command that has to be sent */ - require_send = 0; - - /* return ERROR_OK, unless ft2232_send_and_recv reports a failed check - * that wasn't handled by a caller-provided error handler - */ - retval = ERROR_OK; - - ft2232_buffer_size = 0; - ft2232_expect_read = 0; - - /* blink, if the current layout has that feature */ - if (layout->blink) - layout->blink(); - - while (cmd) { - /* fill the write buffer with the desired command */ - if (ft2232_execute_command(cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - /* Start reading input before FT2232 TX buffer fills up. - * Sometimes this happens because we don't know the - * length of the last command before we execute it. So - * we simple inform the user. - */ - cmd = cmd->next; - - if (ft2232_expect_read >= FT2232_BUFFER_READ_QUEUE_SIZE) { - if (ft2232_expect_read > (FT2232_BUFFER_READ_QUEUE_SIZE+1)) - LOG_DEBUG("read buffer size looks too high %d/%d", - ft2232_expect_read, - (FT2232_BUFFER_READ_QUEUE_SIZE+1)); - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - first_unsent = cmd; - } - } - - if (require_send > 0) - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - - return retval; -} - -#if BUILD_FT2232_FTD2XX == 1 -static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int *try_more) -{ - FT_STATUS status; - DWORD deviceID; - char SerialNumber[16]; - char Description[64]; - DWORD openex_flags = 0; - char *openex_string = NULL; - uint8_t latency_timer; - - if (layout == NULL) { - LOG_WARNING("No ft2232 layout specified'"); - return ERROR_JTAG_INIT_FAILED; - } - - LOG_DEBUG("'ft2232' interface using FTD2XX with '%s' layout (%4.4x:%4.4x)", - layout->name, vid, pid); - -#if IS_WIN32 == 0 - /* Add non-standard Vid/Pid to the linux driver */ - status = FT_SetVIDPID(vid, pid); - if (status != FT_OK) - LOG_WARNING("couldn't add %4.4x:%4.4x", vid, pid); - -#endif - - if (ft2232_device_desc && ft2232_serial) { - LOG_WARNING( - "can't open by device description and serial number, giving precedence to serial"); - ft2232_device_desc = NULL; - } - - if (ft2232_device_desc) { - openex_string = ft2232_device_desc; - openex_flags = FT_OPEN_BY_DESCRIPTION; - } else if (ft2232_serial) { - openex_string = ft2232_serial; - openex_flags = FT_OPEN_BY_SERIAL_NUMBER; - } else { - LOG_ERROR("neither device description nor serial number specified"); - LOG_ERROR( - "please add \"ft2232_device_desc <string>\" or \"ft2232_serial <string>\" to your .cfg file"); - - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_OpenEx(openex_string, openex_flags, &ftdih); - if (status != FT_OK) { - /* under Win32, the FTD2XX driver appends an "A" to the end - * of the description, if we tried by the desc, then - * try by the alternate "A" description. */ - if (openex_string == ft2232_device_desc) { - /* Try the alternate method. */ - openex_string = ft2232_device_desc_A; - status = FT_OpenEx(openex_string, openex_flags, &ftdih); - if (status == FT_OK) { - /* yea, the "alternate" method worked! */ - } else { - /* drat, give the user a meaningfull message. - * telling the use we tried *BOTH* methods. */ - LOG_WARNING("Unable to open FTDI Device tried: '%s' and '%s'", - ft2232_device_desc, - ft2232_device_desc_A); - } - } - } - - if (status != FT_OK) { - DWORD num_devices; - - if (more) { - LOG_WARNING("unable to open ftdi device (trying more): %s", - ftd2xx_status_string(status)); - *try_more = 1; - return ERROR_JTAG_INIT_FAILED; - } - LOG_ERROR("unable to open ftdi device: %s", - ftd2xx_status_string(status)); - status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY); - if (status == FT_OK) { - char **desc_array = malloc(sizeof(char *) * (num_devices + 1)); - uint32_t i; - - for (i = 0; i < num_devices; i++) - desc_array[i] = malloc(64); - - desc_array[num_devices] = NULL; - - status = FT_ListDevices(desc_array, &num_devices, FT_LIST_ALL | openex_flags); - - if (status == FT_OK) { - LOG_ERROR("ListDevices: %" PRIu32, (uint32_t)num_devices); - for (i = 0; i < num_devices; i++) - LOG_ERROR("%" PRIu32 ": \"%s\"", i, desc_array[i]); - } - - for (i = 0; i < num_devices; i++) - free(desc_array[i]); - - free(desc_array); - } else - LOG_ERROR("ListDevices: NONE"); - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_SetLatencyTimer(ftdih, ft2232_latency); - if (status != FT_OK) { - LOG_ERROR("unable to set latency timer: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_GetLatencyTimer(ftdih, &latency_timer); - if (status != FT_OK) { - /* ftd2xx 1.04 (linux) has a bug when calling FT_GetLatencyTimer - * so ignore errors if using this driver version */ - DWORD dw_version; - - status = FT_GetDriverVersion(ftdih, &dw_version); - LOG_ERROR("unable to get latency timer: %s", - ftd2xx_status_string(status)); - - if ((status == FT_OK) && (dw_version == 0x10004)) { - LOG_ERROR("ftd2xx 1.04 detected - this has known issues " \ - "with FT_GetLatencyTimer, upgrade to a newer version"); - } else - return ERROR_JTAG_INIT_FAILED; - } else - LOG_DEBUG("current latency timer: %i", latency_timer); - - status = FT_SetTimeouts(ftdih, 5000, 5000); - if (status != FT_OK) { - LOG_ERROR("unable to set timeouts: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_SetBitMode(ftdih, 0x0b, 2); - if (status != FT_OK) { - LOG_ERROR("unable to enable bit i/o mode: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_GetDeviceInfo(ftdih, &ftdi_device, &deviceID, - SerialNumber, Description, NULL); - if (status != FT_OK) { - LOG_ERROR("unable to get FT_GetDeviceInfo: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_INIT_FAILED; - } else { - static const char *type_str[] = { - "BM", "AM", "100AX", "UNKNOWN", "2232C", "232R", "2232H", "4232H", "232H" - }; - unsigned no_of_known_types = ARRAY_SIZE(type_str) - 1; - unsigned type_index = ((unsigned)ftdi_device <= no_of_known_types) - ? ftdi_device : FT_DEVICE_UNKNOWN; - LOG_INFO("device: %" PRIu32 " \"%s\"", (uint32_t)ftdi_device, type_str[type_index]); - LOG_INFO("deviceID: %" PRIu32, (uint32_t)deviceID); - LOG_INFO("SerialNumber: %s", SerialNumber); - LOG_INFO("Description: %s", Description); - } - - return ERROR_OK; -} - -static int ft2232_purge_ftd2xx(void) -{ - FT_STATUS status; - - status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX); - if (status != FT_OK) { - LOG_ERROR("error purging ftd2xx device: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -#endif /* BUILD_FT2232_FTD2XX == 1 */ - -#if BUILD_FT2232_LIBFTDI == 1 -static int ft2232_init_libftdi(uint16_t vid, uint16_t pid, int more, int *try_more, int channel) -{ - uint8_t latency_timer; - - if (layout == NULL) { - LOG_WARNING("No ft2232 layout specified'"); - return ERROR_JTAG_INIT_FAILED; - } - - LOG_DEBUG("'ft2232' interface using libftdi with '%s' layout (%4.4x:%4.4x)", - layout->name, vid, pid); - - if (ftdi_init(&ftdic) < 0) - return ERROR_JTAG_INIT_FAILED; - - /* default to INTERFACE_A */ - if (channel == INTERFACE_ANY) - channel = INTERFACE_A; - if (ftdi_set_interface(&ftdic, channel) < 0) { - LOG_ERROR("unable to select FT2232 channel A: %s", ftdic.error_str); - return ERROR_JTAG_INIT_FAILED; - } - - /* context, vendor id, product id */ - if (ftdi_usb_open_desc(&ftdic, vid, pid, ft2232_device_desc, ft2232_serial) < 0) { - if (more) - LOG_WARNING("unable to open ftdi device (trying more): %s", - ftdic.error_str); - else - LOG_ERROR("unable to open ftdi device: %s", ftdic.error_str); - *try_more = 1; - return ERROR_JTAG_INIT_FAILED; - } - - /* There is already a reset in ftdi_usb_open_desc, this should be redundant */ - if (ftdi_usb_reset(&ftdic) < 0) { - LOG_ERROR("unable to reset ftdi device"); - return ERROR_JTAG_INIT_FAILED; - } - - if (ftdi_set_latency_timer(&ftdic, ft2232_latency) < 0) { - LOG_ERROR("unable to set latency timer"); - return ERROR_JTAG_INIT_FAILED; - } - - if (ftdi_get_latency_timer(&ftdic, &latency_timer) < 0) { - LOG_ERROR("unable to get latency timer"); - return ERROR_JTAG_INIT_FAILED; - } else - LOG_DEBUG("current latency timer: %i", latency_timer); - - ftdi_set_bitmode(&ftdic, 0x0b, 2); /* ctx, JTAG I/O mask */ - - ftdi_device = ftdic.type; - static const char *type_str[] = { - "AM", "BM", "2232C", "R", "2232H", "4232H", "232H", "Unknown" - }; - unsigned no_of_known_types = ARRAY_SIZE(type_str) - 1; - unsigned type_index = ((unsigned)ftdi_device < no_of_known_types) - ? ftdi_device : no_of_known_types; - LOG_DEBUG("FTDI chip type: %i \"%s\"", (int)ftdi_device, type_str[type_index]); - return ERROR_OK; -} - -static int ft2232_purge_libftdi(void) -{ - if (ftdi_usb_purge_buffers(&ftdic) < 0) { - LOG_ERROR("ftdi_purge_buffers: %s", ftdic.error_str); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -#endif /* BUILD_FT2232_LIBFTDI == 1 */ - -static int ft2232_set_data_bits_low_byte(uint8_t value, uint8_t direction) -{ - uint8_t buf[3]; - uint32_t bytes_written; - - buf[0] = 0x80; /* command "set data bits low byte" */ - buf[1] = value; /* value */ - buf[2] = direction; /* direction */ - - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { - LOG_ERROR("couldn't initialize data bits low byte"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int ft2232_set_data_bits_high_byte(uint8_t value, uint8_t direction) -{ - uint8_t buf[3]; - uint32_t bytes_written; - - buf[0] = 0x82; /* command "set data bits high byte" */ - buf[1] = value; /* value */ - buf[2] = direction; /* direction */ - - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { - LOG_ERROR("couldn't initialize data bits high byte"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int ft2232_init(void) -{ - uint8_t buf[1]; - int retval; - uint32_t bytes_written; - - LOG_WARNING("Using DEPRECATED interface driver 'ft2232'"); -#if BUILD_FTDI - LOG_INFO("Consider using the 'ftdi' interface driver, with configuration files in interface/ftdi/..."); -#endif - - if (tap_get_tms_path_len(TAP_IRPAUSE, TAP_IRPAUSE) == 7) - LOG_DEBUG("ft2232 interface using 7 step jtag state transitions"); - else - LOG_DEBUG("ft2232 interface using shortest path jtag state transitions"); - if (layout == NULL) { - LOG_WARNING("No ft2232 layout specified'"); - return ERROR_JTAG_INIT_FAILED; - } - - for (int i = 0; 1; i++) { - /* - * "more indicates that there are more IDs to try, so we should - * not print an error for an ID mismatch (but for anything - * else, we should). - * - * try_more indicates that the error code returned indicates an - * ID mismatch (and nothing else) and that we should proceeed - * with the next ID pair. - */ - int more = ft2232_vid[i + 1] || ft2232_pid[i + 1]; - int try_more = 0; - -#if BUILD_FT2232_FTD2XX == 1 - retval = ft2232_init_ftd2xx(ft2232_vid[i], ft2232_pid[i], - more, &try_more); -#elif BUILD_FT2232_LIBFTDI == 1 - retval = ft2232_init_libftdi(ft2232_vid[i], ft2232_pid[i], - more, &try_more, ft2232_channel); -#endif - if (retval >= 0) - break; - if (!more || !try_more) - return retval; - } - - ft2232_buffer_size = 0; - ft2232_buffer = malloc(FT2232_BUFFER_SIZE); - - if (layout->init() != ERROR_OK) - return ERROR_JTAG_INIT_FAILED; - - if (ft2232_device_is_highspeed()) { -#ifndef BUILD_FT2232_HIGHSPEED - #if BUILD_FT2232_FTD2XX == 1 - LOG_WARNING( - "High Speed device found - You need a newer FTD2XX driver (version 2.04.16 or later)"); - #elif BUILD_FT2232_LIBFTDI == 1 - LOG_WARNING( - "High Speed device found - You need a newer libftdi version (0.16 or later)"); - #endif -#endif - /* make sure the legacy mode is disabled */ - if (ftx232h_clk_divide_by_5(false) != ERROR_OK) - return ERROR_JTAG_INIT_FAILED; - } - - buf[0] = 0x85; /* Disconnect TDI/DO to TDO/DI for Loopback */ - retval = ft2232_write(buf, 1, &bytes_written); - if (retval != ERROR_OK) { - LOG_ERROR("couldn't write to FT2232 to disable loopback"); - return ERROR_JTAG_INIT_FAILED; - } - -#if BUILD_FT2232_FTD2XX == 1 - return ft2232_purge_ftd2xx(); -#elif BUILD_FT2232_LIBFTDI == 1 - return ft2232_purge_libftdi(); -#endif - - return ERROR_OK; -} - -/** Updates defaults for DBUS signals: the four JTAG signals - * (TCK, TDI, TDO, TMS) and * the four GPIOL signals. - */ -static inline void ftx232_dbus_init(void) -{ - low_output = 0x08; - low_direction = 0x0b; -} - -/** Initializes DBUS signals: the four JTAG signals (TCK, TDI, TDO, TMS), - * the four GPIOL signals. Initialization covers value and direction, - * as customized for each layout. - */ -static int ftx232_dbus_write(void) -{ - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { - low_direction &= ~nTRSTnOE; /* nTRST input */ - low_output &= ~nTRST; /* nTRST = 0 */ - } else { - low_direction |= nTRSTnOE; /* nTRST output */ - low_output |= nTRST; /* nTRST = 1 */ - } - - if (jtag_reset_config & RESET_SRST_PUSH_PULL) { - low_direction |= nSRSTnOE; /* nSRST output */ - low_output |= nSRST; /* nSRST = 1 */ - } else { - low_direction &= ~nSRSTnOE; /* nSRST input */ - low_output &= ~nSRST; /* nSRST = 0 */ - } - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 DBUS"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int usbjtag_init(void) -{ - /* - * NOTE: This is now _specific_ to the "usbjtag" layout. - * Don't try cram any more layouts into this. - */ - ftx232_dbus_init(); - - nTRST = 0x10; - nTRSTnOE = 0x10; - nSRST = 0x40; - nSRSTnOE = 0x40; - - return ftx232_dbus_write(); -} - -static int lm3s811_jtag_init(void) -{ - ftx232_dbus_init(); - - /* There are multiple revisions of LM3S811 eval boards: - * - Rev B (and older?) boards have no SWO trace support. - * - Rev C boards add ADBUS_6 DBG_ENn and BDBUS_4 SWO_EN; - * they should use the "luminary_icdi" layout instead. - */ - nTRST = 0x0; - nTRSTnOE = 0x00; - nSRST = 0x20; - nSRSTnOE = 0x20; - low_output = 0x88; - low_direction = 0x8b; - - return ftx232_dbus_write(); -} - -static int icdi_jtag_init(void) -{ - ftx232_dbus_init(); - - /* Most Luminary eval boards support SWO trace output, - * and should use this "luminary_icdi" layout. - * - * ADBUS 0..3 are used for JTAG as usual. GPIOs are used - * to switch between JTAG and SWD, or switch the ft2232 UART - * on the second MPSSE channel/interface (BDBUS) - * between (i) the stellaris UART (on Luminary boards) - * or (ii) SWO trace data (generic). - * - * We come up in JTAG mode and may switch to SWD later (with - * SWO/trace option if SWD is active). - * - * DBUS == GPIO-Lx - * CBUS == GPIO-Hx - */ - - -#define ICDI_JTAG_EN (1 << 7) /* ADBUS 7 (a.k.a. DBGMOD) */ -#define ICDI_DBG_ENn (1 << 6) /* ADBUS 6 */ -#define ICDI_SRST (1 << 5) /* ADBUS 5 */ - - - /* GPIOs on second channel/interface (UART) ... */ -#define ICDI_SWO_EN (1 << 4) /* BDBUS 4 */ -#define ICDI_TX_SWO (1 << 1) /* BDBUS 1 */ -#define ICDI_VCP_RX (1 << 0) /* BDBUS 0 (to stellaris UART) */ - - nTRST = 0x0; - nTRSTnOE = 0x00; - nSRST = ICDI_SRST; - nSRSTnOE = ICDI_SRST; - - low_direction |= ICDI_JTAG_EN | ICDI_DBG_ENn; - low_output |= ICDI_JTAG_EN; - low_output &= ~ICDI_DBG_ENn; - - return ftx232_dbus_write(); -} - -static int signalyzer_init(void) -{ - ftx232_dbus_init(); - - nTRST = 0x10; - nTRSTnOE = 0x10; - nSRST = 0x20; - nSRSTnOE = 0x20; - return ftx232_dbus_write(); -} - -static int axm0432_jtag_init(void) -{ - low_output = 0x08; - low_direction = 0x2b; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - if (strcmp(layout->name, "axm0432_jtag") == 0) { - nTRST = 0x08; - nTRSTnOE = 0x0; /* No output enable for TRST*/ - nSRST = 0x04; - nSRSTnOE = 0x0; /* No output enable for SRST*/ - } else { - LOG_ERROR("BUG: axm0432_jtag_init called for non axm0432 layout"); - exit(-1); - } - - high_output = 0x0; - high_direction = 0x0c; - - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - LOG_ERROR("can't set nTRSTOE to push-pull on the Dicarlo jtag"); - else - high_output |= nTRST; - - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - LOG_ERROR("can't set nSRST to push-pull on the Dicarlo jtag"); - else - high_output |= nSRST; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'Dicarlo' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int redbee_init(void) -{ - low_output = 0x08; - low_direction = 0x2b; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'redbee' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nTRST = 0x08; - nTRSTnOE = 0x0; /* No output enable for TRST*/ - nSRST = 0x04; - nSRSTnOE = 0x0; /* No output enable for SRST*/ - - high_output = 0x0; - high_direction = 0x0c; - - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - LOG_ERROR("can't set nTRSTOE to push-pull on redbee"); - else - high_output |= nTRST; - - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - LOG_ERROR("can't set nSRST to push-pull on redbee"); - else - high_output |= nSRST; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'redbee' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int jtagkey_init(void) -{ - low_output = 0x08; - low_direction = 0x1b; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - if (strcmp(layout->name, "jtagkey") == 0) { - nTRST = 0x01; - nTRSTnOE = 0x4; - nSRST = 0x02; - nSRSTnOE = 0x08; - } else if ((strcmp(layout->name, "jtagkey_prototype_v1") == 0) - || (strcmp(layout->name, "oocdlink") == 0)) { - nTRST = 0x02; - nTRSTnOE = 0x1; - nSRST = 0x08; - nSRSTnOE = 0x04; - } else { - LOG_ERROR("BUG: jtagkey_init called for non jtagkey layout"); - exit(-1); - } - - high_output = 0x0; - high_direction = 0x0f; - - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { - high_output |= nTRSTnOE; - high_output &= ~nTRST; - } else { - high_output &= ~nTRSTnOE; - high_output |= nTRST; - } - - if (jtag_reset_config & RESET_SRST_PUSH_PULL) { - high_output &= ~nSRSTnOE; - high_output |= nSRST; - } else { - high_output |= nSRSTnOE; - high_output &= ~nSRST; - } - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int olimex_jtag_init(void) -{ - low_output = 0x08; - low_direction = 0x1b; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'Olimex' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nTRST = 0x01; - nTRSTnOE = 0x4; - nSRST = 0x02; - nSRSTnOE = 0x00;/* no output enable for nSRST */ - - high_output = 0x0; - high_direction = 0x0f; - - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { - high_output |= nTRSTnOE; - high_output &= ~nTRST; - } else { - high_output &= ~nTRSTnOE; - high_output |= nTRST; - } - - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - LOG_ERROR("can't set nSRST to push-pull on the Olimex ARM-USB-OCD"); - else - high_output &= ~nSRST; - - /* turn red LED on */ - high_output |= 0x08; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'Olimex' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int flyswatter_init(int rev) -{ - low_output = 0x18; - low_direction = 0x7b; - - if ((rev < 0) || (rev > 3)) { - LOG_ERROR("bogus 'flyswatter' revision supplied (%i)", rev); - return ERROR_JTAG_INIT_FAILED; - } - - if (rev == 1) - low_direction |= 1 << 7; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nTRST = 0x10; - nTRSTnOE = 0x0; /* not output enable for nTRST */ - nSRST = 0x20; - nSRSTnOE = 0x00; /* no output enable for nSRST */ - - high_output = 0x00; - - if (rev == 1) - high_direction = 0x0c; - else - high_direction = 0x01; - - /* turn red LED3 on, LED2 off */ - high_output |= 0x08; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int flyswatter1_init(void) -{ - return flyswatter_init(1); -} - -static int flyswatter2_init(void) -{ - return flyswatter_init(2); -} - -static int minimodule_init(void) -{ - low_output = 0x18; /* check if srst should be 1 or 0 initially. (0x08) (flyswatter was - * 0x18) */ - low_direction = 0xfb; /* 0xfb; */ - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'minimodule' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - - nSRST = 0x20; - - high_output = 0x00; - high_direction = 0x05; - - /* turn red LED3 on, LED2 off */ - /* high_output |= 0x08; */ - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'minimodule' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int turtle_init(void) -{ - low_output = 0x08; - low_direction = 0x5b; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nSRST = 0x40; - - high_output = 0x00; - high_direction = 0x0C; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int comstick_init(void) -{ - low_output = 0x08; - low_direction = 0x0b; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'comstick' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nTRST = 0x01; - nTRSTnOE = 0x00; /* no output enable for nTRST */ - nSRST = 0x02; - nSRSTnOE = 0x00; /* no output enable for nSRST */ - - high_output = 0x03; - high_direction = 0x03; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'comstick' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int stm32stick_init(void) -{ - low_output = 0x88; - low_direction = 0x8b; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nTRST = 0x01; - nTRSTnOE = 0x00; /* no output enable for nTRST */ - nSRST = 0x80; - nSRSTnOE = 0x00; /* no output enable for nSRST */ - - high_output = 0x01; - high_direction = 0x03; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int sheevaplug_init(void) -{ - low_output = 0x08; - low_direction = 0x1b; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'sheevaplug' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nTRSTnOE = 0x1; - nTRST = 0x02; - nSRSTnOE = 0x4; - nSRST = 0x08; - - high_output = 0x0; - high_direction = 0x0f; - - /* nTRST is always push-pull */ - high_output &= ~nTRSTnOE; - high_output |= nTRST; - - /* nSRST is always open-drain */ - high_output |= nSRSTnOE; - high_output &= ~nSRST; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'sheevaplug' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int cortino_jtag_init(void) -{ - low_output = 0x08; - low_direction = 0x1b; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'cortino' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nTRST = 0x01; - nTRSTnOE = 0x00; /* no output enable for nTRST */ - nSRST = 0x02; - nSRSTnOE = 0x00; /* no output enable for nSRST */ - - high_output = 0x03; - high_direction = 0x03; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'cortino' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int lisa_l_init(void) -{ - ftx232_dbus_init(); - - nTRST = 0x10; - nTRSTnOE = 0x10; - nSRST = 0x40; - nSRSTnOE = 0x40; - - high_output = 0x00; - high_direction = 0x18; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'lisa_l' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ftx232_dbus_write(); -} - -static int flossjtag_init(void) -{ - ftx232_dbus_init(); - - nTRST = 0x10; - nTRSTnOE = 0x10; - nSRST = 0x40; - nSRSTnOE = 0x40; - - high_output = 0x00; - high_direction = 0x18; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'Floss-JTAG' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ftx232_dbus_write(); -} - -/* - * The reference schematic from TI for the XDS100v2 has a CPLD on which opens - * the door for a number of different configurations - * - * Known Implementations: - * http://processors.wiki.ti.com/images/9/93/TMS570LS20216_USB_STICK_Schematic.pdf - * - * http://processors.wiki.ti.com/index.php/XDS100 (rev2) - * * CLPD logic: Rising edge to enable outputs (XDS100_PWR_RST) - * * ACBUS3 to transition 0->1 (OE rising edge) - * * CPLD logic: Put the EMU0/1 pins in Hi-Z: - * * ADBUS5/GPIOL1 = EMU_EN = 1 - * * ADBUS6/GPIOL2 = EMU0 = 0 - * * ACBUS4/SPARE0 = EMU1 = 0 - * * CPLD logic: Disable loopback - * * ACBUS6/SPARE2 = LOOPBACK = 0 - */ -#define XDS100_nEMU_EN (1<<5) -#define XDS100_nEMU0 (1<<6) - -#define XDS100_PWR_RST (1<<3) -#define XDS100_nEMU1 (1<<4) -#define XDS100_LOOPBACK (1<<6) -static int xds100v2_init(void) -{ - /* These are in the lower byte */ - nTRST = 0x10; - nTRSTnOE = 0x10; - - /* These aren't actually used on 14 pin connectors - * These are in the upper byte */ - nSRST = 0x01; - nSRSTnOE = 0x01; - - low_output = 0x08 | nTRST | XDS100_nEMU_EN; - low_direction = 0x0b | nTRSTnOE | XDS100_nEMU_EN | XDS100_nEMU0; - - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'xds100v2' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - high_output = 0; - high_direction = nSRSTnOE | XDS100_LOOPBACK | XDS100_PWR_RST | XDS100_nEMU1; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't put CPLD in to reset with 'xds100v2' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - high_output |= XDS100_PWR_RST; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't bring CPLD out of reset with 'xds100v2' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static void olimex_jtag_blink(void) -{ - /* Olimex ARM-USB-OCD has a LED connected to ACBUS3 - * ACBUS3 is bit 3 of the GPIOH port - */ - high_output ^= 0x08; - - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); -} - -static void flyswatter_jtag_blink(unsigned char led) -{ - buffer_write(0x82); - buffer_write(high_output ^ led); - buffer_write(high_direction); -} - -static void flyswatter1_jtag_blink(void) -{ - /* - * Flyswatter has two LEDs connected to ACBUS2 and ACBUS3 - */ - flyswatter_jtag_blink(0xc); -} - -static void flyswatter2_jtag_blink(void) -{ - /* - * Flyswatter2 only has one LED connected to ACBUS2 - */ - flyswatter_jtag_blink(0x4); -} - -static void turtle_jtag_blink(void) -{ - /* - * Turtelizer2 has two LEDs connected to ACBUS2 and ACBUS3 - */ - if (high_output & 0x08) - high_output = 0x04; - else - high_output = 0x08; - - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); -} - -static void lisa_l_blink(void) -{ - /* - * Lisa/L has two LEDs connected to BCBUS3 and BCBUS4 - */ - if (high_output & 0x10) - high_output = 0x08; - else - high_output = 0x10; - - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); -} - -static void flossjtag_blink(void) -{ - /* - * Floss-JTAG has two LEDs connected to ACBUS3 and ACBUS4 - */ - if (high_output & 0x10) - high_output = 0x08; - else - high_output = 0x10; - - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); -} - -static int ft2232_quit(void) -{ -#if BUILD_FT2232_FTD2XX == 1 - - FT_Close(ftdih); -#elif BUILD_FT2232_LIBFTDI == 1 - ftdi_usb_close(&ftdic); - - ftdi_deinit(&ftdic); -#endif - - free(ft2232_buffer); - ft2232_buffer = NULL; - - return ERROR_OK; -} - -COMMAND_HANDLER(ft2232_handle_device_desc_command) -{ - char *cp; - char buf[200]; - if (CMD_ARGC == 1) { - ft2232_device_desc = strdup(CMD_ARGV[0]); - cp = strchr(ft2232_device_desc, 0); - /* under Win32, the FTD2XX driver appends an "A" to the end - * of the description, this examines the given desc - * and creates the 'missing' _A or non_A variable. */ - if ((cp[-1] == 'A') && (cp[-2] == ' ')) { - /* it was, so make this the "A" version. */ - ft2232_device_desc_A = ft2232_device_desc; - /* and *CREATE* the non-A version. */ - strcpy(buf, ft2232_device_desc); - cp = strchr(buf, 0); - cp[-2] = 0; - ft2232_device_desc = strdup(buf); - } else { - /* <space > A not defined - * so create it */ - sprintf(buf, "%s A", ft2232_device_desc); - ft2232_device_desc_A = strdup(buf); - } - } else - LOG_ERROR("expected exactly one argument to ft2232_device_desc <description>"); - - return ERROR_OK; -} - -COMMAND_HANDLER(ft2232_handle_serial_command) -{ - if (CMD_ARGC == 1) - ft2232_serial = strdup(CMD_ARGV[0]); - else - return ERROR_COMMAND_SYNTAX_ERROR; - - return ERROR_OK; -} - -COMMAND_HANDLER(ft2232_handle_layout_command) -{ - if (CMD_ARGC != 1) - return ERROR_COMMAND_SYNTAX_ERROR; - - if (layout) { - LOG_ERROR("already specified ft2232_layout %s", - layout->name); - return (strcmp(layout->name, CMD_ARGV[0]) != 0) - ? ERROR_FAIL - : ERROR_OK; - } - - for (const struct ft2232_layout *l = ft2232_layouts; l->name; l++) { - if (strcmp(l->name, CMD_ARGV[0]) == 0) { - layout = l; - ft2232_channel = l->channel; - return ERROR_OK; - } - } - - LOG_ERROR("No FT2232 layout '%s' found", CMD_ARGV[0]); - return ERROR_FAIL; -} - -COMMAND_HANDLER(ft2232_handle_vid_pid_command) -{ - if (CMD_ARGC > MAX_USB_IDS * 2) { - LOG_WARNING("ignoring extra IDs in ft2232_vid_pid " - "(maximum is %d pairs)", MAX_USB_IDS); - CMD_ARGC = MAX_USB_IDS * 2; - } - if (CMD_ARGC < 2 || (CMD_ARGC & 1)) { - LOG_WARNING("incomplete ft2232_vid_pid configuration directive"); - if (CMD_ARGC < 2) - return ERROR_COMMAND_SYNTAX_ERROR; - /* remove the incomplete trailing id */ - CMD_ARGC -= 1; - } - - unsigned i; - for (i = 0; i < CMD_ARGC; i += 2) { - COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i], ft2232_vid[i >> 1]); - COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], ft2232_pid[i >> 1]); - } - - /* - * Explicitly terminate, in case there are multiples instances of - * ft2232_vid_pid. - */ - ft2232_vid[i >> 1] = ft2232_pid[i >> 1] = 0; - - return ERROR_OK; -} - -COMMAND_HANDLER(ft2232_handle_latency_command) -{ - if (CMD_ARGC == 1) - ft2232_latency = atoi(CMD_ARGV[0]); - else - return ERROR_COMMAND_SYNTAX_ERROR; - - return ERROR_OK; -} - -COMMAND_HANDLER(ft2232_handle_channel_command) -{ - if (CMD_ARGC == 1) { - ft2232_channel = atoi(CMD_ARGV[0]); - if (ft2232_channel < 0 || ft2232_channel > 4) - LOG_ERROR("ft2232_channel must be in the 0 to 4 range"); - } else - LOG_ERROR("expected exactly one argument to ft2232_channel <ch>"); - - return ERROR_OK; -} - -static int ft2232_stableclocks(int num_cycles, struct jtag_command *cmd) -{ - int retval = 0; - - /* 7 bits of either ones or zeros. */ - uint8_t tms = (tap_get_state() == TAP_RESET ? 0x7F : 0x00); - - while (num_cycles > 0) { - /* the command 0x4b, "Clock Data to TMS/CS Pin (no Read)" handles - * at most 7 bits per invocation. Here we invoke it potentially - * several times. - */ - int bitcount_per_command = (num_cycles > 7) ? 7 : num_cycles; - - if (ft2232_buffer_size + 3 >= FT2232_BUFFER_SIZE) { - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - - first_unsent = cmd; - } - - /* there are no state transitions in this code, so omit state tracking */ - - /* command "Clock Data to TMS/CS Pin (no Read)" */ - buffer_write(0x4b); - - /* scan 7 bit */ - buffer_write(bitcount_per_command - 1); - - /* TMS data bits are either all zeros or ones to stay in the current stable state */ - buffer_write(tms); - - require_send = 1; - - num_cycles -= bitcount_per_command; - } - - return retval; -} - -/* --------------------------------------------------------------------- - * Support for IceBear JTAG adapter from Section5: - * http://section5.ch/icebear - * - * Author: Sten, debian@sansys-electronic.com - */ - -/* Icebear pin layout - * - * ADBUS5 (nEMU) nSRST | 2 1| GND (10k->VCC) - * GND GND | 4 3| n.c. - * ADBUS3 TMS | 6 5| ADBUS6 VCC - * ADBUS0 TCK | 8 7| ADBUS7 (GND) - * ADBUS4 nTRST |10 9| ACBUS0 (GND) - * ADBUS1 TDI |12 11| ACBUS1 (GND) - * ADBUS2 TDO |14 13| GND GND - * - * ADBUS0 O L TCK ACBUS0 GND - * ADBUS1 O L TDI ACBUS1 GND - * ADBUS2 I TDO ACBUS2 n.c. - * ADBUS3 O H TMS ACBUS3 n.c. - * ADBUS4 O H nTRST - * ADBUS5 O H nSRST - * ADBUS6 - VCC - * ADBUS7 - GND - */ -static int icebear_jtag_init(void) -{ - low_direction = 0x0b; /* output: TCK TDI TMS; input: TDO */ - low_output = 0x08; /* high: TMS; low: TCK TDI */ - nTRST = 0x10; - nSRST = 0x20; - - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if ((jtag_reset_config & RESET_TRST_OPEN_DRAIN) != 0) - low_direction &= ~nTRST; /* nTRST high impedance */ - else { - low_direction |= nTRST; - low_output |= nTRST; - } - - low_direction |= nSRST; - low_output |= nSRST; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'IceBear' layout (low)"); - return ERROR_JTAG_INIT_FAILED; - } - - high_output = 0x0; - high_direction = 0x00; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'IceBear' layout (high)"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static void icebear_jtag_reset(int trst, int srst) -{ - if (trst == 1) { - low_direction |= nTRST; - low_output &= ~nTRST; - } else if (trst == 0) { - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if ((jtag_reset_config & RESET_TRST_OPEN_DRAIN) != 0) - low_direction &= ~nTRST; - else - low_output |= nTRST; - } - - if (srst == 1) - low_output &= ~nSRST; - else if (srst == 0) - low_output |= nSRST; - - /* command "set data bits low byte" */ - buffer_write(0x80); - buffer_write(low_output); - buffer_write(low_direction); - - LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", - trst, - srst, - low_output, - low_direction); -} - -/* --------------------------------------------------------------------- - * Support for Signalyzer H2 and Signalyzer H4 - * JTAG adapter from Xverve Technologies Inc. - * http://www.signalyzer.com or http://www.xverve.com - * - * Author: Oleg Seiljus, oleg@signalyzer.com - */ -static unsigned char signalyzer_h_side; -static unsigned int signalyzer_h_adapter_type; - -static int signalyzer_h_ctrl_write(int address, unsigned short value); - -#if BUILD_FT2232_FTD2XX == 1 -static int signalyzer_h_ctrl_read(int address, unsigned short *value); -#endif - -#define SIGNALYZER_COMMAND_ADDR 128 -#define SIGNALYZER_DATA_BUFFER_ADDR 129 - -#define SIGNALYZER_COMMAND_VERSION 0x41 -#define SIGNALYZER_COMMAND_RESET 0x42 -#define SIGNALYZER_COMMAND_POWERCONTROL_GET 0x50 -#define SIGNALYZER_COMMAND_POWERCONTROL_SET 0x51 -#define SIGNALYZER_COMMAND_PWM_SET 0x52 -#define SIGNALYZER_COMMAND_LED_SET 0x53 -#define SIGNALYZER_COMMAND_ADC 0x54 -#define SIGNALYZER_COMMAND_GPIO_STATE 0x55 -#define SIGNALYZER_COMMAND_GPIO_MODE 0x56 -#define SIGNALYZER_COMMAND_GPIO_PORT 0x57 -#define SIGNALYZER_COMMAND_I2C 0x58 - -#define SIGNALYZER_CHAN_A 1 -#define SIGNALYZER_CHAN_B 2 -/* LEDS use channel C */ -#define SIGNALYZER_CHAN_C 4 - -#define SIGNALYZER_LED_GREEN 1 -#define SIGNALYZER_LED_RED 2 - -#define SIGNALYZER_MODULE_TYPE_EM_LT16_A 0x0301 -#define SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG 0x0302 -#define SIGNALYZER_MODULE_TYPE_EM_JTAG 0x0303 -#define SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG_P 0x0304 -#define SIGNALYZER_MODULE_TYPE_EM_JTAG_P 0x0305 - - -static int signalyzer_h_ctrl_write(int address, unsigned short value) -{ -#if BUILD_FT2232_FTD2XX == 1 - return FT_WriteEE(ftdih, address, value); -#elif BUILD_FT2232_LIBFTDI == 1 - return 0; -#endif -} - -#if BUILD_FT2232_FTD2XX == 1 -static int signalyzer_h_ctrl_read(int address, unsigned short *value) -{ - return FT_ReadEE(ftdih, address, value); -} -#endif - -static int signalyzer_h_led_set(unsigned char channel, unsigned char led, - int on_time_ms, int off_time_ms, unsigned char cycles) -{ - unsigned char on_time; - unsigned char off_time; - - if (on_time_ms < 0xFFFF) - on_time = (unsigned char)(on_time_ms / 62); - else - on_time = 0xFF; - - off_time = (unsigned char)(off_time_ms / 62); - -#if BUILD_FT2232_FTD2XX == 1 - FT_STATUS status; - - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, - ((uint32_t)(channel << 8) | led)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write((SIGNALYZER_DATA_BUFFER_ADDR + 1), - ((uint32_t)(on_time << 8) | off_time)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write((SIGNALYZER_DATA_BUFFER_ADDR + 2), - ((uint32_t)cycles)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, - SIGNALYZER_COMMAND_LED_SET); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - return ERROR_OK; -#elif BUILD_FT2232_LIBFTDI == 1 - int retval; - - retval = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, - ((uint32_t)(channel << 8) | led)); - if (retval < 0) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftdi_get_error_string(&ftdic)); - return ERROR_JTAG_DEVICE_ERROR; - } - - retval = signalyzer_h_ctrl_write((SIGNALYZER_DATA_BUFFER_ADDR + 1), - ((uint32_t)(on_time << 8) | off_time)); - if (retval < 0) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftdi_get_error_string(&ftdic)); - return ERROR_JTAG_DEVICE_ERROR; - } - - retval = signalyzer_h_ctrl_write((SIGNALYZER_DATA_BUFFER_ADDR + 2), - (uint32_t)cycles); - if (retval < 0) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftdi_get_error_string(&ftdic)); - return ERROR_JTAG_DEVICE_ERROR; - } - - retval = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, - SIGNALYZER_COMMAND_LED_SET); - if (retval < 0) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftdi_get_error_string(&ftdic)); - return ERROR_JTAG_DEVICE_ERROR; - } - - return ERROR_OK; -#endif -} - -static int signalyzer_h_init(void) -{ -#if BUILD_FT2232_FTD2XX == 1 - FT_STATUS status; - int i; -#endif - - char *end_of_desc; - - uint16_t read_buf[12] = { 0 }; - - /* turn on center green led */ - signalyzer_h_led_set(SIGNALYZER_CHAN_C, SIGNALYZER_LED_GREEN, - 0xFFFF, 0x00, 0x00); - - /* determine what channel config wants to open - * TODO: change me... current implementation is made to work - * with openocd description parsing. - */ - end_of_desc = strrchr(ft2232_device_desc, 0x00); - - if (end_of_desc) { - signalyzer_h_side = *(end_of_desc - 1); - if (signalyzer_h_side == 'B') - signalyzer_h_side = SIGNALYZER_CHAN_B; - else - signalyzer_h_side = SIGNALYZER_CHAN_A; - } else { - LOG_ERROR("No Channel was specified"); - return ERROR_FAIL; - } - - signalyzer_h_led_set(signalyzer_h_side, SIGNALYZER_LED_GREEN, - 1000, 1000, 0xFF); - -#if BUILD_FT2232_FTD2XX == 1 - /* read signalyzer versionining information */ - status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, - SIGNALYZER_COMMAND_VERSION); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - for (i = 0; i < 10; i++) { - status = signalyzer_h_ctrl_read((SIGNALYZER_DATA_BUFFER_ADDR + i), - &read_buf[i]); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_read returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - } - - LOG_INFO("Signalyzer: ID info: { %.4x %.4x %.4x %.4x %.4x %.4x %.4x }", - read_buf[0], read_buf[1], read_buf[2], read_buf[3], - read_buf[4], read_buf[5], read_buf[6]); - - /* set gpio register */ - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, - (uint32_t)(signalyzer_h_side << 8)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0404); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, - SIGNALYZER_COMMAND_GPIO_STATE); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - /* read adapter type information */ - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, - ((uint32_t)(signalyzer_h_side << 8) | 0x01)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write( - (SIGNALYZER_DATA_BUFFER_ADDR + 1), 0xA000); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write( - (SIGNALYZER_DATA_BUFFER_ADDR + 2), 0x0008); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, - SIGNALYZER_COMMAND_I2C); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - usleep(100000); - - status = signalyzer_h_ctrl_read(SIGNALYZER_COMMAND_ADDR, &read_buf[0]); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_read returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - if (read_buf[0] != 0x0498) - signalyzer_h_adapter_type = 0x0000; - else { - for (i = 0; i < 4; i++) { - status = signalyzer_h_ctrl_read((SIGNALYZER_DATA_BUFFER_ADDR + i), &read_buf[i]); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_read returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - } - - signalyzer_h_adapter_type = read_buf[0]; - } - -#elif BUILD_FT2232_LIBFTDI == 1 - /* currently libftdi does not allow reading individual eeprom - * locations, therefore adapter type cannot be detected. - * override with most common type - */ - signalyzer_h_adapter_type = SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG; -#endif - - enum reset_types jtag_reset_config = jtag_get_reset_config(); - - /* ADAPTOR: EM_LT16_A */ - if (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_LT16_A) { - LOG_INFO("Signalyzer: EM-LT (16-channel level translator) " - "detected. (HW: %2x).", (read_buf[1] >> 8)); - - nTRST = 0x10; - nTRSTnOE = 0x10; - nSRST = 0x20; - nSRSTnOE = 0x20; - - low_output = 0x08; - low_direction = 0x1b; - - high_output = 0x0; - high_direction = 0x0; - - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { - low_direction &= ~nTRSTnOE; /* nTRST input */ - low_output &= ~nTRST; /* nTRST = 0 */ - } else { - low_direction |= nTRSTnOE; /* nTRST output */ - low_output |= nTRST; /* nTRST = 1 */ - } - - if (jtag_reset_config & RESET_SRST_PUSH_PULL) { - low_direction |= nSRSTnOE; /* nSRST output */ - low_output |= nSRST; /* nSRST = 1 */ - } else { - low_direction &= ~nSRSTnOE; /* nSRST input */ - low_output &= ~nSRST; /* nSRST = 0 */ - } - -#if BUILD_FT2232_FTD2XX == 1 - /* enable power to the module */ - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, - ((uint32_t)(signalyzer_h_side << 8) | 0x01)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, - SIGNALYZER_COMMAND_POWERCONTROL_SET); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - /* set gpio mode register */ - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, - (uint32_t)(signalyzer_h_side << 8)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0000); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_GPIO_MODE); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - /* set gpio register */ - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, - (uint32_t)(signalyzer_h_side << 8)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x4040); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, - SIGNALYZER_COMMAND_GPIO_STATE); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } -#endif - } - /* ADAPTOR: EM_ARM_JTAG, EM_ARM_JTAG_P, EM_JTAG, EM_JTAG_P */ - else if ((signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG) || - (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG_P) || - (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_JTAG) || - (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_JTAG_P)) { - if (signalyzer_h_adapter_type - == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG) - LOG_INFO("Signalyzer: EM-ARM-JTAG (ARM JTAG) " - "detected. (HW: %2x).", (read_buf[1] >> 8)); - else if (signalyzer_h_adapter_type - == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG_P) - LOG_INFO("Signalyzer: EM-ARM-JTAG_P " - "(ARM JTAG with PSU) detected. (HW: %2x).", - (read_buf[1] >> 8)); - else if (signalyzer_h_adapter_type - == SIGNALYZER_MODULE_TYPE_EM_JTAG) - LOG_INFO("Signalyzer: EM-JTAG (Generic JTAG) " - "detected. (HW: %2x).", (read_buf[1] >> 8)); - else if (signalyzer_h_adapter_type - == SIGNALYZER_MODULE_TYPE_EM_JTAG_P) - LOG_INFO("Signalyzer: EM-JTAG-P " - "(Generic JTAG with PSU) detected. (HW: %2x).", - (read_buf[1] >> 8)); - - nTRST = 0x02; - nTRSTnOE = 0x04; - nSRST = 0x08; - nSRSTnOE = 0x10; - - low_output = 0x08; - low_direction = 0x1b; - - high_output = 0x0; - high_direction = 0x1f; - - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { - high_output |= nTRSTnOE; - high_output &= ~nTRST; - } else { - high_output &= ~nTRSTnOE; - high_output |= nTRST; - } - - if (jtag_reset_config & RESET_SRST_PUSH_PULL) { - high_output &= ~nSRSTnOE; - high_output |= nSRST; - } else { - high_output |= nSRSTnOE; - high_output &= ~nSRST; - } - -#if BUILD_FT2232_FTD2XX == 1 - /* enable power to the module */ - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, - ((uint32_t)(signalyzer_h_side << 8) | 0x01)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, - SIGNALYZER_COMMAND_POWERCONTROL_SET); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - /* set gpio mode register (IO_16 and IO_17 set as analog - * inputs, other is gpio) - */ - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, - (uint32_t)(signalyzer_h_side << 8)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0060); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_GPIO_MODE); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - /* set gpio register (all inputs, for -P modules, - * PSU will be turned off) - */ - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, - (uint32_t)(signalyzer_h_side << 8)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0000); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_GPIO_STATE); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } -#endif - } else if (signalyzer_h_adapter_type == 0x0000) { - LOG_INFO("Signalyzer: No external modules were detected."); - - nTRST = 0x10; - nTRSTnOE = 0x10; - nSRST = 0x20; - nSRSTnOE = 0x20; - - low_output = 0x08; - low_direction = 0x1b; - - high_output = 0x0; - high_direction = 0x0; - - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { - low_direction &= ~nTRSTnOE; /* nTRST input */ - low_output &= ~nTRST; /* nTRST = 0 */ - } else { - low_direction |= nTRSTnOE; /* nTRST output */ - low_output |= nTRST; /* nTRST = 1 */ - } - - if (jtag_reset_config & RESET_SRST_PUSH_PULL) { - low_direction |= nSRSTnOE; /* nSRST output */ - low_output |= nSRST; /* nSRST = 1 */ - } else { - low_direction &= ~nSRSTnOE; /* nSRST input */ - low_output &= ~nSRST; /* nSRST = 0 */ - } - } else { - LOG_ERROR("Unknown module type is detected: %.4x", - signalyzer_h_adapter_type); - return ERROR_JTAG_DEVICE_ERROR; - } - - /* initialize low byte of controller for jtag operation */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize Signalyzer-H layout"); - return ERROR_JTAG_INIT_FAILED; - } - -#if BUILD_FT2232_FTD2XX == 1 - if (ftdi_device == FT_DEVICE_2232H) { - /* initialize high byte of controller for jtag operation */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize Signalyzer-H layout"); - return ERROR_JTAG_INIT_FAILED; - } - } -#elif BUILD_FT2232_LIBFTDI == 1 - if (ftdi_device == TYPE_2232H) { - /* initialize high byte of controller for jtag operation */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize Signalyzer-H layout"); - return ERROR_JTAG_INIT_FAILED; - } - } -#endif - return ERROR_OK; -} - -static void signalyzer_h_reset(int trst, int srst) -{ - enum reset_types jtag_reset_config = jtag_get_reset_config(); - - /* ADAPTOR: EM_LT16_A */ - if (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_LT16_A) { - if (trst == 1) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - /* switch to output pin (output is low) */ - low_direction |= nTRSTnOE; - else - /* switch output low */ - low_output &= ~nTRST; - } else if (trst == 0) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - /* switch to input pin (high-Z + internal - * and external pullup) */ - low_direction &= ~nTRSTnOE; - else - /* switch output high */ - low_output |= nTRST; - } - - if (srst == 1) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - /* switch output low */ - low_output &= ~nSRST; - else - /* switch to output pin (output is low) */ - low_direction |= nSRSTnOE; - } else if (srst == 0) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - /* switch output high */ - low_output |= nSRST; - else - /* switch to input pin (high-Z) */ - low_direction &= ~nSRSTnOE; - } - - /* command "set data bits low byte" */ - buffer_write(0x80); - buffer_write(low_output); - buffer_write(low_direction); - LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, " - "low_direction: 0x%2.2x", - trst, srst, low_output, low_direction); - } - /* ADAPTOR: EM_ARM_JTAG, EM_ARM_JTAG_P, EM_JTAG, EM_JTAG_P */ - else if ((signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG) || - (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG_P) || - (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_JTAG) || - (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_JTAG_P)) { - if (trst == 1) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - high_output &= ~nTRSTnOE; - else - high_output &= ~nTRST; - } else if (trst == 0) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - high_output |= nTRSTnOE; - else - high_output |= nTRST; - } - - if (srst == 1) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - high_output &= ~nSRST; - else - high_output &= ~nSRSTnOE; - } else if (srst == 0) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - high_output |= nSRST; - else - high_output |= nSRSTnOE; - } - - /* command "set data bits high byte" */ - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); - LOG_INFO("trst: %i, srst: %i, high_output: 0x%2.2x, " - "high_direction: 0x%2.2x", - trst, srst, high_output, high_direction); - } else if (signalyzer_h_adapter_type == 0x0000) { - if (trst == 1) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - /* switch to output pin (output is low) */ - low_direction |= nTRSTnOE; - else - /* switch output low */ - low_output &= ~nTRST; - } else if (trst == 0) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - /* switch to input pin (high-Z + internal - * and external pullup) */ - low_direction &= ~nTRSTnOE; - else - /* switch output high */ - low_output |= nTRST; - } - - if (srst == 1) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - /* switch output low */ - low_output &= ~nSRST; - else - /* switch to output pin (output is low) */ - low_direction |= nSRSTnOE; - } else if (srst == 0) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - /* switch output high */ - low_output |= nSRST; - else - /* switch to input pin (high-Z) */ - low_direction &= ~nSRSTnOE; - } - - /* command "set data bits low byte" */ - buffer_write(0x80); - buffer_write(low_output); - buffer_write(low_direction); - LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, " - "low_direction: 0x%2.2x", - trst, srst, low_output, low_direction); - } -} - -static void signalyzer_h_blink(void) -{ - signalyzer_h_led_set(signalyzer_h_side, SIGNALYZER_LED_RED, 100, 0, 1); -} - -/******************************************************************** - * Support for KT-LINK - * JTAG adapter from KRISTECH - * http://www.kristech.eu - *******************************************************************/ -static int ktlink_init(void) -{ - uint8_t swd_en = 0x20; /* 0x20 SWD disable, 0x00 SWD enable (ADBUS5) */ - - low_output = 0x08 | swd_en; /* value; TMS=1,TCK=0,TDI=0,SWD=swd_en */ - low_direction = 0x3B; /* out=1; TCK/TDI/TMS=out,TDO=in,SWD=out,RTCK=in,SRSTIN=in */ - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'ktlink' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nTRST = 0x01; - nSRST = 0x02; - nTRSTnOE = 0x04; - nSRSTnOE = 0x08; - - high_output = 0x80; /* turn LED on */ - high_direction = 0xFF; /* all outputs */ - - enum reset_types jtag_reset_config = jtag_get_reset_config(); - - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { - high_output |= nTRSTnOE; - high_output &= ~nTRST; - } else { - high_output &= ~nTRSTnOE; - high_output |= nTRST; - } - - if (jtag_reset_config & RESET_SRST_PUSH_PULL) { - high_output &= ~nSRSTnOE; - high_output |= nSRST; - } else { - high_output |= nSRSTnOE; - high_output &= ~nSRST; - } - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'ktlink' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static void ktlink_reset(int trst, int srst) -{ - enum reset_types jtag_reset_config = jtag_get_reset_config(); - - if (trst == 1) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - high_output &= ~nTRSTnOE; - else - high_output &= ~nTRST; - } else if (trst == 0) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - high_output |= nTRSTnOE; - else - high_output |= nTRST; - } - - if (srst == 1) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - high_output &= ~nSRST; - else - high_output &= ~nSRSTnOE; - } else if (srst == 0) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - high_output |= nSRST; - else - high_output |= nSRSTnOE; - } - - buffer_write(0x82); /* command "set data bits high byte" */ - buffer_write(high_output); - buffer_write(high_direction); - LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", - trst, - srst, - high_output, - high_direction); -} - -static void ktlink_blink(void) -{ - /* LED connected to ACBUS7 */ - high_output ^= 0x80; - - buffer_write(0x82); /* command "set data bits high byte" */ - buffer_write(high_output); - buffer_write(high_direction); -} - -/******************************************************************** - * Support for Digilent HS-1 - * JTAG adapter from Digilent - * http://www.digilent.com - * Author: Stephane Bonnet bonnetst@hds.utc.fr - *******************************************************************/ - -static int digilent_hs1_init(void) -{ - /* the adapter only supports the base JTAG signals, no nTRST - nor nSRST */ - low_output = 0x88; - low_direction = 0x8b; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'digilent_hs1' layout"); - return ERROR_JTAG_INIT_FAILED; - } - return ERROR_OK; -} - -static void digilent_hs1_reset(int trst, int srst) -{ - /* Dummy function, no reset signals supported. */ -} - -static const struct command_registration ft2232_command_handlers[] = { - { - .name = "ft2232_device_desc", - .handler = &ft2232_handle_device_desc_command, - .mode = COMMAND_CONFIG, - .help = "set the USB device description of the FTDI FT2232 device", - .usage = "description_string", - }, - { - .name = "ft2232_serial", - .handler = &ft2232_handle_serial_command, - .mode = COMMAND_CONFIG, - .help = "set the serial number of the FTDI FT2232 device", - .usage = "serial_string", - }, - { - .name = "ft2232_layout", - .handler = &ft2232_handle_layout_command, - .mode = COMMAND_CONFIG, - .help = "set the layout of the FT2232 GPIO signals used " - "to control output-enables and reset signals", - .usage = "layout_name", - }, - { - .name = "ft2232_vid_pid", - .handler = &ft2232_handle_vid_pid_command, - .mode = COMMAND_CONFIG, - .help = "the vendor ID and product ID of the FTDI FT2232 device", - .usage = "(vid pid)* ", - }, - { - .name = "ft2232_latency", - .handler = &ft2232_handle_latency_command, - .mode = COMMAND_CONFIG, - .help = "set the FT2232 latency timer to a new value", - .usage = "value", - }, - { - .name = "ft2232_channel", - .handler = &ft2232_handle_channel_command, - .mode = COMMAND_CONFIG, - .help = "set the FT2232 channel to a new value", - .usage = "value", - }, - COMMAND_REGISTRATION_DONE -}; - -struct jtag_interface ft2232_interface = { - .name = "ft2232", - .supported = DEBUG_CAP_TMS_SEQ, - .commands = ft2232_command_handlers, - .transports = jtag_only, - - .init = ft2232_init, - .quit = ft2232_quit, - .speed = ft2232_speed, - .speed_div = ft2232_speed_div, - .khz = ft2232_khz, - .execute_queue = ft2232_execute_queue, -}; diff --git a/src/jtag/drivers/ftd2xx_common.h b/src/jtag/drivers/ftd2xx_common.h deleted file mode 100644 index 14b8455..0000000 --- a/src/jtag/drivers/ftd2xx_common.h +++ /dev/null @@ -1,55 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2011 by Spencer Oliver <spen@spen-soft.co.uk> * - * * - * Written by Arnim Laeuger, 2008 (from urjtag) * - * * - * 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 * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * 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, see <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -#ifndef OPENOCD_JTAG_DRIVERS_FTD2XX_COMMON_H -#define OPENOCD_JTAG_DRIVERS_FTD2XX_COMMON_H - -#if ((BUILD_FT2232_FTD2XX == 1) || (BUILD_PRESTO_FTD2XX == 1) || (BUILD_USB_BLASTER_FTD2XX == 1)) -#include <ftd2xx.h> - -static const char *ftd2xx_status_string(FT_STATUS status) -{ - switch (status) { - case FT_OK: return "OK"; - case FT_INVALID_HANDLE: return "invalid handle"; - case FT_DEVICE_NOT_FOUND: return "device not found"; - case FT_DEVICE_NOT_OPENED: return "device not opened"; - case FT_IO_ERROR: return "io error"; - case FT_INSUFFICIENT_RESOURCES: return "insufficient resources"; - case FT_INVALID_PARAMETER: return "invalid parameter"; - case FT_INVALID_BAUD_RATE: return "invalid baud rate"; - - case FT_DEVICE_NOT_OPENED_FOR_ERASE: return "device not opened for erase"; - case FT_DEVICE_NOT_OPENED_FOR_WRITE: return "device not opened for write"; - case FT_FAILED_TO_WRITE_DEVICE: return "failed to write device"; - case FT_EEPROM_READ_FAILED: return "eeprom read failed"; - case FT_EEPROM_WRITE_FAILED: return "eeprom write failed"; - case FT_EEPROM_ERASE_FAILED: return "eeprom erase failed"; - case FT_EEPROM_NOT_PRESENT: return "eeprom not present"; - case FT_EEPROM_NOT_PROGRAMMED: return "eeprom not programmed"; - case FT_INVALID_ARGS: return "invalid args"; - case FT_NOT_SUPPORTED: return "not supported"; - case FT_OTHER_ERROR: return "other error"; - } - - return "undefined FTD2xx error"; -} - -#endif -#endif /* OPENOCD_JTAG_DRIVERS_FTD2XX_COMMON_H */ diff --git a/src/jtag/drivers/imx_gpio.c b/src/jtag/drivers/imx_gpio.c new file mode 100644 index 0000000..f33d109 --- /dev/null +++ b/src/jtag/drivers/imx_gpio.c @@ -0,0 +1,552 @@ +/*************************************************************************** + * Copyright (C) 2017 by Grzegorz Kostka, kostka.grzegorz@gmail.com * + * * + * Based on bcm2835gpio.c * + * * + * 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 * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * 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, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <jtag/interface.h> +#include "bitbang.h" + +#include <sys/mman.h> + +#define IMX_GPIO_BASE 0x0209c000 +#define IMX_GPIO_SIZE 0x00004000 +#define IMX_GPIO_REGS_COUNT 8 + +static uint32_t imx_gpio_peri_base = IMX_GPIO_BASE; + +struct imx_gpio_regs { + uint32_t dr; + uint32_t gdir; + uint32_t psr; + uint32_t icr1; + uint32_t icr2; + uint32_t imr; + uint32_t isr; + uint32_t edge_sel; +} __attribute__((aligned(IMX_GPIO_SIZE))); + +static int dev_mem_fd; +static volatile struct imx_gpio_regs *pio_base; + +/* GPIO setup functions */ +static inline bool gpio_mode_get(int g) +{ + return pio_base[g / 32].gdir >> (g & 0x1F) & 1; +} + +static inline void gpio_mode_input_set(int g) +{ + pio_base[g / 32].gdir &= ~(1u << (g & 0x1F)); +} + +static inline void gpio_mode_output_set(int g) +{ + pio_base[g / 32].gdir |= (1u << (g & 0x1F)); +} + +static inline void gpio_mode_set(int g, int m) +{ + (m) ? gpio_mode_output_set(g) : gpio_mode_input_set(g); +} + +static inline void gpio_set(int g) +{ + pio_base[g / 32].dr |= (1u << (g & 0x1F)); +} + +static inline void gpio_clear(int g) +{ + pio_base[g / 32].dr &= ~(1u << (g & 0x1F)); +} + +static inline bool gpio_level(int g) +{ + return pio_base[g / 32].dr >> (g & 0x1F) & 1; +} + +static int imx_gpio_read(void); +static void imx_gpio_write(int tck, int tms, int tdi); +static void imx_gpio_reset(int trst, int srst); + +static int imx_gpio_swdio_read(void); +static void imx_gpio_swdio_drive(bool is_output); + +static int imx_gpio_init(void); +static int imx_gpio_quit(void); + +static struct bitbang_interface imx_gpio_bitbang = { + .read = imx_gpio_read, + .write = imx_gpio_write, + .reset = imx_gpio_reset, + .swdio_read = imx_gpio_swdio_read, + .swdio_drive = imx_gpio_swdio_drive, + .blink = NULL +}; + +/* GPIO numbers for each signal. Negative values are invalid */ +static int tck_gpio = -1; +static int tck_gpio_mode; +static int tms_gpio = -1; +static int tms_gpio_mode; +static int tdi_gpio = -1; +static int tdi_gpio_mode; +static int tdo_gpio = -1; +static int tdo_gpio_mode; +static int trst_gpio = -1; +static int trst_gpio_mode; +static int srst_gpio = -1; +static int srst_gpio_mode; +static int swclk_gpio = -1; +static int swclk_gpio_mode; +static int swdio_gpio = -1; +static int swdio_gpio_mode; + +/* Transition delay coefficients. Tuned for IMX6UL 528MHz. Adjusted + * experimentally for:10kHz, 100Khz, 500KHz. Speeds above 800Khz are impossible + * to reach via memory mapped method (at least for IMX6UL@528MHz). + * Measured mmap raw GPIO toggling speed on IMX6UL@528MHz: 1.3MHz. + */ +static int speed_coeff = 50000; +static int speed_offset = 100; +static unsigned int jtag_delay; + +static int imx_gpio_read(void) +{ + return gpio_level(tdo_gpio); +} + +static void imx_gpio_write(int tck, int tms, int tdi) +{ + tms ? gpio_set(tms_gpio) : gpio_clear(tms_gpio); + tdi ? gpio_set(tdi_gpio) : gpio_clear(tdi_gpio); + tck ? gpio_set(tck_gpio) : gpio_clear(tck_gpio); + + for (unsigned int i = 0; i < jtag_delay; i++) + asm volatile (""); +} + +static void imx_gpio_swd_write(int tck, int tms, int tdi) +{ + tdi ? gpio_set(swdio_gpio) : gpio_clear(swdio_gpio); + tck ? gpio_set(swclk_gpio) : gpio_clear(swclk_gpio); + + for (unsigned int i = 0; i < jtag_delay; i++) + asm volatile (""); +} + +/* (1) assert or (0) deassert reset lines */ +static void imx_gpio_reset(int trst, int srst) +{ + if (trst_gpio != -1) + trst ? gpio_set(trst_gpio) : gpio_clear(trst_gpio); + + if (srst_gpio != -1) + srst ? gpio_set(srst_gpio) : gpio_clear(srst_gpio); +} + +static void imx_gpio_swdio_drive(bool is_output) +{ + if (is_output) + gpio_mode_output_set(swdio_gpio); + else + gpio_mode_input_set(swdio_gpio); +} + +static int imx_gpio_swdio_read(void) +{ + return gpio_level(swdio_gpio); +} + +static int imx_gpio_khz(int khz, int *jtag_speed) +{ + if (!khz) { + LOG_DEBUG("RCLK not supported"); + return ERROR_FAIL; + } + *jtag_speed = speed_coeff/khz - speed_offset; + if (*jtag_speed < 0) + *jtag_speed = 0; + return ERROR_OK; +} + +static int imx_gpio_speed_div(int speed, int *khz) +{ + *khz = speed_coeff/(speed + speed_offset); + return ERROR_OK; +} + +static int imx_gpio_speed(int speed) +{ + jtag_delay = speed; + return ERROR_OK; +} + +static int is_gpio_valid(int gpio) +{ + return gpio >= 0 && gpio < 32 * IMX_GPIO_REGS_COUNT; +} + +COMMAND_HANDLER(imx_gpio_handle_jtag_gpionums) +{ + if (CMD_ARGC == 4) { + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio); + COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tms_gpio); + COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], tdi_gpio); + COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], tdo_gpio); + } else if (CMD_ARGC != 0) { + return ERROR_COMMAND_SYNTAX_ERROR; + } + + command_print(CMD_CTX, + "imx_gpio GPIO config: tck = %d, tms = %d, tdi = %d, tdo = %d", + tck_gpio, tms_gpio, tdi_gpio, tdo_gpio); + + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tck) +{ + if (CMD_ARGC == 1) + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio); + + command_print(CMD_CTX, "imx_gpio GPIO config: tck = %d", tck_gpio); + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tms) +{ + if (CMD_ARGC == 1) + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tms_gpio); + + command_print(CMD_CTX, "imx_gpio GPIO config: tms = %d", tms_gpio); + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tdo) +{ + if (CMD_ARGC == 1) + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdo_gpio); + + command_print(CMD_CTX, "imx_gpio GPIO config: tdo = %d", tdo_gpio); + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tdi) +{ + if (CMD_ARGC == 1) + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdi_gpio); + + command_print(CMD_CTX, "imx_gpio GPIO config: tdi = %d", tdi_gpio); + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_srst) +{ + if (CMD_ARGC == 1) + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], srst_gpio); + + command_print(CMD_CTX, "imx_gpio GPIO config: srst = %d", srst_gpio); + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_trst) +{ + if (CMD_ARGC == 1) + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], trst_gpio); + + command_print(CMD_CTX, "imx_gpio GPIO config: trst = %d", trst_gpio); + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_swd_gpionums) +{ + if (CMD_ARGC == 2) { + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio); + COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], swdio_gpio); + } else if (CMD_ARGC != 0) { + return ERROR_COMMAND_SYNTAX_ERROR; + } + + command_print(CMD_CTX, + "imx_gpio GPIO nums: swclk = %d, swdio = %d", + swclk_gpio, swdio_gpio); + + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_swd_gpionum_swclk) +{ + if (CMD_ARGC == 1) + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio); + + command_print(CMD_CTX, "imx_gpio num: swclk = %d", swclk_gpio); + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_swd_gpionum_swdio) +{ + if (CMD_ARGC == 1) + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swdio_gpio); + + command_print(CMD_CTX, "imx_gpio num: swdio = %d", swdio_gpio); + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_speed_coeffs) +{ + if (CMD_ARGC == 2) { + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], speed_coeff); + COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], speed_offset); + } + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_peripheral_base) +{ + if (CMD_ARGC == 1) + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], imx_gpio_peri_base); + return ERROR_OK; +} + +static const struct command_registration imx_gpio_command_handlers[] = { + { + .name = "imx_gpio_jtag_nums", + .handler = &imx_gpio_handle_jtag_gpionums, + .mode = COMMAND_CONFIG, + .help = "gpio numbers for tck, tms, tdi, tdo. (in that order)", + .usage = "(tck tms tdi tdo)* ", + }, + { + .name = "imx_gpio_tck_num", + .handler = &imx_gpio_handle_jtag_gpionum_tck, + .mode = COMMAND_CONFIG, + .help = "gpio number for tck.", + }, + { + .name = "imx_gpio_tms_num", + .handler = &imx_gpio_handle_jtag_gpionum_tms, + .mode = COMMAND_CONFIG, + .help = "gpio number for tms.", + }, + { + .name = "imx_gpio_tdo_num", + .handler = &imx_gpio_handle_jtag_gpionum_tdo, + .mode = COMMAND_CONFIG, + .help = "gpio number for tdo.", + }, + { + .name = "imx_gpio_tdi_num", + .handler = &imx_gpio_handle_jtag_gpionum_tdi, + .mode = COMMAND_CONFIG, + .help = "gpio number for tdi.", + }, + { + .name = "imx_gpio_swd_nums", + .handler = &imx_gpio_handle_swd_gpionums, + .mode = COMMAND_CONFIG, + .help = "gpio numbers for swclk, swdio. (in that order)", + .usage = "(swclk swdio)* ", + }, + { + .name = "imx_gpio_swclk_num", + .handler = &imx_gpio_handle_swd_gpionum_swclk, + .mode = COMMAND_CONFIG, + .help = "gpio number for swclk.", + }, + { + .name = "imx_gpio_swdio_num", + .handler = &imx_gpio_handle_swd_gpionum_swdio, + .mode = COMMAND_CONFIG, + .help = "gpio number for swdio.", + }, + { + .name = "imx_gpio_srst_num", + .handler = &imx_gpio_handle_jtag_gpionum_srst, + .mode = COMMAND_CONFIG, + .help = "gpio number for srst.", + }, + { + .name = "imx_gpio_trst_num", + .handler = &imx_gpio_handle_jtag_gpionum_trst, + .mode = COMMAND_CONFIG, + .help = "gpio number for trst.", + }, + { + .name = "imx_gpio_speed_coeffs", + .handler = &imx_gpio_handle_speed_coeffs, + .mode = COMMAND_CONFIG, + .help = "SPEED_COEFF and SPEED_OFFSET for delay calculations.", + }, + { + .name = "imx_gpio_peripheral_base", + .handler = &imx_gpio_handle_peripheral_base, + .mode = COMMAND_CONFIG, + .help = "peripheral base to access GPIOs (0x0209c000 for most IMX).", + }, + + COMMAND_REGISTRATION_DONE +}; + +static const char * const imx_gpio_transports[] = { "jtag", "swd", NULL }; + +struct jtag_interface imx_gpio_interface = { + .name = "imx_gpio", + .supported = DEBUG_CAP_TMS_SEQ, + .execute_queue = bitbang_execute_queue, + .transports = imx_gpio_transports, + .swd = &bitbang_swd, + .speed = imx_gpio_speed, + .khz = imx_gpio_khz, + .speed_div = imx_gpio_speed_div, + .commands = imx_gpio_command_handlers, + .init = imx_gpio_init, + .quit = imx_gpio_quit, +}; + +static bool imx_gpio_jtag_mode_possible(void) +{ + if (!is_gpio_valid(tck_gpio)) + return 0; + if (!is_gpio_valid(tms_gpio)) + return 0; + if (!is_gpio_valid(tdi_gpio)) + return 0; + if (!is_gpio_valid(tdo_gpio)) + return 0; + return 1; +} + +static bool imx_gpio_swd_mode_possible(void) +{ + if (!is_gpio_valid(swclk_gpio)) + return 0; + if (!is_gpio_valid(swdio_gpio)) + return 0; + return 1; +} + +static int imx_gpio_init(void) +{ + bitbang_interface = &imx_gpio_bitbang; + + LOG_INFO("imx_gpio GPIO JTAG/SWD bitbang driver"); + + if (imx_gpio_jtag_mode_possible()) { + if (imx_gpio_swd_mode_possible()) + LOG_INFO("JTAG and SWD modes enabled"); + else + LOG_INFO("JTAG only mode enabled (specify swclk and swdio gpio to add SWD mode)"); + } else if (imx_gpio_swd_mode_possible()) { + LOG_INFO("SWD only mode enabled (specify tck, tms, tdi and tdo gpios to add JTAG mode)"); + } else { + LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode and/or swclk and swdio gpio for SWD mode"); + return ERROR_JTAG_INIT_FAILED; + } + + dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC); + if (dev_mem_fd < 0) { + perror("open"); + return ERROR_JTAG_INIT_FAILED; + } + + + LOG_INFO("imx_gpio mmap: pagesize: %u, regionsize: %u", + sysconf(_SC_PAGE_SIZE), IMX_GPIO_REGS_COUNT * IMX_GPIO_SIZE); + pio_base = mmap(NULL, IMX_GPIO_REGS_COUNT * IMX_GPIO_SIZE, + PROT_READ | PROT_WRITE, + MAP_SHARED, dev_mem_fd, imx_gpio_peri_base); + + if (pio_base == MAP_FAILED) { + perror("mmap"); + close(dev_mem_fd); + return ERROR_JTAG_INIT_FAILED; + } + + /* + * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST + * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high. + */ + if (imx_gpio_jtag_mode_possible()) { + tdo_gpio_mode = gpio_mode_get(tdo_gpio); + tdi_gpio_mode = gpio_mode_get(tdi_gpio); + tck_gpio_mode = gpio_mode_get(tck_gpio); + tms_gpio_mode = gpio_mode_get(tms_gpio); + + gpio_clear(tdi_gpio); + gpio_clear(tck_gpio); + gpio_set(tms_gpio); + + gpio_mode_input_set(tdo_gpio); + gpio_mode_output_set(tdi_gpio); + gpio_mode_output_set(tck_gpio); + gpio_mode_output_set(tms_gpio); + } + if (imx_gpio_swd_mode_possible()) { + swclk_gpio_mode = gpio_mode_get(swclk_gpio); + swdio_gpio_mode = gpio_mode_get(swdio_gpio); + + gpio_clear(swdio_gpio); + gpio_clear(swclk_gpio); + gpio_mode_output_set(swclk_gpio); + gpio_mode_output_set(swdio_gpio); + } + if (trst_gpio != -1) { + trst_gpio_mode = gpio_mode_get(trst_gpio); + gpio_set(trst_gpio); + gpio_mode_output_set(trst_gpio); + } + if (srst_gpio != -1) { + srst_gpio_mode = gpio_mode_get(srst_gpio); + gpio_set(srst_gpio); + gpio_mode_output_set(srst_gpio); + } + + LOG_DEBUG("saved pinmux settings: tck %d tms %d tdi %d " + "tdo %d trst %d srst %d", tck_gpio_mode, tms_gpio_mode, + tdi_gpio_mode, tdo_gpio_mode, trst_gpio_mode, srst_gpio_mode); + + if (swd_mode) { + imx_gpio_bitbang.write = imx_gpio_swd_write; + bitbang_switch_to_swd(); + } + + return ERROR_OK; +} + +static int imx_gpio_quit(void) +{ + if (imx_gpio_jtag_mode_possible()) { + gpio_mode_set(tdo_gpio, tdo_gpio_mode); + gpio_mode_set(tdi_gpio, tdi_gpio_mode); + gpio_mode_set(tck_gpio, tck_gpio_mode); + gpio_mode_set(tms_gpio, tms_gpio_mode); + } + if (imx_gpio_swd_mode_possible()) { + gpio_mode_set(swclk_gpio, swclk_gpio_mode); + gpio_mode_set(swdio_gpio, swdio_gpio_mode); + } + if (trst_gpio != -1) + gpio_mode_set(trst_gpio, trst_gpio_mode); + if (srst_gpio != -1) + gpio_mode_set(srst_gpio, srst_gpio_mode); + + return ERROR_OK; +} diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 3009058..bd3c5e0 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -314,12 +314,11 @@ static int jlink_execute_queue(void) static int jlink_speed(int speed) { int ret; - uint32_t freq; - uint16_t divider; + struct jaylink_speed tmp; int max_speed; if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_SPEEDS)) { - ret = jaylink_get_speeds(devh, &freq, ÷r); + ret = jaylink_get_speeds(devh, &tmp); if (ret != JAYLINK_OK) { LOG_ERROR("jaylink_get_speeds() failed: %s.", @@ -327,8 +326,8 @@ static int jlink_speed(int speed) return ERROR_JTAG_DEVICE_ERROR; } - freq = freq / 1000; - max_speed = freq / divider; + tmp.freq /= 1000; + max_speed = tmp.freq / tmp.div; } else { max_speed = JLINK_MAX_SPEED; } @@ -433,15 +432,16 @@ static int select_interface(void) static int jlink_register(void) { int ret; - int i; + size_t i; bool handle_found; + size_t count; if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_REGISTER)) return ERROR_OK; - ret = jaylink_register(devh, &conn, connlist, NULL, NULL); + ret = jaylink_register(devh, &conn, connlist, &count); - if (ret < 0) { + if (ret != JAYLINK_OK) { LOG_ERROR("jaylink_register() failed: %s.", jaylink_strerror_name(ret)); return ERROR_FAIL; @@ -449,7 +449,7 @@ static int jlink_register(void) handle_found = false; - for (i = 0; i < ret; i++) { + for (i = 0; i < count; i++) { if (connlist[i].handle == conn.handle) { handle_found = true; break; @@ -502,6 +502,36 @@ static bool adjust_swd_buffer_size(void) return true; } +static int jaylink_log_handler(const struct jaylink_context *ctx, + enum jaylink_log_level level, const char *format, va_list args, + void *user_data) +{ + enum log_levels tmp; + + switch (level) { + case JAYLINK_LOG_LEVEL_ERROR: + tmp = LOG_LVL_ERROR; + break; + case JAYLINK_LOG_LEVEL_WARNING: + tmp = LOG_LVL_WARNING; + break; + /* + * Forward info messages to the debug output because they are more verbose + * than info messages of OpenOCD. + */ + case JAYLINK_LOG_LEVEL_INFO: + case JAYLINK_LOG_LEVEL_DEBUG: + tmp = LOG_LVL_DEBUG; + break; + default: + tmp = LOG_LVL_WARNING; + } + + log_vprintf_lf(tmp, __FILE__, __LINE__, __func__, format, args); + + return 0; +} + static int jlink_init(void) { int ret; @@ -515,6 +545,9 @@ static int jlink_init(void) enum jaylink_usb_address address; size_t length; + LOG_DEBUG("Using libjaylink %s (compiled with %s).", + jaylink_version_package_get_string(), JAYLINK_VERSION_PACKAGE_STRING); + ret = jaylink_init(&jayctx); if (ret != JAYLINK_OK) { @@ -523,10 +556,28 @@ static int jlink_init(void) return ERROR_JTAG_INIT_FAILED; } - ret = jaylink_get_device_list(jayctx, &devs); + ret = jaylink_log_set_callback(jayctx, &jaylink_log_handler, NULL); - if (ret < 0) { - LOG_ERROR("jaylink_get_device_list() failed: %s.", + if (ret != JAYLINK_OK) { + LOG_ERROR("jaylink_log_set_callback() failed: %s.", + jaylink_strerror_name(ret)); + jaylink_exit(jayctx); + return ERROR_JTAG_INIT_FAILED; + } + + ret = jaylink_discovery_scan(jayctx, 0); + + if (ret != JAYLINK_OK) { + LOG_ERROR("jaylink_discovery_scan() failed: %s.", + jaylink_strerror_name(ret)); + jaylink_exit(jayctx); + return ERROR_JTAG_INIT_FAILED; + } + + ret = jaylink_get_devices(jayctx, &devs, NULL); + + if (ret != JAYLINK_OK) { + LOG_ERROR("jaylink_get_devices() failed: %s.", jaylink_strerror_name(ret)); jaylink_exit(jayctx); return ERROR_JTAG_INIT_FAILED; @@ -576,7 +627,7 @@ static int jlink_init(void) LOG_ERROR("Failed to open device: %s.", jaylink_strerror_name(ret)); } - jaylink_free_device_list(devs, 1); + jaylink_free_devices(devs, true); if (!found_device) { LOG_ERROR("No J-Link device found."); @@ -626,7 +677,7 @@ static int jlink_init(void) } } - jtag_command_version = JAYLINK_JTAG_V2; + jtag_command_version = JAYLINK_JTAG_VERSION_2; if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_HW_VERSION)) { ret = jaylink_get_hardware_version(devh, &hwver); @@ -642,7 +693,7 @@ static int jlink_init(void) LOG_INFO("Hardware version: %u.%02u", hwver.major, hwver.minor); if (hwver.major >= 5) - jtag_command_version = JAYLINK_JTAG_V3; + jtag_command_version = JAYLINK_JTAG_VERSION_3; } if (iface == JAYLINK_TIF_SWD) { @@ -685,7 +736,7 @@ static int jlink_init(void) conn.handle = 0; conn.pid = 0; - conn.hid = 0; + strcpy(conn.hid, "0.0.0.0"); conn.iid = 0; conn.cid = 0; @@ -729,6 +780,7 @@ static int jlink_init(void) static int jlink_quit(void) { int ret; + size_t count; if (trace_enabled) { ret = jaylink_swo_stop(devh); @@ -739,9 +791,9 @@ static int jlink_quit(void) } if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_REGISTER)) { - ret = jaylink_unregister(devh, &conn, connlist, NULL, NULL); + ret = jaylink_unregister(devh, &conn, connlist, &count); - if (ret < 0) + if (ret != JAYLINK_OK) LOG_ERROR("jaylink_unregister() failed: %s.", jaylink_strerror_name(ret)); } @@ -878,14 +930,22 @@ COMMAND_HANDLER(jlink_usb_command) COMMAND_HANDLER(jlink_serial_command) { + int ret; + if (CMD_ARGC != 1) { command_print(CMD_CTX, "Need exactly one argument for jlink serial."); return ERROR_COMMAND_SYNTAX_ERROR; } - if (sscanf(CMD_ARGV[0], "%" SCNd32, &serial_number) != 1) { + ret = jaylink_parse_serial_number(CMD_ARGV[0], &serial_number); + + if (ret == JAYLINK_ERR) { command_print(CMD_CTX, "Invalid serial number: %s.", CMD_ARGV[0]); return ERROR_FAIL; + } else if (ret != JAYLINK_OK) { + command_print(CMD_CTX, "jaylink_parse_serial_number() failed: %s.", + jaylink_strerror_name(ret)); + return ERROR_FAIL; } use_serial_number = true; @@ -951,10 +1011,10 @@ COMMAND_HANDLER(jlink_handle_jlink_jtag_command) if (!CMD_ARGC) { switch (jtag_command_version) { - case JAYLINK_JTAG_V2: + case JAYLINK_JTAG_VERSION_2: version = 2; break; - case JAYLINK_JTAG_V3: + case JAYLINK_JTAG_VERSION_3: version = 3; break; default: @@ -970,10 +1030,10 @@ COMMAND_HANDLER(jlink_handle_jlink_jtag_command) switch (tmp) { case 2: - jtag_command_version = JAYLINK_JTAG_V2; + jtag_command_version = JAYLINK_JTAG_VERSION_2; break; case 3: - jtag_command_version = JAYLINK_JTAG_V3; + jtag_command_version = JAYLINK_JTAG_VERSION_3; break; default: command_print(CMD_CTX, "Invalid argument: %s.", CMD_ARGV[0]); @@ -1545,6 +1605,125 @@ COMMAND_HANDLER(jlink_handle_config_command) return ERROR_OK; } +COMMAND_HANDLER(jlink_handle_emucom_write_command) +{ + int ret; + size_t tmp; + uint32_t channel; + uint32_t length; + uint8_t *buf; + size_t dummy; + + if (CMD_ARGC != 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_EMUCOM)) { + LOG_ERROR("Device does not support EMUCOM."); + return ERROR_FAIL; + } + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], channel); + + tmp = strlen(CMD_ARGV[1]); + + if (tmp % 2 != 0) { + LOG_ERROR("Data must be encoded as hexadecimal pairs."); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + buf = malloc(tmp / 2); + + if (!buf) { + LOG_ERROR("Failed to allocate buffer."); + return ERROR_FAIL; + } + + dummy = unhexify(buf, CMD_ARGV[1], tmp / 2); + + if (dummy != (tmp / 2)) { + LOG_ERROR("Data must be encoded as hexadecimal pairs."); + free(buf); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + length = tmp / 2; + ret = jaylink_emucom_write(devh, channel, buf, &length); + + free(buf); + + if (ret == JAYLINK_ERR_DEV_NOT_SUPPORTED) { + LOG_ERROR("Channel not supported by the device."); + return ERROR_FAIL; + } else if (ret != JAYLINK_OK) { + LOG_ERROR("Failed to write to channel: %s.", + jaylink_strerror_name(ret)); + return ERROR_FAIL; + } + + if (length != (tmp / 2)) + LOG_WARNING("Only %" PRIu32 " bytes written to the channel.", length); + + return ERROR_OK; +} + +COMMAND_HANDLER(jlink_handle_emucom_read_command) +{ + int ret; + uint32_t channel; + uint32_t length; + uint8_t *buf; + size_t tmp; + + if (CMD_ARGC != 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_EMUCOM)) { + LOG_ERROR("Device does not support EMUCOM."); + return ERROR_FAIL; + } + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], channel); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); + + buf = malloc(length * 3 + 1); + + if (!buf) { + LOG_ERROR("Failed to allocate buffer."); + return ERROR_FAIL; + } + + ret = jaylink_emucom_read(devh, channel, buf, &length); + + if (ret == JAYLINK_ERR_DEV_NOT_SUPPORTED) { + LOG_ERROR("Channel is not supported by the device."); + free(buf); + return ERROR_FAIL; + } else if (ret == JAYLINK_ERR_DEV_NOT_AVAILABLE) { + LOG_ERROR("Channel is not available for the requested amount of data. " + "%" PRIu32 " bytes are avilable.", length); + free(buf); + return ERROR_FAIL; + } else if (ret != JAYLINK_OK) { + LOG_ERROR("Failed to read from channel: %s.", + jaylink_strerror_name(ret)); + free(buf); + return ERROR_FAIL; + } + + tmp = hexify((char *)buf + length, buf, length, 2 * length + 1); + + if (tmp != 2 * length) { + LOG_ERROR("Failed to convert data into hexadecimal string."); + free(buf); + return ERROR_FAIL; + } + + command_print(CMD_CTX, "%s", buf + length); + free(buf); + + return ERROR_OK; +} + static const struct command_registration jlink_config_subcommand_handlers[] = { { .name = "usb", @@ -1590,6 +1769,24 @@ static const struct command_registration jlink_config_subcommand_handlers[] = { COMMAND_REGISTRATION_DONE }; +static const struct command_registration jlink_emucom_subcommand_handlers[] = { + { + .name = "write", + .handler = &jlink_handle_emucom_write_command, + .mode = COMMAND_EXEC, + .help = "write to a channel", + .usage = "<channel> <data>", + }, + { + .name = "read", + .handler = &jlink_handle_emucom_read_command, + .mode = COMMAND_EXEC, + .help = "read from a channel", + .usage = "<channel> <length>" + }, + COMMAND_REGISTRATION_DONE +}; + static const struct command_registration jlink_subcommand_handlers[] = { { .name = "jtag", @@ -1639,6 +1836,12 @@ static const struct command_registration jlink_subcommand_handlers[] = { "this will show the device configuration", .chain = jlink_config_subcommand_handlers, }, + { + .name = "emucom", + .mode = COMMAND_EXEC, + .help = "access EMUCOM channel", + .chain = jlink_emucom_subcommand_handlers + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/jtag/drivers/kitprog.c b/src/jtag/drivers/kitprog.c new file mode 100644 index 0000000..c689848 --- /dev/null +++ b/src/jtag/drivers/kitprog.c @@ -0,0 +1,967 @@ +/*************************************************************************** + * Copyright (C) 2007 by Juergen Stuber <juergen@jstuber.net> * + * based on Dominic Rath's and Benedikt Sauter's usbprog.c * + * * + * Copyright (C) 2008 by Spencer Oliver * + * spen@spen-soft.co.uk * + * * + * Copyright (C) 2011 by Jean-Christophe PLAGNIOL-VIILARD * + * plagnioj@jcrosoft.com * + * * + * Copyright (C) 2015 by Marc Schink * + * openocd-dev@marcschink.de * + * * + * Copyright (C) 2015 by Paul Fertser * + * fercerpav@gmail.com * + * * + * Copyright (C) 2015-2017 by Forest Crossman * + * cyrozap@gmail.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 * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * 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, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdint.h> + +#include <hidapi.h> + +#include <jtag/interface.h> +#include <jtag/swd.h> +#include <jtag/commands.h> + +#include "libusb_common.h" + +#define VID 0x04b4 +#define PID 0xf139 + +#define BULK_EP_IN 1 +#define BULK_EP_OUT 2 + +#define CONTROL_TYPE_READ 0x01 +#define CONTROL_TYPE_WRITE 0x02 + +#define CONTROL_COMMAND_PROGRAM 0x07 + +#define CONTROL_MODE_POLL_PROGRAMMER_STATUS 0x01 +#define CONTROL_MODE_RESET_TARGET 0x04 +#define CONTROL_MODE_SET_PROGRAMMER_PROTOCOL 0x40 +#define CONTROL_MODE_SYNCHRONIZE_TRANSFER 0x41 +#define CONTROL_MODE_ACQUIRE_SWD_TARGET 0x42 +#define CONTROL_MODE_SEND_SWD_SEQUENCE 0x43 + +#define PROTOCOL_JTAG 0x00 +#define PROTOCOL_SWD 0x01 + +#define DEVICE_PSOC4 0x00 +#define DEVICE_PSOC3 0x01 +#define DEVICE_UNKNOWN 0x02 +#define DEVICE_PSOC5 0x03 + +#define ACQUIRE_MODE_RESET 0x00 +#define ACQUIRE_MODE_POWER_CYCLE 0x01 + +#define SEQUENCE_LINE_RESET 0x00 +#define SEQUENCE_JTAG_TO_SWD 0x01 + +#define PROGRAMMER_NOK_NACK 0x00 +#define PROGRAMMER_OK_ACK 0x01 + +#define HID_TYPE_WRITE 0x00 +#define HID_TYPE_READ 0x01 +#define HID_TYPE_START 0x02 + +#define HID_COMMAND_POWER 0x80 +#define HID_COMMAND_VERSION 0x81 +#define HID_COMMAND_RESET 0x82 +#define HID_COMMAND_CONFIGURE 0x8f +#define HID_COMMAND_BOOTLOADER 0xa0 + +/* 512 bytes seems to work reliably */ +#define SWD_MAX_BUFFER_LENGTH 512 + +struct kitprog { + hid_device *hid_handle; + struct jtag_libusb_device_handle *usb_handle; + uint16_t packet_size; + uint16_t packet_index; + uint8_t *packet_buffer; + char *serial; + uint8_t hardware_version; + uint8_t minor_version; + uint8_t major_version; + uint16_t millivolts; + + bool supports_jtag_to_swd; +}; + +struct pending_transfer_result { + uint8_t cmd; + uint32_t data; + void *buffer; +}; + +static char *kitprog_serial; +static bool kitprog_init_acquire_psoc; + +static int pending_transfer_count, pending_queue_len; +static struct pending_transfer_result *pending_transfers; + +static int queued_retval; + +static struct kitprog *kitprog_handle; + +static int kitprog_usb_open(void); +static void kitprog_usb_close(void); + +static int kitprog_hid_command(uint8_t *command, size_t command_length, + uint8_t *data, size_t data_length); +static int kitprog_get_version(void); +static int kitprog_get_millivolts(void); +static int kitprog_get_info(void); +static int kitprog_set_protocol(uint8_t protocol); +static int kitprog_get_status(void); +static int kitprog_set_unknown(void); +static int kitprog_acquire_psoc(uint8_t psoc_type, uint8_t acquire_mode, + uint8_t max_attempts); +static int kitprog_reset_target(void); +static int kitprog_swd_sync(void); +static int kitprog_swd_seq(uint8_t seq_type); + +static int kitprog_generic_acquire(void); + +static int kitprog_swd_run_queue(void); +static void kitprog_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data); +static int kitprog_swd_switch_seq(enum swd_special_seq seq); + + +static inline int mm_to_version(uint8_t major, uint8_t minor) +{ + return (major << 8) | minor; +} + +static int kitprog_init(void) +{ + int retval; + + kitprog_handle = malloc(sizeof(struct kitprog)); + if (kitprog_handle == NULL) { + LOG_ERROR("Failed to allocate memory"); + return ERROR_FAIL; + } + + if (kitprog_usb_open() != ERROR_OK) { + LOG_ERROR("Can't find a KitProg device! Please check device connections and permissions."); + return ERROR_JTAG_INIT_FAILED; + } + + /* Get the current KitProg version and target voltage */ + if (kitprog_get_info() != ERROR_OK) + return ERROR_FAIL; + + /* Compatibility check */ + kitprog_handle->supports_jtag_to_swd = true; + int kitprog_version = mm_to_version(kitprog_handle->major_version, kitprog_handle->minor_version); + if (kitprog_version < mm_to_version(2, 14)) { + LOG_WARNING("KitProg firmware versions below v2.14 do not support sending JTAG to SWD sequences. These sequences will be substituted with SWD line resets."); + kitprog_handle->supports_jtag_to_swd = false; + } + + /* I have no idea what this does */ + if (kitprog_set_unknown() != ERROR_OK) + return ERROR_FAIL; + + /* SWD won't work unless we do this */ + if (kitprog_swd_sync() != ERROR_OK) + return ERROR_FAIL; + + /* Set the protocol to SWD */ + if (kitprog_set_protocol(PROTOCOL_SWD) != ERROR_OK) + return ERROR_FAIL; + + /* Reset the SWD bus */ + if (kitprog_swd_seq(SEQUENCE_LINE_RESET) != ERROR_OK) + return ERROR_FAIL; + + if (kitprog_init_acquire_psoc) { + /* Try to acquire any device that will respond */ + retval = kitprog_generic_acquire(); + if (retval != ERROR_OK) { + LOG_ERROR("No PSoC devices found"); + return retval; + } + } + + /* Allocate packet buffers and queues */ + kitprog_handle->packet_size = SWD_MAX_BUFFER_LENGTH; + kitprog_handle->packet_buffer = malloc(SWD_MAX_BUFFER_LENGTH); + if (kitprog_handle->packet_buffer == NULL) { + LOG_ERROR("Failed to allocate memory for the packet buffer"); + return ERROR_FAIL; + } + + pending_queue_len = SWD_MAX_BUFFER_LENGTH / 5; + pending_transfers = malloc(pending_queue_len * sizeof(*pending_transfers)); + if (pending_transfers == NULL) { + LOG_ERROR("Failed to allocate memory for the SWD transfer queue"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_quit(void) +{ + kitprog_usb_close(); + + if (kitprog_handle->packet_buffer != NULL) + free(kitprog_handle->packet_buffer); + if (kitprog_handle->serial != NULL) + free(kitprog_handle->serial); + if (kitprog_handle != NULL) + free(kitprog_handle); + + if (kitprog_serial != NULL) + free(kitprog_serial); + + if (pending_transfers != NULL) + free(pending_transfers); + + return ERROR_OK; +} + +/*************** kitprog usb functions *********************/ + +static int kitprog_get_usb_serial(void) +{ + int retval; + const uint8_t str_index = 128; /* This seems to be a constant */ + char desc_string[256+1]; /* Max size of string descriptor */ + + retval = libusb_get_string_descriptor_ascii(kitprog_handle->usb_handle, + str_index, (unsigned char *)desc_string, sizeof(desc_string)-1); + if (retval < 0) { + LOG_ERROR("libusb_get_string_descriptor_ascii() failed with %d", retval); + return ERROR_FAIL; + } + + /* Null terminate descriptor string */ + desc_string[retval] = '\0'; + + /* Allocate memory for the serial number */ + kitprog_handle->serial = calloc(retval + 1, sizeof(char)); + if (kitprog_handle->serial == NULL) { + LOG_ERROR("Failed to allocate memory for the serial number"); + return ERROR_FAIL; + } + + /* Store the serial number */ + strncpy(kitprog_handle->serial, desc_string, retval + 1); + + return ERROR_OK; +} + +static int kitprog_usb_open(void) +{ + const uint16_t vids[] = { VID, 0 }; + const uint16_t pids[] = { PID, 0 }; + + if (jtag_libusb_open(vids, pids, kitprog_serial, + &kitprog_handle->usb_handle) != ERROR_OK) { + LOG_ERROR("Failed to open or find the device"); + return ERROR_FAIL; + } + + /* Get the serial number for the device */ + if (kitprog_get_usb_serial() != ERROR_OK) + LOG_WARNING("Failed to get KitProg serial number"); + + /* Convert the ASCII serial number into a (wchar_t *) */ + size_t len = strlen(kitprog_handle->serial); + wchar_t *hid_serial = calloc(len + 1, sizeof(wchar_t)); + if (hid_serial == NULL) { + LOG_ERROR("Failed to allocate memory for the serial number"); + return ERROR_FAIL; + } + if (mbstowcs(hid_serial, kitprog_handle->serial, len + 1) == (size_t)-1) { + free(hid_serial); + LOG_ERROR("Failed to convert serial number"); + return ERROR_FAIL; + } + + /* Use HID for the KitBridge interface */ + kitprog_handle->hid_handle = hid_open(VID, PID, hid_serial); + free(hid_serial); + if (kitprog_handle->hid_handle == NULL) { + LOG_ERROR("Failed to open KitBridge (HID) interface"); + return ERROR_FAIL; + } + + /* Claim the KitProg Programmer (bulk transfer) interface */ + if (jtag_libusb_claim_interface(kitprog_handle->usb_handle, 1) != ERROR_OK) { + LOG_ERROR("Failed to claim KitProg Programmer (bulk transfer) interface"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static void kitprog_usb_close(void) +{ + if (kitprog_handle->hid_handle != NULL) { + hid_close(kitprog_handle->hid_handle); + hid_exit(); + } + + jtag_libusb_close(kitprog_handle->usb_handle); +} + +/*************** kitprog lowlevel functions *********************/ + +static int kitprog_hid_command(uint8_t *command, size_t command_length, + uint8_t *data, size_t data_length) +{ + int ret; + + ret = hid_write(kitprog_handle->hid_handle, command, command_length); + if (ret < 0) { + LOG_DEBUG("HID write returned %i", ret); + return ERROR_FAIL; + } + + ret = hid_read(kitprog_handle->hid_handle, data, data_length); + if (ret < 0) { + LOG_DEBUG("HID read returned %i", ret); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_get_version(void) +{ + int ret; + + unsigned char command[3] = {HID_TYPE_START | HID_TYPE_WRITE, 0x00, HID_COMMAND_VERSION}; + unsigned char data[64]; + + ret = kitprog_hid_command(command, sizeof command, data, sizeof data); + if (ret != ERROR_OK) + return ret; + + kitprog_handle->hardware_version = data[1]; + kitprog_handle->minor_version = data[2]; + kitprog_handle->major_version = data[3]; + + return ERROR_OK; +} + +static int kitprog_get_millivolts(void) +{ + int ret; + + unsigned char command[3] = {HID_TYPE_START | HID_TYPE_READ, 0x00, HID_COMMAND_POWER}; + unsigned char data[64]; + + ret = kitprog_hid_command(command, sizeof command, data, sizeof data); + if (ret != ERROR_OK) + return ret; + + kitprog_handle->millivolts = (data[4] << 8) | data[3]; + + return ERROR_OK; +} + +static int kitprog_get_info(void) +{ + /* Get the device version information */ + if (kitprog_get_version() == ERROR_OK) { + LOG_INFO("KitProg v%u.%02u", + kitprog_handle->major_version, kitprog_handle->minor_version); + LOG_INFO("Hardware version: %u", + kitprog_handle->hardware_version); + } else { + LOG_ERROR("Failed to get KitProg version"); + return ERROR_FAIL; + } + + /* Get the current reported target voltage */ + if (kitprog_get_millivolts() == ERROR_OK) { + LOG_INFO("VTARG = %u.%03u V", + kitprog_handle->millivolts / 1000, kitprog_handle->millivolts % 1000); + } else { + LOG_ERROR("Failed to get target voltage"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_set_protocol(uint8_t protocol) +{ + int transferred; + char status = PROGRAMMER_NOK_NACK; + + transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + CONTROL_TYPE_WRITE, + (CONTROL_MODE_SET_PROGRAMMER_PROTOCOL << 8) | CONTROL_COMMAND_PROGRAM, + protocol, &status, 1, 0); + + if (transferred == 0) { + LOG_DEBUG("Zero bytes transferred"); + return ERROR_FAIL; + } + + if (status != PROGRAMMER_OK_ACK) { + LOG_DEBUG("Programmer did not respond OK"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_get_status(void) +{ + int transferred = 0; + char status = PROGRAMMER_NOK_NACK; + + /* Try a maximum of three times */ + for (int i = 0; (i < 3) && (transferred == 0); i++) { + transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + CONTROL_TYPE_READ, + (CONTROL_MODE_POLL_PROGRAMMER_STATUS << 8) | CONTROL_COMMAND_PROGRAM, + 0, &status, 1, 0); + jtag_sleep(1000); + } + + if (transferred == 0) { + LOG_DEBUG("Zero bytes transferred"); + return ERROR_FAIL; + } + + if (status != PROGRAMMER_OK_ACK) { + LOG_DEBUG("Programmer did not respond OK"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_set_unknown(void) +{ + int transferred; + char status = PROGRAMMER_NOK_NACK; + + transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + CONTROL_TYPE_WRITE, + (0x03 << 8) | 0x04, + 0, &status, 1, 0); + + if (transferred == 0) { + LOG_DEBUG("Zero bytes transferred"); + return ERROR_FAIL; + } + + if (status != PROGRAMMER_OK_ACK) { + LOG_DEBUG("Programmer did not respond OK"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_acquire_psoc(uint8_t psoc_type, uint8_t acquire_mode, + uint8_t max_attempts) +{ + int transferred; + char status = PROGRAMMER_NOK_NACK; + + transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + CONTROL_TYPE_WRITE, + (CONTROL_MODE_ACQUIRE_SWD_TARGET << 8) | CONTROL_COMMAND_PROGRAM, + (max_attempts << 8) | (acquire_mode << 4) | psoc_type, &status, 1, 0); + + if (transferred == 0) { + LOG_DEBUG("Zero bytes transferred"); + return ERROR_FAIL; + } + + if (status != PROGRAMMER_OK_ACK) { + LOG_DEBUG("Programmer did not respond OK"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_reset_target(void) +{ + int transferred; + char status = PROGRAMMER_NOK_NACK; + + transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + CONTROL_TYPE_WRITE, + (CONTROL_MODE_RESET_TARGET << 8) | CONTROL_COMMAND_PROGRAM, + 0, &status, 1, 0); + + if (transferred == 0) { + LOG_DEBUG("Zero bytes transferred"); + return ERROR_FAIL; + } + + if (status != PROGRAMMER_OK_ACK) { + LOG_DEBUG("Programmer did not respond OK"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_swd_sync(void) +{ + int transferred; + char status = PROGRAMMER_NOK_NACK; + + transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + CONTROL_TYPE_WRITE, + (CONTROL_MODE_SYNCHRONIZE_TRANSFER << 8) | CONTROL_COMMAND_PROGRAM, + 0, &status, 1, 0); + + if (transferred == 0) { + LOG_DEBUG("Zero bytes transferred"); + return ERROR_FAIL; + } + + if (status != PROGRAMMER_OK_ACK) { + LOG_DEBUG("Programmer did not respond OK"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_swd_seq(uint8_t seq_type) +{ + int transferred; + char status = PROGRAMMER_NOK_NACK; + + transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + CONTROL_TYPE_WRITE, + (CONTROL_MODE_SEND_SWD_SEQUENCE << 8) | CONTROL_COMMAND_PROGRAM, + seq_type, &status, 1, 0); + + if (transferred == 0) { + LOG_DEBUG("Zero bytes transferred"); + return ERROR_FAIL; + } + + if (status != PROGRAMMER_OK_ACK) { + LOG_DEBUG("Programmer did not respond OK"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_generic_acquire(void) +{ + const uint8_t devices[] = {DEVICE_PSOC4, DEVICE_PSOC3, DEVICE_PSOC5}; + + int retval; + int acquire_count = 0; + + /* Due to the way the SWD port is shared between the Test Controller (TC) + * and the Cortex-M3 DAP on the PSoC 5LP, the TC is the default SWD target + * after power is applied. To access the DAP, the PSoC 5LP requires at least + * one acquisition sequence to be run (which switches the SWD mux from the + * TC to the DAP). However, after the mux is switched, the Cortex-M3 will be + * held in reset until a series of registers are written to (see section 5.2 + * of the PSoC 5LP Device Programming Specifications for details). + * + * Instead of writing the registers in this function, we just do what the + * Cypress tools do and run the acquisition sequence a second time. This + * will take the Cortex-M3 out of reset and enable debugging. + */ + for (int i = 0; i < 2; i++) { + for (uint8_t j = 0; j < sizeof devices && acquire_count == i; j++) { + retval = kitprog_acquire_psoc(devices[j], ACQUIRE_MODE_RESET, 3); + if (retval != ERROR_OK) { + LOG_DEBUG("Aquisition function failed for device 0x%02x.", devices[j]); + return retval; + } + + if (kitprog_get_status() == ERROR_OK) + acquire_count++; + } + + jtag_sleep(10); + } + + if (acquire_count < 2) + return ERROR_FAIL; + + return ERROR_OK; +} + +/*************** swd wrapper functions *********************/ + +static int kitprog_swd_init(void) +{ + return ERROR_OK; +} + +static void kitprog_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk) +{ + assert(!(cmd & SWD_CMD_RnW)); + kitprog_swd_queue_cmd(cmd, NULL, value); +} + +static void kitprog_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_clk) +{ + assert(cmd & SWD_CMD_RnW); + kitprog_swd_queue_cmd(cmd, value, 0); +} + +/*************** swd lowlevel functions ********************/ + +static int kitprog_swd_switch_seq(enum swd_special_seq seq) +{ + switch (seq) { + case JTAG_TO_SWD: + if (kitprog_handle->supports_jtag_to_swd) { + LOG_DEBUG("JTAG to SWD"); + if (kitprog_swd_seq(SEQUENCE_JTAG_TO_SWD) != ERROR_OK) + return ERROR_FAIL; + break; + } else { + LOG_DEBUG("JTAG to SWD not supported"); + /* Fall through to fix target reset issue */ + } + case LINE_RESET: + LOG_DEBUG("SWD line reset"); + if (kitprog_swd_seq(SEQUENCE_LINE_RESET) != ERROR_OK) + return ERROR_FAIL; + break; + default: + LOG_ERROR("Sequence %d not supported.", seq); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_swd_run_queue(void) +{ + int ret; + + size_t read_count = 0; + size_t read_index = 0; + size_t write_count = 0; + uint8_t *buffer = kitprog_handle->packet_buffer; + + do { + LOG_DEBUG("Executing %d queued transactions", pending_transfer_count); + + if (queued_retval != ERROR_OK) { + LOG_DEBUG("Skipping due to previous errors: %d", queued_retval); + break; + } + + if (!pending_transfer_count) + break; + + for (int i = 0; i < pending_transfer_count; i++) { + uint8_t cmd = pending_transfers[i].cmd; + uint32_t data = pending_transfers[i].data; + + /* When proper WAIT handling is implemented in the + * common SWD framework, this kludge can be + * removed. However, this might lead to minor + * performance degradation as the adapter wouldn't be + * able to automatically retry anything (because ARM + * has forgotten to implement sticky error flags + * clearing). See also comments regarding + * cmsis_dap_cmd_DAP_TFER_Configure() and + * cmsis_dap_cmd_DAP_SWD_Configure() in + * cmsis_dap_init(). + */ + if (!(cmd & SWD_CMD_RnW) && + !(cmd & SWD_CMD_APnDP) && + (cmd & SWD_CMD_A32) >> 1 == DP_CTRL_STAT && + (data & CORUNDETECT)) { + LOG_DEBUG("refusing to enable sticky overrun detection"); + data &= ~CORUNDETECT; + } + +#if 0 + LOG_DEBUG("%s %s reg %x %"PRIx32, + cmd & SWD_CMD_APnDP ? "AP" : "DP", + cmd & SWD_CMD_RnW ? "read" : "write", + (cmd & SWD_CMD_A32) >> 1, data); +#endif + + buffer[write_count++] = (cmd | SWD_CMD_START | SWD_CMD_PARK) & ~SWD_CMD_STOP; + read_count++; + if (!(cmd & SWD_CMD_RnW)) { + buffer[write_count++] = (data) & 0xff; + buffer[write_count++] = (data >> 8) & 0xff; + buffer[write_count++] = (data >> 16) & 0xff; + buffer[write_count++] = (data >> 24) & 0xff; + } else { + read_count += 4; + } + } + + ret = jtag_libusb_bulk_write(kitprog_handle->usb_handle, + BULK_EP_OUT, (char *)buffer, write_count, 0); + if (ret > 0) { + queued_retval = ERROR_OK; + } else { + LOG_ERROR("Bulk write failed"); + queued_retval = ERROR_FAIL; + break; + } + + /* We use the maximum buffer size here because the KitProg sometimes + * doesn't like bulk reads of fewer than 62 bytes. (?!?!) + */ + ret = jtag_libusb_bulk_read(kitprog_handle->usb_handle, + BULK_EP_IN | LIBUSB_ENDPOINT_IN, (char *)buffer, + SWD_MAX_BUFFER_LENGTH, 0); + if (ret > 0) { + /* Handle garbage data by offsetting the initial read index */ + if ((unsigned int)ret > read_count) + read_index = ret - read_count; + queued_retval = ERROR_OK; + } else { + LOG_ERROR("Bulk read failed"); + queued_retval = ERROR_FAIL; + break; + } + + for (int i = 0; i < pending_transfer_count; i++) { + if (pending_transfers[i].cmd & SWD_CMD_RnW) { + uint32_t data = le_to_h_u32(&buffer[read_index]); + +#if 0 + LOG_DEBUG("Read result: %"PRIx32, data); +#endif + + if (pending_transfers[i].buffer) + *(uint32_t *)pending_transfers[i].buffer = data; + + read_index += 4; + } + + uint8_t ack = buffer[read_index] & 0x07; + if (ack != SWD_ACK_OK || (buffer[read_index] & 0x08)) { + LOG_DEBUG("SWD ack not OK: %d %s", i, + ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK"); + queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL; + break; + } + read_index++; + } + } while (0); + + pending_transfer_count = 0; + int retval = queued_retval; + queued_retval = ERROR_OK; + + return retval; +} + +static void kitprog_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data) +{ + if (pending_transfer_count == pending_queue_len) { + /* Not enough room in the queue. Run the queue. */ + queued_retval = kitprog_swd_run_queue(); + } + + if (queued_retval != ERROR_OK) + return; + + pending_transfers[pending_transfer_count].data = data; + pending_transfers[pending_transfer_count].cmd = cmd; + if (cmd & SWD_CMD_RnW) { + /* Queue a read transaction */ + pending_transfers[pending_transfer_count].buffer = dst; + } + pending_transfer_count++; +} + +/*************** jtag lowlevel functions ********************/ + +static void kitprog_execute_reset(struct jtag_command *cmd) +{ + int retval = ERROR_OK; + + if (cmd->cmd.reset->srst == 1) { + retval = kitprog_reset_target(); + /* Since the previous command also disables SWCLK output, we need to send an + * SWD bus reset command to re-enable it. For some reason, running + * kitprog_swd_seq() immediately after kitprog_reset_target() won't + * actually fix this. Instead, kitprog_swd_seq() will be run once OpenOCD + * tries to send a JTAG-to-SWD sequence, which should happen during + * swd_check_reconnect (see the JTAG_TO_SWD case in kitprog_swd_switch_seq). + */ + } + + if (retval != ERROR_OK) + LOG_ERROR("KitProg: Interface reset failed"); +} + +static void kitprog_execute_sleep(struct jtag_command *cmd) +{ + jtag_sleep(cmd->cmd.sleep->us); +} + +static void kitprog_execute_command(struct jtag_command *cmd) +{ + switch (cmd->type) { + case JTAG_RESET: + kitprog_execute_reset(cmd); + break; + case JTAG_SLEEP: + kitprog_execute_sleep(cmd); + break; + default: + LOG_ERROR("BUG: unknown JTAG command type encountered"); + exit(-1); + } +} + +static int kitprog_execute_queue(void) +{ + struct jtag_command *cmd = jtag_command_queue; + + while (cmd != NULL) { + kitprog_execute_command(cmd); + cmd = cmd->next; + } + + return ERROR_OK; +} + +COMMAND_HANDLER(kitprog_handle_info_command) +{ + int retval = kitprog_get_info(); + + return retval; +} + + +COMMAND_HANDLER(kitprog_handle_acquire_psoc_command) +{ + int retval = kitprog_generic_acquire(); + + return retval; +} + +COMMAND_HANDLER(kitprog_handle_serial_command) +{ + if (CMD_ARGC == 1) { + size_t len = strlen(CMD_ARGV[0]); + kitprog_serial = calloc(len + 1, sizeof(char)); + if (kitprog_serial == NULL) { + LOG_ERROR("Failed to allocate memory for the serial number"); + return ERROR_FAIL; + } + strncpy(kitprog_serial, CMD_ARGV[0], len + 1); + } else { + LOG_ERROR("expected exactly one argument to kitprog_serial <serial-number>"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +COMMAND_HANDLER(kitprog_handle_init_acquire_psoc_command) +{ + kitprog_init_acquire_psoc = true; + + return ERROR_OK; +} + +static const struct command_registration kitprog_subcommand_handlers[] = { + { + .name = "info", + .handler = &kitprog_handle_info_command, + .mode = COMMAND_EXEC, + .usage = "", + .help = "show KitProg info", + }, + { + .name = "acquire_psoc", + .handler = &kitprog_handle_acquire_psoc_command, + .mode = COMMAND_EXEC, + .usage = "", + .help = "try to acquire a PSoC", + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration kitprog_command_handlers[] = { + { + .name = "kitprog", + .mode = COMMAND_ANY, + .help = "perform KitProg management", + .usage = "<cmd>", + .chain = kitprog_subcommand_handlers, + }, + { + .name = "kitprog_serial", + .handler = &kitprog_handle_serial_command, + .mode = COMMAND_CONFIG, + .help = "set the serial number of the adapter", + .usage = "serial_string", + }, + { + .name = "kitprog_init_acquire_psoc", + .handler = &kitprog_handle_init_acquire_psoc_command, + .mode = COMMAND_CONFIG, + .help = "try to acquire a PSoC during init", + .usage = "", + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct swd_driver kitprog_swd = { + .init = kitprog_swd_init, + .switch_seq = kitprog_swd_switch_seq, + .read_reg = kitprog_swd_read_reg, + .write_reg = kitprog_swd_write_reg, + .run = kitprog_swd_run_queue, +}; + +static const char * const kitprog_transports[] = { "swd", NULL }; + +struct jtag_interface kitprog_interface = { + .name = "kitprog", + .commands = kitprog_command_handlers, + .transports = kitprog_transports, + .swd = &kitprog_swd, + .execute_queue = kitprog_execute_queue, + .init = kitprog_init, + .quit = kitprog_quit +}; diff --git a/src/jtag/drivers/libjaylink b/src/jtag/drivers/libjaylink -Subproject d57dee67bc756291b7d8b51d350d1c6213e514f +Subproject 699b7001d34a79c8e7064503dde1bede786fd7f diff --git a/src/jtag/drivers/libusb0_common.c b/src/jtag/drivers/libusb0_common.c index e319751..1825543 100644 --- a/src/jtag/drivers/libusb0_common.c +++ b/src/jtag/drivers/libusb0_common.c @@ -146,7 +146,7 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, unsigned int *usb_read_ep, unsigned int *usb_write_ep, - int bclass, int subclass, int protocol) + int bclass, int subclass, int protocol, int trans_type) { struct jtag_libusb_device *udev = jtag_libusb_get_device(devh); struct usb_interface *iface = udev->config->interface; @@ -157,7 +157,8 @@ int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, for (int i = 0; i < desc->bNumEndpoints; i++) { if ((bclass > 0 && desc->bInterfaceClass != bclass) || (subclass > 0 && desc->bInterfaceSubClass != subclass) || - (protocol > 0 && desc->bInterfaceProtocol != protocol)) + (protocol > 0 && desc->bInterfaceProtocol != protocol) || + (trans_type > 0 && (desc->endpoint[i].bmAttributes & 0x3) != trans_type)) continue; uint8_t epnum = desc->endpoint[i].bEndpointAddress; diff --git a/src/jtag/drivers/libusb0_common.h b/src/jtag/drivers/libusb0_common.h index 7163b43..baa9e3c 100644 --- a/src/jtag/drivers/libusb0_common.h +++ b/src/jtag/drivers/libusb0_common.h @@ -67,7 +67,7 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, unsigned int *usb_read_ep, unsigned int *usb_write_ep, - int bclass, int subclass, int protocol); + int bclass, int subclass, int protocol, int trans_type); int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid); #endif /* OPENOCD_JTAG_DRIVERS_LIBUSB0_COMMON_H */ diff --git a/src/jtag/drivers/libusb1_common.c b/src/jtag/drivers/libusb1_common.c index f8b7c75..89f8092 100644 --- a/src/jtag/drivers/libusb1_common.c +++ b/src/jtag/drivers/libusb1_common.c @@ -187,7 +187,7 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, unsigned int *usb_read_ep, unsigned int *usb_write_ep, - int bclass, int subclass, int protocol) + int bclass, int subclass, int protocol, int trans_type) { struct jtag_libusb_device *udev = jtag_libusb_get_device(devh); const struct libusb_interface *inter; @@ -210,6 +210,8 @@ int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, continue; epdesc = &interdesc->endpoint[k]; + if (trans_type > 0 && (epdesc->bmAttributes & 0x3) != trans_type) + continue; uint8_t epnum = epdesc->bEndpointAddress; bool is_input = epnum & 0x80; diff --git a/src/jtag/drivers/libusb1_common.h b/src/jtag/drivers/libusb1_common.h index fc6526a..7c73d29 100644 --- a/src/jtag/drivers/libusb1_common.h +++ b/src/jtag/drivers/libusb1_common.h @@ -69,12 +69,13 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, * @param bclass `bInterfaceClass` to match, or -1 to ignore this field. * @param subclass `bInterfaceSubClass` to match, or -1 to ignore this field. * @param protocol `bInterfaceProtocol` to match, or -1 to ignore this field. + * @param trans_type `bmAttributes Bits 0..1 Transfer type` to match, or -1 to ignore this field. * @returns Returns ERROR_OK on success, ERROR_FAIL otherwise. */ int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, unsigned int *usb_read_ep, unsigned int *usb_write_ep, - int bclass, int subclass, int protocol); + int bclass, int subclass, int protocol, int trans_type); int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid); #endif /* OPENOCD_JTAG_DRIVERS_LIBUSB1_COMMON_H */ diff --git a/src/jtag/drivers/libusb_common.h b/src/jtag/drivers/libusb_common.h index 563af10..599a0a9 100644 --- a/src/jtag/drivers/libusb_common.h +++ b/src/jtag/drivers/libusb_common.h @@ -19,9 +19,9 @@ #define OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H #ifdef HAVE_LIBUSB1 -#include <libusb1_common.h> +#include "libusb1_common.h" #else -#include <libusb0_common.h> +#include "libusb0_common.h" #endif #endif /* OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H */ diff --git a/src/jtag/drivers/mpsse.c b/src/jtag/drivers/mpsse.c index 0ef88ba..924c974 100644 --- a/src/jtag/drivers/mpsse.c +++ b/src/jtag/drivers/mpsse.c @@ -247,8 +247,8 @@ static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t *vid, con err = libusb_detach_kernel_driver(ctx->usb_dev, ctx->interface); if (err != LIBUSB_SUCCESS && err != LIBUSB_ERROR_NOT_FOUND && err != LIBUSB_ERROR_NOT_SUPPORTED) { - LOG_ERROR("libusb_detach_kernel_driver() failed with %s", libusb_error_name(err)); - goto error; + LOG_WARNING("libusb_detach_kernel_driver() failed with %s, trying to continue anyway", + libusb_error_name(err)); } err = libusb_claim_interface(ctx->usb_dev, ctx->interface); @@ -872,6 +872,8 @@ int mpsse_flush(struct mpsse_ctx *ctx) libusb_fill_bulk_transfer(write_transfer, ctx->usb_dev, ctx->out_ep, ctx->write_buffer, ctx->write_count, write_cb, &write_result, ctx->usb_write_timeout); retval = libusb_submit_transfer(write_transfer); + if (retval != LIBUSB_SUCCESS) + goto error_check; if (ctx->read_count) { read_transfer = libusb_alloc_transfer(0); @@ -879,22 +881,36 @@ int mpsse_flush(struct mpsse_ctx *ctx) ctx->read_chunk_size, read_cb, &read_result, ctx->usb_read_timeout); retval = libusb_submit_transfer(read_transfer); + if (retval != LIBUSB_SUCCESS) + goto error_check; } /* Polling loop, more or less taken from libftdi */ while (!write_result.done || !read_result.done) { - retval = libusb_handle_events(ctx->usb_ctx); + struct timeval timeout_usb; + + timeout_usb.tv_sec = 1; + timeout_usb.tv_usec = 0; + + retval = libusb_handle_events_timeout_completed(ctx->usb_ctx, &timeout_usb, NULL); keep_alive(); - if (retval != LIBUSB_SUCCESS && retval != LIBUSB_ERROR_INTERRUPTED) { + if (retval == LIBUSB_ERROR_NO_DEVICE || retval == LIBUSB_ERROR_INTERRUPTED) + break; + + if (retval != LIBUSB_SUCCESS) { libusb_cancel_transfer(write_transfer); if (read_transfer) libusb_cancel_transfer(read_transfer); - while (!write_result.done || !read_result.done) - if (libusb_handle_events(ctx->usb_ctx) != LIBUSB_SUCCESS) + while (!write_result.done || !read_result.done) { + retval = libusb_handle_events_timeout_completed(ctx->usb_ctx, + &timeout_usb, NULL); + if (retval != LIBUSB_SUCCESS) break; + } } } +error_check: if (retval != LIBUSB_SUCCESS) { LOG_ERROR("libusb_handle_events() failed with %s", libusb_error_name(retval)); retval = ERROR_FAIL; diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c index 157020e..8f11b4b 100644 --- a/src/jtag/drivers/openjtag.c +++ b/src/jtag/drivers/openjtag.c @@ -2,6 +2,10 @@ * Driver for OpenJTAG Project (www.openjtag.org) * * Compatible with libftdi and ftd2xx drivers. * * * + * Cypress CY7C65215 support * + * Copyright (C) 2015 Vianney le Clément de Saint-Marcq, Essensium NV * + * <vianney.leclement@essensium.com> * + * * * Copyright (C) 2010 by Ivan Meleca <mileca@gmail.com> * * * * Copyright (C) 2013 by Ryan Corbin, GlueLogix Inc. <corbin.ryan@gmail.com> * @@ -41,7 +45,18 @@ #include <jtag/interface.h> #include <jtag/commands.h> -#include "usb_common.h" +#include "libusb_common.h" + +static enum { + OPENJTAG_VARIANT_STANDARD, + OPENJTAG_VARIANT_CY7C65215, +} openjtag_variant = OPENJTAG_VARIANT_STANDARD; + +static const char * const openjtag_variant_names[] = { + "standard", + "cy7c65215", + NULL +}; /* * OpenJTAG-OpenOCD state conversion @@ -66,19 +81,8 @@ typedef enum openjtag_tap_state { OPENJTAG_TAP_UPDATE_IR = 15, } openjtag_tap_state_t; -#if (BUILD_OPENJTAG_FTD2XX == 1 && BUILD_OPENJTAG_LIBFTDI == 1) -#error "BUILD_OPENJTAG_FTD2XX && BUILD_OPENJTAG_LIBFTDI " - "are mutually exclusive" -#elif (BUILD_OPENJTAG_FTD2XX != 1 && BUILD_OPENJTAG_LIBFTDI != 1) -#error "BUILD_OPENJTAG_FTD2XX || BUILD_OPENJTAG_LIBFTDI must be chosen" -#endif - /* OPENJTAG access library includes */ -#if BUILD_OPENJTAG_FTD2XX == 1 -#include <ftd2xx.h> -#elif BUILD_OPENJTAG_LIBFTDI == 1 #include <ftdi.h> -#endif /* OpenJTAG vid/pid */ static uint16_t openjtag_vid = 0x0403; @@ -86,12 +90,7 @@ static uint16_t openjtag_pid = 0x6001; static char *openjtag_device_desc; -#if BUILD_OPENJTAG_FTD2XX == 1 -static FT_HANDLE ftdih; - -#elif BUILD_OPENJTAG_LIBFTDI == 1 static struct ftdi_context ftdic; -#endif #define OPENJTAG_BUFFER_SIZE 504 #define OPENJTAG_MAX_PENDING_RESULTS 256 @@ -112,10 +111,24 @@ static uint8_t usb_rx_buf[OPENJTAG_BUFFER_SIZE]; static struct openjtag_scan_result openjtag_scan_result_buffer[OPENJTAG_MAX_PENDING_RESULTS]; static int openjtag_scan_result_count; -/* Openocd usb handler */ -struct openocd { - struct usb_dev_handle *usb_handle; -}; +static jtag_libusb_device_handle *usbh; + +/* CY7C65215 model only */ +#define CY7C65215_JTAG_REQUEST 0x40 /* bmRequestType: vendor host-to-device */ +#define CY7C65215_JTAG_ENABLE 0xD0 /* bRequest: enable JTAG */ +#define CY7C65215_JTAG_DISABLE 0xD1 /* bRequest: disable JTAG */ +#define CY7C65215_JTAG_READ 0xD2 /* bRequest: read buffer */ +#define CY7C65215_JTAG_WRITE 0xD3 /* bRequest: write buffer */ + +#define CY7C65215_USB_TIMEOUT 100 + +static const uint16_t cy7c65215_vids[] = {0x04b4, 0}; +static const uint16_t cy7c65215_pids[] = {0x0007, 0}; + +#define CY7C65215_JTAG_CLASS 0xff +#define CY7C65215_JTAG_SUBCLASS 0x04 + +static unsigned int ep_in, ep_out; #ifdef _DEBUG_USB_COMMS_ @@ -201,26 +214,9 @@ static int8_t openjtag_get_tap_state(int8_t state) } } -static int openjtag_buf_write( +static int openjtag_buf_write_standard( uint8_t *buf, int size, uint32_t *bytes_written) { -#if BUILD_OPENJTAG_FTD2XX == 1 - FT_STATUS status; - DWORD dw_bytes_written; - -#ifdef _DEBUG_USB_COMMS_ - openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE); -#endif - - status = FT_Write(ftdih, buf, size, &dw_bytes_written); - if (status != FT_OK) { - *bytes_written = dw_bytes_written; - LOG_ERROR("FT_Write returned: %u", status); - return ERROR_JTAG_DEVICE_ERROR; - } - *bytes_written = dw_bytes_written; - return ERROR_OK; -#elif BUILD_OPENJTAG_LIBFTDI == 1 int retval; #ifdef _DEBUG_USB_COMMS_ openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE); @@ -236,36 +232,56 @@ static int openjtag_buf_write( *bytes_written += retval; return ERROR_OK; -#endif } -static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read) +static int openjtag_buf_write_cy7c65215( + uint8_t *buf, int size, uint32_t *bytes_written) { + int ret; -#if BUILD_OPENJTAG_FTD2XX == 1 - DWORD dw_bytes_read; - FT_STATUS status; - int timeout = 50; +#ifdef _DEBUG_USB_COMMS_ + openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE); +#endif - *bytes_read = 0; - while (qty && (*bytes_read < qty) && timeout--) { + if (size == 0) { + *bytes_written = 0; + return ERROR_OK; + } - status = FT_Read(ftdih, buf + *bytes_read, - qty - *bytes_read, &dw_bytes_read); - if (status != FT_OK) { - *bytes_read = dw_bytes_read; - LOG_ERROR("FT_Read returned: %u", status); - return ERROR_JTAG_DEVICE_ERROR; - } - *bytes_read += dw_bytes_read; + ret = jtag_libusb_control_transfer(usbh, CY7C65215_JTAG_REQUEST, + CY7C65215_JTAG_WRITE, size, 0, + NULL, 0, CY7C65215_USB_TIMEOUT); + if (ret < 0) { + LOG_ERROR("vendor command failed, error %d", ret); + return ERROR_JTAG_DEVICE_ERROR; } -#ifdef _DEBUG_USB_COMMS_ - openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ); -#endif + ret = jtag_libusb_bulk_write(usbh, ep_out, (char *)buf, size, + CY7C65215_USB_TIMEOUT); + if (ret < 0) { + LOG_ERROR("bulk write failed, error %d", ret); + return ERROR_JTAG_DEVICE_ERROR; + } + *bytes_written = ret; return ERROR_OK; -#elif BUILD_OPENJTAG_LIBFTDI == 1 +} + +static int openjtag_buf_write( + uint8_t *buf, int size, uint32_t *bytes_written) +{ + switch (openjtag_variant) { + case OPENJTAG_VARIANT_CY7C65215: + return openjtag_buf_write_cy7c65215(buf, size, bytes_written); + default: + return openjtag_buf_write_standard(buf, size, bytes_written); + } +} + +static int openjtag_buf_read_standard( + uint8_t *buf, uint32_t qty, uint32_t *bytes_read) +{ + int retval; int timeout = 5; @@ -287,10 +303,53 @@ static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read) openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ); #endif + return ERROR_OK; +} + +static int openjtag_buf_read_cy7c65215( + uint8_t *buf, uint32_t qty, uint32_t *bytes_read) +{ + int ret; + + if (qty == 0) { + *bytes_read = 0; + goto out; + } + + ret = jtag_libusb_control_transfer(usbh, CY7C65215_JTAG_REQUEST, + CY7C65215_JTAG_READ, qty, 0, + NULL, 0, CY7C65215_USB_TIMEOUT); + if (ret < 0) { + LOG_ERROR("vendor command failed, error %d", ret); + return ERROR_JTAG_DEVICE_ERROR; + } + + ret = jtag_libusb_bulk_read(usbh, ep_in, (char *)buf, qty, + CY7C65215_USB_TIMEOUT); + if (ret < 0) { + LOG_ERROR("bulk read failed, error %d", ret); + return ERROR_JTAG_DEVICE_ERROR; + } + *bytes_read = ret; + +out: +#ifdef _DEBUG_USB_COMMS_ + openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ); #endif + return ERROR_OK; } +static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read) +{ + switch (openjtag_variant) { + case OPENJTAG_VARIANT_CY7C65215: + return openjtag_buf_read_cy7c65215(buf, qty, bytes_read); + default: + return openjtag_buf_read_standard(buf, qty, bytes_read); + } +} + static int openjtag_sendcommand(uint8_t cmd) { uint32_t written; @@ -335,109 +394,17 @@ static int openjtag_speed(int speed) return ERROR_OK; } -static int openjtag_init(void) +static int openjtag_init_standard(void) { uint8_t latency_timer; -#if BUILD_OPENJTAG_FTD2XX == 1 - FT_STATUS status; -#endif - -usb_tx_buf_offs = 0; -usb_rx_buf_len = 0; -openjtag_scan_result_count = 0; - -#if BUILD_OPENJTAG_FTD2XX == 1 - LOG_DEBUG("'openjtag' interface using FTD2XX"); -#elif BUILD_OPENJTAG_LIBFTDI == 1 - LOG_DEBUG("'openjtag' interface using libftdi"); -#endif - -/* Open by device description */ -if (openjtag_device_desc == NULL) { - LOG_WARNING("no openjtag device description specified, " + /* Open by device description */ + if (openjtag_device_desc == NULL) { + LOG_WARNING("no openjtag device description specified, " "using default 'Open JTAG Project'"); - openjtag_device_desc = "Open JTAG Project"; -} - -#if BUILD_OPENJTAG_FTD2XX == 1 - -#if IS_WIN32 == 0 - /* Add non-standard Vid/Pid to the linux driver */ - status = FT_SetVIDPID(openjtag_vid, openjtag_pid); - if (status != FT_OK) { - LOG_WARNING("couldn't add %4.4x:%4.4x", - openjtag_vid, openjtag_pid); - } -#endif - - status = FT_OpenEx(openjtag_device_desc, FT_OPEN_BY_DESCRIPTION, - &ftdih); - if (status != FT_OK) { - DWORD num_devices; - - LOG_ERROR("unable to open ftdi device: %u", status); - status = FT_ListDevices(&num_devices, NULL, - FT_LIST_NUMBER_ONLY); - if (status == FT_OK) { - char **desc_array = malloc(sizeof(char *) - * (num_devices + 1)); - unsigned int i; - - for (i = 0; i < num_devices; i++) - desc_array[i] = malloc(64); - desc_array[num_devices] = NULL; - - status = FT_ListDevices(desc_array, &num_devices, - FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION); - - if (status == FT_OK) { - LOG_ERROR("ListDevices: %u\n", num_devices); - for (i = 0; i < num_devices; i++) - LOG_ERROR("%i: %s", i, desc_array[i]); - } - - for (i = 0; i < num_devices; i++) - free(desc_array[i]); - free(desc_array); - } else { - LOG_ERROR("ListDevices: NONE\n"); - } - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_SetLatencyTimer(ftdih, 2); - if (status != FT_OK) { - LOG_ERROR("unable to set latency timer: %u", status); - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_GetLatencyTimer(ftdih, &latency_timer); - if (status != FT_OK) { - LOG_ERROR("unable to get latency timer: %u", status); - return ERROR_JTAG_INIT_FAILED; - } - LOG_DEBUG("current latency timer: %i", latency_timer); - - status = FT_SetBitMode(ftdih, 0x00, 0x40); - if (status != FT_OK) { - LOG_ERROR("unable to disable bit i/o mode: %u", status); - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_SetTimeouts(ftdih, 50, 0); - if (status != FT_OK) { - LOG_ERROR("unable to set timeouts: %u", status); - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX); - if (status != FT_OK) { - LOG_ERROR("unable to FT_Purge() %u", status); - return ERROR_JTAG_INIT_FAILED; + openjtag_device_desc = "Open JTAG Project"; } -#elif BUILD_OPENJTAG_LIBFTDI == 1 if (ftdi_init(&ftdic) < 0) return ERROR_JTAG_INIT_FAILED; @@ -470,40 +437,109 @@ if (openjtag_device_desc == NULL) { ftdi_get_error_string(&ftdic)); return ERROR_JTAG_DEVICE_ERROR; } -#endif -#if BUILD_OPENJTAG_FTD2XX == 1 - status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX); - if (status != FT_OK) - return ERROR_JTAG_INIT_FAILED; -#elif BUILD_OPENJTAG_LIBFTDI == 1 if (ftdi_usb_purge_buffers(&ftdic) < 0) { LOG_ERROR("ftdi_purge_buffers: %s", ftdic.error_str); return ERROR_JTAG_INIT_FAILED; } -#endif - /* OpenJTAG speed */ - openjtag_sendcommand(0xE0); /*Start at slowest adapter speed*/ + return ERROR_OK; +} + +static int openjtag_init_cy7c65215(void) +{ + int ret; + + usbh = NULL; + ret = jtag_libusb_open(cy7c65215_vids, cy7c65215_pids, NULL, &usbh); + if (ret != ERROR_OK) { + LOG_ERROR("unable to open cy7c65215 device"); + goto err; + } + + ret = jtag_libusb_choose_interface(usbh, &ep_in, &ep_out, + CY7C65215_JTAG_CLASS, + CY7C65215_JTAG_SUBCLASS, -1, LIBUSB_TRANSFER_TYPE_BULK); + if (ret != ERROR_OK) { + LOG_ERROR("unable to claim JTAG interface"); + goto err; + } - /* MSB */ - openjtag_sendcommand(0x75); + ret = jtag_libusb_control_transfer(usbh, + CY7C65215_JTAG_REQUEST, + CY7C65215_JTAG_ENABLE, + 0, 0, NULL, 0, CY7C65215_USB_TIMEOUT); + if (ret < 0) { + LOG_ERROR("could not enable JTAG module"); + goto err; + } return ERROR_OK; + +err: + if (usbh != NULL) + jtag_libusb_close(usbh); + return ERROR_JTAG_INIT_FAILED; } -static int openjtag_quit(void) +static int openjtag_init(void) +{ + int ret; + + usb_tx_buf_offs = 0; + usb_rx_buf_len = 0; + openjtag_scan_result_count = 0; + + switch (openjtag_variant) { + case OPENJTAG_VARIANT_CY7C65215: + ret = openjtag_init_cy7c65215(); + break; + default: + ret = openjtag_init_standard(); + } + if (ret != ERROR_OK) + return ret; + + openjtag_speed(375); /* Start at slowest adapter speed */ + openjtag_sendcommand(0x75); /* MSB */ + + return ERROR_OK; +} + +static int openjtag_quit_standard(void) { -#if BUILD_OPENJTAG_FTD2XX == 1 - FT_Close(ftdih); -#elif BUILD_OPENJTAG_LIBFTDI == 1 ftdi_usb_close(&ftdic); ftdi_deinit(&ftdic); -#endif return ERROR_OK; } +static int openjtag_quit_cy7c65215(void) +{ + int ret; + + ret = jtag_libusb_control_transfer(usbh, + CY7C65215_JTAG_REQUEST, + CY7C65215_JTAG_DISABLE, + 0, 0, NULL, 0, CY7C65215_USB_TIMEOUT); + if (ret < 0) + LOG_WARNING("could not disable JTAG module"); + + jtag_libusb_close(usbh); + + return ERROR_OK; +} + +static int openjtag_quit(void) +{ + switch (openjtag_variant) { + case OPENJTAG_VARIANT_CY7C65215: + return openjtag_quit_cy7c65215(); + default: + return openjtag_quit_standard(); + } +} + static void openjtag_write_tap_buffer(void) { uint32_t written; @@ -536,8 +572,8 @@ static int openjtag_execute_tap_queue(void) uint8_t *buffer = openjtag_scan_result_buffer[res_count].buffer; - while (len) { - if (len <= 8) { + while (len > 0) { + if (len <= 8 && openjtag_variant != OPENJTAG_VARIANT_CY7C65215) { DEBUG_JTAG_IO("bits < 8 buf = 0x%X, will be 0x%X", usb_rx_buf[rx_offs], usb_rx_buf[rx_offs] >> (8 - len)); buffer[count] = usb_rx_buf[rx_offs] >> (8 - len); @@ -724,11 +760,14 @@ static void openjtag_execute_runtest(struct jtag_command *cmd) if (cmd->cmd.runtest->num_cycles > 16) LOG_WARNING("num_cycles > 16 on run test"); - uint8_t command; - command = 7; - command |= ((cmd->cmd.runtest->num_cycles - 1) & 0x0F) << 4; + if (openjtag_variant != OPENJTAG_VARIANT_CY7C65215 || + cmd->cmd.runtest->num_cycles) { + uint8_t command; + command = 7; + command |= ((cmd->cmd.runtest->num_cycles - 1) & 0x0F) << 4; - openjtag_add_byte(command); + openjtag_add_byte(command); + } tap_set_end_state(end_state); if (tap_get_end_state() != tap_get_state()) { @@ -816,6 +855,24 @@ COMMAND_HANDLER(openjtag_handle_device_desc_command) return ERROR_OK; } +COMMAND_HANDLER(openjtag_handle_variant_command) +{ + if (CMD_ARGC == 1) { + const char * const *name = openjtag_variant_names; + int variant = 0; + for (; *name; name++, variant++) { + if (strcasecmp(CMD_ARGV[0], *name) == 0) { + openjtag_variant = variant; + return ERROR_OK; + } + } + LOG_ERROR("unknown openjtag variant '%s'", CMD_ARGV[0]); + } else { + LOG_ERROR("require exactly one argument to " + "openjtag_variant <variant>"); + } + return ERROR_OK; +} static const struct command_registration openjtag_command_handlers[] = { { @@ -825,6 +882,13 @@ static const struct command_registration openjtag_command_handlers[] = { .help = "set the USB device description of the OpenJTAG", .usage = "description-string", }, + { + .name = "openjtag_variant", + .handler = openjtag_handle_variant_command, + .mode = COMMAND_CONFIG, + .help = "set the OpenJTAG variant", + .usage = "variant-string", + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/jtag/drivers/presto.c b/src/jtag/drivers/presto.c index 0a18dc9..49caa67 100644 --- a/src/jtag/drivers/presto.c +++ b/src/jtag/drivers/presto.c @@ -34,14 +34,7 @@ #include "bitq.h" /* PRESTO access library includes */ -#if BUILD_PRESTO_FTD2XX == 1 -#include <ftd2xx.h> -#include "ftd2xx_common.h" -#elif BUILD_PRESTO_LIBFTDI == 1 #include <ftdi.h> -#else -#error "BUG: either FTD2XX and LIBFTDI has to be used" -#endif /* -------------------------------------------------------------------------- */ @@ -55,13 +48,8 @@ #define BUFFER_SIZE (64*62) struct presto { -#if BUILD_PRESTO_FTD2XX == 1 - FT_HANDLE handle; - FT_STATUS status; -#elif BUILD_PRESTO_LIBFTDI == 1 struct ftdi_context ftdic; int retval; -#endif char serial[FT_DEVICE_SERNUM_LEN]; @@ -95,15 +83,6 @@ static uint8_t presto_init_seq[] = { static int presto_write(uint8_t *buf, uint32_t size) { -#if BUILD_PRESTO_FTD2XX == 1 - DWORD ftbytes; - presto->status = FT_Write(presto->handle, buf, size, &ftbytes); - if (presto->status != FT_OK) { - LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(presto->status)); - return ERROR_JTAG_DEVICE_ERROR; - } - -#elif BUILD_PRESTO_LIBFTDI == 1 uint32_t ftbytes; presto->retval = ftdi_write_data(&presto->ftdic, buf, size); if (presto->retval < 0) { @@ -111,7 +90,6 @@ static int presto_write(uint8_t *buf, uint32_t size) return ERROR_JTAG_DEVICE_ERROR; } ftbytes = presto->retval; -#endif if (ftbytes != size) { LOG_ERROR("couldn't write the requested number of bytes to PRESTO (%u < %u)", @@ -124,15 +102,6 @@ static int presto_write(uint8_t *buf, uint32_t size) static int presto_read(uint8_t *buf, uint32_t size) { -#if BUILD_PRESTO_FTD2XX == 1 - DWORD ftbytes; - presto->status = FT_Read(presto->handle, buf, size, &ftbytes); - if (presto->status != FT_OK) { - LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(presto->status)); - return ERROR_JTAG_DEVICE_ERROR; - } - -#elif BUILD_PRESTO_LIBFTDI == 1 uint32_t ftbytes = 0; struct timeval timeout, now; @@ -152,7 +121,6 @@ static int presto_read(uint8_t *buf, uint32_t size) ((now.tv_sec == timeout.tv_sec) && (now.tv_usec > timeout.tv_usec))) break; } -#endif if (ftbytes != size) { /* this is just a warning, there might have been timeout when detecting PRESTO, @@ -165,150 +133,6 @@ static int presto_read(uint8_t *buf, uint32_t size) return ERROR_OK; } -#if BUILD_PRESTO_FTD2XX == 1 -static int presto_open_ftd2xx(char *req_serial) -{ - uint32_t i; - DWORD numdevs; - DWORD vidpid; - char devname[FT_DEVICE_NAME_LEN]; - FT_DEVICE device; - - BYTE presto_data; - DWORD ftbytes; - - presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE; - -#if IS_WIN32 == 0 - /* Add non-standard Vid/Pid to the linux driver */ - presto->status = FT_SetVIDPID(PRESTO_VID, PRESTO_PID); - if (presto->status != FT_OK) { - LOG_ERROR("couldn't add PRESTO VID/PID"); - exit(-1); - } -#endif - - presto->status = FT_ListDevices(&numdevs, NULL, FT_LIST_NUMBER_ONLY); - if (presto->status != FT_OK) { - LOG_ERROR("FT_ListDevices failed: %s", ftd2xx_status_string(presto->status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - LOG_DEBUG("FTDI devices available: %" PRIu32, (uint32_t)numdevs); - for (i = 0; i < numdevs; i++) { - presto->status = FT_Open(i, &(presto->handle)); - if (presto->status != FT_OK) { - /* this is not fatal, the device may be legitimately open by other process, - *hence debug message only */ - LOG_DEBUG("FT_Open failed: %s", ftd2xx_status_string(presto->status)); - continue; - } - LOG_DEBUG("FTDI device %i open", (int)i); - - presto->status = FT_GetDeviceInfo(presto->handle, &device, - &vidpid, presto->serial, devname, NULL); - if (presto->status == FT_OK) { - if (vidpid == PRESTO_VID_PID && (req_serial == NULL || - !strcmp(presto->serial, req_serial))) - break; - } else - LOG_DEBUG("FT_GetDeviceInfo failed: %s", ftd2xx_status_string( - presto->status)); - - LOG_DEBUG("FTDI device %i does not match, closing", (int)i); - FT_Close(presto->handle); - presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE; - } - - if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE) - return ERROR_JTAG_DEVICE_ERROR; /* presto not open, return */ - - presto->status = FT_SetLatencyTimer(presto->handle, 1); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - presto->status = FT_SetTimeouts(presto->handle, 100, 0); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - presto_data = 0xD0; - presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - /* delay between first write/read turnaround (after purge?) necessary - * under Linux for unknown reason, - * probably a bug in library threading */ - usleep(100000); - presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - if (ftbytes != 1) { - LOG_DEBUG("PRESTO reset"); - - presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - presto->status = FT_SetBitMode(presto->handle, 0x80, 1); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - presto->status = FT_SetBaudRate(presto->handle, 9600); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - presto_data = 0; - for (i = 0; i < 4 * 62; i++) { - presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - } - usleep(100000); - - presto->status = FT_SetBitMode(presto->handle, 0x00, 0); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - presto_data = 0xD0; - presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - /* delay between first write/read turnaround (after purge?) necessary under Linux for unknown reason, - probably a bug in library threading */ - usleep(100000); - presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - if (ftbytes != 1) { - LOG_DEBUG("PRESTO not responding"); - return ERROR_JTAG_DEVICE_ERROR; - } - } - - presto->status = FT_SetTimeouts(presto->handle, 0, 0); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - presto->status = FT_Write(presto->handle, &presto_init_seq, - sizeof(presto_init_seq), &ftbytes); - - if (presto->status != FT_OK || ftbytes != sizeof(presto_init_seq)) - return ERROR_JTAG_DEVICE_ERROR; - - return ERROR_OK; -} - -#elif BUILD_PRESTO_LIBFTDI == 1 static int presto_open_libftdi(char *req_serial) { uint8_t presto_data; @@ -371,7 +195,6 @@ static int presto_open_libftdi(char *req_serial) return ERROR_OK; } -#endif /* BUILD_PRESTO_LIBFTDI == 1 */ static int presto_open(char *req_serial) { @@ -391,11 +214,7 @@ static int presto_open(char *req_serial) presto->jtag_speed = 0; -#if BUILD_PRESTO_FTD2XX == 1 - return presto_open_ftd2xx(req_serial); -#elif BUILD_PRESTO_LIBFTDI == 1 return presto_open_libftdi(req_serial); -#endif } static int presto_close(void) @@ -403,35 +222,6 @@ static int presto_close(void) int result = ERROR_OK; -#if BUILD_PRESTO_FTD2XX == 1 - DWORD ftbytes; - - if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE) - return result; - - presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX); - if (presto->status != FT_OK) - result = ERROR_JTAG_DEVICE_ERROR; - - presto->status = FT_Write(presto->handle, - &presto_init_seq, - sizeof(presto_init_seq), - &ftbytes); - if (presto->status != FT_OK || ftbytes != sizeof(presto_init_seq)) - result = ERROR_JTAG_DEVICE_ERROR; - - presto->status = FT_SetLatencyTimer(presto->handle, 16); - if (presto->status != FT_OK) - result = ERROR_JTAG_DEVICE_ERROR; - - presto->status = FT_Close(presto->handle); - if (presto->status != FT_OK) - result = ERROR_JTAG_DEVICE_ERROR; - else - presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE; - -#elif BUILD_PRESTO_LIBFTDI == 1 - presto->retval = ftdi_write_data(&presto->ftdic, presto_init_seq, sizeof(presto_init_seq)); if (presto->retval != sizeof(presto_init_seq)) result = ERROR_JTAG_DEVICE_ERROR; @@ -445,7 +235,6 @@ static int presto_close(void) result = ERROR_JTAG_DEVICE_ERROR; else ftdi_deinit(&presto->ftdic); -#endif return result; } @@ -455,11 +244,7 @@ static int presto_flush(void) if (presto->buff_out_pos == 0) return ERROR_OK; -#if BUILD_PRESTO_FTD2XX == 1 - if (presto->status != FT_OK) { -#elif BUILD_PRESTO_LIBFTDI == 1 if (presto->retval < 0) { -#endif LOG_DEBUG("error in previous communication, canceling I/O operation"); return ERROR_JTAG_DEVICE_ERROR; } @@ -502,13 +287,9 @@ static int presto_sendbyte(int data) } else return ERROR_JTAG_DEVICE_ERROR; -#if BUILD_PRESTO_FTD2XX == 1 - if (presto->buff_out_pos >= BUFFER_SIZE) -#elif BUILD_PRESTO_LIBFTDI == 1 /* libftdi does not do background read, be sure that USB IN buffer does not overflow (128 *bytes only!) */ if (presto->buff_out_pos >= BUFFER_SIZE || presto->buff_in_exp == 128) -#endif return presto_flush(); return ERROR_OK; diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 699c41f..0bdcd31 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -216,7 +216,7 @@ struct stlink_usb_handle_s { #define STLINK_DEBUG_APIV2_DRIVE_NRST_HIGH 0x01 #define STLINK_DEBUG_APIV2_DRIVE_NRST_PULSE 0x02 -#define STLINK_TRACE_SIZE 1024 +#define STLINK_TRACE_SIZE 4096 #define STLINK_TRACE_MAX_HZ 2000000 #define STLINK_TRACE_MIN_VERSION 13 diff --git a/src/jtag/drivers/ti_icdi_usb.c b/src/jtag/drivers/ti_icdi_usb.c index 3db03b0..171ac66 100644 --- a/src/jtag/drivers/ti_icdi_usb.c +++ b/src/jtag/drivers/ti_icdi_usb.c @@ -242,7 +242,8 @@ static int icdi_send_remote_cmd(void *handle, const char *data) struct icdi_usb_handle_s *h = handle; size_t cmd_len = sprintf(h->write_buffer, PACKET_START "qRcmd,"); - cmd_len += hexify(h->write_buffer + cmd_len, data, 0, h->max_packet - cmd_len); + cmd_len += hexify(h->write_buffer + cmd_len, (const uint8_t *)data, + strlen(data), h->max_packet - cmd_len); return icdi_send_packet(handle, cmd_len); } @@ -266,7 +267,7 @@ static int icdi_get_cmd_result(void *handle) if (h->read_buffer[offset] == 'E') { /* get error code */ - char result; + uint8_t result; if (unhexify(&result, h->read_buffer + offset + 1, 1) != 1) return ERROR_FAIL; return result; @@ -328,7 +329,7 @@ static int icdi_usb_version(void *handle) } /* convert reply */ - if (unhexify(version, h->read_buffer + 2, 4) != 4) { + if (unhexify((uint8_t *)version, h->read_buffer + 2, 4) != 4) { LOG_WARNING("unable to get ICDI version"); return ERROR_OK; } @@ -495,7 +496,7 @@ static int icdi_usb_read_reg(void *handle, int num, uint32_t *val) /* convert result */ uint8_t buf[4]; - if (unhexify((char *)buf, h->read_buffer + 2, 4) != 4) { + if (unhexify(buf, h->read_buffer + 2, 4) != 4) { LOG_ERROR("failed to convert result"); return ERROR_FAIL; } @@ -512,7 +513,7 @@ static int icdi_usb_write_reg(void *handle, int num, uint32_t val) h_u32_to_le(buf, val); int cmd_len = snprintf(cmd, sizeof(cmd), "P%x=", num); - hexify(cmd + cmd_len, (const char *)buf, 4, sizeof(cmd)); + hexify(cmd + cmd_len, buf, 4, sizeof(cmd)); result = icdi_send_cmd(handle, cmd); if (result != ERROR_OK) diff --git a/src/jtag/drivers/ulink.c b/src/jtag/drivers/ulink.c index c319a11..550df1c 100644 --- a/src/jtag/drivers/ulink.c +++ b/src/jtag/drivers/ulink.c @@ -2066,7 +2066,7 @@ static int ulink_khz(int khz, int *jtag_speed) } #ifdef _DEBUG_JTAG_IO_ - long f_tck, f_tms, f_scan_in, f_scan_out, f_scan_io; + long f_tck = 0, f_tms = 0, f_scan_in = 0, f_scan_out = 0, f_scan_io = 0; ulink_calculate_frequency(DELAY_CLOCK_TCK, ulink_handle->delay_clock_tck, &f_tck); diff --git a/src/jtag/drivers/usb_blaster/Makefile.am b/src/jtag/drivers/usb_blaster/Makefile.am index 0fb4700..a6694c5 100644 --- a/src/jtag/drivers/usb_blaster/Makefile.am +++ b/src/jtag/drivers/usb_blaster/Makefile.am @@ -1,24 +1,13 @@ -include $(top_srcdir)/common.mk +noinst_LTLIBRARIES += %D%/libocdusbblaster.la +%C%_libocdusbblaster_la_SOURCES = $(USB_BLASTER_SRC) +%C%_libocdusbblaster_la_CPPFLAGS = -I$(top_srcdir)/src/jtag/drivers $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) $(LIBFTDI_CFLAGS) -AM_CPPFLAGS += -I$(top_srcdir)/src/jtag/drivers $(LIBUSB1_CFLAGS) $(LIBFTDI_CFLAGS) +USB_BLASTER_SRC = %D%/usb_blaster.c %D%/ublast_access.h -noinst_LTLIBRARIES = libocdusbblaster.la -libocdusbblaster_la_SOURCES = $(USB_BLASTER_SRC) - -USB_BLASTER_SRC = usb_blaster.c - -if USB_BLASTER_LIBFTDI -USB_BLASTER_SRC += ublast_access_ftdi.c -endif - -if USB_BLASTER_FTD2XX -USB_BLASTER_SRC += ublast_access_ftd2xx.c +if USB_BLASTER +USB_BLASTER_SRC += %D%/ublast_access_ftdi.c endif if USB_BLASTER_2 -USB_BLASTER_SRC += ublast2_access_libusb.c +USB_BLASTER_SRC += %D%/ublast2_access_libusb.c endif - -noinst_HEADERS = ublast_access.h - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in diff --git a/src/jtag/drivers/usb_blaster/ublast_access.h b/src/jtag/drivers/usb_blaster/ublast_access.h index 00349d2..252f003 100644 --- a/src/jtag/drivers/usb_blaster/ublast_access.h +++ b/src/jtag/drivers/usb_blaster/ublast_access.h @@ -56,19 +56,16 @@ struct ublast_lowlevel { /** * ublast_register_ftdi - get a lowlevel USB Blaster driver - * ublast_register_ftd2xx - get a lowlevel USB Blaster driver * ublast2_register_libusb - get a lowlevel USB Blaster II driver * - * Get a lowlevel USB-Blaster driver. In the current implementation, there are 3 + * Get a lowlevel USB-Blaster driver. In the current implementation, there are 2 * possible lowlevel drivers : - * - one based on libftdi from ftdichip.com - * - one based on libftdxx, the free alternative + * - one based on libftdi, * - one based on libusb, specific to the USB-Blaster II * * Returns the lowlevel driver structure. */ extern struct ublast_lowlevel *ublast_register_ftdi(void); -extern struct ublast_lowlevel *ublast_register_ftd2xx(void); extern struct ublast_lowlevel *ublast2_register_libusb(void); #endif /* OPENOCD_JTAG_DRIVERS_USB_BLASTER_UBLAST_ACCESS_H */ diff --git a/src/jtag/drivers/usb_blaster/ublast_access_ftd2xx.c b/src/jtag/drivers/usb_blaster/ublast_access_ftd2xx.c deleted file mode 100644 index ffcf312..0000000 --- a/src/jtag/drivers/usb_blaster/ublast_access_ftd2xx.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Driver for USB-JTAG, Altera USB-Blaster and compatibles - * - * Inspired from original code from Kolja Waschk's USB-JTAG project - * (http://www.ixo.de/info/usb_jtag/), and from openocd project. - * - * Copyright (C) 2012 Robert Jarzmik robert.jarzmik@free.fr - * Copyright (C) 2011 Ali Lown ali@lown.me.uk - * Copyright (C) 2009 Catalin Patulea cat@vv.carleton.ca - * Copyright (C) 2006 Kolja Waschk usbjtag@ixo.de - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * 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, see <http://www.gnu.org/licenses/>. - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <jtag/interface.h> -#include <jtag/commands.h> - -#include "ublast_access.h" - -#include <ftd2xx.h> -#include "jtag/drivers/ftd2xx_common.h" - -static FT_HANDLE *ublast_getftdih(struct ublast_lowlevel *low) -{ - return low->priv; -} - -static int ublast_ftd2xx_write(struct ublast_lowlevel *low, uint8_t *buf, int size, - uint32_t *bytes_written) -{ - FT_STATUS status; - DWORD dw_bytes_written; - FT_HANDLE *ftdih = ublast_getftdih(low); - - status = FT_Write(*ftdih, buf, size, &dw_bytes_written); - if (status != FT_OK) { - *bytes_written = dw_bytes_written; - LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - *bytes_written = dw_bytes_written; - return ERROR_OK; -} - -static int ublast_ftd2xx_read(struct ublast_lowlevel *low, uint8_t *buf, - unsigned size, uint32_t *bytes_read) -{ - DWORD dw_bytes_read; - FT_STATUS status; - FT_HANDLE *ftdih = ublast_getftdih(low); - - status = FT_Read(*ftdih, buf, size, &dw_bytes_read); - if (status != FT_OK) { - *bytes_read = dw_bytes_read; - LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - *bytes_read = dw_bytes_read; - return ERROR_OK; -} - -static int ublast_ftd2xx_init(struct ublast_lowlevel *low) -{ - FT_STATUS status; - FT_HANDLE *ftdih = ublast_getftdih(low); - uint8_t latency_timer; - - LOG_INFO("usb blaster interface using FTD2XX"); - /* Open by device description */ - if (low->ublast_device_desc == NULL) { - LOG_WARNING("no usb blaster device description specified, " - "using default 'USB-Blaster'"); - low->ublast_device_desc = "USB-Blaster"; - } - -#if IS_WIN32 == 0 - /* Add non-standard Vid/Pid to the linux driver */ - status = FT_SetVIDPID(low->ublast_vid, low->ublast_pid); - if (status != FT_OK) { - LOG_WARNING("couldn't add %4.4x:%4.4x", - low->ublast_vid, low->ublast_pid); - } -#endif - status = FT_OpenEx(low->ublast_device_desc, FT_OPEN_BY_DESCRIPTION, - ftdih); - if (status != FT_OK) { - DWORD num_devices; - - LOG_ERROR("unable to open ftdi device: %s", - ftd2xx_status_string(status)); - status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY); - if (status == FT_OK) { - char **desc_array = - malloc(sizeof(char *) * (num_devices + 1)); - unsigned int i; - - for (i = 0; i < num_devices; i++) - desc_array[i] = malloc(64); - desc_array[num_devices] = NULL; - - status = FT_ListDevices(desc_array, &num_devices, - FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION); - - if (status == FT_OK) { - LOG_ERROR("ListDevices: %" PRIu32, (uint32_t)num_devices); - for (i = 0; i < num_devices; i++) - LOG_ERROR("%i: %s", i, desc_array[i]); - } - - for (i = 0; i < num_devices; i++) - free(desc_array[i]); - free(desc_array); - } else { - printf("ListDevices: NONE\n"); - } - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_SetLatencyTimer(*ftdih, 2); - if (status != FT_OK) { - LOG_ERROR("unable to set latency timer: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_GetLatencyTimer(*ftdih, &latency_timer); - if (status != FT_OK) - LOG_ERROR("unable to get latency timer: %s", - ftd2xx_status_string(status)); - else - LOG_DEBUG("current latency timer: %i", latency_timer); - - status = FT_SetBitMode(*ftdih, 0x00, 0); - if (status != FT_OK) { - LOG_ERROR("unable to disable bit i/o mode: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_INIT_FAILED; - } - return ERROR_OK; -} - -static int ublast_ftd2xx_quit(struct ublast_lowlevel *low) -{ - FT_HANDLE *ftdih = ublast_getftdih(low); - - FT_Close(*ftdih); - return ERROR_OK; -} - -static struct ublast_lowlevel_priv { - FT_HANDLE ftdih; -} info; - -static struct ublast_lowlevel low = { - .open = ublast_ftd2xx_init, - .close = ublast_ftd2xx_quit, - .read = ublast_ftd2xx_read, - .write = ublast_ftd2xx_write, - .priv = &info, -}; - -struct ublast_lowlevel *ublast_register_ftd2xx(void) -{ - return &low; -} diff --git a/src/jtag/drivers/usb_blaster/usb_blaster.c b/src/jtag/drivers/usb_blaster/usb_blaster.c index 8f3f327..a975bd1 100644 --- a/src/jtag/drivers/usb_blaster/usb_blaster.c +++ b/src/jtag/drivers/usb_blaster/usb_blaster.c @@ -147,12 +147,9 @@ struct drvs_map { }; static struct drvs_map lowlevel_drivers_map[] = { -#if BUILD_USB_BLASTER_LIBFTDI +#if BUILD_USB_BLASTER { .name = "ftdi", .drv_register = ublast_register_ftdi }, #endif -#if BUILD_USB_BLASTER_FTD2XX - { .name = "ftd2xx", .drv_register = ublast_register_ftd2xx }, -#endif #if BUILD_USB_BLASTER_2 { .name = "ublast2", .drv_register = ublast2_register_libusb }, #endif @@ -1048,8 +1045,8 @@ static const struct command_registration ublast_command_handlers[] = { .name = "usb_blaster_lowlevel_driver", .handler = ublast_handle_lowlevel_drv_command, .mode = COMMAND_CONFIG, - .help = "set the lowlevel access for the USB Blaster (ftdi, ftd2xx, ublast2)", - .usage = "(ftdi|ftd2xx|ublast2)", + .help = "set the lowlevel access for the USB Blaster (ftdi, ublast2)", + .usage = "(ftdi|ublast2)", }, { .name = "usb_blaster_pin", diff --git a/src/jtag/hla/Makefile.am b/src/jtag/hla/Makefile.am index 4fbc70e..6bb2960 100644 --- a/src/jtag/hla/Makefile.am +++ b/src/jtag/hla/Makefile.am @@ -1,23 +1,11 @@ -include $(top_srcdir)/common.mk - -noinst_LTLIBRARIES = libocdhla.la - -libocdhla_la_SOURCES = \ - $(HLFILES) - -HLFILES = - -if HLADAPTER -HLFILES += hla_transport.c -HLFILES += hla_tcl.c -HLFILES += hla_interface.c -HLFILES += hla_layout.c -endif - -noinst_HEADERS = \ - hla_interface.h \ - hla_layout.h \ - hla_tcl.h \ - hla_transport.h - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +noinst_LTLIBRARIES += %D%/libocdhla.la + +%C%_libocdhla_la_SOURCES = \ + %D%/hla_transport.c \ + %D%/hla_tcl.c \ + %D%/hla_interface.c \ + %D%/hla_layout.c \ + %D%/hla_transport.h \ + %D%/hla_interface.h \ + %D%/hla_layout.h \ + %D%/hla_tcl.h diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index 64fdd71..174c63a 100644 --- a/src/jtag/interfaces.c +++ b/src/jtag/interfaces.c @@ -51,16 +51,10 @@ extern struct jtag_interface parport_interface; #if BUILD_DUMMY == 1 extern struct jtag_interface dummy_interface; #endif -#if BUILD_FT2232_FTD2XX == 1 -extern struct jtag_interface ft2232_interface; -#endif -#if BUILD_FT2232_LIBFTDI == 1 -extern struct jtag_interface ft2232_interface; -#endif #if BUILD_FTDI == 1 extern struct jtag_interface ftdi_interface; #endif -#if BUILD_USB_BLASTER_LIBFTDI == 1 || BUILD_USB_BLASTER_FTD2XX == 1 || BUILD_USB_BLASTER_2 == 1 +#if BUILD_USB_BLASTER == 1 || BUILD_USB_BLASTER_2 == 1 extern struct jtag_interface usb_blaster_interface; #endif #if BUILD_JTAG_VPI == 1 @@ -78,7 +72,7 @@ extern struct jtag_interface at91rm9200_interface; #if BUILD_GW16012 == 1 extern struct jtag_interface gw16012_interface; #endif -#if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1 +#if BUILD_PRESTO extern struct jtag_interface presto_interface; #endif #if BUILD_USBPROG == 1 @@ -129,6 +123,12 @@ extern struct jtag_interface bcm2835gpio_interface; #if BUILD_CMSIS_DAP == 1 extern struct jtag_interface cmsis_dap_interface; #endif +#if BUILD_KITPROG == 1 +extern struct jtag_interface kitprog_interface; +#endif +#if BUILD_IMX_GPIO == 1 +extern struct jtag_interface imx_gpio_interface; +#endif #endif /* standard drivers */ /** @@ -150,16 +150,10 @@ struct jtag_interface *jtag_interfaces[] = { #if BUILD_DUMMY == 1 &dummy_interface, #endif -#if BUILD_FT2232_FTD2XX == 1 - &ft2232_interface, -#endif -#if BUILD_FT2232_LIBFTDI == 1 - &ft2232_interface, -#endif #if BUILD_FTDI == 1 &ftdi_interface, #endif -#if BUILD_USB_BLASTER_LIBFTDI == 1 || BUILD_USB_BLASTER_FTD2XX == 1 || BUILD_USB_BLASTER_2 == 1 +#if BUILD_USB_BLASTER || BUILD_USB_BLASTER_2 == 1 &usb_blaster_interface, #endif #if BUILD_JTAG_VPI == 1 @@ -177,7 +171,7 @@ struct jtag_interface *jtag_interfaces[] = { #if BUILD_GW16012 == 1 &gw16012_interface, #endif -#if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1 +#if BUILD_PRESTO &presto_interface, #endif #if BUILD_USBPROG == 1 @@ -228,6 +222,12 @@ struct jtag_interface *jtag_interfaces[] = { #if BUILD_CMSIS_DAP == 1 &cmsis_dap_interface, #endif +#if BUILD_KITPROG == 1 + &kitprog_interface, +#endif +#if BUILD_IMX_GPIO == 1 + &imx_gpio_interface, +#endif #endif /* standard drivers */ NULL, }; |