]> git.sur5r.net Git - openocd/commitdiff
ULINK driver: Implement variable TCK frequency in OpenULINK firmware
authorMartin Schmölzer <martin.schmoelzer@student.tuwien.ac.at>
Mon, 4 Jul 2011 17:03:29 +0000 (19:03 +0200)
committerØyvind Harboe <oyvind.harboe@zylin.com>
Wed, 31 Aug 2011 14:25:41 +0000 (16:25 +0200)
Also, speed up jtag_clock_tck() significantly (150 kHz -> 375 kHz)

Signed-off-by: Martin Schmölzer <martin.schmoelzer@student.tuwien.ac.at>
src/jtag/drivers/OpenULINK/include/jtag.h
src/jtag/drivers/OpenULINK/include/msgtypes.h
src/jtag/drivers/OpenULINK/src/jtag.c
src/jtag/drivers/OpenULINK/src/protocol.c

index 93ecfb0a97aec1ed0b8cc1452e95cc0310943fa9..cef5f426aad16315ad1bdfe2af3da3121bb73453 100644 (file)
 #define NOP {__asm nop __endasm;}
 
 void jtag_scan_in(u8 out_offset, u8 in_offset);
+void jtag_slow_scan_in(u8 out_offset, u8 in_offset);
+
 void jtag_scan_out(u8 out_offset);
-void jtag_scan_io(u8 out_offset, u8 in_offset);
+void jtag_slow_scan_out(u8 out_offset);
 
-void jtag_slow_scan_in(u8 scan_size_bytes, u8 tdo_index, u8 scan_options);
-void jtag_slow_scan_out(u8 scan_size_bytes, u8 tdi_index, u8 scan_options);
-void jtag_slow_scan_io(u8 scan_size_bytes, u8 tdi_index, u8 tdo_index,
-    u8 scan_options);
+void jtag_scan_io(u8 out_offset, u8 in_offset);
+void jtag_slow_scan_io(u8 out_offset, u8 in_offset);
 
 void jtag_clock_tck(u16 count);
+void jtag_slow_clock_tck(u16 count);
 void jtag_clock_tms(u8 count, u8 sequence);
 void jtag_slow_clock_tms(u8 count, u8 sequence);
 
 u16  jtag_get_signals(void);
 void jtag_set_signals(u8 low, u8 high);
 
-void jtag_configure_tck_delay(u8 scan, u8 tck, u8 tms);
+void jtag_configure_tck_delay(u8 scan_in, u8 scan_out, u8 scan_io, u8 tck,
+    u8 tms);
 
 #endif
index e3afb670f167fe040bff064506dc3195106862d2..cb356128a0e3425b5d3ea99fb4e6367b3dfd9af0 100644 (file)
@@ -75,7 +75,7 @@
  * offset 1: tms_count                                                      *
  * offset 2: tms_sequence                                                   *
  ****************************************************************************
- * CMD_CLOCK_TCK:                                                           *
+ * CMD_CLOCK_TCK, CMD_SLOW_CLOCK_TCK:                                       *
  *                                                                          *
  * OUT:                                                                     *
  * offset 1: low byte of tck_count                                          *
  * CMD_CONFIGURE_TCK_FREQ:                                                  *
  *                                                                          *
  * OUT:                                                                     *
- * offset 1: delay value for scan functions                                 *
- * offset 2: delay value for clock_tck function                             *
- * offset 3: delay value for clock_tms function                             *
+ * offset 1: delay value for scan_in function                               *
+ * offset 2: delay value for scan_out function                              *
+ * offset 3: delay value for scan_io function                               *
+ * offset 4: delay value for clock_tck function                             *
+ * offset 5: delay value for clock_tms function                             *
  ****************************************************************************
  * CMD_SET_LEDS:                                                            *
  *                                                                          *
 #define CMD_CLOCK_TMS           0x20
 #define CMD_SLOW_CLOCK_TMS      0x21
 #define CMD_CLOCK_TCK           0x22
