openocd: fix SPDX tag format for files .c
[fw/openocd] / src / jtag / drivers / xds110.c
index f0899246b4ca8fb034816228f9538f0517493f20..ecba36bb9a2e7f1472cdf1ecd1c90aa678b43766 100644 (file)
@@ -1,18 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
 /***************************************************************************
  *   Copyright (C) 2017 by Texas Instruments, Inc.                         *
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
 #endif
 
 #include <transport/transport.h>
+#include <jtag/adapter.h>
 #include <jtag/swd.h>
 #include <jtag/interface.h>
 #include <jtag/commands.h>
 #include <jtag/tcl.h>
 #include <libusb.h>
 
-/* XDS110 USB serial number length */
-#define XDS110_SERIAL_LEN 8
-
 /* XDS110 stand-alone probe voltage supply limits */
 #define XDS110_MIN_VOLTAGE 1800
 #define XDS110_MAX_VOLTAGE 3600
 #define OCD_FIRMWARE_UPGRADE \
        "XDS110: upgrade to version 2.3.0.11+ for improved support"
 
+/* Firmware version that introduced improved TCK performance */
+#define FAST_TCK_FIRMWARE_VERSION 0x03000000
+
+/* Firmware version that introduced 10 MHz and 12 MHz TCK support */
+#define FAST_TCK_PLUS_FIRMWARE_VERSION 0x03000003
+
 /***************************************************************************
  *   USB Connection Buffer Definitions                                     *
  ***************************************************************************/
 #endif
 #define MAX_RESULT_QUEUE (MAX_DATA_BLOCK / 4)
 
-/***************************************************************************
- *   USB Connection Endpoints                                              *
- ***************************************************************************/
-
-/* Bulk endpoints used by the XDS110 debug interface */
-#define INTERFACE_DEBUG (2)
-#define ENDPOINT_DEBUG_IN (3 | LIBUSB_ENDPOINT_IN)
-#define ENDPOINT_DEBUG_OUT (2 | LIBUSB_ENDPOINT_OUT)
-
 /***************************************************************************
  *   XDS110 Firmware API Definitions                                       *
  ***************************************************************************/
 
 /* TCK frequency limits */
 #define XDS110_MIN_TCK_SPEED  100 /* kHz */
-#define XDS110_MAX_TCK_SPEED 2500 /* kHz */
-#define XDS110_TCK_PULSE_INCREMENT 66.0
+#define XDS110_MAX_SLOW_TCK_SPEED 2500 /* kHz */
+#define XDS110_MAX_FAST_TCK_SPEED 14000 /* kHz */
+#define XDS110_DEFAULT_TCK_SPEED 2500 /* kHz */
+
+/* Fixed TCK delay values for "Fast" TCK frequencies */
+#define FAST_TCK_DELAY_14000_KHZ 0
+#define FAST_TCK_DELAY_10000_KHZ 0xfffffffd
+#define FAST_TCK_DELAY_12000_KHZ 0xfffffffe
+#define FAST_TCK_DELAY_8500_KHZ 1
+#define FAST_TCK_DELAY_5500_KHZ 2
+/* For TCK frequencies below 5500 kHz, use calculated delay */
 
 /* Scan mode on connect */
 #define MODE_JTAG 1
 #define CMD_STABLECLOCKS 4
 
 /* Array to convert from OpenOCD tap_state_t to XDS JTAG state */
