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

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)