Here's another patch I've had kicking around for a while, now cleaned up a bit.

I was having a problem using an ARM-OCD-USB-H cable where after using the interactive "frequency" command, the TCK frequency was 5 times what I wanted.

The ARM-OCD-USB vs ARM-OCD-USB-H cables are wired pretty much the same,
but for the "H" chip on the latter.

The only distinction made in the tap/cable/ft2232.c between the H and non-H versions is in
calling of ft2232_set_frequency() vs ft2232h_set_frequency() for
ARM-USB-OCD-H.  ft2232h_set_frequency() is only called in intitial
setup, and ft2232_set_frequency is called afterwards.  The result is
that user-requested TCK frequencies are 5x what the user asked for.

It looks like the driver tables were assuming they could call
ft2232_set_frequency() as a generic thing for either chip.  But that's
not correct: the calculation for FT2232H is different once the divider
is disabled to take it out of FT2232 compatibility mode.

This was most clear in the ARM-OCD-USB vs ARM-OCD-USB-H cable drivers,
whose short init routines both call ft2232_armusbocd_init_common
with an is_ft2232h argument of 0 and 1, respectively.

The fix in this patch:
- store the value of is_ft2232h from init time in the params struct
- make a single compatible ft2232_set_frequency() function, which uses
the is_ft2232h flag to determine the base (maximum) rate for the divider
calculation.


another change I considered but decided not to make:
- if the requested frequency is less than the maximum for non-H
parts, we could change back to non-H compatibility mode, 6 MHz base frequency.
- but except for not being able to hit very low frequencies, this actually is less flexible, as the frequencies available are very coarse
near the 6 MHz limit.
So instead, I left things as they were before; FT2232H chips always use the 30 MHz base frequency, which results in a minimum frequency of 457 Hz - which should be slow enough for everyone.


Another issue that we don't address: some cables have comments about
maximum frequencies that are lower than the chip's maximum TCK rate
for other hardware reasons.  This suggested-maximum is still set in
the init routines, and is still not rememembered.  So users invoking
the "frequency" command or python set_frequency() method still need to
be aware of their hardware's limitations when overriding the default TCK
frequency.


One last cleanup included: rather than calling ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ); or ft2232_set_frequency (cable, FT2232H_MAX_TCK_FREQ); in all of the init routines, we can simply call: ft2232_set_frequency (cable, 0) in all of the init routines, because ft2232_set_frequency() defaults to setting the maximum frequency. This makes the code clear that most cables set the default, and makes the few non-default cases stand out.

Note that when using FT2232H/FT4232H cables, the default of 30 MHz
requires careful attention to the electrical environment of the JTAG
signals. long ribbon cables are likely to be problematic - or at least
seldom work for me.

So users may need to set a lower frequency, and its nice when the frequency requested is actually what gets set.



From 71532eb4332f4fcfc058cd06b8a4b63e7f77b976 Mon Sep 17 00:00:00 2001
From: Steve Tell <t...@telltronics.org>
Date: Thu, 29 Jun 2017 17:31:38 -0400
Subject: [PATCH] Rework FT2232(H)_set_frequency() and calls.  An is_ft2232h 
flag is stored n
 struct params, so that the correct calculation can be done subsequent
 "frequency" commands.  Previously, TCK would end up 5x faster than expected
 for FT2232/FT4232H cables.

---
 urjtag/src/tap/cable/ft2232.c |   95 +++++++++++++++++++++-------------------
 1 files changed, 50 insertions(+), 45 deletions(-)

diff --git a/urjtag/src/tap/cable/ft2232.c b/urjtag/src/tap/cable/ft2232.c
index 53e9445..32792af 100644
--- a/urjtag/src/tap/cable/ft2232.c
+++ b/urjtag/src/tap/cable/ft2232.c
@@ -279,6 +279,8 @@ typedef struct
     int signals;
 
     urj_tap_cable_cx_cmd_root_t cmd_root;
+    /* is this an FT232H/FT2232H/FT4232H chip? else non-H */
+    int is_ft2232h;
 } params_t;
 
 
@@ -298,32 +300,48 @@ ft2232h_disable_clockdiv_by5 (urj_cable_t *cable)
 }
 
 static void
