tcl.c 40.7 KB
Newer Older
1
2
3
4
/***************************************************************************
 *   Copyright (C) 2005 by Dominic Rath                                    *
 *   Dominic.Rath@gmx.de                                                   *
 *                                                                         *
5
 *   Copyright (C) 2007,2008 Øyvind Harboe                                 *
6
 *   oyvind.harboe@zylin.com                                               *
ntfreak's avatar
ntfreak committed
7
8
 *                                                                         *
 *   Copyright (C) 2009 SoftPLC Corporation                                *
zwelch's avatar
zwelch committed
9
 *       http://softplc.com                                                *
ntfreak's avatar
ntfreak committed
10
 *   dick@softplc.com                                                      *
11
 *                                                                         *
12
13
14
 *   Copyright (C) 2009 Zachary T Welch                                    *
 *   zw@superlucidity.net                                                  *
 *                                                                         *
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "jtag.h"
zwelch's avatar
zwelch committed
35
#include "minidriver.h"
36
#include "interface.h"
37
#include "interfaces.h"
38

39
40
41
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
42

43
static const Jim_Nvp nvp_jtag_tap_event[] = {
44
45
	{ .value = JTAG_TRST_ASSERTED,		.name = "post-reset" },
	{ .value = JTAG_TAP_EVENT_SETUP,	.name = "setup" },
46
47
48
49
50
	{ .value = JTAG_TAP_EVENT_ENABLE,       .name = "tap-enable" },
	{ .value = JTAG_TAP_EVENT_DISABLE,      .name = "tap-disable" },

	{ .name = NULL, .value = -1 }
};
51

52
extern jtag_interface_t *jtag_interface;
53

54
55
56
57
58
/* jtag commands */
static int handle_interface_list_command(struct command_context_s *cmd_ctx,
		char *cmd, char **args, int argc);
static int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_jtag_khz_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
59
static int handle_jtag_rclk_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
60
61
62
static int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
oharboe's avatar
oharboe committed
63
64
static int handle_jtag_nsrst_assert_width_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_jtag_ntrst_assert_width_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
oharboe's avatar
oharboe committed
65

66
static int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
67

