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

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)