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

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)