-ft2232_set_frequency_common (urj_cable_t *cable, uint32_t new_frequency, 
uint32_t max_frequency)
+ft2232h_enable_clockdiv_by5 (urj_cable_t *cable)
 {
     params_t *params = cable->params;
     urj_tap_cable_cx_cmd_root_t *cmd_root = &params->cmd_root;
 
-    if (!new_frequency || new_frequency > max_frequency)
-        new_frequency = max_frequency;
+    urj_tap_cable_cx_cmd_queue( cmd_root, 0 );
+    urj_tap_cable_cx_cmd_push( cmd_root, ENABLE_CLOCKDIV );
+}
+
+static void
+ft2232_set_frequency (urj_cable_t *cable, uint32_t new_frequency)
+{
+    params_t *params = cable->params;
+    urj_tap_cable_cx_cmd_root_t *cmd_root = &params->cmd_root;
+    uint32_t base_frequency;
+
+    if (params->is_ft2232h)
+        base_frequency = FT2232H_MAX_TCK_FREQ;
+    else
+        base_frequency = FT2232_MAX_TCK_FREQ;
+
+    if (!new_frequency || new_frequency > base_frequency)
+        new_frequency = base_frequency;
 
-    /* update ft2232 frequency if cable setting changed */
+    /* update ft2232(h) frequency if cable setting changed */
     if (new_frequency != params->mpsse_frequency)
     {
         uint32_t div;
 
-        div = max_frequency / new_frequency;
-        if (max_frequency % new_frequency)
+        div = base_frequency / new_frequency;
+        if (base_frequency % new_frequency)
             div++;
 
         if (div >= (1 << 16))
         {
             div = (1 << 16) - 1;
             urj_warning (_("Warning: Setting lowest supported frequency for 
FT2232%s: %d\n"),
-                         max_frequency == FT2232H_MAX_TCK_FREQ ? "H" : "", 
max_frequency/div);
+                         params->is_ft2232h ? "H" : "", base_frequency/div);
+        }
+        if (params->is_ft2232h) {
+                ft2232h_disable_clockdiv_by5 (cable);
         }
-
-        if (max_frequency == FT2232H_MAX_TCK_FREQ)
-            ft2232h_disable_clockdiv_by5 (cable);
 
         /* send new divisor to device */
         div -= 1;
@@ -335,24 +353,11 @@ ft2232_set_frequency_common (urj_cable_t *cable, uint32_t 
new_frequency, uint32_
         urj_tap_cable_cx_xfer (cmd_root, &imm_cmd, cable,
                                URJ_TAP_CABLE_COMPLETELY);
 
-        params->mpsse_frequency = max_frequency / (div + 1);
+        params->mpsse_frequency = base_frequency / (div + 1);
         cable->frequency = params->mpsse_frequency;
     }
 }
 
-
-static void
-ft2232_set_frequency (urj_cable_t *cable, uint32_t new_frequency)
-{
-    ft2232_set_frequency_common (cable, new_frequency, FT2232_MAX_TCK_FREQ);
-}
-
-static void
-ft2232h_set_frequency (urj_cable_t *cable, uint32_t new_frequency)
-{
-    ft2232_set_frequency_common (cable, new_frequency, FT2232H_MAX_TCK_FREQ);
-}
-
 static int
 ft2232_generic_init (urj_cable_t *cable)
 {
@@ -384,7 +389,7 @@ ft2232_generic_init (urj_cable_t *cable)
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
 
-    ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+    ft2232_set_frequency (cable, 0);
 
     params->bit_trst = -1;      /* not used */
     params->bit_reset = -1;     /* not used */
@@ -437,7 +442,7 @@ ft2232_jtagkey_init (urj_cable_t *cable)
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
 
-    ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+    ft2232_set_frequency (cable, 0);
 
     params->bit_trst = BIT_JTAGKEY_TRST_N_OUT + 8;      /* member of HIGH byte 
*/
     params->bit_reset = BIT_JTAGKEY_SRST_N_OUT + 8;     /* member of HIGH byte 
*/
@@ -491,10 +496,8 @@ ft2232_armusbocd_init_common (urj_cable_t *cable, int 
is_ft2232h)
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
 
-    if (is_ft2232h)
-        ft2232h_set_frequency (cable, FT2232H_MAX_TCK_FREQ);
-    else
-        ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+    ft2232_set_frequency (cable, 0);
+    params->is_ft2232h = is_ft2232h;
 
     params->bit_trst = BIT_ARMUSBOCD_nTRST + 8;         /* member of HIGH byte 
*/
     params->bit_reset = BIT_ARMUSBOCD_nTSRST + 8;       /* member of HIGH byte 
*/
@@ -551,12 +554,13 @@ ft2232_gnice_init_common (urj_cable_t *cable, int 
is_ft2232h)
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
 
+    params->is_ft2232h = is_ft2232h;
     if (is_ft2232h)
         /* On ADI boards with the onboard EZKIT Debug Agent, max TCK where 
things
            work is 15MHz. */
-        ft2232h_set_frequency (cable, FT2232H_MAX_TCK_FREQ / 2);
+        ft2232_set_frequency (cable, FT2232H_MAX_TCK_FREQ / 2);
     else
-        ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+        ft2232_set_frequency (cable, 0);
 
     params->bit_trst = BIT_GNICE_nTRST + 8;     /* member of HIGH byte */
     params->bit_reset = -1;     /* not used */
@@ -620,7 +624,7 @@ ft2232_oocdlinks_init (urj_cable_t *cable)
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
 
-    ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+    ft2232_set_frequency (cable, 0);
 
     params->bit_trst = BIT_OOCDLINKS_nTRST + 8; /* member of HIGH byte */
     params->bit_reset = BIT_OOCDLINKS_nSRST + 8;        /* member of HIGH byte 
*/
@@ -669,7 +673,7 @@ ft2232_turtelizer2_init (urj_cable_t *cable)
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
 
-    ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+    ft2232_set_frequency (cable, 0);
 
     params->bit_trst = -1;      /* not used */
     params->bit_reset = BIT_TURTELIZER2_RST;    /* member of LOW byte */
@@ -722,7 +726,7 @@ ft2232_usbjtagrs232_init (urj_cable_t *cable)
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
 
-    ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+    ft2232_set_frequency (cable, 0);
 
     params->bit_trst = BIT_USBJTAGRS232_nTRST + 8; /* member of HIGH byte */
     params->bit_reset = BIT_USBJTAGRS232_nSRST + 8;        /* member of HIGH 
byte */
@@ -820,7 +824,7 @@ ft2232_signalyzer_init (urj_cable_t *cable)
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
 
-    ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+    ft2232_set_frequency (cable, 0);
 
     params->bit_trst = BIT_SIGNALYZER_nTRST;    /* member of LOW byte */
     params->bit_reset = BIT_SIGNALYZER_nSRST;   /* member of LOW byte */
@@ -866,7 +870,7 @@ ft2232_flyswatter_init (urj_cable_t *cable)
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
 
-    ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+    ft2232_set_frequency (cable, 0);
 
     params->bit_trst = BIT_FLYSWATTER_nTRST;    /* member of LOW byte */
     params->bit_reset = BIT_FLYSWATTER_nSRST;   /* member of LOW byte */
@@ -924,7 +928,7 @@ ft2232_usbscarab2_init (urj_cable_t *cable)
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
 
-    ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+    ft2232_set_frequency (cable, 0);
 
     params->bit_trst = BIT_USBSCARAB2_TRST + 8; /* member of HIGH byte */
     params->bit_reset = BIT_USBSCARAB2_nSRST + 8;       /* member of HIGH byte 
*/
@@ -959,8 +963,8 @@ ft2232_ktlink_init (urj_cable_t *cable)
         urj_log (URJ_LOG_LEVEL_NORMAL, "nSRST pin state is high...\n");
 
     /* Set some internal parameters such as speed, reset signals, etc. */
-    ft2232h_set_frequency (cable, FT2232H_MAX_TCK_FREQ);
-    ft2232h_disable_clockdiv_by5 (cable);
+    params->is_ft2232h = 1;
+    ft2232_set_frequency (cable, 0);
 
     params->bit_reset = BIT_KTLINK_SRST + 8;  /* member of HIGH byte */
     params->signals = URJ_POD_CS_RESET;
@@ -1050,7 +1054,8 @@ ft2232_milkymist_init (urj_cable_t *cable)
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
 
-    ft2232h_set_frequency (cable, FT2232H_MAX_TCK_FREQ);
+    params->is_ft2232h = 1;
+    ft2232_set_frequency (cable, 0);
 
     params->bit_trst = -1;      /* not used */
     params->bit_reset = -1;     /* not used */
@@ -1092,7 +1097,7 @@ ft2232_digilenths1_init (urj_cable_t *cable)
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
     urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
 
-    ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+    ft2232_set_frequency (cable, 0);
 
     params->bit_trst = -1;      /* not used */
     params->bit_reset = -1;     /* not used */
@@ -2390,7 +2395,7 @@ const urj_cable_driver_t 
urj_tap_cable_ft2232_gniceplus_driver = {
     ft2232_cable_free,
     ft2232_gniceplus_init,
     ft2232_gnice_done,
-    ft2232h_set_frequency,
+    ft2232_set_frequency,
     ft2232_clock,
     ft2232_get_tdo,
     ft2232_transfer,
@@ -2570,7 +2575,7 @@ const urj_cable_driver_t 
urj_tap_cable_ft2232_ktlink_driver = {
     ft2232_cable_free,
     ft2232_ktlink_init,
     ft2232_ktlink_done,
-    ft2232h_set_frequency,
+    ft2232_set_frequency,
     ft2232_clock,
     ft2232_get_tdo,
     ft2232_transfer,
@@ -2590,7 +2595,7 @@ const urj_cable_driver_t 
urj_tap_cable_ft2232_milkymist_driver = {
     ft2232_cable_free,
     ft2232_milkymist_init,
     ft2232_milkymist_done,
-    ft2232h_set_frequency,
+    ft2232_set_frequency,
     ft2232_clock,
     ft2232_get_tdo,
     ft2232_transfer,
-- 
1.7.1

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
UrJTAG-development mailing list
UrJTAG-development@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/urjtag-development

Reply via email to