jtag/drivers: add support for Nu-Link (Nuvoton ICE) over usb
[fw/openocd] / src / jtag / drivers / cmsis_dap_usb.c
index bd8d0bec7cd5215e1ceacdf3f954606bc71c3a16..6d55392d5a47bccf5fa229a7e5eb846946c50ac0 100644 (file)
@@ -77,8 +77,8 @@ static bool swd_mode;
 #define CMD_DAP_RESET_TARGET      0x0A
 
 /* CMD_INFO */
-#define INFO_ID_VID               0x00      /* string */
-#define INFO_ID_PID               0x02      /* string */
+#define INFO_ID_VENDOR            0x01      /* string */
+#define INFO_ID_PRODUCT           0x02      /* string */
 #define INFO_ID_SERNUM            0x03      /* string */
 #define INFO_ID_FW_VER            0x04      /* string */
 #define INFO_ID_TD_VEND           0x05      /* string */
@@ -229,14 +229,16 @@ static int cmsis_dap_usb_open(void)
        int i;
        struct hid_device_info *devs, *cur_dev;
        unsigned short target_vid, target_pid;
-       wchar_t *target_serial = NULL;
-
        bool found = false;
-       bool serial_found = false;
 
        target_vid = 0;
        target_pid = 0;
 
+       if (hid_init() != 0) {
+               LOG_ERROR("unable to open HIDAPI");
+               return ERROR_FAIL;
+       }
+
        /*
         * The CMSIS-DAP specification stipulates:
         * "The Product String must contain "CMSIS-DAP" somewhere in the string. This is used by the
@@ -268,12 +270,15 @@ static int cmsis_dap_usb_open(void)
                                found = true;
                }
 
+               /* LPC-LINK2 has cmsis-dap on interface 0 and other HID functions on other interfaces */
+               if (cur_dev->vendor_id == 0x1fc9 && cur_dev->product_id == 0x0090 && cur_dev->interface_number != 0)
+                       found = false;
+
                if (found) {
                        /* we have found an adapter, so exit further checks */
                        /* check serial number matches if given */
                        if (cmsis_dap_serial != NULL) {
                                if ((cur_dev->serial_number != NULL) && wcscmp(cmsis_dap_serial, cur_dev->serial_number) == 0) {
-                                       serial_found = true;
                                        break;
                                }
                        } else
@@ -288,23 +293,16 @@ static int cmsis_dap_usb_open(void)
        if (NULL != cur_dev) {
                target_vid = cur_dev->vendor_id;
                target_pid = cur_dev->product_id;
-               if (serial_found)
-                       target_serial = cmsis_dap_serial;
        }
 
-       hid_free_enumeration(devs);
-
        if (target_vid == 0 && target_pid == 0) {
                LOG_ERROR("unable to find CMSIS-DAP device");
+               hid_free_enumeration(devs);
                return ERROR_FAIL;
        }
 
-       if (hid_init() != 0) {
-               LOG_ERROR("unable to open HIDAPI");
-               return ERROR_FAIL;
-       }
-
-       dev = hid_open(target_vid, target_pid, target_serial);
+       dev = hid_open_path(cur_dev->path);
+       hid_free_enumeration(devs);
 
        if (dev == NULL) {
                LOG_ERROR("unable to open CMSIS-DAP device 0x%x:0x%x", target_vid, target_pid);
@@ -335,7 +333,7 @@ static int cmsis_dap_usb_open(void)
         * board */
        /* TODO: HID report descriptor should be parsed instead of
         * hardcoding a match by VID */
-       if (target_vid == 0x03eb && target_pid != 0x2145)
+       if (target_vid == 0x03eb && target_pid != 0x2145 && target_pid != 0x2175)
                packet_size = 512 + 1;
 
        cmsis_dap_handle->packet_buffer = malloc(packet_size);
@@ -364,8 +362,6 @@ static void cmsis_dap_usb_close(struct cmsis_dap *dap)
                free(pending_fifo[i].transfers);
                pending_fifo[i].transfers = NULL;
        }
-
-       return;
 }
 
 static int cmsis_dap_usb_write(struct cmsis_dap *dap, int txlen)
