kinetis flash: use longword write when writing into pflash
[openocd.git] / src / flash / nor / non_cfi.c
1 /***************************************************************************
2 * Copyright (C) 2007 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * Copyright (C) 2009 Michael Schwingen *
5 * michael@schwingen.org *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "imp.h"
27 #include "cfi.h"
28 #include "non_cfi.h"
29
30
31 #define KB 1024
32 #define MB (1024*1024)
33 #define ERASE_REGION(num, size) (((size/256) << 16) | (num-1))
34
35 /* non-CFI compatible flashes */
36 static struct non_cfi non_cfi_flashes[] = {
37 {
38 .mfr = CFI_MFR_SST,
39 .id = 0xd4,
40 .pri_id = 0x02,
41 .dev_size = 64*KB,
42 .interface_desc = 0x0, /* x8 only device */
43 .max_buf_write_size = 0x0,
44 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
45 .num_erase_regions = 1,
46 .erase_region_info =
47 {
48 ERASE_REGION(16, 4*KB)
49 }
50 },
51 {
52 .mfr = CFI_MFR_SST,
53 .id = 0xd5,
54 .pri_id = 0x02,
55 .dev_size = 128*KB,
56 .interface_desc = 0x0, /* x8 only device */
57 .max_buf_write_size = 0x0,
58 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
59 .num_erase_regions = 1,
60 .erase_region_info =
61 {
62 ERASE_REGION(32, 4*KB)
63 }
64 },
65 {
66 .mfr = CFI_MFR_SST,
67 .id = 0xd6,
68 .pri_id = 0x02,
69 .dev_size = 256*KB,
70 .interface_desc = 0x0, /* x8 only device */
71 .max_buf_write_size = 0x0,
72 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
73 .num_erase_regions = 1,
74 .erase_region_info =
75 {
76 ERASE_REGION(64, 4*KB)
77 }
78 },
79 {
80 .mfr = CFI_MFR_SST,
81 .id = 0xd7,
82 .pri_id = 0x02,
83 .dev_size = 512*KB,
84 .interface_desc = 0x0, /* x8 only device */
85 .max_buf_write_size = 0x0,
86 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
87 .num_erase_regions = 1,
88 .erase_region_info =
89 {
90 ERASE_REGION(128, 4*KB)
91 }
92 },
93 {
94 .mfr = CFI_MFR_AMD, /* Spansion AM29LV040B */
95 .id = 0x4f,
96 .pri_id = 0x02,
97 .dev_size = 512*KB,
98 .interface_desc = 0x0, /* x8 only device */
99 .max_buf_write_size = 0x0,
100 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
101 .num_erase_regions = 1,
102 .erase_region_info =
103 {
104 ERASE_REGION(8, 64*KB)
105 }
106 },
107 {
108 .mfr = CFI_MFR_SST,
109 .id = 0x2780,
110 .pri_id = 0x02,
111 .dev_size = 512*KB,
112 .interface_desc = 0x2, /* x8 or x16 device */
113 .max_buf_write_size = 0x0,
114 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
115 .num_erase_regions = 1,
116 .erase_region_info =
117 {
118 ERASE_REGION(128, 4*KB)
119 }
120 },
121 {
122 .mfr = CFI_MFR_ST,
123 .id = 0xd6, /* ST29F400BB */
124 .pri_id = 0x02,
125 .dev_size = 512*KB,
126 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
127 .max_buf_write_size = 0x0,
128 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
129 .num_erase_regions = 4,
130 .erase_region_info =
131 {
132 ERASE_REGION(1, 16*KB),
133 ERASE_REGION(2, 8*KB),
134 ERASE_REGION(1, 32*KB),
135 ERASE_REGION(7, 64*KB)
136 }
137 },
138 {
139 .mfr = CFI_MFR_ST,
140 .id = 0xd5, /* ST29F400BT */
141 .pri_id = 0x02,
142 .dev_size = 512*KB,
143 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
144 .max_buf_write_size = 0x0,
145 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
146 .num_erase_regions = 4,
147 .erase_region_info =
148 {
149 ERASE_REGION(7, 64*KB),
150 ERASE_REGION(1, 32*KB),
151 ERASE_REGION(2, 8*KB),
152 ERASE_REGION(1, 16*KB)
153 }
154 },
155
156 /* SST 39VF* do not support DQ5 status polling - this currently is
157 only supported by the host algorithm, not by the target code using
158 the work area.
159 Only true for 8-bit and 32-bit wide memories. 16-bit wide memories
160 without DQ5 status polling are supported by the target code.
161 */
162 {
163 .mfr = CFI_MFR_SST,
164 .id = 0x2782, /* SST39xF160 */
165 .pri_id = 0x02,
166 .dev_size = 2*MB,
167 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
168 .max_buf_write_size = 0x0,
169 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
170 .num_erase_regions = 1,
171 .erase_region_info =
172 {
173 ERASE_REGION(512, 4*KB)
174 }
175 },
176 {
177 .mfr = CFI_MFR_SST,
178 .id = 0x2783, /* SST39VF320 */
179 .pri_id = 0x02,
180 .dev_size = 4*MB,
181 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
182 .max_buf_write_size = 0x0,
183 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
184 .num_erase_regions = 1,
185 .erase_region_info =
186 {
187 ERASE_REGION(1024, 4*KB)
188 }
189 },
190 {
191 .mfr = CFI_MFR_SST,
192 .id = 0x234b, /* SST39VF1601 */
193 .pri_id = 0x02,
194 .dev_size = 2*MB,
195 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
196 .max_buf_write_size = 0x0,
197 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
198 .num_erase_regions = 1,
199 .erase_region_info =
200 {
201 ERASE_REGION(512, 4*KB)
202 }
203 },
204 {
205 .mfr = CFI_MFR_SST,
206 .id = 0x274b, /* SST39WF1601 */
207 .pri_id = 0x02,
208 .dev_size = 2*MB,
209 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
210 .max_buf_write_size = 0x0,
211 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
212 .num_erase_regions = 1,
213 .erase_region_info =
214 {
215 ERASE_REGION(512, 4*KB)
216 }
217 },
218 {
219 .mfr = CFI_MFR_SST,
220 .id = 0x234a, /* SST39VF1602 */
221 .pri_id = 0x02,
222 .dev_size = 2*MB,
223 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
224 .max_buf_write_size = 0x0,
225 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
226 .num_erase_regions = 1,
227 .erase_region_info =
228 {
229 ERASE_REGION(512, 4*KB)
230 }
231 },
232 {
233 .mfr = CFI_MFR_SST,
234 .id = 0x235b, /* SST39VF3201 */
235 .pri_id = 0x02,
236 .dev_size = 4*MB,
237 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
238 .max_buf_write_size = 0x0,
239 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
240 .num_erase_regions = 1,
241 .erase_region_info =
242 {
243 ERASE_REGION(1024, 4*KB)
244 }
245 },
246 {
247 .mfr = CFI_MFR_SST,
248 .id = 0x235a, /* SST39VF3202 */
249 .pri_id = 0x02,
250 .dev_size = 4*MB,
251 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
252 .max_buf_write_size = 0x0,
253 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
254 .num_erase_regions = 1,
255 .erase_region_info =
256 {
257 ERASE_REGION(1024, 4*KB)
258 }
259 },
260 {
261 .mfr = CFI_MFR_SST,
262 .id = 0x236d, /* SST39VF6401B */
263 .pri_id = 0x02,
264 .dev_size = 8*MB,
265 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
266 .max_buf_write_size = 0x0,
267 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
268 .num_erase_regions = 1,
269 .erase_region_info =
270 {
271 ERASE_REGION(2048, 4*KB)
272 }
273 },
274 {
275 .mfr = CFI_MFR_AMD,
276 .id = 0x22ab, /* AM29F400BB */
277 .pri_id = 0x02,
278 .dev_size = 512*KB,
279 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
280 .max_buf_write_size = 0x0,
281 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
282 .num_erase_regions = 4,
283 .erase_region_info =
284 {
285 ERASE_REGION(1, 16*KB),
286 ERASE_REGION(2, 8*KB),
287 ERASE_REGION(1, 32*KB),
288 ERASE_REGION(7, 64*KB)
289 }
290 },
291 {
292 .mfr = CFI_MFR_AMD,
293 .id = 0x2223, /* AM29F400BT */
294 .pri_id = 0x02,
295 .dev_size = 512*KB,
296 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
297 .max_buf_write_size = 0x0,
298 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
299 .num_erase_regions = 4,
300 .erase_region_info =
301 {
302 ERASE_REGION(7, 64*KB),
303 ERASE_REGION(1, 32*KB),
304 ERASE_REGION(2, 8*KB),
305 ERASE_REGION(1, 16*KB)
306 }
307 },
308 {
309 .mfr = CFI_MFR_FUJITSU,
310 .id = 0x226b, /* AM29SL800DB */
311 .pri_id = 0x02,
312 .dev_size = 1*MB,
313 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
314 .max_buf_write_size = 0x0,
315 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
316 .num_erase_regions = 4,
317 .erase_region_info =
318 {
319 ERASE_REGION(1, 16*KB),
320 ERASE_REGION(2, 8*KB),
321 ERASE_REGION(1, 32*KB),
322 ERASE_REGION(15, 64*KB)
323 }
324 },
325 {
326 .mfr = CFI_MFR_FUJITSU,
327 .id = 0x22ea, /* MBM29SL800TE */
328 .pri_id = 0x02,
329 .dev_size = 1*MB,
330 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
331 .max_buf_write_size = 0x0,
332 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
333 .num_erase_regions = 4,
334 .erase_region_info =
335 {
336 ERASE_REGION(15, 64*KB),
337 ERASE_REGION(1, 32*KB),
338 ERASE_REGION(2, 8*KB),
339 ERASE_REGION(1, 16*KB)
340 }
341 },
342 {
343 .mfr = CFI_MFR_FUJITSU,
344 .id = 0xba, /* 29LV400BC */
345 .pri_id = 0x02,
346 .dev_size = 512*KB,
347 .interface_desc = 0x1, /* x8 or x16 device w/ nBYTE */
348 .max_buf_write_size = 0x00,
349 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
350 .num_erase_regions = 4,
351 .erase_region_info =
352 {
353 ERASE_REGION(1, 16*KB),
354 ERASE_REGION(2, 8*KB),
355 ERASE_REGION(1, 32*KB),
356 ERASE_REGION(7, 64*KB)
357 }
358 },
359 {
360 .mfr = CFI_MFR_AMIC,
361 .id = 0xb31a, /* A29L800A */
362 .pri_id = 0x02,
363 .dev_size = 1*MB,
364 .interface_desc = 0x2,
365 .max_buf_write_size = 0x0,
366 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
367 .num_erase_regions = 4,
368 .erase_region_info =
369 {
370 ERASE_REGION(1, 16*KB),
371 ERASE_REGION(2, 8*KB),
372 ERASE_REGION(1, 32*KB),
373 ERASE_REGION(15, 64*KB)
374 }
375 },
376 {
377 .mfr = CFI_MFR_MX,
378 .id = 0x225b, /* MX29LV800B */
379 .pri_id = 0x02,
380 .dev_size = 1*MB,
381 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
382 .max_buf_write_size = 0x0,
383 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
384 .num_erase_regions = 4,
385 .erase_region_info =
386 {
387 ERASE_REGION(1, 16*KB),
388 ERASE_REGION(2, 8*KB),
389 ERASE_REGION(1, 32*KB),
390 ERASE_REGION(15, 64*KB)
391 }
392 },
393
394 {
395 .mfr = CFI_MFR_MX,
396 .id = 0x2249, /* MX29LV160AB: 2MB */
397 .pri_id = 0x02,
398 .dev_size = 2*MB,
399 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
400 .max_buf_write_size = 0x0,
401 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
402 .num_erase_regions = 4,
403 .erase_region_info =
404 {
405 ERASE_REGION(1, 16*KB),
406 ERASE_REGION(2, 8*KB),
407 ERASE_REGION(1, 32*KB),
408 ERASE_REGION(31, 64*KB)
409 }
410 },
411 {
412 .mfr = CFI_MFR_MX,
413 .id = 0x22C4, /* MX29LV160AT: 2MB */
414 .pri_id = 0x02,
415 .dev_size = 2*MB,
416 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
417 .max_buf_write_size = 0x0,
418 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
419 .num_erase_regions = 4,
420 .erase_region_info =
421 {
422 ERASE_REGION(31, 64*KB),
423 ERASE_REGION(1, 32*KB),
424 ERASE_REGION(2, 8*KB),
425 ERASE_REGION(1, 16*KB)
426 }
427 },
428 {
429 .mfr = CFI_MFR_EON,
430 .id = 0x225b, /* EN29LV800BB */
431 .pri_id = 0x02,
432 .dev_size = 1*MB,
433 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
434 .max_buf_write_size = 0x0,
435 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
436 .num_erase_regions = 4,
437 .erase_region_info =
438 {
439 ERASE_REGION(1, 16*KB),
440 ERASE_REGION(2, 8*KB),
441 ERASE_REGION(1, 32*KB),
442 ERASE_REGION(15, 64*KB)
443 }
444 },
445 {
446 .mfr = CFI_MFR_ATMEL,
447 .id = 0x00c0, /* Atmel 49BV1614 */
448 .pri_id = 0x02,
449 .dev_size = 2*MB,
450 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
451 .max_buf_write_size = 0x0,
452 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
453 .num_erase_regions = 3,
454 .erase_region_info =
455 {
456 ERASE_REGION(8, 8*KB),
457 ERASE_REGION(2, 32*KB),
458 ERASE_REGION(30, 64*KB)
459 }
460 },
461 {
462 .mfr = CFI_MFR_ATMEL,
463 .id = 0xC2, /* Atmel 49BV1614T */
464 .pri_id = 0x02,
465 .dev_size = 2*MB,
466 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
467 .max_buf_write_size = 0x0,
468 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
469 .num_erase_regions = 3,
470 .erase_region_info =
471 {
472 ERASE_REGION(30, 64*KB),
473 ERASE_REGION(2, 32*KB),
474 ERASE_REGION(8, 8*KB)
475 }
476 },
477 {
478 .mfr = CFI_MFR_AMD,
479 .id = 0x225b, /* S29AL008D */
480 .pri_id = 0x02,
481 .dev_size = 1*MB,
482 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
483 .max_buf_write_size = 0x0,
484 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
485 .num_erase_regions = 4,
486 .erase_region_info =
487 {
488 ERASE_REGION(1, 16*KB),
489 ERASE_REGION(2, 8*KB),
490 ERASE_REGION(1, 32*KB),
491 ERASE_REGION(15, 64*KB)
492 }
493 },
494 {
495 .mfr = 0,
496 .id = 0,
497 }
498 };
499
500 void cfi_fixup_non_cfi(struct flash_bank *bank)
501 {
502 unsigned int mask;
503 struct cfi_flash_bank *cfi_info = bank->driver_priv;
504 struct non_cfi *non_cfi = non_cfi_flashes;
505
506 if(cfi_info->x16_as_x8)
507 mask = 0xFF;
508 else
509 mask = 0xFFFF;
510
511 for (non_cfi = non_cfi_flashes; non_cfi->mfr; non_cfi++)
512 {
513 if ((cfi_info->manufacturer == non_cfi->mfr)
514 && (cfi_info->device_id == (non_cfi->id & mask)))
515 {
516 break;
517 }
518 }
519
520 /* only fixup jedec flashs found in table */
521 if (!non_cfi->mfr)
522 return;
523
524 cfi_info->not_cfi = 1;
525
526 /* fill in defaults for non-critical data */
527 cfi_info->vcc_min = 0x0;
528 cfi_info->vcc_max = 0x0;
529 cfi_info->vpp_min = 0x0;
530 cfi_info->vpp_max = 0x0;
531 /* these are used for timeouts - use vales that should be long enough
532 for normal operation. */
533 cfi_info->word_write_timeout_typ = 0x0a;
534 cfi_info->buf_write_timeout_typ = 0x0d;
535 cfi_info->block_erase_timeout_typ = 0x0d;
536 cfi_info->chip_erase_timeout_typ = 0x10;
537 cfi_info->word_write_timeout_max = 0x0;
538 cfi_info->buf_write_timeout_max = 0x0;
539 cfi_info->block_erase_timeout_max = 0x0;
540 cfi_info->chip_erase_timeout_max = 0x0;
541
542 cfi_info->qry[0] = 'Q';
543 cfi_info->qry[1] = 'R';
544 cfi_info->qry[2] = 'Y';
545
546 cfi_info->pri_id = non_cfi->pri_id;
547 cfi_info->pri_addr = 0x0;
548 cfi_info->alt_id = 0x0;
549 cfi_info->alt_addr = 0x0;
550 cfi_info->alt_ext = NULL;
551
552 cfi_info->interface_desc = non_cfi->interface_desc;
553 cfi_info->max_buf_write_size = non_cfi->max_buf_write_size;
554 cfi_info->status_poll_mask = non_cfi->status_poll_mask;
555 cfi_info->num_erase_regions = non_cfi->num_erase_regions;
556 size_t erase_region_info_size = sizeof(*cfi_info->erase_region_info) *
557 cfi_info->num_erase_regions;
558 cfi_info->erase_region_info = malloc(erase_region_info_size);
559 memcpy(cfi_info->erase_region_info,
560 non_cfi->erase_region_info, erase_region_info_size);
561 cfi_info->dev_size = non_cfi->dev_size;
562
563 if (cfi_info->pri_id == 0x2)
564 {
565 struct cfi_spansion_pri_ext *pri_ext = malloc(sizeof(struct cfi_spansion_pri_ext));
566
567 pri_ext->pri[0] = 'P';
568 pri_ext->pri[1] = 'R';
569 pri_ext->pri[2] = 'I';
570
571 pri_ext->major_version = '1';
572 pri_ext->minor_version = '0';
573
574 pri_ext->SiliconRevision = 0x0;
575 pri_ext->EraseSuspend = 0x0;
576 pri_ext->EraseSuspend = 0x0;
577 pri_ext->BlkProt = 0x0;
578 pri_ext->TmpBlkUnprotect = 0x0;
579 pri_ext->BlkProtUnprot = 0x0;
580 pri_ext->SimultaneousOps = 0x0;
581 pri_ext->BurstMode = 0x0;
582 pri_ext->PageMode = 0x0;
583 pri_ext->VppMin = 0x0;
584 pri_ext->VppMax = 0x0;
585 pri_ext->TopBottom = 0x0;
586
587 pri_ext->_unlock1 = 0x5555;
588 pri_ext->_unlock2 = 0x2AAA;
589 pri_ext->_reversed_geometry = 0;
590
591 cfi_info->pri_ext = pri_ext;
592 } else if ((cfi_info->pri_id == 0x1) || (cfi_info->pri_id == 0x3))
593 {
594 LOG_ERROR("BUG: non-CFI flashes using the Intel commandset are not yet supported");
595 exit(-1);
596 }
597 }

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)