1 /***************************************************************************
2 * Copyright (C) 2007 by Pavel Chromy *
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. *
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. *
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 ***************************************************************************/
28 #define INCLUDE_JTAG_INTERFACE_H
29 #include "interface.h"
30 #include "time_support.h"
34 /* PRESTO access library includes */
35 #if BUILD_PRESTO_FTD2XX == 1
37 #elif BUILD_PRESTO_LIBFTDI == 1
40 #error "BUG: either FTD2XX and LIBFTDI has to be used"
43 static int presto_jtag_speed(int speed
);
44 static int presto_jtag_khz(int khz
, int *jtag_speed
);
45 static int presto_jtag_speed_div(int speed
, int *khz
);
46 static int presto_jtag_register_commands(struct command_context_s
*cmd_ctx
);
47 static int presto_jtag_init(void);
48 static int presto_jtag_quit(void);
50 jtag_interface_t presto_interface
=
53 .execute_queue
= bitq_execute_queue
,
54 .speed
= presto_jtag_speed
,
55 .khz
= presto_jtag_khz
,
56 .speed_div
= presto_jtag_speed_div
,
57 .register_commands
= presto_jtag_register_commands
,
58 .init
= presto_jtag_init
,
59 .quit
= presto_jtag_quit
,
62 static int presto_bitq_out(int tms
, int tdi
, int tdo_req
);
63 static int presto_bitq_flush(void);
64 static int presto_bitq_sleep(unsigned long us
);
65 static int presto_bitq_reset(int trst
, int srst
);
66 static int presto_bitq_in_rdy(void);
67 static int presto_bitq_in(void);
69 static bitq_interface_t presto_bitq
=
71 .out
= presto_bitq_out
,
72 .flush
= presto_bitq_flush
,
73 .sleep
= presto_bitq_sleep
,
74 .reset
= presto_bitq_reset
,
75 .in_rdy
= presto_bitq_in_rdy
,
79 /* -------------------------------------------------------------------------- */
81 #define FT_DEVICE_NAME_LEN 64
82 #define FT_DEVICE_SERNUM_LEN 64
84 #define PRESTO_VID_PID 0x0403f1a0
85 #define PRESTO_VID (0x0403)
86 #define PRESTO_PID (0xf1a0)
88 #define BUFFER_SIZE (64*62)
90 typedef struct presto_s
92 #if BUILD_PRESTO_FTD2XX == 1
95 #elif BUILD_PRESTO_LIBFTDI == 1
96 struct ftdi_context ftdic
;
100 char serial
[FT_DEVICE_SERNUM_LEN
];
102 u8 buff_out
[BUFFER_SIZE
];
105 u8 buff_in
[BUFFER_SIZE
];
106 int buff_in_exp
; /* expected in buffer length */
107 int buff_in_len
; /* length of data received */
110 unsigned long total_out
;
111 unsigned long total_in
;
113 int jtag_tms
; /* last tms state */
114 int jtag_tck
; /* last tck state */
115 int jtag_rst
; /* last trst state */
124 static presto_t presto_state
;
125 static presto_t
*presto
= &presto_state
;
127 static u8 presto_init_seq
[] =
129 0x80, 0xA0, 0xA8, 0xB0, 0xC0, 0xE0
132 static int presto_write(u8
*buf
, u32 size
)
134 #if BUILD_PRESTO_FTD2XX == 1
136 if ((presto
->status
= FT_Write(presto
->handle
, buf
, size
, &ftbytes
)) != FT_OK
)
138 LOG_ERROR("FT_Write returned: %lu", presto
->status
);
139 return ERROR_JTAG_DEVICE_ERROR
;
142 #elif BUILD_PRESTO_LIBFTDI == 1
144 if ((presto
->retval
= ftdi_write_data(&presto
->ftdic
, buf
, size
)) < 0)
146 LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&presto
->ftdic
));
147 return ERROR_JTAG_DEVICE_ERROR
;
149 ftbytes
= presto
->retval
;
154 LOG_ERROR("couldn't write the requested number of bytes to PRESTO (%u < %u)", (u32
)ftbytes
, size
);
155 return ERROR_JTAG_DEVICE_ERROR
;
161 static int presto_read(u8
* buf
, u32 size
)
163 #if BUILD_PRESTO_FTD2XX == 1
165 if ((presto
->status
= FT_Read(presto
->handle
, buf
, size
, &ftbytes
)) != FT_OK
)
167 LOG_ERROR("FT_Read returned: %lu", presto
->status
);
168 return ERROR_JTAG_DEVICE_ERROR
;
171 #elif BUILD_PRESTO_LIBFTDI == 1
174 struct timeval timeout
, now
;
175 gettimeofday(&timeout
, NULL
);
176 timeval_add_time(&timeout
, 1, 0); /* one second timeout */
178 while (ftbytes
< size
)
180 if ((presto
->retval
= ftdi_read_data(&presto
->ftdic
, buf
+ ftbytes
, size
- ftbytes
)) < 0)
182 LOG_ERROR("ftdi_read_data: %s", ftdi_get_error_string(&presto
->ftdic
));
183 return ERROR_JTAG_DEVICE_ERROR
;
185 ftbytes
+= presto
->retval
;
187 gettimeofday(&now
, NULL
);
188 if ((now
.tv_sec
> timeout
.tv_sec
) || ((now
.tv_sec
== timeout
.tv_sec
) && (now
.tv_usec
> timeout
.tv_usec
)))
195 /* this is just a warning, there might have been timeout when detecting PRESTO, which is not fatal */
196 LOG_WARNING("couldn't read the requested number of bytes from PRESTO (%u < %u)", (u32
)ftbytes
, size
);
197 return ERROR_JTAG_DEVICE_ERROR
;
203 #if BUILD_PRESTO_FTD2XX == 1
204 static int presto_open_ftd2xx(char *req_serial
)
209 char devname
[FT_DEVICE_NAME_LEN
];
215 presto
->handle
= (FT_HANDLE
)INVALID_HANDLE_VALUE
;
218 /* Add non-standard Vid/Pid to the linux driver */
219 if ((presto
->status
= FT_SetVIDPID(PRESTO_VID
, PRESTO_PID
)) != FT_OK
)
221 LOG_ERROR("couldn't add PRESTO VID/PID");
226 if ((presto
->status
= FT_ListDevices(&numdevs
, NULL
, FT_LIST_NUMBER_ONLY
)) != FT_OK
)
228 LOG_ERROR("FT_ListDevices failed: %i", (int)presto
->status
);
229 return ERROR_JTAG_DEVICE_ERROR
;
232 LOG_DEBUG("FTDI devices available: %lu", numdevs
);
233 for (i
= 0; i
< numdevs
; i
++)
235 if ((presto
->status
= FT_Open(i
, &(presto
->handle
))) != FT_OK
)
237 /* this is not fatal, the device may be legitimately open by other process, hence debug message only */
238 LOG_DEBUG("FT_Open failed: %i", (int)presto
->status
);
241 LOG_DEBUG("FTDI device %i open", i
);
243 if ((presto
->status
= FT_GetDeviceInfo(presto
->handle
, &device
, &vidpid
,
244 presto
->serial
, devname
, NULL
)) == FT_OK
)
246 if (vidpid
== PRESTO_VID_PID
247 && (req_serial
== NULL
|| !strcmp(presto
->serial
, req_serial
)))
251 LOG_DEBUG("FT_GetDeviceInfo failed: %lu", presto
->status
);
253 LOG_DEBUG("FTDI device %i does not match, closing", i
);
254 FT_Close(presto
->handle
);
255 presto
->handle
= (FT_HANDLE
)INVALID_HANDLE_VALUE
;
258 if (presto
->handle
== (FT_HANDLE
)INVALID_HANDLE_VALUE
)
259 return ERROR_JTAG_DEVICE_ERROR
; /* presto not open, return */
261 if ((presto
->status
= FT_SetLatencyTimer(presto
->handle
, 1)) != FT_OK
)
262 return ERROR_JTAG_DEVICE_ERROR
;
265 if ((presto
->status
= FT_SetTimeouts(presto
->handle
, 100, 0)) != FT_OK
)
266 return ERROR_JTAG_DEVICE_ERROR
;
268 if ((presto
->status
= FT_Purge(presto
->handle
, FT_PURGE_TX
| FT_PURGE_RX
)) != FT_OK
)
269 return ERROR_JTAG_DEVICE_ERROR
;
272 if ((presto
->status
= FT_Write(presto
->handle
, &presto_data
, 1, &ftbytes
)) != FT_OK
)
273 return ERROR_JTAG_DEVICE_ERROR
;
275 /* delay between first write/read turnaround (after purge?) necessary under Linux for unknown reason,
276 probably a bug in library threading */
278 if ((presto
->status
= FT_Read(presto
->handle
, &presto_data
, 1, &ftbytes
)) != FT_OK
)
279 return ERROR_JTAG_DEVICE_ERROR
;
283 LOG_DEBUG("PRESTO reset");
285 if ((presto
->status
= FT_Purge(presto
->handle
, FT_PURGE_TX
| FT_PURGE_RX
)) != FT_OK
)
286 return ERROR_JTAG_DEVICE_ERROR
;
287 if ((presto
->status
= FT_SetBitMode(presto
->handle
, 0x80, 1)) != FT_OK
)
288 return ERROR_JTAG_DEVICE_ERROR
;
289 if ((presto
->status
= FT_SetBaudRate(presto
->handle
, 9600)) != FT_OK
)
290 return ERROR_JTAG_DEVICE_ERROR
;
293 for (i
= 0; i
< 4 * 62; i
++)
294 if ((presto
->status
=FT_Write(presto
->handle
, &presto_data
, 1, &ftbytes
)) != FT_OK
)
295 return ERROR_JTAG_DEVICE_ERROR
;
299 if ((presto
->status
= FT_SetBitMode(presto
->handle
, 0x00, 0)) != FT_OK
)
300 return ERROR_JTAG_DEVICE_ERROR
;
302 if ((presto
->status
= FT_Purge(presto
->handle
, FT_PURGE_TX
| FT_PURGE_RX
)) != FT_OK
)
303 return ERROR_JTAG_DEVICE_ERROR
;
306 if ((presto
->status
= FT_Write(presto
->handle
, &presto_data
, 1, &ftbytes
)) != FT_OK
)
307 return ERROR_JTAG_DEVICE_ERROR
;
309 /* delay between first write/read turnaround (after purge?) necessary under Linux for unknown reason,
310 probably a bug in library threading */
312 if ((presto
->status
= FT_Read(presto
->handle
, &presto_data
, 1, &ftbytes
)) != FT_OK
)
313 return ERROR_JTAG_DEVICE_ERROR
;
317 LOG_DEBUG("PRESTO not responding");
318 return ERROR_JTAG_DEVICE_ERROR
;
322 if ((presto
->status
= FT_SetTimeouts(presto
->handle
, 0, 0)) != FT_OK
)
323 return ERROR_JTAG_DEVICE_ERROR
;
326 presto
->status
= FT_Write(presto
->handle
, &presto_init_seq
, sizeof(presto_init_seq
), &ftbytes
);
327 if (presto
->status
!= FT_OK
|| ftbytes
!= sizeof(presto_init_seq
))
328 return ERROR_JTAG_DEVICE_ERROR
;
333 #elif BUILD_PRESTO_LIBFTDI == 1
334 static int presto_open_libftdi(char *req_serial
)
338 LOG_DEBUG("searching for PRESTO using libftdi");
340 /* initialize FTDI context structure */
341 if (ftdi_init(&presto
->ftdic
) < 0)
343 LOG_ERROR("unable to init libftdi: %s", presto
->ftdic
.error_str
);
344 return ERROR_JTAG_DEVICE_ERROR
;
347 /* context, vendor id, product id */
348 if (ftdi_usb_open_desc(&presto
->ftdic
, PRESTO_VID
, PRESTO_PID
, NULL
, req_serial
) < 0)
350 LOG_ERROR("unable to open PRESTO: %s", presto
->ftdic
.error_str
);
351 return ERROR_JTAG_DEVICE_ERROR
;
354 if (ftdi_usb_reset(&presto
->ftdic
) < 0)
356 LOG_ERROR("unable to reset PRESTO device");
357 return ERROR_JTAG_DEVICE_ERROR
;
360 if (ftdi_set_latency_timer(&presto
->ftdic
, 1) < 0)
362 LOG_ERROR("unable to set latency timer");
363 return ERROR_JTAG_DEVICE_ERROR
;
366 if (ftdi_usb_purge_buffers(&presto
->ftdic
) < 0)
368 LOG_ERROR("unable to purge PRESTO buffers");
369 return ERROR_JTAG_DEVICE_ERROR
;
373 if (presto_write(&presto_data
, 1) != ERROR_OK
)
375 LOG_ERROR("error writing to PRESTO");
376 return ERROR_JTAG_DEVICE_ERROR
;
379 if (presto_read(&presto_data
, 1) != ERROR_OK
)
381 LOG_DEBUG("no response from PRESTO, retrying");
383 if (ftdi_usb_purge_buffers(&presto
->ftdic
) < 0)
384 return ERROR_JTAG_DEVICE_ERROR
;
387 if (presto_write(&presto_data
, 1) != ERROR_OK
)
388 return ERROR_JTAG_DEVICE_ERROR
;
390 if (presto_read(&presto_data
, 1) != ERROR_OK
)
392 LOG_ERROR("no response from PRESTO, giving up");
393 return ERROR_JTAG_DEVICE_ERROR
;
397 if (presto_write(presto_init_seq
, sizeof(presto_init_seq
)) != ERROR_OK
)
399 LOG_ERROR("error writing PRESTO init sequence");
400 return ERROR_JTAG_DEVICE_ERROR
;
405 #endif /* BUILD_PRESTO_LIBFTDI == 1 */
407 static int presto_open(char *req_serial
)
409 presto
->buff_out_pos
=0;
410 presto
->buff_in_pos
=0;
411 presto
->buff_in_len
=0;
412 presto
->buff_in_exp
=0;
420 presto
->jtag_tdi_data
=0;
421 presto
->jtag_tdi_count
=0;
423 presto
->jtag_speed
=0;
425 #if BUILD_PRESTO_FTD2XX == 1
426 return presto_open_ftd2xx(req_serial
);
427 #elif BUILD_PRESTO_LIBFTDI == 1
428 return presto_open_libftdi(req_serial
);
432 static int presto_close(void)
435 int result
= ERROR_OK
;
437 #if BUILD_PRESTO_FTD2XX == 1
438 unsigned long ftbytes
;
440 if (presto
->handle
== (FT_HANDLE
)INVALID_HANDLE_VALUE
)
443 presto
->status
= FT_Purge(presto
->handle
, FT_PURGE_TX
| FT_PURGE_RX
);
444 if (presto
->status
!= FT_OK
)
445 result
= ERROR_JTAG_DEVICE_ERROR
;
447 presto
->status
= FT_Write(presto
->handle
, &presto_init_seq
, sizeof(presto_init_seq
), &ftbytes
);
448 if (presto
->status
!= FT_OK
|| ftbytes
!= sizeof(presto_init_seq
))
449 result
= ERROR_JTAG_DEVICE_ERROR
;
451 if ((presto
->status
= FT_SetLatencyTimer(presto
->handle
, 16)) != FT_OK
)
452 result
= ERROR_JTAG_DEVICE_ERROR
;
454 if ((presto
->status
= FT_Close(presto
->handle
)) != FT_OK
)
455 result
= ERROR_JTAG_DEVICE_ERROR
;
457 presto
->handle
= (FT_HANDLE
)INVALID_HANDLE_VALUE
;
459 #elif BUILD_PRESTO_LIBFTDI == 1
461 if ((presto
->retval
= ftdi_write_data(&presto
->ftdic
, presto_init_seq
, sizeof(presto_init_seq
))) != sizeof(presto_init_seq
))
462 result
= ERROR_JTAG_DEVICE_ERROR
;
464 if ((presto
->retval
= ftdi_set_latency_timer(&presto
->ftdic
, 16)) < 0)
465 result
= ERROR_JTAG_DEVICE_ERROR
;
467 if ((presto
->retval
= ftdi_usb_close(&presto
->ftdic
)) < 0)
468 result
= ERROR_JTAG_DEVICE_ERROR
;
470 ftdi_deinit(&presto
->ftdic
);
476 static int presto_flush(void)
478 if (presto
->buff_out_pos
== 0)
481 #if BUILD_PRESTO_FTD2XX == 1
482 if (presto
->status
!= FT_OK
)
483 #elif BUILD_PRESTO_LIBFTDI == 1
484 if (presto
->retval
< 0)
487 LOG_DEBUG("error in previous communication, canceling I/O operation");
488 return ERROR_JTAG_DEVICE_ERROR
;
491 if (presto_write(presto
->buff_out
, presto
->buff_out_pos
) != ERROR_OK
)
493 presto
->buff_out_pos
= 0;
494 return ERROR_JTAG_DEVICE_ERROR
;
497 presto
->total_out
+= presto
->buff_out_pos
;
498 presto
->buff_out_pos
= 0;
500 if (presto
->buff_in_exp
== 0)
503 presto
->buff_in_pos
= 0;
504 presto
->buff_in_len
= 0;
506 if (presto_read(presto
->buff_in
, presto
->buff_in_exp
) != ERROR_OK
)
508 presto
->buff_in_exp
= 0;
509 return ERROR_JTAG_DEVICE_ERROR
;
512 presto
->total_in
+= presto
->buff_in_exp
;
513 presto
->buff_in_len
= presto
->buff_in_exp
;
514 presto
->buff_in_exp
= 0;
519 static int presto_sendbyte(int data
)
521 if (data
== EOF
) return presto_flush();
523 if (presto
->buff_out_pos
< BUFFER_SIZE
)
525 presto
->buff_out
[presto
->buff_out_pos
++] = (u8
)data
;
526 if (((data
& 0xC0) == 0x40) || ((data
& 0xD0)== 0xD0))
527 presto
->buff_in_exp
++;
530 return ERROR_JTAG_DEVICE_ERROR
;
532 #if BUILD_PRESTO_FTD2XX == 1
533 if (presto
->buff_out_pos
>= BUFFER_SIZE
)
534 #elif BUILD_PRESTO_LIBFTDI == 1
535 /* libftdi does not do background read, be sure that USB IN buffer does not overflow (128 bytes only!) */
536 if (presto
->buff_out_pos
>= BUFFER_SIZE
|| presto
->buff_in_exp
==128)
538 return presto_flush();
544 static int presto_getbyte(void)
546 if (presto
->buff_in_pos
< presto
->buff_in_len
)
547 return presto
->buff_in
[presto
->buff_in_pos
++];
549 if (presto
->buff_in_exp
== 0)
552 if (presto_flush() != ERROR_OK
)
555 if (presto
->buff_in_pos
<presto
->buff_in_len
)
556 return presto
->buff_in
[presto
->buff_in_pos
++];
562 /* -------------------------------------------------------------------------- */
564 static int presto_tdi_flush(void)
566 if (presto
->jtag_tdi_count
== 0)
569 if (presto
->jtag_tck
== 0)
571 LOG_ERROR("BUG: unexpected TAP condition, TCK low");
575 presto
->jtag_tdi_data
|= (presto
->jtag_tdi_count
- 1) << 4;
576 presto_sendbyte(presto
->jtag_tdi_data
);
577 presto
->jtag_tdi_count
= 0;
578 presto
->jtag_tdi_data
= 0;
583 static int presto_tck_idle(void)
585 if (presto
->jtag_tck
== 1)
587 presto_sendbyte(0xCA);
588 presto
->jtag_tck
= 0;
594 /* -------------------------------------------------------------------------- */
596 static int presto_bitq_out(int tms
, int tdi
, int tdo_req
)
601 if (presto
->jtag_tck
== 0)
603 presto_sendbyte(0xA4); /* LED idicator - JTAG active */
605 else if (presto
->jtag_speed
== 0 && !tdo_req
&& tms
== presto
->jtag_tms
)
607 presto
->jtag_tdi_data
|= (tdi
!= 0) << presto
->jtag_tdi_count
;
609 if (++presto
->jtag_tdi_count
== 4)
617 cmd
= tdi
? 0xCB : 0xCA;
618 presto_sendbyte(cmd
);
620 if (tms
!= presto
->jtag_tms
)
622 presto_sendbyte((tms
? 0xEC : 0xE8) | (presto
->jtag_rst
? 0x02 : 0));
623 presto
->jtag_tms
= tms
;
626 /* delay with TCK low */
627 for (i
=presto
->jtag_speed
; i
>1; i
--)
628 presto_sendbyte(cmd
);
631 presto_sendbyte(cmd
| (tdo_req
? 0x10 : 0));
633 /* delay with TCK high */
634 for (i
=presto
->jtag_speed
; i
>1; i
--)
635 presto_sendbyte(cmd
);
637 presto
->jtag_tck
= 1;
642 static int presto_bitq_flush(void)
647 presto_sendbyte(0xA0); /* LED idicator - JTAG idle */
649 return presto_flush();
652 static int presto_bitq_in_rdy(void)
654 if (presto
->buff_in_pos
>=presto
->buff_in_len
)
656 return presto
->buff_in_len
-presto
->buff_in_pos
;
659 static int presto_bitq_in(void)
661 if (presto
->buff_in_pos
>=presto
->buff_in_len
)
663 if (presto
->buff_in
[presto
->buff_in_pos
++]&0x08) return 1;
667 static int presto_bitq_sleep(unsigned long us
)
681 waits
= us
/ 170 + 2;
683 presto_sendbyte(0x80);
688 static int presto_bitq_reset(int trst
, int srst
)
693 /* add a delay after possible TCK transition */
694 presto_sendbyte(0x80);
695 presto_sendbyte(0x80);
697 presto
->jtag_rst
= trst
|| srst
;
698 presto_sendbyte((presto
->jtag_rst
? 0xEA : 0xE8) | (presto
->jtag_tms
? 0x04 : 0));
703 /* -------------------------------------------------------------------------- */
705 static int presto_jtag_khz(int khz
, int *jtag_speed
)
710 return ERROR_INVALID_ARGUMENTS
;
713 if (khz
>= 3000) *jtag_speed
= 0;
714 else *jtag_speed
= (1000+khz
-1)/khz
;
719 static int presto_jtag_speed_div(int speed
, int *khz
)
721 if ((speed
< 0) || (speed
> 1000))
724 return ERROR_INVALID_ARGUMENTS
;
727 if (speed
== 0) *khz
= 3000;
728 else *khz
= 1000/speed
;
733 static int presto_jtag_speed(int speed
)
737 if (presto_jtag_speed_div(speed
, &khz
))
739 return ERROR_INVALID_ARGUMENTS
;
742 presto
->jtag_speed
= speed
;
745 LOG_INFO("setting speed to %d, max. TCK freq. is %d MHz", speed
, khz
/1000);
747 LOG_INFO("setting speed to %d, max. TCK freq. is %d kHz", speed
, khz
);
752 static char *presto_serial
;
754 static int presto_handle_serial_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
760 presto_serial
= strdup(args
[0]);
764 LOG_ERROR("expected exactly one argument to presto_serial <serial-number>");
770 static int presto_jtag_register_commands(struct command_context_s
*cmd_ctx
)
772 register_command(cmd_ctx
, NULL
, "presto_serial", presto_handle_serial_command
,
773 COMMAND_CONFIG
, NULL
);
777 static int presto_jtag_init(void)
779 if (presto_open(presto_serial
) != ERROR_OK
)
782 if (presto_serial
!= NULL
)
783 LOG_ERROR("Cannot open PRESTO, serial number '%s'", presto_serial
);
785 LOG_ERROR("Cannot open PRESTO");
786 return ERROR_JTAG_INIT_FAILED
;
788 LOG_INFO("PRESTO open, serial number '%s'", presto
->serial
);
790 /* use JTAG speed setting from configuration file */
791 presto_jtag_speed(jtag_speed
);
793 bitq_interface
= &presto_bitq
;
797 static int presto_jtag_quit(void)
801 LOG_INFO("PRESTO closed");
806 presto_serial
= NULL
;
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)