Skip to content

Commit

Permalink
jtag: add -ir-bypass option to newtap
Browse files Browse the repository at this point in the history
Some devices with an internal multi-tap JTAG router require a vendor
specific bypass instruction to bypass the master TAP when addressing
slave taps internal to the same device. On these devices the standard
bypass instruction bypasses the whole device.

Change-Id: I4506f0e67c9e4dfe39b7fa18c63d67900313e594
Signed-off-by: Henrik Nordström <[email protected]>
Reviewed-on: https://review.openocd.org/c/openocd/+/8041
Reviewed-by: Antonio Borneo <[email protected]>
Tested-by: jenkins
  • Loading branch information
hno-addiva authored and borneoa committed Dec 30, 2023
1 parent fc268f8 commit 8d3728f
Show file tree
Hide file tree
Showing 7 changed files with 31 additions and 1 deletion.
4 changes: 4 additions & 0 deletions doc/openocd.texi
Original file line number Diff line number Diff line change
Expand Up @@ -4424,6 +4424,10 @@ there seems to be no problems with JTAG scan chain operations.
register during initial examination and when checking the sticky error bit.
This bit is normally checked after setting the CSYSPWRUPREQ bit, but some
devices do not set the ack bit until sometime later.
@item @code{-ir-bypass} @var{NUMBER}
@*Vendor specific bypass instruction, required by some hierarchical JTAG
routers where the normal BYPASS instruction bypasses the whole router and
a vendor specific bypass instruction is required to access child nodes.
@end itemize
@end deffn

Expand Down
8 changes: 7 additions & 1 deletion src/jtag/drivers/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,13 @@ int interface_jtag_add_ir_scan(struct jtag_tap *active,
tap->bypass = true;

field->num_bits = tap->ir_length;
field->out_value = buf_set_ones(cmd_queue_alloc(DIV_ROUND_UP(tap->ir_length, 8)), tap->ir_length);
if (tap->ir_bypass_value) {
uint8_t *v = cmd_queue_alloc(DIV_ROUND_UP(tap->ir_length, 8));
buf_set_u64(v, 0, tap->ir_length, tap->ir_bypass_value);
field->out_value = v;
} else {
field->out_value = buf_set_ones(cmd_queue_alloc(DIV_ROUND_UP(tap->ir_length, 8)), tap->ir_length);
}
field->in_value = NULL; /* do not collect input for tap's in bypass */
}

Expand Down
2 changes: 2 additions & 0 deletions src/jtag/hla/hla_transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ static const struct command_registration hl_swd_transport_subcommand_handlers[]
"['-ignore-version'] "
"['-ignore-bypass'] "
"['-ircapture' number] "
"['-ir-bypass' number] "
"['-mask' number]",
},
COMMAND_REGISTRATION_DONE
Expand Down Expand Up @@ -74,6 +75,7 @@ static const struct command_registration hl_transport_jtag_subcommand_handlers[]
"['-ignore-version'] "
"['-ignore-bypass'] "
"['-ircapture' number] "
"['-ir-bypass' number] "
"['-mask' number]",
},
{
Expand Down
3 changes: 3 additions & 0 deletions src/jtag/jtag.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ struct jtag_tap {
/** Bypass register selected */
bool bypass;

/** Bypass instruction value */
uint64_t ir_bypass_value;

struct jtag_tap_event_action *event_action;

struct jtag_tap *next_tap;
Expand Down
12 changes: 12 additions & 0 deletions src/jtag/tcl.c
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ static int jtag_tap_configure_cmd(struct jim_getopt_info *goi, struct jtag_tap *
#define NTAP_OPT_EXPECTED_ID 5
#define NTAP_OPT_VERSION 6
#define NTAP_OPT_BYPASS 7
#define NTAP_OPT_IRBYPASS 8

static const struct nvp jtag_newtap_opts[] = {
{ .name = "-irlen", .value = NTAP_OPT_IRLEN },
Expand All @@ -396,6 +397,7 @@ static const struct nvp jtag_newtap_opts[] = {
{ .name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID },
{ .name = "-ignore-version", .value = NTAP_OPT_VERSION },
{ .name = "-ignore-bypass", .value = NTAP_OPT_BYPASS },
{ .name = "-ir-bypass", .value = NTAP_OPT_IRBYPASS },
{ .name = NULL, .value = -1 },
};

Expand Down Expand Up @@ -499,6 +501,15 @@ static COMMAND_HELPER(handle_jtag_newtap_args, struct jtag_tap *tap)
tap->ignore_bypass = true;
break;

case NTAP_OPT_IRBYPASS:
if (!CMD_ARGC)
return ERROR_COMMAND_ARGUMENT_INVALID;

COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], tap->ir_bypass_value);
CMD_ARGC--;
CMD_ARGV++;
break;

default:
nvp_unknown_command_print(CMD, jtag_newtap_opts, NULL, CMD_ARGV[-1]);
return ERROR_COMMAND_ARGUMENT_INVALID;
Expand Down Expand Up @@ -752,6 +763,7 @@ static const struct command_registration jtag_subcommand_handlers[] = {
"['-ignore-version'] "
"['-ignore-bypass'] "
"['-ircapture' number] "
"['-ir-bypass' number] "
"['-mask' number]",
},
{
Expand Down
2 changes: 2 additions & 0 deletions src/target/adi_v5_dapdirect.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ static const struct command_registration dapdirect_jtag_subcommand_handlers[] =
"['-ignore-version'] "
"['-ignore-bypass'] "
"['-ircapture' number] "
"['-ir-bypass' number] "
"['-mask' number]",
},
{
Expand Down Expand Up @@ -156,6 +157,7 @@ static const struct command_registration dapdirect_swd_subcommand_handlers[] = {
"['-ignore-version'] "
"['-ignore-bypass'] "
"['-ircapture' number] "
"['-ir-bypass' number] "
"['-mask' number]",
},
COMMAND_REGISTRATION_DONE
Expand Down
1 change: 1 addition & 0 deletions src/target/adi_v5_swd.c
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,7 @@ static const struct command_registration swd_commands[] = {
"['-ignore-version'] "
"['-ignore-bypass'] "
"['-ircapture' number] "
"['-ir-bypass' number] "
"['-mask' number]",
},
COMMAND_REGISTRATION_DONE
Expand Down

0 comments on commit 8d3728f

Please sign in to comment.