]> git.sur5r.net Git - openocd/blobdiff - src/jtag/drivers/ft2232.c
transport: move files over to transport folder
[openocd] / src / jtag / drivers / ft2232.c
index e9eba541f3b2ec50a41b4b809b0bd72ab5422df3..38ead566cf3290fd619cb3a1666bb3d7dfb10b85 100644 (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.  Since JTAG uses
- * only one of the two parts on these devices, on integrated boards the
- * second port often serves as a USB-to-serial adapter for the target's
- * console UART even when the JTAG port is not in use.  (Systems which
- * support ARM's SWD in addition to JTAG, or instead of it, may use that
- * second port for reading SWV trace data.)
+ * 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.
@@ -69,6 +81,7 @@
 
 /* project specific includes */
 #include <jtag/interface.h>
+#include <transport/transport.h>
 #include <helper/time_support.h>
 
 #if IS_CYGWIN == 1
 /* FT2232 access library includes */
 #if BUILD_FT2232_FTD2XX == 1
 #include <ftd2xx.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
@@ -131,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;
 
@@ -145,13 +167,17 @@ 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 minimodule_init(void);
 static int turtle_init(void);
 static int comstick_init(void);
 static int stm32stick_init(void);
@@ -159,14 +185,20 @@ 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);
 
 /* 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);
+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);
@@ -175,6 +207,8 @@ 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);
 
 /* blink procedures for layouts that support a blinking led */
 static void olimex_jtag_blink(void);
@@ -182,36 +216,143 @@ 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 = "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 = 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
@@ -238,6 +379,12 @@ static int             require_send;
        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 = NULL;
@@ -364,7 +511,7 @@ 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;
+       DWORD dw_bytes_written = 0;
        if ((status = FT_Write(ftdih, buf, size, &dw_bytes_written)) != FT_OK)
        {
                *bytes_written = dw_bytes_written;
@@ -374,7 +521,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;
@@ -387,9 +533,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)
@@ -463,8 +615,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");
@@ -483,8 +636,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");
@@ -521,7 +674,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;
@@ -631,7 +784,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);
@@ -1246,7 +1399,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)
@@ -1417,6 +1571,24 @@ static void flyswatter_reset(int trst, int srst)
        LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", trst, srst, low_output, low_direction);
 }
 
+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)
 {
        trst = trst;
@@ -1517,6 +1689,66 @@ 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 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;
@@ -1618,6 +1850,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;
@@ -1770,20 +2068,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;
 }
@@ -1810,12 +2111,20 @@ static int ft2232_execute_queue(void)
 
        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 */
+               /* 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 > 256)
+
+               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;
@@ -1840,7 +2149,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 */
@@ -1888,7 +2202,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);
                        }
@@ -1921,7 +2235,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]);
                        }
@@ -1933,7 +2247,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;
        }
@@ -2003,17 +2317,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;
@@ -2080,13 +2402,51 @@ static int ft2232_purge_libftdi(void)
 
 #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;
-       const struct ft2232_layout* cur_layout = ft2232_layouts;
-       int i;
 
        if (tap_get_tms_path_len(TAP_IRPAUSE,TAP_IRPAUSE) == 7)
        {
@@ -2097,29 +2457,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
@@ -2138,7 +2481,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;
@@ -2166,10 +2509,8 @@ static int ft2232_init(void)
                        return ERROR_JTAG_INIT_FAILED;
        }
 
-       ft2232_speed(jtag_get_speed());
-
        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;
