34a4ae784d3a34d0aca47956eede1328d9db71f0
[openocd.git] / src / jtag / drivers / amt_jtagaccel.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
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 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <jtag/interface.h>
25
26 #if PARPORT_USE_PPDEV == 1
27 #include <linux/parport.h>
28 #include <linux/ppdev.h>
29 #include <sys/ioctl.h>
30 #else /* not PARPORT_USE_PPDEV */
31 #ifndef _WIN32
32 #include <sys/io.h>
33 #endif
34 #endif
35
36 #if PARPORT_USE_GIVEIO == 1
37 #if IS_CYGWIN == 1
38 #include <windows.h>
39 #endif
40 #endif
41
42 /**
43 * @file
44 * Support the Amontec Chameleon POD with JTAG Accelerator support.
45 * This is a parallel port JTAG adapter with a CPLD between the
46 * parallel port and the JTAG connection. VHDL code running in the
47 * CPLD significantly accelerates JTAG operations compared to the
48 * bitbanging "Wiggler" style of most parallel port adapters.
49 */
50
51 /* configuration */
52 static uint16_t amt_jtagaccel_port;
53
54 /* interface variables
55 */
56 static uint8_t aw_control_rst = 0x00;
57 static uint8_t aw_control_fsm = 0x10;
58 static uint8_t aw_control_baudrate = 0x20;
59
60 static int rtck_enabled = 0;
61
62 #if PARPORT_USE_PPDEV == 1
63 static int device_handle;
64
65 static const int addr_mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
66
67 /* FIXME do something sane when these ioctl/read/write calls fail. */
68
69 #define AMT_AW(val) \
70 do { \
71 int __retval; \
72 \
73 __retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
74 assert(__retval >= 0); \
75 __retval = write(device_handle, &val, 1); \
76 assert(__retval >= 0); \
77 } while (0)
78 #define AMT_AR(val) \
79 do { \
80 int __retval; \
81 \
82 __retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
83 assert(__retval >= 0); \
84 __retval = read(device_handle, &val, 1); \
85 assert(__retval >= 0); \
86 } while (0)
87
88 static const int data_mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
89
90 #define AMT_DW(val) \
91 do { \
92 int __retval; \
93 \
94 __retval = ioctl(device_handle, PPSETMODE, &data_mode); \
95 assert(__retval >= 0); \
96 __retval = write(device_handle, &val, 1); \
97 assert(__retval >= 0); \
98 } while (0)
99 #define AMT_DR(val) \
100 do { \
101 int __retval; \
102 \
103 __retval = ioctl(device_handle, PPSETMODE, &data_mode); \
104 assert(__retval >= 0); \
105 __retval = read(device_handle, &val, 1); \
106 assert(__retval >= 0); \
107 } while (0)
108
109 #else
110
111 #define AMT_AW(val) do { outb(val, amt_jtagaccel_port + 3); } while (0)
112 #define AMT_AR(val) do { val = inb(amt_jtagaccel_port + 3); } while (0)
113 #define AMT_DW(val) do { outb(val, amt_jtagaccel_port + 4); } while (0)
114 #define AMT_DR(val) do { val = inb(amt_jtagaccel_port + 4); } while (0)
115
116 #endif // PARPORT_USE_PPDEV
117
118 /* tap_move[i][j]: tap movement command to go from state i to state j
119 * 0: Test-Logic-Reset
120 * 1: Run-Test/Idle
121 * 2: Shift-DR
122 * 3: Pause-DR
123 * 4: Shift-IR
124 * 5: Pause-IR
125 */
126 static uint8_t amt_jtagaccel_tap_move[6][6][2] =
127 {
128 /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */
129 {{0x1f, 0x00}, {0x0f, 0x00}, {0x05, 0x00}, {0x0a, 0x00}, {0x06, 0x00}, {0x96, 0x00}}, /* RESET */
130 {{0x1f, 0x00}, {0x00, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x0b, 0x00}}, /* IDLE */
131 {{0x1f, 0x00}, {0x0d, 0x00}, {0x00, 0x00}, {0x01, 0x00}, {0x8f, 0x09}, {0x8f, 0x01}}, /* DRSHIFT */
132 {{0x1f, 0x00}, {0x0c, 0x00}, {0x08, 0x00}, {0x00, 0x00}, {0x8f, 0x09}, {0x8f, 0x01}}, /* DRPAUSE */
133 {{0x1f, 0x00}, {0x0d, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x00, 0x00}, {0x01, 0x00}}, /* IRSHIFT */
134 {{0x1f, 0x00}, {0x0c, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x08, 0x00}, {0x00, 0x00}}, /* IRPAUSE */
135 };
136
137
138 static void amt_jtagaccel_reset(int trst, int srst)
139 {
140 if (trst == 1)
141 aw_control_rst |= 0x4;
142 else if (trst == 0)
143 aw_control_rst &= ~0x4;
144
145 if (srst == 1)
146 aw_control_rst |= 0x1;
147 else if (srst == 0)
148 aw_control_rst &= ~0x1;
149
150 AMT_AW(aw_control_rst);
151 }
152
153 static int amt_jtagaccel_speed(int speed)
154 {
155 aw_control_baudrate &= 0xf0;
156 aw_control_baudrate |= speed & 0x0f;
157 AMT_AW(aw_control_baudrate);
158
159 return ERROR_OK;
160 }
161
162 static void amt_jtagaccel_end_state(tap_state_t state)
163 {
164 if (tap_is_state_stable(state))
165 tap_set_end_state(state);
166 else
167 {
168 LOG_ERROR("BUG: %i is not a valid end state", state);
169 exit(-1);
170 }
171 }
172
173 static void amt_wait_scan_busy(void)
174 {
175 int timeout = 4096;
176 uint8_t ar_status;
177
178 AMT_AR(ar_status);
179 while (((ar_status) & 0x80) && (timeout-- > 0))
180 AMT_AR(ar_status);
181
182 if (ar_status & 0x80)
183 {
184 LOG_ERROR("amt_jtagaccel timed out while waiting for end of scan, rtck was %s, last AR_STATUS: 0x%2.2x", (rtck_enabled) ? "enabled" : "disabled", ar_status);
185 exit(-1);
186 }
187 }
188
189 static void amt_jtagaccel_state_move(void)
190 {
191 uint8_t aw_scan_tms_5;
192 uint8_t tms_scan[2];
193
194 tap_state_t cur_state = tap_get_state();
195 tap_state_t end_state = tap_get_end_state();
196
197 tms_scan[0] = amt_jtagaccel_tap_move[tap_move_ndx(cur_state)][tap_move_ndx(end_state)][0];
198 tms_scan[1] = amt_jtagaccel_tap_move[tap_move_ndx(cur_state)][tap_move_ndx(end_state)][1];
199
200 aw_scan_tms_5 = 0x40 | (tms_scan[0] & 0x1f);
201 AMT_AW(aw_scan_tms_5);
202 int jtag_speed=0;
203 int retval = jtag_get_speed(&jtag_speed);
204 assert(retval == ERROR_OK);
205 if (jtag_speed > 3 || rtck_enabled)
206 amt_wait_scan_busy();
207
208 if (tms_scan[0] & 0x80)
209 {
210 aw_scan_tms_5 = 0x40 | (tms_scan[1] & 0x1f);
211 AMT_AW(aw_scan_tms_5);
212 if (jtag_speed > 3 || rtck_enabled)
213 amt_wait_scan_busy();
214 }
215
216 tap_set_state(end_state);
217 }
218
219 static void amt_jtagaccel_runtest(int num_cycles)
220 {
221 int i = 0;
222 uint8_t aw_scan_tms_5;
223 uint8_t aw_scan_tms_1to4;
224
225 tap_state_t saved_end_state = tap_get_end_state();
226
227 /* only do a state_move when we're not already in IDLE */
228 if (tap_get_state() != TAP_IDLE)
229 {
230 amt_jtagaccel_end_state(TAP_IDLE);
231 amt_jtagaccel_state_move();
232 }
233
234 while (num_cycles - i >= 5)
235 {
236 aw_scan_tms_5 = 0x40;
237 AMT_AW(aw_scan_tms_5);
238 i += 5;
239 }
240
241 if (num_cycles - i > 0)
242 {
243 aw_scan_tms_1to4 = 0x80 | ((num_cycles - i - 1) & 0x3) << 4;
244 AMT_AW(aw_scan_tms_1to4);
245 }
246
247 amt_jtagaccel_end_state(saved_end_state);
248 if (tap_get_state() != tap_get_end_state())
249 amt_jtagaccel_state_move();
250 }
251
252 static void amt_jtagaccel_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size)
253 {
254 int bits_left = scan_size;
255 int bit_count = 0;
256 tap_state_t saved_end_state = tap_get_end_state();
257 uint8_t aw_tdi_option;
258 uint8_t dw_tdi_scan;
259 uint8_t dr_tdo;
260 uint8_t aw_tms_scan;
261 uint8_t tms_scan[2];
262 int jtag_speed_var;
263 int retval = jtag_get_speed(&jtag_speed_var);
264 assert(retval == ERROR_OK);
265
266 if (ir_scan)
267 amt_jtagaccel_end_state(TAP_IRSHIFT);
268 else
269 amt_jtagaccel_end_state(TAP_DRSHIFT);
270
271 amt_jtagaccel_state_move();
272 amt_jtagaccel_end_state(saved_end_state);
273
274 /* handle unaligned bits at the beginning */
275 if ((scan_size - 1) % 8)
276 {
277 aw_tdi_option = 0x30 | (((scan_size - 1) % 8) - 1);
278 AMT_AW(aw_tdi_option);
279
280 dw_tdi_scan = buf_get_u32(buffer, bit_count, (scan_size - 1) % 8) & 0xff;
281 AMT_DW(dw_tdi_scan);
282 if (jtag_speed_var > 3 || rtck_enabled)
283 amt_wait_scan_busy();
284
285 if ((type == SCAN_IN) || (type == SCAN_IO))
286 {
287 AMT_DR(dr_tdo);
288 dr_tdo = dr_tdo >> (8 - ((scan_size - 1) % 8));
289 buf_set_u32(buffer, bit_count, (scan_size - 1) % 8, dr_tdo);
290 }
291
292 bit_count += (scan_size - 1) % 8;
293 bits_left -= (scan_size - 1) % 8;
294 }
295
296 while (bits_left - 1 >= 8)
297 {
298 dw_tdi_scan = buf_get_u32(buffer, bit_count, 8) & 0xff;
299 AMT_DW(dw_tdi_scan);
300 if (jtag_speed_var > 3 || rtck_enabled)
301 amt_wait_scan_busy();
302
303 if ((type == SCAN_IN) || (type == SCAN_IO))
304 {
305 AMT_DR(dr_tdo);
306 buf_set_u32(buffer, bit_count, 8, dr_tdo);
307 }
308
309 bit_count += 8;
310 bits_left -= 8;
311 }
312
313 tms_scan[0] = amt_jtagaccel_tap_move[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][0];
314 tms_scan[1] = amt_jtagaccel_tap_move[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][1];
315 aw_tms_scan = 0x40 | (tms_scan[0] & 0x1f) | (buf_get_u32(buffer, bit_count, 1) << 5);
316 AMT_AW(aw_tms_scan);
317 if (jtag_speed_var > 3 || rtck_enabled)
318 amt_wait_scan_busy();
319
320 if ((type == SCAN_IN) || (type == SCAN_IO))
321 {
322 AMT_DR(dr_tdo);
323 dr_tdo = dr_tdo >> 7;
324 buf_set_u32(buffer, bit_count, 1, dr_tdo);
325 }
326
327 if (tms_scan[0] & 0x80)
328 {
329 aw_tms_scan = 0x40 | (tms_scan[1] & 0x1f);
330 AMT_AW(aw_tms_scan);
331 if (jtag_speed_var > 3 || rtck_enabled)
332 amt_wait_scan_busy();
333 }
334 tap_set_state(tap_get_end_state());
335 }
336
337 static int amt_jtagaccel_execute_queue(void)
338 {
339 struct jtag_command *cmd = jtag_command_queue; /* currently processed command */
340 int scan_size;
341 enum scan_type type;
342 uint8_t *buffer;
343 int retval;
344
345 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
346 * that wasn't handled by a caller-provided error handler
347 */
348 retval = ERROR_OK;
349
350 while (cmd)
351 {
352 switch (cmd->type)
353 {
354 case JTAG_RESET:
355 #ifdef _DEBUG_JTAG_IO_
356 LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
357 #endif
358 if (cmd->cmd.reset->trst == 1)
359 {
360 tap_set_state(TAP_RESET);
361 }
362 amt_jtagaccel_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
363 break;
364 case JTAG_RUNTEST:
365 #ifdef _DEBUG_JTAG_IO_
366 LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
367 #endif
368 amt_jtagaccel_end_state(cmd->cmd.runtest->end_state);
369 amt_jtagaccel_runtest(cmd->cmd.runtest->num_cycles);
370 break;
371 case JTAG_TLR_RESET:
372 #ifdef _DEBUG_JTAG_IO_
373 LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
374 #endif
375 amt_jtagaccel_end_state(cmd->cmd.statemove->end_state);
376 amt_jtagaccel_state_move();
377 break;
378 case JTAG_SCAN:
379 #ifdef _DEBUG_JTAG_IO_
380 LOG_DEBUG("scan end in %i", cmd->cmd.scan->end_state);
381 #endif
382 amt_jtagaccel_end_state(cmd->cmd.scan->end_state);
383 scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
384 type = jtag_scan_type(cmd->cmd.scan);
385 amt_jtagaccel_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
386 if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
387 retval = ERROR_JTAG_QUEUE_FAILED;
388 if (buffer)
389 free(buffer);
390 break;
391 case JTAG_SLEEP:
392 #ifdef _DEBUG_JTAG_IO_
393 LOG_DEBUG("sleep %" PRIi32, cmd->cmd.sleep->us);
394 #endif
395 jtag_sleep(cmd->cmd.sleep->us);
396 break;
397 default:
398 LOG_ERROR("BUG: unknown JTAG command type encountered");
399 exit(-1);
400 }
401 cmd = cmd->next;
402 }
403
404 return retval;
405 }
406
407 #if PARPORT_USE_GIVEIO == 1
408 int amt_jtagaccel_get_giveio_access(void)
409 {
410 HANDLE h;
411 OSVERSIONINFO version;
412
413 version.dwOSVersionInfoSize = sizeof version;
414 if (!GetVersionEx(&version)) {
415 errno = EINVAL;
416 return -1;
417 }
418 if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
419 return 0;
420
421 h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
422 if (h == INVALID_HANDLE_VALUE) {
423 errno = ENODEV;
424 return -1;
425 }
426
427 CloseHandle(h);
428
429 return 0;
430 }
431 #endif
432
433 static int amt_jtagaccel_init(void)
434 {
435 #if PARPORT_USE_PPDEV == 1
436 char buffer[256];
437 int i = 0;
438 uint8_t control_port;
439 #else
440 uint8_t status_port;
441 #endif
442 uint8_t ar_status;
443
444 #if PARPORT_USE_PPDEV == 1
445 if (device_handle > 0)
446 {
447 LOG_ERROR("device is already opened");
448 return ERROR_JTAG_INIT_FAILED;
449 }
450
451 snprintf(buffer, 256, "/dev/parport%d", amt_jtagaccel_port);
452 device_handle = open(buffer, O_RDWR);
453
454 if (device_handle < 0)
455 {
456 LOG_ERROR("cannot open device. check it exists and that user read and write rights are set");
457 return ERROR_JTAG_INIT_FAILED;
458 }
459
460 i = ioctl(device_handle, PPCLAIM);
461 if (i < 0)
462 {
463 LOG_ERROR("cannot claim device");
464 return ERROR_JTAG_INIT_FAILED;
465 }
466
467 i = IEEE1284_MODE_EPP;
468 i = ioctl(device_handle, PPSETMODE, & i);
469 if (i < 0)
470 {
471 LOG_ERROR(" cannot set compatible mode to device");
472 return ERROR_JTAG_INIT_FAILED;
473 }
474
475 control_port = 0x00;
476 i = ioctl(device_handle, PPWCONTROL, &control_port);
477
478 control_port = 0x04;
479 i = ioctl(device_handle, PPWCONTROL, &control_port);
480
481 #else
482 if (amt_jtagaccel_port == 0)
483 {
484 amt_jtagaccel_port = 0x378;
485 LOG_WARNING("No parport port specified, using default '0x378' (LPT1)");
486 }
487
488 #if PARPORT_USE_GIVEIO == 1
489 if (amt_jtagaccel_get_giveio_access() != 0) {
490 #else /* PARPORT_USE_GIVEIO */
491 if (ioperm(amt_jtagaccel_port, 5, 1) != 0) {
492 #endif /* PARPORT_USE_GIVEIO */
493 LOG_ERROR("missing privileges for direct i/o");
494 return ERROR_JTAG_INIT_FAILED;
495 }
496
497 /* prepare epp port */
498 /* clear timeout */
499 status_port = inb(amt_jtagaccel_port + 1);
500 outb(status_port | 0x1, amt_jtagaccel_port + 1);
501
502 /* reset epp port */
503 outb(0x00, amt_jtagaccel_port + 2);
504 outb(0x04, amt_jtagaccel_port + 2);
505 #endif
506
507 if (rtck_enabled)
508 {
509 /* set RTCK enable bit */
510 aw_control_fsm |= 0x02;
511 }
512
513 /* enable JTAG port */
514 aw_control_fsm |= 0x04;
515 AMT_AW(aw_control_fsm);
516
517 enum reset_types jtag_reset_config = jtag_get_reset_config();
518 if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
519 aw_control_rst &= ~0x8;
520 else
521 aw_control_rst |= 0x8;
522
523 if (jtag_reset_config & RESET_SRST_PUSH_PULL)
524 aw_control_rst &= ~0x2;
525 else
526 aw_control_rst |= 0x2;
527
528 amt_jtagaccel_reset(0, 0);
529
530 /* read status register */
531 AMT_AR(ar_status);
532 LOG_DEBUG("AR_STATUS: 0x%2.2x", ar_status);
533
534 return ERROR_OK;
535 }
536
537 static int amt_jtagaccel_quit(void)
538 {
539
540 return ERROR_OK;
541 }
542
543 COMMAND_HANDLER(amt_jtagaccel_handle_parport_port_command)
544 {
545 if (CMD_ARGC == 1)
546 {
547 /* only if the port wasn't overwritten by cmdline */
548 if (amt_jtagaccel_port == 0)
549 {
550 uint16_t port;
551 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port);
552 amt_jtagaccel_port = port;
553 }
554 else
555 {
556 LOG_ERROR("The parport port was already configured!");
557 return ERROR_FAIL;
558 }
559 }
560
561 command_print(CMD_CTX, "parport port = %u", amt_jtagaccel_port);
562
563 return ERROR_OK;
564 }
565
566 COMMAND_HANDLER(amt_jtagaccel_handle_rtck_command)
567 {
568 if (CMD_ARGC == 0)
569 {
570 command_print(CMD_CTX, "amt_jtagaccel RTCK feature %s", (rtck_enabled) ? "enabled" : "disabled");
571 return ERROR_OK;
572 }
573 else
574 {
575 if (strcmp(CMD_ARGV[0], "enabled") == 0)
576 {
577 rtck_enabled = 1;
578 }
579 else
580 {
581 rtck_enabled = 0;
582 }
583 }
584
585 return ERROR_OK;
586 }
587
588 static const struct command_registration amtjtagaccel_command_handlers[] = {
589 {
590 .name = "parport_port",
591 .handler = &amt_jtagaccel_handle_parport_port_command,
592 .mode = COMMAND_CONFIG,
593 .help = "configure or display the parallel port to use",
594 .usage = "[port_num]",
595 },
596 {
597 /**
598 * @todo Remove this "rtck" command; just use the standard
599 * mechanism to enable/disable adaptive clocking. First
600 * implement the standard mechanism and deprecate "rtck";
601 * after a year or so, it'll be safe to remove this.
602 */
603 .name = "rtck",
604 .handler = &amt_jtagaccel_handle_rtck_command,
605 .mode = COMMAND_CONFIG,
606 .help = "configure or display RTCK support",
607 .usage = "[enable|disable]",
608 },
609 COMMAND_REGISTRATION_DONE
610 };
611
612 struct jtag_interface amt_jtagaccel_interface = {
613 .name = "amt_jtagaccel",
614 .commands = amtjtagaccel_command_handlers,
615
616 .init = amt_jtagaccel_init,
617 .quit = amt_jtagaccel_quit,
618 .speed = amt_jtagaccel_speed,
619 .execute_queue = amt_jtagaccel_execute_queue,
620 };

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)