summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/jtag/jtag.c142
1 files changed, 88 insertions, 54 deletions
diff --git a/src/jtag/jtag.c b/src/jtag/jtag.c
index 56a8075b..ecd4931a 100644
--- a/src/jtag/jtag.c
+++ b/src/jtag/jtag.c
@@ -2651,77 +2651,111 @@ static int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cm
static int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
+ int new_cfg = 0;
+ int mask = 0;
+
if (argc < 1)
return ERROR_COMMAND_SYNTAX_ERROR;
- if (argc >= 1)
- {
- if (strcmp(args[0], "none") == 0)
- jtag_reset_config = RESET_NONE;
- else if (strcmp(args[0], "trst_only") == 0)
- jtag_reset_config = RESET_HAS_TRST;
- else if (strcmp(args[0], "srst_only") == 0)
- jtag_reset_config = RESET_HAS_SRST;
- else if (strcmp(args[0], "trst_and_srst") == 0)
- jtag_reset_config = RESET_TRST_AND_SRST;
+ /* Original versions cared about the order of these tokens:
+ * reset_config signals [combination [trst_type [srst_type]]]
+ * They also clobbered the previous configuration even on error.
+ *
+ * Here we don't care about the order, and only change values
+ * which have been explicitly specified.
+ */
+ for (; argc; argc--, args++) {
+ int tmp = 0;
+ int m;
+
+ /* signals */
+ m = RESET_HAS_TRST | RESET_HAS_SRST;
+ if (strcmp(*args, "none") == 0)
+ tmp = RESET_NONE;
+ else if (strcmp(*args, "trst_only") == 0)
+ tmp = RESET_HAS_TRST;
+ else if (strcmp(*args, "srst_only") == 0)
+ tmp = RESET_HAS_SRST;
+ else if (strcmp(*args, "trst_and_srst") == 0)
+ tmp = RESET_HAS_TRST | RESET_HAS_SRST;
else
- {
- LOG_ERROR("(1) invalid reset_config argument (%s), defaulting to none", args[0]);
- jtag_reset_config = RESET_NONE;
+ m = 0;
+ if (mask & m) {
+ LOG_ERROR("extra reset_config %s spec (%s)",
+ "signal", *args);
return ERROR_INVALID_ARGUMENTS;
}
- }
-
- if (argc >= 2)
- {
- if (strcmp(args[1], "separate") == 0)
- {
- /* seperate reset lines - default */
- } else
- {
- if (strcmp(args[1], "srst_pulls_trst") == 0)
- jtag_reset_config |= RESET_SRST_PULLS_TRST;
- else if (strcmp(args[1], "trst_pulls_srst") == 0)
- jtag_reset_config |= RESET_TRST_PULLS_SRST;
- else if (strcmp(args[1], "combined") == 0)
- jtag_reset_config |= RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST;
- else
- {
- LOG_ERROR("(2) invalid reset_config argument (%s), defaulting to none", args[1]);
- jtag_reset_config = RESET_NONE;
- return ERROR_INVALID_ARGUMENTS;
- }
+ if (m)
+ goto next;
+
+ /* combination (options for broken wiring) */
+ m = RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST;
+ if (strcmp(*args, "separate") == 0)
+ /* separate reset lines - default */;
+ else if (strcmp(*args, "srst_pulls_trst") == 0)
+ tmp |= RESET_SRST_PULLS_TRST;
+ else if (strcmp(*args, "trst_pulls_srst") == 0)
+ tmp |= RESET_TRST_PULLS_SRST;
+ else if (strcmp(*args, "combined") == 0)
+ tmp |= RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST;
+ else
+ m = 0;
+ if (mask & m) {
+ LOG_ERROR("extra reset_config %s spec (%s)",
+ "combination", *args);
+ return ERROR_INVALID_ARGUMENTS;
}
- }
+ if (m)
+ goto next;
- if (argc >= 3)
- {
- if (strcmp(args[2], "trst_open_drain") == 0)
- jtag_reset_config |= RESET_TRST_OPEN_DRAIN;
- else if (strcmp(args[2], "trst_push_pull") == 0)
- jtag_reset_config &= ~RESET_TRST_OPEN_DRAIN;
+ /* trst_type (NOP without HAS_TRST) */
+ m = RESET_TRST_OPEN_DRAIN;
+ if (strcmp(*args, "trst_open_drain") == 0)
+ tmp |= RESET_TRST_OPEN_DRAIN;
+ else if (strcmp(*args, "trst_push_pull") == 0)
+ /* push/pull from adapter - default */;
else
- {
- LOG_ERROR("(3) invalid reset_config argument (%s) defaulting to none", args[2] );
- jtag_reset_config = RESET_NONE;
+ m = 0;
+ if (mask & m) {
+ LOG_ERROR("extra reset_config %s spec (%s)",
+ "trst_type", *args);
return ERROR_INVALID_ARGUMENTS;
}
- }
+ if (m)
+ goto next;
- if (argc >= 4)
- {
- if (strcmp(args[3], "srst_push_pull") == 0)
- jtag_reset_config |= RESET_SRST_PUSH_PULL;
- else if (strcmp(args[3], "srst_open_drain") == 0)
- jtag_reset_config &= ~RESET_SRST_PUSH_PULL;
+ /* srst_type (NOP without HAS_SRST) */
+ m |= RESET_SRST_PUSH_PULL;
+ if (strcmp(*args, "srst_push_pull") == 0)
+ tmp |= RESET_SRST_PUSH_PULL;
+ else if (strcmp(*args, "srst_open_drain") == 0)
+ /* open drain from adapter - default */;
else
- {
- LOG_ERROR("(4) invalid reset_config argument (%s), defaulting to none", args[3]);
- jtag_reset_config = RESET_NONE;
+ m = 0;
+ if (mask & m) {
+ LOG_ERROR("extra reset_config %s spec (%s)",
+ "srst_type", *args);
return ERROR_INVALID_ARGUMENTS;
}
+ if (m)
+ goto next;
+
+ /* caller provided nonsense; fail */
+ LOG_ERROR("unknown reset_config flag (%s)", *args);
+ return ERROR_INVALID_ARGUMENTS;
+
+next:
+ /* Remember the bits which were specified (mask)
+ * and their new values (new_cfg).
+ */
+ mask |= m;
+ new_cfg |= tmp;
}
+ /* clear previous values of those bits, save new values */
+ jtag_reset_config &= ~mask;
+ jtag_reset_config |= new_cfg;
+
return ERROR_OK;
}