@@ -2184,60 +2525,21 @@ 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)
-       {
-               /* 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;
-       }
-       else if (strcmp(ft2232_layout, "luminary_icdi") == 0)
-       {
-               /* Most Luminary eval boards support SWO trace output,
-                * and should use this "luminary_icdi" layout.
-                */
-               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)
+{
        enum reset_types jtag_reset_config = jtag_get_reset_config();
        if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
        {
@@ -2262,35 +2564,111 @@ static int usbjtag_init(void)
        }
 
        /* initialize low byte for jtag */
-       buf[0] = 0x80;          /* command "set data bits low byte" */
-       buf[1] = low_output;    /* value (TMS = 1,TCK = 0, TDI = 0, xRST high) */
-       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_set_data_bits_low_byte(low_output,low_direction) != 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 axm0432_jtag_init(void)
+static int usbjtag_init(void)
 {
-       uint8_t  buf[3];
-       uint32_t bytes_written;
+       /*
+        * 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 */
-       buf[0] = 0x80;          /* command "set data bits low byte" */
-       buf[1] = low_output;    /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
-       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_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;
@@ -2331,13 +2709,8 @@ static int axm0432_jtag_init(void)
                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, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       /* 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;
@@ -2346,21 +2719,62 @@ static int axm0432_jtag_init(void)
        return ERROR_OK;
 }
 
-static int jtagkey_init(void)
+static int redbee_init(void)
 {
-       uint8_t  buf[3];
-       uint32_t bytes_written;
+       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 */
-       buf[0] = 0x80;          /* command "set data bits low byte" */
-       buf[1] = low_output;    /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
-       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_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;
@@ -2413,13 +2827,8 @@ static int jtagkey_init(void)
                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, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       /* 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;
@@ -2430,19 +2839,11 @@ static int jtagkey_init(void)
 
 static int olimex_jtag_init(void)
 {
-       uint8_t  buf[3];
-       uint32_t bytes_written;
-
        low_output    = 0x08;
        low_direction = 0x1b;
 
        /* initialize low byte for jtag */
-       buf[0] = 0x80;          /* command "set data bits low byte" */
-       buf[1] = low_output;    /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
-       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_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;
@@ -2480,13 +2881,8 @@ static int olimex_jtag_init(void)
        /* turn red LED on */
        high_output |= 0x08;
 
-       /* 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, 3, &bytes_written) != ERROR_OK) || (bytes_written != 3))
+       /* 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;
@@ -2497,19 +2893,11 @@ static int olimex_jtag_init(void)
 
 static int flyswatter_init(void)
 {
-       uint8_t  buf[3];
-       uint32_t bytes_written;
-
        low_output    = 0x18;
        low_direction = 0xfb;
 
        /* initialize low byte for jtag */
-       buf[0] = 0x80;          /* command "set data bits low byte" */
-       buf[1] = low_output;    /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
-       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_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;
@@ -2526,13 +2914,8 @@ static int flyswatter_init(void)
        /* turn red LED3 on, LED2 off */
        high_output |= 0x08;
 
-       /* 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, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       /* 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;
@@ -2541,21 +2924,44 @@ static int flyswatter_init(void)
        return ERROR_OK;
 }
 
-static int turtle_init(void)
+static int minimodule_init(void)
 {
-       uint8_t  buf[3];
-       uint32_t bytes_written;
+       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 */
-       buf[0] = 0x80;          /* command "set data bits low byte" */
-       buf[1] = low_output;    /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
-       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_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;
@@ -2566,13 +2972,8 @@ static int turtle_init(void)
        high_output    = 0x00;
        high_direction = 0x0C;
 
-       /* 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, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       /* 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;
@@ -2583,19 +2984,11 @@ static int turtle_init(void)
 
 static int comstick_init(void)
 {
-       uint8_t  buf[3];
-       uint32_t bytes_written;
-
        low_output    = 0x08;
        low_direction = 0x0b;
 
        /* initialize low byte for jtag */
-       buf[0] = 0x80;          /* command "set data bits low byte" */
-       buf[1] = low_output;    /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
-       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_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;
@@ -2609,13 +3002,8 @@ static int comstick_init(void)
        high_output    = 0x03;
        high_direction = 0x03;
 
-       /* 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, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       /* 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;
@@ -2626,19 +3014,11 @@ static int comstick_init(void)
 
 static int stm32stick_init(void)
 {
-       uint8_t  buf[3];
-       uint32_t bytes_written;
-
        low_output    = 0x88;
        low_direction = 0x8b;
 
        /* initialize low byte for jtag */
-       buf[0] = 0x80;          /* command "set data bits low byte" */
-       buf[1] = low_output;    /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
-       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_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;
@@ -2652,13 +3032,8 @@ static int stm32stick_init(void)
        high_output    = 0x01;
        high_direction = 0x03;
 
-       /* 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, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       /* 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;
@@ -2669,19 +3044,11 @@ static int stm32stick_init(void)
 
 static int sheevaplug_init(void)
 {
-       uint8_t buf[3];
-       uint32_t bytes_written;
-
        low_output = 0x08;
        low_direction = 0x1b;
 
        /* initialize low byte for jtag */
-       buf[0] = 0x80; /* command "set data bits low byte" */
-       buf[1] = low_output; /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
-       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_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;
@@ -2703,13 +3070,8 @@ static int sheevaplug_init(void)
        high_output |= nSRSTnOE;
        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 */
-       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))
+       /* 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;
@@ -2720,19 +3082,11 @@ static int sheevaplug_init(void)
 
 static int cortino_jtag_init(void)
 {
-       uint8_t  buf[3];
-       uint32_t bytes_written;
-
        low_output    = 0x08;
        low_direction = 0x1b;
 
        /* initialize low byte for jtag */
-       buf[0] = 0x80;          /* command "set data bits low byte" */
-       buf[1] = low_output;    /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
-       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_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;
@@ -2746,15 +3100,94 @@ static int cortino_jtag_init(void)
        high_output    = 0x03;
        high_direction = 0x03;
 
