4b8d2208afef5a440e471c52616ec6cd8c263446
[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, "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, "tms470 flash_keyset <key0> <key1> <key2> <key3>");
314 return ERROR_COMMAND_SYNTAX_ERROR;
315 }
316
317 if (keysSet) {
318 command_print(CMD,
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, "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, "osc_megahertz must be positive and non-zero!");
356 oscMHz = 12;
357 return ERROR_COMMAND_SYNTAX_ERROR;
358 }
359
360 command_print(CMD, "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, "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 assert(sector >= 0);
713 if (sector < 16) {
714 target_read_u32(target, 0xFFE88008, &fmbsea);
715 target_write_u32(target, 0xFFE88008, fmbsea | (1 << sector));
716 LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea | (1 << sector));
717 } else {
718 target_read_u32(target, 0xFFE8800C, &fmbseb);
719 target_write_u32(target, 0xFFE8800C, fmbseb | (1 << (sector - 16)));
720 LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb | (1 << (sector - 16)));
721 }
722 bank->sectors[sector].is_protected = 0;
723
724 /*
725 * clear status register, sent erase command, kickoff erase
726 */
727 target_write_u16(target, flashAddr, 0x0040);
728 LOG_DEBUG("write *(uint16_t *)0x%08" PRIx32 "=0x0040", flashAddr);
729 target_write_u16(target, flashAddr, 0x0020);
730 LOG_DEBUG("write *(uint16_t *)0x%08" PRIx32 "=0x0020", flashAddr);
731 target_write_u16(target, flashAddr, 0xffff);
732 LOG_DEBUG("write *(uint16_t *)0x%08" PRIx32 "=0xffff", flashAddr);
733
734 /*
735 * Monitor FMMSTAT, busy until clear, then check and other flags for
736 * ultimate result of the operation.
737 */
738 do {
739 target_read_u32(target, 0xFFE8BC0C, &fmmstat);
740 if (fmmstat & 0x0100)
741 alive_sleep(1);
742 } while (fmmstat & 0x0100);
743
744 result = tms470_flash_status(bank);
745
746 if (sector < 16) {
747 target_write_u32(target, 0xFFE88008, fmbsea);
748 LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea);
749 bank->sectors[sector].is_protected = fmbsea & (1 << sector) ? 0 : 1;
750 } else {
751 target_write_u32(target, 0xFFE8800C, fmbseb);
752 LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb);
753 bank->sectors[sector].is_protected = fmbseb & (1 << (sector - 16)) ? 0 : 1;
754 }
755 target_write_u32(target, 0xFFE89C00, orig_fmregopt);
756 LOG_DEBUG("set fmregopt = 0x%08" PRIx32 "", orig_fmregopt);
757 target_write_u32(target, 0xFFFFFFDC, glbctrl);
758 LOG_DEBUG("set glbctrl = 0x%08" PRIx32 "", glbctrl);
759
760 return result;
761 }
762
763 /*----------------------------------------------------------------------
764 * Implementation of Flash Driver Interfaces
765 *---------------------------------------------------------------------- */
766
767 static const struct command_registration tms470_any_command_handlers[] = {
768 {
769 .name = "flash_keyset",
770 .usage = "<key0> <key1> <key2> <key3>",
771 .handler = tms470_handle_flash_keyset_command,
772 .mode = COMMAND_ANY,
773 .help = "tms470 flash_keyset <key0> <key1> <key2> <key3>",
774 },
775 {
776 .name = "osc_megahertz",
777 .usage = "<MHz>",
778 .handler = tms470_handle_osc_megahertz_command,
779 .mode = COMMAND_ANY,
780 .help = "tms470 osc_megahertz <MHz>",
781 },
782 {
783 .name = "plldis",
784 .usage = "<0 | 1>",
785 .handler = tms470_handle_plldis_command,
786 .mode = COMMAND_ANY,
787 .help = "tms470 plldis <0/1>",
788 },
789 COMMAND_REGISTRATION_DONE
790 };
791 static const struct command_registration tms470_command_handlers[] = {
792 {
793 .name = "tms470",
794 .mode = COMMAND_ANY,
795 .help = "TI tms470 flash command group",
796 .usage = "",
797 .chain = tms470_any_command_handlers,
798 },
799 COMMAND_REGISTRATION_DONE
800 };
801
802 /* ---------------------------------------------------------------------- */
803
804 static int tms470_erase(struct flash_bank *bank, unsigned int first,
805 unsigned int last)
806 {
807 struct tms470_flash_bank *tms470_info = bank->driver_priv;
808 int result = ERROR_OK;
809
810 if (bank->target->state != TARGET_HALTED) {
811 LOG_ERROR("Target not halted");
812 return ERROR_TARGET_NOT_HALTED;
813 }
814
815 tms470_read_part_info(bank);
816
817 if ((first >= bank->num_sectors) || (last >= bank->num_sectors) ||
818 (first > last)) {
819 LOG_ERROR("Sector range %u to %u invalid.", first, last);
820 return ERROR_FLASH_SECTOR_INVALID;
821 }
822
823 result = tms470_unlock_flash(bank);
824 if (result != ERROR_OK)
825 return result;
826
827 for (unsigned int sector = first; sector <= last; sector++) {
828 LOG_INFO("Erasing tms470 bank %u sector %u...", tms470_info->ordinal, sector);
829
830 result = tms470_erase_sector(bank, sector);
831
832 if (result != ERROR_OK) {
833 LOG_ERROR("tms470 could not erase flash sector.");
834 break;
835 } else
836 LOG_INFO("sector erased successfully.");
837 }
838
839 return result;
840 }
841
842 /* ---------------------------------------------------------------------- */
843
844 static int tms470_protect(struct flash_bank *bank, int set, unsigned int first,
845 unsigned int last)
846 {
847 struct tms470_flash_bank *tms470_info = bank->driver_priv;
848 struct target *target = bank->target;
849 uint32_t fmmac2, fmbsea, fmbseb;
850
851 if (target->state != TARGET_HALTED) {
852 LOG_ERROR("Target not halted");
853 return ERROR_TARGET_NOT_HALTED;
854 }
855
856 tms470_read_part_info(bank);
857
858 if ((first >= bank->num_sectors) || (last >= bank->num_sectors) ||
859 (first > last)) {
860 LOG_ERROR("Sector range %u to %u invalid.", first, last);
861 return ERROR_FLASH_SECTOR_INVALID;
862 }
863
864 /* enable the appropriate bank */
865 target_read_u32(target, 0xFFE8BC04, &fmmac2);
866 target_write_u32(target, 0xFFE8BC04, (fmmac2 & ~7) | tms470_info->ordinal);
867
868 /* get the original sector protection flags for this bank */
869 target_read_u32(target, 0xFFE88008, &fmbsea);
870 target_read_u32(target, 0xFFE8800C, &fmbseb);
871
872 for (unsigned int sector = 0; sector < bank->num_sectors; sector++) {
873 if (sector < 16) {
874 fmbsea = set ? fmbsea & ~(1 << sector) : fmbsea | (1 << sector);
875 bank->sectors[sector].is_protected = set ? 1 : 0;
876 } else {
877 fmbseb = set ? fmbseb &
878 ~(1 << (sector - 16)) : fmbseb | (1 << (sector - 16));
879 bank->sectors[sector].is_protected = set ? 1 : 0;
880 }
881 }
882
883 /* update the protection bits */
884 target_write_u32(target, 0xFFE88008, fmbsea);
885 target_write_u32(target, 0xFFE8800C, fmbseb);
886
887 return ERROR_OK;
888 }
889
890 /* ---------------------------------------------------------------------- */
891
892 static int tms470_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
893 {
894 struct target *target = bank->target;
895 uint32_t glbctrl, fmbac2, orig_fmregopt, fmbsea, fmbseb, fmmaxpp, fmmstat;
896 int result = ERROR_OK;
897 uint32_t i;
898
899 if (target->state != TARGET_HALTED) {
900 LOG_ERROR("Target not halted");
901 return ERROR_TARGET_NOT_HALTED;
902 }
903
904 tms470_read_part_info(bank);
905
906 LOG_INFO("Writing %" PRId32 " bytes starting at " TARGET_ADDR_FMT,
907 count, bank->base + offset);
908
909 /* set GLBCTRL.4 */
910 target_read_u32(target, 0xFFFFFFDC, &glbctrl);
911 target_write_u32(target, 0xFFFFFFDC, glbctrl | 0x10);
912
913 (void)tms470_flash_initialize_internal_state_machine(bank);
914
915 /* force max wait states */
916 target_read_u32(target, 0xFFE88004, &fmbac2);
917 target_write_u32(target, 0xFFE88004, fmbac2 | 0xff);
918
919 /* save current access mode, force normal read mode */
920 target_read_u32(target, 0xFFE89C00, &orig_fmregopt);
921 target_write_u32(target, 0xFFE89C00, 0x00);
922
923 /*
924 * Disable Level 1 protection for all sectors to be erased/written.
925 */
926 target_read_u32(target, 0xFFE88008, &fmbsea);
927 target_write_u32(target, 0xFFE88008, 0xffff);
928 target_read_u32(target, 0xFFE8800C, &fmbseb);
929 target_write_u32(target, 0xFFE8800C, 0xffff);
930
931 /* read MAXPP */
932 target_read_u32(target, 0xFFE8A07C, &fmmaxpp);
933
934 for (i = 0; i < count; i += 2) {
935 uint32_t addr = bank->base + offset + i;
936 uint16_t word = (((uint16_t) buffer[i]) << 8) | (uint16_t) buffer[i + 1];
937
938 if (word != 0xffff) {
939 LOG_INFO("writing 0x%04x at 0x%08" PRIx32 "", word, addr);
940
941 /* clear status register */
942 target_write_u16(target, addr, 0x0040);
943 /* program flash command */
944 target_write_u16(target, addr, 0x0010);
945 /* burn the 16-bit word (big-endian) */
946 target_write_u16(target, addr, word);
947
948 /*
949 * Monitor FMMSTAT, busy until clear, then check and other flags
950 * for ultimate result of the operation.
951 */
952 do {
953 target_read_u32(target, 0xFFE8BC0C, &fmmstat);
954 if (fmmstat & 0x0100)
955 alive_sleep(1);
956 } while (fmmstat & 0x0100);
957
958 if (fmmstat & 0x3ff) {
959 LOG_ERROR("fmstat = 0x%04" PRIx32 "", fmmstat);
960 LOG_ERROR(
961 "Could not program word 0x%04x at address 0x%08" PRIx32 ".",
962 word,
963 addr);
964 result = ERROR_FLASH_OPERATION_FAILED;
965 break;
966 }
967 } else
968 LOG_INFO("skipping 0xffff at 0x%08" PRIx32 "", addr);
969 }
970
971 /* restore */
972 target_write_u32(target, 0xFFE88008, fmbsea);
973 target_write_u32(target, 0xFFE8800C, fmbseb);
974 target_write_u32(target, 0xFFE88004, fmbac2);
975 target_write_u32(target, 0xFFE89C00, orig_fmregopt);
976 target_write_u32(target, 0xFFFFFFDC, glbctrl);
977
978 return result;
979 }
980
981 /* ---------------------------------------------------------------------- */
982
983 static int tms470_probe(struct flash_bank *bank)
984 {
985 if (bank->target->state != TARGET_HALTED) {
986 LOG_WARNING("Cannot communicate... target not halted.");
987 return ERROR_TARGET_NOT_HALTED;
988 }
989
990 return tms470_read_part_info(bank);
991 }
992
993 static int tms470_auto_probe(struct flash_bank *bank)
994 {
995 struct tms470_flash_bank *tms470_info = bank->driver_priv;
996
997 if (tms470_info->device_ident_reg)
998 return ERROR_OK;
999 return tms470_probe(bank);
1000 }
1001
1002 /* ---------------------------------------------------------------------- */
1003
1004 static int tms470_erase_check(struct flash_bank *bank)
1005 {
1006 struct target *target = bank->target;
1007 struct tms470_flash_bank *tms470_info = bank->driver_priv;
1008 int result = ERROR_OK;
1009 uint32_t fmmac2, fmbac2, glbctrl, orig_fmregopt;
1010 static uint8_t buffer[64 * 1024];
1011
1012 if (target->state != TARGET_HALTED) {
1013 LOG_ERROR("Target not halted");
1014 return ERROR_TARGET_NOT_HALTED;
1015 }
1016
1017 if (!tms470_info->device_ident_reg)
1018 tms470_read_part_info(bank);
1019
1020 /* set GLBCTRL.4 */
1021 target_read_u32(target, 0xFFFFFFDC, &glbctrl);
1022 target_write_u32(target, 0xFFFFFFDC, glbctrl | 0x10);
1023
1024 /* save current access mode, force normal read mode */
1025 target_read_u32(target, 0xFFE89C00, &orig_fmregopt);
1026 target_write_u32(target, 0xFFE89C00, 0x00);
1027
1028 /* enable the appropriate bank */
1029 target_read_u32(target, 0xFFE8BC04, &fmmac2);
1030 target_write_u32(target, 0xFFE8BC04, (fmmac2 & ~7) | tms470_info->ordinal);
1031
1032 /* TCR = 0 */
1033 target_write_u32(target, 0xFFE8BC10, 0x2fc0);
1034
1035 /* clear TEZ in fmbrdy */
1036 target_write_u32(target, 0xFFE88010, 0x0b);
1037
1038 /* save current wait states, force max */
1039 target_read_u32(target, 0xFFE88004, &fmbac2);
1040 target_write_u32(target, 0xFFE88004, fmbac2 | 0xff);
1041
1042 /*
1043 * The TI primitives inspect the flash memory by reading one 32-bit
1044 * word at a time. Here we read an entire sector and inspect it in
1045 * an attempt to reduce the JTAG overhead.
1046 */
1047 for (unsigned int sector = 0; sector < bank->num_sectors; sector++) {
1048 uint32_t i, addr = bank->base + bank->sectors[sector].offset;
1049
1050 LOG_INFO("checking flash bank %u sector %u", tms470_info->ordinal, sector);
1051
1052 target_read_buffer(target, addr, bank->sectors[sector].size, buffer);
1053
1054 bank->sectors[sector].is_erased = 1;
1055 for (i = 0; i < bank->sectors[sector].size; i++) {
1056 if (buffer[i] != 0xff) {
1057 bank->sectors[sector].is_erased = 0;
1058 break;
1059 }
1060 }
1061 if (bank->sectors[sector].is_erased != 1) {
1062 result = ERROR_FLASH_SECTOR_NOT_ERASED;
1063 break;
1064 } else
1065 LOG_INFO("sector erased");
1066 }
1067
1068 /* reset TEZ, wait states, read mode, GLBCTRL.4 */
1069 target_write_u32(target, 0xFFE88010, 0x0f);
1070 target_write_u32(target, 0xFFE88004, fmbac2);
1071 target_write_u32(target, 0xFFE89C00, orig_fmregopt);
1072 target_write_u32(target, 0xFFFFFFDC, glbctrl);
1073
1074 return result;
1075 }
1076
1077 /* ---------------------------------------------------------------------- */
1078
1079 static int tms470_protect_check(struct flash_bank *bank)
1080 {
1081 struct target *target = bank->target;
1082 struct tms470_flash_bank *tms470_info = bank->driver_priv;
1083 int result = ERROR_OK;
1084 uint32_t fmmac2, fmbsea, fmbseb;
1085
1086 if (target->state != TARGET_HALTED) {
1087 LOG_ERROR("Target not halted");
1088 return ERROR_TARGET_NOT_HALTED;
1089 }
1090
1091 if (!tms470_info->device_ident_reg)
1092 tms470_read_part_info(bank);
1093
1094 /* enable the appropriate bank */
1095 target_read_u32(target, 0xFFE8BC04, &fmmac2);
1096 target_write_u32(target, 0xFFE8BC04, (fmmac2 & ~7) | tms470_info->ordinal);
1097
1098 target_read_u32(target, 0xFFE88008, &fmbsea);
1099 target_read_u32(target, 0xFFE8800C, &fmbseb);
1100
1101 for (unsigned int sector = 0; sector < bank->num_sectors; sector++) {
1102 int protected;
1103
1104 if (sector < 16) {
1105 protected = fmbsea & (1 << sector) ? 0 : 1;
1106 bank->sectors[sector].is_protected = protected;
1107 } else {
1108 protected = fmbseb & (1 << (sector - 16)) ? 0 : 1;
1109 bank->sectors[sector].is_protected = protected;
1110 }
1111
1112 LOG_DEBUG("bank %u sector %u is %s",
1113 tms470_info->ordinal,
1114 sector,
1115 protected ? "protected" : "not protected");
1116 }
1117
1118 return result;
1119 }
1120
1121 /* ---------------------------------------------------------------------- */
1122
1123 static int get_tms470_info(struct flash_bank *bank, char *buf, int buf_size)
1124 {
1125 int used = 0;
1126 struct tms470_flash_bank *tms470_info = bank->driver_priv;
1127
1128 if (!tms470_info->device_ident_reg)
1129 tms470_read_part_info(bank);
1130
1131 if (!tms470_info->device_ident_reg) {
1132 (void)snprintf(buf, buf_size, "Cannot identify target as a TMS470\n");
1133 return ERROR_FLASH_OPERATION_FAILED;
1134 }
1135
1136 used =
1137 snprintf(buf, buf_size, "\ntms470 information: Chip is %s\n",
1138 tms470_info->part_name);
1139 buf += used;
1140 buf_size -= used;
1141
1142 snprintf(buf, buf_size, "Flash protection level 2 is %s\n",
1143 tms470_check_flash_unlocked(bank->target) == ERROR_OK ? "disabled" : "enabled");
1144
1145 return ERROR_OK;
1146 }
1147
1148 /* ---------------------------------------------------------------------- */
1149
1150 /*
1151 * flash bank tms470 <base> <size> <chip_width> <bus_width> <target>
1152 * [options...]
1153 */
1154
1155 FLASH_BANK_COMMAND_HANDLER(tms470_flash_bank_command)
1156 {
1157 bank->driver_priv = malloc(sizeof(struct tms470_flash_bank));
1158
1159 if (!bank->driver_priv)
1160 return ERROR_FLASH_OPERATION_FAILED;
1161
1162 (void)memset(bank->driver_priv, 0, sizeof(struct tms470_flash_bank));
1163
1164 return ERROR_OK;
1165 }
1166
1167 const struct flash_driver tms470_flash = {
1168 .name = "tms470",
1169 .commands = tms470_command_handlers,
1170 .flash_bank_command = tms470_flash_bank_command,
1171 .erase = tms470_erase,
1172 .protect = tms470_protect,
1173 .write = tms470_write,
1174 .read = default_flash_read,
1175 .probe = tms470_probe,
1176 .auto_probe = tms470_auto_probe,
1177 .erase_check = tms470_erase_check,
1178 .protect_check = tms470_protect_check,
1179 .info = get_tms470_info,
1180 .free_driver_priv = default_flash_free_driver_priv,
1181 };

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)