68
69
70
71
static int handle_jtag_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_runtest_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
oharboe's avatar
oharboe committed
72
static int Jim_Command_pathmove(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
73
static int Jim_Command_flush_count(Jim_Interp *interp, int argc, Jim_Obj *const *args);
74

75
76
77
static int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_verify_jtag_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_tms_sequence_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
78

79

80
81
82
83
84
85
86
87
88
89
enum jtag_tap_cfg_param {
	JCFG_EVENT
};

static Jim_Nvp nvp_config_opts[] = {
	{ .name = "-event",      .value = JCFG_EVENT },

	{ .name = NULL,          .value = -1 }
};

90
static int jtag_tap_configure_cmd(Jim_GetOptInfo *goi, jtag_tap_t * tap)
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
{
	Jim_Nvp *n;
	Jim_Obj *o;
	int e;

	/* parse config or cget options */
	while (goi->argc > 0) {
		Jim_SetEmptyResult (goi->interp);

		e = Jim_GetOpt_Nvp(goi, nvp_config_opts, &n);
		if (e != JIM_OK) {
			Jim_GetOpt_NvpUnknown(goi, nvp_config_opts, 0);
			return e;
		}

		switch (n->value) {
			case JCFG_EVENT:
				if (goi->argc == 0) {
109
					Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ...");
110
111
112
					return JIM_ERR;
				}

113
				e = Jim_GetOpt_Nvp(goi, nvp_jtag_tap_event, &n);
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
				if (e != JIM_OK) {
					Jim_GetOpt_NvpUnknown(goi, nvp_jtag_tap_event, 1);
					return e;
				}

				if (goi->isconfigure) {
					if (goi->argc != 1) {
						Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?");
						return JIM_ERR;
					}
				} else {
					if (goi->argc != 0) {
						Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name?");
						return JIM_ERR;
					}
				}

				{
					jtag_tap_event_action_t *jteap;

					jteap = tap->event_action;
					/* replace existing? */
					while (jteap) {
zwelch's avatar
zwelch committed
137
						if (jteap->event == (enum jtag_event)n->value) {
138
139
140
141
142
143
							break;
						}
						jteap = jteap->next;
					}

					if (goi->isconfigure) {
144
						bool replace = true;
145
146
147
						if (jteap == NULL) {
							/* create new */
							jteap = calloc(1, sizeof (*jteap));
148
							replace = false;
149
150
						}
						jteap->event = n->value;
151
						Jim_GetOpt_Obj(goi, &o);
152
153
154
155
156
157
						if (jteap->body) {
							Jim_DecrRefCount(interp, jteap->body);
						}
						jteap->body = Jim_DuplicateObj(goi->interp, o);
						Jim_IncrRefCount(jteap->body);

158
159
160
161
162
163
						if (!replace)
						{
							/* add to head of event list */
							jteap->next = tap->event_action;
							tap->event_action = jteap;
						}
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
						Jim_SetEmptyResult(goi->interp);
					} else {
						/* get */
						if (jteap == NULL) {
							Jim_SetEmptyResult(goi->interp);
						} else {
							Jim_SetResult(goi->interp, Jim_DuplicateObj(goi->interp, jteap->body));
						}
					}
				}
				/* loop for more */
				break;
		}
	} /* while (goi->argc) */

	return JIM_OK;
}
181

zwelch's avatar
zwelch committed
182
183
184
185
186
187
188
189
190
static int is_bad_irval(int ir_length, jim_wide w)
{
	jim_wide v = 1;

	v <<= ir_length;
	v -= 1;
	v = ~v;
	return (w & v) != 0;
}
191

192
static int jim_newtap_cmd(Jim_GetOptInfo *goi)
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
{
	jtag_tap_t *pTap;
	jim_wide w;
	int x;
	int e;
	Jim_Nvp *n;
	char *cp;
	const Jim_Nvp opts[] = {
#define NTAP_OPT_IRLEN     0
		{ .name = "-irlen"			,	.value = NTAP_OPT_IRLEN },
#define NTAP_OPT_IRMASK    1
		{ .name = "-irmask"			,	.value = NTAP_OPT_IRMASK },
#define NTAP_OPT_IRCAPTURE 2
		{ .name = "-ircapture"		,	.value = NTAP_OPT_IRCAPTURE },
#define NTAP_OPT_ENABLED   3
208
		{ .name = "-enable"			,	.value = NTAP_OPT_ENABLED },
209
#define NTAP_OPT_DISABLED  4
210
		{ .name = "-disable"		,	.value = NTAP_OPT_DISABLED },
211
#define NTAP_OPT_EXPECTED_ID 5
212
213
		{ .name = "-expected-id"	,	.value = NTAP_OPT_EXPECTED_ID },
		{ .name = NULL				,	.value = -1 },
214
215
	};

zwelch's avatar
zwelch committed
216
217
218
	pTap = calloc(1, sizeof(jtag_tap_t));
	if (!pTap) {
		Jim_SetResult_sprintf(goi->interp, "no memory");
219
220
		return JIM_ERR;
	}
zwelch's avatar
zwelch committed
221

222
223
224
	/*
	 * we expect CHIP + TAP + OPTIONS
	 * */
zwelch's avatar
zwelch committed
225
	if (goi->argc < 3) {
226
		Jim_SetResult_sprintf(goi->interp, "Missing CHIP TAP OPTIONS ....");
227
		free(pTap);
228
229
		return JIM_ERR;
	}
230
	Jim_GetOpt_String(goi, &cp, NULL);
231
232
	pTap->chip = strdup(cp);

233
	Jim_GetOpt_String(goi, &cp, NULL);
234
	pTap->tapname = strdup(cp);
oharboe's avatar
oharboe committed
235

236
	/* name + dot + name + null */
237
	x = strlen(pTap->chip) + 1 + strlen(pTap->tapname) + 1;
238
239
	cp = malloc(x);
	sprintf(cp, "%s.%s", pTap->chip, pTap->tapname);
240
241
	pTap->dotted_name = cp;

oharboe's avatar
oharboe committed
242
	LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params",
243
244
			  pTap->chip, pTap->tapname, pTap->dotted_name, goi->argc);

245
246
247
248
249
250
	/* IEEE specifies that the two LSBs of an IR scan are 01, so make
	 * that the default.  The "-irlen" and "-irmask" options are only
	 * needed to cope with nonstandard TAPs, or to specify more bits.
	 */
	pTap->ir_capture_mask = 0x03;
	pTap->ir_capture_value = 0x01;
251

zwelch's avatar
zwelch committed
252
	while (goi->argc) {
253
		e = Jim_GetOpt_Nvp(goi, opts, &n);
zwelch's avatar
zwelch committed
254
		if (e != JIM_OK) {
255
			Jim_GetOpt_NvpUnknown(goi, opts, 0);
256
257
			free((void *)pTap->dotted_name);
			free(pTap);
258
259
			return e;
		}
260
		LOG_DEBUG("Processing option: %s", n->name);
zwelch's avatar
zwelch committed
261
		switch (n->value) {
262
		case NTAP_OPT_ENABLED:
zwelch's avatar
zwelch committed
263
			pTap->disabled_after_reset = false;
264
265
			break;
		case NTAP_OPT_DISABLED:
zwelch's avatar
zwelch committed
266
			pTap->disabled_after_reset = true;
267
268
			break;
		case NTAP_OPT_EXPECTED_ID:
269
		{
270
			uint32_t *new_expected_ids;
271

272
			e = Jim_GetOpt_Wide(goi, &w);
273
			if (e != JIM_OK) {
274
				Jim_SetResult_sprintf(goi->interp, "option: %s bad parameter", n->name);
275
276
				free((void *)pTap->dotted_name);
				free(pTap);
277
278
279
				return e;
			}

280
			new_expected_ids = malloc(sizeof(uint32_t) * (pTap->expected_ids_cnt + 1));
281
			if (new_expected_ids == NULL) {
282
				Jim_SetResult_sprintf(goi->interp, "no memory");
283
284
				free((void *)pTap->dotted_name);
				free(pTap);
285
286
287
				return JIM_ERR;
			}

288
			memcpy(new_expected_ids, pTap->expected_ids, sizeof(uint32_t) * pTap->expected_ids_cnt);
289
290

			new_expected_ids[pTap->expected_ids_cnt] = w;
291
292

			free(pTap->expected_ids);
293
294
			pTap->expected_ids = new_expected_ids;
			pTap->expected_ids_cnt++;
295
			break;
296
		}
297
298
299
		case NTAP_OPT_IRLEN:
		case NTAP_OPT_IRMASK:
		case NTAP_OPT_IRCAPTURE:
300
			e = Jim_GetOpt_Wide(goi, &w);
zwelch's avatar
zwelch committed
301
			if (e != JIM_OK) {
302
				Jim_SetResult_sprintf(goi->interp, "option: %s bad parameter", n->name);
303
304
				free((void *)pTap->dotted_name);
				free(pTap);
305
306
				return e;
			}
zwelch's avatar
zwelch committed
307
			switch (n->value) {
308
			case NTAP_OPT_IRLEN:
zwelch's avatar
zwelch committed
309
				if (w > (jim_wide) (8 * sizeof(pTap->ir_capture_value)))
310
311
312
					LOG_WARNING("%s: huge IR length %d",
							pTap->dotted_name,
							(int) w);
313
314
315
				pTap->ir_length = w;
				break;
			case NTAP_OPT_IRMASK:
zwelch's avatar
zwelch committed
316
				if (is_bad_irval(pTap->ir_length, w)) {
317
318
					LOG_ERROR("%s: IR mask %x too big",
							pTap->dotted_name,
zwelch's avatar
zwelch committed
319
							(int) w);
320
321
					free((void *)pTap->dotted_name);
					free(pTap);
zwelch's avatar
zwelch committed
322
323
					return ERROR_FAIL;
				}
324
325
326
				if ((w & 3) != 3)
					LOG_WARNING("%s: nonstandard IR mask",
							pTap->dotted_name);
327
328
329
				pTap->ir_capture_mask = w;
				break;
			case NTAP_OPT_IRCAPTURE:
zwelch's avatar
zwelch committed
330
				if (is_bad_irval(pTap->ir_length, w)) {
331
332
					LOG_ERROR("%s: IR capture %x too big",
							pTap->dotted_name,
zwelch's avatar
zwelch committed
333
							(int) w);
334
335
					free((void *)pTap->dotted_name);
					free(pTap);
zwelch's avatar
zwelch committed
336
337
					return ERROR_FAIL;
				}
338
339
340
				if ((w & 3) != 1)
					LOG_WARNING("%s: nonstandard IR value",
							pTap->dotted_name);
341
342
343
				pTap->ir_capture_value = w;
				break;
			}
zwelch's avatar
zwelch committed
344
		} /* switch (n->value) */
345
	} /* while (goi->argc) */
346

zwelch's avatar
zwelch committed
347
348
349
	/* default is enabled-after-reset */
	pTap->enabled = !pTap->disabled_after_reset;

350
	/* Did all the required option bits get cleared? */
351
	if (pTap->ir_length != 0)
352
353
354
	{
		jtag_tap_init(pTap);
		return ERROR_OK;
355
356
	}

357
	Jim_SetResult_sprintf(goi->interp,
358
			"newtap: %s missing IR length",
359
			pTap->dotted_name);
360
	jtag_tap_free(pTap);
361
362
	return JIM_ERR;
}
363

