summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCatalin Patulea <cat@vv.carleton.ca>2009-12-26 15:05:06 -0800
committerDavid Brownell <dbrownell@users.sourceforge.net>2009-12-26 15:05:06 -0800
commit84dbf8ab5a2e85c9d9c9d276fba152a45a441433 (patch)
treed7047d2501d208824ffb9e2c1ac6c997f14086b8
parent900d745567809d9f0163cfde5832b10ec0581a0e (diff)
downloadopenocd+libswd-84dbf8ab5a2e85c9d9c9d276fba152a45a441433.tar.gz
openocd+libswd-84dbf8ab5a2e85c9d9c9d276fba152a45a441433.tar.bz2
openocd+libswd-84dbf8ab5a2e85c9d9c9d276fba152a45a441433.tar.xz
openocd+libswd-84dbf8ab5a2e85c9d9c9d276fba152a45a441433.zip
Driver for USB-JTAG, Altera USB-Blaster and compatibles
The 10-pin JTAG layout used with these adapters is used by a variety of platforms including AVR. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
-rw-r--r--NEWS1
-rw-r--r--configure.in26
-rw-r--r--doc/openocd.texi59
-rw-r--r--src/Makefile.am4
-rw-r--r--src/jtag/drivers/Makefile.am3
-rw-r--r--src/jtag/drivers/usb_blaster.c589
-rw-r--r--src/jtag/interfaces.c6
-rw-r--r--tcl/interface/altera-usb-blaster.cfg11
-rw-r--r--tcl/interface/usb-jtag.cfg11
9 files changed, 709 insertions, 1 deletions
diff --git a/NEWS b/NEWS
index 173d06af..e3e813cb 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,7 @@ and other issues not mentioned here.
JTAG Layer:
Support KT-Link JTAG adapter.
+ Support USB-JTAG, Altera USB-Blaster and compatibles.
Boundary Scan:
Target Layer:
diff --git a/configure.in b/configure.in
index 7ce79559..21edba92 100644
--- a/configure.in
+++ b/configure.in
@@ -392,6 +392,14 @@ AC_ARG_ENABLE(ft2232_ftd2xx,
AS_HELP_STRING([--enable-ft2232_ftd2xx], [Enable building support for FT2232 based devices using the FTD2XX driver from ftdichip.com]),
[build_ft2232_ftd2xx=$enableval], [build_ft2232_ftd2xx=no])
+AC_ARG_ENABLE(usb_blaster_libftdi,
+ AS_HELP_STRING([--enable-usb_blaster_libftdi], [Enable building support for the Altera USB-Blaster using the libftdi driver, opensource alternate of FTD2XX]),
+ [build_usb_blaster_libftdi=$enableval], [build_usb_blaster_libftdi=no])
+
+AC_ARG_ENABLE(usb_blaster_ftd2xx,
+ AS_HELP_STRING([--enable-usb_blaster_ftd2xx], [Enable building support for the Altera USB-Blaster using the FTD2XX driver from ftdichip.com]),
+ [build_usb_blaster_ftd2xx=$enableval], [build_usb_blaster_ftd2xx=no])
+
AC_ARG_ENABLE(amtjtagaccel,
AS_HELP_STRING([--enable-amtjtagaccel], [Enable building the Amontec JTAG-Accelerator driver]),
[build_amtjtagaccel=$enableval], [build_amtjtagaccel=no])
@@ -651,6 +659,20 @@ else
AC_DEFINE(BUILD_FT2232_FTD2XX, 0, [0 if you don't want ftd2xx ft2232.])
fi
+if test $build_usb_blaster_libftdi = yes; then
+ build_bitbang=yes
+ AC_DEFINE(BUILD_USB_BLASTER_LIBFTDI, 1, [1 if you want libftdi usb_blaster.])
+else
+ AC_DEFINE(BUILD_USB_BLASTER_LIBFTDI, 0, [0 if you don't want libftdi usb_blaster.])
+fi
+
+if test $build_usb_blaster_ftd2xx = yes; then
+ build_bitbang=yes
+ AC_DEFINE(BUILD_USB_BLASTER_FTD2XX, 1, [1 if you want ftd2xx usb_blaster.])
+else
+ AC_DEFINE(BUILD_USB_BLASTER_FTD2XX, 0, [0 if you don't want ftd2xx usb_blaster.])
+fi
+
if test $build_amtjtagaccel = yes; then
AC_DEFINE(BUILD_AMTJTAGACCEL, 1, [1 if you want the Amontec JTAG-Accelerator driver.])
else
@@ -727,7 +749,7 @@ then
AC_MSG_ERROR([The option: with_ftd2xx_linux_tardir is for LINUX only.])
fi
-if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes ; then
+if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes ; then
AC_MSG_CHECKING([for ftd2xx.lib exists (win32)])
# if we are given a zipdir...
@@ -1001,6 +1023,8 @@ AM_CONDITIONAL(AT91RM9200, test $build_at91rm9200 = yes)
AM_CONDITIONAL(BITBANG, test $build_bitbang = yes)
AM_CONDITIONAL(FT2232_LIBFTDI, test $build_ft2232_libftdi = yes)
AM_CONDITIONAL(FT2232_DRIVER, test $build_ft2232_ftd2xx = yes -o $build_ft2232_libftdi = yes)
+AM_CONDITIONAL(USB_BLASTER_LIBFTDI, test $build_usb_blaster_libftdi = yes)
+AM_CONDITIONAL(USB_BLASTER_DRIVER, test $build_usb_blaster_ftd2xx = yes -o $build_usb_blaster_libftdi = yes)
AM_CONDITIONAL(AMTJTAGACCEL, test $build_amtjtagaccel = yes)
AM_CONDITIONAL(GW16012, test $build_gw16012 = yes)
AM_CONDITIONAL(PRESTO_LIBFTDI, test $build_presto_libftdi = yes)
diff --git a/doc/openocd.texi b/doc/openocd.texi
index 013a31a8..1c20716c 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -310,6 +310,25 @@ chips are starting to become available in JTAG adapters.
@* Link @url{http://www.hitex.com/index.php?id=cortino}
@end itemize
+@section USB-JTAG / Altera USB-Blaster compatibles
+
+These devices also show up as FTDI devices, but are not
+protocol-compatible with the FT2232 devices. They are, however,
+protocol-compatible among themselves. USB-JTAG devices typically consist
+of a FT245 followed by a CPLD that understands a particular protocol,
+or emulate this protocol using some other hardware.
+
+They may appear under different USB VID/PID depending on the particular
+product. The driver can be configured to search for any VID/PID pair
+(see the section on driver commands).
+
+@itemize
+@item @b{USB-JTAG} Kolja Waschk's USB Blaster-compatible adapter
+@* Link: @url{http://www.ixo.de/info/usb_jtag/}
+@item @b{Altera USB-Blaster}
+@* Link: @url{http://www.altera.com/literature/ug/ug_usb_blstr.pdf}
+@end itemize
+
@section USB JLINK based
There are several OEM versions of the Segger @b{JLINK} adapter. It is
an example of a micro controller based JTAG adapter, it uses an
@@ -1989,6 +2008,46 @@ ft2232_vid_pid 0x0403 0xbdc8
@end example
@end deffn
+@deffn {Interface Driver} {usb_blaster}
+USB JTAG/USB-Blaster compatibles over one of the userspace libraries
+for FTDI chips. These interfaces have several commands, used to
+configure the driver before initializing the JTAG scan chain:
+
+@deffn {Config Command} {usb_blaster_device_desc} description
+Provides the USB device description (the @emph{iProduct string})
+of the FTDI FT245 device. If not
+specified, the FTDI default value is used. This setting is only valid
+if compiled with FTD2XX support.
+@end deffn
+
+@deffn {Config Command} {usb_blaster_vid_pid} vid pid
+The vendor ID and product ID of the FTDI FT245 device. If not specified,
+default values are used.
+Currently, only one @var{vid}, @var{pid} pair may be given, e.g. for
+Altera USB-Blaster (default):
+@example
+ft2232_vid_pid 0x09FB 0x6001
+@end example
+The following VID/PID is for Kolja Waschk's USB JTAG:
+@example
+ft2232_vid_pid 0x16C0 0x06AD
+@end example
+@end deffn
+
+@deffn {Command} {usb_blaster} (@option{pin6}|@option{pin8}) (@option{0}|@option{1})
+Sets the state of the unused GPIO pins on USB-Blasters (pins 6 and 8 on the
+female JTAG header). These pins can be used as SRST and/or TRST provided the
+appropriate connections are made on the target board.
+
+For example, to use pin 6 as SRST (as with an AVR board):
+@example
+$_TARGETNAME configure -event reset-assert \
+ "usb_blaster pin6 1; wait 1; usb_blaster pin6 0"
+@end example
+@end deffn
+
+@end deffn
+
@deffn {Interface Driver} {gw16012}
Gateworks GW16012 JTAG programmer.
This has one driver-specific command:
diff --git a/src/Makefile.am b/src/Makefile.am
index f60feac3..a566b4d4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -60,12 +60,16 @@ endif
if FT2232_LIBFTDI
FTDI2232LIB = -lftdi -lusb
else
+if USB_BLASTER_LIBFTDI
+FTDI2232LIB = -lftdi -lusb
+else
if PRESTO_LIBFTDI
FTDI2232LIB = -lftdi -lusb
else
FTDI2232LIB =
endif
endif
+endif
if USBPROG
LIBUSB = -lusb
diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am
index 8ee5ac59..d6113c60 100644
--- a/src/jtag/drivers/Makefile.am
+++ b/src/jtag/drivers/Makefile.am
@@ -28,6 +28,9 @@ endif
if FT2232_DRIVER
DRIVERFILES += ft2232.c
endif
+if USB_BLASTER_DRIVER
+DRIVERFILES += usb_blaster.c
+endif
if AMTJTAGACCEL
DRIVERFILES += amt_jtagaccel.c
endif
diff --git a/src/jtag/drivers/usb_blaster.c b/src/jtag/drivers/usb_blaster.c
new file mode 100644
index 00000000..3703323b
--- /dev/null
+++ b/src/jtag/drivers/usb_blaster.c
@@ -0,0 +1,589 @@
+/***************************************************************************
+ * Driver for USB-JTAG, Altera USB-Blaster and compatibles *
+ * Original code from Kolja Waschk's USB-JTAG project *
+ * (http://www.ixo.de/info/usb_jtag/). *
+ * Some updates by Anthony Liu (2006). *
+ * Minor updates and cleanup by Catalin Patulea (2009). *
+ * *
+ * Copyright (C) 2009 Catalin Patulea *
+ * cat@vv.carleton.ca *
+ * *
+ * Copyright (C) 2006 Kolja Waschk *
+ * usbjtag@ixo.de *
+ * *
+ * Based on ft2232.c and bitbang.c, *
+ * Copyright (C) 2004,2006 by Dominic Rath *
+ * *
+ * 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, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+/*
+ * The following information is originally from Kolja Waschk's USB-JTAG,
+ * where it was obtained by reverse engineering an Altera USB-Blaster.
+ * See http://www.ixo.de/info/usb_jtag/ for USB-Blaster block diagram and
+ * usb_jtag-20080705-1200.zip#usb_jtag/host/openocd for protocol.
+ *
+ * The same information is also on the UrJTAG mediawiki, with some additional
+ * notes on bits marked as "unknown" by usb_jtag.
+ * (http://sourceforge.net/apps/mediawiki/urjtag/index.php?
+ * title=Cable_Altera_USB-Blaster)
+ *
+ * USB-JTAG, Altera USB-Blaster and compatibles are typically implemented as
+ * an FTDIChip FT245 followed by a CPLD which handles a two-mode protocol:
+ *
+ * _________
+ * | |
+ * | AT93C46 |
+ * |_________|
+ * __|__________ _________
+ * | | | |
+ * USB__| FTDI 245BM |__| EPM7064 |__JTAG (B_TDO,B_TDI,B_TMS,B_TCK)
+ * |_____________| |_________|
+ * __|__________ _|___________
+ * | | | |
+ * | 6 MHz XTAL | | 24 MHz Osc. |
+ * |_____________| |_____________|
+ *
+ * Protocol details are given in the code below.
+ *
+ * It is also possible to emulate this configuration using a single-chip USB
+ * controller like the Cypress FX2 (again, see usb_jtag for details).
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if IS_CYGWIN == 1
+#include "windows.h"
+#undef LOG_ERROR
+#endif
+
+/* project specific includes */
+#include <jtag/interface.h>
+#include <jtag/commands.h>
+#include <helper/time_support.h>
+
+/* system includes */
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "bitbang.h"
+
+#if (BUILD_USB_BLASTER_FTD2XX == 1 && BUILD_USB_BLASTER_LIBFTDI == 1)
+#error "BUILD_USB_BLASTER_FTD2XX && BUILD_USB_BLASTER_LIBFTDI "
+ "are mutually exclusive"
+#elif (BUILD_USB_BLASTER_FTD2XX != 1 && BUILD_USB_BLASTER_LIBFTDI != 1)
+#error "BUILD_USB_BLASTER_FTD2XX || BUILD_USB_BLASTER_LIBFTDI must be chosen"
+#endif
+
+/* USB_BLASTER access library includes */
+#if BUILD_USB_BLASTER_FTD2XX == 1
+#include <ftd2xx.h>
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+#include <ftdi.h>
+#endif
+
+#include <sys/time.h>
+#include <time.h>
+
+static char *usb_blaster_device_desc;
+static uint16_t usb_blaster_vid = 0x09fb; /* Altera */
+static uint16_t usb_blaster_pid = 0x6001; /* USB-Blaster */
+
+/* last output byte in simple bit banging mode */
+static uint8_t out_value;
+
+#if BUILD_USB_BLASTER_FTD2XX == 1
+static FT_HANDLE ftdih;
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+static struct ftdi_context ftdic;
+#endif
+
+static int usb_blaster_buf_write(
+ uint8_t *buf, int size, uint32_t *bytes_written)
+{
+#if BUILD_USB_BLASTER_FTD2XX == 1
+ FT_STATUS status;
+ DWORD dw_bytes_written;
+
+#ifdef _DEBUG_JTAG_IO_
+ LOG_DEBUG("usb_blaster_buf_write %02X (%d)\n", buf[0], size);
+#endif
+ status = FT_Write(ftdih, buf, size, &dw_bytes_written);
+ if (status != FT_OK)
+ {
+ *bytes_written = dw_bytes_written;
+ LOG_ERROR("FT_Write returned: %lu", status);
+ return ERROR_JTAG_DEVICE_ERROR;
+ }
+ *bytes_written = dw_bytes_written;
+ return ERROR_OK;
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+ int retval;
+#ifdef _DEBUG_JTAG_IO_
+ LOG_DEBUG("usb_blaster_buf_write %02X (%d)\n", buf[0], size);
+#endif
+ 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;
+ }
+ *bytes_written = retval;
+ return ERROR_OK;
+#endif
+}
+
+static int
+usb_blaster_buf_read(uint8_t *buf, unsigned size, uint32_t *bytes_read)
+{
+#if BUILD_USB_BLASTER_FTD2XX == 1
+ DWORD dw_bytes_read;
+ FT_STATUS status;
+
+ status = FT_Read(ftdih, buf, size, &dw_bytes_read);
+ if (status != FT_OK)
+ {
+ *bytes_read = dw_bytes_read;
+ LOG_ERROR("FT_Read returned: %lu", status);
+ return ERROR_JTAG_DEVICE_ERROR;
+ }
+#ifdef _DEBUG_JTAG_IO_
+ LOG_DEBUG("usb_blaster_buf_read %02X (%lu)\n", buf[0], dw_bytes_read);
+#endif
+ *bytes_read = dw_bytes_read;
+ return ERROR_OK;
+
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+ int retval;
+ int timeout = 100;
+
+ *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;
+ }
+#ifdef _DEBUG_JTAG_IO_
+ LOG_DEBUG("usb_blaster_buf_read %02X (%d)\n", buf[0], *bytes_read);
+#endif
+ return ERROR_OK;
+#endif
+}
+
+/* The following code doesn't fully utilize the possibilities of the
+ * USB-Blaster. It writes one byte per JTAG pin state change at a time; it
+ * doesn't even try to buffer data up to the maximum packet size of 64 bytes.
+ *
+ * Actually, the USB-Blaster offers a byte-shift mode to transmit up to 504 data
+ * bits (bidirectional) in a single USB packet. A header byte has to be sent as
+ * the first byte in a packet with the following meaning:
+ *
+ * Bit 7 (0x80): Must be set to indicate byte-shift mode.
+ * Bit 6 (0x40): If set, the USB-Blaster will also read data, not just write.
+ * Bit 5..0: Define the number N of following bytes
+ *
+ * All N following bytes will then be clocked out serially on TDI. If Bit 6 was
+ * set, it will afterwards return N bytes with TDO data read while clocking out
+ * the TDI data. LSB of the first byte after the header byte will appear first
+ * on TDI.
+ */
+
+/* Simple bit banging mode:
+ *
+ * Bit 7 (0x80): Must be zero (see byte-shift mode above)
+ * Bit 6 (0x40): If set, you will receive a byte indicating the state of TDO
+ * in return.
+ * Bit 5 (0x20): Output Enable/LED.
+ * Bit 4 (0x10): TDI Output.
+ * Bit 3 (0x08): nCS Output (not used in JTAG mode).
+ * Bit 2 (0x04): nCE Output (not used in JTAG mode).
+ * Bit 1 (0x02): TMS Output.
+ * Bit 0 (0x01): TCK Output.
+ *
+ * For transmitting a single data bit, you need to write two bytes. Up to 64
+ * bytes can be combined in a single USB packet (but this is not done in the
+ * code below). It isn't possible to read a data without transmitting data.
+ */
+
+#define TCK (1 << 0)
+#define TMS (1 << 1)
+#define NCE (1 << 2)
+#define NCS (1 << 3)
+#define TDI (1 << 4)
+#define LED (1 << 5)
+#define READ (1 << 6)
+#define SHMODE (1 << 7)
+#define OTHERS ((1 << 2) | (1 << 3) | (1 << 5))
+
+#define READ_TDO (1 << 0)
+
+static void usb_blaster_write_data(void)
+{
+ uint32_t bytes_written;
+ usb_blaster_buf_write(&out_value, 1, &bytes_written);
+}
+
+static int usb_blaster_read_data(void)
+{
+ int status;
+ uint8_t buf[1];
+ uint32_t bytes_read;
+
+ out_value |= READ;
+ usb_blaster_write_data();
+ out_value &= ~READ;
+
+ status = usb_blaster_buf_read(buf, 1, &bytes_read);
+ if (status < 0)
+ return 0;
+
+ return !!(buf[0] & READ_TDO);
+}
+
+static void usb_blaster_write(int tck, int tms, int tdi)
+{
+#ifdef _DEBUG_JTAG_IO_
+ LOG_DEBUG("---- usb_blaster_write(%d,%d,%d)\n", tck, tms, tdi);
+#endif
+ out_value &= ~(TCK | TMS | TDI);
+ if (tck)
+ out_value |= TCK;
+ if (tms)
+ out_value |= TMS;
+ if (tdi)
+ out_value |= TDI;
+
+ usb_blaster_write_data();
+}
+
+static int usb_blaster_speed(int speed)
+{
+#if BUILD_USB_BLASTER_FTD2XX == 1
+ LOG_DEBUG("TODO: usb_blaster_speed() isn't implemented for libftd2xx!");
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+ LOG_DEBUG("TODO: usb_blaster_speed() isn't optimally implemented!");
+
+ /* TODO: libftdi's ftdi_set_baudrate chokes on high rates, use lowlevel
+ * usb function instead! And additionally allow user to throttle.
+ */
+ if (ftdi_set_baudrate(&ftdic, 3000000 / 4) < 0)
+ {
+ LOG_ERROR("Can't set baud rate to max: %s",
+ ftdi_get_error_string(&ftdic));
+ return ERROR_JTAG_DEVICE_ERROR;
+ };
+#endif
+
+ return ERROR_OK;
+}
+
+static void usb_blaster_reset(int trst, int srst)
+{
+ LOG_DEBUG("TODO: usb_blaster_reset(%d,%d) isn't implemented!",
+ trst, srst);
+}
+
+static struct bitbang_interface usb_blaster_bitbang = {
+ .read = usb_blaster_read_data,
+ .write = usb_blaster_write,
+ .reset = usb_blaster_reset,
+};
+
+static int usb_blaster_init(void)
+{
+ uint8_t latency_timer;
+
+#if BUILD_USB_BLASTER_FTD2XX == 1
+ FT_STATUS status;
+#endif
+
+#if BUILD_USB_BLASTER_FTD2XX == 1
+ LOG_DEBUG("'usb_blaster' interface using FTD2XX");
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+ LOG_DEBUG("'usb_blaster' interface using libftdi");
+#endif
+
+#if BUILD_USB_BLASTER_FTD2XX == 1
+ /* Open by device description */
+ if (usb_blaster_device_desc == NULL)
+ {
+ LOG_WARNING("no usb_blaster device description specified, "
+ "using default 'USB-Blaster'");
+ usb_blaster_device_desc = "USB-Blaster";
+ }
+
+#if IS_WIN32 == 0
+ /* Add non-standard Vid/Pid to the linux driver */
+ status = FT_SetVIDPID(usb_blaster_vid, usb_blaster_pid);
+ if (status != FT_OK)
+ {
+ LOG_WARNING("couldn't add %4.4x:%4.4x",
+ usb_blaster_vid, usb_blaster_pid);
+ }
+#endif
+
+ status = FT_OpenEx(usb_blaster_device_desc, FT_OPEN_BY_DESCRIPTION,
+ &ftdih);
+ if (status != FT_OK)
+ {
+ DWORD num_devices;
+
+ LOG_ERROR("unable to open ftdi device: %lu", 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: %lu\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
+ {
+ 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: %lu", status);
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ status = FT_GetLatencyTimer(ftdih, &latency_timer);
+ if (status != FT_OK)
+ {
+ LOG_ERROR("unable to get latency timer: %lu", status);
+ return ERROR_JTAG_INIT_FAILED;
+ }
+ 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: %lu", status);
+ return ERROR_JTAG_INIT_FAILED;
+ }
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+ if (ftdi_init(&ftdic) < 0)
+ return ERROR_JTAG_INIT_FAILED;
+
+ /* context, vendor id, product id */
+ if (ftdi_usb_open(&ftdic, usb_blaster_vid, usb_blaster_pid) < 0)
+ {
+ LOG_ERROR("unable to open ftdi device: %s", ftdic.error_str);
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ if (ftdi_usb_reset(&ftdic) < 0)
+ {
+ LOG_ERROR("unable to reset ftdi device");
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ if (ftdi_set_latency_timer(&ftdic, 2) < 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;
+ }
+ LOG_DEBUG("current latency timer: %u", latency_timer);
+
+ ftdi_disable_bitbang(&ftdic);
+#endif
+
+ bitbang_interface = &usb_blaster_bitbang;
+
+ usb_blaster_speed(jtag_get_speed());
+
+#if 0
+#if BUILD_USB_BLASTER_FTD2XX == 1
+ if ((status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX)) != FT_OK)
+ {
+ LOG_ERROR("error purging ftd2xx device: %i", status);
+ return ERROR_JTAG_INIT_FAILED;
+ }
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+ if (ftdi_usb_purge_buffers(&ftdic) < 0)
+ {
+ LOG_ERROR("ftdi_purge_buffers: %s", ftdic.error_str);
+ return ERROR_JTAG_INIT_FAILED;
+ }
+#endif
+#endif
+
+ return ERROR_OK;
+}
+
+static int usb_blaster_quit(void)
+{
+#if BUILD_USB_BLASTER_FTD2XX == 1
+ FT_STATUS status;
+
+ status = FT_Close(ftdih);
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+ ftdi_usb_close(&ftdic);
+ ftdi_deinit(&ftdic);
+#endif
+
+ return ERROR_OK;
+}
+
+COMMAND_HANDLER(usb_blaster_handle_device_desc_command)
+{
+ if (CMD_ARGC == 1)
+ usb_blaster_device_desc = strdup(CMD_ARGV[0]);
+ else
+ LOG_ERROR("require exactly one argument to "
+ "usb_blaster_device_desc <description>");
+
+ return ERROR_OK;
+}
+
+COMMAND_HANDLER(usb_blaster_handle_vid_pid_command)
+{
+ if (CMD_ARGC > 2)
+ {
+ LOG_WARNING("ignoring extra IDs in ft2232_vid_pid "
+ "(maximum is 1 pair)");
+ CMD_ARGC = 2;
+ }
+ if (CMD_ARGC == 2)
+ {
+ COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], usb_blaster_vid);
+ COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], usb_blaster_pid);
+ }
+ else
+ LOG_WARNING("incomplete usb_blaster_vid_pid configuration");
+
+ return ERROR_OK;
+}
+
+COMMAND_HANDLER(usb_blaster_handle_pin_command)
+{
+ if (CMD_ARGC == 2)
+ {
+ const char * const pin_name = CMD_ARGV[0];
+ uint8_t mask;
+ unsigned int state;
+
+ if (!strcmp(pin_name, "pin6"))
+ mask = NCE;
+ else if (!strcmp(pin_name, "pin8"))
+ mask = NCS;
+ else
+ {
+ LOG_ERROR("%s: pin name must be \"pin6\" or \"pin8\"",
+ CMD_NAME);
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ }
+
+ COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], state);
+ if (state == 0)
+ {
+ out_value &= ~mask;
+ usb_blaster_write_data();
+ }
+ else if (state == 1)
+ {
+ out_value |= mask;
+ usb_blaster_write_data();
+ }
+ else
+ {
+ LOG_ERROR("%s: pin state must be 0 or 1", CMD_NAME);
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ }
+
+ return ERROR_OK;
+ }
+ else
+ {
+ LOG_ERROR("%s takes exactly two arguments", CMD_NAME);
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ }
+}
+
+static const struct command_registration usb_blaster_command_handlers[] = {
+ {
+ .name = "usb_blaster_device_desc",
+ .handler = usb_blaster_handle_device_desc_command,
+ .mode = COMMAND_CONFIG,
+ .help = "set the USB device description of the USB-Blaster",
+ .usage = "description-string",
+ },
+ {
+ .name = "usb_blaster_vid_pid",
+ .handler = usb_blaster_handle_vid_pid_command,
+ .mode = COMMAND_CONFIG,
+ .help = "the vendor ID and product ID of the USB-Blaster",
+ .usage = "vid pid",
+ },
+ {
+ .name = "usb_blaster",
+ .handler = usb_blaster_handle_pin_command,
+ .mode = COMMAND_ANY,
+ .help = "set pin state for the unused GPIO pins",
+ .usage = "(pin6|pin8) (0|1)",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+struct jtag_interface usb_blaster_interface = {
+ .name = "usb_blaster",
+ .commands = usb_blaster_command_handlers,
+
+ .execute_queue = bitbang_execute_queue,
+
+ .speed = usb_blaster_speed,
+ .init = usb_blaster_init,
+ .quit = usb_blaster_quit,
+};
diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c
index 643e1118..f6d82195 100644
--- a/src/jtag/interfaces.c
+++ b/src/jtag/interfaces.c
@@ -58,6 +58,9 @@ extern struct jtag_interface ft2232_interface;
#if BUILD_FT2232_LIBFTDI == 1
extern struct jtag_interface ft2232_interface;
#endif
+#if BUILD_USB_BLASTER_LIBFTDI == 1 || BUILD_USB_BLASTER_FTD2XX == 1
+extern struct jtag_interface usb_blaster_interface;
+#endif
#if BUILD_AMTJTAGACCEL == 1
extern struct jtag_interface amt_jtagaccel_interface;
#endif
@@ -115,6 +118,9 @@ struct jtag_interface *jtag_interfaces[] = {
#if BUILD_FT2232_LIBFTDI == 1
&ft2232_interface,
#endif
+#if BUILD_USB_BLASTER_LIBFTDI == 1 || BUILD_USB_BLASTER_FTD2XX == 1
+ &usb_blaster_interface,
+#endif
#if BUILD_AMTJTAGACCEL == 1
&amt_jtagaccel_interface,
#endif
diff --git a/tcl/interface/altera-usb-blaster.cfg b/tcl/interface/altera-usb-blaster.cfg
new file mode 100644
index 00000000..ae214652
--- /dev/null
+++ b/tcl/interface/altera-usb-blaster.cfg
@@ -0,0 +1,11 @@
+#
+# Altera USB-Blaster
+#
+# http://www.altera.com/literature/ug/ug_usb_blstr.pdf
+#
+
+interface usb_blaster
+# These are already the defaults.
+# usb_blaster_vid_pid 0x09FB 0x6001
+# usb_blaster_device_desc "USB-Blaster"
+jtag_khz 3000
diff --git a/tcl/interface/usb-jtag.cfg b/tcl/interface/usb-jtag.cfg
new file mode 100644
index 00000000..b81028d6
--- /dev/null
+++ b/tcl/interface/usb-jtag.cfg
@@ -0,0 +1,11 @@
+#
+# Kolja Waschk's USB-JTAG
+#
+# http://www.ixo.de/info/usb_jtag/
+#
+
+interface usb_blaster
+usb_blaster_vid_pid 0x16C0 0x06AD
+usb_blaster_device_desc "USB-JTAG-IF"
+jtag_khz 3000
+