@@ -509,15 +505,15 @@ static int cmsis_dap_cmd_DAP_Info(uint8_t info, uint8_t **data)
        return ERROR_OK;
 }
 
-static int cmsis_dap_cmd_DAP_LED(uint8_t leds)
+static int cmsis_dap_cmd_DAP_LED(uint8_t led, uint8_t state)
 {
        int retval;
        uint8_t *buffer = cmsis_dap_handle->packet_buffer;
 
        buffer[0] = 0;  /* report number */
        buffer[1] = CMD_DAP_LED;
-       buffer[2] = 0x00;
-       buffer[3] = leds;
+       buffer[2] = led;
+       buffer[3] = state;
        retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 4);
 
        if (retval != ERROR_OK || buffer[1] != 0x00) {
@@ -1007,7 +1003,7 @@ static int cmsis_dap_init(void)
                LOG_INFO("CMSIS-DAP: Interface Initialised (JTAG)");
        }
 
-       /* Be conservative and supress submiting multiple HID requests
+       /* Be conservative and suppress submitting multiple HID requests
         * until we get packet count info from the adaptor */
        cmsis_dap_handle->packet_count = 1;
        pending_queue_len = 12;
@@ -1086,8 +1082,12 @@ static int cmsis_dap_init(void)
                if (retval != ERROR_OK)
                        return ERROR_FAIL;
        }
+       /* Both LEDs on */
+       retval = cmsis_dap_cmd_DAP_LED(LED_ID_CONNECT, LED_ON);
+       if (retval != ERROR_OK)
+               return ERROR_FAIL;
 
-       retval = cmsis_dap_cmd_DAP_LED(0x03);           /* Both LEDs on */
+       retval = cmsis_dap_cmd_DAP_LED(LED_ID_RUN, LED_ON);
        if (retval != ERROR_OK)
                return ERROR_FAIL;
 
@@ -1102,9 +1102,6 @@ static int cmsis_dap_init(void)
                        LOG_INFO("Connecting under reset");
                }
        }
-
-       cmsis_dap_cmd_DAP_LED(0x00);                    /* Both LEDs off */
-
        LOG_INFO("CMSIS-DAP: Interface ready");
 
        return ERROR_OK;
@@ -1119,28 +1116,31 @@ static int cmsis_dap_swd_init(void)
 static int cmsis_dap_quit(void)
 {
        cmsis_dap_cmd_DAP_Disconnect();
-       cmsis_dap_cmd_DAP_LED(0x00);            /* Both LEDs off */
+       /* Both LEDs off */
+       cmsis_dap_cmd_DAP_LED(LED_ID_RUN, LED_OFF);
+       cmsis_dap_cmd_DAP_LED(LED_ID_CONNECT, LED_OFF);
 
        cmsis_dap_usb_close(cmsis_dap_handle);
 
        return ERROR_OK;
 }
 
-static void cmsis_dap_execute_reset(struct jtag_command *cmd)
+static int cmsis_dap_reset(int trst, int srst)
 {
        /* Set both TRST and SRST even if they're not enabled as
         * there's no way to tristate them */
 
        output_pins = 0;
-       if (!cmd->cmd.reset->srst)
+       if (!srst)
                output_pins |= SWJ_PIN_SRST;
-       if (!cmd->cmd.reset->trst)
+       if (!trst)
                output_pins |= SWJ_PIN_TRST;
 
        int retval = cmsis_dap_cmd_DAP_SWJ_Pins(output_pins,
                        SWJ_PIN_TRST | SWJ_PIN_SRST, 0, NULL);
        if (retval != ERROR_OK)
                LOG_ERROR("CMSIS-DAP: Interface reset failed");
+       return retval;
 }
 
 static void cmsis_dap_execute_sleep(struct jtag_command *cmd)
@@ -1246,7 +1246,7 @@ static void cmsis_dap_flush(void)
        if (!queued_seq_count)
                return;
 
-       DEBUG_JTAG_IO("Flushing %d queued sequences (%d bytes) with %d pending scan results to capture",
+       LOG_DEBUG_IO("Flushing %d queued sequences (%d bytes) with %d pending scan results to capture",
                queued_seq_count, queued_seq_buf_end, pending_scan_result_count);
 
        /* prep CMSIS-DAP packet */
@@ -1268,7 +1268,7 @@ static void cmsis_dap_flush(void)
        }
 
 #ifdef CMSIS_DAP_JTAG_DEBUG