zwelch's avatar
zwelch committed
364
static void jtag_tap_handle_event(jtag_tap_t *tap, enum jtag_event e)
365
366
367
{
	jtag_tap_event_action_t * jteap;

dbrownell's avatar
dbrownell committed
368
	for (jteap = tap->event_action; jteap != NULL; jteap = jteap->next) {
369
		if (jteap->event == e) {
370
			LOG_DEBUG("JTAG tap: %s event: %d (%s)\n\taction: %s",
371
372
373
					tap->dotted_name,
					e,
					Jim_Nvp_value2name_simple(nvp_jtag_tap_event, e)->name,
374
					Jim_GetString(jteap->body, NULL));
375
376
			if (Jim_EvalObj(interp, jteap->body) != JIM_OK) {
				Jim_PrintErrorMessage(interp);
377
378
379
			} else switch (e) {
			case JTAG_TAP_EVENT_ENABLE:
			case JTAG_TAP_EVENT_DISABLE:
zwelch's avatar
zwelch committed
380
				/* NOTE:  we currently assume the handlers
381
382
				 * can't fail.  Right here is where we should
				 * really be verifying the scan chains ...
zwelch's avatar
zwelch committed
383
				 */
384
				tap->enabled = (e == JTAG_TAP_EVENT_ENABLE);
385
386
				LOG_INFO("JTAG tap: %s %s", tap->dotted_name,
					tap->enabled ? "enabled" : "disabled");
387
388
389
				break;
			default:
				break;
390
391
392
393
394
395
			}
		}
	}
}