-#define CMD_SLEEP_US            0x23
-#define CMD_SLEEP_MS            0x24
-#define CMD_GET_SIGNALS         0x25
-#define CMD_SET_SIGNALS         0x26
-#define CMD_CONFIGURE_TCK_FREQ  0x27
-#define CMD_SET_LEDS            0x28
-#define CMD_TEST                0x29
+#define CMD_SLOW_CLOCK_TCK      0x23
+#define CMD_SLEEP_US            0x24
+#define CMD_SLEEP_MS            0x25
+#define CMD_GET_SIGNALS         0x26
+#define CMD_SET_SIGNALS         0x27
+#define CMD_CONFIGURE_TCK_FREQ  0x28
+#define CMD_SET_LEDS            0x29
+#define CMD_TEST                0x2A
 
 /* JTAG signal definition for jtag_get_signals() -- Input signals! */
 #define SIGNAL_TDO      (1<<0)
index cf126ed274344859986e98155e0391630adb8fbe..812d4f73a8cdfbbb0aa0163fb30900ad22373011 100644 (file)
 
 #include <stdbool.h>
 
-/** Delay value for SCAN operations with less than maximum TCK frequency */
-u8 delay_scan = 0;
+/** Delay value for SCAN_IN operations with less than maximum TCK frequency */
+u8 delay_scan_in = 0;
 
-/** Delay value for CLOCK_TCK operations */
+/** Delay value for SCAN_OUT operations with less than maximum TCK frequency */
+u8 delay_scan_out = 0;
+
+/** Delay value for SCAN_IO operations with less than maximum TCK frequency */
+u8 delay_scan_io = 0;
+
+/** Delay value for CLOCK_TCK operations with less than maximum frequency */
 u8 delay_tck = 0;
 
 /** Delay value for CLOCK_TMS operations with less than maximum frequency */
@@ -41,6 +47,8 @@ u8 delay_tms = 0;
  * Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and
  * stored in the EP2 IN buffer.
  *
+ * Maximum achievable TCK frequency is 182 kHz for ULINK clocked at 24 MHz.
+ *
  * @param out_offset offset in OUT2BUF where payload data starts
  */
 void jtag_scan_in(u8 out_offset, u8 in_offset)
@@ -72,8 +80,8 @@ void jtag_scan_in(u8 out_offset, u8 in_offset)
 
     for (j = 0; j < 8; j++) {
       OUTB = outb_buffer; /* TCK changes here */
-      OUTB = (outb_buffer | PIN_TCK);
       tdo_data = tdo_data >> 1;
+      OUTB = (outb_buffer | PIN_TCK);
 
       if (GET_TDO()) {
         tdo_data |= 0x80;
@@ -96,8 +104,8 @@ void jtag_scan_in(u8 out_offset, u8 in_offset)
     }
 
     OUTB = outb_buffer; /* TCK change here */
-    OUTB = (outb_buffer | PIN_TCK);
     tdo_data = tdo_data >> 1;
+    OUTB = (outb_buffer | PIN_TCK);
 
     if (GET_TDO()) {
       tdo_data |= 0x80;
@@ -114,6 +122,93 @@ void jtag_scan_in(u8 out_offset, u8 in_offset)
   }
 }
 
