Remove FSF address from GPL notices
[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         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 static int jim_aice_arp_init(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
162 {
163         LOG_DEBUG("No implement: jim_aice_arp_init");
164
165         return JIM_OK;
166 }
167
168 /* */
169 static int aice_init_reset(struct command_context *cmd_ctx)
170 {
171         LOG_DEBUG("Initializing with hard TRST+SRST reset");
172
173         int retval;
174         enum reset_types jtag_reset_config = jtag_get_reset_config();
175
176         jtag_add_reset(1, 0);   /* TAP_RESET */
177         if (jtag_reset_config & RESET_HAS_SRST) {
178                 jtag_add_reset(1, 1);
179                 if ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0)
180                         jtag_add_reset(0, 1);
181         }
182         jtag_add_reset(0, 0);
183         retval = jtag_execute_queue();
184         if (retval != ERROR_OK)
185                 return retval;
186
187         return ERROR_OK;
188 }
189
190 /* */
191 static int jim_aice_arp_init_reset(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
192 {
193         int e = ERROR_OK;
194         Jim_GetOptInfo goi;
195         Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
196         if (goi.argc != 0) {
197                 Jim_WrongNumArgs(goi.interp, 1, goi.argv - 1, "(no params)");
198                 return JIM_ERR;
199         }
200         struct command_context *context = current_command_context(interp);
201         e = aice_init_reset(context);
202
203         if (e != ERROR_OK) {
204                 Jim_Obj *eObj = Jim_NewIntObj(goi.interp, e);
205                 Jim_SetResultFormatted(goi.interp, "error: %#s", eObj);
206                 Jim_FreeNewObj(goi.interp, eObj);
207                 return JIM_ERR;
208         }
209         return JIM_OK;
210 }
211
212 static int jim_aice_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
213 {
214         Jim_GetOptInfo goi;
215         Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
216         if (goi.argc != 0) {
217                 Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
218                 return JIM_ERR;
219         }
220         Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0));
221         struct jtag_tap *tap;
222
223         for (tap = jtag_all_taps(); tap; tap = tap->next_tap)
224                 Jim_ListAppendElement(goi.interp,
225                                 Jim_GetResult(goi.interp),
226                                 Jim_NewStringObj(goi.interp,
227                                         tap->dotted_name, -1));
228
229         return JIM_OK;
230 }
231
232 /* */
233 static const struct command_registration
234 aice_transport_jtag_subcommand_handlers[] = {
235         {
236                 .name = "init",
237                 .mode = COMMAND_ANY,
238                 .handler = handle_aice_init_command,
239                 .help = "initialize jtag scan chain",
240                 .usage = ""
241         },
242         {
243                 .name = "arp_init",
244                 .mode = COMMAND_ANY,
245                 .jim_handler = jim_aice_arp_init,
246                 .help = "Validates JTAG scan chain against the list of "
247                         "declared TAPs.",
248         },
249         {
250                 .name = "arp_init-reset",
251                 .mode = COMMAND_ANY,
252                 .jim_handler = jim_aice_arp_init_reset,
253                 .help = "Uses TRST and SRST to try resetting everything on "
254                         "the JTAG scan chain, then performs 'jtag arp_init'."
255         },
256         {
257                 .name = "newtap",
258                 .mode = COMMAND_CONFIG,
259                 .jim_handler = jim_aice_newtap,
260                 .help = "Create a new TAP instance named basename.tap_type, "
261                         "and appends it to the scan chain.",
262                 .usage = "basename tap_type ['-expected_id' number]"
263         },
264         {
265                 .name = "tapisenabled",
266                 .mode = COMMAND_EXEC,
267                 .jim_handler = jim_jtag_tap_enabler,
268                 .help = "Returns a Tcl boolean (0/1) indicating whether "
269                         "the TAP is enabled (1) or not (0).",
270                 .usage = "tap_name",
271         },
272         {
273                 .name = "tapenable",
274                 .mode = COMMAND_EXEC,
275                 .jim_handler = jim_jtag_tap_enabler,
276                 .help = "Try to enable the specified TAP using the "
277                         "'tap-enable' TAP event.",
278                 .usage = "tap_name",
279         },
280         {
281                 .name = "tapdisable",
282                 .mode = COMMAND_EXEC,
283                 .jim_handler = jim_jtag_tap_enabler,
284                 .help = "Try to disable the specified TAP using the "
285                         "'tap-disable' TAP event.",
286                 .usage = "tap_name",
287         },
288         {
289                 .name = "configure",
290                 .mode = COMMAND_EXEC,
291                 .jim_handler = jim_jtag_configure,
292                 .help = "Provide a Tcl handler for the specified "
293                         "TAP event.",
294                 .usage = "tap_name '-event' event_name handler",
295         },
296         {
297                 .name = "cget",
298                 .mode = COMMAND_EXEC,
299                 .jim_handler = jim_jtag_configure,
300                 .help = "Return any Tcl handler for the specified "
301                         "TAP event.",
302                 .usage = "tap_name '-event' event_name",
303         },
304         {
305                 .name = "names",
306                 .mode = COMMAND_ANY,
307                 .jim_handler = jim_aice_names,
308                 .help = "Returns list of all JTAG tap names.",
309         },
310
311         COMMAND_REGISTRATION_DONE
312 };
313
314 /* */
315 static const struct command_registration aice_transport_command_handlers[] = {
316         {
317                 .name = "jtag",
318                 .mode = COMMAND_ANY,
319                 .usage = "",
320                 .chain = aice_transport_jtag_subcommand_handlers,
321         },
322         COMMAND_REGISTRATION_DONE
323
324 };
325
326 /* */
327 static int aice_transport_register_commands(struct command_context *cmd_ctx)
328 {
329         return register_commands(cmd_ctx, NULL,
330                         aice_transport_command_handlers);
331 }
332
333 /* */
334 static int aice_transport_init(struct command_context *cmd_ctx)
335 {
336         LOG_DEBUG("aice_transport_init");
337         struct target *t = get_current_target(cmd_ctx);
338         struct transport *transport;
339
340         if (!t) {
341                 LOG_ERROR("no current target");
342                 return ERROR_FAIL;
343         }
344
345         transport = get_current_transport();
346
347         if (!transport) {
348                 LOG_ERROR("no transport selected");
349                 return ERROR_FAIL;
350         }
351
352         LOG_DEBUG("current transport %s", transport->name);
353
354         return aice_init_targets();
355 }
356
357 /* */
358 static int aice_transport_select(struct command_context *ctx)
359 {
360         LOG_DEBUG("aice_transport_select");
361
362         int retval;
363
364         retval = aice_transport_register_commands(ctx);
365
366         if (retval != ERROR_OK)
367                 return retval;
368
369         return ERROR_OK;
370 }
371
372 static struct transport aice_jtag_transport = {
373         .name = "aice_jtag",
374         .select = aice_transport_select,
375         .init = aice_transport_init,
376 };
377
378 const char *aice_transports[] = { "aice_jtag", NULL };
379
380 static void aice_constructor(void) __attribute__((constructor));
381 static void aice_constructor(void)
382 {
383         transport_register(&aice_jtag_transport);
384 }
385