396
static int jim_jtag_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
397
398
399
400
{
	Jim_GetOptInfo goi;
	int e;
	Jim_Nvp *n;
401
	Jim_Obj *o;
402
403
404
405
	struct command_context_s *context;

	enum {
		JTAG_CMD_INTERFACE,
406
		JTAG_CMD_INIT,
407
		JTAG_CMD_INIT_RESET,
408
409
410
		JTAG_CMD_NEWTAP,
		JTAG_CMD_TAPENABLE,
		JTAG_CMD_TAPDISABLE,
411
412
		JTAG_CMD_TAPISENABLED,
		JTAG_CMD_CONFIGURE,
zwelch's avatar
zwelch committed
413
414
		JTAG_CMD_CGET,
		JTAG_CMD_NAMES,
415
	};
416

417
418
	const Jim_Nvp jtag_cmds[] = {
		{ .name = "interface"     , .value = JTAG_CMD_INTERFACE },
419
		{ .name = "arp_init"      , .value = JTAG_CMD_INIT },
420
		{ .name = "arp_init-reset", .value = JTAG_CMD_INIT_RESET },
421
422
423
424
		{ .name = "newtap"        , .value = JTAG_CMD_NEWTAP },
		{ .name = "tapisenabled"     , .value = JTAG_CMD_TAPISENABLED },
		{ .name = "tapenable"     , .value = JTAG_CMD_TAPENABLE },
		{ .name = "tapdisable"    , .value = JTAG_CMD_TAPDISABLE },
425
426
		{ .name = "configure"     , .value = JTAG_CMD_CONFIGURE },
		{ .name = "cget"          , .value = JTAG_CMD_CGET },
zwelch's avatar
zwelch committed
427
		{ .name = "names"         , .value = JTAG_CMD_NAMES },
428

429
430
431
432
		{ .name = NULL, .value = -1 },
	};

	context = Jim_GetAssocData(interp, "context");
433
	/* go past the command */
434
	Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1);
435

436
	e = Jim_GetOpt_Nvp(&goi, jtag_cmds, &n);
zwelch's avatar
zwelch committed
437
	if (e != JIM_OK) {
438
		Jim_GetOpt_NvpUnknown(&goi, jtag_cmds, 0);
439
440
		return e;
	}
441
		Jim_SetEmptyResult(goi.interp);