+/**
+ * Perform JTAG SCAN-IN operation at variable TCK frequency.
+ *
+ * Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and
+ * stored in the EP2 IN buffer.
+ *
+ * Maximum achievable TCK frequency is 113 kHz for ULINK clocked at 24 MHz.
+ *
+ * @param out_offset offset in OUT2BUF where payload data starts
+ */
+void jtag_slow_scan_in(u8 out_offset, u8 in_offset)
+{
+  u8 scan_size_bytes, bits_last_byte;
+  u8 tms_count_start, tms_count_end;
+  u8 tms_sequence_start, tms_sequence_end;
+  u8 tdo_data, i, j, k;
+
+  u8 outb_buffer;
+
+  /* Get parameters from OUT2BUF */
+  scan_size_bytes = OUT2BUF[out_offset];
+  bits_last_byte = OUT2BUF[out_offset + 1];
+  tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
+  tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
+  tms_sequence_start = OUT2BUF[out_offset + 3];
+  tms_sequence_end = OUT2BUF[out_offset + 4];
+
+  if (tms_count_start > 0) {
+    jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
+  }
+
+  outb_buffer = OUTB & ~(PIN_TDI | PIN_TCK | PIN_TMS);
+
+  /* Shift all bytes except the last byte */
+  for (i = 0; i < scan_size_bytes - 1; i++) {
+    tdo_data = 0;
+
+    for (j = 0; j < 8; j++) {
+      OUTB = outb_buffer; /* TCK changes here */
+      for (k = 0; k < delay_scan_in; k++);
+      tdo_data = tdo_data >> 1;
+
+      OUTB = (outb_buffer | PIN_TCK);
+      for (k = 0; k < delay_scan_in; k++);
+
+      if (GET_TDO()) {
+        tdo_data |= 0x80;
+      }
+    }
+
+    /* Copy TDO data to IN2BUF */
+    IN2BUF[i + in_offset] = tdo_data;
+  }
+
+  tdo_data = 0;
+
+  /* Shift the last byte */
+  for (j = 0; j < bits_last_byte; j++) {
+    /* Assert TMS signal if requested and this is the last bit */
+    if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
+      outb_buffer |= PIN_TMS;
+      tms_count_end--;
+      tms_sequence_end = tms_sequence_end >> 1;
+    }
+
+    OUTB = outb_buffer; /* TCK change here */
+    for (k = 0; k < delay_scan_in; k++);
+    tdo_data = tdo_data >> 1;
+
+    OUTB = (outb_buffer | PIN_TCK);
+    for (k = 0; k < delay_scan_in; k++);
+
+    if (GET_TDO()) {
+      tdo_data |= 0x80;
+    }
+  }
+  tdo_data = tdo_data >> (8 - bits_last_byte);
+
+  /* Copy TDO data to IN2BUF */
+  IN2BUF[i + in_offset] = tdo_data;
+
+  /* Move to correct end state */
+  if (tms_count_end > 0) {
+    jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
+  }
+}
+
 /**
  * Perform JTAG SCAN-OUT operation at maximum TCK frequency.
  *
@@ -121,6 +216,8 @@ void jtag_scan_in(u8 out_offset, u8 in_offset)
  * data is not sampled.
  * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
  *
+ * Maximum achievable TCK frequency is 142 kHz for ULINK clocked at 24 MHz.
+ *
  * @param out_offset offset in OUT2BUF where payload data starts
  */
 void jtag_scan_out(u8 out_offset)
@@ -193,6 +290,93 @@ void jtag_scan_out(u8 out_offset)
   }
 }
 
+/**
+ * Perform JTAG SCAN-OUT operation at maximum TCK frequency.
+ *
+ * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
+ * data is not sampled.
+ * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
+ *
+ * Maximum achievable TCK frequency is 97 kHz for ULINK clocked at 24 MHz.
+ *
+ * @param out_offset offset in OUT2BUF where payload data starts
+ */
+void jtag_slow_scan_out(u8 out_offset)
+{
+  u8 scan_size_bytes, bits_last_byte;
+  u8 tms_count_start, tms_count_end;
+  u8 tms_sequence_start, tms_sequence_end;
+  u8 tdi_data, i, j, k;
+
+  u8 outb_buffer;
+
+  /* Get parameters from OUT2BUF */
+  scan_size_bytes = OUT2BUF[out_offset];
+  bits_last_byte = OUT2BUF[out_offset + 1];
+  tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
+  tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
+  tms_sequence_start = OUT2BUF[out_offset + 3];
+  tms_sequence_end = OUT2BUF[out_offset + 4];
+
+  if (tms_count_start > 0) {
+    jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
+  }
+
+  outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
+
+  /* Shift all bytes except the last byte */
+  for (i = 0; i < scan_size_bytes - 1; i++) {
+    tdi_data = OUT2BUF[i + out_offset + 5];
+
+    for (j = 0; j < 8; j++) {
+      if (tdi_data & 0x01) {
+        outb_buffer |= PIN_TDI;
+      }
+      else {
+        outb_buffer &= ~PIN_TDI;
+      }
+
+      OUTB = outb_buffer; /* TDI and TCK change here */
+      for (k = 0; k < delay_scan_out; k++);
+      tdi_data = tdi_data >> 1;
+
+      OUTB = (outb_buffer | PIN_TCK);
+      for (k = 0; k < delay_scan_out; k++);
+    }
+  }
+
+  tdi_data = OUT2BUF[i + out_offset + 5];
+
+  /* Shift the last byte */
+  for (j = 0; j < bits_last_byte; j++) {
+    if (tdi_data & 0x01) {
+      outb_buffer |= PIN_TDI;
+    }
+    else {
+      outb_buffer &= ~PIN_TDI;
+    }
+
+    /* Assert TMS signal if requested and this is the last bit */
+    if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
+      outb_buffer |= PIN_TMS;
+      tms_count_end--;
+      tms_sequence_end = tms_sequence_end >> 1;
+    }
+
+    OUTB = outb_buffer; /* TDI and TCK change here */
+    for (k = 0; k < delay_scan_out; k++);
+    tdi_data = tdi_data >> 1;
+
+    OUTB = (outb_buffer | PIN_TCK);
+    for (k = 0; k < delay_scan_out; k++);
+  }
+
+  /* Move to correct end state */
+  if (tms_count_end > 0) {
+    jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
+  }
+}
+
 /**
  * Perform bidirectional JTAG SCAN operation at maximum TCK frequency.
  *
@@ -200,6 +384,8 @@ void jtag_scan_out(u8 out_offset)
  * data is sampled and stored in the EP2 IN buffer.
  * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
  *
+ * Maximum achievable TCK frequency is 100 kHz for ULINK clocked at 24 MHz.
+ *
  * @param out_offset offset in OUT2BUF where payload data starts
  */
 void jtag_scan_io(u8 out_offset, u8 in_offset)
