+ .name = "targetpower",
+ .handler = &jlink_handle_config_target_power_command,
+ .mode = COMMAND_EXEC,
+ .help = "set the target power supply",
+ .usage = "[on|off]"
+ },
+ {
+ .name = "mac",
+ .handler = &jlink_handle_config_mac_address_command,
+ .mode = COMMAND_EXEC,
+ .help = "set the MAC Address",
+ .usage = "[ff:ff:ff:ff:ff:ff]",
+ },
+ {
+ .name = "ip",
+ .handler = &jlink_handle_config_ip_address_command,
+ .mode = COMMAND_EXEC,
+ .help = "set the IP address, where A.B.C.D is the IP address, "
+ "E the bit of the subnet mask, F.G.H.I the subnet mask",
+ .usage = "[A.B.C.D[/E] [F.G.H.I]]",
+ },
+ {
+ .name = "reset",
+ .handler = &jlink_handle_config_reset_command,
+ .mode = COMMAND_EXEC,
+ .help = "undo configuration changes"
+ },
+ {
+ .name = "write",
+ .handler = &jlink_handle_config_write_command,
+ .mode = COMMAND_EXEC,
+ .help = "write configuration to the device"
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration jlink_subcommand_handlers[] = {
+ {
+ .name = "jtag",
+ .handler = &jlink_handle_jlink_jtag_command,
+ .mode = COMMAND_EXEC,
+ .help = "select the JTAG command version",
+ .usage = "[2|3]",
+ },
+ {
+ .name = "targetpower",
+ .handler = &jlink_handle_target_power_command,
+ .mode = COMMAND_EXEC,
+ .help = "set the target power supply",
+ .usage = "<on|off>"
+ },
+ {
+ .name = "freemem",
+ .handler = &jlink_handle_free_memory_command,
+ .mode = COMMAND_EXEC,
+ .help = "show free device memory"
+ },
+ {
+ .name = "hwstatus",
+ .handler = &jlink_handle_hwstatus_command,
+ .mode = COMMAND_EXEC,
+ .help = "show the hardware status"
+ },
+ {
+ .name = "usb",
+ .handler = &jlink_usb_command,
+ .mode = COMMAND_CONFIG,
+ .help = "set the USB address of the device that should be used",
+ .usage = "<0-3>"
+ },
+ {
+ .name = "serial",
+ .handler = &jlink_serial_command,
+ .mode = COMMAND_CONFIG,
+ .help = "set the serial number of the device that should be used",
+ .usage = "<serial number>"
+ },
+ {
+ .name = "config",
+ .handler = &jlink_handle_config_command,
+ .mode = COMMAND_EXEC,
+ .help = "access the device configuration. If no argument is given "
+ "this will show the device configuration",
+ .chain = jlink_config_subcommand_handlers,
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration jlink_command_handlers[] = {
+ {
+ .name = "jlink",
+ .mode = COMMAND_ANY,
+ .help = "perform jlink management",
+ .chain = jlink_subcommand_handlers,
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+static int jlink_swd_init(void)
+{
+ iface = JAYLINK_TIF_SWD;
+
+ return ERROR_OK;
+}
+
+static void jlink_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk)
+{
+ assert(!(cmd & SWD_CMD_RnW));
+ jlink_swd_queue_cmd(cmd, NULL, value, ap_delay_clk);
+}
+
+static void jlink_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_clk)
+{
+ assert(cmd & SWD_CMD_RnW);
+ jlink_swd_queue_cmd(cmd, value, 0, ap_delay_clk);
+}
+
+static int_least32_t jlink_swd_frequency(int_least32_t hz)
+{
+ if (hz > 0)
+ jlink_speed(hz / 1000);
+
+ return hz;
+}
+
+/***************************************************************************/
+/* J-Link tap functions */
+
+static unsigned tap_length;
+/* In SWD mode use tms buffer for direction control */
+static uint8_t tms_buffer[JLINK_TAP_BUFFER_SIZE];
+static uint8_t tdi_buffer[JLINK_TAP_BUFFER_SIZE];
+static uint8_t tdo_buffer[JLINK_TAP_BUFFER_SIZE];
+
+struct pending_scan_result {
+ /** First bit position in tdo_buffer to read. */
+ unsigned first;
+ /** Number of bits to read. */
+ unsigned length;
+ /** Location to store the result */
+ void *buffer;
+ /** Offset in the destination buffer */
+ unsigned buffer_offset;
+};
+
+#define MAX_PENDING_SCAN_RESULTS 256
+
+static int pending_scan_results_length;
+static struct pending_scan_result pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS];
+
+static void jlink_tap_init(void)
+{
+ tap_length = 0;
+ pending_scan_results_length = 0;
+ memset(tms_buffer, 0, sizeof(tms_buffer));
+ memset(tdi_buffer, 0, sizeof(tdi_buffer));
+}
+
+static void jlink_clock_data(const uint8_t *out, unsigned out_offset,
+ const uint8_t *tms_out, unsigned tms_offset,
+ uint8_t *in, unsigned in_offset,
+ unsigned length)
+{
+ do {
+ unsigned available_length = JLINK_TAP_BUFFER_SIZE - tap_length / 8;
+
+ if (!available_length ||
+ (in && pending_scan_results_length == MAX_PENDING_SCAN_RESULTS)) {
+ if (jlink_flush() != ERROR_OK)
+ return;
+ available_length = JLINK_TAP_BUFFER_SIZE;
+ }
+
+ struct pending_scan_result *pending_scan_result =
+ &pending_scan_results_buffer[pending_scan_results_length];
+
+ unsigned scan_length = length > available_length ?
+ available_length : length;
+
+ if (out)
+ buf_set_buf(out, out_offset, tdi_buffer, tap_length, scan_length);
+ if (tms_out)
+ buf_set_buf(tms_out, tms_offset, tms_buffer, tap_length, scan_length);
+
+ if (in) {
+ pending_scan_result->first = tap_length;
+ pending_scan_result->length = scan_length;
+ pending_scan_result->buffer = in;
+ pending_scan_result->buffer_offset = in_offset;
+ pending_scan_results_length++;
+ }
+
+ tap_length += scan_length;
+ out_offset += scan_length;
+ tms_offset += scan_length;
+ in_offset += scan_length;
+ length -= scan_length;
+ } while (length > 0);
+}
+
+static int jlink_flush(void)
+{
+ int i;
+ int ret;
+
+ if (!tap_length)
+ return ERROR_OK;
+
+ jlink_last_state = jtag_debug_state_machine(tms_buffer, tdi_buffer,
+ tap_length, jlink_last_state);
+
+ ret = jaylink_jtag_io(devh, tms_buffer, tdi_buffer, tdo_buffer,
+ tap_length, jtag_command_version);
+
+ if (ret != JAYLINK_OK) {
+ LOG_ERROR("jaylink_jtag_io() failed: %s.", jaylink_strerror_name(ret));
+ jlink_tap_init();
+ return ERROR_JTAG_QUEUE_FAILED;