X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fdrivers%2Fft2232.c;h=54f7c260269107610c7dd3f00146980b0cbe2a6e;hp=c7503f8a46c19bebaab118c7048d3c394091f6b6;hb=0535531d2753f1b86454bb6ffad6ffbdd56c66d0;hpb=c9e448222cc5d1162f5e495cdfd327732c50a484 diff --git a/src/jtag/drivers/ft2232.c b/src/jtag/drivers/ft2232.c index c7503f8a46..54f7c26026 100644 --- a/src/jtag/drivers/ft2232.c +++ b/src/jtag/drivers/ft2232.c @@ -27,13 +27,52 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ -/* This code uses information contained in the MPSSE specification which was +/** + * @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 @@ -41,8 +80,8 @@ #endif /* project specific includes */ -#include "interface.h" -#include +#include +#include #include #if IS_CYGWIN == 1 @@ -60,6 +99,16 @@ /* FT2232 access library includes */ #if BUILD_FT2232_FTD2XX == 1 #include + +enum ftdi_interface +{ + INTERFACE_ANY = 0, + INTERFACE_A = 1, + INTERFACE_B = 2, + INTERFACE_C = 3, + INTERFACE_D = 4 +}; + #elif BUILD_FT2232_LIBFTDI == 1 #include #endif @@ -105,7 +154,6 @@ static int ft2232_stableclocks(int num_cycles, struct jtag_command* cmd); static char * ft2232_device_desc_A = NULL; static char* ft2232_device_desc = NULL; static char* ft2232_serial = NULL; -static char* ft2232_layout = NULL; static uint8_t ft2232_latency = 2; static unsigned ft2232_max_tck = FTDI_2232C_MAX_TCK; @@ -119,11 +167,14 @@ struct ft2232_layout { 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 flyswatter_init(void); static int turtle_init(void); @@ -133,11 +184,15 @@ 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); /* reset procedures for supported layouts */ -static void usbjtag_reset(int trst, int srst); +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 flyswatter_reset(int trst, int srst); @@ -149,6 +204,7 @@ 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); /* blink procedures for layouts that support a blinking led */ static void olimex_jtag_blink(void); @@ -156,36 +212,135 @@ static void flyswatter_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[] = { - { "usbjtag", usbjtag_init, usbjtag_reset, NULL }, - { "jtagkey", jtagkey_init, jtagkey_reset, NULL }, - { "jtagkey_prototype_v1", jtagkey_init, jtagkey_reset, NULL }, - { "oocdlink", jtagkey_init, jtagkey_reset, NULL }, - { "signalyzer", usbjtag_init, usbjtag_reset, NULL }, - { "evb_lm3s811", usbjtag_init, usbjtag_reset, NULL }, - { "luminary_icdi", usbjtag_init, usbjtag_reset, NULL }, - { "olimex-jtag", olimex_jtag_init, olimex_jtag_reset, olimex_jtag_blink }, - { "flyswatter", flyswatter_init, flyswatter_reset, flyswatter_jtag_blink }, - { "turtelizer2", turtle_init, turtle_reset, turtle_jtag_blink }, - { "comstick", comstick_init, comstick_reset, NULL }, - { "stm32stick", stm32stick_init, stm32stick_reset, NULL }, - { "axm0432_jtag", axm0432_jtag_init, axm0432_jtag_reset, NULL }, - { "sheevaplug", sheevaplug_init, sheevaplug_reset, NULL }, - { "icebear", icebear_jtag_init, icebear_jtag_reset, NULL }, - { "cortino", cortino_jtag_init, comstick_reset, NULL }, - { "signalyzer-h", signalyzer_h_init, signalyzer_h_reset, signalyzer_h_blink }, - { "ktlink", ktlink_init, ktlink_reset, ktlink_blink }, - { NULL, NULL, NULL, NULL }, + { .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 = flyswatter_init, + .reset = flyswatter_reset, + .blink = flyswatter_jtag_blink + }, + { .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 = NULL, /* END OF TABLE */ }, }; -static uint8_t nTRST, nTRSTnOE, nSRST, nSRSTnOE; +/* 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 = 0x0; + +/* 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 = 0x0; +/** default value bitmask for CBUS GPIOH(0..4) */ static uint8_t high_output = 0x0; +/** default direction bitmask for CBUS GPIOH(0..4) */ static uint8_t high_direction = 0x0; #if BUILD_FT2232_FTD2XX == 1 @@ -348,7 +503,6 @@ static int ft2232_write(uint8_t* buf, int size, uint32_t* bytes_written) else { *bytes_written = dw_bytes_written; - return ERROR_OK; } #elif BUILD_FT2232_LIBFTDI == 1 int retval; @@ -361,9 +515,15 @@ static int ft2232_write(uint8_t* buf, int size, uint32_t* bytes_written) else { *bytes_written = retval; - return ERROR_OK; } #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) @@ -437,8 +597,9 @@ static int ft2232h_ft4232h_adaptive_clocking(bool enable) LOG_DEBUG("%2.2x", buf); uint32_t bytes_written; - int retval = ft2232_write(&buf, 1, &bytes_written); - if ((ERROR_OK != retval) || (bytes_written != 1)) + int retval; + + if ((retval = ft2232_write(&buf, sizeof(buf), &bytes_written)) != ERROR_OK) { LOG_ERROR("couldn't write command to %s adaptive clocking" , enable ? "enable" : "disable"); @@ -457,8 +618,8 @@ static int ft2232h_ft4232h_clk_divide_by_5(bool enable) { uint32_t bytes_written; uint8_t buf = enable ? 0x8b : 0x8a; - int retval = ft2232_write(&buf, 1, &bytes_written); - if ((ERROR_OK != retval) || (bytes_written != 1)) + + 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"); @@ -495,7 +656,7 @@ static int ft2232_speed(int speed) buf[2] = (speed >> 8) & 0xff; /* valueH */ LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((retval = ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if ((retval = ft2232_write(buf, sizeof(buf), &bytes_written)) != ERROR_OK) { LOG_ERROR("couldn't set FT2232 TCK speed"); return retval; @@ -605,7 +766,7 @@ static void ft2232_debug_dump_buffer(void) for (i = 0; i < ft2232_buffer_size; i++) { - line_p += snprintf(line_p, 256 - (line_p - line), "%2.2x ", ft2232_buffer[i]); + line_p += snprintf(line_p, sizeof(line) - (line_p - line), "%2.2x ", ft2232_buffer[i]); if (i % 16 == 15) { LOG_DEBUG("%s", line); @@ -1220,7 +1381,8 @@ static int ft2232_predict_scan_in(int scan_size, enum scan_type type) return predicted_size; } -static void usbjtag_reset(int trst, int srst) +/* 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) @@ -1491,6 +1653,36 @@ static void sheevaplug_reset(int trst, int srst) 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 int ft2232_execute_runtest(struct jtag_command *cmd) { int retval; @@ -1592,6 +1784,72 @@ static int ft2232_execute_statemove(struct jtag_command *cmd) 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; @@ -1744,20 +2002,23 @@ static int ft2232_execute_stableclocks(struct jtag_command *cmd) static int ft2232_execute_command(struct jtag_command *cmd) { int retval; - retval = ERROR_OK; switch (cmd->type) { case JTAG_RESET: retval = ft2232_execute_reset(cmd); break; case JTAG_RUNTEST: retval = ft2232_execute_runtest(cmd); break; - case JTAG_STATEMOVE: retval = ft2232_execute_statemove(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"); - exit(-1); + retval = ERROR_JTAG_QUEUE_FAILED; + break; } return retval; } @@ -1814,7 +2075,12 @@ static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int* try_mor char* openex_string = NULL; uint8_t latency_timer; - LOG_DEBUG("'ft2232' interface using FTD2XX with '%s' layout (%4.4x:%4.4x)", ft2232_layout, vid, pid); + 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 */ @@ -1862,7 +2128,7 @@ static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int* try_mor } 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'\n", + LOG_WARNING("Unable to open FTDI Device tried: '%s' and '%s'", ft2232_device_desc, ft2232_device_desc_A); } @@ -1895,7 +2161,7 @@ static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int* try_mor if (status == FT_OK) { - LOG_ERROR("ListDevices: %lu\n", num_devices); + LOG_ERROR("ListDevices: %lu", num_devices); for (i = 0; i < num_devices; i++) LOG_ERROR("%" PRIu32 ": \"%s\"", i, desc_array[i]); } @@ -1907,7 +2173,7 @@ static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int* try_mor } else { - LOG_ERROR("ListDevices: NONE\n"); + LOG_ERROR("ListDevices: NONE"); } return ERROR_JTAG_INIT_FAILED; } @@ -1977,17 +2243,25 @@ static int ft2232_purge_ftd2xx(void) #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) +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)", - ft2232_layout, vid, pid); + layout->name, vid, pid); if (ftdi_init(&ftdic) < 0) return ERROR_JTAG_INIT_FAILED; - if (ftdi_set_interface(&ftdic, INTERFACE_A) < 0) + /* 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; @@ -2059,8 +2333,6 @@ static int ft2232_init(void) uint8_t buf[1]; int retval; uint32_t bytes_written; - const struct ft2232_layout* cur_layout = ft2232_layouts; - int i; if (tap_get_tms_path_len(TAP_IRPAUSE,TAP_IRPAUSE) == 7) { @@ -2071,29 +2343,12 @@ static int ft2232_init(void) LOG_DEBUG("ft2232 interface using shortest path jtag state transitions"); } - if ((ft2232_layout == NULL) || (ft2232_layout[0] == 0)) - { - ft2232_layout = "usbjtag"; - LOG_WARNING("No ft2232 layout specified, using default 'usbjtag'"); - } - - while (cur_layout->name) - { - if (strcmp(cur_layout->name, ft2232_layout) == 0) - { - layout = cur_layout; - break; - } - cur_layout++; - } - - if (!layout) - { - LOG_ERROR("No matching layout found for %s", ft2232_layout); + if (layout == NULL) { + LOG_WARNING("No ft2232 layout specified'"); return ERROR_JTAG_INIT_FAILED; } - for (i = 0; 1; i++) + for (int i = 0; 1; i++) { /* * "more indicates that there are more IDs to try, so we should @@ -2112,7 +2367,7 @@ static int ft2232_init(void) more, &try_more); #elif BUILD_FT2232_LIBFTDI == 1 retval = ft2232_init_libftdi(ft2232_vid[i], ft2232_pid[i], - more, &try_more); + more, &try_more, layout->channel); #endif if (retval >= 0) break; @@ -2140,10 +2395,14 @@ static int ft2232_init(void) return ERROR_JTAG_INIT_FAILED; } - ft2232_speed(jtag_get_speed()); + int jtag_speed_var; + retval = jtag_get_speed(&jtag_speed_var); + if (retval != ERROR_OK) + return retval; + ft2232_speed(jtag_speed_var); buf[0] = 0x85; /* Disconnect TDI/DO to TDO/DI for Loopback */ - if (((retval = ft2232_write(buf, 1, &bytes_written)) != ERROR_OK) || (bytes_written != 1)) + if ((retval = ft2232_write(buf, 1, &bytes_written)) != ERROR_OK) { LOG_ERROR("couldn't write to FT2232 to disable loopback"); return ERROR_JTAG_INIT_FAILED; @@ -2158,51 +2417,23 @@ static int ft2232_init(void) return ERROR_OK; } -static int usbjtag_init(void) +/** 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) { - uint8_t buf[3]; - uint32_t bytes_written; - low_output = 0x08; low_direction = 0x0b; +} - if (strcmp(ft2232_layout, "usbjtag") == 0) - { - nTRST = 0x10; - nTRSTnOE = 0x10; - nSRST = 0x40; - nSRSTnOE = 0x40; - } - else if (strcmp(ft2232_layout, "signalyzer") == 0) - { - nTRST = 0x10; - nTRSTnOE = 0x10; - nSRST = 0x20; - nSRSTnOE = 0x20; - } - else if (strcmp(ft2232_layout, "evb_lm3s811") == 0) - { - nTRST = 0x0; - nTRSTnOE = 0x00; - nSRST = 0x20; - nSRSTnOE = 0x20; - low_output = 0x88; - low_direction = 0x8b; - } - else if (strcmp(ft2232_layout, "luminary_icdi") == 0) - { - nTRST = 0x0; - nTRSTnOE = 0x00; - nSRST = 0x20; - nSRSTnOE = 0x20; - low_output = 0x88; - low_direction = 0xcb; - } - else - { - LOG_ERROR("BUG: usbjtag_init called for unknown layout '%s'", ft2232_layout); - return ERROR_JTAG_INIT_FAILED; - } +/** 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) +{ + uint8_t buf[3]; + uint32_t bytes_written; enum reset_types jtag_reset_config = jtag_get_reset_config(); if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) @@ -2233,15 +2464,104 @@ static int usbjtag_init(void) buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in */ LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'USBJTAG' layout"); + 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) { uint8_t buf[3]; @@ -2256,7 +2576,7 @@ static int axm0432_jtag_init(void) buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */ LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2303,7 +2623,7 @@ static int axm0432_jtag_init(void) buf[2] = high_direction; /* all outputs (xRST and xRSTnOE) */ LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'Dicarlo' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2312,6 +2632,71 @@ static int axm0432_jtag_init(void) return ERROR_OK; } +static int redbee_init(void) +{ + uint8_t buf[3]; + uint32_t bytes_written; + + low_output = 0x08; + low_direction = 0x2b; + + /* initialize low byte for jtag */ + /* command "set data bits low byte" */ + buf[0] = 0x80; + /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */ + buf[2] = low_direction; + /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */ + buf[1] = low_output; + 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 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 port */ + buf[0] = 0x82; /* command "set data bits high byte" */ + buf[1] = high_output; /* value */ + buf[2] = high_direction; /* all outputs (xRST and xRSTnOE) */ + 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 FT2232 with 'redbee' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + static int jtagkey_init(void) { uint8_t buf[3]; @@ -2326,7 +2711,7 @@ static int jtagkey_init(void) buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */ LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2385,7 +2770,7 @@ static int jtagkey_init(void) buf[2] = high_direction; /* all outputs (xRST and xRSTnOE) */ LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2408,7 +2793,7 @@ static int olimex_jtag_init(void) buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */ LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'Olimex' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2452,7 +2837,7 @@ static int olimex_jtag_init(void) buf[2] = high_direction; /* all outputs (xRST and xRSTnOE) */ LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if ((ft2232_write(buf, 3, &bytes_written) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'Olimex' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2475,7 +2860,7 @@ static int flyswatter_init(void) buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE[12]=out, n[ST]srst = out */ LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2498,7 +2883,7 @@ static int flyswatter_init(void) buf[2] = high_direction; /* all outputs (xRST and xRSTnOE) */ LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2521,7 +2906,7 @@ static int turtle_init(void) buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */ LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2538,7 +2923,7 @@ static int turtle_init(void) buf[2] = high_direction; LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2561,7 +2946,7 @@ static int comstick_init(void) buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */ LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'comstick' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2581,7 +2966,7 @@ static int comstick_init(void) buf[2] = high_direction; LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'comstick' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2604,7 +2989,7 @@ static int stm32stick_init(void) buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */ LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2624,7 +3009,7 @@ static int stm32stick_init(void) buf[2] = high_direction; LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2647,7 +3032,7 @@ static int sheevaplug_init(void) buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in */ LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'sheevaplug' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2675,7 +3060,7 @@ static int sheevaplug_init(void) buf[2] = high_direction; /* all outputs - xRST */ LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'sheevaplug' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2698,7 +3083,7 @@ static int cortino_jtag_init(void) buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */ LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'cortino' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2718,7 +3103,7 @@ static int cortino_jtag_init(void) buf[2] = high_direction; LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2727,6 +3112,66 @@ static int cortino_jtag_init(void) return ERROR_OK; } +static int lisa_l_init(void) +{ + uint8_t buf[3]; + uint32_t bytes_written; + + ftx232_dbus_init(); + + nTRST = 0x10; + nTRSTnOE = 0x10; + nSRST = 0x40; + nSRSTnOE = 0x40; + + high_output = 0x00; + high_direction = 0x18; + + /* initialize high port */ + buf[0] = 0x82; /* command "set data bits high byte" */ + buf[1] = high_output; + buf[2] = high_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 FT2232 with 'lisa_l' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ftx232_dbus_write(); +} + +static int flossjtag_init(void) +{ + uint8_t buf[3]; + uint32_t bytes_written; + + ftx232_dbus_init(); + + nTRST = 0x10; + nTRSTnOE = 0x10; + nSRST = 0x40; + nSRSTnOE = 0x40; + + high_output = 0x00; + high_direction = 0x18; + + /* initialize high port */ + buf[0] = 0x82; /* command "set data bits high byte" */ + buf[1] = high_output; + buf[2] = high_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 FT2232 with 'Floss-JTAG' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ftx232_dbus_write(); +} + static void olimex_jtag_blink(void) { /* Olimex ARM-USB-OCD has a LED connected to ACBUS3 @@ -2779,6 +3224,44 @@ static void turtle_jtag_blink(void) 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 @@ -2847,13 +3330,28 @@ COMMAND_HANDLER(ft2232_handle_serial_command) COMMAND_HANDLER(ft2232_handle_layout_command) { - if (CMD_ARGC == 0) - return ERROR_OK; + if (CMD_ARGC != 1) { + LOG_ERROR("Need exactly one argument to ft2232_layout"); + return ERROR_FAIL; + } - ft2232_layout = malloc(strlen(CMD_ARGV[0]) + 1); - strcpy(ft2232_layout, CMD_ARGV[0]); + if (layout) { + LOG_ERROR("already specified ft2232_layout %s", + layout->name); + return (strcmp(layout->name, CMD_ARGV[0]) != 0) + ? ERROR_FAIL + : ERROR_OK; + } - return ERROR_OK; + for (const struct ft2232_layout *l = ft2232_layouts; l->name; l++) { + if (strcmp(l->name, CMD_ARGV[0]) == 0) { + layout = l; + return ERROR_OK; + } + } + + LOG_ERROR("No FT2232 layout '%s' found", CMD_ARGV[0]); + return ERROR_FAIL; } COMMAND_HANDLER(ft2232_handle_vid_pid_command) @@ -2998,7 +3496,7 @@ static int icebear_jtag_init(void) { buf[2] = low_direction; LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) { + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'IceBear' layout (low)"); return ERROR_JTAG_INIT_FAILED; } @@ -3013,7 +3511,7 @@ static int icebear_jtag_init(void) { buf[2] = high_direction; /* all outputs (xRST and xRSTnOE) */ LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) { + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'IceBear' layout (high)"); return ERROR_JTAG_INIT_FAILED; } @@ -3660,8 +4158,7 @@ static int signalyzer_h_init(void) buf[1] = low_output; buf[2] = low_direction; - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) - || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize Signalyzer-H layout"); return ERROR_JTAG_INIT_FAILED; @@ -3675,8 +4172,7 @@ static int signalyzer_h_init(void) buf[1] = high_output; buf[2] = high_direction; - if ((ft2232_write(buf, 3, &bytes_written) != ERROR_OK) - || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize Signalyzer-H layout"); return ERROR_JTAG_INIT_FAILED; @@ -3690,8 +4186,7 @@ static int signalyzer_h_init(void) buf[1] = high_output; buf[2] = high_direction; - if ((ft2232_write(buf, 3, &bytes_written) != ERROR_OK) - || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize Signalyzer-H layout"); return ERROR_JTAG_INIT_FAILED; @@ -3875,7 +4370,7 @@ static int ktlink_init(void) buf[2] = low_direction; LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'ktlink' layout"); return ERROR_JTAG_INIT_FAILED; @@ -3913,7 +4408,7 @@ static int ktlink_init(void) buf[2] = high_direction; LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'ktlink' layout"); return ERROR_JTAG_INIT_FAILED; @@ -3975,14 +4470,14 @@ static const struct command_registration ft2232_command_handlers[] = { .handler = &ft2232_handle_device_desc_command, .mode = COMMAND_CONFIG, .help = "set the USB device description of the FTDI FT2232 device", - .usage = "", + .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 = "", + .usage = "serial_string", }, { .name = "ft2232_layout", @@ -3990,32 +4485,35 @@ static const struct command_registration ft2232_command_handlers[] = { .mode = COMMAND_CONFIG, .help = "set the layout of the FT2232 GPIO signals used " "to control output-enables and reset signals", - .usage = "", + .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 = " [...]", + .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 = " [...]", + .usage = "value", }, COMMAND_REGISTRATION_DONE }; struct jtag_interface ft2232_interface = { - .name = "ft2232", - .commands = ft2232_command_handlers, - .init = &ft2232_init, - .quit = &ft2232_quit, - .speed = &ft2232_speed, - .speed_div = &ft2232_speed_div, - .khz = &ft2232_khz, - .execute_queue = &ft2232_execute_queue, - }; + .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, +};