jtag/drivers/openjtag: Add support for Cypress CY7C65215 05/2805/13
authorVianney le Clément de Saint-Marcq <vianney.leclement@essensium.com>
Tue, 2 Jun 2015 14:55:42 +0000 (16:55 +0200)
committerPaul Fertser <fercerpav@gmail.com>
Thu, 8 Dec 2016 12:35:23 +0000 (12:35 +0000)
The Cypress CY7C65215 Dual Channel USB-Serial Bridge Controller [1]
understands the OpenJTAG protocol over a proprietary USB interface.

This patch adds support for the CY7C65215 to the openjtag interface
driver.  A new configuration option, `openjtag_variant`, allows to
select the transport to use.

Libusb (1.x or 0.1) is now a hard dependency of the openjtag driver.
This should not be a big issue as libftdi also depends on it.

[1] http://www.cypress.com/?rID=82870

Change-Id: I55ffb3fd9e006eb311e405d9fb836bb119644bfd
Signed-off-by: Vianney le Clément de Saint-Marcq <vianney.leclement@essensium.com>
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
Reviewed-on: http://openocd.zylin.com/2805
Tested-by: jenkins
Reviewed-by: Jiri Kastner <cz172638@gmail.com>
Reviewed-by: Paul Fertser <fercerpav@gmail.com>
configure.ac
doc/openocd.texi
src/jtag/drivers/openjtag.c

index a47a18417a6708af833e183b06f0aaf422eb9252..1e6be14173a035405b1f8c4d38cba921108274d3 100644 (file)
@@ -782,6 +782,13 @@ PROCESS_ADAPTERS([USB0_ADAPTERS], [$use_libusb0 = yes], [libusb-0.1])
 PROCESS_ADAPTERS([HIDAPI_ADAPTERS], [$use_hidapi = yes], [hidapi])
 PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], [$use_libusb1 = yes -a $use_internal_libjaylink = yes -o $HAVE_LIBJAYLINK = yes], [libusb-1.x or libjaylink-0.1])
 
+if test $build_openjtag = yes; then
+       if test $use_libusb1 != yes -a $use_libusb0 != yes; then
+               AC_MSG_ERROR([libusb-1.x or libusb-0.1 is required for the OpenJTAG Programmer])
+               build_openjtag=no
+       fi
+fi
+
 if test $enable_stlink != no -o $enable_ti_icdi != no; then
        AC_DEFINE([BUILD_HLADAPTER], [1], [1 if you want the High Level JTAG driver.])
 else
index 1cca4ab11a626d8f43982aaa0955203213de7317..7c2152b1c927a8987cc0b35a480f61513c8478cd 100644 (file)
@@ -2912,6 +2912,27 @@ pinout.
 
 @end deffn
 
