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