-       DEBUG_JTAG_IO("USB response buf:");
+       LOG_DEBUG_IO("USB response buf:");
        for (int c = 0; c < queued_seq_buf_end + 3; ++c)
                printf("%02X ", buffer[c]);
        printf("\n");
@@ -1277,7 +1277,7 @@ static void cmsis_dap_flush(void)
        /* copy scan results into client buffers */
        for (int i = 0; i < pending_scan_result_count; ++i) {
                struct pending_scan_result *scan = &pending_scan_results[i];
-               DEBUG_JTAG_IO("Copying pending_scan_result %d/%d: %d bits from byte %d -> buffer + %d bits",
+               LOG_DEBUG_IO("Copying pending_scan_result %d/%d: %d bits from byte %d -> buffer + %d bits",
                        i, pending_scan_result_count, scan->length, scan->first + 2, scan->buffer_offset);
 #ifdef CMSIS_DAP_JTAG_DEBUG
                for (uint32_t b = 0; b < DIV_ROUND_UP(scan->length, 8); ++b)
@@ -1302,7 +1302,7 @@ static void cmsis_dap_flush(void)
 static void cmsis_dap_add_jtag_sequence(int s_len, const uint8_t *sequence, int s_offset,
                                        bool tms, uint8_t *tdo_buffer, int tdo_buffer_offset)
 {
-       DEBUG_JTAG_IO("[at %d] %d bits, tms %s, seq offset %d, tdo buf %p, tdo offset %d",
+       LOG_DEBUG_IO("[at %d] %d bits, tms %s, seq offset %d, tdo buf %p, tdo offset %d",
                queued_seq_buf_end,
                s_len, tms ? "HIGH" : "LOW", s_offset, tdo_buffer, tdo_buffer_offset);
 
@@ -1310,12 +1310,12 @@ static void cmsis_dap_add_jtag_sequence(int s_len, const uint8_t *sequence, int
                return;
 
        if (s_len > 64) {
-               DEBUG_JTAG_IO("START JTAG SEQ SPLIT");
+               LOG_DEBUG_IO("START JTAG SEQ SPLIT");
                for (int offset = 0; offset < s_len; offset += 64) {
                        int len = s_len - offset;
                        if (len > 64)
                                len = 64;
-                       DEBUG_JTAG_IO("Splitting long jtag sequence: %d-bit chunk starting at offset %d", len, offset);
+                       LOG_DEBUG_IO("Splitting long jtag sequence: %d-bit chunk starting at offset %d", len, offset);
                        cmsis_dap_add_jtag_sequence(
                                len,
                                sequence,
@@ -1325,7 +1325,7 @@ static void cmsis_dap_add_jtag_sequence(int s_len, const uint8_t *sequence, int
                                tdo_buffer == NULL ? 0 : (tdo_buffer_offset + offset)
                                );
                }
-               DEBUG_JTAG_IO("END JTAG SEQ SPLIT");
+               LOG_DEBUG_IO("END JTAG SEQ SPLIT");
                return;
        }
 
@@ -1362,7 +1362,7 @@ static void cmsis_dap_add_jtag_sequence(int s_len, const uint8_t *sequence, int
 /* queue a sequence of bits to clock out TMS, executing if the buffer is full */
 static void cmsis_dap_add_tms_sequence(const uint8_t *sequence, int s_len)
 {
-       DEBUG_JTAG_IO("%d bits: %02X", s_len, *sequence);
+       LOG_DEBUG_IO("%d bits: %02X", s_len, *sequence);
        /* we use a series of CMD_DAP_JTAG_SEQ commands to toggle TMS,
           because even though it seems ridiculously inefficient, it
           allows us to combine TMS and scan sequences into the same
@@ -1383,7 +1383,7 @@ static void cmsis_dap_state_move(void)
        tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state());
        tms_scan_bits = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
 
-       DEBUG_JTAG_IO("state move from %s to %s: %d clocks, %02X on tms",
+       LOG_DEBUG_IO("state move from %s to %s: %d clocks, %02X on tms",
                tap_state_name(tap_get_state()), tap_state_name(tap_get_end_state()),
                tms_scan_bits, tms_scan);
        cmsis_dap_add_tms_sequence(&tms_scan, tms_scan_bits);
@@ -1395,7 +1395,7 @@ static void cmsis_dap_state_move(void)
 /* Execute a JTAG scan operation by queueing TMS and TDI/TDO sequences */
 static void cmsis_dap_execute_scan(struct jtag_command *cmd)
 {
-       DEBUG_JTAG_IO("%s type:%d", cmd->cmd.scan->ir_scan ? "IRSCAN" : "DRSCAN",
+       LOG_DEBUG_IO("%s type:%d", cmd->cmd.scan->ir_scan ? "IRSCAN" : "DRSCAN",
                jtag_scan_type(cmd->cmd.scan));
 
        /* Make sure there are no trailing fields with num_bits == 0, or the logic below will fail. */
@@ -1429,7 +1429,7 @@ static void cmsis_dap_execute_scan(struct jtag_command *cmd)
 
        for (int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) {
                scan_size += field->num_bits;
-               DEBUG_JTAG_IO("%s%s field %d/%d %d bits",
+               LOG_DEBUG_IO("%s%s field %d/%d %d bits",
                        field->in_value ? "in" : "",
                        field->out_value ? "out" : "",
                        i,
@@ -1437,7 +1437,7 @@ static void cmsis_dap_execute_scan(struct jtag_command *cmd)
                        field->num_bits);
 
                if (i == cmd->cmd.scan->num_fields - 1 && tap_get_state() != tap_get_end_state()) {
-                       DEBUG_JTAG_IO("Last field and have to move out of SHIFT state");
+                       LOG_DEBUG_IO("Last field and have to move out of SHIFT state");
                        /* Last field, and we're leaving IRSHIFT/DRSHIFT. Clock last bit during tap
                         * movement. This last field can't have length zero, it was checked above. */
                        cmsis_dap_add_jtag_sequence(
@@ -1471,7 +1471,7 @@ static void cmsis_dap_execute_scan(struct jtag_command *cmd)
                                0);
                        tap_set_state(tap_state_transition(tap_get_state(), 0));
                } else {
-                       DEBUG_JTAG_IO("Internal field, staying in SHIFT state afterwards");
+                       LOG_DEBUG_IO("Internal field, staying in SHIFT state afterwards");
                        /* Clocking part of a sequence into DR or IR with TMS=0,
                           leaving TMS=0 at the end so we can continue later */
                        cmsis_dap_add_jtag_sequence(
@@ -1489,7 +1489,7 @@ static void cmsis_dap_execute_scan(struct jtag_command *cmd)
                cmsis_dap_state_move();
        }
 
-       DEBUG_JTAG_IO("%s scan, %i bits, end in %s",
+       LOG_DEBUG_IO("%s scan, %i bits, end in %s",
                (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size,
                tap_state_name(tap_get_end_state()));
 }
@@ -1519,7 +1519,7 @@ static void cmsis_dap_pathmove(int num_states, tap_state_t *path)
 
 static void cmsis_dap_execute_pathmove(struct jtag_command *cmd)
 {
-       DEBUG_JTAG_IO("pathmove: %i states, end in %i",
+       LOG_DEBUG_IO("pathmove: %i states, end in %i",
                      cmd->cmd.pathmove->num_states,
               cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
 
@@ -1557,7 +1557,7 @@ static void cmsis_dap_runtest(int num_cycles)
 
 static void cmsis_dap_execute_runtest(struct jtag_command *cmd)
 {
-       DEBUG_JTAG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles,
+       LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles,
                      cmd->cmd.runtest->end_state);
 
        cmsis_dap_end_state(cmd->cmd.runtest->end_state);
@@ -1566,13 +1566,13 @@ static void cmsis_dap_execute_runtest(struct jtag_command *cmd)
 
 static void cmsis_dap_execute_stableclocks(struct jtag_command *cmd)
 {
-       DEBUG_JTAG_IO("stableclocks %i cycles", cmd->cmd.runtest->num_cycles);
+       LOG_DEBUG_IO("stableclocks %i cycles", cmd->cmd.runtest->num_cycles);
        cmsis_dap_stableclocks(cmd->cmd.runtest->num_cycles);
 }
 
 static void cmsis_dap_execute_tms(struct jtag_command *cmd)
 {
-       DEBUG_JTAG_IO("TMS: %d bits", cmd->cmd.tms->num_bits);
+       LOG_DEBUG_IO("TMS: %d bits", cmd->cmd.tms->num_bits);
        cmsis_dap_cmd_DAP_SWJ_Sequence(cmd->cmd.tms->num_bits, cmd->cmd.tms->bits);
 }
 
@@ -1581,10 +1581,6 @@ static void cmsis_dap_execute_tms(struct jtag_command *cmd)
 static void cmsis_dap_execute_command(struct jtag_command *cmd)
 {
        switch (cmd->type) {
-               case JTAG_RESET:
-                       cmsis_dap_flush();
-                       cmsis_dap_execute_reset(cmd);
-                       break;
                case JTAG_SLEEP:
                        cmsis_dap_flush();
                        cmsis_dap_execute_sleep(cmd);
@@ -1631,10 +1627,10 @@ static int cmsis_dap_execute_queue(void)
 static int cmsis_dap_speed(int speed)
 {
        if (speed > DAP_MAX_CLOCK)
-               LOG_INFO("High speed (adapter_khz %d) may be limited by adapter firmware.", speed);
+               LOG_INFO("High speed (adapter speed %d) may be limited by adapter firmware.", speed);
 
        if (speed == 0) {
-               LOG_ERROR("RTCK not supported. Set nonzero adapter_khz.");
+               LOG_ERROR("RTCK not supported. Set nonzero \"adapter speed\".");
                return ERROR_JTAG_NOT_IMPLEMENTED;
        }
 
@@ -1653,15 +1649,6 @@ static int cmsis_dap_khz(int khz, int *jtag_speed)
        return ERROR_OK;
 }
 
-static int_least32_t cmsis_dap_swd_frequency(int_least32_t hz)
-{
-       if (hz > 0)
-               cmsis_dap_speed(hz / 1000);
-
-       return hz;
-}
-
-
 COMMAND_HANDLER(cmsis_dap_handle_info_command)
 {
        if (cmsis_dap_get_version_info() == ERROR_OK)
@@ -1790,7 +1777,6 @@ static const struct command_registration cmsis_dap_command_handlers[] = {
 
 static const struct swd_driver cmsis_dap_swd_driver = {
        .init = cmsis_dap_swd_init,
-       .frequency = cmsis_dap_swd_frequency,
        .switch_seq = cmsis_dap_swd_switch_seq,
        .read_reg = cmsis_dap_swd_read_reg,
        .write_reg = cmsis_dap_swd_write_reg,
@@ -1799,17 +1785,23 @@ static const struct swd_driver cmsis_dap_swd_driver = {
 
 static const char * const cmsis_dap_transport[] = { "swd", "jtag", NULL };
 
-struct jtag_interface cmsis_dap_interface = {
-       .name = "cmsis-dap",
+static struct jtag_interface cmsis_dap_interface = {
        .supported = DEBUG_CAP_TMS_SEQ,
-       .commands = cmsis_dap_command_handlers,
-       .swd = &cmsis_dap_swd_driver,
+       .execute_queue = cmsis_dap_execute_queue,
+};
+
+struct adapter_driver cmsis_dap_adapter_driver = {
+       .name = "cmsis-dap",
        .transports = cmsis_dap_transport,
+       .commands = cmsis_dap_command_handlers,
 
-       .execute_queue = cmsis_dap_execute_queue,
-       .speed = cmsis_dap_speed,
-       .speed_div = cmsis_dap_speed_div,
-       .khz = cmsis_dap_khz,
        .init = cmsis_dap_init,
        .quit = cmsis_dap_quit,
+       .reset = cmsis_dap_reset,
+       .speed = cmsis_dap_speed,
+       .khz = cmsis_dap_khz,
+       .speed_div = cmsis_dap_speed_div,
+
+       .jtag_ops = &cmsis_dap_interface,
+       .swd_ops = &cmsis_dap_swd_driver,
 };