zwelch's avatar
zwelch committed
442
	switch (n->value) {
443
	case JTAG_CMD_INTERFACE:
444
445
446
		/* return the name of the interface */
		/* TCL code might need to know the exact type... */
		/* FUTURE: we allow this as a means to "set" the interface. */
zwelch's avatar
zwelch committed
447
		if (goi.argc != 0) {
448
			Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
449
450
			return JIM_ERR;
		}
451
		Jim_SetResultString(goi.interp, jtag_interface->name, -1);
452
		return JIM_OK;
453
454
455
456
457
458
459
460
461
462
463
	case JTAG_CMD_INIT:
		if (goi.argc != 0) {
			Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
			return JIM_ERR;
		}
		e = jtag_init_inner(context);
		if (e != ERROR_OK) {
			Jim_SetResult_sprintf(goi.interp, "error: %d", e);
			return JIM_ERR;
		}
		return JIM_OK;
464
	case JTAG_CMD_INIT_RESET:
zwelch's avatar
zwelch committed
465
		if (goi.argc != 0) {
466
			Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
467
468
469
			return JIM_ERR;
		}
		e = jtag_init_reset(context);
zwelch's avatar
zwelch committed
470
		if (e != ERROR_OK) {
471
			Jim_SetResult_sprintf(goi.interp, "error: %d", e);
472
473
474
			return JIM_ERR;
		}
		return JIM_OK;
475
	case JTAG_CMD_NEWTAP:
476
		return jim_newtap_cmd(&goi);
477
478
479
480
		break;
	case JTAG_CMD_TAPISENABLED:
	case JTAG_CMD_TAPENABLE:
	case JTAG_CMD_TAPDISABLE:
zwelch's avatar
zwelch committed
481
		if (goi.argc != 1) {
482
			Jim_SetResultString(goi.interp, "Too many parameters",-1);
483
484
			return JIM_ERR;
		}
oharboe's avatar
oharboe committed
485
486

		{
487
			jtag_tap_t *t;
zwelch's avatar
zwelch committed
488
489
490

			t = jtag_tap_by_jim_obj(goi.interp, goi.argv[0]);
			if (t == NULL)
491
				return JIM_ERR;
zwelch's avatar
zwelch committed
492
493

			switch (n->value) {
494
495
496
			case JTAG_CMD_TAPISENABLED:
				break;
			case JTAG_CMD_TAPENABLE:
zwelch's avatar
zwelch committed
497
498
499
500
501
502
503
504
505
506
				if (t->enabled)
					break;
				jtag_tap_handle_event(t, JTAG_TAP_EVENT_ENABLE);
				if (!t->enabled)
					break;

				/* FIXME add JTAG sanity checks, w/o TLR
				 *  - scan chain length grew by one (this)
				 *  - IDs and IR lengths are as expected
				 */
zwelch's avatar
zwelch committed
507
508

				jtag_call_event_callbacks(JTAG_TAP_EVENT_ENABLE);
509
510
				break;
			case JTAG_CMD_TAPDISABLE:
zwelch's avatar
zwelch committed
511
512
513
514
515
516
517
518
519
520
				if (!t->enabled)
					break;
				jtag_tap_handle_event(t, JTAG_TAP_EVENT_DISABLE);
				if (t->enabled)
					break;

				/* FIXME add JTAG sanity checks, w/o TLR
				 *  - scan chain length shrank by one (this)
				 *  - IDs and IR lengths are as expected
				 */
zwelch's avatar
zwelch committed
521
522

				jtag_call_event_callbacks(JTAG_TAP_EVENT_DISABLE);
523
524
				break;
			}
zwelch's avatar
zwelch committed
525
526
			e = t->enabled;
			Jim_SetResult(goi.interp, Jim_NewIntObj(goi.interp, e));
527
528
			return JIM_OK;
		}
529
530
531
		break;

	case JTAG_CMD_CGET:
zwelch's avatar
zwelch committed
532
		if (goi.argc < 2) {
zwelch's avatar
zwelch committed
533
534
			Jim_WrongNumArgs(goi.interp, 0, NULL,
					"cget tap_name queryparm");
535
536
537
538
539
540
541
			return JIM_ERR;
		}

		{
			jtag_tap_t *t;

			Jim_GetOpt_Obj(&goi, &o);
542
			t = jtag_tap_by_jim_obj(goi.interp, o);
zwelch's avatar
zwelch committed
543
			if (t == NULL) {
544
545
546
547
				return JIM_ERR;
			}

			goi.isconfigure = 0;
548
			return jtag_tap_configure_cmd(&goi, t);
549
550
551
552
		}
		break;

	case JTAG_CMD_CONFIGURE:
zwelch's avatar
zwelch committed
553
		if (goi.argc < 3) {
zwelch's avatar
zwelch committed
554
555
			Jim_WrongNumArgs(goi.interp, 0, NULL,
					"configure tap_name attribute value ...");
556
557
558
559
560
561
562
			return JIM_ERR;
		}

		{
			jtag_tap_t *t;

			Jim_GetOpt_Obj(&goi, &o);
563
			t = jtag_tap_by_jim_obj(goi.interp, o);
zwelch's avatar
zwelch committed
564
			if (t == NULL) {
565
566
567
568
				return JIM_ERR;
			}

			goi.isconfigure = 1;
569
			return jtag_tap_configure_cmd(&goi, t);
570
		}
zwelch's avatar
zwelch committed
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
		break;

	case JTAG_CMD_NAMES:
		if (goi.argc != 0) {
			Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
			return JIM_ERR;
		}
		Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0));
		{
			jtag_tap_t *tap;

			for (tap = jtag_all_taps(); tap; tap = tap->next_tap) {
				Jim_ListAppendElement(goi.interp,
					Jim_GetResult(goi.interp),
					Jim_NewStringObj(goi.interp,
						tap->dotted_name, -1));
			}
			return JIM_OK;
		}
		break;

592
	}
593

594
595
596
	return JIM_ERR;
}

597

598
void jtag_notify_event(enum jtag_event event)
599
600
{
	jtag_tap_t *tap;
601

602
	for (tap = jtag_all_taps(); tap; tap = tap->next_tap)
603
		jtag_tap_handle_event(tap, event);
604
605
606
}


