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