-       /* 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]);
+       /* 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;
 
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       /* 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");
+               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();
+}
+
+static int xds100v2_init(void)
+{
+       low_output    = 0x3A;
+       low_direction = 0x7B;
+
+       /* 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 'xds100v2' layout");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       nTRST    = 0x10;
+       nTRSTnOE = 0x0;     /* not output enable for nTRST */
+       nSRST    = 0x00;    /* TODO: SRST is not supported yet */
+       nSRSTnOE = 0x00;    /* no output enable for nSRST */
+
+       high_output    = 0x00;
+       high_direction = 0x59;
+
+       /* 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 'xds100v2' layout");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       high_output    = 0x86;
+       high_direction = 0x59;
+
+       /* 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 'xds100v2' layout");
                return ERROR_JTAG_INIT_FAILED;
        }
 
@@ -2766,16 +3199,7 @@ static void olimex_jtag_blink(void)
        /* Olimex ARM-USB-OCD has a LED connected to ACBUS3
         * ACBUS3 is bit 3 of the GPIOH port
         */
-       if (high_output & 0x08)
-       {
-               /* set port pin high */
-               high_output &= 0x07;
-       }
-       else
-       {
-               /* set port pin low */
-               high_output |= 0x08;
-       }
+       high_output ^= 0x08;
 
        buffer_write(0x82);
        buffer_write(high_output);
@@ -2813,6 +3237,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
@@ -2881,13 +3343,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)
@@ -3006,9 +3483,6 @@ static int ft2232_stableclocks(int num_cycles, struct jtag_command* cmd)
  * ADBUS7 -   GND
  */
 static int icebear_jtag_init(void) {
-       uint8_t  buf[3];
-       uint32_t bytes_written;
-
        low_direction   = 0x0b; /* output: TCK TDI TMS; input: TDO */
        low_output      = 0x08; /* high: TMS; low: TCK TDI */
        nTRST           = 0x10;
@@ -3027,12 +3501,7 @@ static int icebear_jtag_init(void) {
        low_output      |= nSRST;
 
        /* initialize low byte for jtag */
-       buf[0] = 0x80;          /* command "set data bits low byte" */
-       buf[1] = low_output;
-       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_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;
        }
@@ -3040,14 +3509,8 @@ static int icebear_jtag_init(void) {
        high_output    = 0x0;
        high_direction = 0x00;
 
-
-       /* 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, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) {
+       /* 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;
        }
@@ -3244,8 +3707,6 @@ static int signalyzer_h_init(void)
        char *end_of_desc;
 
        uint16_t read_buf[12] = { 0 };
-       uint8_t  buf[3];
-       uint32_t bytes_written;
 
        /* turn on center green led */
        signalyzer_h_led_set(SIGNALYZER_CHAN_C, SIGNALYZER_LED_GREEN,
@@ -3690,12 +4151,7 @@ static int signalyzer_h_init(void)
        }
 
        /* initialize low byte of controller for jtag operation */
-       buf[0] = 0x80;
-       buf[1] = low_output;
-       buf[2] = low_direction;
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK)
-                       || (bytes_written != 3))
+       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;
@@ -3705,12 +4161,7 @@ static int signalyzer_h_init(void)
        if (ftdi_device == FT_DEVICE_2232H)
        {
                /* initialize high byte of controller for jtag operation */
-               buf[0] = 0x82;
-               buf[1] = high_output;
-               buf[2] = high_direction;
-
-               if ((ft2232_write(buf, 3, &bytes_written) != ERROR_OK)
-                               || (bytes_written != 3))
+               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;
@@ -3720,12 +4171,7 @@ static int signalyzer_h_init(void)
        if (ftdi_device == TYPE_2232H)
        {
                /* initialize high byte of controller for jtag operation */
-               buf[0] = 0x82;
-               buf[1] = high_output;
-               buf[2] = high_direction;
-
-               if ((ft2232_write(buf, 3, &bytes_written) != ERROR_OK)
-                               || (bytes_written != 3))
+               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;
@@ -3896,20 +4342,13 @@ static void signalyzer_h_blink(void)
  *******************************************************************/
 static int ktlink_init(void)
 {
-       uint8_t  buf[3];
-       uint32_t bytes_written;
        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 port
-       buf[0] = 0x80;          // command "set data bits low byte"
-       buf[1] = low_output;
-       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))
+       /* 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;
@@ -3941,13 +4380,8 @@ static int ktlink_init(void)
                high_output &= ~nSRST;
        }
 
-       // initialize high port
-       buf[0] = 0x82;              // command "set data bits high byte"
-       buf[1] = high_output;       // value
-       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))
+       /* 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;
@@ -3993,10 +4427,7 @@ static void ktlink_reset(int trst, int srst)
 static void ktlink_blink(void)
 {
        /* LED connected to ACBUS7 */
-       if (high_output & 0x80)
-               high_output &= 0x7F;
-       else
-               high_output |= 0x80;
+       high_output ^= 0x80;
 
        buffer_write(0x82);  // command "set data bits high byte"
        buffer_write(high_output);
@@ -4045,7 +4476,9 @@ static const struct command_registration ft2232_command_handlers[] = {
 
 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,