607
608
int jtag_register_commands(struct command_context_s *cmd_ctx)
{
609
	register_jim(cmd_ctx, "jtag", jim_jtag_command, "perform jtag tap actions");
610

611
	register_command(cmd_ctx, NULL, "interface", handle_interface_command,
oharboe's avatar
oharboe committed
612
		COMMAND_CONFIG, "try to configure interface");
613
614
615
	register_command(cmd_ctx, NULL,
		"interface_list", &handle_interface_list_command,
		COMMAND_ANY, "list all built-in interfaces");
616
	register_command(cmd_ctx, NULL, "jtag_khz", handle_jtag_khz_command,
zwelch's avatar
zwelch committed
617
618
		COMMAND_ANY, "set maximum jtag speed (if supported); "
		"parameter is maximum khz, or 0 for adaptive clocking (RTCK).");
619
620
	register_command(cmd_ctx, NULL, "jtag_rclk", handle_jtag_rclk_command,
		COMMAND_ANY, "fallback_speed_khz - set JTAG speed to RCLK or use fallback speed");
621
	register_command(cmd_ctx, NULL, "reset_config", handle_reset_config_command,
622
		COMMAND_ANY,
dbrownell's avatar
dbrownell committed
623
624
625
626
627
628
		"reset_config "
		"[none|trst_only|srst_only|trst_and_srst] "
		"[srst_pulls_trst|trst_pulls_srst|combined|separate] "
		"[srst_gates_jtag|srst_nogate] "
		"[trst_push_pull|trst_open_drain] "
		"[srst_push_pull|srst_open_drain]");
629
	register_command(cmd_ctx, NULL, "jtag_nsrst_delay", handle_jtag_nsrst_delay_command,
630
		COMMAND_ANY, "jtag_nsrst_delay <ms> - delay after deasserting srst in ms");
631
	register_command(cmd_ctx, NULL, "jtag_ntrst_delay", handle_jtag_ntrst_delay_command,
632
		COMMAND_ANY, "jtag_ntrst_delay <ms> - delay after deasserting trst in ms");
oharboe's avatar
oharboe committed
633
634
635
636
	register_command(cmd_ctx, NULL, "jtag_nsrst_assert_width", handle_jtag_nsrst_assert_width_command,
		COMMAND_ANY, "jtag_nsrst_assert_width <ms> - delay after asserting srst in ms");
	register_command(cmd_ctx, NULL, "jtag_ntrst_assert_width", handle_jtag_ntrst_assert_width_command,
		COMMAND_ANY, "jtag_ntrst_assert_width <ms> - delay after asserting trst in ms");
637

638
639
640
641
642
643
644
645
646
	register_command(cmd_ctx, NULL, "scan_chain", handle_scan_chain_command,
		COMMAND_EXEC, "print current scan chain configuration");

	register_command(cmd_ctx, NULL, "jtag_reset", handle_jtag_reset_command,
		COMMAND_EXEC, "toggle reset lines <trst> <srst>");
	register_command(cmd_ctx, NULL, "runtest", handle_runtest_command,
		COMMAND_EXEC, "move to Run-Test/Idle, and execute <num_cycles>");
	register_command(cmd_ctx, NULL, "irscan", handle_irscan_command,
		COMMAND_EXEC, "execute IR scan <device> <instr> [dev2] [instr2] ...");
647
	register_jim(cmd_ctx, "drscan", Jim_Command_drscan, "execute DR scan <device> <num_bits> <value> <num_bits1> <value2> ...");
648
	register_jim(cmd_ctx, "flush_count", Jim_Command_flush_count, "returns number of times the JTAG queue has been flushed");
oharboe's avatar
oharboe committed
649
	register_jim(cmd_ctx, "pathmove", Jim_Command_pathmove, "move JTAG to state1 then to state2, state3, etc. <state1>,<state2>,<stat3>...");
650
651

	register_command(cmd_ctx, NULL, "verify_ircapture", handle_verify_ircapture_command,
zwelch's avatar
zwelch committed
652
		COMMAND_ANY, "verify value captured during Capture-IR <enable | disable>");
oharboe's avatar
oharboe committed
653
	register_command(cmd_ctx, NULL, "verify_jtag", handle_verify_jtag_command,
zwelch's avatar
zwelch committed
654
		COMMAND_ANY, "verify value capture <enable | disable>");
655
	register_command(cmd_ctx, NULL, "tms_sequence", handle_tms_sequence_command,
zwelch's avatar
zwelch committed
656
		COMMAND_ANY, "choose short(default) or long tms_sequence <short | long>");
657
658
659
	return ERROR_OK;
}

660
661
static int default_khz(int khz, int *jtag_speed)
{
662
	LOG_ERROR("Translation from khz to jtag_speed not implemented");
663
664
665
	return ERROR_FAIL;
}

oharboe's avatar
oharboe committed
666
static int default_speed_div(int speed, int *khz)
667
{
668
	LOG_ERROR("Translation from jtag_speed to khz not implemented");
669
670
671
672
673
	return ERROR_FAIL;
}

static int default_power_dropout(int *dropout)
{
zwelch's avatar
zwelch committed
674
	*dropout = 0; /* by default we can't detect power dropout */
675
676
677
678
679
	return ERROR_OK;
}

static int default_srst_asserted(int *srst_asserted)
{
zwelch's avatar
zwelch committed
680
	*srst_asserted = 0; /* by default we can't detect srst asserted */
681
	return ERROR_OK;
682
683
}

684
685
static int handle_interface_command(struct command_context_s *cmd_ctx,
		char *cmd, char **args, int argc)
