0c208bfa25ec86111bea10a26f9a2bf9350011d9
[openocd.git] / 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 Jim_GetOpt_String(goi, &cp, NULL);
94 pTap->chip = strdup(cp);
95
96 Jim_GetOpt_String(goi, &cp, NULL);
97 pTap->tapname = strdup(cp);
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((void *)pTap->dotted_name);
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((void *)pTap->dotted_name);
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