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

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)