tcl/target/ti_k3: Rename m4 target as general purpose mcu
[fw/openocd] / 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 #include <string.h>
31
32 /* */
33 static int jim_newtap_expected_id(struct jim_nvp *n, struct jim_getopt_info *goi,
34                 struct jtag_tap *tap)
35 {
36         jim_wide w;
37         int e = jim_getopt_wide(goi, &w);
38         if (e != JIM_OK) {
39                 Jim_SetResultFormatted(goi->interp, "option: %s bad parameter",
40                                 n->name);
41                 return e;
42         }
43
44         unsigned expected_len = sizeof(uint32_t) * tap->expected_ids_cnt;
45         uint32_t *new_expected_ids = malloc(expected_len + sizeof(uint32_t));
46         if (!new_expected_ids) {
47                 Jim_SetResultFormatted(goi->interp, "no memory");
48                 return JIM_ERR;
49         }
50
51         assert(tap->expected_ids);
52         memcpy(new_expected_ids, tap->expected_ids, expected_len);
53
54         new_expected_ids[tap->expected_ids_cnt] = w;
55
56         free(tap->expected_ids);
57         tap->expected_ids = new_expected_ids;
58         tap->expected_ids_cnt++;
59
60         return JIM_OK;
61 }
62
63 #define NTAP_OPT_EXPECTED_ID 0
64
65 /* */
66 static int jim_aice_newtap_cmd(struct jim_getopt_info *goi)
67 {
68         struct jtag_tap *tap;
69         int x;
70         int e;
71         struct jim_nvp *n;
72         char *cp;
73         const struct jim_nvp opts[] = {
74                 {.name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID},
75                 {.name = NULL, .value = -1},
76         };
77
78         tap = calloc(1, sizeof(struct jtag_tap));
79         if (!tap) {
80                 Jim_SetResultFormatted(goi->interp, "no memory");
81                 return JIM_ERR;
82         }
83
84         /*
85          * we expect CHIP + TAP + OPTIONS
86          * */
87         if (goi->argc < 3) {
88                 Jim_SetResultFormatted(goi->interp,
89                                 "Missing CHIP TAP OPTIONS ....");
90                 free(tap);
91                 return JIM_ERR;
92         }
93
94         const char *tmp;
95         jim_getopt_string(goi, &tmp, NULL);
96         tap->chip = strdup(tmp);
97
98         jim_getopt_string(goi, &tmp, NULL);
99         tap->tapname = strdup(tmp);
100
101         /* name + dot + name + null */
102         x = strlen(tap->chip) + 1 + strlen(tap->tapname) + 1;
103         cp = malloc(x);
104         sprintf(cp, "%s.%s", tap->chip, tap->tapname);
105         tap->dotted_name = cp;
106
107         LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params",
108                         tap->chip, tap->tapname, tap->dotted_name, goi->argc);
109
110         while (goi->argc) {
111                 e = jim_getopt_nvp(goi, opts, &n);
112                 if (e != JIM_OK) {
113                         jim_getopt_nvp_unknown(goi, opts, 0);
114                         free(cp);
115                         free(tap);
116                         return e;
117                 }
118                 LOG_DEBUG("Processing option: %s", n->name);
119                 switch (n->value) {
120                         case NTAP_OPT_EXPECTED_ID:
121                                 e = jim_newtap_expected_id(n, goi, tap);
122                                 if (e != JIM_OK) {
123                                         free(cp);
124                                         free(tap);
125                                         return e;
126                                 }
127                                 break;
128                 }               /* switch (n->value) */
129         }                       /* while (goi->argc) */
130
131         /* default is enabled-after-reset */
132         tap->enabled = !tap->disabled_after_reset;
133
134         jtag_tap_init(tap);
135         return JIM_OK;
136 }
137
138 /* */
139 static int jim_aice_newtap(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
140 {
141         struct jim_getopt_info goi;
142         jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
143         return jim_aice_newtap_cmd(&goi);
144 }
145
146 /* */
147 COMMAND_HANDLER(handle_aice_init_command)
148 {
149         if (CMD_ARGC != 0)
150                 return ERROR_COMMAND_SYNTAX_ERROR;
151
152         static bool jtag_initialized;
153         if (jtag_initialized) {
154                 LOG_INFO("'jtag init' has already been called");
155                 return ERROR_OK;
156         }
157         jtag_initialized = true;
158
159         LOG_DEBUG("Initializing jtag devices...");
160         return jtag_init(CMD_CTX);
161 }
162
163 COMMAND_HANDLER(handle_scan_chain_command)
164 {
165         struct jtag_tap *tap;
166         char expected_id[12];
167
168         aice_scan_jtag_chain();
169         tap = jtag_all_taps();
170         command_print(CMD,
171                 "   TapName             Enabled  IdCode     Expected   IrLen IrCap IrMask");
172         command_print(CMD,
173                 "-- ------------------- -------- ---------- ---------- ----- ----- ------");
174
175         while (tap) {
176                 uint32_t expected, expected_mask, ii;
177
178                 snprintf(expected_id, sizeof(expected_id), "0x%08x",
179                         (unsigned)((tap->expected_ids_cnt > 0)
180                                    ? tap->expected_ids[0]
181                                    : 0));
182                 if (tap->ignore_version)
183                         expected_id[2] = '*';
184
185                 expected = buf_get_u32(tap->expected, 0, tap->ir_length);
186                 expected_mask = buf_get_u32(tap->expected_mask, 0, tap->ir_length);
187
188                 command_print(CMD,
189                         "%2d %-18s     %c     0x%08x %s %5d 0x%02x  0x%02x",
190                         tap->abs_chain_position,
191                         tap->dotted_name,
192                         tap->enabled ? 'Y' : 'n',
193                         (unsigned int)(tap->idcode),
194                         expected_id,
195                         (unsigned int)(tap->ir_length),
196                         (unsigned int)(expected),
197                         (unsigned int)(expected_mask));
198
199                 for (ii = 1; ii < tap->expected_ids_cnt; ii++) {
200                         snprintf(expected_id, sizeof(expected_id), "0x%08x",
201                                 (unsigned) tap->expected_ids[ii]);
202                         if (tap->ignore_version)
203                                 expected_id[2] = '*';
204
205                         command_print(CMD,
206                                 "                                           %s",
207                                 expected_id);
208                 }
209
210                 tap = tap->next_tap;
211         }
212
213         return ERROR_OK;
214 }
215
216 static int jim_aice_arp_init(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
217 {
218         LOG_DEBUG("No implement: jim_aice_arp_init");
219
220         return JIM_OK;
221 }
222
223 /* */
224 static int aice_init_reset(struct command_context *cmd_ctx)
225 {
226         LOG_DEBUG("Initializing with hard TRST+SRST reset");
227
228         int retval;
229         enum reset_types jtag_reset_config = jtag_get_reset_config();
230
231         jtag_add_reset(1, 0);   /* TAP_RESET */
232         if (jtag_reset_config & RESET_HAS_SRST) {
233                 jtag_add_reset(1, 1);
234                 if ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0)
235                         jtag_add_reset(0, 1);
236         }
237         jtag_add_reset(0, 0);
238         retval = jtag_execute_queue();
239         if (retval != ERROR_OK)
240                 return retval;
241
242         return ERROR_OK;
243 }
244
245 /* */
246 static int jim_aice_arp_init_reset(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
247 {
248         int e = ERROR_OK;
249         struct jim_getopt_info goi;
250         jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
251         if (goi.argc != 0) {
252                 Jim_WrongNumArgs(goi.interp, 1, goi.argv - 1, "(no params)");
253                 return JIM_ERR;
254         }
255         struct command_context *context = current_command_context(interp);
256         e = aice_init_reset(context);
257
258         if (e != ERROR_OK) {
259                 Jim_Obj *obj = Jim_NewIntObj(goi.interp, e);
260                 Jim_SetResultFormatted(goi.interp, "error: %#s", obj);
261                 return JIM_ERR;
262         }
263         return JIM_OK;
264 }
265
266 static int jim_aice_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
267 {
268         struct jim_getopt_info goi;
269         jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
270         if (goi.argc != 0) {
271                 Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
272                 return JIM_ERR;
273         }
274         Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0));
275         struct jtag_tap *tap;
276
277         for (tap = jtag_all_taps(); tap; tap = tap->next_tap)
278                 Jim_ListAppendElement(goi.interp,
279                                 Jim_GetResult(goi.interp),
280                                 Jim_NewStringObj(goi.interp,
281                                         tap->dotted_name, -1));
282
283         return JIM_OK;
284 }
285
286 /* */
287 static const struct command_registration 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_ANY,
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, aice_transport_command_handlers);
390 }
391
392 /* */
393 static int aice_transport_init(struct command_context *cmd_ctx)
394 {
395         LOG_DEBUG("aice_transport_init");
396         struct target *t = get_current_target(cmd_ctx);
397         struct transport *transport;
398
399         if (!t) {
400                 LOG_ERROR("no current target");
401                 return ERROR_FAIL;
402         }
403
404         transport = get_current_transport();
405
406         if (!transport) {
407                 LOG_ERROR("no transport selected");
408                 return ERROR_FAIL;
409         }
410
411         LOG_DEBUG("current transport %s", transport->name);
412
413         return aice_init_targets();
414 }
415
416 /* */
417 static int aice_transport_select(struct command_context *ctx)
418 {
419         LOG_DEBUG("aice_transport_select");
420
421         int retval;
422
423         retval = aice_transport_register_commands(ctx);
424
425         if (retval != ERROR_OK)
426                 return retval;
427
428         return ERROR_OK;
429 }
430
431 static struct transport aice_jtag_transport = {
432         .name = "aice_jtag",
433         .select = aice_transport_select,
434         .init = aice_transport_init,
435 };
436
437 const char *aice_transports[] = { "aice_jtag", NULL };
438
439 static void aice_constructor(void) __attribute__((constructor));
440 static void aice_constructor(void)
441 {
442         transport_register(&aice_jtag_transport);
443 }