flash: Analog Devices ADuCM360 support
[openocd.git] / src / flash / nor / aducm360.c
1 /***************************************************************************
2 * Copyright (C) 2015 by Ivan Buliev *
3 * i.buliev@mikrosistemi.com *
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 ***************************************************************************/
16
17 /***************************************************************************
18 * This version for ADuCM360 is largely based on the following flash *
19 * drivers: *
20 * - aduc702x.c *
21 * Copyright (C) 2008 by Kevin McGuire *
22 * Copyright (C) 2008 by Marcel Wijlaars *
23 * Copyright (C) 2009 by Michael Ashton *
24 * and *
25 * - stm32f1x.c *
26 * Copyright (C) 2005 by Dominic Rath *
27 * Dominic.Rath@gmx.de *
28 * *
29 * Copyright (C) 2008 by Spencer Oliver *
30 * spen@spen-soft.co.uk *
31 * *
32 * Copyright (C) 2011 by Andreas Fritiofson *
33 * andreas.fritiofson@gmail.com *
34 ***************************************************************************/
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include "imp.h"
41 #include <helper/binarybuffer.h>
42 #include <helper/time_support.h>
43 #include <target/algorithm.h>
44 #include <target/armv7m.h>
45
46 static int aducm360_build_sector_list(struct flash_bank *bank);
47 static int aducm360_check_flash_completion(struct target *target, unsigned int timeout_ms);
48 static int aducm360_set_write_enable(struct target *target, int enable);
49
50 #define ADUCM360_FLASH_BASE 0x40002800
51 #define ADUCM360_FLASH_FEESTA 0x0000
52 #define ADUCM360_FLASH_FEECON0 0x0004
53 #define ADUCM360_FLASH_FEECMD 0x0008
54 #define ADUCM360_FLASH_FEEADR0L 0x0010
55 #define ADUCM360_FLASH_FEEADR0H 0x0014
56 #define ADUCM360_FLASH_FEEADR1L 0x0018
57 #define ADUCM360_FLASH_FEEADR1H 0x001C
58 #define ADUCM360_FLASH_FEEKEY 0x0020
59 #define ADUCM360_FLASH_FEEPROL 0x0028
60 #define ADUCM360_FLASH_FEEPROH 0x002C
61 #define ADUCM360_FLASH_FEESIGL 0x0030
62 #define ADUCM360_FLASH_FEESIGH 0x0034
63 #define ADUCM360_FLASH_FEECON1 0x0038
64 #define ADUCM360_FLASH_FEEADRAL 0x0048
65 #define ADUCM360_FLASH_FEEADRAH 0x004C
66 #define ADUCM360_FLASH_FEEAEN0 0x0078
67 #define ADUCM360_FLASH_FEEAEN1 0x007C
68 #define ADUCM360_FLASH_FEEAEN2 0x0080
69
70 /* flash bank aducm360 0 0 0 0 <target#> */
71 FLASH_BANK_COMMAND_HANDLER(aducm360_flash_bank_command)
72 {
73 bank->base = 0x00000000;
74 bank->size = 0x00020000;
75
76 aducm360_build_sector_list(bank);
77
78 return ERROR_OK;
79 }
80
81 #define FLASH_SECTOR_SIZE 512
82
83 /* ----------------------------------------------------------------------- */
84 static int aducm360_build_sector_list(struct flash_bank *bank)
85 {
86 int i = 0;
87 uint32_t offset = 0;
88
89 /* sector size is 512 */
90 bank->num_sectors = bank->size / FLASH_SECTOR_SIZE;
91 bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
92 for (i = 0; i < bank->num_sectors; ++i) {
93 bank->sectors[i].offset = offset;
94 bank->sectors[i].size = FLASH_SECTOR_SIZE;
95 offset += bank->sectors[i].size;
96 bank->sectors[i].is_erased = -1;
97 bank->sectors[i].is_protected = 0;
98 }
99
100 return ERROR_OK;
101 }
102
103 /* ----------------------------------------------------------------------- */
104 static int aducm360_protect_check(struct flash_bank *bank)
105 {
106 LOG_WARNING("aducm360_protect_check not implemented.");
107 return ERROR_OK;
108 }
109
110 /* ----------------------------------------------------------------------- */
111 static int aducm360_mass_erase(struct target *target)
112 {
113 uint32_t value;
114 int res = ERROR_OK;
115
116 /* Clear any old status */
117 target_read_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEESTA, &value);
118
119 /* Enable the writing to the flash*/
120 aducm360_set_write_enable(target, 1);
121
122 /* Unlock for writing */
123 target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEKEY, 0x0000F456);
124 target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEKEY, 0x0000F123);
125 /* Issue the 'MASSERASE' command */
126 target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEECMD, 0x00000003);
127
128 /* Check the result */
129 res = aducm360_check_flash_completion(target, 3500);
130 if (res != ERROR_OK) {
131 LOG_ERROR("mass erase failed.");
132 aducm360_set_write_enable(target, 0);
133 res = ERROR_FLASH_OPERATION_FAILED;
134 }
135
136 return res;
137 }
138
139 /* ----------------------------------------------------------------------- */
140 static int aducm360_page_erase(struct target *target, uint32_t padd)
141 {
142 uint32_t value;
143 int res = ERROR_OK;
144
145 /* Clear any old status */
146 target_read_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEESTA, &value);
147
148 /* Enable the writing to the flash*/
149 aducm360_set_write_enable(target, 1);
150
151 /* Unlock for writing */
152 target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEKEY, 0x0000F456);
153 target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEKEY, 0x0000F123);
154 /* Write the sector address */
155 target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEADR0L, padd & 0xFFFF);
156 target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEADR0H, (padd>>16) & 0xFFFF);
157 /* Issue the 'ERASEPAGE' command */
158 target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEECMD, 0x00000001);
159
160 /* Check the result */
161 res = aducm360_check_flash_completion(target, 50);
162 if (res != ERROR_OK) {
163 LOG_ERROR("page erase failed at 0x%08" PRIx32, padd);
164 aducm360_set_write_enable(target, 0);
165 res = ERROR_FLASH_OPERATION_FAILED;
166 }
167
168 return res;
169 }
170
171 /* ----------------------------------------------------------------------- */
172 static int aducm360_erase(struct flash_bank *bank, int first, int last)
173 {
174 int res = ERROR_OK;
175 int i;
176 int count;
177 struct target *target = bank->target;
178 uint32_t padd;
179
180 if (((first | last) == 0) || ((first == 0) && (last >= bank->num_sectors))) {
181 res = aducm360_mass_erase(target);
182 } else {
183 count = last - first + 1;
184 for (i = 0; i < count; ++i) {
185 padd = bank->base + ((first+i)*FLASH_SECTOR_SIZE);
186 res = aducm360_page_erase(target, padd);
187 if (res != ERROR_OK)
188 break;
189 }
190 }
191
192 return res;
193 }
194
195 /* ----------------------------------------------------------------------- */
196 static int aducm360_protect(struct flash_bank *bank, int set, int first, int last)
197 {
198 LOG_ERROR("aducm360_protect not implemented.");
199 return ERROR_FLASH_OPERATION_FAILED;
200 }
201
202 /* ----------------------------------------------------------------------- */
203 static int aducm360_write_block_sync(
204 struct flash_bank *bank,
205 const uint8_t *buffer,
206 uint32_t offset,
207 uint32_t count)
208 {
209 struct target *target = bank->target;
210 uint32_t target_buffer_size = 8192;
211 struct working_area *helper;
212 struct working_area *target_buffer;
213 uint32_t address = bank->base + offset;
214 struct reg_param reg_params[8];
215 int retval = ERROR_OK;
216 uint32_t entry_point = 0, exit_point = 0;
217 uint32_t res;
218 struct armv7m_algorithm armv7m_algo;
219
220 static const uint32_t aducm360_flash_write_code[] = {
221 /* helper.code */
222 0x88AF4D10, 0x0704F047, 0x682F80AF, 0x600E6806,
223 0xF017882F, 0xF43F0F08, 0xF851AFFB, 0x42B77B04,
224 0x800DF040, 0x0004F100, 0xF47F3A04, 0x686FAFEF,
225 0x0704F027, 0xF04F80AF, 0xF0000400, 0xF04FB802,
226 0xBE000480, 0x40002800, 0x00015000, 0x20000000,
227 0x00013000
228 };
229
230 LOG_DEBUG("'aducm360_write_block_sync' requested, dst:0x%08" PRIx32 ", count:0x%08" PRIx32 "bytes.",
231 address, count);
232
233 /* ----- Check the destination area for a Long Word alignment ----- */
234 if (((count%4) != 0) || ((offset%4) != 0)) {
235 LOG_ERROR("write block must be multiple of four bytes in offset & length");
236 return ERROR_FAIL;
237 }
238
239 /* ----- Allocate space in the target's RAM for the helper code ----- */
240 if (target_alloc_working_area(target, sizeof(aducm360_flash_write_code),
241 &helper) != ERROR_OK) {
242 LOG_WARNING("no working area available, can't do block memory writes");
243 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
244 }
245
246 /* ----- Upload the helper code to the space in the target's RAM ----- */
247 uint8_t code[sizeof(aducm360_flash_write_code)];
248 target_buffer_set_u32_array(target, code, ARRAY_SIZE(aducm360_flash_write_code),
249 aducm360_flash_write_code);
250 retval = target_write_buffer(target, helper->address, sizeof(code), code);
251 if (retval != ERROR_OK)
252 return retval;
253 entry_point = helper->address;
254
255 /* ----- Allocate space in the target's RAM for the user application's object code ----- */
256 while (target_alloc_working_area_try(target, target_buffer_size, &target_buffer) != ERROR_OK) {
257 LOG_WARNING("couldn't allocate a buffer space of 0x%08" PRIx32 "bytes in the target's SRAM.",
258 target_buffer_size);
259 target_buffer_size /= 2;
260 if (target_buffer_size <= 256) { /* No room available */
261 LOG_WARNING("no large enough working area available, can't do block memory writes");
262 target_free_working_area(target, helper);
263 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
264 }
265 }
266
267 /* ----- Prepare the target for the helper ----- */
268 armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
269 armv7m_algo.core_mode = ARM_MODE_THREAD;
270
271 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT); /*SRC */
272 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /*DST */
273 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /*COUNT */
274 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /*not used */
275 init_reg_param(&reg_params[4], "r4", 32, PARAM_IN); /*RESULT */
276
277 /* ===== Execute the Main Programming Loop! ===== */
278 while (count > 0) {
279 uint32_t thisrun_count = (count > target_buffer_size) ? target_buffer_size : count;
280
281 /* ----- Upload the chunk ----- */
282 retval = target_write_buffer(target, target_buffer->address, thisrun_count, buffer);
283 if (retval != ERROR_OK)
284 break;
285 /* Set the arguments for the helper */
286 buf_set_u32(reg_params[0].value, 0, 32, target_buffer->address); /*SRC */
287 buf_set_u32(reg_params[1].value, 0, 32, address); /*DST */
288 buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); /*COUNT */
289 buf_set_u32(reg_params[3].value, 0, 32, 0); /*NOT USED*/
290
291 retval = target_run_algorithm(target, 0, NULL, 5,
292 reg_params, entry_point, exit_point, 10000, &armv7m_algo);
293 if (retval != ERROR_OK) {
294 LOG_ERROR("error executing aducm360 flash write algorithm");
295 break;
296 }
297
298 res = buf_get_u32(reg_params[4].value, 0, 32);
299 if (res) {
300 LOG_ERROR("aducm360 fast sync algorithm reports an error (%02X)", res);
301 retval = ERROR_FAIL;
302 break;
303 }
304
305 buffer += thisrun_count;
306 address += thisrun_count;
307 count -= thisrun_count;
308 }
309
310 target_free_working_area(target, target_buffer);
311 target_free_working_area(target, helper);
312
313 destroy_reg_param(&reg_params[0]);
314 destroy_reg_param(&reg_params[1]);
315 destroy_reg_param(&reg_params[2]);
316 destroy_reg_param(&reg_params[3]);
317 destroy_reg_param(&reg_params[4]);
318
319 return retval;
320 }
321
322 /* ----------------------------------------------------------------------- */
323 static int aducm360_write_block_async(
324 struct flash_bank *bank,
325 const uint8_t *buffer,
326 uint32_t offset,
327 uint32_t count)
328 {
329 struct target *target = bank->target;
330 uint32_t target_buffer_size = 1024;
331 struct working_area *helper;
332 struct working_area *target_buffer;
333 uint32_t address = bank->base + offset;
334 struct reg_param reg_params[9];
335 int retval = ERROR_OK;
336 uint32_t entry_point = 0, exit_point = 0;
337 uint32_t res;
338 uint32_t wcount;
339 struct armv7m_algorithm armv7m_algo;
340
341 static const uint32_t aducm360_flash_write_code[] = {
342 /* helper.code */
343 0x4050F8DF, 0xF04588A5, 0x80A50504, 0x8000F8D0,
344 0x0F00F1B8, 0x8016F000, 0x45476847, 0xAFF6F43F,
345 0x6B04F857, 0x6B04F842, 0xF0158825, 0xF43F0F08,
346 0x428FAFFB, 0xF100BF28, 0x60470708, 0xB10B3B01,
347 0xBFE4F7FF, 0xF02588A5, 0x80A50504, 0x0900F04F,
348 0xBE00BF00, 0x40002800, 0x20000000, 0x20000100,
349 0x00013000
350 };
351
352 LOG_DEBUG("'aducm360_write_block_async' requested, dst:0x%08" PRIx32 ", count:0x%08" PRIx32 "bytes.",
353 address, count);
354
355 /* ----- Check the destination area for a Long Word alignment ----- */
356 if (((count%4) != 0) || ((offset%4) != 0)) {
357 LOG_ERROR("write block must be multiple of four bytes in offset & length");
358 return ERROR_FAIL;
359 }
360 wcount = count/4;
361
362 /* ----- Allocate space in the target's RAM for the helper code ----- */
363 if (target_alloc_working_area(target, sizeof(aducm360_flash_write_code),
364 &helper) != ERROR_OK) {
365 LOG_WARNING("no working area available, can't do block memory writes");
366 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
367 }
368
369 /* ----- Upload the helper code to the space in the target's RAM ----- */
370 uint8_t code[sizeof(aducm360_flash_write_code)];
371 target_buffer_set_u32_array(target, code, ARRAY_SIZE(aducm360_flash_write_code),
372 aducm360_flash_write_code);
373 retval = target_write_buffer(target, helper->address, sizeof(code), code);
374 if (retval != ERROR_OK)
375 return retval;
376 entry_point = helper->address;
377
378 /* ----- Allocate space in the target's RAM for the user application's object code ----- */
379 while (target_alloc_working_area_try(target, target_buffer_size, &target_buffer) != ERROR_OK) {
380 LOG_WARNING("couldn't allocate a buffer space of 0x%08" PRIx32 "bytes in the target's SRAM.",
381 target_buffer_size);
382 target_buffer_size /= 2;
383 if (target_buffer_size <= 256) { /* No room available */
384 LOG_WARNING("no large enough working area available, can't do block memory writes");
385 target_free_working_area(target, helper);
386 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
387 }
388 }
389
390 /* ----- Prepare the target for the helper ----- */
391 armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
392 armv7m_algo.core_mode = ARM_MODE_THREAD;
393
394 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT); /*SRCBEG */
395 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /*SRCEND */
396 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /*DST */
397 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /*COUNT (LWs)*/
398 init_reg_param(&reg_params[4], "r9", 32, PARAM_IN); /*RESULT */
399
400 buf_set_u32(reg_params[0].value, 0, 32, target_buffer->address);
401 buf_set_u32(reg_params[1].value, 0, 32, target_buffer->address + target_buffer->size);
402 buf_set_u32(reg_params[2].value, 0, 32, address);
403 buf_set_u32(reg_params[3].value, 0, 32, wcount);
404
405 retval = target_run_flash_async_algorithm(target, buffer, wcount, 4,
406 0, NULL,
407 5, reg_params,
408 target_buffer->address, target_buffer->size,
409 entry_point, exit_point,
410 &armv7m_algo);
411 if (retval != ERROR_OK) {
412 LOG_ERROR("error executing aducm360 flash write algorithm");
413 } else {
414 res = buf_get_u32(reg_params[4].value, 0, 32); /*RESULT*/
415 if (res) {
416 LOG_ERROR("aducm360 fast async algorithm reports an error (%02X)", res);
417 retval = ERROR_FAIL;
418 }
419 }
420
421 target_free_working_area(target, target_buffer);
422 target_free_working_area(target, helper);
423
424 destroy_reg_param(&reg_params[0]);
425 destroy_reg_param(&reg_params[1]);
426 destroy_reg_param(&reg_params[2]);
427 destroy_reg_param(&reg_params[3]);
428 destroy_reg_param(&reg_params[4]);
429
430 return retval;
431 }
432
433 /* ----------------------------------------------------------------------- */
434 /* If this fn returns ERROR_TARGET_RESOURCE_NOT_AVAILABLE, then the caller can fall
435 * back to another mechanism that does not require onboard RAM
436 *
437 * Caller should not check for other return values specifically
438 */
439 static int aducm360_write_block(struct flash_bank *bank,
440 const uint8_t *buffer,
441 uint32_t offset,
442 uint32_t count)
443 {
444 int choice = 0;
445
446 switch (choice) {
447 case 0:
448 return aducm360_write_block_sync(bank, buffer, offset, count);
449 break;
450 case 1:
451 return aducm360_write_block_async(bank, buffer, offset, count);
452 break;
453 default:
454 LOG_ERROR("aducm360_write_block was cancelled (no writing method was chosen)!");
455 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
456 }
457 }
458
459 /* ----------------------------------------------------------------------- */
460 #define FEESTA_WRDONE 0x00000008
461
462 static int aducm360_write_modified(struct flash_bank *bank,
463 const uint8_t *buffer,
464 uint32_t offset,
465 uint32_t count)
466 {
467 uint32_t value;
468 int res = ERROR_OK;
469 uint32_t i, j, a, d;
470 struct target *target = bank->target;
471
472 LOG_DEBUG("performing slow write (offset=0x%08" PRIx32 ", count=0x%08" PRIx32 ")...",
473 offset, count);
474
475 /* Enable the writing to the flash */
476 aducm360_set_write_enable(target, 1);
477
478 /* Clear any old status */
479 target_read_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEESTA, &value);
480
481 for (i = 0; i < count; i += 4) {
482 a = offset+i;
483 for (j = 0; i < 4; i += 1)
484 *((uint8_t *)(&d) + j) = buffer[i+j];
485 target_write_u32(target, a, d);
486 do {
487 target_read_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEESTA, &value);
488 } while (!(value & FEESTA_WRDONE));
489 }
490 aducm360_set_write_enable(target, 0);
491
492 return res;
493 }
494
495 /* ----------------------------------------------------------------------- */
496 static int aducm360_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
497 {
498 int retval;
499
500 /* try using a block write */
501 retval = aducm360_write_block(bank, buffer, offset, count);
502 if (retval != ERROR_OK) {
503 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
504 /* if block write failed (no sufficient working area),
505 * use normal (slow) JTAG method */
506 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
507
508 retval = aducm360_write_modified(bank, buffer, offset, count);
509 if (retval != ERROR_OK) {
510 LOG_ERROR("slow write failed");
511 return ERROR_FLASH_OPERATION_FAILED;
512 }
513 }
514 }
515 return retval;
516 }
517
518 /* ----------------------------------------------------------------------- */
519 static int aducm360_probe(struct flash_bank *bank)
520 {
521 return ERROR_OK;
522 }
523
524 /* ----------------------------------------------------------------------- */
525 /* sets FEECON0 bit 2
526 * enable = 1 enables writes & erases, 0 disables them */
527 static int aducm360_set_write_enable(struct target *target, int enable)
528 {
529 /* don't bother to preserve int enable bit here */
530 uint32_t value;
531
532 target_read_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEECON0, &value);
533 if (enable)
534 value |= 0x00000004;
535 else
536 value &= ~0x00000004;
537 target_write_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEECON0, value);
538
539 return ERROR_OK;
540 }
541
542 /* ----------------------------------------------------------------------- */
543 /* wait up to timeout_ms for controller to not be busy,
544 * then check whether the command passed or failed.
545 *
546 * this function sleeps 1ms between checks (after the first one),
547 * so in some cases may slow things down without a usleep after the first read */
548 static int aducm360_check_flash_completion(struct target *target, unsigned int timeout_ms)
549 {
550 uint32_t v = 1;
551
552 long long endtime = timeval_ms() + timeout_ms;
553 while (1) {
554 target_read_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEESTA, &v);
555 if ((v & 0x00000001) == 0)
556 break;
557 alive_sleep(1);
558 if (timeval_ms() >= endtime)
559 break;
560 }
561
562 if (!(v & 0x00000004)) /* b2 */
563 return ERROR_FAIL;
564
565 return ERROR_OK;
566 }
567
568 /* ----------------------------------------------------------------------- */
569 struct flash_driver aducm360_flash = {
570 .name = "aducm360",
571 .flash_bank_command = aducm360_flash_bank_command,
572 .erase = aducm360_erase,
573 .protect = aducm360_protect,
574 .write = aducm360_write,
575 .read = default_flash_read,
576 .probe = aducm360_probe,
577 .auto_probe = aducm360_probe,
578 .erase_check = default_flash_blank_check,
579 .protect_check = aducm360_protect_check,
580 };

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)