Commit 7ce767ae authored by Adrian Byszuk's avatar Adrian Byszuk

configure_ftdi.py: add support for Vivado JTAG

The only thing required by Vivado to recognize random FTDI chips as a valid
JTAG dongle is a magic EEPROM content.
This commit adds this magic sequence to FTDI configuration script.
Partially inspired by Xilinx's own "program_ftdi" tool bundled with Vivado
versions >= 2022.1, which allows to do exactly the same thing.
parent 2f1a6668
......@@ -9,6 +9,14 @@ connected to USB ports at the same time!
from pyftdi.eeprom import FtdiEeprom
from pyftdi.misc import hexdump
import struct
# EEPROM chip type (0x46, 0x56 or 0x66)
CHIP_TYPE = 0x56
# Xilinx magic constants for different FTDI chips
MAGIC_232H = 0x584a0002
MAGIC_2232H = 0x584a0003
MAGIC_4232H = 0x584a0004
eeprom = FtdiEeprom()
eeprom.open('ftdi://ftdi:ft4232h/1')
......@@ -24,6 +32,49 @@ except AttributeError:
print('\nInitializing config:')
eeprom.initialize()
# Manufacturer has to be set to 'Xilinx' to stay compatible with Xilinx udev
# rules (part of driver installation package)
eeprom.set_manufacturer_name('Xilinx')
eeprom.set_product_name('DIOT FMC Carrier')
# uncomment to set your own SN instead of random one
# eeprom.set_serial_number('FT5PTILK')
# Now we're fiddling with a low level EEPROM layout. This layout isn't
# documented by FTDI, but it's somewhat documented in libftdi source code.
# There are a few things we need to set here to make FTDI chip recognizable as
# a JTAG dongle by Vivado.
# We need to use a few non-public class fields, so this code is prone to break
# on pyftdi update.
# ATTENTION: bit layout and meaning changes between FTDI device types !!!
#
# - chip type (not really necessary, but let's be nice)
eeprom._chip = CHIP_TYPE
chipoff = eeprom._PROPERTIES[eeprom.device_version].chipoff
eeprom._eeprom[chipoff] = CHIP_TYPE # usually at 0x18 offset
# - switch port A (JTAG), B (I2C) and D (unused) to D2XX type
eeprom._eeprom[0x00] = 0x80 # bit 3 - CH A D2xx, bit 7 - CH C VCP
eeprom._eeprom[0x01] = 0x00 # bit 3 - CH B D2xx, bit 7 - CH D D2XX
# - self powered, no remote wakeup, no battery powered
eeprom._eeprom[0x08] = 0xC0
# - use serial, no suspend_pull_down
eeprom._eeprom[0x0a] = 0x08
# - all channels rs485 disable
eeprom._eeprom[0x0b] = 0x00
# - group settings, other FT4232H dongles have 0 here
eeprom._eeprom[0x0c] = 0x00
eeprom._eeprom[0x0d] = 0x00
# - now the magic sequence at the beginning of user area
useroff = eeprom._PROPERTIES[eeprom.device_version].user
eeprom._eeprom[useroff:useroff+4] = struct.pack('<I', MAGIC_4232H)
# - vendor and product names, but different from generic FTDI ones
bstream = bytearray()
bstream.extend('CERN\0'.encode('utf-8')) # Vendor name
bstream.extend('DIOT FMC Carrier FT4232H\0'.encode('utf-8')) # Product name
eeprom._eeprom[useroff+4:useroff+4+len(bstream)] = bstream
eeprom._dirty.add('eeprom')
eeprom.sync()
eeprom.dump_config()
print(hexdump(eeprom.data))
print('Writing EEPROM...')
if not eeprom.commit(dry_run=False):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment