jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / flash / nor / stmsmi.c
1 /***************************************************************************
2 * Copyright (C) 2010 by Antonio Borneo <borneo.antonio@gmail.com> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
16 ***************************************************************************/
17
18 /* STM Serial Memory Interface (SMI) controller is a SPI bus controller
19 * specifically designed for SPI memories.
20 * Only SPI "mode 3" (CPOL=1 and CPHA=1) is supported.
21 * Two working modes are available:
22 * - SW mode: the SPI is controlled by SW. Any custom commands can be sent
23 * on the bus.
24 * - HW mode: the SPI but is under SMI control. Memory content is directly
25 * accessible in CPU memory space. CPU can read, write and execute memory
26 * content. */
27
28 /* ATTENTION:
29 * To have flash memory mapped in CPU memory space, the SMI controller
30 * have to be in "HW mode". This requires following constraints:
31 * 1) The command "reset init" have to initialize SMI controller and put
32 * it in HW mode;
33 * 2) every command in this file have to return to prompt in HW mode. */
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38
39 #include "imp.h"
40 #include "spi.h"
41 #include <jtag/jtag.h>
42 #include <helper/time_support.h>
43
44 #define SMI_READ_REG(a) (_SMI_READ_REG(a))
45 #define _SMI_READ_REG(a) \
46 { \
47 int __a; \
48 uint32_t __v; \
49 \
50 __a = target_read_u32(target, io_base + (a), &__v); \
51 if (__a != ERROR_OK) \
52 return __a; \
53 __v; \
54 }
55
56 #define SMI_WRITE_REG(a, v) \
57 { \
58 int __r; \
59 \
60 __r = target_write_u32(target, io_base + (a), (v)); \
61 if (__r != ERROR_OK) \
62 return __r; \
63 }
64
65 #define SMI_POLL_TFF(timeout) \
66 { \
67 int __r; \
68 \
69 __r = poll_tff(target, io_base, timeout); \
70 if (__r != ERROR_OK) \
71 return __r; \
72 }
73
74 #define SMI_SET_SW_MODE() SMI_WRITE_REG(SMI_CR1, \
75 SMI_READ_REG(SMI_CR1) | SMI_SW_MODE)
76 #define SMI_SET_HWWB_MODE() SMI_WRITE_REG(SMI_CR1, \
77 (SMI_READ_REG(SMI_CR1) | SMI_WB_MODE) & ~SMI_SW_MODE)
78 #define SMI_SET_HW_MODE() SMI_WRITE_REG(SMI_CR1, \
79 SMI_READ_REG(SMI_CR1) & ~(SMI_SW_MODE | SMI_WB_MODE))
80 #define SMI_CLEAR_TFF() SMI_WRITE_REG(SMI_SR, ~SMI_TFF)
81
82 #define SMI_BANK_SIZE (0x01000000)
83
84 #define SMI_CR1 (0x00) /* Control register 1 */
85 #define SMI_CR2 (0x04) /* Control register 2 */
86 #define SMI_SR (0x08) /* Status register */
87 #define SMI_TR (0x0c) /* TX */
88 #define SMI_RR (0x10) /* RX */
89
90 /* fields in SMI_CR1 */
91 #define SMI_SW_MODE 0x10000000 /* set to enable SW Mode */
92 #define SMI_WB_MODE 0x20000000 /* Write Burst Mode */
93
94 /* fields in SMI_CR2 */
95 #define SMI_TX_LEN_1 0x00000001 /* data length = 1 byte */
96 #define SMI_TX_LEN_4 0x00000004 /* data length = 4 byte */
97 #define SMI_RX_LEN_3 0x00000030 /* data length = 3 byte */
98 #define SMI_SEND 0x00000080 /* Send data */
99 #define SMI_RSR 0x00000400 /* reads status reg */
100 #define SMI_WE 0x00000800 /* Write Enable */
101 #define SMI_SEL_BANK0 0x00000000 /* Select Bank0 */
102 #define SMI_SEL_BANK1 0x00001000 /* Select Bank1 */
103 #define SMI_SEL_BANK2 0x00002000 /* Select Bank2 */
104 #define SMI_SEL_BANK3 0x00003000 /* Select Bank3 */
105
106 /* fields in SMI_SR */
107 #define SMI_TFF 0x00000100 /* Transfer Finished Flag */
108
109 /* Commands */
110 #define SMI_READ_ID 0x0000009F /* Read Flash Identification */
111
112 /* Timeout in ms */
113 #define SMI_CMD_TIMEOUT (100)
114 #define SMI_PROBE_TIMEOUT (100)
115 #define SMI_MAX_TIMEOUT (3000)
116
117 struct stmsmi_flash_bank {
118 int probed;
119 uint32_t io_base;
120 uint32_t bank_num;
121 const struct flash_device *dev;
122 };
123
124 struct stmsmi_target {
125 char *name;
126 uint32_t tap_idcode;
127 uint32_t smi_base;
128 uint32_t io_base;
129 };
130
131 static const struct stmsmi_target target_devices[] = {
132 /* name, tap_idcode, smi_base, io_base */
133 { "SPEAr3xx/6xx", 0x07926041, 0xf8000000, 0xfc000000 },
134 { "STR75x", 0x4f1f0041, 0x80000000, 0x90000000 },
135 { NULL, 0, 0, 0 }
136 };
137
138 FLASH_BANK_COMMAND_HANDLER(stmsmi_flash_bank_command)
139 {
140 struct stmsmi_flash_bank *stmsmi_info;
141
142 LOG_DEBUG("%s", __func__);
143
144 if (CMD_ARGC < 6)
145 return ERROR_COMMAND_SYNTAX_ERROR;
146
147 stmsmi_info = malloc(sizeof(struct stmsmi_flash_bank));
148 if (stmsmi_info == NULL) {
149 LOG_ERROR("not enough memory");
150 return ERROR_FAIL;
151 }
152
153 bank->driver_priv = stmsmi_info;
154 stmsmi_info->probed = 0;
155
156 return ERROR_OK;
157 }
158
159 /* Poll transmit finished flag */
160 /* timeout in ms */
161 static int poll_tff(struct target *target, uint32_t io_base, int timeout)
162 {
163 int64_t endtime;
164
165 if (SMI_READ_REG(SMI_SR) & SMI_TFF)
166 return ERROR_OK;
167
168 endtime = timeval_ms() + timeout;
169 do {
170 alive_sleep(1);
171 if (SMI_READ_REG(SMI_SR) & SMI_TFF)
172 return ERROR_OK;
173 } while (timeval_ms() < endtime);
174
175 LOG_ERROR("Timeout while polling TFF");
176 return ERROR_FLASH_OPERATION_FAILED;
177 }
178
179 /* Read the status register of the external SPI flash chip.
180 * The operation is triggered by setting SMI_RSR bit.
181 * SMI sends the proper SPI command (0x05) and returns value in SMI_SR */
182 static int read_status_reg(struct flash_bank *bank, uint32_t *status)
183 {
184 struct target *target = bank->target;
185 struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
186 uint32_t io_base = stmsmi_info->io_base;
187
188 /* clear transmit finished flag */
189 SMI_CLEAR_TFF();
190
191 /* Read status */
192 SMI_WRITE_REG(SMI_CR2, stmsmi_info->bank_num | SMI_RSR);
193
194 /* Poll transmit finished flag */
195 SMI_POLL_TFF(SMI_CMD_TIMEOUT);
196
197 /* clear transmit finished flag */
198 SMI_CLEAR_TFF();
199
200 *status = SMI_READ_REG(SMI_SR) & 0x0000ffff;
201
202 /* clean-up SMI_CR2 */
203 SMI_WRITE_REG(SMI_CR2, 0); /* AB: Required ? */
204
205 return ERROR_OK;
206 }
207
208 /* check for WIP (write in progress) bit in status register */
209 /* timeout in ms */
210 static int wait_till_ready(struct flash_bank *bank, int timeout)
211 {
212 uint32_t status;
213 int retval;
214 int64_t endtime;
215
216 endtime = timeval_ms() + timeout;
217 do {
218 /* read flash status register */
219 retval = read_status_reg(bank, &status);
220 if (retval != ERROR_OK)
221 return retval;
222
223 if ((status & SPIFLASH_BSY_BIT) == 0)
224 return ERROR_OK;
225 alive_sleep(1);
226 } while (timeval_ms() < endtime);
227
228 LOG_ERROR("timeout");
229 return ERROR_FAIL;
230 }
231
232 /* Send "write enable" command to SPI flash chip.
233 * The operation is triggered by setting SMI_WE bit, and SMI sends
234 * the proper SPI command (0x06) */
235 static int smi_write_enable(struct flash_bank *bank)
236 {
237 struct target *target = bank->target;
238 struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
239 uint32_t io_base = stmsmi_info->io_base;
240 uint32_t status;
241 int retval;
242
243 /* Enter in HW mode */
244 SMI_SET_HW_MODE(); /* AB: is this correct ?*/
245
246 /* clear transmit finished flag */
247 SMI_CLEAR_TFF();
248
249 /* Send write enable command */
250 SMI_WRITE_REG(SMI_CR2, stmsmi_info->bank_num | SMI_WE);
251
252 /* Poll transmit finished flag */
253 SMI_POLL_TFF(SMI_CMD_TIMEOUT);
254
255 /* read flash status register */
256 retval = read_status_reg(bank, &status);
257 if (retval != ERROR_OK)
258 return retval;
259
260 /* Check write enabled */
261 if ((status & SPIFLASH_WE_BIT) == 0) {
262 LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status);
263 return ERROR_FAIL;
264 }
265
266 return ERROR_OK;
267 }
268
269 static uint32_t erase_command(struct stmsmi_flash_bank *stmsmi_info,
270 uint32_t offset)
271 {
272 uint8_t cmd_bytes[] = {
273 stmsmi_info->dev->erase_cmd,
274 offset >> 16,
275 offset >> 8,
276 offset
277 };
278
279 return le_to_h_u32(cmd_bytes);
280 }
281
282 static int smi_erase_sector(struct flash_bank *bank, int sector)
283 {
284 struct target *target = bank->target;
285 struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
286 uint32_t io_base = stmsmi_info->io_base;
287 uint32_t cmd;
288 int retval;
289
290 retval = smi_write_enable(bank);
291 if (retval != ERROR_OK)
292 return retval;
293
294 /* Switch to SW mode to send sector erase command */
295 SMI_SET_SW_MODE();
296
297 /* clear transmit finished flag */
298 SMI_CLEAR_TFF();
299
300 /* send SPI command "block erase" */
301 cmd = erase_command(stmsmi_info, bank->sectors[sector].offset);
302 SMI_WRITE_REG(SMI_TR, cmd);
303 SMI_WRITE_REG(SMI_CR2, stmsmi_info->bank_num | SMI_SEND | SMI_TX_LEN_4);
304
305 /* Poll transmit finished flag */
306 SMI_POLL_TFF(SMI_CMD_TIMEOUT);
307
308 /* poll WIP for end of self timed Sector Erase cycle */
309 retval = wait_till_ready(bank, SMI_MAX_TIMEOUT);
310 if (retval != ERROR_OK)
311 return retval;
312
313 return ERROR_OK;
314 }
315
316 static int stmsmi_erase(struct flash_bank *bank, int first, int last)
317 {
318 struct target *target = bank->target;
319 struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
320 uint32_t io_base = stmsmi_info->io_base;
321 int retval = ERROR_OK;
322 int sector;
323
324 LOG_DEBUG("%s: from sector %d to sector %d", __func__, first, last);
325
326 if (target->state != TARGET_HALTED) {
327 LOG_ERROR("Target not halted");
328 return ERROR_TARGET_NOT_HALTED;
329 }
330
331 if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
332 LOG_ERROR("Flash sector invalid");
333 return ERROR_FLASH_SECTOR_INVALID;
334 }
335
336 if (!(stmsmi_info->probed)) {
337 LOG_ERROR("Flash bank not probed");
338 return ERROR_FLASH_BANK_NOT_PROBED;
339 }
340
341 for (sector = first; sector <= last; sector++) {
342 if (bank->sectors[sector].is_protected) {
343 LOG_ERROR("Flash sector %d protected", sector);
344 return ERROR_FAIL;
345 }
346 }
347
348 if (stmsmi_info->dev->erase_cmd == 0x00)
349 return ERROR_FLASH_OPER_UNSUPPORTED;
350
351 for (sector = first; sector <= last; sector++) {
352 retval = smi_erase_sector(bank, sector);
353 if (retval != ERROR_OK)
354 break;
355 keep_alive();
356 }
357
358 /* Switch to HW mode before return to prompt */
359 SMI_SET_HW_MODE();
360 return retval;
361 }
362
363 static int stmsmi_protect(struct flash_bank *bank, int set,
364 int first, int last)
365 {
366 int sector;
367
368 for (sector = first; sector <= last; sector++)
369 bank->sectors[sector].is_protected = set;
370 return ERROR_OK;
371 }
372
373 static int smi_write_buffer(struct flash_bank *bank, const uint8_t *buffer,
374 uint32_t address, uint32_t len)
375 {
376 struct target *target = bank->target;
377 struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
378 uint32_t io_base = stmsmi_info->io_base;
379 int retval;
380
381 LOG_DEBUG("%s: address=0x%08" PRIx32 " len=0x%08" PRIx32,
382 __func__, address, len);
383
384 retval = smi_write_enable(bank);
385 if (retval != ERROR_OK)
386 return retval;
387
388 /* HW mode, write burst mode */
389 SMI_SET_HWWB_MODE();
390
391 retval = target_write_buffer(target, address, len, buffer);
392 if (retval != ERROR_OK)
393 return retval;
394
395 return ERROR_OK;
396 }
397
398 static int stmsmi_write(struct flash_bank *bank, const uint8_t *buffer,
399 uint32_t offset, uint32_t count)
400 {
401 struct target *target = bank->target;
402 struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
403 uint32_t io_base = stmsmi_info->io_base;
404 uint32_t cur_count, page_size, page_offset;
405 int sector;
406 int retval = ERROR_OK;
407
408 LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
409 __func__, offset, count);
410
411 if (target->state != TARGET_HALTED) {
412 LOG_ERROR("Target not halted");
413 return ERROR_TARGET_NOT_HALTED;
414 }
415
416 if (offset + count > stmsmi_info->dev->size_in_bytes) {
417 LOG_WARNING("Write pasts end of flash. Extra data discarded.");
418 count = stmsmi_info->dev->size_in_bytes - offset;
419 }
420
421 /* Check sector protection */
422 for (sector = 0; sector < bank->num_sectors; sector++) {
423 /* Start offset in or before this sector? */
424 /* End offset in or behind this sector? */
425 if ((offset <
426 (bank->sectors[sector].offset + bank->sectors[sector].size))
427 && ((offset + count - 1) >= bank->sectors[sector].offset)
428 && bank->sectors[sector].is_protected) {
429 LOG_ERROR("Flash sector %d protected", sector);
430 return ERROR_FAIL;
431 }
432 }
433
434 /* if no valid page_size, use reasonable default */
435 page_size = stmsmi_info->dev->pagesize ?
436 stmsmi_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
437
438 /* unaligned buffer head */
439 if (count > 0 && (offset & 3) != 0) {
440 cur_count = 4 - (offset & 3);
441 if (cur_count > count)
442 cur_count = count;
443 retval = smi_write_buffer(bank, buffer, bank->base + offset,
444 cur_count);
445 if (retval != ERROR_OK)
446 goto err;
447 offset += cur_count;
448 buffer += cur_count;
449 count -= cur_count;
450 }
451
452 page_offset = offset % page_size;
453 /* central part, aligned words */
454 while (count >= 4) {
455 /* clip block at page boundary */
456 if (page_offset + count > page_size)
457 cur_count = page_size - page_offset;
458 else
459 cur_count = count & ~3;
460
461 retval = smi_write_buffer(bank, buffer, bank->base + offset,
462 cur_count);
463 if (retval != ERROR_OK)
464 goto err;
465
466 page_offset = 0;
467 buffer += cur_count;
468 offset += cur_count;
469 count -= cur_count;
470
471 keep_alive();
472 }
473
474 /* buffer tail */
475 if (count > 0)
476 retval = smi_write_buffer(bank, buffer, bank->base + offset, count);
477
478 err:
479 /* Switch to HW mode before return to prompt */
480 SMI_SET_HW_MODE();
481 return retval;
482 }
483
484 /* Return ID of flash device */
485 /* On exit, SW mode is kept */
486 static int read_flash_id(struct flash_bank *bank, uint32_t *id)
487 {
488 struct target *target = bank->target;
489 struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
490 uint32_t io_base = stmsmi_info->io_base;
491 int retval;
492
493 if (target->state != TARGET_HALTED) {
494 LOG_ERROR("Target not halted");
495 return ERROR_TARGET_NOT_HALTED;
496 }
497
498 /* poll WIP */
499 retval = wait_till_ready(bank, SMI_PROBE_TIMEOUT);
500 if (retval != ERROR_OK)
501 return retval;
502
503 /* enter in SW mode */
504 SMI_SET_SW_MODE();
505
506 /* clear transmit finished flag */
507 SMI_CLEAR_TFF();
508
509 /* Send SPI command "read ID" */
510 SMI_WRITE_REG(SMI_TR, SMI_READ_ID);
511 SMI_WRITE_REG(SMI_CR2,
512 stmsmi_info->bank_num | SMI_SEND | SMI_RX_LEN_3 | SMI_TX_LEN_1);
513
514 /* Poll transmit finished flag */
515 SMI_POLL_TFF(SMI_CMD_TIMEOUT);
516
517 /* clear transmit finished flag */
518 SMI_CLEAR_TFF();
519
520 /* read ID from Receive Register */
521 *id = SMI_READ_REG(SMI_RR) & 0x00ffffff;
522 return ERROR_OK;
523 }
524
525 static int stmsmi_probe(struct flash_bank *bank)
526 {
527 struct target *target = bank->target;
528 struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
529 uint32_t io_base, sectorsize;
530 struct flash_sector *sectors;
531 uint32_t id = 0; /* silence uninitialized warning */
532 const struct stmsmi_target *target_device;
533 int retval;
534
535 if (stmsmi_info->probed)
536 free(bank->sectors);
537 stmsmi_info->probed = 0;
538
539 for (target_device = target_devices ; target_device->name ; ++target_device)
540 if (target_device->tap_idcode == target->tap->idcode)
541 break;
542 if (!target_device->name) {
543 LOG_ERROR("Device ID 0x%" PRIx32 " is not known as SMI capable",
544 target->tap->idcode);
545 return ERROR_FAIL;
546 }
547
548 switch (bank->base - target_device->smi_base) {
549 case 0:
550 stmsmi_info->bank_num = SMI_SEL_BANK0;
551 break;
552 case SMI_BANK_SIZE:
553 stmsmi_info->bank_num = SMI_SEL_BANK1;
554 break;
555 case 2*SMI_BANK_SIZE:
556 stmsmi_info->bank_num = SMI_SEL_BANK2;
557 break;
558 case 3*SMI_BANK_SIZE:
559 stmsmi_info->bank_num = SMI_SEL_BANK3;
560 break;
561 default:
562 LOG_ERROR("Invalid SMI base address " TARGET_ADDR_FMT, bank->base);
563 return ERROR_FAIL;
564 }
565 io_base = target_device->io_base;
566 stmsmi_info->io_base = io_base;
567
568 LOG_DEBUG("Valid SMI on device %s at address " TARGET_ADDR_FMT,
569 target_device->name, bank->base);
570
571 /* read and decode flash ID; returns in SW mode */
572 retval = read_flash_id(bank, &id);
573 SMI_SET_HW_MODE();
574 if (retval != ERROR_OK)
575 return retval;
576
577 stmsmi_info->dev = NULL;
578 for (const struct flash_device *p = flash_devices; p->name ; p++)
579 if (p->device_id == id) {
580 stmsmi_info->dev = p;
581 break;
582 }
583
584 if (!stmsmi_info->dev) {
585 LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id);
586 return ERROR_FAIL;
587 }
588
589 LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")",
590 stmsmi_info->dev->name, stmsmi_info->dev->device_id);
591
592 /* Set correct size value */
593 bank->size = stmsmi_info->dev->size_in_bytes;
594 if (bank->size <= (1UL << 16))
595 LOG_WARNING("device needs 2-byte addresses - not implemented");
596 if (bank->size > (1UL << 24))
597 LOG_WARNING("device needs paging or 4-byte addresses - not implemented");
598
599 /* if no sectors, treat whole bank as single sector */
600 sectorsize = stmsmi_info->dev->sectorsize ?
601 stmsmi_info->dev->sectorsize : stmsmi_info->dev->size_in_bytes;
602
603 /* create and fill sectors array */
604 bank->num_sectors =
605 stmsmi_info->dev->size_in_bytes / sectorsize;
606 sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
607 if (sectors == NULL) {
608 LOG_ERROR("not enough memory");
609 return ERROR_FAIL;
610 }
611
612 for (int sector = 0; sector < bank->num_sectors; sector++) {
613 sectors[sector].offset = sector * sectorsize;
614 sectors[sector].size = sectorsize;
615 sectors[sector].is_erased = -1;
616 sectors[sector].is_protected = 1;
617 }
618
619 bank->sectors = sectors;
620 stmsmi_info->probed = 1;
621 return ERROR_OK;
622 }
623
624 static int stmsmi_auto_probe(struct flash_bank *bank)
625 {
626 struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
627 if (stmsmi_info->probed)
628 return ERROR_OK;
629 return stmsmi_probe(bank);
630 }
631
632 static int stmsmi_protect_check(struct flash_bank *bank)
633 {
634 /* Nothing to do. Protection is only handled in SW. */
635 return ERROR_OK;
636 }
637
638 static int get_stmsmi_info(struct flash_bank *bank, char *buf, int buf_size)
639 {
640 struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
641
642 if (!(stmsmi_info->probed)) {
643 snprintf(buf, buf_size,
644 "\nSMI flash bank not probed yet\n");
645 return ERROR_OK;
646 }
647
648 snprintf(buf, buf_size, "\nSMI flash information:\n"
649 " Device \'%s\' (ID 0x%08" PRIx32 ")\n",
650 stmsmi_info->dev->name, stmsmi_info->dev->device_id);
651
652 return ERROR_OK;
653 }
654
655 const struct flash_driver stmsmi_flash = {
656 .name = "stmsmi",
657 .flash_bank_command = stmsmi_flash_bank_command,
658 .erase = stmsmi_erase,
659 .protect = stmsmi_protect,
660 .write = stmsmi_write,
661 .read = default_flash_read,
662 .probe = stmsmi_probe,
663 .auto_probe = stmsmi_auto_probe,
664 .erase_check = default_flash_blank_check,
665 .protect_check = stmsmi_protect_check,
666 .info = get_stmsmi_info,
667 .free_driver_priv = default_flash_free_driver_priv,
668 };

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)