]> git.sur5r.net Git - openocd/blob - src/jtag/aice/aice_transport.c
jim-nvp: Make Jim_GetOpt_String const-correct
[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, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
19  ***************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 /* project specific includes */
26 #include <jtag/interface.h>
27 #include <jtag/tcl.h>
28 #include <transport/transport.h>
29 #include <target/target.h>
30 #include <jtag/aice/aice_interface.h>
31 #include <jtag/aice/aice_transport.h>
32
33 /* */
34 static int jim_newtap_expected_id(Jim_Nvp *n, Jim_GetOptInfo *goi,
35                 struct jtag_tap *pTap)
36 {
37         jim_wide w;
38         int e = Jim_GetOpt_Wide(goi, &w);
39         if (e != JIM_OK) {
40                 Jim_SetResultFormatted(goi->interp, "option: %s bad parameter",
41                                 n->name);
42                 return e;
43         }
44
45         unsigned expected_len = sizeof(uint32_t) * pTap->expected_ids_cnt;
46         uint32_t *new_expected_ids = malloc(expected_len + sizeof(uint32_t));
47         if (new_expected_ids == NULL) {
48                 Jim_SetResultFormatted(goi->interp, "no memory");
49                 return JIM_ERR;
50         }
51
52         memcpy(new_expected_ids, pTap->expected_ids, expected_len);
53
54         new_expected_ids[pTap->expected_ids_cnt] = w;
55
56         free(pTap->expected_ids);
57         pTap->expected_ids = new_expected_ids;
58         pTap->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(Jim_GetOptInfo *goi)
67 {
68         struct jtag_tap *pTap;
69         int x;
70         int e;
71         Jim_Nvp *n;
72         char *cp;
73         const Jim_Nvp opts[] = {
74                 {.name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID},
75                 {.name = NULL, .value = -1},
76         };
77
78         pTap = calloc(1, sizeof(struct jtag_tap));
79         if (!pTap) {
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(pTap);
91                 return JIM_ERR;
92         }
93
94         const char *tmp;
95         Jim_GetOpt_String(goi, &tmp, NULL);
96         pTap->chip = strdup(tmp);
97
98         Jim_GetOpt_String(goi, &tmp, NULL);
99         pTap->tapname = strdup(tmp);
100
101         /* name + dot + name + null */
102         x = strlen(pTap->chip) + 1 + strlen(pTap->tapname) + 1;
103         cp = malloc(x);
104         sprintf(cp, "%s.%s", pTap->chip, pTap->tapname);
105         pTap->dotted_name = cp;
106
107         LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params",
108                         pTap->chip, pTap->tapname, pTap->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_NvpUnknown(goi, opts, 0);
114                         free(cp);
115                         free(pTap);
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, pTap);
122                                 if (JIM_OK != e) {
123                                         free(cp);
124                                         free(pTap);
125                                         return e;
126                                 }
127                                 break;
128                 }               /* switch (n->value) */
129         }                       /* while (goi->argc) */
130
131         /* default is enabled-after-reset */
132         pTap->enabled = !pTap->disabled_after_reset;
133
134         jtag_tap_init(pTap);
135         return JIM_OK;
136 }
137
138 /* */
139 static int jim_aice_newtap(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
140 {
141         Jim_GetOptInfo 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 static int jim_aice_arp_init(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
164 {
165         LOG_DEBUG("No implement: jim_aice_arp_init");
166
167         return JIM_OK;
168 }
169
170 /* */
171 static int aice_init_reset(struct command_context *cmd_ctx)
172 {
173         LOG_DEBUG("Initializing with hard TRST+SRST reset");
174
175         int retval;
176         enum reset_types jtag_reset_config = jtag_get_reset_config();
177
178         jtag_add_reset(1, 0);   /* TAP_RESET */
179         if (jtag_reset_config & RESET_HAS_SRST) {
180                 jtag_add_reset(1, 1);
181                 if ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0)
182                         jtag_add_reset(0, 1);
183         }
184         jtag_add_reset(0, 0);
185         retval = jtag_execute_queue();
186         if (retval != ERROR_OK)
187                 return retval;
188
189         return ERROR_OK;
190 }
191
192 /* */
193 static int jim_aice_arp_init_reset(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
194 {
195         int e = ERROR_OK;
196         Jim_GetOptInfo goi;
197         Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
198         if (goi.argc != 0) {
199                 Jim_WrongNumArgs(goi.interp, 1, goi.argv - 1, "(no params)");
200                 return JIM_ERR;
201         }
202         struct command_context *context = current_command_context(interp);
203         e = aice_init_reset(context);
204
205         if (e != ERROR_OK) {
206                 Jim_Obj *eObj = Jim_NewIntObj(goi.interp, e);
207                 Jim_SetResultFormatted(goi.interp, "error: %#s", eObj);
208                 Jim_FreeNewObj(goi.interp, eObj);
209                 return JIM_ERR;
210         }
211         return JIM_OK;
212 }
213
214 static int jim_aice_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
215 {
216         Jim_GetOptInfo goi;
217         Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
218         if (goi.argc != 0) {
219                 Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
220                 return JIM_ERR;
221         }
222         Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0));
223         struct jtag_tap *tap;
224
225         for (tap = jtag_all_taps(); tap; tap = tap->next_tap)
226                 Jim_ListAppendElement(goi.interp,
227                                 Jim_GetResult(goi.interp),
228                                 Jim_NewStringObj(goi.interp,
229                                         tap->dotted_name, -1));
230
231         return JIM_OK;
232 }
233
234 /* */
235 static const struct command_registration
236 aice_transport_jtag_subcommand_handlers[] = {
237         {
238                 .name = "init",
239                 .mode = COMMAND_ANY,
240                 .handler = handle_aice_init_command,
241                 .help = "initialize jtag scan chain",
242                 .usage = ""
243         },
244         {
245                 .name = "arp_init",
246                 .mode = COMMAND_ANY,
247                 .jim_handler = jim_aice_arp_init,
248                 .help = "Validates JTAG scan chain against the list of "
249                         "declared TAPs.",
250         },
251         {
252                 .name = "arp_init-reset",
253                 .mode = COMMAND_ANY,
254                 .jim_handler = jim_aice_arp_init_reset,
255                 .help = "Uses TRST and SRST to try resetting everything on "
256                         "the JTAG scan chain, then performs 'jtag arp_init'."
257         },
258         {
259                 .name = "newtap",
260                 .mode = COMMAND_CONFIG,
261                 .jim_handler = jim_aice_newtap,
262                 .help = "Create a new TAP instance named basename.tap_type, "
263                         "and appends it to the scan chain.",
264                 .usage = "basename tap_type ['-expected_id' number]"
265         },
266         {
267                 .name = "tapisenabled",
268                 .mode = COMMAND_EXEC,
269                 .jim_handler = jim_jtag_tap_enabler,
270                 .help = "Returns a Tcl boolean (0/1) indicating whether "
271                         "the TAP is enabled (1) or not (0).",
272                 .usage = "tap_name",
273         },
274         {
275                 .name = "tapenable",
276                 .mode = COMMAND_EXEC,
277                 .jim_handler = jim_jtag_tap_enabler,
278                 .help = "Try to enable the specified TAP using the "
279                         "'tap-enable' TAP event.",
280                 .usage = "tap_name",
281         },
282         {
283                 .name = "tapdisable",
284                 .mode = COMMAND_EXEC,
285                 .jim_handler = jim_jtag_tap_enabler,
286                 .help = "Try to disable the specified TAP using the "
287                         "'tap-disable' TAP event.",
288                 .usage = "tap_name",
289         },
290         {
291                 .name = "configure",
292                 .mode = COMMAND_EXEC,
293                 .jim_handler = jim_jtag_configure,
294                 .help = "Provide a Tcl handler for the specified "
295                         "TAP event.",
296                 .usage = "tap_name '-event' event_name handler",
297         },
298         {
299                 .name = "cget",
300                 .mode = COMMAND_EXEC,
301                 .jim_handler = jim_jtag_configure,
302                 .help = "Return any Tcl handler for the specified "
303                         "TAP event.",
304                 .usage = "tap_name '-event' event_name",
305         },
306         {
307                 .name = "names",
308                 .mode = COMMAND_ANY,
309                 .jim_handler = jim_aice_names,
310                 .help = "Returns list of all JTAG tap names.",
311         },
312
313         COMMAND_REGISTRATION_DONE
314 };
315
316 /* */
317 static const struct command_registration aice_transport_command_handlers[] = {
318         {
319                 .name = "jtag",
320                 .mode = COMMAND_ANY,
321                 .usage = "",
322                 .chain = aice_transport_jtag_subcommand_handlers,
323         },
324         COMMAND_REGISTRATION_DONE
325
326 };
327
328 /* */
329 static int aice_transport_register_commands(struct command_context *cmd_ctx)
330 {
331         return register_commands(cmd_ctx, NULL,
332                         aice_transport_command_handlers);
333 }
334
335 /* */
336 static int aice_transport_init(struct command_context *cmd_ctx)
337 {
338         LOG_DEBUG("aice_transport_init");
339         struct target *t = get_current_target(cmd_ctx);
340         struct transport *transport;
341
342         if (!t) {
343                 LOG_ERROR("no current target");
344                 return ERROR_FAIL;
345         }
346
347         transport = get_current_transport();
348
349         if (!transport) {
350                 LOG_ERROR("no transport selected");
351                 return ERROR_FAIL;
352         }
353
354         LOG_DEBUG("current transport %s", transport->name);
355
356         return aice_init_targets();
357 }
358
359 /* */
360 static int aice_transport_select(struct command_context *ctx)
361 {
362         LOG_DEBUG("aice_transport_select");
363
364         int retval;
365
366         retval = aice_transport_register_commands(ctx);
367
368         if (retval != ERROR_OK)
369                 return retval;
370
371         return ERROR_OK;
372 }
373
374 static struct transport aice_jtag_transport = {
375         .name = "aice_jtag",
376         .select = aice_transport_select,
377         .init = aice_transport_init,
378 };
379
380 const char *aice_transports[] = { "aice_jtag", NULL };
381
382 static void aice_constructor(void) __attribute__((constructor));
383 static void aice_constructor(void)
384 {
385         transport_register(&aice_jtag_transport);
386 }
387