+@deffn {Interface Driver} {openjtag}
+OpenJTAG compatible USB adapter.
+This defines some driver-specific commands:
+
+@deffn {Config Command} {openjtag_variant} variant
+Specifies the variant of the OpenJTAG adapter (see @uref{http://www.openjtag.org/}).
+Currently valid @var{variant} values include:
+
+@itemize @minus
+@item @b{standard} Standard variant (default).
+@item @b{cy7c65215} Cypress CY7C65215 Dual Channel USB-Serial Bridge Controller
+(see @uref{http://www.cypress.com/?rID=82870}).
+@end itemize
+@end deffn
+
+@deffn {Config Command} {openjtag_device_desc} string
+The USB device description string of the adapter.
+This value is only used with the standard variant.
+@end deffn
+@end deffn
+
 @section Transport Configuration
 @cindex Transport
 As noted earlier, depending on the version of OpenOCD you use,
index 5d1084cebcb9d0d4c2997c5af1bebf21f3f8ab89..bb0ff74db77ce27c4ebecd2d5aab652b51307bfd 100644 (file)
@@ -1,6 +1,10 @@
 /*******************************************************************************
  *   Driver for OpenJTAG Project (www.openjtag.org)                            *
- *   Compatible with libftdi driver.                                           *
+ *   Compatible with libftdi and ftd2xx drivers.                               *
+ *                                                                             *
+ *   Cypress CY7C65215 support                                                 *
+ *   Copyright (C) 2015 Vianney le Clément de Saint-Marcq, Essensium NV        *
+ *                      <vianney.leclement@essensium.com>                      *
  *                                                                             *
  *   Copyright (C) 2010 by Ivan Meleca <mileca@gmail.com>                      *
  *                                                                             *
 
 #include <jtag/interface.h>
 #include <jtag/commands.h>
-#include "usb_common.h"
+#include "libusb_common.h"
+
+static enum {
+       OPENJTAG_VARIANT_STANDARD,
+       OPENJTAG_VARIANT_CY7C65215,
+} openjtag_variant = OPENJTAG_VARIANT_STANDARD;
+
+static const char * const openjtag_variant_names[] = {
+       "standard",
+       "cy7c65215",
+       NULL
+};
 
 /*
  * OpenJTAG-OpenOCD state conversion
@@ -96,10 +111,24 @@ static uint8_t usb_rx_buf[OPENJTAG_BUFFER_SIZE];
 static struct openjtag_scan_result openjtag_scan_result_buffer[OPENJTAG_MAX_PENDING_RESULTS];
 static int openjtag_scan_result_count;
 
-/* Openocd usb handler */
-struct openocd {
-       struct usb_dev_handle *usb_handle;
-};
+static jtag_libusb_device_handle *usbh;
+
+/* CY7C65215 model only */
+#define CY7C65215_JTAG_REQUEST  0x40  /* bmRequestType: vendor host-to-device */
+#define CY7C65215_JTAG_ENABLE   0xD0  /* bRequest: enable JTAG */
+#define CY7C65215_JTAG_DISABLE  0xD1  /* bRequest: disable JTAG */
+#define CY7C65215_JTAG_READ     0xD2  /* bRequest: read buffer */
+#define CY7C65215_JTAG_WRITE    0xD3  /* bRequest: write buffer */
+
+#define CY7C65215_USB_TIMEOUT   100
+
+static const uint16_t cy7c65215_vids[] = {0x04b4, 0};
+static const uint16_t cy7c65215_pids[] = {0x0007, 0};
+
+#define CY7C65215_JTAG_CLASS     0xff
+#define CY7C65215_JTAG_SUBCLASS  0x04
+
+static unsigned int ep_in, ep_out;
 
 #ifdef _DEBUG_USB_COMMS_
 
@@ -185,7 +214,7 @@ static int8_t openjtag_get_tap_state(int8_t state)
        }
 }
 
-static int openjtag_buf_write(
+static int openjtag_buf_write_standard(
        uint8_t *buf, int size, uint32_t *bytes_written)
 {
        int retval;
@@ -205,8 +234,54 @@ static int openjtag_buf_write(
        return ERROR_OK;
 }
 
-static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read)
+static int openjtag_buf_write_cy7c65215(
+       uint8_t *buf, int size, uint32_t *bytes_written)
+{
+       int ret;
+
+#ifdef _DEBUG_USB_COMMS_
+       openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE);
+#endif
+
+       if (size == 0) {
+               *bytes_written = 0;
+               return ERROR_OK;
+       }
+
+       ret = jtag_libusb_control_transfer(usbh, CY7C65215_JTAG_REQUEST,
+                                                                          CY7C65215_JTAG_WRITE, size, 0,
+                                                                          NULL, 0, CY7C65215_USB_TIMEOUT);
+       if (ret < 0) {
+               LOG_ERROR("vendor command failed, error %d", ret);
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+
+       ret = jtag_libusb_bulk_write(usbh, ep_out, (char *)buf, size,
+                                                                CY7C65215_USB_TIMEOUT);
+       if (ret < 0) {
+               LOG_ERROR("bulk write failed, error %d", ret);
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+       *bytes_written = ret;
+
+       return ERROR_OK;
+}
+
+static int openjtag_buf_write(
+       uint8_t *buf, int size, uint32_t *bytes_written)
+{
+       switch (openjtag_variant) {
+       case OPENJTAG_VARIANT_CY7C65215:
+               return openjtag_buf_write_cy7c65215(buf, size, bytes_written);
+       default:
+               return openjtag_buf_write_standard(buf, size, bytes_written);
+       }
+}
+
+static int openjtag_buf_read_standard(
+       uint8_t *buf, uint32_t qty, uint32_t *bytes_read)
 {
+
        int retval;
        int timeout = 5;
 
@@ -231,6 +306,50 @@ static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read)
        return ERROR_OK;
 }
 
+static int openjtag_buf_read_cy7c65215(
+       uint8_t *buf, uint32_t qty, uint32_t *bytes_read)
+{
+       int ret;
+
+       if (qty == 0) {
+               *bytes_read = 0;
+               goto out;
+       }
+
+       ret = jtag_libusb_control_transfer(usbh, CY7C65215_JTAG_REQUEST,
+                                                                          CY7C65215_JTAG_READ, qty, 0,
+                                                                          NULL, 0, CY7C65215_USB_TIMEOUT);
+       if (ret < 0) {
+               LOG_ERROR("vendor command failed, error %d", ret);
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+
+       ret = jtag_libusb_bulk_read(usbh, ep_in, (char *)buf, qty,
+                                                               CY7C65215_USB_TIMEOUT);
+       if (ret < 0) {
+               LOG_ERROR("bulk read failed, error %d", ret);
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+       *bytes_read = ret;
+
+out:
+#ifdef _DEBUG_USB_COMMS_
+       openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ);
+#endif
+
+       return ERROR_OK;
+}
+
+static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read)
+{
+       switch (openjtag_variant) {
+       case OPENJTAG_VARIANT_CY7C65215:
+               return openjtag_buf_read_cy7c65215(buf, qty, bytes_read);
+       default:
+               return openjtag_buf_read_standard(buf, qty, bytes_read);
+       }
+}
+
 static int openjtag_sendcommand(uint8_t cmd)
 {
        uint32_t written;
@@ -275,16 +394,10 @@ static int openjtag_speed(int speed)
        return ERROR_OK;
 }
 
-static int openjtag_init(void)
+static int openjtag_init_standard(void)
 {
        uint8_t latency_timer;
 
-       usb_tx_buf_offs = 0;
-       usb_rx_buf_len = 0;
-       openjtag_scan_result_count = 0;
-
-       LOG_DEBUG("'openjtag' interface using libftdi");
-
        /* Open by device description */
        if (openjtag_device_desc == NULL) {
                LOG_WARNING("no openjtag device description specified, "
@@ -330,16 +443,70 @@ static int openjtag_init(void)
                return ERROR_JTAG_INIT_FAILED;
        }
 
-       /* OpenJTAG speed */
-       openjtag_sendcommand(0xE0); /*Start at slowest adapter speed*/
+       return ERROR_OK;
+}
+
+static int openjtag_init_cy7c65215(void)
+{
+       int ret;
+
+       usbh = NULL;
+       ret = jtag_libusb_open(cy7c65215_vids, cy7c65215_pids, NULL, &usbh);
+       if (ret != ERROR_OK) {
+               LOG_ERROR("unable to open cy7c65215 device");
+               goto err;
+       }
+
+       ret = jtag_libusb_choose_interface(usbh, &ep_in, &ep_out,
+                                                                          CY7C65215_JTAG_CLASS,
+                                                                          CY7C65215_JTAG_SUBCLASS, -1);
+       if (ret != ERROR_OK) {
+               LOG_ERROR("unable to claim JTAG interface");
+               goto err;
+       }
 
-       /* MSB */
-       openjtag_sendcommand(0x75);
+       ret = jtag_libusb_control_transfer(usbh,
+                                                                          CY7C65215_JTAG_REQUEST,
+                                                                          CY7C65215_JTAG_ENABLE,
+                                                                          0, 0, NULL, 0, CY7C65215_USB_TIMEOUT);
+       if (ret < 0) {
+               LOG_ERROR("could not enable JTAG module");
+               goto err;
+       }
 
        return ERROR_OK;
+
+err:
+       if (usbh != NULL)
+               jtag_libusb_close(usbh);
+       return ERROR_JTAG_INIT_FAILED;
 }
 
-static int openjtag_quit(void)
+static int openjtag_init(void)
+{
+       int ret;
+
+       usb_tx_buf_offs = 0;
+       usb_rx_buf_len = 0;
+       openjtag_scan_result_count = 0;
+
+       switch (openjtag_variant) {
+       case OPENJTAG_VARIANT_CY7C65215:
+               ret = openjtag_init_cy7c65215();
+               break;
+       default:
+               ret = openjtag_init_standard();
+       }
+       if (ret != ERROR_OK)
+               return ret;
+
+       openjtag_speed(375); /* Start at slowest adapter speed */
+       openjtag_sendcommand(0x75); /* MSB */
+
+       return ERROR_OK;
+}
+
+static int openjtag_quit_standard(void)
 {
        ftdi_usb_close(&ftdic);
        ftdi_deinit(&ftdic);
@@ -347,6 +514,32 @@ static int openjtag_quit(void)
        return ERROR_OK;
 }
 
+static int openjtag_quit_cy7c65215(void)
+{
+       int ret;
+
+       ret = jtag_libusb_control_transfer(usbh,
+                                                                          CY7C65215_JTAG_REQUEST,
+                                                                          CY7C65215_JTAG_DISABLE,
+                                                                          0, 0, NULL, 0, CY7C65215_USB_TIMEOUT);
+       if (ret < 0)
+               LOG_WARNING("could not disable JTAG module");
+
+       jtag_libusb_close(usbh);
+
+       return ERROR_OK;
+}
+
+static int openjtag_quit(void)
+{
+       switch (openjtag_variant) {
+       case OPENJTAG_VARIANT_CY7C65215:
+               return openjtag_quit_cy7c65215();
+       default:
+               return openjtag_quit_standard();
+       }
+}
+
 static void openjtag_write_tap_buffer(void)
 {
        uint32_t written;
@@ -379,8 +572,8 @@ static int openjtag_execute_tap_queue(void)
 
                        uint8_t *buffer = openjtag_scan_result_buffer[res_count].buffer;
 
-                       while (len) {
-                               if (len <= 8) {
+                       while (len > 0) {
+                               if (len <= 8 && openjtag_variant != OPENJTAG_VARIANT_CY7C65215) {
                                        DEBUG_JTAG_IO("bits < 8 buf = 0x%X, will be 0x%X",
                                                usb_rx_buf[rx_offs], usb_rx_buf[rx_offs] >> (8 - len));
                                        buffer[count] = usb_rx_buf[rx_offs] >> (8 - len);
@@ -567,11 +760,14 @@ static void openjtag_execute_runtest(struct jtag_command *cmd)
        if (cmd->cmd.runtest->num_cycles > 16)
                LOG_WARNING("num_cycles > 16 on run test");
 
-       uint8_t command;
-       command = 7;
-       command |= ((cmd->cmd.runtest->num_cycles - 1) & 0x0F) << 4;
+       if (openjtag_variant != OPENJTAG_VARIANT_CY7C65215 ||
+               cmd->cmd.runtest->num_cycles) {
+               uint8_t command;
+               command = 7;
+               command |= ((cmd->cmd.runtest->num_cycles - 1) & 0x0F) << 4;
 
-       openjtag_add_byte(command);
+               openjtag_add_byte(command);
+       }
 
        tap_set_end_state(end_state);
        if (tap_get_end_state() != tap_get_state()) {
@@ -659,6 +855,24 @@ COMMAND_HANDLER(openjtag_handle_device_desc_command)
        return ERROR_OK;
 }
 
+COMMAND_HANDLER(openjtag_handle_variant_command)
+{
+       if (CMD_ARGC == 1) {
+               const char * const *name = openjtag_variant_names;
+               int variant = 0;
+               for (; *name; name++, variant++) {
+                       if (strcasecmp(CMD_ARGV[0], *name) == 0) {
+                               openjtag_variant = variant;
+                               return ERROR_OK;
+                       }
+               }
+               LOG_ERROR("unknown openjtag variant '%s'", CMD_ARGV[0]);
+       } else {
+               LOG_ERROR("require exactly one argument to "
+                               "openjtag_variant <variant>");
+       }
+       return ERROR_OK;
+}
 
 static const struct command_registration openjtag_command_handlers[] = {
        {
@@ -668,6 +882,13 @@ static const struct command_registration openjtag_command_handlers[] = {
                .help = "set the USB device description of the OpenJTAG",
                .usage = "description-string",
        },
+       {
+               .name = "openjtag_variant",
+               .handler = openjtag_handle_variant_command,
+               .mode = COMMAND_CONFIG,
+               .help = "set the OpenJTAG variant",
+               .usage = "variant-string",
+       },
        COMMAND_REGISTRATION_DONE
 };
 

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)