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

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)