This is an automated email from Gerrit. "Daniel Anselmi <danse...@gmx.ch>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/7713
-- gerrit commit 2e39cf4dfcf3d76ab6a698ef6294257c0e83fd34 Author: Daniel Anselmi <danse...@gmx.ch> Date: Sat Apr 15 01:13:12 2023 +0200 pld/xilinx: make instruction codes configurable Change-Id: I4d2c1fbd4d6007ba8d5c8c687a7c13e25fb6a474 Signed-off-by: Daniel Anselmi <danse...@gmx.ch> diff --git a/doc/openocd.texi b/doc/openocd.texi index d0bc3f9f50..18a7793c61 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -8509,6 +8509,22 @@ openocd -f board/digilent_zedboard.cfg -c "init" \ Reads and displays the Virtex-II status register (STAT) for FPGA @var{num}. @end deffn + +@deffn {Command} {virtex2 set_instr_codes} device.tap cfg_out cfg_in jprogb jstart jshutdown [user1 [user2 [user3 [user4]]]] +Change values for boundary scan instructions. Default are values for Virtex 2 devices Virtex 4/5/6 are using different values. +@end deffn +@var{device.tap} is the name of the tap. +@var{cfg_out} is the value used to select CFG_OUT instruction. +@var{cfg_in} is the value used to select CFG_IN instruction. +@var{jprogb} is the value used to select JPROGRAM instruction. +@var{jstart} is the value used to select JSTART instruction. +@var{jshutdown} is the value used to select JSHUTDOWN instruction. +@var{user1} to @var{user4} are the intruction used to select the user registers USER1 to USER4. + +@deffn {Command} {virtex2 set_user_codes} device.tap user1 [user2 [user3 [user4]]] +Change values for boundary scan instructions selecting the registers USER1 to USER4. +@end deffn +Description of the arguments can be found at command @command{virtex2 set_instr_codes}. @end deffn diff --git a/src/pld/virtex2.c b/src/pld/virtex2.c index fd0725a63a..58cc2df3c7 100644 --- a/src/pld/virtex2.c +++ b/src/pld/virtex2.c @@ -13,12 +13,25 @@ #include "xilinx_bit.h" #include "pld.h" -static int virtex2_set_instr(struct jtag_tap *tap, uint32_t new_instr) +static const struct virtex2_command_set virtex2_default_commands = { + .cfg_out = 0x04, + .cfg_in = 0x05, + .jprog_b = 0x0b, + .jstart = 0x0c, + .jshutdown = 0x0d, + .bypass = 0x3f, + .user = {0x02, 0x03}, + .num_user = 2, /* virtex II has only 2 user instructions */ +}; + +static struct virtex2_pld_device *virtex2_pld_devices; + +static int virtex2_set_instr(struct jtag_tap *tap, uint64_t new_instr) { if (!tap) return ERROR_FAIL; - if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr) { + if (buf_get_u64(tap->cur_instr, 0, tap->ir_length) != new_instr) { struct scan_field field; field.num_bits = tap->ir_length; @@ -28,7 +41,7 @@ static int virtex2_set_instr(struct jtag_tap *tap, uint32_t new_instr) return ERROR_FAIL; } field.out_value = t; - buf_set_u32(t, 0, field.num_bits, new_instr); + buf_set_u64(t, 0, field.num_bits, new_instr); field.in_value = NULL; jtag_add_ir_scan(tap, &field, TAP_IDLE); @@ -60,7 +73,7 @@ static int virtex2_send_32(struct pld_device *pld_device, for (i = 0; i < num_words; i++) buf_set_u32(values + 4 * i, 0, 32, flip_u32(*words++, 32)); - int retval = virtex2_set_instr(virtex2_info->tap, 0x5); /* CFG_IN */ + int retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.cfg_in); if (retval != ERROR_OK) { free(values); return retval; @@ -89,7 +102,7 @@ static int virtex2_receive_32(struct pld_device *pld_device, scan_field.out_value = NULL; scan_field.in_value = NULL; - int retval = virtex2_set_instr(virtex2_info->tap, 0x4); /* CFG_OUT */ + int retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.cfg_out); if (retval != ERROR_OK) return retval; @@ -137,7 +150,7 @@ static int virtex2_load_prepare(struct pld_device *pld_device) struct virtex2_pld_device *virtex2_info = pld_device->driver_priv; int retval; - retval = virtex2_set_instr(virtex2_info->tap, 0xb); /* JPROG_B */ + retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jprog_b); if (retval != ERROR_OK) return retval; @@ -146,7 +159,7 @@ static int virtex2_load_prepare(struct pld_device *pld_device) return retval; jtag_add_sleep(1000); - retval = virtex2_set_instr(virtex2_info->tap, 0x5); /* CFG_IN */ + retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.cfg_in); if (retval != ERROR_OK) return retval; @@ -161,24 +174,24 @@ static int virtex2_load_cleanup(struct pld_device *pld_device) jtag_add_tlr(); if (!(virtex2_info->no_jstart)) { - retval = virtex2_set_instr(virtex2_info->tap, 0xc); /* JSTART */ + retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jstart); if (retval != ERROR_OK) return retval; } jtag_add_runtest(13, TAP_IDLE); - retval = virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */ + retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.bypass); if (retval != ERROR_OK) return retval; - retval = virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */ + retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.bypass); if (retval != ERROR_OK) return retval; if (!(virtex2_info->no_jstart)) { - retval = virtex2_set_instr(virtex2_info->tap, 0xc); /* JSTART */ + retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jstart); if (retval != ERROR_OK) return retval; } jtag_add_runtest(13, TAP_IDLE); - retval = virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */ + retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.bypass); if (retval != ERROR_OK) return retval; @@ -252,6 +265,91 @@ COMMAND_HANDLER(virtex2_handle_read_stat_command) return ERROR_OK; } +static int virtex2_get_pld_device_for_tap(struct jtag_tap *tap, struct virtex2_pld_device **virtex2_info) +{ + if (!tap) + return ERROR_FAIL; + + struct virtex2_pld_device *info = virtex2_pld_devices; + while (info) { + if (info->tap == tap) + break; + info = info->next; + } + if (!info) + return ERROR_FAIL; + + *virtex2_info = info; + + return ERROR_OK; +} + +COMMAND_HANDLER(virtex2_handle_set_instuction_codes_command) +{ + if (CMD_ARGC < 6) + return ERROR_COMMAND_SYNTAX_ERROR; + + struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[0]); + if (!tap) { + command_print(CMD, "Tap %s unknown", CMD_ARGV[0]); + return ERROR_FAIL; + } + + struct virtex2_pld_device *virtex2_info; + int retval = virtex2_get_pld_device_for_tap(tap, &virtex2_info); + if (retval != ERROR_OK) { + command_print(CMD, "No virtex2 pld driver initialized for tap %s", CMD_ARGV[0]); + return ERROR_FAIL; + } + + struct virtex2_command_set instr_codes; + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], instr_codes.cfg_out); + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[2], instr_codes.cfg_in); + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[3], instr_codes.jprog_b); + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[4], instr_codes.jstart); + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[5], instr_codes.jshutdown); + instr_codes.bypass = 0xffffffffffffffff; + + uint8_t num_user = 0; + for (size_t i = 0; i < VIRTEX2_MAX_USER_INSTRUCTIONS && CMD_ARGC > 6 + i; ++i) { + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[6 + i], instr_codes.user[i]); + num_user++; + } + instr_codes.num_user = num_user; + + virtex2_info->command_set = instr_codes; + return ERROR_OK; +} + +COMMAND_HANDLER(virtex2_handle_set_user_codes_command) +{ + if (CMD_ARGC < 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[0]); + if (!tap) { + command_print(CMD, "Tap %s unknown", CMD_ARGV[0]); + return ERROR_FAIL; + } + + struct virtex2_pld_device *virtex2_info; + int retval = virtex2_get_pld_device_for_tap(tap, &virtex2_info); + if (retval != ERROR_OK) { + command_print(CMD, "No virtex2 pld driver initialized for tap %s", CMD_ARGV[0]); + return ERROR_FAIL; + } + + uint64_t user[VIRTEX2_MAX_USER_INSTRUCTIONS]; + uint8_t num_user = 0; + for (size_t i = 0; i < VIRTEX2_MAX_USER_INSTRUCTIONS && CMD_ARGC > 1 + i; ++i) { + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1 + i], user[i]); + num_user++; + } + virtex2_info->command_set.num_user = num_user; + memcpy(virtex2_info->command_set.user, user, num_user * sizeof(uint64_t)); + return ERROR_OK; +} + PLD_DEVICE_COMMAND_HANDLER(virtex2_pld_device_command) { struct jtag_tap *tap; @@ -273,13 +371,24 @@ PLD_DEVICE_COMMAND_HANDLER(virtex2_pld_device_command) return ERROR_FAIL; } virtex2_info->tap = tap; + memcpy(&virtex2_info->command_set, &virtex2_default_commands, sizeof(struct virtex2_command_set)); virtex2_info->no_jstart = 0; if (CMD_ARGC >= 3) COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], virtex2_info->no_jstart); + virtex2_info->next = NULL; pld->driver_priv = virtex2_info; + if (!virtex2_pld_devices) { + virtex2_pld_devices = virtex2_info; + } else { + struct virtex2_pld_device *devs = virtex2_pld_devices; + while (devs->next) + devs = devs->next; + devs->next = virtex2_info; + } + return ERROR_OK; } @@ -290,9 +399,23 @@ static const struct command_registration virtex2_exec_command_handlers[] = { .handler = virtex2_handle_read_stat_command, .help = "read status register", .usage = "pld_num", + }, { + .name = "set_instr_codes", + .mode = COMMAND_EXEC, + .handler = virtex2_handle_set_instuction_codes_command, + .help = "set instructions codes used for loading the bitstream/refreshing/jtag-hub", + .usage = "device.tap cfg_out cfg_in jprogb jstart jshutdown" + " [user1 [user2 [user3 [user4]]]]", + }, { + .name = "set_user_codes", + .mode = COMMAND_EXEC, + .handler = virtex2_handle_set_user_codes_command, + .help = "set instructions codes used for jtag-hub", + .usage = "device.tap user1 [user2 [user3 [user4]]]", }, COMMAND_REGISTRATION_DONE }; + static const struct command_registration virtex2_command_handler[] = { { .name = "virtex2", diff --git a/src/pld/virtex2.h b/src/pld/virtex2.h index 05558f709d..32dc44b391 100644 --- a/src/pld/virtex2.h +++ b/src/pld/virtex2.h @@ -10,9 +10,24 @@ #include <jtag/jtag.h> +#define VIRTEX2_MAX_USER_INSTRUCTIONS 4 + +struct virtex2_command_set { + uint64_t cfg_out; + uint64_t cfg_in; + uint64_t jprog_b; + uint64_t jstart; + uint64_t jshutdown; + uint64_t bypass; + uint64_t user[VIRTEX2_MAX_USER_INSTRUCTIONS]; + uint8_t num_user; +}; + struct virtex2_pld_device { struct jtag_tap *tap; int no_jstart; + struct virtex2_command_set command_set; + struct virtex2_pld_device *next; }; #endif /* OPENOCD_PLD_VIRTEX2_H */ --