686
687
688
689
{
	/* check whether the interface is already configured */
	if (jtag_interface)
	{
690
		LOG_WARNING("Interface already configured, ignoring");
691
692
693
694
		return ERROR_OK;
	}

	/* interface name is a mandatory argument */
695
	if (argc != 1 || args[0][0] == '\0')
696
697
		return ERROR_COMMAND_SYNTAX_ERROR;

698
	for (unsigned i = 0; NULL != jtag_interfaces[i]; i++)
699
	{
700
701
702
703
704
		if (strcmp(args[0], jtag_interfaces[i]->name) != 0)
			continue;

		int retval = jtag_interfaces[i]->register_commands(cmd_ctx);
		if (ERROR_OK != retval)
705
				return retval;
706

707
		jtag_interface = jtag_interfaces[i];
708

709
710
711
712
713
714
715
716
		if (jtag_interface->khz == NULL)
			jtag_interface->khz = default_khz;
		if (jtag_interface->speed_div == NULL)
			jtag_interface->speed_div = default_speed_div;
		if (jtag_interface->power_dropout == NULL)
			jtag_interface->power_dropout = default_power_dropout;
		if (jtag_interface->srst_asserted == NULL)
			jtag_interface->srst_asserted = default_srst_asserted;
717

718
		return ERROR_OK;
719
720
721
722
723
	}

	/* no valid interface was found (i.e. the configuration option,
	 * didn't match one of the compiled-in interfaces
	 */
724
	LOG_ERROR("The specified JTAG interface was not found (%s)", args[0]);
725
726
727
728
729
730
731
732
733
734
735
	handle_interface_list_command(cmd_ctx, cmd, args, argc);
	return ERROR_JTAG_INVALID_INTERFACE;
}

static int handle_interface_list_command(struct command_context_s *cmd_ctx,
		char *cmd, char **args, int argc)
{
	if (strcmp(cmd, "interface_list") == 0 && argc > 0)
		return ERROR_COMMAND_SYNTAX_ERROR;

	command_print(cmd_ctx, "The following JTAG interfaces are available:");
736
	for (unsigned i = 0; NULL != jtag_interfaces[i]; i++)
737
738
739
740
	{
		const char *name = jtag_interfaces[i]->name;
		command_print(cmd_ctx, "%u: %s", i + 1, name);
	}
741

742
	return ERROR_OK;
743
744
}

745
static int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
746
{
747
	jtag_tap_t *tap;
748

749
	tap = jtag_all_taps();
750
751
752
	command_print(cmd_ctx, "     TapName            | Enabled |   IdCode      Expected    IrLen IrCap  IrMask Instr     ");
	command_print(cmd_ctx, "---|--------------------|---------|------------|------------|------|------|------|---------");

zwelch's avatar
zwelch committed
753
	while (tap) {
754
		uint32_t expected, expected_mask, cur_instr, ii;
755
756
757
		expected = buf_get_u32(tap->expected, 0, tap->ir_length);
		expected_mask = buf_get_u32(tap->expected_mask, 0, tap->ir_length);
		cur_instr = buf_get_u32(tap->cur_instr, 0, tap->ir_length);
758

759
760
761
762
763
		command_print(cmd_ctx,
					  "%2d | %-18s |    %c    | 0x%08x | 0x%08x | 0x%02x | 0x%02x | 0x%02x | 0x%02x",
					  tap->abs_chain_position,
					  tap->dotted_name,
					  tap->enabled ? 'Y' : 'n',
764
765
766
767
768
769
					  (unsigned int)(tap->idcode),
					  (unsigned int)(tap->expected_ids_cnt > 0 ? tap->expected_ids[0] : 0),
					  (unsigned int)(tap->ir_length),
					  (unsigned int)(expected),
					  (unsigned int)(expected_mask),
					  (unsigned int)(cur_instr));
770
771
772

		for (ii = 1; ii < tap->expected_ids_cnt; ii++) {
			command_print(cmd_ctx, "   |                    |         |            | 0x%08x |      |      |      |         ",
773
						  (unsigned int)(tap->expected_ids[ii]));
774
775
		}

776
		tap = tap->next_tap;
777
778
779
780
781
	}

	return ERROR_OK;
}

