aice: add Andes AICE support
[openocd.git] / src / jtag / aice / aice_interface.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 #include <jtag/interface.h>
26 #include <jtag/commands.h>
27 #include <transport/transport.h>
28 #include <target/target.h>
29 #include <jtag/aice/aice_transport.h>
30 #include <jtag/drivers/libusb_common.h>
31 #include "aice_usb.h"
32
33 #define AICE_KHZ_TO_SPEED_MAP_SIZE 16
34 static int aice_khz_to_speed_map[AICE_KHZ_TO_SPEED_MAP_SIZE] = {
35 30000,
36 15000,
37 7500,
38 3750,
39 1875,
40 937,
41 468,
42 234,
43 48000,
44 24000,
45 12000,
46 6000,
47 3000,
48 1500,
49 750,
50 375,
51 };
52
53 static struct aice_port_s aice;
54
55 /***************************************************************************/
56 /* External interface implementation */
57 #define AICE_MAX_TARGET_ID_CODES 0x10
58 static uint32_t aice_target_id_codes[AICE_MAX_TARGET_ID_CODES];
59 static uint8_t aice_num_of_target_id_codes;
60
61 /***************************************************************************/
62 /* AICE operations */
63 int aice_init_target(struct target *t)
64 {
65 int res;
66
67 LOG_DEBUG("aice_init_target");
68
69 if (aice_num_of_target_id_codes == 0) {
70 res = aice.port->api->idcode(aice_target_id_codes, &aice_num_of_target_id_codes);
71 if (res != ERROR_OK) {
72 LOG_ERROR("<-- TARGET ERROR! Failed to identify AndesCore "
73 "JTAG Manufacture ID in the JTAG scan chain. "
74 "Failed to access EDM registers. -->");
75 return res;
76 }
77 }
78
79 t->tap->idcode = aice_target_id_codes[t->tap->abs_chain_position];
80
81 unsigned ii, limit = t->tap->expected_ids_cnt;
82 int found = 0;
83
84 for (ii = 0; ii < limit; ii++) {
85 uint32_t expected = t->tap->expected_ids[ii];
86
87 /* treat "-expected-id 0" as a "don't-warn" wildcard */
88 if (!expected || (t->tap->idcode == expected)) {
89 found = 1;
90 break;
91 }
92 }
93
94 if (found == 0) {
95 LOG_ERROR
96 ("aice_init_target: target not found: idcode: %x ",
97 t->tap->idcode);
98 return ERROR_FAIL;
99 }
100
101 t->tap->priv = &aice;
102 t->tap->hasidcode = 1;
103
104 return ERROR_OK;
105 }
106
107 /***************************************************************************/
108 /* End of External interface implementation */
109
110 /* initial aice
111 * 1. open usb
112 * 2. get/show version number
113 * 3. reset
114 */
115 static int aice_init(void)
116 {
117 if (ERROR_OK != aice.port->api->open(&(aice.param))) {
118 LOG_ERROR("Cannot find AICE Interface! Please check "
119 "connection and permissions.");
120 return ERROR_JTAG_INIT_FAILED;
121 }
122
123 aice.port->api->set_retry_times(aice.retry_times);
124 aice.port->api->set_count_to_check_dbger(aice.count_to_check_dbger);
125
126 LOG_INFO("AICE JTAG Interface ready");
127
128 return ERROR_OK;
129 }
130
131 /* cleanup aice resource
132 * close usb
133 */
134 static int aice_quit(void)
135 {
136 aice.port->api->close();
137 return ERROR_OK;
138 }
139
140 static int aice_execute_reset(struct jtag_command *cmd)
141 {
142 static int last_trst;
143 int retval = ERROR_OK;
144
145 DEBUG_JTAG_IO("reset trst: %i", cmd->cmd.reset->trst);
146
147 if (cmd->cmd.reset->trst != last_trst) {
148 if (cmd->cmd.reset->trst)
149 retval = aice.port->api->reset();
150
151 last_trst = cmd->cmd.reset->trst;
152 }
153
154 return retval;
155 }
156
157 static int aice_execute_command(struct jtag_command *cmd)
158 {
159 int retval;
160
161 switch (cmd->type) {
162 case JTAG_RESET:
163 retval = aice_execute_reset(cmd);
164 break;
165 default:
166 retval = ERROR_OK;
167 break;
168 }
169 return retval;
170 }
171
172 /* aice has no need to implement jtag execution model
173 */
174 static int aice_execute_queue(void)
175 {
176 struct jtag_command *cmd = jtag_command_queue; /* currently processed command */
177 int retval;
178
179 retval = ERROR_OK;
180
181 while (cmd) {
182 if (aice_execute_command(cmd) != ERROR_OK)
183 retval = ERROR_JTAG_QUEUE_FAILED;
184
185 cmd = cmd->next;
186 }
187
188 return retval;
189 }
190
191 /* set jtag frequency(base frequency/frequency divider) to your jtag adapter */
192 static int aice_speed(int speed)
193 {
194 return aice.port->api->set_jtag_clock(speed);
195 }
196
197 /* convert jtag adapter frequency(base frequency/frequency divider) to
198 * human readable KHz value */
199 static int aice_speed_div(int speed, int *khz)
200 {
201 *khz = aice_khz_to_speed_map[speed];
202
203 return ERROR_OK;
204 }
205
206 /* convert human readable KHz value to jtag adapter frequency
207 * (base frequency/frequency divider) */
208 static int aice_khz(int khz, int *jtag_speed)
209 {
210 int i;
211 for (i = 0 ; i < AICE_KHZ_TO_SPEED_MAP_SIZE ; i++) {
212 if (khz == aice_khz_to_speed_map[i]) {
213 if (8 <= i)
214 *jtag_speed = i | AICE_TCK_CONTROL_TCK3048;
215 else
216 *jtag_speed = i;
217 break;
218 }
219 }
220
221 if (i == AICE_KHZ_TO_SPEED_MAP_SIZE) {
222 LOG_INFO("No support the jtag clock: %d", khz);
223 LOG_INFO("Supported jtag clocks are:");
224
225 for (i = 0 ; i < AICE_KHZ_TO_SPEED_MAP_SIZE ; i++)
226 LOG_INFO("* %d", aice_khz_to_speed_map[i]);
227
228 return ERROR_FAIL;
229 }
230
231 return ERROR_OK;
232 }
233
234 /***************************************************************************/
235 /* Command handlers */
236 COMMAND_HANDLER(aice_handle_aice_info_command)
237 {
238 LOG_DEBUG("aice_handle_aice_info_command");
239
240 command_print(CMD_CTX, "Description: %s", aice.param.device_desc);
241 command_print(CMD_CTX, "Serial number: %s", aice.param.serial);
242 if (strncmp(aice.port->name, "aice_pipe", 9) == 0)
243 command_print(CMD_CTX, "Adapter: %s", aice.param.adapter_name);
244
245 return ERROR_OK;
246 }
247
248 COMMAND_HANDLER(aice_handle_aice_port_command)
249 {
250 LOG_DEBUG("aice_handle_aice_port_command");
251
252 if (CMD_ARGC != 1) {
253 LOG_ERROR("Need exactly one argument to 'aice port'");
254 return ERROR_COMMAND_SYNTAX_ERROR;
255 }
256
257 for (const struct aice_port *l = aice_port_get_list(); l->name; l++) {
258 if (strcmp(l->name, CMD_ARGV[0]) == 0) {
259 aice.port = l;
260 return ERROR_OK;
261 }
262 }
263
264 LOG_ERROR("No AICE port '%s' found", CMD_ARGV[0]);
265 return ERROR_FAIL;
266 }
267
268 COMMAND_HANDLER(aice_handle_aice_desc_command)
269 {
270 LOG_DEBUG("aice_handle_aice_desc_command");
271
272 if (CMD_ARGC == 1)
273 aice.param.device_desc = strdup(CMD_ARGV[0]);
274 else
275 LOG_ERROR("expected exactly one argument to aice desc <description>");
276
277 return ERROR_OK;
278 }
279
280 COMMAND_HANDLER(aice_handle_aice_serial_command)
281 {
282 LOG_DEBUG("aice_handle_aice_serial_command");
283
284 if (CMD_ARGC == 1)
285 aice.param.serial = strdup(CMD_ARGV[0]);
286 else
287 LOG_ERROR("expected exactly one argument to aice serial <serial-number>");
288
289 return ERROR_OK;
290 }
291
292 COMMAND_HANDLER(aice_handle_aice_vid_pid_command)
293 {
294 LOG_DEBUG("aice_handle_aice_vid_pid_command");
295
296 if (CMD_ARGC != 2) {
297 LOG_WARNING("ignoring extra IDs in aice vid_pid (maximum is 1 pair)");
298 return ERROR_COMMAND_SYNTAX_ERROR;
299 }
300
301 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], aice.param.vid);
302 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], aice.param.pid);
303
304 return ERROR_OK;
305 }
306
307 COMMAND_HANDLER(aice_handle_aice_adapter_command)
308 {
309 LOG_DEBUG("aice_handle_aice_adapter_command");
310
311 if (CMD_ARGC == 1)
312 aice.param.adapter_name = strdup(CMD_ARGV[0]);
313 else
314 LOG_ERROR("expected exactly one argument to aice adapter <adapter-name>");
315
316 return ERROR_OK;
317 }
318
319 COMMAND_HANDLER(aice_handle_aice_retry_times_command)
320 {
321 LOG_DEBUG("aice_handle_aice_retry_times_command");
322
323 if (CMD_ARGC == 1)
324 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], aice.retry_times);
325 else
326 LOG_ERROR("expected exactly one argument to aice retry_times <num_of_retry>");
327
328 return ERROR_OK;
329 }
330
331 COMMAND_HANDLER(aice_handle_aice_count_to_check_dbger_command)
332 {
333 LOG_DEBUG("aice_handle_aice_count_to_check_dbger_command");
334
335 if (CMD_ARGC == 1)
336 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], aice.count_to_check_dbger);
337 else
338 LOG_ERROR("expected exactly one argument to aice count_to_check_dbger "
339 "<count_of_checking>");
340
341 return ERROR_OK;
342 }
343
344 COMMAND_HANDLER(aice_handle_aice_custom_srst_script_command)
345 {
346 LOG_DEBUG("aice_handle_aice_custom_srst_script_command");
347
348 if (CMD_ARGC > 0) {
349 aice.port->api->set_custom_srst_script(CMD_ARGV[0]);
350 return ERROR_OK;
351 }
352
353 return ERROR_FAIL;
354 }
355
356 COMMAND_HANDLER(aice_handle_aice_custom_trst_script_command)
357 {
358 LOG_DEBUG("aice_handle_aice_custom_trst_script_command");
359
360 if (CMD_ARGC > 0) {
361 aice.port->api->set_custom_trst_script(CMD_ARGV[0]);
362 return ERROR_OK;
363 }
364
365 return ERROR_FAIL;
366 }
367
368 COMMAND_HANDLER(aice_handle_aice_custom_restart_script_command)
369 {
370 LOG_DEBUG("aice_handle_aice_custom_restart_script_command");
371
372 if (CMD_ARGC > 0) {
373 aice.port->api->set_custom_restart_script(CMD_ARGV[0]);
374 return ERROR_OK;
375 }
376
377 return ERROR_FAIL;
378 }
379
380 COMMAND_HANDLER(aice_handle_aice_reset_command)
381 {
382 LOG_DEBUG("aice_handle_aice_reset_command");
383
384 return aice.port->api->reset();
385 }
386
387
388 static const struct command_registration aice_subcommand_handlers[] = {
389 {
390 .name = "info",
391 .handler = &aice_handle_aice_info_command,
392 .mode = COMMAND_EXEC,
393 .help = "show aice info",
394 .usage = "aice info",
395 },
396 {
397 .name = "port",
398 .handler = &aice_handle_aice_port_command,
399 .mode = COMMAND_CONFIG,
400 .help = "set the port of the AICE",
401 .usage = "aice port ['aice_pipe'|'aice_usb']",
402 },
403 {
404 .name = "desc",
405 .handler = &aice_handle_aice_desc_command,
406 .mode = COMMAND_CONFIG,
407 .help = "set the aice device description",
408 .usage = "aice desc [desciption string]",
409 },
410 {
411 .name = "serial",
412 .handler = &aice_handle_aice_serial_command,
413 .mode = COMMAND_CONFIG,
414 .help = "set the serial number of the AICE device",
415 .usage = "aice serial [serial string]",
416 },
417 {
418 .name = "vid_pid",
419 .handler = &aice_handle_aice_vid_pid_command,
420 .mode = COMMAND_CONFIG,
421 .help = "the vendor and product ID of the AICE device",
422 .usage = "aice vid_pid (vid pid)*",
423 },
424 {
425 .name = "adapter",
426 .handler = &aice_handle_aice_adapter_command,
427 .mode = COMMAND_CONFIG,
428 .help = "set the file name of adapter",
429 .usage = "aice adapter [adapter name]",
430 },
431 {
432 .name = "retry_times",
433 .handler = &aice_handle_aice_retry_times_command,
434 .mode = COMMAND_CONFIG,
435 .help = "set retry times as AICE timeout",
436 .usage = "aice retry_times num_of_retry",
437 },
438 {
439 .name = "count_to_check_dbger",
440 .handler = &aice_handle_aice_count_to_check_dbger_command,
441 .mode = COMMAND_CONFIG,
442 .help = "set retry times as checking $DBGER status",
443 .usage = "aice count_to_check_dbger count_of_checking",
444 },
445 {
446 .name = "custom_srst_script",
447 .handler = &aice_handle_aice_custom_srst_script_command,
448 .mode = COMMAND_CONFIG,
449 .usage = "custom_srst_script script_file_name",
450 .help = "set custom srst script",
451 },
452 {
453 .name = "custom_trst_script",
454 .handler = &aice_handle_aice_custom_trst_script_command,
455 .mode = COMMAND_CONFIG,
456 .usage = "custom_trst_script script_file_name",
457 .help = "set custom trst script",
458 },
459 {
460 .name = "custom_restart_script",
461 .handler = &aice_handle_aice_custom_restart_script_command,
462 .mode = COMMAND_CONFIG,
463 .usage = "custom_restart_script script_file_name",
464 .help = "set custom restart script",
465 },
466 {
467 .name = "reset",
468 .handler = &aice_handle_aice_reset_command,
469 .mode = COMMAND_EXEC,
470 .usage = "aice reset",
471 .help = "reset AICE",
472 },
473 COMMAND_REGISTRATION_DONE
474 };
475
476 static const struct command_registration aice_command_handlers[] = {
477 {
478 .name = "aice",
479 .mode = COMMAND_ANY,
480 .help = "perform aice management",
481 .usage = "aice [subcommand]",
482 .chain = aice_subcommand_handlers,
483 },
484 COMMAND_REGISTRATION_DONE
485 };
486 /***************************************************************************/
487 /* End of Command handlers */
488
489 struct jtag_interface aice_interface = {
490 .name = "aice",
491 .commands = aice_command_handlers,
492 .transports = aice_transports,
493 .init = aice_init,
494 .quit = aice_quit,
495 .execute_queue = aice_execute_queue,
496 .speed = aice_speed, /* set interface speed */
497 .speed_div = aice_speed_div, /* return readable value */
498 .khz = aice_khz, /* convert khz to interface speed value */
499 };
500

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)