@@ -291,27 +477,155 @@ void jtag_scan_io(u8 out_offset, u8 in_offset)
   }
 }
 
+/**
+ * Perform bidirectional JTAG SCAN operation at maximum TCK frequency.
+ *
+ * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
+ * data is sampled and stored in the EP2 IN buffer.
+ * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
+ *
+ * Maximum achievable TCK frequency is 78 kHz for ULINK clocked at 24 MHz.
+ *
+ * @param out_offset offset in OUT2BUF where payload data starts
+ */
+void jtag_slow_scan_io(u8 out_offset, u8 in_offset)
+{
+  u8 scan_size_bytes, bits_last_byte;
+  u8 tms_count_start, tms_count_end;
+  u8 tms_sequence_start, tms_sequence_end;
+  u8 tdi_data, tdo_data, i, j, k;
+
+  u8 outb_buffer;
+
+  /* Get parameters from OUT2BUF */
+  scan_size_bytes = OUT2BUF[out_offset];
+  bits_last_byte = OUT2BUF[out_offset + 1];
+  tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
+  tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
+  tms_sequence_start = OUT2BUF[out_offset + 3];
+  tms_sequence_end = OUT2BUF[out_offset + 4];
+
+  if (tms_count_start > 0) {
+    jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
+  }
+
+  outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
+
+  /* Shift all bytes except the last byte */
+  for (i = 0; i < scan_size_bytes - 1; i++) {
+    tdi_data = OUT2BUF[i + out_offset + 5];
+    tdo_data = 0;
+
+    for (j = 0; j < 8; j++) {
+      if (tdi_data & 0x01) {
+        outb_buffer |= PIN_TDI;
+      }
+      else {
+        outb_buffer &= ~PIN_TDI;
+      }
+
+      OUTB = outb_buffer; /* TDI and TCK change here */
+      for (k = 0; k < delay_scan_io; k++);
+      tdi_data = tdi_data >> 1;
+
+      OUTB = (outb_buffer | PIN_TCK);
+      for (k = 0; k < delay_scan_io; k++);
+      tdo_data = tdo_data >> 1;
+
+      if (GET_TDO()) {
+        tdo_data |= 0x80;
+      }
+    }
+
+    /* Copy TDO data to IN2BUF */
+    IN2BUF[i + in_offset] = tdo_data;
+  }
+
+  tdi_data = OUT2BUF[i + out_offset + 5];
+  tdo_data = 0;
+
+  /* Shift the last byte */
+  for (j = 0; j < bits_last_byte; j++) {
+    if (tdi_data & 0x01) {
+      outb_buffer |= PIN_TDI;
+    }
+    else {
+      outb_buffer &= ~PIN_TDI;
+    }
+
+    /* Assert TMS signal if requested and this is the last bit */
+    if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
+      outb_buffer |= PIN_TMS;
+      tms_count_end--;
+      tms_sequence_end = tms_sequence_end >> 1;
+    }
+
+    OUTB = outb_buffer; /* TDI and TCK change here */
+    for (k = 0; k < delay_scan_io; k++);
+    tdi_data = tdi_data >> 1;
+
+    OUTB = (outb_buffer | PIN_TCK);
+    for (k = 0; k < delay_scan_io; k++);
+    tdo_data = tdo_data >> 1;
+
+    if (GET_TDO()) {
+      tdo_data |= 0x80;
+    }
+  }
+  tdo_data = tdo_data >> (8 - bits_last_byte);
+
+  /* Copy TDO data to IN2BUF */
+  IN2BUF[i + in_offset] = tdo_data;
+
+  /* Move to correct end state */
+  if (tms_count_end > 0) {
+    jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
+  }
+}
+
 /**
  * Generate TCK clock cycles.
  *
+ * Maximum achievable TCK frequency is 375 kHz for ULINK clocked at 24 MHz.
+ *
  * @param count number of TCK clock cyclces to generate.
  */
 void jtag_clock_tck(u16 count)
 {
   u16 i;
-  u8 j;
+  u8 outb_buffer = OUTB & ~(PIN_TCK);
 
   for ( i = 0; i < count; i++ ) {
-    SET_TCK_LOW();
-    for(j = 0; j < delay_tck; j++);
+    OUTB = outb_buffer;
+    OUTB = outb_buffer | PIN_TCK;
+  }
+}
+
+/**
+ * Generate TCK clock cycles at variable frequency.
+ *
+ * Maximum achieveable TCK frequency is 166.6 kHz for ULINK clocked at 24 MHz.
+ *
+ * @param count number of TCK clock cyclces to generate.
+ */
+void jtag_slow_clock_tck(u16 count)
+{
+  u16 i;
+  u8 j;
+  u8 outb_buffer = OUTB & ~(PIN_TCK);
 
-    SET_TCK_HIGH();
-    for(j = 0; j < delay_tck; j++);
+  for ( i = 0; i < count; i++ ) {
+    OUTB = outb_buffer;
+    for (j = 0; j < delay_tck; j++);
+    OUTB = outb_buffer | PIN_TCK;
+    for (j = 0; j < delay_tck; j++);
   }
 }
 
 /**
- * Perform TAP-FSM state transitions at maximum TCK frequency.
+ * Perform TAP FSM state transitions at maximum TCK frequency.
+ *
+ * Maximum achievable TCK frequency is 176 kHz for ULINK clocked at 24 MHz.
  *
  * @param count the number of state transitions to perform.
  * @param sequence the TMS pin levels for each state transition, starting with
@@ -319,11 +633,9 @@ void jtag_clock_tck(u16 count)
  */
 void jtag_clock_tms(u8 count, u8 sequence)
 {
-  volatile u8 outb_buffer;
+  u8 outb_buffer = OUTB & ~(PIN_TCK);
   u8 i;
 
-  outb_buffer = OUTB & ~(PIN_TCK);
-
   for ( i = 0; i < count; i++ ) {
     /* Set TMS pin according to sequence parameter */
     if ( sequence & 0x1 ) {
@@ -342,13 +654,32 @@ void jtag_clock_tms(u8 count, u8 sequence)
 /**
  * Perform TAP-FSM state transitions at less than maximum TCK frequency.
  *
+ * Maximum achievable TCK frequency is 117 kHz for ULINK clocked at 24 MHz.
+ *
  * @param count the number of state transitions to perform.
  * @param sequence the TMS pin levels for each state transition, starting with
  *  the least-significant bit.
  */
 void jtag_slow_clock_tms(u8 count, u8 sequence)
 {
+  u8 outb_buffer = OUTB & ~(PIN_TCK);
+  u8 i, j;
+
+  for (i = 0; i < count; i++) {
+    /* Set TMS pin according to sequence parameter */
+    if ( sequence & 0x1 ) {
+      outb_buffer |= PIN_TMS;
+    }
+    else {
+      outb_buffer &= ~PIN_TMS;
+    }
 
+    OUTB = outb_buffer;
+    for (j = 0; j < delay_tms; j++);
+    sequence = sequence >> 1;
+    OUTB = outb_buffer | PIN_TCK;
+    for (j = 0; j < delay_tms; j++);
+  }
 }
 
 /**
@@ -402,13 +733,18 @@ void jtag_set_signals(u8 low, u8 high)
 /**
  * Configure TCK delay parameters.
  *
- * @param scan number of delay cycles in shift operations.
+ * @param scan_in number of delay cycles in scan_in operations.
+ * @param scan_out number of delay cycles in scan_out operations.
+ * @param scan_io number of delay cycles in scan_io operations.
  * @param tck number of delay cycles in clock_tck operations.
  * @param tms number of delay cycles in clock_tms operations.
  */
-void jtag_configure_tck_delay(u8 scan, u8 tck, u8 tms)
+void jtag_configure_tck_delay(u8 scan_in, u8 scan_out, u8 scan_io, u8 tck,
+    u8 tms)
 {
-  delay_scan = scan;
+  delay_scan_in = scan_in;
+  delay_scan_out = scan_out;
+  delay_scan_io = scan_io;
   delay_tck = tck;
   delay_tms = tms;
 }
index 05929d0f99d8164eb57fd055f2407f904fdea97e..6e33ec7116b5a37dac37835974f316c01404820b 100644 (file)
@@ -121,6 +121,30 @@ bool execute_command(void)
     count |= ((u16)OUT2BUF[cmd_id_index + 2]) << 8;
     jtag_clock_tck(count);
     break;
+  case CMD_SLOW_SCAN_IN:
+    usb_out_bytecount = 5;
+    usb_in_bytecount = OUT2BUF[cmd_id_index + 1];
+    jtag_slow_scan_in(cmd_id_index + 1, payload_index_in);
+    break;
+  case CMD_SLOW_SCAN_OUT:
+    usb_out_bytecount = OUT2BUF[cmd_id_index + 1] + 5;
+    jtag_slow_scan_out(cmd_id_index + 1);
+    break;
+  case CMD_SLOW_SCAN_IO:
+    usb_in_bytecount = OUT2BUF[cmd_id_index + 1];
+    usb_out_bytecount = usb_in_bytecount + 5;
+    jtag_slow_scan_io(cmd_id_index + 1, payload_index_in);
+    break;
+  case CMD_SLOW_CLOCK_TMS:
+    usb_out_bytecount = 2;
+    jtag_slow_clock_tms(OUT2BUF[cmd_id_index + 1], OUT2BUF[cmd_id_index + 2]);
+    break;
+  case CMD_SLOW_CLOCK_TCK:
+    usb_out_bytecount = 2;
+    count = (u16)OUT2BUF[cmd_id_index + 1];
+    count |= ((u16)OUT2BUF[cmd_id_index + 2]) << 8;
+    jtag_slow_clock_tck(count);
+    break;
   case CMD_SLEEP_US:
     usb_out_bytecount = 2;
     count = (u16)OUT2BUF[cmd_id_index + 1];
@@ -144,6 +168,15 @@ bool execute_command(void)
     usb_out_bytecount = 2;
     jtag_set_signals(OUT2BUF[cmd_id_index + 1], OUT2BUF[cmd_id_index + 2]);
     break;
+  case CMD_CONFIGURE_TCK_FREQ:
+    usb_out_bytecount = 5;
+    jtag_configure_tck_delay(
+        OUT2BUF[cmd_id_index + 1],  /* scan_in */
+        OUT2BUF[cmd_id_index + 2],  /* scan_out */
+        OUT2BUF[cmd_id_index + 3],  /* scan_io */
+        OUT2BUF[cmd_id_index + 4],  /* clock_tck */
+        OUT2BUF[cmd_id_index + 5]); /* clock_tms */
+    break;
   case CMD_SET_LEDS:
     usb_out_bytecount = 1;
     execute_set_led_command();