-const uint32_t xds_jtag_state[] = {
+static const uint32_t xds_jtag_state[] = {
        XDS_JTAG_STATE_EXIT2_DR,   /* TAP_DREXIT2   = 0x0 */
        XDS_JTAG_STATE_EXIT1_DR,   /* TAP_DREXIT1   = 0x1 */
        XDS_JTAG_STATE_SHIFT_DR,   /* TAP_DRSHIFT   = 0x2 */
@@ -207,11 +200,18 @@ struct scan_result {
 
 struct xds110_info {
        /* USB connection handles and data buffers */
-       libusb_context *ctx;
-       libusb_device_handle *dev;
+       struct libusb_context *ctx;
+       struct libusb_device_handle *dev;
        unsigned char read_payload[USB_PAYLOAD_SIZE];
        unsigned char write_packet[3];
        unsigned char write_payload[USB_PAYLOAD_SIZE];
+       /* Device vid/pid */
+       uint16_t vid;
+       uint16_t pid;
+       /* Debug interface */
+       uint8_t interface;
+       uint8_t endpoint_in;
+       uint8_t endpoint_out;
        /* Status flags */
        bool is_connected;
        bool is_cmapi_connected;
@@ -225,8 +225,6 @@ struct xds110_info {
        /* TCK speed and delay count*/
        uint32_t speed;
        uint32_t delay_count;
-       /* XDS110 serial number */
-       char serial[XDS110_SERIAL_LEN + 1];
        /* XDS110 voltage supply setting */
        uint32_t voltage;
        /* XDS110 firmware and hardware version */
@@ -244,14 +242,18 @@ struct xds110_info {
 static struct xds110_info xds110 = {
        .ctx = NULL,
        .dev = NULL,
+       .vid = 0,
+       .pid = 0,
+       .interface = 0,
+       .endpoint_in = 0,
+       .endpoint_out = 0,
        .is_connected = false,
        .is_cmapi_connected = false,
        .is_cmapi_acquired = false,
        .is_swd_mode = false,
        .is_ap_dirty = false,
-       .speed = XDS110_MAX_TCK_SPEED,
+       .speed = XDS110_DEFAULT_TCK_SPEED,
        .delay_count = 0,
-       .serial = {0},
        .voltage = 0,
        .firmware = 0,
        .hardware = 0,
@@ -299,23 +301,31 @@ static inline uint16_t xds110_get_u16(uint8_t *buffer)
 
 static bool usb_connect(void)
 {
-       libusb_context *ctx  = NULL;
-       libusb_device **list = NULL;
-       libusb_device_handle *dev  = NULL;
+       struct libusb_context *ctx  = NULL;
+       struct libusb_device **list = NULL;
+       struct libusb_device_handle *dev  = NULL;
 
        struct libusb_device_descriptor desc;
 
-       uint16_t vid = 0x0451;
-       uint16_t pid = 0xbef3;
+       /* The vid/pids of possible XDS110 configurations */
+       uint16_t vids[] = { 0x0451, 0x0451, 0x1cbe };
+       uint16_t pids[] = { 0xbef3, 0xbef4, 0x02a5 };
+       /* Corresponding interface and endpoint numbers for configurations */
+       uint8_t interfaces[] = { 2, 2, 0 };
+       uint8_t endpoints_in[] = { 3, 3, 1 };
+       uint8_t endpoints_out[] = { 2, 2, 1 };
+
        ssize_t count = 0;
        ssize_t i = 0;
        int result = 0;
        bool found = false;
+       uint32_t device = 0;
+       bool match = false;
 
        /* Initialize libusb context */
        result = libusb_init(&ctx);
 
-       if (0 == result) {
+       if (result == 0) {
                /* Get list of USB devices attached to system */
                count = libusb_get_device_list(ctx, &list);
                if (count <= 0) {
@@ -324,29 +334,37 @@ static bool usb_connect(void)
                }
        }
 
-       if (0 == result) {
+       if (result == 0) {
                /* Scan through list of devices for any XDS110s */
                for (i = 0; i < count; i++) {
-                       /* Check for device VID/PID match */
+                       /* Check for device vid/pid match */
                        libusb_get_device_descriptor(list[i], &desc);
-                       if (desc.idVendor == vid && desc.idProduct == pid) {
+                       match = false;
+                       for (device = 0; device < ARRAY_SIZE(vids); device++) {
+                               if (desc.idVendor == vids[device] &&
+                                       desc.idProduct == pids[device]) {
+                                       match = true;
+                                       break;
+                               }
+                       }
+                       if (match) {
                                result = libusb_open(list[i], &dev);
-                               if (0 == result) {
-                                       const int MAX_DATA = 256;
-                                       unsigned char data[MAX_DATA + 1];
+                               if (result == 0) {
+                                       const int max_data = 256;
+                                       unsigned char data[max_data + 1];
                                        *data = '\0';
 
                                        /* May be the requested device if serial number matches */
-                                       if (0 == xds110.serial[0]) {
+                                       if (!adapter_get_required_serial()) {
                                                /* No serial number given; match first XDS110 found */
                                                found = true;
                                                break;
                                        } else {
                                                /* Get the device's serial number string */
                                                result = libusb_get_string_descriptor_ascii(dev,
-                                                                       desc.iSerialNumber, data, MAX_DATA);
-                                               if (0 < result &&
-                                                       0 == strcmp((char *)data, (char *)xds110.serial)) {
+                                                                       desc.iSerialNumber, data, max_data);
+                                               if (result > 0 &&
+                                                       strcmp((char *)data, adapter_get_required_serial()) == 0) {
                                                        found = true;
                                                        break;
                                                }
@@ -366,12 +384,21 @@ static bool usb_connect(void)
         * 2) didn't find the XDS110, and no devices are currently open
         */
 
-       if (NULL != list) {
+       if (list) {
                /* Free the device list, we're done with it */
                libusb_free_device_list(list, 1);
        }
 
        if (found) {
+               /* Save the vid/pid of the device we're using */
+               xds110.vid = vids[device];
+               xds110.pid = pids[device];
+
+               /* Save the debug interface and endpoints for the device */
+               xds110.interface = interfaces[device];
+               xds110.endpoint_in = endpoints_in[device] | LIBUSB_ENDPOINT_IN;
+               xds110.endpoint_out = endpoints_out[device] | LIBUSB_ENDPOINT_OUT;
+
                /* Save the context and device handles */
                xds110.ctx = ctx;
                xds110.dev = dev;
@@ -380,43 +407,43 @@ static bool usb_connect(void)
                (void)libusb_set_auto_detach_kernel_driver(dev, 1);
 
                /* Claim the debug interface on the XDS110 */
-               result = libusb_claim_interface(dev, INTERFACE_DEBUG);
+               result = libusb_claim_interface(dev, xds110.interface);
        } else {
                /* Couldn't find an XDS110, flag the error */
                result = -1;
        }
 
        /* On an error, clean up what we can */
-       if (0 != result) {
-               if (NULL != dev) {
+       if (result != 0) {
+               if (dev) {
                        /* Release the debug and data interface on the XDS110 */
-                       (void)libusb_release_interface(dev, INTERFACE_DEBUG);
+                       (void)libusb_release_interface(dev, xds110.interface);
                        libusb_close(dev);
                }
-               if (NULL != ctx)
+               if (ctx)
                        libusb_exit(ctx);
                xds110.ctx = NULL;
                xds110.dev = NULL;
        }
 
        /* Log the results */
-       if (0 == result)
+       if (result == 0)
                LOG_INFO("XDS110: connected");
        else
                LOG_ERROR("XDS110: failed to connect");
 
-       return (0 == result) ? true : false;
+       return (result == 0) ? true : false;
 }
 
 static void usb_disconnect(void)
 {
-       if (NULL != xds110.dev) {
+       if (xds110.dev) {
                /* Release the debug and data interface on the XDS110 */
-               (void)libusb_release_interface(xds110.dev, INTERFACE_DEBUG);
+               (void)libusb_release_interface(xds110.dev, xds110.interface);
                libusb_close(xds110.dev);
                xds110.dev = NULL;
        }
-       if (NULL != xds110.ctx) {
+       if (xds110.ctx) {
                libusb_exit(xds110.ctx);
                xds110.ctx = NULL;
        }
@@ -429,17 +456,17 @@ static bool usb_read(unsigned char *buffer, int size, int *bytes_read,
 {
        int result;
 
-       if (NULL == xds110.dev || NULL == buffer || NULL == bytes_read)
+       if (!xds110.dev || !buffer || !bytes_read)
                return false;
 
        /* Force a non-zero timeout to prevent blocking */
-       if (0 == timeout)
+       if (timeout == 0)
                timeout = DEFAULT_TIMEOUT;
 
-       result = libusb_bulk_transfer(xds110.dev, ENDPOINT_DEBUG_IN, buffer, size,
+       result = libusb_bulk_transfer(xds110.dev, xds110.endpoint_in, buffer, size,
                                bytes_read, timeout);
 
-       return (0 == result) ? true : false;
+       return (result == 0) ? true : false;
 }
 
 static bool usb_write(unsigned char *buffer, int size, int *written)
@@ -448,24 +475,24 @@ static bool usb_write(unsigned char *buffer, int size, int *written)
        int result = LIBUSB_SUCCESS;
        int retries = 0;
 
-       if (NULL == xds110.dev || NULL == buffer)
+       if (!xds110.dev || !buffer)
                return false;
 
-       result = libusb_bulk_transfer(xds110.dev, ENDPOINT_DEBUG_OUT, buffer,
+       result = libusb_bulk_transfer(xds110.dev, xds110.endpoint_out, buffer,
                                size, &bytes_written, 0);
 
-       while (LIBUSB_ERROR_PIPE == result && retries < 3) {
+       while (result == LIBUSB_ERROR_PIPE && retries < 3) {
                /* Try clearing the pipe stall and retry transfer */
-               libusb_clear_halt(xds110.dev, ENDPOINT_DEBUG_OUT);
-               result = libusb_bulk_transfer(xds110.dev, ENDPOINT_DEBUG_OUT, buffer,
+               libusb_clear_halt(xds110.dev, xds110.endpoint_out);
+               result = libusb_bulk_transfer(xds110.dev, xds110.endpoint_out, buffer,
                                        size, &bytes_written, 0);
                retries++;
        }
 
-       if (NULL != written)
+       if (written)
                *written = bytes_written;
 
-       return (0 == result && size == bytes_written) ? true : false;
+       return (result == 0 && size == bytes_written) ? true : false;
 }
 
 static bool usb_get_response(uint32_t *total_bytes_read, uint32_t timeout)
@@ -507,7 +534,7 @@ static bool usb_get_response(uint32_t *total_bytes_read, uint32_t timeout)
 
        /* Abort now if we didn't receive a valid response */
        if (!success) {
-               if (NULL != total_bytes_read)
+               if (total_bytes_read)
                        *total_bytes_read = 0;
                return false;
        }
@@ -544,7 +571,7 @@ static bool usb_get_response(uint32_t *total_bytes_read, uint32_t timeout)
 
        if (!success)
                count = 0;
-       if (NULL != total_bytes_read)
+       if (total_bytes_read)
                *total_bytes_read = count;
 
        return success;
@@ -593,7 +620,7 @@ static bool xds_execute(uint32_t out_length, uint32_t in_length,
        int error = 0;
        uint32_t bytes_read = 0;
 
-       if (NULL == xds110.dev)
+       if (!xds110.dev)
                return false;
 
        while (!done && attempts > 0) {
@@ -612,13 +639,13 @@ static bool xds_execute(uint32_t out_length, uint32_t in_length,
                        if (bytes_read != in_length) {
                                /* Unexpected amount of data returned */
                                success = false;
-                               LOG_DEBUG("XDS110: command 0x%02x return %d bytes, expected %d",
+                               LOG_DEBUG("XDS110: command 0x%02x return %" PRIu32 " bytes, expected %" PRIu32,
                                        xds110.write_payload[0], bytes_read, in_length);
                        } else {
                                /* Extract error code from return packet */
                                error = (int)xds110_get_u32(&xds110.read_payload[0]);
                                done = true;
-                               if (SC_ERR_NONE != error)
+                               if (error != SC_ERR_NONE)
                                        LOG_DEBUG("XDS110: command 0x%02x returned error %d",
                                                xds110.write_payload[0], error);
                        }
@@ -628,7 +655,7 @@ static bool xds_execute(uint32_t out_length, uint32_t in_length,
        if (!success)
                error = SC_ERR_XDS110_FAIL;
 
-       if (0 != error)
+       if (error != 0)
                success = false;
 
        return success;
@@ -671,9 +698,9 @@ static bool xds_version(uint32_t *firmware_id, uint16_t *hardware_id)
                                DEFAULT_TIMEOUT);
 
        if (success) {
-               if (NULL != firmware_id)
+               if (firmware_id)
                        *firmware_id = xds110_get_u32(fw_id_pntr);
-               if (NULL != hardware_id)
+               if (hardware_id)
                        *hardware_id = xds110_get_u16(hw_id_pntr);
        }
 
@@ -820,7 +847,7 @@ static bool cmapi_connect(uint32_t *idcode)
                                DEFAULT_TIMEOUT);
 
        if (success) {
-               if (NULL != idcode)
+               if (idcode)
                        *idcode = xds110_get_u32(idcode_pntr);
        }
 
@@ -883,7 +910,7 @@ static bool cmapi_read_dap_reg(uint32_t type, uint32_t ap_num,
                                DEFAULT_TIMEOUT);
 
        if (success) {
-               if (NULL != value)
+               if (value)
                        *value = xds110_get_u32(value_pntr);
        }
 
@@ -900,7 +927,7 @@ static bool cmapi_write_dap_reg(uint32_t type, uint32_t ap_num,
 
        bool success;
 
-       if (NULL == value)
+       if (!value)
                return false;
 
        xds110.write_payload[0] = CMAPI_REG_WRITE;
@@ -978,7 +1005,7 @@ static bool xds_set_supply(uint32_t voltage)
        xds110.write_payload[0] = XDS_SET_SUPPLY;
 
        xds110_set_u32(volts_pntr, voltage);
-       *source_pntr = (uint8_t)(0 != voltage ? 1 : 0);
+       *source_pntr = (uint8_t)(voltage != 0 ? 1 : 0);
 
        success = xds_execute(XDS_OUT_LEN + 5, XDS_IN_LEN, DEFAULT_ATTEMPTS,
                                DEFAULT_TIMEOUT);
@@ -994,7 +1021,7 @@ static bool ocd_dap_request(uint8_t *dap_requests, uint32_t request_size,
 
        bool success;
 
-       if (NULL == dap_requests || NULL == dap_results)
+       if (!dap_requests || !dap_results)
                return false;
 
        xds110.write_payload[0] = OCD_DAP_REQUEST;
@@ -1019,7 +1046,7 @@ static bool ocd_scan_request(uint8_t *scan_requests, uint32_t request_size,
 
        bool success;
 
-       if (NULL == scan_requests || NULL == scan_results)
+       if (!scan_requests || !scan_results)
                return false;
 
        xds110.write_payload[0] = OCD_SCAN_REQUEST;
@@ -1043,7 +1070,7 @@ static bool ocd_pathmove(uint32_t num_states, uint8_t *path)
 
        bool success;
 
-       if (NULL == path)
+       if (!path)
                return false;
 
        xds110.write_payload[0] = OCD_PATHMOVE;
@@ -1086,7 +1113,7 @@ static int xds110_swd_switch_seq(enum swd_special_seq seq)
                xds110.is_cmapi_acquired = false;
                /* Run sequence to put target in SWD mode */
                success = swd_connect();
-               /* Re-iniitialize CMAPI API for DAP access */
+               /* Re-initialize CMAPI API for DAP access */
                if (success) {
                        xds110.is_swd_mode = true;
                        success = cmapi_connect(&idcode);
@@ -1122,9 +1149,9 @@ static int xds110_swd_switch_seq(enum swd_special_seq seq)
 static bool xds110_legacy_read_reg(uint8_t cmd, uint32_t *value)
 {
        /* Make sure this is a read request */
-       bool is_read_request = (0 != (SWD_CMD_RnW & cmd));
+       bool is_read_request = (0 != (SWD_CMD_RNW & cmd));
        /* Determine whether this is a DP or AP register access */
-       uint32_t type = (0 != (SWD_CMD_APnDP & cmd)) ? DAP_AP : DAP_DP;
+       uint32_t type = (0 != (SWD_CMD_APNDP & cmd)) ? DAP_AP : DAP_DP;
        /* Determine the AP number from cached SELECT value */
        uint32_t ap_num = (xds110.select & 0xff000000) >> 24;
        /* Extract register address from command */
@@ -1140,7 +1167,7 @@ static bool xds110_legacy_read_reg(uint8_t cmd, uint32_t *value)
        if (!is_read_request)
                return false;
 
-       if (DAP_AP == type) {
+       if (type == DAP_AP) {
                /* Add bank address to register address for CMAPI call */
                address |= bank;
        }
@@ -1166,7 +1193,7 @@ static bool xds110_legacy_read_reg(uint8_t cmd, uint32_t *value)
        /* Handle result of read attempt */
        if (!success)
                LOG_ERROR("XDS110: failed to read DAP register");
-       else if (NULL != value)
+       else if (value)
                *value = reg_value;
 
        if (success && DAP_AP == type) {
@@ -1184,9 +1211,9 @@ static bool xds110_legacy_read_reg(uint8_t cmd, uint32_t *value)
 static bool xds110_legacy_write_reg(uint8_t cmd, uint32_t value)
 {
        /* Make sure this isn't a read request */
-       bool is_read_request = (0 != (SWD_CMD_RnW & cmd));
+       bool is_read_request = (0 != (SWD_CMD_RNW & cmd));
        /* Determine whether this is a DP or AP register access */
-       uint32_t type = (0 != (SWD_CMD_APnDP & cmd)) ? DAP_AP : DAP_DP;
+       uint32_t type = (0 != (SWD_CMD_APNDP & cmd)) ? DAP_AP : DAP_DP;
        /* Determine the AP number from cached SELECT value */
        uint32_t ap_num = (xds110.select & 0xff000000) >> 24;
        /* Extract register address from command */
@@ -1202,12 +1229,12 @@ static bool xds110_legacy_write_reg(uint8_t cmd, uint32_t value)
        /* Invalidate the RDBUFF cache */
        xds110.use_rdbuff = false;
 
-       if (DAP_AP == type) {
+       if (type == DAP_AP) {
                /* Add bank address to register address for CMAPI call */
                address |= bank;
                /* Any write to an AP register invalidates the firmware's cache */
                xds110.is_ap_dirty = true;
-       } else if (DAP_DP_SELECT == address) {
+       } else if (address == DAP_DP_SELECT) {
                /* Any write to the SELECT register invalidates the firmware's cache */
                xds110.is_ap_dirty = true;
        }
@@ -1221,7 +1248,7 @@ static bool xds110_legacy_write_reg(uint8_t cmd, uint32_t value)
                 * If the debugger wrote to SELECT, cache the value
                 * to use to build the apNum and address values above
                 */
-               if ((DAP_DP == type) && (DAP_DP_SELECT == address))
+               if ((type == DAP_DP) && (address == DAP_DP_SELECT))
                        xds110.select = value;
        }
 
@@ -1237,7 +1264,7 @@ static int xds110_swd_run_queue(void)
        uint32_t value;
        bool success = true;
 
-       if (0 == xds110.txn_request_size)
+       if (xds110.txn_request_size == 0)
                return ERROR_OK;
 
        /* Terminate request queue */
@@ -1253,7 +1280,7 @@ static int xds110_swd_run_queue(void)
                result = 0;
                while (xds110.txn_requests[request] != 0) {
                        cmd = xds110.txn_requests[request++];
-                       if (0 == (SWD_CMD_RnW & cmd)) {
+                       if (0 == (SWD_CMD_RNW & cmd)) {
                                /* DAP register write command */
                                value  = (uint32_t)(xds110.txn_requests[request++]) <<  0;
                                value |= (uint32_t)(xds110.txn_requests[request++]) <<  8;
@@ -1273,7 +1300,7 @@ static int xds110_swd_run_queue(void)
 
        /* Transfer results into caller's buffers */
        for (result = 0; result < xds110.txn_result_count; result++)
-               if (0 != xds110.txn_dap_results[result])
+               if (xds110.txn_dap_results[result] != 0)
                        *xds110.txn_dap_results[result] = dap_results[result];
 
        xds110.txn_request_size = 0;
@@ -1286,9 +1313,9 @@ static int xds110_swd_run_queue(void)
 static void xds110_swd_queue_cmd(uint8_t cmd, uint32_t *value)
 {
        /* Check if this is a read or write request */
-       bool is_read_request = (0 != (SWD_CMD_RnW & cmd));
+       bool is_read_request = (0 != (SWD_CMD_RNW & cmd));
        /* Determine whether this is a DP or AP register access */
-       uint32_t type = (0 != (SWD_CMD_APnDP & cmd)) ? DAP_AP : DAP_DP;
+       uint32_t type = (0 != (SWD_CMD_APNDP & cmd)) ? DAP_AP : DAP_DP;
        /* Extract register address from command */
        uint32_t address = ((cmd & SWD_CMD_A32) >> 1);
        uint32_t request_size = (is_read_request) ? 1 : 5;
@@ -1345,20 +1372,21 @@ static void xds110_show_info(void)
 {
        uint32_t firmware = xds110.firmware;
 
-       LOG_INFO("XDS110: firmware version = %d.%d.%d.%d",
+       LOG_INFO("XDS110: vid/pid = %04x/%04x", xds110.vid, xds110.pid);
+       LOG_INFO("XDS110: firmware version = %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32,
                (((firmware >> 28) & 0xf) * 10) + ((firmware >> 24) & 0xf),
                (((firmware >> 20) & 0xf) * 10) + ((firmware >> 16) & 0xf),
                (((firmware >> 12) & 0xf) * 10) + ((firmware >>  8) & 0xf),
                (((firmware >>  4) & 0xf) * 10) + ((firmware >>  0) & 0xf));
        LOG_INFO("XDS110: hardware version = 0x%04x", xds110.hardware);
-       if (0 != xds110.serial[0])
-               LOG_INFO("XDS110: serial number = %s", xds110.serial);
+       if (adapter_get_required_serial())
+               LOG_INFO("XDS110: serial number = %s", adapter_get_required_serial());
        if (xds110.is_swd_mode) {
                LOG_INFO("XDS110: connected to target via SWD");
-               LOG_INFO("XDS110: SWCLK set to %d kHz", xds110.speed);
+               LOG_INFO("XDS110: SWCLK set to %" PRIu32 " kHz", xds110.speed);
        } else {
                LOG_INFO("XDS110: connected to target via JTAG");
-               LOG_INFO("XDS110: TCK set to %d kHz", xds110.speed);
+               LOG_INFO("XDS110: TCK set to %" PRIu32 " kHz", xds110.speed);
        }
 
        /* Alert user that there's a better firmware to use */
@@ -1426,12 +1454,12 @@ static int xds110_init(void)
 
        if (success) {
                /* Set supply voltage for stand-alone probes */
-               if (XDS110_STAND_ALONE_ID == xds110.hardware) {
+               if (xds110.hardware == XDS110_STAND_ALONE_ID) {
                        success = xds_set_supply(xds110.voltage);
                        /* Allow time for target device to power up */
                        /* (CC32xx takes up to 1300 ms before debug is enabled) */
                        alive_sleep(1500);
-               } else if (0 != xds110.voltage) {
+               } else if (xds110.voltage != 0) {
                        /* Voltage supply not a feature of embedded probes */
                        LOG_WARNING(
                                "XDS110: ignoring supply voltage, not supported on this probe");
@@ -1513,7 +1541,7 @@ static void xds110_flush(void)
        uint8_t data_in[MAX_DATA_BLOCK];
        uint8_t *data_pntr;
 
-       if (0 == xds110.txn_request_size)
+       if (xds110.txn_request_size == 0)
                return;
 
        /* Terminate request queue */
@@ -1624,7 +1652,11 @@ static int xds110_reset(int trst, int srst)
                        retval = ERROR_FAIL;
 
                /* Toggle TCK to trigger HIB on CC13x/CC26x devices */
-               success = xds_cycle_tck(60000);
+               if (success && !xds110.is_swd_mode) {
+                       /* Toggle TCK for about 50 ms */
+                       success = xds_cycle_tck(xds110.speed * 50);
+               }
+
                if (!success)
                        retval = ERROR_FAIL;
        }
@@ -1635,14 +1667,11 @@ static int xds110_reset(int trst, int srst)
 static void xds110_execute_sleep(struct jtag_command *cmd)
 {
        jtag_sleep(cmd->cmd.sleep->us);
-       return;
 }
 
 static void xds110_execute_tlr_reset(struct jtag_command *cmd)
 {
        (void)xds_goto_state(XDS_JTAG_STATE_RESET);
-
-       return;
 }
 
 static void xds110_execute_pathmove(struct jtag_command *cmd)
@@ -1678,8 +1707,6 @@ static void xds110_execute_pathmove(struct jtag_command *cmd)
        }
 
        free((void *)path);
-
-       return;
 }
 
 static void xds110_queue_scan(struct jtag_command *cmd)
@@ -1713,7 +1740,7 @@ static void xds110_queue_scan(struct jtag_command *cmd)
 
        /* Check if this single request is too large to fit */
        if ((1 + total_bytes + sizeof(end_state) + 1) > MAX_DATA_BLOCK) {
-               LOG_ERROR("BUG: JTAG scan request is too large to handle (%d bits)",
+               LOG_ERROR("BUG: JTAG scan request is too large to handle (%" PRIu32 " bits)",
                        total_bits);
                /* Failing to run this scan mucks up debug on this target */
                exit(-1);
@@ -1751,8 +1778,6 @@ static void xds110_queue_scan(struct jtag_command *cmd)
        }
        xds110.txn_request_size += total_bytes;
        xds110.txn_result_size += total_bytes;
-
-       return;
 }
 
 static void xds110_queue_runtest(struct jtag_command *cmd)
@@ -1772,8 +1797,6 @@ static void xds110_queue_runtest(struct jtag_command *cmd)
        xds110.txn_requests[xds110.txn_request_size++] = (clocks >> 16) & 0xff;
        xds110.txn_requests[xds110.txn_request_size++] = (clocks >> 24) & 0xff;
        xds110.txn_requests[xds110.txn_request_size++] = end_state;
-
-       return;
 }
 
 static void xds110_queue_stableclocks(struct jtag_command *cmd)
@@ -1790,8 +1813,6 @@ static void xds110_queue_stableclocks(struct jtag_command *cmd)
        xds110.txn_requests[xds110.txn_request_size++] = (clocks >>  8) & 0xff;
        xds110.txn_requests[xds110.txn_request_size++] = (clocks >> 16) & 0xff;
        xds110.txn_requests[xds110.txn_request_size++] = (clocks >> 24) & 0xff;
-
-       return;
 }
 
 static void xds110_execute_command(struct jtag_command *cmd)
@@ -1830,7 +1851,7 @@ static int xds110_execute_queue(void)
 {
        struct jtag_command *cmd = jtag_command_queue;
 
-       while (cmd != NULL) {
+       while (cmd) {
                xds110_execute_command(cmd);
                cmd = cmd->next;
        }
@@ -1842,6 +1863,8 @@ static int xds110_execute_queue(void)
 
 static int xds110_speed(int speed)
 {
+       double freq_to_use;
+       uint32_t delay_count;
        bool success;
 
        if (speed == 0) {
@@ -1849,61 +1872,110 @@ static int xds110_speed(int speed)
                return ERROR_JTAG_NOT_IMPLEMENTED;
        }
 
-       if (speed > XDS110_MAX_TCK_SPEED) {
-               LOG_INFO("XDS110: reduce speed request: %dkHz to %dkHz maximum",
-                       speed, XDS110_MAX_TCK_SPEED);
-               speed = XDS110_MAX_TCK_SPEED;
-       }
-
        if (speed < XDS110_MIN_TCK_SPEED) {
-               LOG_INFO("XDS110: increase speed request: %dkHz to %dkHz minimum",
+               LOG_INFO("XDS110: increase speed request: %d kHz to %d kHz minimum",
                        speed, XDS110_MIN_TCK_SPEED);
                speed = XDS110_MIN_TCK_SPEED;
        }
 
-       /* The default is the maximum frequency the XDS110 can support */
-       uint32_t freq_to_use = XDS110_MAX_TCK_SPEED * 1000; /* Hz */
-       uint32_t delay_count = 0;
+       /* Older XDS110 firmware had inefficient scan routines and could only */
+       /* achieve a peak TCK frequency of about 2500 kHz */
+       if (xds110.firmware < FAST_TCK_FIRMWARE_VERSION) {
 
-       if (XDS110_MAX_TCK_SPEED != speed) {
-               freq_to_use = speed * 1000; /* Hz */
+               /* Check for request for top speed or higher */
+               if (speed >= XDS110_MAX_SLOW_TCK_SPEED) {
 
-               /* Calculate the delay count value */
-               double one_giga = 1000000000;
-               /* Get the pulse duration for the maximum frequency supported in ns */
-               double max_freq_pulse_duration = one_giga /
-                       (XDS110_MAX_TCK_SPEED * 1000);
+                       /* Inform user that speed was adjusted down to max possible */
+                       if (speed > XDS110_MAX_SLOW_TCK_SPEED) {
+                               LOG_INFO(
+                                       "XDS110: reduce speed request: %d kHz to %d kHz maximum",
+                                       speed, XDS110_MAX_SLOW_TCK_SPEED);
+                               speed = XDS110_MAX_SLOW_TCK_SPEED;
+                       }
+                       delay_count = 0;
 
-               /* Convert frequency to pulse duration */
-               double freq_to_pulse_width_in_ns = one_giga / freq_to_use;
+               } else {
 
-               /*
-                * Start with the pulse duration for the maximum frequency. Keep
-                * decrementing the time added by each count value till the requested
-                * frequency pulse is less than the calculated value.
-                */
-               double current_value = max_freq_pulse_duration;
+                       const double XDS110_TCK_PULSE_INCREMENT = 66.0;
+                       freq_to_use = speed * 1000; /* Hz */
+                       delay_count = 0;
+
+                       /* Calculate the delay count value */
+                       double one_giga = 1000000000;
+                       /* Get the pulse duration for the max frequency supported in ns */
+                       double max_freq_pulse_duration = one_giga /
+                               (XDS110_MAX_SLOW_TCK_SPEED * 1000);
+
+                       /* Convert frequency to pulse duration */
+                       double freq_to_pulse_width_in_ns = one_giga / freq_to_use;
+
+                       /*
+                       * Start with the pulse duration for the maximum frequency. Keep
+                       * decrementing time added by each count value till the requested
+                       * frequency pulse is less than the calculated value.
+                       */
+                       double current_value = max_freq_pulse_duration;
+
+                       while (current_value < freq_to_pulse_width_in_ns) {
+                               current_value += XDS110_TCK_PULSE_INCREMENT;
+                               ++delay_count;
+                       }
 
-               while (current_value < freq_to_pulse_width_in_ns) {
-                       current_value += XDS110_TCK_PULSE_INCREMENT;
-                       ++delay_count;
+                       /*
+                       * Determine which delay count yields the best match.
+                       * The one obtained above or one less.
+                       */
+                       if (delay_count) {
+                               double diff_freq_1 = freq_to_use -
+                                       (one_giga / (max_freq_pulse_duration +
+                                       (XDS110_TCK_PULSE_INCREMENT * delay_count)));
+                               double diff_freq_2 = (one_giga / (max_freq_pulse_duration +
+                                       (XDS110_TCK_PULSE_INCREMENT * (delay_count - 1)))) -
+                                       freq_to_use;
+
+                               /* One less count value yields a better match */
+                               if (diff_freq_1 > diff_freq_2)
+                                       --delay_count;
+                       }
                }
 
-               /*
-                * Determine which delay count yields the best match.
-                * The one obtained above or one less.
-                */
-               if (delay_count) {
-                       double diff_freq_1 = freq_to_use -
-                               (one_giga / (max_freq_pulse_duration +
-                               (XDS110_TCK_PULSE_INCREMENT * delay_count)));
-                       double diff_freq_2 = (one_giga / (max_freq_pulse_duration +
-                               (XDS110_TCK_PULSE_INCREMENT * (delay_count - 1)))) -
-                               freq_to_use;
-
-                       /* One less count value yields a better match */
-                       if (diff_freq_1 > diff_freq_2)
-                               --delay_count;
+       /* Newer firmware has reworked TCK routines that are much more efficient */
+       /* and can now achieve a peak TCK frequency of 14000 kHz */
+       } else {
+
+               if (speed >= XDS110_MAX_FAST_TCK_SPEED) {
+                       if (speed > XDS110_MAX_FAST_TCK_SPEED) {
+                               LOG_INFO(
+                                       "XDS110: reduce speed request: %d kHz to %d kHz maximum",
+                                       speed, XDS110_MAX_FAST_TCK_SPEED);
+                               speed = XDS110_MAX_FAST_TCK_SPEED;
+                       }
+                       delay_count = 0;
+               } else if (speed >= 12000 && xds110.firmware >=
+                       FAST_TCK_PLUS_FIRMWARE_VERSION) {
+                       delay_count = FAST_TCK_DELAY_12000_KHZ;
+               } else if (speed >= 10000 && xds110.firmware >=
+                       FAST_TCK_PLUS_FIRMWARE_VERSION) {
+                       delay_count = FAST_TCK_DELAY_10000_KHZ;
+               } else if (speed >= 8500) {
+                       delay_count = FAST_TCK_DELAY_8500_KHZ;
+               } else if (speed >= 5500) {
+                       delay_count = FAST_TCK_DELAY_5500_KHZ;
+               } else {
+                       /* Calculate the delay count to set the frequency */
+                       /* Formula determined by measuring the waveform on Saeleae logic */
+                       /* analyzer using known values for delay count */
+                       const double m = 17100000.0; /* slope */
+                       const double b = -1.02;      /* y-intercept */
+
+                       freq_to_use = speed * 1000; /* Hz */
+                       double period = 1.0/freq_to_use;
+                       double delay = m * period + b;
+
+                       if (delay < 1.0)
+                               delay_count = 1;
+                       else
+                               delay_count = (uint32_t)delay;
                }
        }
 
@@ -1936,43 +2008,12 @@ COMMAND_HANDLER(xds110_handle_info_command)
        return ERROR_OK;
 }
 
-COMMAND_HANDLER(xds110_handle_serial_command)
-{
-       wchar_t serial[XDS110_SERIAL_LEN + 1];
-
-       xds110.serial[0] = 0;
-
-       if (CMD_ARGC == 1) {
-               size_t len = mbstowcs(0, CMD_ARGV[0], 0);
-               if (len > XDS110_SERIAL_LEN) {
-                       LOG_ERROR("XDS110: serial number is limited to %d characters",
-                               XDS110_SERIAL_LEN);
-                       return ERROR_FAIL;
-               }
-               if ((size_t)-1 == mbstowcs(serial, CMD_ARGV[0], len + 1)) {
-                       LOG_ERROR("XDS110: unable to convert serial number");
-                       return ERROR_FAIL;
-               }
-
-               for (uint32_t i = 0; i < len; i++)
-                       xds110.serial[i] = (char)serial[i];
-
-               xds110.serial[len] = 0;
-       } else {
-               LOG_ERROR("XDS110: expected exactly one argument to xds110_serial "
-                       "<serial-number>");
-               return ERROR_FAIL;
-       }
-
-       return ERROR_OK;
-}
-
 COMMAND_HANDLER(xds110_handle_supply_voltage_command)
 {
        uint32_t voltage = 0;
 
        if (CMD_ARGC == 1) {
-               COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], voltage);
+               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], voltage);
                if (voltage == 0 || (voltage >= XDS110_MIN_VOLTAGE && voltage
                        <= XDS110_MAX_VOLTAGE)) {
                        /* Requested voltage is in range */
@@ -1983,11 +2024,8 @@ COMMAND_HANDLER(xds110_handle_supply_voltage_command)
                        return ERROR_FAIL;
                }
                xds110.voltage = voltage;
-       } else {
-               LOG_ERROR("XDS110: expected one argument to xds110_supply_voltage "
-                       "<millivolts>");
-               return ERROR_FAIL;
-       }
+       } else
+               return ERROR_COMMAND_SYNTAX_ERROR;
 
        return ERROR_OK;
 }
@@ -1997,8 +2035,15 @@ static const struct command_registration xds110_subcommand_handlers[] = {
                .name = "info",
                .handler = &xds110_handle_info_command,
                .mode = COMMAND_EXEC,
-               .usage = "",
                .help = "show XDS110 info",
+               .usage = "",
+       },
+       {
+               .name = "supply",
+               .handler = &xds110_handle_supply_voltage_command,
+               .mode = COMMAND_CONFIG,
+               .help = "set the XDS110 probe supply voltage",
+               .usage = "voltage_in_millivolts",
        },
        COMMAND_REGISTRATION_DONE
 };
@@ -2008,23 +2053,9 @@ static const struct command_registration xds110_command_handlers[] = {
                .name = "xds110",
                .mode = COMMAND_ANY,
                .help = "perform XDS110 management",
-               .usage = "<cmd>",
+               .usage = "",
                .chain = xds110_subcommand_handlers,
        },
-       {
-               .name = "xds110_serial",
-               .handler = &xds110_handle_serial_command,
-               .mode = COMMAND_CONFIG,
-               .help = "set the XDS110 probe serial number",
-               .usage = "serial_string",
-       },
-       {
-               .name = "xds110_supply_voltage",
-               .handler = &xds110_handle_supply_voltage_command,
-               .mode = COMMAND_CONFIG,
-               .help = "set the XDS110 probe supply voltage",
-               .usage = "supply_voltage (millivolts)",
-       },
        COMMAND_REGISTRATION_DONE
 };
 
@@ -2038,17 +2069,22 @@ static const struct swd_driver xds110_swd_driver = {
 
 static const char * const xds110_transport[] = { "swd", "jtag", NULL };
 
-struct jtag_interface xds110_interface = {
+static struct jtag_interface xds110_interface = {
+       .execute_queue = xds110_execute_queue,
+};
+
+struct adapter_driver xds110_adapter_driver = {
        .name = "xds110",
-       .commands = xds110_command_handlers,
-       .swd = &xds110_swd_driver,
        .transports = xds110_transport,
+       .commands = xds110_command_handlers,
 
-       .execute_queue = xds110_execute_queue,
-       .speed = xds110_speed,
-       .speed_div = xds110_speed_div,
-       .khz = xds110_khz,
        .init = xds110_init,
        .quit = xds110_quit,
        .reset = xds110_reset,
+       .speed = xds110_speed,
+       .khz = xds110_khz,
+       .speed_div = xds110_speed_div,
+
+       .jtag_ops = &xds110_interface,
+       .swd_ops = &xds110_swd_driver,
 };