Set empty usage field for commands that do not need parameters
[openocd.git] / src / flash / nor / tms470.c
1 /***************************************************************************
2 * Copyright (C) 2007,2008 by Christopher Kilgour *
3 * techie |_at_| whiterocker |_dot_| 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 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include "imp.h"
24
25 /* ----------------------------------------------------------------------
26 * Internal Support, Helpers
27 * ---------------------------------------------------------------------- */
28
29 struct tms470_flash_bank {
30 unsigned ordinal;
31
32 /* device identification register */
33 uint32_t device_ident_reg;
34 uint32_t silicon_version;
35 uint32_t technology_family;
36 uint32_t rom_flash;
37 uint32_t part_number;
38 const char *part_name;
39
40 };
41
42 static const struct flash_sector TMS470R1A256_SECTORS[] = {
43 {0x00000000, 0x00002000, -1, -1},
44 {0x00002000, 0x00002000, -1, -1},
45 {0x00004000, 0x00002000, -1, -1},
46 {0x00006000, 0x00002000, -1, -1},
47 {0x00008000, 0x00008000, -1, -1},
48 {0x00010000, 0x00008000, -1, -1},
49 {0x00018000, 0x00008000, -1, -1},
50 {0x00020000, 0x00008000, -1, -1},
51 {0x00028000, 0x00008000, -1, -1},
52 {0x00030000, 0x00008000, -1, -1},
53 {0x00038000, 0x00002000, -1, -1},
54 {0x0003A000, 0x00002000, -1, -1},
55 {0x0003C000, 0x00002000, -1, -1},
56 {0x0003E000, 0x00002000, -1, -1},
57 };
58
59 #define TMS470R1A256_NUM_SECTORS \
60 ARRAY_SIZE(TMS470R1A256_SECTORS)
61
62 static const struct flash_sector TMS470R1A288_BANK0_SECTORS[] = {
63 {0x00000000, 0x00002000, -1, -1},
64 {0x00002000, 0x00002000, -1, -1},
65 {0x00004000, 0x00002000, -1, -1},
66 {0x00006000, 0x00002000, -1, -1},
67 };
68
69 #define TMS470R1A288_BANK0_NUM_SECTORS \
70 ARRAY_SIZE(TMS470R1A288_BANK0_SECTORS)
71
72 static const struct flash_sector TMS470R1A288_BANK1_SECTORS[] = {
73 {0x00040000, 0x00010000, -1, -1},
74 {0x00050000, 0x00010000, -1, -1},
75 {0x00060000, 0x00010000, -1, -1},
76 {0x00070000, 0x00010000, -1, -1},
77 };
78
79 #define TMS470R1A288_BANK1_NUM_SECTORS \
80 ARRAY_SIZE(TMS470R1A288_BANK1_SECTORS)
81
82 static const struct flash_sector TMS470R1A384_BANK0_SECTORS[] = {
83 {0x00000000, 0x00002000, -1, -1},
84 {0x00002000, 0x00002000, -1, -1},
85 {0x00004000, 0x00004000, -1, -1},
86 {0x00008000, 0x00004000, -1, -1},
87 {0x0000C000, 0x00004000, -1, -1},
88 {0x00010000, 0x00004000, -1, -1},
89 {0x00014000, 0x00004000, -1, -1},
90 {0x00018000, 0x00002000, -1, -1},
91 {0x0001C000, 0x00002000, -1, -1},
92 {0x0001E000, 0x00002000, -1, -1},
93 };
94
95 #define TMS470R1A384_BANK0_NUM_SECTORS \
96 ARRAY_SIZE(TMS470R1A384_BANK0_SECTORS)
97
98 static const struct flash_sector TMS470R1A384_BANK1_SECTORS[] = {
99 {0x00020000, 0x00008000, -1, -1},
100 {0x00028000, 0x00008000, -1, -1},
101 {0x00030000, 0x00008000, -1, -1},
102 {0x00038000, 0x00008000, -1, -1},
103 };
104
105 #define TMS470R1A384_BANK1_NUM_SECTORS \
106 ARRAY_SIZE(TMS470R1A384_BANK1_SECTORS)
107
108 static const struct flash_sector TMS470R1A384_BANK2_SECTORS[] = {
109 {0x00040000, 0x00008000, -1, -1},
110 {0x00048000, 0x00008000, -1, -1},
111 {0x00050000, 0x00008000, -1, -1},
112 {0x00058000, 0x00008000, -1, -1},
113 };
114
115 #define TMS470R1A384_BANK2_NUM_SECTORS \
116 ARRAY_SIZE(TMS470R1A384_BANK2_SECTORS)
117
118 /* ---------------------------------------------------------------------- */
119
120 static int tms470_read_part_info(struct flash_bank *bank)
121 {
122 struct tms470_flash_bank *tms470_info = bank->driver_priv;
123 struct target *target = bank->target;
124 uint32_t device_ident_reg;
125 uint32_t silicon_version;
126 uint32_t technology_family;
127 uint32_t rom_flash;
128 uint32_t part_number;
129 const char *part_name;
130
131 /* we shall not rely on the caller in this test, this function allocates memory,
132 thus and executing the code more than once may cause memory leak */
133 if (tms470_info->device_ident_reg)
134 return ERROR_OK;
135
136 /* read and parse the device identification register */
137 target_read_u32(target, 0xFFFFFFF0, &device_ident_reg);
138
139 LOG_INFO("device_ident_reg = 0x%08" PRIx32 "", device_ident_reg);
140
141 if ((device_ident_reg & 7) == 0) {
142 LOG_WARNING("Cannot identify target as a TMS470 family.");
143 return ERROR_FLASH_OPERATION_FAILED;
144 }
145
146 silicon_version = (device_ident_reg >> 12) & 0xF;
147 technology_family = (device_ident_reg >> 11) & 1;
148 rom_flash = (device_ident_reg >> 10) & 1;
149 part_number = (device_ident_reg >> 3) & 0x7f;
150
151 if (bank->sectors) {
152 free(bank->sectors);
153 bank->sectors = NULL;
154 bank->num_sectors = 0;
155 }
156
157 /*
158 * If the part number is known, determine if the flash bank is valid
159 * based on the base address being within the known flash bank
160 * ranges. Then fixup/complete the remaining fields of the flash
161 * bank structure.
162 */
163 switch (part_number) {
164 case 0x0a:
165 part_name = "TMS470R1A256";
166
167 if (bank->base >= 0x00040000) {
168 LOG_ERROR("No %s flash bank contains base address "
169 TARGET_ADDR_FMT ".",
170 part_name,
171 bank->base);
172 return ERROR_FLASH_OPERATION_FAILED;
173 }
174 tms470_info->ordinal = 0;
175 bank->base = 0x00000000;
176 bank->size = 256 * 1024;
177 bank->num_sectors = TMS470R1A256_NUM_SECTORS;
178 bank->sectors = malloc(sizeof(TMS470R1A256_SECTORS));
179 if (!bank->sectors)
180 return ERROR_FLASH_OPERATION_FAILED;
181 (void)memcpy(bank->sectors, TMS470R1A256_SECTORS, sizeof(TMS470R1A256_SECTORS));
182 break;
183
184 case 0x2b:
185 part_name = "TMS470R1A288";
186
187 if (bank->base < 0x00008000) {
188 tms470_info->ordinal = 0;
189 bank->base = 0x00000000;
190 bank->size = 32 * 1024;
191 bank->num_sectors = TMS470R1A288_BANK0_NUM_SECTORS;
192 bank->sectors = malloc(sizeof(TMS470R1A288_BANK0_SECTORS));
193 if (!bank->sectors)
194 return ERROR_FLASH_OPERATION_FAILED;
195 (void)memcpy(bank->sectors, TMS470R1A288_BANK0_SECTORS,
196 sizeof(TMS470R1A288_BANK0_SECTORS));
197 } else if ((bank->base >= 0x00040000) && (bank->base < 0x00080000)) {
198 tms470_info->ordinal = 1;
199 bank->base = 0x00040000;
200 bank->size = 256 * 1024;
201 bank->num_sectors = TMS470R1A288_BANK1_NUM_SECTORS;
202 bank->sectors = malloc(sizeof(TMS470R1A288_BANK1_SECTORS));
203 if (!bank->sectors)
204 return ERROR_FLASH_OPERATION_FAILED;
205 (void)memcpy(bank->sectors, TMS470R1A288_BANK1_SECTORS,
206 sizeof(TMS470R1A288_BANK1_SECTORS));
207 } else {
208 LOG_ERROR("No %s flash bank contains base address " TARGET_ADDR_FMT ".",
209 part_name, bank->base);
210 return ERROR_FLASH_OPERATION_FAILED;
211 }
212 break;
213
214 case 0x2d:
215 part_name = "TMS470R1A384";
216
217 if (bank->base < 0x00020000) {
218 tms470_info->ordinal = 0;
219 bank->base = 0x00000000;
220 bank->size = 128 * 1024;
221 bank->num_sectors = TMS470R1A384_BANK0_NUM_SECTORS;
222 bank->sectors = malloc(sizeof(TMS470R1A384_BANK0_SECTORS));
223 if (!bank->sectors)
224 return ERROR_FLASH_OPERATION_FAILED;
225 (void)memcpy(bank->sectors, TMS470R1A384_BANK0_SECTORS,
226 sizeof(TMS470R1A384_BANK0_SECTORS));
227 } else if ((bank->base >= 0x00020000) && (bank->base < 0x00040000)) {
228 tms470_info->ordinal = 1;
229 bank->base = 0x00020000;
230 bank->size = 128 * 1024;
231 bank->num_sectors = TMS470R1A384_BANK1_NUM_SECTORS;
232 bank->sectors = malloc(sizeof(TMS470R1A384_BANK1_SECTORS));
233 if (!bank->sectors)
234 return ERROR_FLASH_OPERATION_FAILED;
235 (void)memcpy(bank->sectors, TMS470R1A384_BANK1_SECTORS,
236 sizeof(TMS470R1A384_BANK1_SECTORS));
237 } else if ((bank->base >= 0x00040000) && (bank->base < 0x00060000)) {
238 tms470_info->ordinal = 2;
239 bank->base = 0x00040000;
240 bank->size = 128 * 1024;
241 bank->num_sectors = TMS470R1A384_BANK2_NUM_SECTORS;
242 bank->sectors = malloc(sizeof(TMS470R1A384_BANK2_SECTORS));
243 if (!bank->sectors)
244 return ERROR_FLASH_OPERATION_FAILED;
245 (void)memcpy(bank->sectors, TMS470R1A384_BANK2_SECTORS,
246 sizeof(TMS470R1A384_BANK2_SECTORS));
247 } else {
248 LOG_ERROR("No %s flash bank contains base address " TARGET_ADDR_FMT ".",
249 part_name, bank->base);
250 return ERROR_FLASH_OPERATION_FAILED;
251 }
252 break;
253
254 default:
255 LOG_WARNING("Could not identify part 0x%02x as a member of the TMS470 family.",
256 (unsigned)part_number);
257 return ERROR_FLASH_OPERATION_FAILED;
258 }
259
260 /* turn off memory selects */
261 target_write_u32(target, 0xFFFFFFE4, 0x00000000);
262 target_write_u32(target, 0xFFFFFFE0, 0x00000000);
263
264 bank->chip_width = 32;
265 bank->bus_width = 32;
266
267 LOG_INFO("Identified %s, ver=%d, core=%s, nvmem=%s.",
268 part_name,
269 (int)(silicon_version),
270 (technology_family ? "1.8v" : "3.3v"),
271 (rom_flash ? "rom" : "flash"));
272
273 tms470_info->device_ident_reg = device_ident_reg;
274 tms470_info->silicon_version = silicon_version;
275 tms470_info->technology_family = technology_family;
276 tms470_info->rom_flash = rom_flash;
277 tms470_info->part_number = part_number;
278 tms470_info->part_name = part_name;
279
280 /*
281 * Disable reset on address access violation.
282 */
283 target_write_u32(target, 0xFFFFFFE0, 0x00004007);
284
285 return ERROR_OK;
286 }
287
288 /* ---------------------------------------------------------------------- */
289
290 static uint32_t keysSet;
291 static uint32_t flashKeys[4];
292
293 COMMAND_HANDLER(tms470_handle_flash_keyset_command)
294 {
295 if (CMD_ARGC > 4)
296 return ERROR_COMMAND_SYNTAX_ERROR;
297 else if (CMD_ARGC == 4) {
298 int i;
299
300 for (i = 0; i < 4; i++) {
301 int start = (0 == strncmp(CMD_ARGV[i], "0x", 2)) ? 2 : 0;
302
303 if (1 != sscanf(&CMD_ARGV[i][start], "%" SCNx32 "", &flashKeys[i])) {
304 command_print(CMD_CTX, "could not process flash key %s",
305 CMD_ARGV[i]);
306 LOG_ERROR("could not process flash key %s", CMD_ARGV[i]);
307 return ERROR_COMMAND_SYNTAX_ERROR;
308 }
309 }
310
311 keysSet = 1;
312 } else if (CMD_ARGC != 0) {
313 command_print(CMD_CTX, "tms470 flash_keyset <key0> <key1> <key2> <key3>");
314 return ERROR_COMMAND_SYNTAX_ERROR;
315 }
316
317 if (keysSet) {
318 command_print(CMD_CTX,
319 "using flash keys 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 "",
320 flashKeys[0],
321 flashKeys[1],
322 flashKeys[2],
323 flashKeys[3]);
324 } else
325 command_print(CMD_CTX, "flash keys not set");
326
327 return ERROR_OK;
328 }
329
330 static const uint32_t FLASH_KEYS_ALL_ONES[] = { 0xFFFFFFFF, 0xFFFFFFFF,
331 0xFFFFFFFF, 0xFFFFFFFF,};
332
333 static const uint32_t FLASH_KEYS_ALL_ZEROS[] = { 0x00000000, 0x00000000,
334 0x00000000, 0x00000000,};
335
336 static const uint32_t FLASH_KEYS_MIX1[] = { 0xf0fff0ff, 0xf0fff0ff,
337 0xf0fff0ff, 0xf0fff0ff};
338
339 static const uint32_t FLASH_KEYS_MIX2[] = { 0x0000ffff, 0x0000ffff,
340 0x0000ffff, 0x0000ffff};
341
342 /* ---------------------------------------------------------------------- */
343
344 static int oscMHz = 12;
345
346 COMMAND_HANDLER(tms470_handle_osc_megahertz_command)
347 {
348 if (CMD_ARGC > 1)
349 return ERROR_COMMAND_SYNTAX_ERROR;
350 else if (CMD_ARGC == 1)
351 sscanf(CMD_ARGV[0], "%d", &oscMHz);
352
353 if (oscMHz <= 0) {
354 LOG_ERROR("osc_megahertz must be positive and non-zero!");
355 command_print(CMD_CTX, "osc_megahertz must be positive and non-zero!");
356 oscMHz = 12;
357 return ERROR_COMMAND_SYNTAX_ERROR;
358 }
359
360 command_print(CMD_CTX, "osc_megahertz=%d", oscMHz);
361
362 return ERROR_OK;
363 }
364
365 /* ---------------------------------------------------------------------- */
366
367 static int plldis;
368
369 COMMAND_HANDLER(tms470_handle_plldis_command)
370 {
371 if (CMD_ARGC > 1)
372 return ERROR_COMMAND_SYNTAX_ERROR;
373 else if (CMD_ARGC == 1) {
374 sscanf(CMD_ARGV[0], "%d", &plldis);
375 plldis = plldis ? 1 : 0;
376 }
377
378 command_print(CMD_CTX, "plldis=%d", plldis);
379
380 return ERROR_OK;
381 }
382
383 /* ---------------------------------------------------------------------- */
384
385 static int tms470_check_flash_unlocked(struct target *target)
386 {
387 uint32_t fmbbusy;
388
389 target_read_u32(target, 0xFFE89C08, &fmbbusy);
390 LOG_INFO("tms470 fmbbusy = 0x%08" PRIx32 " -> %s",
391 fmbbusy,
392 fmbbusy & 0x8000 ? "unlocked" : "LOCKED");
393 return fmbbusy & 0x8000 ? ERROR_OK : ERROR_FLASH_OPERATION_FAILED;
394 }
395
396 /* ---------------------------------------------------------------------- */
397
398 static int tms470_try_flash_keys(struct target *target, const uint32_t *key_set)
399 {
400 uint32_t glbctrl, fmmstat;
401 int retval = ERROR_FLASH_OPERATION_FAILED;
402
403 /* set GLBCTRL.4 */
404 target_read_u32(target, 0xFFFFFFDC, &glbctrl);
405 target_write_u32(target, 0xFFFFFFDC, glbctrl | 0x10);
406
407 /* only perform the key match when 3VSTAT is clear */
408 target_read_u32(target, 0xFFE8BC0C, &fmmstat);
409 if (!(fmmstat & 0x08)) {
410 unsigned i;
411 uint32_t fmbptr, fmbac2, orig_fmregopt;
412
413 target_write_u32(target, 0xFFE8BC04, fmmstat & ~0x07);
414
415 /* wait for pump ready */
416 do {
417 target_read_u32(target, 0xFFE8A814, &fmbptr);
418 alive_sleep(1);
419 } while (!(fmbptr & 0x0200));
420
421 /* force max wait states */
422 target_read_u32(target, 0xFFE88004, &fmbac2);
423 target_write_u32(target, 0xFFE88004, fmbac2 | 0xff);
424
425 /* save current access mode, force normal read mode */
426 target_read_u32(target, 0xFFE89C00, &orig_fmregopt);
427 target_write_u32(target, 0xFFE89C00, 0x00);
428
429 for (i = 0; i < 4; i++) {
430 uint32_t tmp;
431
432 /* There is no point displaying the value of tmp, it is
433 * filtered by the chip. The purpose of this read is to
434 * prime the unlocking logic rather than read out the value.
435 */
436 target_read_u32(target, 0x00001FF0 + 4 * i, &tmp);
437
438 LOG_INFO("tms470 writing fmpkey = 0x%08" PRIx32 "", key_set[i]);
439 target_write_u32(target, 0xFFE89C0C, key_set[i]);
440 }
441
442 if (ERROR_OK == tms470_check_flash_unlocked(target)) {
443 /*
444 * There seems to be a side-effect of reading the FMPKEY
445 * register in that it re-enables the protection. So we
446 * re-enable it.
447 */
448 for (i = 0; i < 4; i++) {
449 uint32_t tmp;
450
451 target_read_u32(target, 0x00001FF0 + 4 * i, &tmp);
452 target_write_u32(target, 0xFFE89C0C, key_set[i]);
453 }
454 retval = ERROR_OK;
455 }
456
457 /* restore settings */
458 target_write_u32(target, 0xFFE89C00, orig_fmregopt);
459 target_write_u32(target, 0xFFE88004, fmbac2);
460 }
461
462 /* clear config bit */
463 target_write_u32(target, 0xFFFFFFDC, glbctrl);
464
465 return retval;
466 }
467
468 /* ---------------------------------------------------------------------- */
469
470 static int tms470_unlock_flash(struct flash_bank *bank)
471 {
472 struct target *target = bank->target;
473 const uint32_t *p_key_sets[5];
474 unsigned i, key_set_count;
475
476 if (keysSet) {
477 key_set_count = 5;
478 p_key_sets[0] = flashKeys;
479 p_key_sets[1] = FLASH_KEYS_ALL_ONES;
480 p_key_sets[2] = FLASH_KEYS_ALL_ZEROS;
481 p_key_sets[3] = FLASH_KEYS_MIX1;
482 p_key_sets[4] = FLASH_KEYS_MIX2;
483 } else {
484 key_set_count = 4;
485 p_key_sets[0] = FLASH_KEYS_ALL_ONES;
486 p_key_sets[1] = FLASH_KEYS_ALL_ZEROS;
487 p_key_sets[2] = FLASH_KEYS_MIX1;
488 p_key_sets[3] = FLASH_KEYS_MIX2;
489 }
490
491 for (i = 0; i < key_set_count; i++) {
492 if (tms470_try_flash_keys(target, p_key_sets[i]) == ERROR_OK) {
493 LOG_INFO("tms470 flash is unlocked");
494 return ERROR_OK;
495 }
496 }
497
498 LOG_WARNING("tms470 could not unlock flash memory protection level 2");
499 return ERROR_FLASH_OPERATION_FAILED;
500 }
501
502 /* ---------------------------------------------------------------------- */
503
504 static int tms470_flash_initialize_internal_state_machine(struct flash_bank *bank)
505 {
506 uint32_t fmmac2, fmmac1, fmmaxep, k, delay, glbctrl, sysclk;
507 struct target *target = bank->target;
508 struct tms470_flash_bank *tms470_info = bank->driver_priv;
509 int result = ERROR_OK;
510
511 /*
512 * Select the desired bank to be programmed by writing BANK[2:0] of
513 * FMMAC2.
514 */
515 target_read_u32(target, 0xFFE8BC04, &fmmac2);
516 fmmac2 &= ~0x0007;
517 fmmac2 |= (tms470_info->ordinal & 7);
518 target_write_u32(target, 0xFFE8BC04, fmmac2);
519 LOG_DEBUG("set fmmac2 = 0x%04" PRIx32 "", fmmac2);
520
521 /*
522 * Disable level 1 sector protection by setting bit 15 of FMMAC1.
523 */
524 target_read_u32(target, 0xFFE8BC00, &fmmac1);
525 fmmac1 |= 0x8000;
526 target_write_u32(target, 0xFFE8BC00, fmmac1);
527 LOG_DEBUG("set fmmac1 = 0x%04" PRIx32 "", fmmac1);
528
529 /*
530 * FMTCREG = 0x2fc0;
531 */
532 target_write_u32(target, 0xFFE8BC10, 0x2fc0);
533 LOG_DEBUG("set fmtcreg = 0x2fc0");
534
535 /*
536 * MAXPP = 50
537 */
538 target_write_u32(target, 0xFFE8A07C, 50);
539 LOG_DEBUG("set fmmaxpp = 50");
540
541 /*
542 * MAXCP = 0xf000 + 2000
543 */
544 target_write_u32(target, 0xFFE8A084, 0xf000 + 2000);
545 LOG_DEBUG("set fmmaxcp = 0x%04x", 0xf000 + 2000);
546
547 /*
548 * configure VHV
549 */
550 target_read_u32(target, 0xFFE8A080, &fmmaxep);
551 if (fmmaxep == 0xf000) {
552 fmmaxep = 0xf000 + 4095;
553 target_write_u32(target, 0xFFE8A80C, 0x9964);
554 LOG_DEBUG("set fmptr3 = 0x9964");
555 } else {
556 fmmaxep = 0xa000 + 4095;
557 target_write_u32(target, 0xFFE8A80C, 0x9b64);
558 LOG_DEBUG("set fmptr3 = 0x9b64");
559 }
560 target_write_u32(target, 0xFFE8A080, fmmaxep);
561 LOG_DEBUG("set fmmaxep = 0x%04" PRIx32 "", fmmaxep);
562
563 /*
564 * FMPTR4 = 0xa000
565 */
566 target_write_u32(target, 0xFFE8A810, 0xa000);
567 LOG_DEBUG("set fmptr4 = 0xa000");
568
569 /*
570 * FMPESETUP, delay parameter selected based on clock frequency.
571 *
572 * According to the TI App Note SPNU257 and flashing code, delay is
573 * int((sysclk(MHz) + 1) / 2), with a minimum of 5. The system
574 * clock is usually derived from the ZPLL module, and selected by
575 * the plldis global.
576 */
577 target_read_u32(target, 0xFFFFFFDC, &glbctrl);
578 sysclk = (plldis ? 1 : (glbctrl & 0x08) ? 4 : 8) * oscMHz / (1 + (glbctrl & 7));
579 delay = (sysclk > 10) ? (sysclk + 1) / 2 : 5;
580 target_write_u32(target, 0xFFE8A018, (delay << 4) | (delay << 8));
581 LOG_DEBUG("set fmpsetup = 0x%04" PRIx32 "", (delay << 4) | (delay << 8));
582
583 /*
584 * FMPVEVACCESS, based on delay.
585 */
586 k = delay | (delay << 8);
587 target_write_u32(target, 0xFFE8A05C, k);
588 LOG_DEBUG("set fmpvevaccess = 0x%04" PRIx32 "", k);
589
590 /*
591 * FMPCHOLD, FMPVEVHOLD, FMPVEVSETUP, based on delay.
592 */
593 k <<= 1;
594 target_write_u32(target, 0xFFE8A034, k);
595 LOG_DEBUG("set fmpchold = 0x%04" PRIx32 "", k);
596 target_write_u32(target, 0xFFE8A040, k);
597 LOG_DEBUG("set fmpvevhold = 0x%04" PRIx32 "", k);
598 target_write_u32(target, 0xFFE8A024, k);
599 LOG_DEBUG("set fmpvevsetup = 0x%04" PRIx32 "", k);
600
601 /*
602 * FMCVACCESS, based on delay.
603 */
604 k = delay * 16;
605 target_write_u32(target, 0xFFE8A060, k);
606 LOG_DEBUG("set fmcvaccess = 0x%04" PRIx32 "", k);
607
608 /*
609 * FMCSETUP, based on delay.
610 */
611 k = 0x3000 | delay * 20;
612 target_write_u32(target, 0xFFE8A020, k);
613 LOG_DEBUG("set fmcsetup = 0x%04" PRIx32 "", k);
614
615 /*
616 * FMEHOLD, based on delay.
617 */
618 k = (delay * 20) << 2;
619 target_write_u32(target, 0xFFE8A038, k);
620 LOG_DEBUG("set fmehold = 0x%04" PRIx32 "", k);
621
622 /*
623 * PWIDTH, CWIDTH, EWIDTH, based on delay.
624 */
625 target_write_u32(target, 0xFFE8A050, delay * 8);
626 LOG_DEBUG("set fmpwidth = 0x%04" PRIx32 "", delay * 8);
627 target_write_u32(target, 0xFFE8A058, delay * 1000);
628 LOG_DEBUG("set fmcwidth = 0x%04" PRIx32 "", delay * 1000);
629 target_write_u32(target, 0xFFE8A054, delay * 5400);
630 LOG_DEBUG("set fmewidth = 0x%04" PRIx32 "", delay * 5400);
631
632 return result;
633 }
634
635 /* ---------------------------------------------------------------------- */
636
637 static int tms470_flash_status(struct flash_bank *bank)
638 {
639 struct target *target = bank->target;
640 int result = ERROR_OK;
641 uint32_t fmmstat;
642
643 target_read_u32(target, 0xFFE8BC0C, &fmmstat);
644 LOG_DEBUG("set fmmstat = 0x%04" PRIx32 "", fmmstat);
645
646 if (fmmstat & 0x0080) {
647 LOG_WARNING("tms470 flash command: erase still active after busy clear.");
648 result = ERROR_FLASH_OPERATION_FAILED;
649 }
650
651 if (fmmstat & 0x0040) {
652 LOG_WARNING("tms470 flash command: program still active after busy clear.");
653 result = ERROR_FLASH_OPERATION_FAILED;
654 }
655
656 if (fmmstat & 0x0020) {
657 LOG_WARNING("tms470 flash command: invalid data command.");
658 result = ERROR_FLASH_OPERATION_FAILED;
659 }
660
661 if (fmmstat & 0x0010) {
662 LOG_WARNING("tms470 flash command: program, erase or validate sector failed.");
663 result = ERROR_FLASH_OPERATION_FAILED;
664 }
665
666 if (fmmstat & 0x0008) {
667 LOG_WARNING("tms470 flash command: voltage instability detected.");
668 result = ERROR_FLASH_OPERATION_FAILED;
669 }
670
671 if (fmmstat & 0x0006) {
672 LOG_WARNING("tms470 flash command: command suspend detected.");
673 result = ERROR_FLASH_OPERATION_FAILED;
674 }
675
676 if (fmmstat & 0x0001) {
677 LOG_WARNING("tms470 flash command: sector was locked.");
678 result = ERROR_FLASH_OPERATION_FAILED;
679 }
680
681 return result;
682 }
683
684 /* ---------------------------------------------------------------------- */
685
686 static int tms470_erase_sector(struct flash_bank *bank, int sector)
687 {
688 uint32_t glbctrl, orig_fmregopt, fmbsea, fmbseb, fmmstat;
689 struct target *target = bank->target;
690 uint32_t flashAddr = bank->base + bank->sectors[sector].offset;
691 int result = ERROR_OK;
692
693 /*
694 * Set the bit GLBCTRL4 of the GLBCTRL register (in the System
695 * module) to enable writing to the flash registers }.
696 */
697 target_read_u32(target, 0xFFFFFFDC, &glbctrl);
698 target_write_u32(target, 0xFFFFFFDC, glbctrl | 0x10);
699 LOG_DEBUG("set glbctrl = 0x%08" PRIx32 "", glbctrl | 0x10);
700
701 /* Force normal read mode. */
702 target_read_u32(target, 0xFFE89C00, &orig_fmregopt);
703 target_write_u32(target, 0xFFE89C00, 0);
704 LOG_DEBUG("set fmregopt = 0x%08x", 0);
705
706 (void)tms470_flash_initialize_internal_state_machine(bank);
707
708 /*
709 * Select one or more bits in FMBSEA or FMBSEB to disable Level 1
710 * protection for the particular sector to be erased/written.
711 */
712 if (sector < 16) {
713 target_read_u32(target, 0xFFE88008, &fmbsea);
714 target_write_u32(target, 0xFFE88008, fmbsea | (1 << sector));
715 LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea | (1 << sector));
716 } else {
717 target_read_u32(target, 0xFFE8800C, &fmbseb);
718 target_write_u32(target, 0xFFE8800C, fmbseb | (1 << (sector - 16)));
719 LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb | (1 << (sector - 16)));
720 }
721 bank->sectors[sector].is_protected = 0;
722
723 /*
724 * clear status regiser, sent erase command, kickoff erase
725 */
726 target_write_u16(target, flashAddr, 0x0040);
727 LOG_DEBUG("write *(uint16_t *)0x%08" PRIx32 "=0x0040", flashAddr);
728 target_write_u16(target, flashAddr, 0x0020);
729 LOG_DEBUG("write *(uint16_t *)0x%08" PRIx32 "=0x0020", flashAddr);
730 target_write_u16(target, flashAddr, 0xffff);
731 LOG_DEBUG("write *(uint16_t *)0x%08" PRIx32 "=0xffff", flashAddr);
732
733 /*
734 * Monitor FMMSTAT, busy until clear, then check and other flags for
735 * ultimate result of the operation.
736 */
737 do {
738 target_read_u32(target, 0xFFE8BC0C, &fmmstat);
739 if (fmmstat & 0x0100)
740 alive_sleep(1);
741 } while (fmmstat & 0x0100);
742
743 result = tms470_flash_status(bank);
744
745 if (sector < 16) {
746 target_write_u32(target, 0xFFE88008, fmbsea);
747 LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea);
748 bank->sectors[sector].is_protected = fmbsea & (1 << sector) ? 0 : 1;
749 } else {
750 target_write_u32(target, 0xFFE8800C, fmbseb);
751 LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb);
752 bank->sectors[sector].is_protected = fmbseb & (1 << (sector - 16)) ? 0 : 1;
753 }
754 target_write_u32(target, 0xFFE89C00, orig_fmregopt);
755 LOG_DEBUG("set fmregopt = 0x%08" PRIx32 "", orig_fmregopt);
756 target_write_u32(target, 0xFFFFFFDC, glbctrl);
757 LOG_DEBUG("set glbctrl = 0x%08" PRIx32 "", glbctrl);
758
759 return result;
760 }
761
762 /*----------------------------------------------------------------------
763 * Implementation of Flash Driver Interfaces
764 *---------------------------------------------------------------------- */
765
766 static const struct command_registration tms470_any_command_handlers[] = {
767 {
768 .name = "flash_keyset",
769 .usage = "<key0> <key1> <key2> <key3>",
770 .handler = tms470_handle_flash_keyset_command,
771 .mode = COMMAND_ANY,
772 .help = "tms470 flash_keyset <key0> <key1> <key2> <key3>",
773 },
774 {
775 .name = "osc_megahertz",
776 .usage = "<MHz>",
777 .handler = tms470_handle_osc_megahertz_command,
778 .mode = COMMAND_ANY,
779 .help = "tms470 osc_megahertz <MHz>",
780 },
781 {
782 .name = "plldis",
783 .usage = "<0 | 1>",
784 .handler = tms470_handle_plldis_command,
785 .mode = COMMAND_ANY,
786 .help = "tms470 plldis <0/1>",
787 },
788 COMMAND_REGISTRATION_DONE
789 };
790 static const struct command_registration tms470_command_handlers[] = {
791 {
792 .name = "tms470",
793 .mode = COMMAND_ANY,
794 .help = "TI tms470 flash command group",
795 .usage = "",
796 .chain = tms470_any_command_handlers,
797 },
798 COMMAND_REGISTRATION_DONE
799 };
800
801 /* ---------------------------------------------------------------------- */
802
803 static int tms470_erase(struct flash_bank *bank, int first, int last)
804 {
805 struct tms470_flash_bank *tms470_info = bank->driver_priv;
806 int sector, result = ERROR_OK;
807
808 if (bank->target->state != TARGET_HALTED) {
809 LOG_ERROR("Target not halted");
810 return ERROR_TARGET_NOT_HALTED;
811 }
812
813 tms470_read_part_info(bank);
814
815 if ((first < 0) || (first >= bank->num_sectors) || (last < 0) ||
816 (last >= bank->num_sectors) || (first > last)) {
817 LOG_ERROR("Sector range %d to %d invalid.", first, last);
818 return ERROR_FLASH_SECTOR_INVALID;
819 }
820
821 result = tms470_unlock_flash(bank);
822 if (result != ERROR_OK)
823 return result;
824
825 for (sector = first; sector <= last; sector++) {
826 LOG_INFO("Erasing tms470 bank %d sector %d...", tms470_info->ordinal, sector);
827
828 result = tms470_erase_sector(bank, sector);
829
830 if (result != ERROR_OK) {
831 LOG_ERROR("tms470 could not erase flash sector.");
832 break;
833 } else
834 LOG_INFO("sector erased successfully.");
835 }
836
837 return result;
838 }
839
840 /* ---------------------------------------------------------------------- */
841
842 static int tms470_protect(struct flash_bank *bank, int set, int first, int last)
843 {
844 struct tms470_flash_bank *tms470_info = bank->driver_priv;
845 struct target *target = bank->target;
846 uint32_t fmmac2, fmbsea, fmbseb;
847 int sector;
848
849 if (target->state != TARGET_HALTED) {
850 LOG_ERROR("Target not halted");
851 return ERROR_TARGET_NOT_HALTED;
852 }
853
854 tms470_read_part_info(bank);
855
856 if ((first < 0) || (first >= bank->num_sectors) || (last < 0) ||
857 (last >= bank->num_sectors) || (first > last)) {
858 LOG_ERROR("Sector range %d to %d invalid.", first, last);
859 return ERROR_FLASH_SECTOR_INVALID;
860 }
861
862 /* enable the appropriate bank */
863 target_read_u32(target, 0xFFE8BC04, &fmmac2);
864 target_write_u32(target, 0xFFE8BC04, (fmmac2 & ~7) | tms470_info->ordinal);
865
866 /* get the original sector proection flags for this bank */
867 target_read_u32(target, 0xFFE88008, &fmbsea);
868 target_read_u32(target, 0xFFE8800C, &fmbseb);
869
870 for (sector = 0; sector < bank->num_sectors; sector++) {
871 if (sector < 16) {
872 fmbsea = set ? fmbsea & ~(1 << sector) : fmbsea | (1 << sector);
873 bank->sectors[sector].is_protected = set ? 1 : 0;
874 } else {
875 fmbseb = set ? fmbseb &
876 ~(1 << (sector - 16)) : fmbseb | (1 << (sector - 16));
877 bank->sectors[sector].is_protected = set ? 1 : 0;
878 }
879 }
880
881 /* update the protection bits */
882 target_write_u32(target, 0xFFE88008, fmbsea);
883 target_write_u32(target, 0xFFE8800C, fmbseb);
884
885 return ERROR_OK;
886 }
887
888 /* ---------------------------------------------------------------------- */
889
890 static int tms470_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
891 {
892 struct target *target = bank->target;
893 uint32_t glbctrl, fmbac2, orig_fmregopt, fmbsea, fmbseb, fmmaxpp, fmmstat;
894 int result = ERROR_OK;
895 uint32_t i;
896
897 if (target->state != TARGET_HALTED) {
898 LOG_ERROR("Target not halted");
899 return ERROR_TARGET_NOT_HALTED;
900 }
901
902 tms470_read_part_info(bank);
903
904 LOG_INFO("Writing %" PRId32 " bytes starting at " TARGET_ADDR_FMT,
905 count, bank->base + offset);
906
907 /* set GLBCTRL.4 */
908 target_read_u32(target, 0xFFFFFFDC, &glbctrl);
909 target_write_u32(target, 0xFFFFFFDC, glbctrl | 0x10);
910
911 (void)tms470_flash_initialize_internal_state_machine(bank);
912
913 /* force max wait states */
914 target_read_u32(target, 0xFFE88004, &fmbac2);
915 target_write_u32(target, 0xFFE88004, fmbac2 | 0xff);
916
917 /* save current access mode, force normal read mode */
918 target_read_u32(target, 0xFFE89C00, &orig_fmregopt);
919 target_write_u32(target, 0xFFE89C00, 0x00);
920
921 /*
922 * Disable Level 1 protection for all sectors to be erased/written.
923 */
924 target_read_u32(target, 0xFFE88008, &fmbsea);
925 target_write_u32(target, 0xFFE88008, 0xffff);
926 target_read_u32(target, 0xFFE8800C, &fmbseb);
927 target_write_u32(target, 0xFFE8800C, 0xffff);
928
929 /* read MAXPP */
930 target_read_u32(target, 0xFFE8A07C, &fmmaxpp);
931
932 for (i = 0; i < count; i += 2) {
933 uint32_t addr = bank->base + offset + i;
934 uint16_t word = (((uint16_t) buffer[i]) << 8) | (uint16_t) buffer[i + 1];
935
936 if (word != 0xffff) {
937 LOG_INFO("writing 0x%04x at 0x%08" PRIx32 "", word, addr);
938
939 /* clear status register */
940 target_write_u16(target, addr, 0x0040);
941 /* program flash command */
942 target_write_u16(target, addr, 0x0010);
943 /* burn the 16-bit word (big-endian) */
944 target_write_u16(target, addr, word);
945
946 /*
947 * Monitor FMMSTAT, busy until clear, then check and other flags
948 * for ultimate result of the operation.
949 */
950 do {
951 target_read_u32(target, 0xFFE8BC0C, &fmmstat);
952 if (fmmstat & 0x0100)
953 alive_sleep(1);
954 } while (fmmstat & 0x0100);
955
956 if (fmmstat & 0x3ff) {
957 LOG_ERROR("fmstat = 0x%04" PRIx32 "", fmmstat);
958 LOG_ERROR(
959 "Could not program word 0x%04x at address 0x%08" PRIx32 ".",
960 word,
961 addr);
962 result = ERROR_FLASH_OPERATION_FAILED;
963 break;
964 }
965 } else
966 LOG_INFO("skipping 0xffff at 0x%08" PRIx32 "", addr);
967 }
968
969 /* restore */
970 target_write_u32(target, 0xFFE88008, fmbsea);
971 target_write_u32(target, 0xFFE8800C, fmbseb);
972 target_write_u32(target, 0xFFE88004, fmbac2);
973 target_write_u32(target, 0xFFE89C00, orig_fmregopt);
974 target_write_u32(target, 0xFFFFFFDC, glbctrl);
975
976 return result;
977 }
978
979 /* ---------------------------------------------------------------------- */
980
981 static int tms470_probe(struct flash_bank *bank)
982 {
983 if (bank->target->state != TARGET_HALTED) {
984 LOG_WARNING("Cannot communicate... target not halted.");
985 return ERROR_TARGET_NOT_HALTED;
986 }
987
988 return tms470_read_part_info(bank);
989 }
990
991 static int tms470_auto_probe(struct flash_bank *bank)
992 {
993 struct tms470_flash_bank *tms470_info = bank->driver_priv;
994
995 if (tms470_info->device_ident_reg)
996 return ERROR_OK;
997 return tms470_probe(bank);
998 }
999
1000 /* ---------------------------------------------------------------------- */
1001
1002 static int tms470_erase_check(struct flash_bank *bank)
1003 {
1004 struct target *target = bank->target;
1005 struct tms470_flash_bank *tms470_info = bank->driver_priv;
1006 int sector, result = ERROR_OK;
1007 uint32_t fmmac2, fmbac2, glbctrl, orig_fmregopt;
1008 static uint8_t buffer[64 * 1024];
1009
1010 if (target->state != TARGET_HALTED) {
1011 LOG_ERROR("Target not halted");
1012 return ERROR_TARGET_NOT_HALTED;
1013 }
1014
1015 if (!tms470_info->device_ident_reg)
1016 tms470_read_part_info(bank);
1017
1018 /* set GLBCTRL.4 */
1019 target_read_u32(target, 0xFFFFFFDC, &glbctrl);
1020 target_write_u32(target, 0xFFFFFFDC, glbctrl | 0x10);
1021
1022 /* save current access mode, force normal read mode */
1023 target_read_u32(target, 0xFFE89C00, &orig_fmregopt);
1024 target_write_u32(target, 0xFFE89C00, 0x00);
1025
1026 /* enable the appropriate bank */
1027 target_read_u32(target, 0xFFE8BC04, &fmmac2);
1028 target_write_u32(target, 0xFFE8BC04, (fmmac2 & ~7) | tms470_info->ordinal);
1029
1030 /* TCR = 0 */
1031 target_write_u32(target, 0xFFE8BC10, 0x2fc0);
1032
1033 /* clear TEZ in fmbrdy */
1034 target_write_u32(target, 0xFFE88010, 0x0b);
1035
1036 /* save current wait states, force max */
1037 target_read_u32(target, 0xFFE88004, &fmbac2);
1038 target_write_u32(target, 0xFFE88004, fmbac2 | 0xff);
1039
1040 /*
1041 * The TI primitives inspect the flash memory by reading one 32-bit
1042 * word at a time. Here we read an entire sector and inspect it in
1043 * an attempt to reduce the JTAG overhead.
1044 */
1045 for (sector = 0; sector < bank->num_sectors; sector++) {
1046 uint32_t i, addr = bank->base + bank->sectors[sector].offset;
1047
1048 LOG_INFO("checking flash bank %d sector %d", tms470_info->ordinal, sector);
1049
1050 target_read_buffer(target, addr, bank->sectors[sector].size, buffer);
1051
1052 bank->sectors[sector].is_erased = 1;
1053 for (i = 0; i < bank->sectors[sector].size; i++) {
1054 if (buffer[i] != 0xff) {
1055 bank->sectors[sector].is_erased = 0;
1056 break;
1057 }
1058 }
1059 if (bank->sectors[sector].is_erased != 1) {
1060 result = ERROR_FLASH_SECTOR_NOT_ERASED;
1061 break;
1062 } else
1063 LOG_INFO("sector erased");
1064 }
1065
1066 /* reset TEZ, wait states, read mode, GLBCTRL.4 */
1067 target_write_u32(target, 0xFFE88010, 0x0f);
1068 target_write_u32(target, 0xFFE88004, fmbac2);
1069 target_write_u32(target, 0xFFE89C00, orig_fmregopt);
1070 target_write_u32(target, 0xFFFFFFDC, glbctrl);
1071
1072 return result;
1073 }
1074
1075 /* ---------------------------------------------------------------------- */
1076
1077 static int tms470_protect_check(struct flash_bank *bank)
1078 {
1079 struct target *target = bank->target;
1080 struct tms470_flash_bank *tms470_info = bank->driver_priv;
1081 int sector, result = ERROR_OK;
1082 uint32_t fmmac2, fmbsea, fmbseb;
1083
1084 if (target->state != TARGET_HALTED) {
1085 LOG_ERROR("Target not halted");
1086 return ERROR_TARGET_NOT_HALTED;
1087 }
1088
1089 if (!tms470_info->device_ident_reg)
1090 tms470_read_part_info(bank);
1091
1092 /* enable the appropriate bank */
1093 target_read_u32(target, 0xFFE8BC04, &fmmac2);
1094 target_write_u32(target, 0xFFE8BC04, (fmmac2 & ~7) | tms470_info->ordinal);
1095
1096 target_read_u32(target, 0xFFE88008, &fmbsea);
1097 target_read_u32(target, 0xFFE8800C, &fmbseb);
1098
1099 for (sector = 0; sector < bank->num_sectors; sector++) {
1100 int protected;
1101
1102 if (sector < 16) {
1103 protected = fmbsea & (1 << sector) ? 0 : 1;
1104 bank->sectors[sector].is_protected = protected;
1105 } else {
1106 protected = fmbseb & (1 << (sector - 16)) ? 0 : 1;
1107 bank->sectors[sector].is_protected = protected;
1108 }
1109
1110 LOG_DEBUG("bank %d sector %d is %s",
1111 tms470_info->ordinal,
1112 sector,
1113 protected ? "protected" : "not protected");
1114 }
1115
1116 return result;
1117 }
1118
1119 /* ---------------------------------------------------------------------- */
1120
1121 static int get_tms470_info(struct flash_bank *bank, char *buf, int buf_size)
1122 {
1123 int used = 0;
1124 struct tms470_flash_bank *tms470_info = bank->driver_priv;
1125
1126 if (!tms470_info->device_ident_reg)
1127 tms470_read_part_info(bank);
1128
1129 if (!tms470_info->device_ident_reg) {
1130 (void)snprintf(buf, buf_size, "Cannot identify target as a TMS470\n");
1131 return ERROR_FLASH_OPERATION_FAILED;
1132 }
1133
1134 used =
1135 snprintf(buf, buf_size, "\ntms470 information: Chip is %s\n",
1136 tms470_info->part_name);
1137 buf += used;
1138 buf_size -= used;
1139
1140 snprintf(buf, buf_size, "Flash protection level 2 is %s\n",
1141 tms470_check_flash_unlocked(bank->target) == ERROR_OK ? "disabled" : "enabled");
1142
1143 return ERROR_OK;
1144 }
1145
1146 /* ---------------------------------------------------------------------- */
1147
1148 /*
1149 * flash bank tms470 <base> <size> <chip_width> <bus_width> <target>
1150 * [options...]
1151 */
1152
1153 FLASH_BANK_COMMAND_HANDLER(tms470_flash_bank_command)
1154 {
1155 bank->driver_priv = malloc(sizeof(struct tms470_flash_bank));
1156
1157 if (!bank->driver_priv)
1158 return ERROR_FLASH_OPERATION_FAILED;
1159
1160 (void)memset(bank->driver_priv, 0, sizeof(struct tms470_flash_bank));
1161
1162 return ERROR_OK;
1163 }
1164
1165 const struct flash_driver tms470_flash = {
1166 .name = "tms470",
1167 .commands = tms470_command_handlers,
1168 .flash_bank_command = tms470_flash_bank_command,
1169 .erase = tms470_erase,
1170 .protect = tms470_protect,
1171 .write = tms470_write,
1172 .read = default_flash_read,
1173 .probe = tms470_probe,
1174 .auto_probe = tms470_auto_probe,
1175 .erase_check = tms470_erase_check,
1176 .protect_check = tms470_protect_check,
1177 .info = get_tms470_info,
1178 .free_driver_priv = default_flash_free_driver_priv,
1179 };

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)