jtagspi/pld: add interface to get support from pld drivers
Jtagspi is using a proxy bitstream to "connect" JTAG to the SPI pins. This is not possible with all FPGA vendors/families. In this cases a dedicated procedure is needed to establish such a connection. This patch adds a jtagspi-mode for these cases. It also adds the needed interfaces to jtagspi and the pld-driver so the driver can select the mode and provide the necessary procedures. For the cases where a proxy bitstream is needed, the pld driver will select the mode and provide instruction code needed in this case. Change-Id: I9563f26739589157b39a3664a73d91152cd13f77 Signed-off-by: Daniel Anselmi <danselmi@gmx.ch> Reviewed-on: https://review.openocd.org/c/openocd/+/7822 Tested-by: jenkins Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
parent
30375c6439
commit
fe5ed48f40
|
@ -5900,24 +5900,42 @@ flash bank $_FLASHNAME cfi 0x00000000 0x02000000 2 4 $_TARGETNAME
|
||||||
@c "cfi part_id" disabled
|
@c "cfi part_id" disabled
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
@anchor{jtagspi}
|
||||||
@deffn {Flash Driver} {jtagspi}
|
@deffn {Flash Driver} {jtagspi}
|
||||||
@cindex Generic JTAG2SPI driver
|
@cindex Generic JTAG2SPI driver
|
||||||
@cindex SPI
|
@cindex SPI
|
||||||
@cindex jtagspi
|
@cindex jtagspi
|
||||||
@cindex bscan_spi
|
@cindex bscan_spi
|
||||||
Several FPGAs and CPLDs can retrieve their configuration (bitstream) from a
|
Several FPGAs and CPLDs can retrieve their configuration (bitstream) from a
|
||||||
SPI flash connected to them. To access this flash from the host, the device
|
SPI flash connected to them. To access this flash from the host, some FPGA
|
||||||
is first programmed with a special proxy bitstream that
|
device provides dedicated JTAG instructions, while other FPGA devices should
|
||||||
exposes the SPI flash on the device's JTAG interface. The flash can then be
|
be programmed with a special proxy bitstream that exposes the SPI flash on
|
||||||
accessed through JTAG.
|
the device's JTAG interface. The flash can then be accessed through JTAG.
|
||||||
|
|
||||||
Since signaling between JTAG and SPI is compatible, all that is required for
|
Since signalling between JTAG and SPI is compatible, all that is required for
|
||||||
a proxy bitstream is to connect TDI-MOSI, TDO-MISO, TCK-CLK and activate
|
a proxy bitstream is to connect TDI-MOSI, TDO-MISO, TCK-CLK and activate
|
||||||
the flash chip select when the JTAG state machine is in SHIFT-DR. Such
|
the flash chip select when the JTAG state machine is in SHIFT-DR.
|
||||||
a bitstream for several Xilinx FPGAs can be found in
|
|
||||||
|
Such a bitstream for several Xilinx FPGAs can be found in
|
||||||
@file{contrib/loaders/flash/fpga/xilinx_bscan_spi.py}. It requires
|
@file{contrib/loaders/flash/fpga/xilinx_bscan_spi.py}. It requires
|
||||||
@uref{https://github.com/m-labs/migen, migen} and a Xilinx toolchain to build.
|
@uref{https://github.com/m-labs/migen, migen} and a Xilinx toolchain to build.
|
||||||
|
|
||||||
|
This mechanism with a proxy bitstream can also be used for FPGAs from Intel and
|
||||||
|
Efinix. FPGAs from Lattice and Cologne Chip have dedicated JTAG instructions
|
||||||
|
and procedure to connect the JTAG to the SPI signals and don't need a proxy
|
||||||
|
bitstream. Support for these devices with dedicated procedure is provided by
|
||||||
|
the pld drivers. For convenience the PLD drivers will provide the USERx code
|
||||||
|
for FPGAs with a proxy bitstream. Currently the following PLD drivers are able
|
||||||
|
to support jtagspi:
|
||||||
|
@itemize
|
||||||
|
@item Efinix: proxy-bitstream
|
||||||
|
@item Gatemate: dedicated procedure
|
||||||
|
@item Intel/Altera: proxy-bitstream
|
||||||
|
@item Lattice: dedicated procedure supporting ECP2, ECP3, ECP5, Certus and Certus Pro devices
|
||||||
|
@item AMD/Xilinx: proxy-bitstream
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
|
||||||
This flash bank driver requires a target on a JTAG tap and will access that
|
This flash bank driver requires a target on a JTAG tap and will access that
|
||||||
tap directly. Since no support from the target is needed, the target can be a
|
tap directly. Since no support from the target is needed, the target can be a
|
||||||
"testee" dummy. Since the target does not expose the flash memory
|
"testee" dummy. Since the target does not expose the flash memory
|
||||||
|
@ -5935,14 +5953,25 @@ command, see below.
|
||||||
@item @var{ir} ... is loaded into the JTAG IR to map the flash as the JTAG DR.
|
@item @var{ir} ... is loaded into the JTAG IR to map the flash as the JTAG DR.
|
||||||
For the bitstreams generated from @file{xilinx_bscan_spi.py} this is the
|
For the bitstreams generated from @file{xilinx_bscan_spi.py} this is the
|
||||||
@var{USER1} instruction.
|
@var{USER1} instruction.
|
||||||
@end itemize
|
@example
|
||||||
|
target create $_TARGETNAME testee -chain-position $_CHIPNAME.tap
|
||||||
|
set _USER1_INSTR_CODE 0x02
|
||||||
|
flash bank $_FLASHNAME jtagspi 0x0 0 0 0 \
|
||||||
|
$_TARGETNAME $_USER1_INSTR_CODE
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@item The option @option{-pld} @var{name} is used to have support from the
|
||||||
|
PLD driver of pld device @var{name}. The name is the name of the pld device
|
||||||
|
given during creation of the pld device.
|
||||||
|
Pld device names are shown by the @command{pld devices} command.
|
||||||
|
|
||||||
@example
|
@example
|
||||||
target create $_TARGETNAME testee -chain-position $_CHIPNAME.fpga
|
target create $_TARGETNAME testee -chain-position $_CHIPNAME.tap
|
||||||
set _XILINX_USER1 0x02
|
set _JTAGSPI_CHAIN_ID $_CHIPNAME.pld
|
||||||
flash bank $_FLASHNAME spi 0x0 0 0 0 \
|
flash bank $_FLASHNAME jtagspi 0x0 0 0 0 \
|
||||||
$_TARGETNAME $_XILINX_USER1
|
$_TARGETNAME -pld $_JTAGSPI_CHAIN_ID
|
||||||
@end example
|
@end example
|
||||||
|
@end itemize
|
||||||
|
|
||||||
@deffn Command {jtagspi set} bank_id name total_size page_size read_cmd unused pprg_cmd mass_erase_cmd sector_size sector_erase_cmd
|
@deffn Command {jtagspi set} bank_id name total_size page_size read_cmd unused pprg_cmd mass_erase_cmd sector_size sector_erase_cmd
|
||||||
Sets flash parameters: @var{name} human readable string, @var{total_size}
|
Sets flash parameters: @var{name} human readable string, @var{total_size}
|
||||||
|
@ -8668,7 +8697,8 @@ Accordingly, both are called PLDs here.
|
||||||
|
|
||||||
As it does for JTAG TAPs, debug targets, and flash chips (both NOR and NAND),
|
As it does for JTAG TAPs, debug targets, and flash chips (both NOR and NAND),
|
||||||
OpenOCD maintains a list of PLDs available for use in various commands.
|
OpenOCD maintains a list of PLDs available for use in various commands.
|
||||||
Also, each such PLD requires a driver.
|
Also, each such PLD requires a driver. PLD drivers may also be needed to program
|
||||||
|
SPI flash connected to the FPGA to store the bitstream (@xref{jtagspi} for details).
|
||||||
|
|
||||||
They are referenced by the name which was given when the pld was created or
|
They are referenced by the name which was given when the pld was created or
|
||||||
the number shown by the @command{pld devices} command.
|
the number shown by the @command{pld devices} command.
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <jtag/jtag.h>
|
#include <jtag/jtag.h>
|
||||||
#include <flash/nor/spi.h>
|
#include <flash/nor/spi.h>
|
||||||
#include <helper/time_support.h>
|
#include <helper/time_support.h>
|
||||||
|
#include <pld/pld.h>
|
||||||
|
|
||||||
#define JTAGSPI_MAX_TIMEOUT 3000
|
#define JTAGSPI_MAX_TIMEOUT 3000
|
||||||
|
|
||||||
|
@ -22,18 +23,43 @@ struct jtagspi_flash_bank {
|
||||||
char devname[32];
|
char devname[32];
|
||||||
bool probed;
|
bool probed;
|
||||||
bool always_4byte; /* use always 4-byte address except for basic read 0x03 */
|
bool always_4byte; /* use always 4-byte address except for basic read 0x03 */
|
||||||
uint32_t ir;
|
|
||||||
unsigned int addr_len; /* address length in bytes */
|
unsigned int addr_len; /* address length in bytes */
|
||||||
|
struct pld_device *pld_device; /* if not NULL, the PLD has special instructions for JTAGSPI */
|
||||||
|
uint32_t ir; /* when !pld_device, this instruction code is used in
|
||||||
|
jtagspi_set_user_ir to connect through a proxy bitstream */
|
||||||
};
|
};
|
||||||
|
|
||||||
FLASH_BANK_COMMAND_HANDLER(jtagspi_flash_bank_command)
|
FLASH_BANK_COMMAND_HANDLER(jtagspi_flash_bank_command)
|
||||||
{
|
{
|
||||||
struct jtagspi_flash_bank *info;
|
|
||||||
|
|
||||||
if (CMD_ARGC < 7)
|
if (CMD_ARGC < 7)
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
info = malloc(sizeof(struct jtagspi_flash_bank));
|
unsigned int ir = 0;
|
||||||
|
struct pld_device *device = NULL;
|
||||||
|
if (strcmp(CMD_ARGV[6], "-pld") == 0) {
|
||||||
|
if (CMD_ARGC < 8)
|
||||||
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
device = get_pld_device_by_name_or_numstr(CMD_ARGV[7]);
|
||||||
|
if (device) {
|
||||||
|
bool has_jtagspi_instruction = false;
|
||||||
|
int retval = pld_has_jtagspi_instruction(device, &has_jtagspi_instruction);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
if (!has_jtagspi_instruction) {
|
||||||
|
retval = pld_get_jtagspi_userircode(device, &ir);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
device = NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("pld device '#%s' is out of bounds or unknown", CMD_ARGV[7]);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[6], ir);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct jtagspi_flash_bank *info = calloc(1, sizeof(struct jtagspi_flash_bank));
|
||||||
if (!info) {
|
if (!info) {
|
||||||
LOG_ERROR("no memory for flash bank info");
|
LOG_ERROR("no memory for flash bank info");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
@ -47,18 +73,19 @@ FLASH_BANK_COMMAND_HANDLER(jtagspi_flash_bank_command)
|
||||||
}
|
}
|
||||||
info->tap = bank->target->tap;
|
info->tap = bank->target->tap;
|
||||||
info->probed = false;
|
info->probed = false;
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[6], info->ir);
|
|
||||||
|
info->ir = ir;
|
||||||
|
info->pld_device = device;
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void jtagspi_set_ir(struct flash_bank *bank)
|
static void jtagspi_set_user_ir(struct jtagspi_flash_bank *info)
|
||||||
{
|
{
|
||||||
struct jtagspi_flash_bank *info = bank->driver_priv;
|
|
||||||
struct scan_field field;
|
struct scan_field field;
|
||||||
uint8_t buf[4] = { 0 };
|
uint8_t buf[4] = { 0 };
|
||||||
|
|
||||||
LOG_DEBUG("loading jtagspi ir");
|
LOG_DEBUG("loading jtagspi ir(0x%" PRIx32 ")", info->ir);
|
||||||
buf_set_u32(buf, 0, info->tap->ir_length, info->ir);
|
buf_set_u32(buf, 0, info->tap->ir_length, info->ir);
|
||||||
field.num_bits = info->tap->ir_length;
|
field.num_bits = info->tap->ir_length;
|
||||||
field.out_value = buf;
|
field.out_value = buf;
|
||||||
|
@ -79,6 +106,7 @@ static int jtagspi_cmd(struct flash_bank *bank, uint8_t cmd,
|
||||||
assert(data_buffer || data_len == 0);
|
assert(data_buffer || data_len == 0);
|
||||||
|
|
||||||
struct scan_field fields[6];
|
struct scan_field fields[6];
|
||||||
|
struct jtagspi_flash_bank *info = bank->driver_priv;
|
||||||
|
|
||||||
LOG_DEBUG("cmd=0x%02x write_len=%d data_len=%d", cmd, write_len, data_len);
|
LOG_DEBUG("cmd=0x%02x write_len=%d data_len=%d", cmd, write_len, data_len);
|
||||||
|
|
||||||
|
@ -87,8 +115,20 @@ static int jtagspi_cmd(struct flash_bank *bank, uint8_t cmd,
|
||||||
if (is_read)
|
if (is_read)
|
||||||
data_len = -data_len;
|
data_len = -data_len;
|
||||||
|
|
||||||
|
unsigned int facing_read_bits = 0;
|
||||||
|
unsigned int trailing_write_bits = 0;
|
||||||
|
|
||||||
|
if (info->pld_device) {
|
||||||
|
int retval = pld_get_jtagspi_stuff_bits(info->pld_device, &facing_read_bits, &trailing_write_bits);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
const uint8_t marker = 1;
|
const uint8_t marker = 1;
|
||||||
|
uint8_t xfer_bits[4];
|
||||||
|
if (!info->pld_device) { /* mode == JTAGSPI_MODE_PROXY_BITSTREAM */
|
||||||
|
facing_read_bits = jtag_tap_count_enabled();
|
||||||
fields[n].num_bits = 1;
|
fields[n].num_bits = 1;
|
||||||
fields[n].out_value = ▮
|
fields[n].out_value = ▮
|
||||||
fields[n].in_value = NULL;
|
fields[n].in_value = NULL;
|
||||||
|
@ -96,13 +136,13 @@ static int jtagspi_cmd(struct flash_bank *bank, uint8_t cmd,
|
||||||
|
|
||||||
/* transfer length = cmd + address + read/write,
|
/* transfer length = cmd + address + read/write,
|
||||||
* -1 due to the counter implementation */
|
* -1 due to the counter implementation */
|
||||||
uint8_t xfer_bits[4];
|
|
||||||
h_u32_to_be(xfer_bits, ((sizeof(cmd) + write_len + data_len) * CHAR_BIT) - 1);
|
h_u32_to_be(xfer_bits, ((sizeof(cmd) + write_len + data_len) * CHAR_BIT) - 1);
|
||||||
flip_u8(xfer_bits, xfer_bits, sizeof(xfer_bits));
|
flip_u8(xfer_bits, xfer_bits, sizeof(xfer_bits));
|
||||||
fields[n].num_bits = sizeof(xfer_bits) * CHAR_BIT;
|
fields[n].num_bits = sizeof(xfer_bits) * CHAR_BIT;
|
||||||
fields[n].out_value = xfer_bits;
|
fields[n].out_value = xfer_bits;
|
||||||
fields[n].in_value = NULL;
|
fields[n].in_value = NULL;
|
||||||
n++;
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
flip_u8(&cmd, &cmd, sizeof(cmd));
|
flip_u8(&cmd, &cmd, sizeof(cmd));
|
||||||
fields[n].num_bits = sizeof(cmd) * CHAR_BIT;
|
fields[n].num_bits = sizeof(cmd) * CHAR_BIT;
|
||||||
|
@ -120,10 +160,12 @@ static int jtagspi_cmd(struct flash_bank *bank, uint8_t cmd,
|
||||||
|
|
||||||
if (data_len > 0) {
|
if (data_len > 0) {
|
||||||
if (is_read) {
|
if (is_read) {
|
||||||
fields[n].num_bits = jtag_tap_count_enabled();
|
if (facing_read_bits) {
|
||||||
|
fields[n].num_bits = facing_read_bits;
|
||||||
fields[n].out_value = NULL;
|
fields[n].out_value = NULL;
|
||||||
fields[n].in_value = NULL;
|
fields[n].in_value = NULL;
|
||||||
n++;
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
fields[n].out_value = NULL;
|
fields[n].out_value = NULL;
|
||||||
fields[n].in_value = data_buffer;
|
fields[n].in_value = data_buffer;
|
||||||
|
@ -135,16 +177,33 @@ static int jtagspi_cmd(struct flash_bank *bank, uint8_t cmd,
|
||||||
fields[n].num_bits = data_len * CHAR_BIT;
|
fields[n].num_bits = data_len * CHAR_BIT;
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
if (!is_read && trailing_write_bits) {
|
||||||
|
fields[n].num_bits = trailing_write_bits;
|
||||||
|
fields[n].out_value = NULL;
|
||||||
|
fields[n].in_value = NULL;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info->pld_device) {
|
||||||
|
int retval = pld_connect_spi_to_jtag(info->pld_device);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
} else {
|
||||||
|
jtagspi_set_user_ir(info);
|
||||||
|
}
|
||||||
|
|
||||||
jtagspi_set_ir(bank);
|
|
||||||
/* passing from an IR scan to SHIFT-DR clears BYPASS registers */
|
/* passing from an IR scan to SHIFT-DR clears BYPASS registers */
|
||||||
struct jtagspi_flash_bank *info = bank->driver_priv;
|
|
||||||
jtag_add_dr_scan(info->tap, n, fields, TAP_IDLE);
|
jtag_add_dr_scan(info->tap, n, fields, TAP_IDLE);
|
||||||
int retval = jtag_execute_queue();
|
int retval = jtag_execute_queue();
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
if (is_read)
|
if (is_read)
|
||||||
flip_u8(data_buffer, data_buffer, data_len);
|
flip_u8(data_buffer, data_buffer, data_len);
|
||||||
return retval;
|
|
||||||
|
if (info->pld_device)
|
||||||
|
return pld_disconnect_spi_from_jtag(info->pld_device);
|
||||||
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_HANDLER(jtagspi_handle_set)
|
COMMAND_HANDLER(jtagspi_handle_set)
|
||||||
|
|
|
@ -69,8 +69,95 @@ struct pld_device *get_pld_device_by_name_or_numstr(const char *str)
|
||||||
return get_pld_device_by_num(dev_num);
|
return get_pld_device_by_num(dev_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* @deffn {Config Command} {pld create} pld_name driver -chain-position tap_name [options]
|
|
||||||
*/
|
int pld_has_jtagspi_instruction(struct pld_device *pld_device, bool *has_instruction)
|
||||||
|
{
|
||||||
|
*has_instruction = false; /* default is using a proxy bitstream */
|
||||||
|
|
||||||
|
if (!pld_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct pld_driver *pld_driver = pld_device->driver;
|
||||||
|
if (!pld_driver) {
|
||||||
|
LOG_ERROR("pld device has no associated driver");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pld_driver->has_jtagspi_instruction)
|
||||||
|
return pld_driver->has_jtagspi_instruction(pld_device, has_instruction);
|
||||||
|
/* else, take the default (proxy bitstream) */
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pld_get_jtagspi_userircode(struct pld_device *pld_device, unsigned int *ir)
|
||||||
|
{
|
||||||
|
if (!pld_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct pld_driver *pld_driver = pld_device->driver;
|
||||||
|
if (!pld_driver) {
|
||||||
|
LOG_ERROR("pld device has no associated driver");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pld_driver->get_jtagspi_userircode)
|
||||||
|
return pld_driver->get_jtagspi_userircode(pld_device, ir);
|
||||||
|
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pld_get_jtagspi_stuff_bits(struct pld_device *pld_device, unsigned int *facing_read_bits,
|
||||||
|
unsigned int *trailing_write_bits)
|
||||||
|
{
|
||||||
|
if (!pld_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct pld_driver *pld_driver = pld_device->driver;
|
||||||
|
if (!pld_driver) {
|
||||||
|
LOG_ERROR("pld device has no associated driver");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pld_driver->get_stuff_bits)
|
||||||
|
return pld_driver->get_stuff_bits(pld_device, facing_read_bits, trailing_write_bits);
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pld_connect_spi_to_jtag(struct pld_device *pld_device)
|
||||||
|
{
|
||||||
|
if (!pld_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct pld_driver *pld_driver = pld_device->driver;
|
||||||
|
if (!pld_driver) {
|
||||||
|
LOG_ERROR("pld device has no associated driver");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pld_driver->connect_spi_to_jtag)
|
||||||
|
return pld_driver->connect_spi_to_jtag(pld_device);
|
||||||
|
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pld_disconnect_spi_from_jtag(struct pld_device *pld_device)
|
||||||
|
{
|
||||||
|
if (!pld_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct pld_driver *pld_driver = pld_device->driver;
|
||||||
|
if (!pld_driver) {
|
||||||
|
LOG_ERROR("pld device has no associated driver");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pld_driver->disconnect_spi_from_jtag)
|
||||||
|
return pld_driver->disconnect_spi_from_jtag(pld_device);
|
||||||
|
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
COMMAND_HANDLER(handle_pld_create_command)
|
COMMAND_HANDLER(handle_pld_create_command)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC < 2)
|
if (CMD_ARGC < 2)
|
||||||
|
|
|
@ -20,12 +20,26 @@ struct pld_ipdbg_hub {
|
||||||
unsigned int user_ir_code;
|
unsigned int user_ir_code;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int pld_has_jtagspi_instruction(struct pld_device *device, bool *has_instruction);
|
||||||
|
int pld_get_jtagspi_userircode(struct pld_device *pld_device, unsigned int *ir);
|
||||||
|
|
||||||
|
int pld_get_jtagspi_stuff_bits(struct pld_device *pld_device, unsigned int *facing_read_bits,
|
||||||
|
unsigned int *trailing_write_bits);
|
||||||
|
int pld_connect_spi_to_jtag(struct pld_device *pld_device);
|
||||||
|
int pld_disconnect_spi_from_jtag(struct pld_device *pld_device);
|
||||||
|
|
||||||
struct pld_driver {
|
struct pld_driver {
|
||||||
const char *name;
|
const char *name;
|
||||||
__PLD_CREATE_COMMAND((*pld_create_command));
|
__PLD_CREATE_COMMAND((*pld_create_command));
|
||||||
const struct command_registration *commands;
|
const struct command_registration *commands;
|
||||||
int (*load)(struct pld_device *pld_device, const char *filename);
|
int (*load)(struct pld_device *pld_device, const char *filename);
|
||||||
int (*get_ipdbg_hub)(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub);
|
int (*get_ipdbg_hub)(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub);
|
||||||
|
int (*has_jtagspi_instruction)(struct pld_device *device, bool *has_instruction);
|
||||||
|
int (*get_jtagspi_userircode)(struct pld_device *pld_device, unsigned int *ir);
|
||||||
|
int (*connect_spi_to_jtag)(struct pld_device *pld_device);
|
||||||
|
int (*disconnect_spi_from_jtag)(struct pld_device *pld_device);
|
||||||
|
int (*get_stuff_bits)(struct pld_device *pld_device, unsigned int *facing_read_bits,
|
||||||
|
unsigned int *trailing_write_bits);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PLD_CREATE_COMMAND_HANDLER(name) \
|
#define PLD_CREATE_COMMAND_HANDLER(name) \
|
||||||
|
|
|
@ -4,6 +4,8 @@ set _USER1 0x02
|
||||||
|
|
||||||
if { [info exists JTAGSPI_IR] } {
|
if { [info exists JTAGSPI_IR] } {
|
||||||
set _JTAGSPI_IR $JTAGSPI_IR
|
set _JTAGSPI_IR $JTAGSPI_IR
|
||||||
|
} elseif {[info exists JTAGSPI_CHAIN_ID]} {
|
||||||
|
set _JTAGSPI_CHAIN_ID $JTAGSPI_CHAIN_ID
|
||||||
} else {
|
} else {
|
||||||
set _JTAGSPI_IR $_USER1
|
set _JTAGSPI_IR $_USER1
|
||||||
}
|
}
|
||||||
|
@ -21,7 +23,11 @@ if { [info exists FLASHNAME] } {
|
||||||
}
|
}
|
||||||
|
|
||||||
target create $_TARGETNAME testee -chain-position $_CHIPNAME.tap
|
target create $_TARGETNAME testee -chain-position $_CHIPNAME.tap
|
||||||
|
if { [info exists _JTAGSPI_IR] } {
|
||||||
flash bank $_FLASHNAME jtagspi 0 0 0 0 $_TARGETNAME $_JTAGSPI_IR
|
flash bank $_FLASHNAME jtagspi 0 0 0 0 $_TARGETNAME $_JTAGSPI_IR
|
||||||
|
} else {
|
||||||
|
flash bank $_FLASHNAME jtagspi 0 0 0 0 $_TARGETNAME -pld $_JTAGSPI_CHAIN_ID
|
||||||
|
}
|
||||||
|
|
||||||
# initialize jtagspi flash
|
# initialize jtagspi flash
|
||||||
# chain_id: identifier of pld (you can get a list with 'pld devices')
|
# chain_id: identifier of pld (you can get a list with 'pld devices')
|
||||||
|
@ -33,7 +39,9 @@ flash bank $_FLASHNAME jtagspi 0 0 0 0 $_TARGETNAME $_JTAGSPI_IR
|
||||||
proc jtagspi_init {chain_id proxy_bit {release_from_pwr_down_cmd -1}} {
|
proc jtagspi_init {chain_id proxy_bit {release_from_pwr_down_cmd -1}} {
|
||||||
# load proxy bitstream $proxy_bit and probe spi flash
|
# load proxy bitstream $proxy_bit and probe spi flash
|
||||||
global _FLASHNAME
|
global _FLASHNAME
|
||||||
|
if { $proxy_bit ne "" } {
|
||||||
pld load $chain_id $proxy_bit
|
pld load $chain_id $proxy_bit
|
||||||
|
}
|
||||||
reset halt
|
reset halt
|
||||||
if {$release_from_pwr_down_cmd != -1} {
|
if {$release_from_pwr_down_cmd != -1} {
|
||||||
jtagspi cmd $_FLASHNAME 0 $release_from_pwr_down_cmd
|
jtagspi cmd $_FLASHNAME 0 $release_from_pwr_down_cmd
|
||||||
|
|
Loading…
Reference in New Issue