782
static int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
783
{
zwelch's avatar
zwelch committed
784
785
786
787
788
789
790
791
792
793
794
795
796
797
	int new_cfg = 0;
	int mask = 0;

	/* 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;

dbrownell's avatar
dbrownell committed
798
799
		/* gating */
		m = RESET_SRST_NO_GATING;
800
		if (strcmp(*args, "srst_gates_jtag") == 0)
dbrownell's avatar
dbrownell committed
801
802
803
804
805
806
807
808
809
			/* default: don't use JTAG while SRST asserted */;
		else if (strcmp(*args, "srst_nogate") == 0)
			tmp = RESET_SRST_NO_GATING;
		else
			m = 0;
		if (mask & m) {
			LOG_ERROR("extra reset_config %s spec (%s)",
					"gating", *args);
			return ERROR_INVALID_ARGUMENTS;
810
		}
dbrownell's avatar
dbrownell committed
811
812
		if (m)
			goto next;
813

zwelch's avatar
zwelch committed
814
815
816
817
818
819
820
821
822
823
		/* 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;
824
		else
zwelch's avatar
zwelch committed
825
826
827
828
			m = 0;
		if (mask & m) {
			LOG_ERROR("extra reset_config %s spec (%s)",
					"signal", *args);
829
830
			return ERROR_INVALID_ARGUMENTS;
		}
zwelch's avatar
zwelch committed
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
		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;
850
		}
zwelch's avatar
zwelch committed
851
852
853
854
855
856
857
858
859
		if (m)
			goto next;

		/* 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 */;
860
		else
zwelch's avatar
zwelch committed
861
862
863
864
			m = 0;
		if (mask & m) {
			LOG_ERROR("extra reset_config %s spec (%s)",
					"trst_type", *args);
865
866
			return ERROR_INVALID_ARGUMENTS;
		}
zwelch's avatar
zwelch committed
867
868
869
870
871
872
873
874
875
		if (m)
			goto next;

		/* 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 */;
876
		else
zwelch's avatar
zwelch committed
877
878
879
880
			m = 0;
		if (mask & m) {
			LOG_ERROR("extra reset_config %s spec (%s)",
					"srst_type", *args);
881
882
			return ERROR_INVALID_ARGUMENTS;
		}
zwelch's avatar
zwelch committed
883
884
885
886
887
888
889
890
891
892
893
894
895
		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;
896
	}
897

zwelch's avatar
zwelch committed
898
	/* clear previous values of those bits, save new values */
dbrownell's avatar
dbrownell committed
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
	if (mask) {
		int old_cfg = jtag_get_reset_config();

		old_cfg &= ~mask;
		new_cfg |= old_cfg;
		jtag_set_reset_config(new_cfg);
	} else
		new_cfg = jtag_get_reset_config();


	/*
	 * Display the (now-)current reset mode
	 */
	char *modes[5];

	/* minimal JTAG has neither SRST nor TRST (so that's the default) */
	switch (new_cfg & (RESET_HAS_TRST | RESET_HAS_SRST)) {
	case RESET_HAS_SRST:
		modes[0] = "srst_only";
		break;
	case RESET_HAS_TRST:
		modes[0] = "trst_only";
		break;
	case RESET_TRST_AND_SRST:
		modes[0] = "trst_and_srst";
		break;
	default:
		modes[0] = "none";
		break;
	}

	/* normally SRST and TRST are decoupled; but bugs happen ... */
	switch (new_cfg & (RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST)) {
	case RESET_SRST_PULLS_TRST:
		modes[1] = "srst_pulls_trst";
		break;
	case RESET_TRST_PULLS_SRST:
		modes[1] = "trst_pulls_srst";
		break;
	case RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST:
		modes[1] = "combined";
		break;
	default:
		modes[1] = "separate";
		break;
	}

	/* TRST-less connectors include Altera, Xilinx, and minimal JTAG */
	if (new_cfg & RESET_HAS_TRST) {
		if (new_cfg & RESET_TRST_OPEN_DRAIN)
			modes[3] = " trst_open_drain";
		else
			modes[3] = " trst_push_pull";
	} else
		modes[3] = "";

	/* SRST-less connectors include TI-14, Xilinx, and minimal JTAG */
	if (new_cfg & RESET_HAS_SRST) {
		if (new_cfg & RESET_SRST_NO_GATING)
			modes[2] = " srst_nogate";
		else
			modes[2] = " srst_gates_jtag";

		if (new_cfg & RESET_SRST_PUSH_PULL)
			modes[4] = " srst_push_pull";
		else
			modes[4] = " srst_open_drain";
	} else {
		modes[2] = "";
		modes[4] = "";
	}

	command_print(cmd_ctx, "%s %s%s%s%s",
			modes[0], modes[1],
			modes[2], modes[3], modes[4]);
zwelch's avatar
zwelch committed
974

975
976
977
	return ERROR_OK;
}

978
979
static int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx,
		char *cmd, char **args, int argc)
980
{
981
	if (argc > 1)
982
		return ERROR_COMMAND_SYNTAX_ERROR;
983
	if (argc == 1)
984
985
	{
		unsigned delay;
986
987
		COMMAND_PARSE_NUMBER(uint, args[0], delay);

988
989
		jtag_set_nsrst_delay(delay);
	}
990
	command_print(cmd_ctx, "jtag_nsrst_delay: %u", jtag_get_nsrst_delay());
991
992
993
	return ERROR_OK;
}

994
995
static int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx,
		char *cmd, char **args, int argc)
996
{
997
	if (argc > 1)
998
		return ERROR_COMMAND_SYNTAX_ERROR;
999
	if (argc == 1)
1000
	{