changeset 34:f5fbcf1ff032

doc: initial import from freecalypso-hwlab
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 09 Sep 2023 21:28:02 +0000
parents df284688d0c8
children f548ae912622
files doc/DUART28-EEPROM-config doc/FT232R-notes doc/FTDI-EEPROM-tools doc/Unbuffered-FT2232x-JTAG
diffstat 4 files changed, 521 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/DUART28-EEPROM-config	Sat Sep 09 21:28:02 2023 +0000
@@ -0,0 +1,70 @@
+The EEPROM on the DUART28 adapter board has two valid configurations: DUART28C
+and DUART28S.  As of this writing the S configuration is the default shipping
+one, but this situation may change in the future.  The difference between the
+two configs is in the USB VID:PID presented by the USB device, and this USB ID
+difference has the following practical impact:
+
+* The C configuration presents a custom USB ID and requires a custom patch to
+  the Linux kernel ftdi_sio driver in order to work - without this ftdi_sio
+  driver patch it won't work at all.  But if you do go through the pain of
+  applying the needed patch to your Linux kernel ftdi_sio driver, the reward
+  is that you get not only the two Calypso UARTs, but also working boot control
+  outputs.
+
+* The S configuration presents the default FT2232x USB ID and is therefore
+  supported out of the box by the standard Linux ftdi_sio driver without needing
+  any patches.  However, the adapter's CTL1 and CTL2 outputs cannot be used in
+  this configuration (they will be bogusly asserted whenever Channel B ttyUSB
+  device is opened), and thus they must be left unconnected, and you don't get
+  to play with the remote boot control feature.
+
+The physical hardware is identical between the two configurations, only the
+EEPROM programming changes, thus end users need to be able to switch freely
+between the two EEPROM configs as they wish.  This article explains how to
+program the EEPROM back and forth between the two configs.
+
+Determining your current DUART28 config
+=======================================
+
+Connect the USB cable between your DUART28 board and your Linux host, and
+observe dmesg output.  If your DUART28 board is in the C configuration, it will
+present as USB ID 0403:7152, and if it is in the S config, it will present as
+USB ID 0403:6010.  You can also see these USB IDs with lsusb.  The product ID
+string is also programmed as "DUART28C" or "DUART28S".
+
+Converting from DUART28S to DUART28C
+====================================
+
+If your DUART28 board is currently in the S config, its USB ID will be
+0403:6010, which is the default ID for FTDI's two-channel FT2232x family.
+Because it is the standard default, there are plenty of other gadgets using the
+same ID - thus you need to ensure that you have no other USB devices with the
+same ID connected to your system during the reprogramming operation.  Run lsusb
+and ensure that you see only one USB device with ID 0403:6010.  Ensure that this
+one device really is your DUART28 board: unplug that USB cable and make sure
+that the device disappears, plug it back in and make sure that it reappears.
+
+One you have confirmed that you won't inadvertently hit some other FT2232x
+device, execute the actual programming command as follows (from the top
+directory of this code repository):
+
+ftee-gen2232c eeproms/duart28c $Serial | fteeprom-prog i:0x0403:0x6010
+
+(See FTDI-EEPROM-tools article for other ways to specify the target device to
+ fteeprom-prog.)
+
+Replace the $Serial metavariable with the 3-digit serial number of your DUART28
+adapter board as it appears on the factory serial number sticker.
+
+After this operation completes successfully, unplug and replug the USB cable
+between the DUART28 board and your host - the adapter should now show up with
+USB ID 0403:7152.
+
+Converting from DUART28C to DUART28S
+====================================
+
+If your DUART28 board is currently in the C config, its USB ID will be
+0403:7152, which is a private ID that belongs to us and should not be used by
+other parties.  The reverse conversion command is as follows:
+
+ftee-gen2232c eeproms/duart28s $Serial | fteeprom-prog i:0x0403:0x7152
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/FT232R-notes	Sat Sep 09 21:28:02 2023 +0000
@@ -0,0 +1,42 @@
+Unlike FT2232x devices with external EEPROMs, an FT232R device is not expected
+to ever have a blank EEPROM in normal usage: these chips have their EEPROM
+built in, and FTDI probably ships them with this internal EEPROM already
+programmed.  I said "probably" because I have not yet had an occasion to build
+my own FT232R-containing board where I would be getting completely pristine
+"bare" chips from Digi-Key, thus I have no first-hand verified knowledge.
+
+As an experiment, I have programmed "blank" (0xFFFF in every word) images into
+the two FT232R devices I have available for play at the moment (specifically
+devices which I could afford to brick if things went badly), and FT232R behaves
+the same way as FTDI's earlier chips with external EEPROMs: it runs with a fixed
+default config when the EEPROM is invalid.  But this configuration is NOT
+recommended for production use - you should always have a valid EEPROM config
+in your FT232R chip.
+
+When our FreeCalypso fteeprom tools were first put together in 2019-04, I was
+getting erratic behaviour: when I tried to program my own EEPROM config
+generated with ftee-gen232r, the resulting EEPROM content became a bitwise AND
+between the previous image and the new one, as if the "EEPROM" is not really an
+erasable memory, but one of OTP kind where ones can be turned into zeros, but
+not the other way around.  I was doing this experiment on a no-name FT232RL
+adapter from ebay, thus my first thought was that the FT232RL chip was bad, a
+less-than-perfect clone rather than genuine FTDI.  But then I bought a UB232R
+module from Digi-Key (presumably containing a genuine FT232RQ chip), and it
+behaved the same way.
+
+Further investigation revealed that FT232R EEPROM write operations work
+correctly only if they are preceded by this magic sequence:
+
+	ftdi_usb_reset(&ftdi);
+	ftdi_poll_modem_status(&ftdi, &modem_status);
+	ftdi_set_latency_timer(&ftdi, 0x77);
+
+I can see how FTDI could have reasonably implemented a sort of safety lock on
+their EEPROM write operations, allowing them only if a special unlock sequence
+has been given - but it completely baffles me why they are doing some sort of
+OTP emulation in the absence of the right magic sequence, as opposed to
+disabling EEPROM writes altogether.  It is worth noting that this magic sequence
+is NOT needed for programming external EEPROMs behind FT2232x chips - were FTDI
+folks being deliberately malicious in designing their FT232R chip to simulate
+appearance of being bricked when it is programmed with older (or third-party)
+software tools that don't know the new magic sequence?  Who knows...
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/FTDI-EEPROM-tools	Sat Sep 09 21:28:02 2023 +0000
@@ -0,0 +1,243 @@
+Mother Mychaela has developed a set of Linux command line tools for manipulating
+configuration EEPROMs that are attached to FT2232x devices and accessed in-band
+via USB.  This document describes these tools.
+
+Supported FTDI chips and EEPROMs
+================================
+
+The present tools work with 93C46, 93C56 and 93C66 EEPROMs attached behind
+FT2232x dual-channel UART/FIFO/MPSSE/etc chips, both FT2232C/D and FT2232H.
+We can read these EEPROMs for examination or backup, and we can program them
+with new bits, either restoring a previously saved backup or creating a new
+from-scratch configuration.  These EEPROM configurations (which we can save,
+restore or create from scratch) set the USB VID:PID and the textual strings
+naming the manufacturer, the product model and an optional serial number,
+select whether each FT2232x channel will come up in the default UART mode or
+one of the other EEPROM-configurable modes (245 FIFO, CPU-style FIFO or fast
+opto-isolated serial), and allow a few other obscure chip settings to be
+tweaked.
+
+Some work has also been done toward the goal of being able to program the
+internal EEPROM in FT232R chips (a very popular single-channel USB to UART
+converter needing no external components), but this work should be considered
+experimental: the tools appear to work on an UB232R module from Digi-Key
+(presumably containing a genuine FT232RQ chip) and on a no-name FT232RL adapter
+where the chip is uncertain, but because we have no real production use case
+yet, we are not ready to truly vouch for FT232R support.
+
+More generally:
+
+* our fteeprom-read tool should be able to read out the EEPROM content from
+  just about any FTDI chip;
+
+* our fteeprom-prog tool should be able to program a user-supplied set of bits
+  into any FTDI+EEPROM combo where the EEPROM is a separate chip, or into FT232R
+  internal EEPROM - but it most likely won't work for newer FT-X chips;
+
+* if the goal is to generate a new EEPROM config from scratch, as opposed to
+  restoring a saved backup, we currently have generators only for FT2232C/D,
+  for FT2232H and for FT232R, with the last one considered experimental and not
+  proven.
+
+libftdi dependency
+==================
+
+We use libftdi (which is in turn layered on libusb) to issue the special USB
+control pipe commands to FTDI chips which are needed to read and write their
+EEPROMs.  We use old-style libftdi-0.x (-lftdi on the link line) as opposed to
+libftdi1 (-lftdi1) because the new versions took away the ability to write to
+the EEPROM directly with ftdi_write_eeprom_location() calls, forcing users to
+go through libftdi1's own EEPROM smarts, which we don't want to do - our tools
+are all about more direct user empowerment at the lowest level.
+
+Selecting the device to operate on
+==================================
+
+Our fteeprom-read, fteeprom-prog and fteeprom-erase tools take a device selector
+argument, selecting the device to operate on.  This required argument is the
+string to be passed to the ftdi_usb_open_string() function in libftdi, allowing
+the device to be operated on to be selected in one of several ways.  Copying
+from libftdi documentation, the available formats are:
+
+d:<devicenode> - path of bus and device-node (e.g. "003/001") within usb device
+tree (usually at /proc/bus/usb/)
+
+i:<vendor>:<product> - first device with given vendor and product id, ids can
+be decimal, octal (preceded by "0") or hex (preceded by "0x")
+
+i:<vendor>:<product>:<index> - as above with index being the number of the
+device (starting with 0) if there are more than one
+
+s:<vendor>:<product>:<serial> - first device with given vendor id, product id
+and serial string
+
+If you have only one FTDI device connected to your PC or laptop at the time of
+your EEPROM manipulation session (generally a good idea to avoid hitting the
+wrong device by mistake) and if that FTDI device has some sensible starting
+USB VID:PID (either from the previous EEPROM config or the chip's sans-EEPROM
+default) that doesn't clash with anything else, then the i: form will probably
+be the most convenient, e.g.:
+
+i:0x0403:0x6001 for single-channel FT232x devices running with the default ID
+i:0x0403:0x6010 for dual-channel FT2232x devices running with the default ID
+i:0x0403:0xPPPP for custom PIDs assigned out of FTDI's VID range
+i:0xVVVV:0xPPPP for totally custom USB IDs
+
+Or if the current device config is totally hosed (the EEPROM has a passing
+checksum, but sets some completely bogus USB ID), then the d: form will
+probably be required for recovery.
+
+Reading the EEPROM
+==================
+
+The basic EEPROM read command is as follows:
+
+fteeprom-read <device-selector>
+
+See the previous section for the device selector argument.  In this default
+form the tool will read the first 64 EEPROM words, which is appropriate for
+93C46 external EEPROMs or for the internal 1024-bit EEPROM in the FT232R chip.
+However, if you are working with an FT2232x board with an external EEPROM and
+that EEPROM is of a larger variety (93C56 or 93C66), this basic form with give
+you an incomplete (truncated) read, and you will need one of the following
+extended forms to read the complete EEPROM:
+
+fteeprom-read -b <device-selector>	-- read 128 EEPROM words (93C56)
+fteeprom-read -B <device-selector>	-- read 256 EEPROM words (93C66)
+
+(If you use one of the extended forms on a smaller EEPROM, you will get 2 or 4
+ copies of the same bits.)
+
+The output of fteeprom-read is in the same format as the input to fteeprom-prog,
+thus you can redirect the output to a file and get a restorable backup copy of
+your EEPROM.
+
+It also needs to be noted that if the FTDI device has the kernel's ftdi_sio
+driver attached to it (ttyUSB device present) when you run fteeprom-read (same
+for fteeprom-prog and fteeprom-erase), the act of running any of our EEPROM
+tools will cause it to unbind, i.e., the ttyUSB device will disappear.  If the
+device being operated on is a dual-channel FT2232x, then only the ttyUSB device
+corresponding to Channel A will disappear, while the Channel B ttyUSB device
+will stay.
+
+Programming the EEPROM
+======================
+
+In terms of the primitives provided over USB, writing to EEPROMs sitting behind
+FTDI chips is accomplished by writing one 16-bit word at a time: the
+SIO_WRITE_EEPROM_REQUEST command writes a user-supplied word at a user-supplied
+EEPROM address.  However, our fteeprom-prog tool currently supports only writing
+complete EEPROMs (64 or 128 or 256 16-bit words starting at address 0) and we
+do not currently provide any kind of "random access write" utility; the primary
+reason for this design decision is practical usefulness: FTDI's EEPROM structure
+includes a checksum over the first 64 words for 1024-bit EEPROMs or over the
+first 128 words for larger ones, and if this checksum fails to match, the entire
+structure is deemed to be invalid - hence there is no practical use case for
+selectively rewriting individual words.  The only exception may be with 93C66
+EEPROMs: on these giants only the first half would be subject to the checksum,
+and the second half could be used arbitrarily.  However, we have not yet
+encountered any boards out in the wild with such big EEPROMs, and we have no
+plans to use such in any of our own hardware designs either, hence there is no
+business case at the present moment to develop tooling support for them.
+
+There are two primary modes of usage for our fteeprom-prog tool: restoring a
+saved EEPROM backup or writing a new EEPROM config which you generate yourself.
+To restore a saved EEPROM backup, run the tool as follows:
+
+fteeprom-prog <device-selector> <eeprom-image-file>
+
+To program a new EEPROM config of your own, run a pipeline of this form:
+
+<generator-tool> | fteeprom-prog <device-selector>
+
+fteeprom-prog reads the EEPROM image from stdin if no image file is named on
+the command line; the image format is the same in both cases, and the length of
+this EEPROM image tells the tool how many words need to be programmed - there
+are no -b or -B options to fteeprom-prog.
+
+Generator tools
+===============
+
+Unfortunately FTDI never documented the format of their EEPROM configuration
+structure - apparently they consider it a proprietary trade secret just like
+the wire protocol spoken over USB between their chips and their closed-source
+proprietary drivers.  All FOSS community support for these chips is based on
+reverse engineering, and that includes the EEPROM format.
+
+The present suite of tools includes ftee-gen2232c and ftee-gen2232h EEPROM image
+generators, meant for use with FT2232C/D and FT2232H chips, respectively.  These
+tools are based on the knowledge extracted from other (pre-existing) community
+tools, primarily the EEPROM config code built into various libftdi versions -
+we haven't done any FTDI RE of our own, instead the goal of this project has
+been to create a set of tools that are better fit for production use.
+
+Our ftee-gen2232c and ftee-gen2232h tools are invoked as follows:
+
+ftee-gen2232[ch] [-b|-B] <config-file> [serial-num]
+
+The output of these generator tools is meant to be piped directly into
+fteeprom-prog.
+
+The philosophy of which settings are given in the config file vs. which ones
+are given on the command line reflects configuration management and factory
+production line operations.  In the envisioned usage there would be a config
+file for each product, giving the USB VID:PID, textual manufacturer and product
+ID strings and possibly other config settings which need to be changed from the
+defaults, but the optional serial number string is given on the command line
+because it would be different for each individual unit being programmed.
+
+The EEPROM size selection is also made on the command line, so that the same
+config can be programmed into a smaller EEPROM or a bigger one.  By default our
+tools generate an image suitable for a 93C46 EEPROM: the generated image is 64
+words long, with a checksum in word 63, and the EEPROM type byte in FTDI's
+structure is set to 0x46.  Running with -b produces an image for a 93C56 EEPROM:
+the EEPROM type byte is set to 0x56, and the checksum-covered image length is
+extended to 128 words.  Finally, -B sets things up for a 93C66 EEPROM: the
+EEPROM type byte is set to 0x66, but the generated checksum-covered image is
+still 128 words long just like with -b, as that is what FT2232x chips apparently
+expect.  I said "apparently" because I don't have any FT2232x hardware with
+93C66 EEPROMs and I don't plan on acquiring or building any, hence this minimal
+93C66 support is completely untested - use at your own risk.
+
+It also needs to be noted that with our current RE-based understanding of FTDI's
+undocumented EEPROM structure, using a bigger EEPROM does NOT provide more room
+for strings: all that happens with -b and -B options is that a gap of 64 unused
+EEPROM words is inserted between the end of the fixed structure and the
+beginning of strings.  The exact same arrangement has been observed in all 93C56
+EEPROM images found in the wild, presumably produced with FTDI's official tools,
+including FTDI's own USB-COM232-PLUS2 board - thus it is not clear at all if
+FT2232x chips actually support longer strings with bigger EEPROMs, and if not,
+what does one need a bigger EEPROM for...
+
+For the format of config files read by our ftee-gen2232[ch] tools and what
+settings can be tweaked, read the source code.
+
+Erasing the EEPROM (making it blank)
+====================================
+
+If you are playing with a "generic" FT2232x breakout board that is made for
+tinkering, as opposed to a more finished product, such boards are typically
+shipped with their EEPROMs completely blank.  In that case restoring the EEPROM
+to its "pristine" state after playing around would mean erasing it, i.e.,
+bringing it into a blank (all ones) state.  FT2232x chips provide two ways to
+do so: one can explicitly write 0xFFFF into each individual EEPROM word with
+SIO_WRITE_EEPROM_REQUEST, or one can send a SIO_ERASE_EEPROM_REQUEST command to
+the chip, and the chip then erases the entire EEPROM.  But we don't know how
+the latter SIO_ERASE_EEPROM_REQUEST operation is implemented by FT2232x chips:
+does the FT2232x chip go through and erase each word individually, or does it
+issue an "erase full chip" opcode to the serial EEPROM?  If the latter, then
+according to some EEPROM datasheets that operation may not work if the EEPROM
+is powered from a 3.3V rail rather than the full USB 5V - may be an issue in
+FT2232H-based designs.
+
+In any case our tools provide both ways.  To perform the "automatic full chip
+erase" operation, run the following command:
+
+fteeprom-erase <device-selector>
+
+To blank the EEPROM by writing 0xFFFF into each word, run one of the following
+pipelines:
+
+ftee-mkblank | fteeprom-prog <device-selector>		-- blank a 93C46 EEPROM
+ftee-mkblank -b | fteeprom-prog <device-selector>	-- blank a 93C56 EEPROM
+ftee-mkblank -B | fteeprom-prog <device-selector>	-- blank a 93C66 EEPROM
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/Unbuffered-FT2232x-JTAG	Sat Sep 09 21:28:02 2023 +0000
@@ -0,0 +1,166 @@
+How to make a safe JTAG adapter out of a generic unbuffered FT2232x board
+=========================================================================
+
+Among the FOSS community of tinkerers who use OpenOCD to operate on the JTAG
+interfaces of various hardware targets, one of the most common JTAG adapter
+choices (if not the most common) is to use some adapter gadget based on an FTDI
+chip, most commonly one of FT2232x variants.  However, a major distinction needs
+to be drawn between specialized purpose-made JTAG adapter products which just
+happen to use an FT2232x chip internally, versus generic FT2232x breakout boards
+which the user wires up for JTAG on his or her own.
+
+In an ideal world, using a purpose-made buffered JTAG adapter (one that has a
+buffer inserted between FT2232x I/O pins and the target connection interface)
+would be strongly preferable for a whole host of reasons.  However, to this
+author's disappointment, there are very few community vendors who make such
+adapters, and I was NOT able to find any high-quality buffered JTAG adapter
+which can be bought in the present and which comes with published schematics.
+(There is one very well-known vendor of "community" JTAG adapters who refuses
+to publish schematics for their current model; they have an older model for
+which they did publish schematics, but it is discontinued and they are not
+interested in bringing it back into production or handing the complete design
+over to the community - probably because it would then compete with their
+current sans-schematics product!  Selling JTAG adapters to the community while
+keeping their schematics secret is just assinine, and I refuse to give my
+business to such vendors.)
+
+Given the current sorry state of availability of buffered JTAG adapters, I have
+given more thought to the unbuffered option, and I found what appears to be a
+way to make them safe - but my method requires programming the EEPROM on the
+FT2232x board with a special custom configuration, and in this article I am
+going to provide the full details and instructions.
+
+To begin with, an unbuffered JTAG adapter (one in which the target JTAG signals
+are connected directly to FT2232x I/O pins without any buffer in between) can
+work only with targets that operate their JTAG interface at 3.3 V, or perhaps
+a slightly lower but still fully 3.3V-compatible logic voltage level like the
+2.8 V I/O on Calypso GSM baseband processors.  An unbuffered adapter CANNOT
+work with, say, a 1.8 V JTAG interface - but as long as your target runs at
+3.3 or 2.8 V, then we can continue.
+
+The next big problem with unbuffered FT2232x adapters is that if you don't put
+a special configuration in the EEPROM (or if your FT2232x board omits the EEPROM
+altogether), the channel which you are going to wire up for JTAG (can only be
+Channel A on FT2232C/D, can be either channel on FT2232H) is going to come up
+in FTDI's default UART mode on power-up, and it is going to stay in that mode
+until and unless you run OpenOCD, which will then switch it into MPSSE mode for
+JTAG.  Why is it a problem?  Answer: you need to connect the TDO line from the
+target to the FT2232x chip's ADBUS2 pin for JTAG to work via MPSSE, but in the
+power-up default UART mode this ADBUS2 pin is the RTS output.  FT2232x RTS
+output fighting with the target's TDO output - not good, and it could even fry
+one or both of the chips.
+
+Unfortunately FTDI's stupid chip design does not allow the desired MPSSE mode
+to be configured in the EEPROM so that it is there right from power-up.  But
+there is a workaround: if the EEPROM config is set up to put Channel A (the one
+that will be wired for JTAG) into the rarely-used 245 FIFO mode instead of UART,
+all 8 ADBUS pins (including ADBUS2 where TDO will be connected) will power up
+as inputs with weak internal pull-ups (as long as the ACBUS2 control line is
+left unconnected), which is much safer than what these pins do in the default
+UART mode.
+
+And if we need to program the EEPROM with a special custom config to change
+Channel A from 232 UART to 245 FIFO, we can also assign a different USB VID:PID
+at the same time.  FTDI's default FT2232x ID of 0403:6010 works great when both
+channels of the FT2232x device are used as UARTs - the Linux kernel recognizes
+this USB ID, creates a pair of ttyUSB devices (one for each channel), and
+everything Just Works.  But what if Channel A is used for JTAG and is therefore
+not a valid UART channel?  If the default USB ID is left unchanged, what happens
+is that a pair of ttyUSB devices still gets created, with the first out of the
+pair being completely bogus and non-functional.  And when you run OpenOCD, that
+bogus Channel A ttyUSB device disappears, while the Channel B ttyUSB device
+(which will actually work if Channel B is wired as a UART) remains, creating a
+gap in ttyUSB numbers.  If you have a ton of ttyUSB devices on your system and
+are struggling to keep track of which is which, this behaviour certainly does
+not help.
+
+As it happens, our company Falconia Partners LLC has received a block of 8 PIDs
+from FTDI, allocated out of FTDI's VID range - these PIDs have been officially
+allocated by FTDI to our company for use in products based on FTDI chips.  And
+because we can spare one PID for a worthy cause, one of these PIDs (0403:7151)
+is hereby being donated to the community for use on generic FT2232x boards in
+the unbuffered JTAG adapter configuration.
+
+Support for this 0403:7151 USB ID has been added to Linux ftdi_sio driver in
+2020-09 with this commit:
+
+https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6cf87e5edd9944e1d3b6efd966ea401effc304ee
+
+This commit is included in stable kernel versions 4.4.240, 4.9.240, 4.14.202,
+4.19.152, 5.4.72, 5.8.16 and 5.9.1, and it will appear in mainline kernels from
+5.10 onward.  If your Linux kernel version (or rather ftdi_sio driver version
+if it's a module) includes this commit, the ftdi_sio driver will create a
+ttyUSB device for Channel B, allowing that channel to function as a UART if
+desired, but Channel A will be left alone by the kernel driver, reserved for
+userspace applications like OpenOCD.  If your kernel/driver version does not
+include the newly added commit, both FT2232x channels will be left alone by the
+kernel driver, i.e., no ttyUSB devices will be created.  If you are interested
+only in JTAG and don't need an extra UART on Channel B, it should not matter
+whether your ftdi_sio driver knows about the new custom USB ID or not - you
+simply configure your OpenOCD in userspace to find your unbuffered and ad-hoc-
+wired JTAG adapter at USB ID 0403:7151.  If you do need the UART on Channel B
+but your Linux kernel version does not include the recent addition, you will
+need to manually apply the trivial patch from the commit linked above.
+
+Choice of FT2232x breakout board
+================================
+
+Here at FreeCalypso HQ we make very extensive use of FT2232C/D breakout boards
+by PLDkit, and I officially recommend and endorse this vendor:
+
+http://pldkit.com/other/ft2232d-module
+
+These modules were originally made with FT2232D chips, then the vendor found a
+stash of old but still good FT2232C chips, and some modules were made with these
+FT2232C chips.  Now it looks like the vendor has gone back to FT2232D - but this
+distinction makes no difference for the present purpose.
+
+These days FT2232H chips and FT2232H breakout boards are much more popular, but
+I generally prefer FT2232C/D for classicness and simplicity.  Additionally,
+FTDI's AN_184 document lists I/O pin behaviour of various FTDI chips including
+FT2232D and FT2232H; according to this document FT2232H I/O pins go through a
+brief phase of acting as UART signals (including RTS output on ADBUS2) while
+the EEPROM is being read, whereas FT2232D I/O pins are tristated during this
+time.  Thus I strongly recommend using an FT2232D breakout board.
+
+Programming the EEPROM
+======================
+
+The officially recommended FT2232D breakout boards from PLDkit have 93C46
+EEPROMs on them, and the boards are shipped with blank EEPROMs.  The blank
+EEPROM state is perfectly good for operating the board as a dual UART, but our
+JTAG application calls for custom EEPROM programming.  A number of people in
+the FOSS community have produced several different tools for programming FTDI
+EEPROMs, and you could even use FTDI's official Winblows tools if you like, but
+I am going to describe how to program the EEPROM using the tools which I
+developed and which are used in production here at Falconia Partners LLC.
+
+To compile my FTDI EEPROM tools, go into the fteeprom directory and run make
+there; you will need to have libftdi (the classic one, not libftdi1) installed
+on your system.  If all you seek to do is to program this one EEPROM, you don't
+need to install my tools system-wide - you can just run them from the directory
+where they are compiled.
+
+If you have the FT2232D board in its initial blank-EEPROM state plugged into
+your system and you don't have any other FT2232x devices with 0403:6010 IDs,
+you can program the EEPROM for JTAG as follows - run this pipeline from the top
+directory of this code repository:
+
+fteeprom/ftee-gen2232c eeproms/jtag-unbuf | fteeprom/fteeprom-prog i:0x0403:0x6010
+
+Then unplug and replug the FT2232D board, and it should come back with the new
+0403:7151 USB ID.  If you wish to bring it back to its original blank-EEPROM
+state, you can do so by erasing the EEPROM:
+
+fteeprom-erase i:0x0403:0x7151
+
+Wire connections
+================
+
+The JTAG signal connections to ADBUS0 through ADBUS3 are fixed by FTDI, and if
+you go against my advice and use FT2232H rather than FT2232C/D, then ADBUS7 is
+also reserved for RTCK.  The I/O pins available for reset and other sideband or
+GPIO signals are ADBUS4 through ADBUS7 on FT2232C/D adapters, or ADBUS4 through
+ADBUS6 and ACBUS5 through ACBUS7 on FT2232H.  The other pins should be left
+untouched to avoid problems with the 245 FIFO mode which is active in the time
+window between power-up (USB plug-in) and running OpenOCD.