57c93f2a15977d5a7474e422537e78a69ced99e0
[openocd.git] / src / jtag / aice / aice_transport.c
1 /***************************************************************************
2 * Copyright (C) 2013 by Andes Technology *
3 * Hsiangkai Wang <hkwang@andestech.com> *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 /* project specific includes */
24 #include <jtag/interface.h>
25 #include <jtag/tcl.h>
26 #include <transport/transport.h>
27 #include <target/target.h>
28 #include <jtag/aice/aice_interface.h>
29 #include <jtag/aice/aice_transport.h>
30
31 /* */
32 static int jim_newtap_expected_id(Jim_Nvp *n, Jim_GetOptInfo *goi,
33 struct jtag_tap *pTap)
34 {
35 jim_wide w;
36 int e = Jim_GetOpt_Wide(goi, &w);
37 if (e != JIM_OK) {
38 Jim_SetResultFormatted(goi->interp, "option: %s bad parameter",
39 n->name);
40 return e;
41 }
42
43 unsigned expected_len = sizeof(uint32_t) * pTap->expected_ids_cnt;
44 uint32_t *new_expected_ids = malloc(expected_len + sizeof(uint32_t));
45 if (new_expected_ids == NULL) {
46 Jim_SetResultFormatted(goi->interp, "no memory");
47 return JIM_ERR;
48 }
49
50 memcpy(new_expected_ids, pTap->expected_ids, expected_len);
51
52 new_expected_ids[pTap->expected_ids_cnt] = w;
53
54 free(pTap->expected_ids);
55 pTap->expected_ids = new_expected_ids;
56 pTap->expected_ids_cnt++;
57
58 return JIM_OK;
59 }
60
61 #define NTAP_OPT_EXPECTED_ID 0
62
63 /* */
64 static int jim_aice_newtap_cmd(Jim_GetOptInfo *goi)
65 {
66 struct jtag_tap *pTap;
67 int x;
68 int e;
69 Jim_Nvp *n;
70 char *cp;
71 const Jim_Nvp opts[] = {
72 {.name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID},
73 {.name = NULL, .value = -1},
74 };
75
76 pTap = calloc(1, sizeof(struct jtag_tap));
77 if (!pTap) {
78 Jim_SetResultFormatted(goi->interp, "no memory");
79 return JIM_ERR;
80 }
81
82 /*
83 * we expect CHIP + TAP + OPTIONS
84 * */
85 if (goi->argc < 3) {
86 Jim_SetResultFormatted(goi->interp,
87 "Missing CHIP TAP OPTIONS ....");
88 free(pTap);
89 return JIM_ERR;
90 }
91
92 const char *tmp;
93 Jim_GetOpt_String(goi, &tmp, NULL);
94 pTap->chip = strdup(tmp);
95
96 Jim_GetOpt_String(goi, &tmp, NULL);
97 pTap->tapname = strdup(tmp);
98
99 /* name + dot + name + null */
100 x = strlen(pTap->chip) + 1 + strlen(pTap->tapname) + 1;
101 cp = malloc(x);
102 sprintf(cp, "%s.%s", pTap->chip, pTap->tapname);
103 pTap->dotted_name = cp;
104
105 LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params",
106 pTap->chip, pTap->tapname, pTap->dotted_name, goi->argc);
107
108 while (goi->argc) {
109 e = Jim_GetOpt_Nvp(goi, opts, &n);
110 if (e != JIM_OK) {
111 Jim_GetOpt_NvpUnknown(goi, opts, 0);
112 free(cp);
113 free(pTap);
114 return e;
115 }
116 LOG_DEBUG("Processing option: %s", n->name);
117 switch (n->value) {
118 case NTAP_OPT_EXPECTED_ID:
119 e = jim_newtap_expected_id(n, goi, pTap);
120 if (JIM_OK != e) {
121 free(cp);
122 free(pTap);
123 return e;
124 }
125 break;
126 } /* switch (n->value) */
127 } /* while (goi->argc) */
128
129 /* default is enabled-after-reset */
130 pTap->enabled = !pTap->disabled_after_reset;
131
132 jtag_tap_init(pTap);
133 return JIM_OK;
134 }
135
136 /* */
137 static int jim_aice_newtap(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
138 {
139 Jim_GetOptInfo goi;
140 Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
141 return jim_aice_newtap_cmd(&goi);
142 }
143
144 /* */
145 COMMAND_HANDLER(handle_aice_init_command)
146 {
147 if (CMD_ARGC != 0)
148 return ERROR_COMMAND_SYNTAX_ERROR;
149
150 static bool jtag_initialized;
151 if (jtag_initialized) {
152 LOG_INFO("'jtag init' has already been called");
153 return ERROR_OK;
154 }
155 jtag_initialized = true;
156
157 LOG_DEBUG("Initializing jtag devices...");
158 return jtag_init(CMD_CTX);
159 }
160
161 COMMAND_HANDLER(handle_scan_chain_command)
162 {
163 struct jtag_tap *tap;
164 char expected_id[12];
165
166 aice_scan_jtag_chain();
167 tap = jtag_all_taps();
168 command_print(CMD_CTX,
169 " TapName Enabled IdCode Expected IrLen IrCap IrMask");
170 command_print(CMD_CTX,
171 "-- ------------------- -------- ---------- ---------- ----- ----- ------");
172
173 while (tap) {
174 uint32_t expected, expected_mask, ii;
175
176 snprintf(expected_id, sizeof expected_id, "0x%08x",
177 (unsigned)((tap->expected_ids_cnt > 0)
178 ? tap->expected_ids[0]
179 : 0));
180 if (tap->ignore_version)
181 expected_id[2] = '*';
182
183 expected = buf_get_u32(tap->expected, 0, tap->ir_length);
184 expected_mask = buf_get_u32(tap->expected_mask, 0, tap->ir_length);
185
186 command_print(CMD_CTX,
187 "%2d %-18s %c 0x%08x %s %5d 0x%02x 0x%02x",
188 tap->abs_chain_position,
189 tap->dotted_name,
190 tap->enabled ? 'Y' : 'n',
191 (unsigned int)(tap->idcode),
192 expected_id,
193 (unsigned int)(tap->ir_length),
194 (unsigned int)(expected),
195 (unsigned int)(expected_mask));
196
197 for (ii = 1; ii < tap->expected_ids_cnt; ii++) {
198 snprintf(expected_id, sizeof expected_id, "0x%08x",
199 (unsigned) tap->expected_ids[ii]);
200 if (tap->ignore_version)
201 expected_id[2] = '*';
202
203 command_print(CMD_CTX,
204 " %s",
205 expected_id);
206 }
207
208 tap = tap->next_tap;
209 }
210
211 return ERROR_OK;
212 }
213
214 static int jim_aice_arp_init(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
215 {
216 LOG_DEBUG("No implement: jim_aice_arp_init");
217
218 return JIM_OK;
219 }
220
221 /* */
222 static int aice_init_reset(struct command_context *cmd_ctx)
223 {
224 LOG_DEBUG("Initializing with hard TRST+SRST reset");
225
226 int retval;
227 enum reset_types jtag_reset_config = jtag_get_reset_config();
228
229 jtag_add_reset(1, 0); /* TAP_RESET */
230 if (jtag_reset_config & RESET_HAS_SRST) {
231 jtag_add_reset(1, 1);
232 if ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0)
233 jtag_add_reset(0, 1);
234 }
235 jtag_add_reset(0, 0);
236 retval = jtag_execute_queue();
237 if (retval != ERROR_OK)
238 return retval;
239
240 return ERROR_OK;
241 }
242
243 /* */
244 static int jim_aice_arp_init_reset(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
245 {
246 int e = ERROR_OK;
247 Jim_GetOptInfo goi;
248 Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
249 if (goi.argc != 0) {
250 Jim_WrongNumArgs(goi.interp, 1, goi.argv - 1, "(no params)");
251 return JIM_ERR;
252 }
253 struct command_context *context = current_command_context(interp);
254 e = aice_init_reset(context);
255
256 if (e != ERROR_OK) {
257 Jim_Obj *eObj = Jim_NewIntObj(goi.interp, e);
258 Jim_SetResultFormatted(goi.interp, "error: %#s", eObj);
259 Jim_FreeNewObj(goi.interp, eObj);
260 return JIM_ERR;
261 }
262 return JIM_OK;
263 }
264
265 static int jim_aice_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
266 {
267 Jim_GetOptInfo goi;
268 Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
269 if (goi.argc != 0) {
270 Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
271 return JIM_ERR;
272 }
273 Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0));
274 struct jtag_tap *tap;
275
276 for (tap = jtag_all_taps(); tap; tap = tap->next_tap)
277 Jim_ListAppendElement(goi.interp,
278 Jim_GetResult(goi.interp),
279 Jim_NewStringObj(goi.interp,
280 tap->dotted_name, -1));
281
282 return JIM_OK;
283 }
284
285 /* */
286 static const struct command_registration
287 aice_transport_jtag_subcommand_handlers[] = {
288 {
289 .name = "init",
290 .mode = COMMAND_ANY,
291 .handler = handle_aice_init_command,
292 .help = "initialize jtag scan chain",
293 .usage = ""
294 },
295 {
296 .name = "arp_init",
297 .mode = COMMAND_ANY,
298 .jim_handler = jim_aice_arp_init,
299 .help = "Validates JTAG scan chain against the list of "
300 "declared TAPs.",
301 },
302 {
303 .name = "arp_init-reset",
304 .mode = COMMAND_ANY,
305 .jim_handler = jim_aice_arp_init_reset,
306 .help = "Uses TRST and SRST to try resetting everything on "
307 "the JTAG scan chain, then performs 'jtag arp_init'."
308 },
309 {
310 .name = "newtap",
311 .mode = COMMAND_CONFIG,
312 .jim_handler = jim_aice_newtap,
313 .help = "Create a new TAP instance named basename.tap_type, "
314 "and appends it to the scan chain.",
315 .usage = "basename tap_type ['-expected_id' number]"
316 },
317 {
318 .name = "tapisenabled",
319 .mode = COMMAND_EXEC,
320 .jim_handler = jim_jtag_tap_enabler,
321 .help = "Returns a Tcl boolean (0/1) indicating whether "
322 "the TAP is enabled (1) or not (0).",
323 .usage = "tap_name",
324 },
325 {
326 .name = "tapenable",
327 .mode = COMMAND_EXEC,
328 .jim_handler = jim_jtag_tap_enabler,
329 .help = "Try to enable the specified TAP using the "
330 "'tap-enable' TAP event.",
331 .usage = "tap_name",
332 },
333 {
334 .name = "tapdisable",
335 .mode = COMMAND_EXEC,
336 .jim_handler = jim_jtag_tap_enabler,
337 .help = "Try to disable the specified TAP using the "
338 "'tap-disable' TAP event.",
339 .usage = "tap_name",
340 },
341 {
342 .name = "configure",
343 .mode = COMMAND_EXEC,
344 .jim_handler = jim_jtag_configure,
345 .help = "Provide a Tcl handler for the specified "
346 "TAP event.",
347 .usage = "tap_name '-event' event_name handler",
348 },
349 {
350 .name = "cget",
351 .mode = COMMAND_EXEC,
352 .jim_handler = jim_jtag_configure,
353 .help = "Return any Tcl handler for the specified "
354 "TAP event.",
355 .usage = "tap_name '-event' event_name",
356 },
357 {
358 .name = "names",
359 .mode = COMMAND_ANY,
360 .jim_handler = jim_aice_names,
361 .help = "Returns list of all JTAG tap names.",
362 },
363 {
364 .name = "scan_chain",
365 .handler = handle_scan_chain_command,
366 .mode = COMMAND_ANY,
367 .help = "print current scan chain configuration",
368 .usage = ""
369 },
370
371 COMMAND_REGISTRATION_DONE
372 };
373
374 /* */
375 static const struct command_registration aice_transport_command_handlers[] = {
376 {
377 .name = "jtag",
378 .mode = COMMAND_ANY,
379 .usage = "",
380 .chain = aice_transport_jtag_subcommand_handlers,
381 },
382 COMMAND_REGISTRATION_DONE
383
384 };
385
386 /* */
387 static int aice_transport_register_commands(struct command_context *cmd_ctx)
388 {
389 return register_commands(cmd_ctx, NULL,
390 aice_transport_command_handlers);
391 }
392
393 /* */
394 static int aice_transport_init(struct command_context *cmd_ctx)
395 {
396 LOG_DEBUG("aice_transport_init");
397 struct target *t = get_current_target(cmd_ctx);
398 struct transport *transport;
399
400 if (!t) {
401 LOG_ERROR("no current target");
402 return ERROR_FAIL;
403 }
404
405 transport = get_current_transport();
406
407 if (!transport) {
408 LOG_ERROR("no transport selected");
409 return ERROR_FAIL;
410 }
411
412 LOG_DEBUG("current transport %s", transport->name);
413
414 return aice_init_targets();
415 }
416
417 /* */
418 static int aice_transport_select(struct command_context *ctx)
419 {
420 LOG_DEBUG("aice_transport_select");
421
422 int retval;
423
424 retval = aice_transport_register_commands(ctx);
425
426 if (retval != ERROR_OK)
427 return retval;
428
429 return ERROR_OK;
430 }
431
432 static struct transport aice_jtag_transport = {
433 .name = "aice_jtag",
434 .select = aice_transport_select,
435 .init = aice_transport_init,
436 };
437
438 const char *aice_transports[] = { "aice_jtag", NULL };
439
440 static void aice_constructor(void) __attribute__((constructor));
441 static void aice_constructor(void)
442 {
443 transport_register(&aice_jtag_transport);
444 }
445