102bf1b15090944af0da86871eb241b09ee1ff13
[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 }
155
156 /*
157 * If the part number is known, determine if the flash bank is valid
158 * based on the base address being within the known flash bank
159 * ranges. Then fixup/complete the remaining fields of the flash
160 * bank structure.
161 */
162 switch (part_number) {
163 case 0x0a:
164 part_name = "TMS470R1A256";
165
166 if (bank->base >= 0x00040000) {
167 LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".",
168 part_name,
169 bank->base);
170 return ERROR_FLASH_OPERATION_FAILED;
171 }
172 tms470_info->ordinal = 0;
173 bank->base = 0x00000000;
174 bank->size = 256 * 1024;
175 bank->num_sectors = TMS470R1A256_NUM_SECTORS;
176 bank->sectors = malloc(sizeof(TMS470R1A256_SECTORS));
177 if (!bank->sectors)
178 return ERROR_FLASH_OPERATION_FAILED;
179 (void)memcpy(bank->sectors, TMS470R1A256_SECTORS, sizeof(TMS470R1A256_SECTORS));
180 break;
181
182 case 0x2b:
183 part_name = "TMS470R1A288";
184
185 if (bank->base < 0x00008000) {
186 tms470_info->ordinal = 0;
187 bank->base = 0x00000000;
188 bank->size = 32 * 1024;
189 bank->num_sectors = TMS470R1A288_BANK0_NUM_SECTORS;
190 bank->sectors = malloc(sizeof(TMS470R1A288_BANK0_SECTORS));
191 if (!bank->sectors)
192 return ERROR_FLASH_OPERATION_FAILED;
193 (void)memcpy(bank->sectors, TMS470R1A288_BANK0_SECTORS,
194 sizeof(TMS470R1A288_BANK0_SECTORS));
195 } else if ((bank->base >= 0x00040000) && (bank->base < 0x00080000)) {
196 tms470_info->ordinal = 1;
197 bank->base = 0x00040000;
198 bank->size = 256 * 1024;
199 bank->num_sectors = TMS470R1A288_BANK1_NUM_SECTORS;
200 bank->sectors = malloc(sizeof(TMS470R1A288_BANK1_SECTORS));
201 if (!bank->sectors)
202 return ERROR_FLASH_OPERATION_FAILED;
203 (void)memcpy(bank->sectors, TMS470R1A288_BANK1_SECTORS,
204 sizeof(TMS470R1A288_BANK1_SECTORS));
205 } else {
206 LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".",
207 part_name, bank->base);
208 return ERROR_FLASH_OPERATION_FAILED;
209 }
210 break;
211
212 case 0x2d:
213 part_name = "TMS470R1A384";
214
215 if (bank->base < 0x00020000) {
216 tms470_info->ordinal = 0;
217 bank->base = 0x00000000;
218 bank->size = 128 * 1024;
219 bank->num_sectors = TMS470R1A384_BANK0_NUM_SECTORS;
220 bank->sectors = malloc(sizeof(TMS470R1A384_BANK0_SECTORS));
221 if (!bank->sectors)
222 return ERROR_FLASH_OPERATION_FAILED;
223 (void)memcpy(bank->sectors, TMS470R1A384_BANK0_SECTORS,
224 sizeof(TMS470R1A384_BANK0_SECTORS));
225 } else if ((bank->base >= 0x00020000) && (bank->base < 0x00040000)) {
226 tms470_info->ordinal = 1;
227 bank->base = 0x00020000;
228 bank->size = 128 * 1024;
229 bank->num_sectors = TMS470R1A384_BANK1_NUM_SECTORS;
230 bank->sectors = malloc(sizeof(TMS470R1A384_BANK1_SECTORS));
231 if (!bank->sectors)
232 return ERROR_FLASH_OPERATION_FAILED;
233 (void)memcpy(bank->sectors, TMS470R1A384_BANK1_SECTORS,
234 sizeof(TMS470R1A384_BANK1_SECTORS));
235 } else if ((bank->base >= 0x00040000) && (bank->base < 0x00060000)) {
236 tms470_info->ordinal = 2;
237 bank->base = 0x00040000;
238 bank->size = 128 * 1024;
239 bank->num_sectors = TMS470R1A384_BANK2_NUM_SECTORS;
240 bank->sectors = malloc(sizeof(TMS470R1A384_BANK2_SECTORS));
241 if (!bank->sectors)
242 return ERROR_FLASH_OPERATION_FAILED;
243 (void)memcpy(bank->sectors, TMS470R1A384_BANK2_SECTORS,
244 sizeof(TMS470R1A384_BANK2_SECTORS));
245 } else {
246 LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".",
247 part_name, bank->base);
248 return ERROR_FLASH_OPERATION_FAILED;
249 }
250 break;
251
252 default:
253 LOG_WARNING("Could not identify part 0x%02x as a member of the TMS470 family.",
254 (unsigned)part_number);
255 return ERROR_FLASH_OPERATION_FAILED;
256 }
257
258 /* turn off memory selects */
259 target_write_u32(target, 0xFFFFFFE4, 0x00000000);
260 target_write_u32(target, 0xFFFFFFE0, 0x00000000);
261
262 bank->chip_width = 32;
263 bank->bus_width = 32;
264
265 LOG_INFO("Identified %s, ver=%d, core=%s, nvmem=%s.",
266 part_name,
267 (int)(silicon_version),
268 (technology_family ? "1.8v" : "3.3v"),
269 (rom_flash ? "rom" : "flash"));
270
271 tms470_info->device_ident_reg = device_ident_reg;
272 tms470_info->silicon_version = silicon_version;
273 tms470_info->technology_family = technology_family;
274 tms470_info->rom_flash = rom_flash;
275 tms470_info->part_number = part_number;
276 tms470_info->part_name = part_name;
277
278 /*
279 * Disable reset on address access violation.
280 */
281 target_write_u32(target, 0xFFFFFFE0, 0x00004007);
282
283 return ERROR_OK;
284 }
285
286 /* ---------------------------------------------------------------------- */
287
288 static uint32_t keysSet;
289 static uint32_t flashKeys[4];
290
291 COMMAND_HANDLER(tms470_handle_flash_keyset_command)
292 {
293 if (CMD_ARGC > 4)
294 return ERROR_COMMAND_SYNTAX_ERROR;
295 else if (CMD_ARGC == 4) {
296 int i;
297
298 for (i = 0; i < 4; i++) {
299 int start = (0 == strncmp(CMD_ARGV[i], "0x", 2)) ? 2 : 0;
300
301 if (1 != sscanf(&CMD_ARGV[i][start], "%" SCNx32 "", &flashKeys[i])) {
302 command_print(CMD_CTX, "could not process flash key %s",
303 CMD_ARGV[i]);
304 LOG_ERROR("could not process flash key %s", CMD_ARGV[i]);
305 return ERROR_COMMAND_SYNTAX_ERROR;
306 }
307 }
308
309 keysSet = 1;
310 } else if (CMD_ARGC != 0) {
311 command_print(CMD_CTX, "tms470 flash_keyset <key0> <key1> <key2> <key3>");
312 return ERROR_COMMAND_SYNTAX_ERROR;
313 }
314
315 if (keysSet) {
316 command_print(CMD_CTX,
317 "using flash keys 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 "",
318 flashKeys[0],
319 flashKeys[1],
320 flashKeys[2],
321 flashKeys[3]);
322 } else
323 command_print(CMD_CTX, "flash keys not set");
324
325 return ERROR_OK;
326 }
327
328 static const uint32_t FLASH_KEYS_ALL_ONES[] = { 0xFFFFFFFF, 0xFFFFFFFF,
329 0xFFFFFFFF, 0xFFFFFFFF,};
330
331 static const uint32_t FLASH_KEYS_ALL_ZEROS[] = { 0x00000000, 0x00000000,
332 0x00000000, 0x00000000,};
333
334 static const uint32_t FLASH_KEYS_MIX1[] = { 0xf0fff0ff, 0xf0fff0ff,
335 0xf0fff0ff, 0xf0fff0ff};
336
337 static const uint32_t FLASH_KEYS_MIX2[] = { 0x0000ffff, 0x0000ffff,
338 0x0000ffff, 0x0000ffff};
339
340 /* ---------------------------------------------------------------------- */
341
342 static int oscMHz = 12;
343
344 COMMAND_HANDLER(tms470_handle_osc_megahertz_command)
345 {
346 if (CMD_ARGC > 1)
347 return ERROR_COMMAND_SYNTAX_ERROR;
348 else if (CMD_ARGC == 1)
349 sscanf(CMD_ARGV[0], "%d", &oscMHz);
350
351 if (oscMHz <= 0) {
352 LOG_ERROR("osc_megahertz must be positive and non-zero!");
353 command_print(CMD_CTX, "osc_megahertz must be positive and non-zero!");
354 oscMHz = 12;
355 return ERROR_COMMAND_SYNTAX_ERROR;
356 }
357
358 command_print(CMD_CTX, "osc_megahertz=%d", oscMHz);
359
360 return ERROR_OK;
361 }
362
363 /* ---------------------------------------------------------------------- */
364
365 static int plldis;
366
367 COMMAND_HANDLER(tms470_handle_plldis_command)
368 {
369 if (CMD_ARGC > 1)
370 return ERROR_COMMAND_SYNTAX_ERROR;
371 else if (CMD_ARGC == 1) {
372 sscanf(CMD_ARGV[0], "%d", &plldis);
373 plldis = plldis ? 1 : 0;
374 }
375
376 command_print(CMD_CTX, "plldis=%d", plldis);
377
378 return ERROR_OK;
379 }
380
381 /* ---------------------------------------------------------------------- */
382
383 static int tms470_check_flash_unlocked(struct target *target)
384 {
385 uint32_t fmbbusy;
386
387 target_read_u32(target, 0xFFE89C08, &fmbbusy);
388 LOG_INFO("tms470 fmbbusy = 0x%08" PRIx32 " -> %s",
389 fmbbusy,
390 fmbbusy & 0x8000 ? "unlocked" : "LOCKED");
391 return fmbbusy & 0x8000 ? ERROR_OK : ERROR_FLASH_OPERATION_FAILED;
392 }
393
394 /* ---------------------------------------------------------------------- */
395
396 static int tms470_try_flash_keys(struct target *target, const uint32_t *key_set)
397 {
398 uint32_t glbctrl, fmmstat;
399 int retval = ERROR_FLASH_OPERATION_FAILED;
400
401 /* set GLBCTRL.4 */
402 target_read_u32(target, 0xFFFFFFDC, &glbctrl);
403 target_write_u32(target, 0xFFFFFFDC, glbctrl | 0x10);
404
405 /* only perform the key match when 3VSTAT is clear */
406 target_read_u32(target, 0xFFE8BC0C, &fmmstat);
407 if (!(fmmstat & 0x08)) {
408 unsigned i;
409 uint32_t fmbptr, fmbac2, orig_fmregopt;
410
411 target_write_u32(target, 0xFFE8BC04, fmmstat & ~0x07);
412
413 /* wait for pump ready */
414 do {
415 target_read_u32(target, 0xFFE8A814, &fmbptr);
416 alive_sleep(1);
417 } while (!(fmbptr & 0x0200));
418
419 /* force max wait states */
420 target_read_u32(target, 0xFFE88004, &fmbac2);
421 target_write_u32(target, 0xFFE88004, fmbac2 | 0xff);
422
423 /* save current access mode, force normal read mode */
424 target_read_u32(target, 0xFFE89C00, &orig_fmregopt);
425 target_write_u32(target, 0xFFE89C00, 0x00);
426
427 for (i = 0; i < 4; i++) {
428 uint32_t tmp;
429
430 /* There is no point displaying the value of tmp, it is
431 * filtered by the chip. The purpose of this read is to
432 * prime the unlocking logic rather than read out the value.
433 */
434 target_read_u32(target, 0x00001FF0 + 4 * i, &tmp);
435
436 LOG_INFO("tms470 writing fmpkey = 0x%08" PRIx32 "", key_set[i]);
437 target_write_u32(target, 0xFFE89C0C, key_set[i]);
438 }
439
440 if (ERROR_OK == tms470_check_flash_unlocked(target)) {
441 /*
442 * There seems to be a side-effect of reading the FMPKEY
443 * register in that it re-enables the protection. So we
444 * re-enable it.
445 */
446 for (i = 0; i < 4; i++) {
447 uint32_t tmp;
448
449 target_read_u32(target, 0x00001FF0 + 4 * i, &tmp);
450 target_write_u32(target, 0xFFE89C0C, key_set[i]);
451 }
452 retval = ERROR_OK;
453 }
454
455 /* restore settings */
456 target_write_u32(target, 0xFFE89C00, orig_fmregopt);
457 target_write_u32(target, 0xFFE88004, fmbac2);
458 }
459
460 /* clear config bit */
461 target_write_u32(target, 0xFFFFFFDC, glbctrl);
462
463 return retval;
464 }
465
466 /* ---------------------------------------------------------------------- */
467
468 static int tms470_unlock_flash(struct flash_bank *bank)
469 {
470 struct target *target = bank->target;
471 const uint32_t *p_key_sets[5];
472 unsigned i, key_set_count;
473
474 if (keysSet) {
475 key_set_count = 5;
476 p_key_sets[0] = flashKeys;
477 p_key_sets[1] = FLASH_KEYS_ALL_ONES;
478 p_key_sets[2] = FLASH_KEYS_ALL_ZEROS;
479 p_key_sets[3] = FLASH_KEYS_MIX1;
480 p_key_sets[4] = FLASH_KEYS_MIX2;
481 } else {
482 key_set_count = 4;
483 p_key_sets[0] = FLASH_KEYS_ALL_ONES;
484 p_key_sets[1] = FLASH_KEYS_ALL_ZEROS;
485 p_key_sets[2] = FLASH_KEYS_MIX1;
486 p_key_sets[3] = FLASH_KEYS_MIX2;
487 }
488
489 for (i = 0; i < key_set_count; i++) {
490 if (tms470_try_flash_keys(target, p_key_sets[i]) == ERROR_OK) {
491 LOG_INFO("tms470 flash is unlocked");
492 return ERROR_OK;
493 }
494 }
495
496 LOG_WARNING("tms470 could not unlock flash memory protection level 2");
497 return ERROR_FLASH_OPERATION_FAILED;
498 }
499
500 /* ---------------------------------------------------------------------- */
501
502 static int tms470_flash_initialize_internal_state_machine(struct flash_bank *bank)
503 {
504 uint32_t fmmac2, fmmac1, fmmaxep, k, delay, glbctrl, sysclk;
505 struct target *target = bank->target;
506 struct tms470_flash_bank *tms470_info = bank->driver_priv;
507 int result = ERROR_OK;
508
509 /*
510 * Select the desired bank to be programmed by writing BANK[2:0] of
511 * FMMAC2.
512 */
513 target_read_u32(target, 0xFFE8BC04, &fmmac2);
514 fmmac2 &= ~0x0007;
515 fmmac2 |= (tms470_info->ordinal & 7);
516 target_write_u32(target, 0xFFE8BC04, fmmac2);
517 LOG_DEBUG("set fmmac2 = 0x%04" PRIx32 "", fmmac2);
518
519 /*
520 * Disable level 1 sector protection by setting bit 15 of FMMAC1.
521 */
522 target_read_u32(target, 0xFFE8BC00, &fmmac1);
523 fmmac1 |= 0x8000;
524 target_write_u32(target, 0xFFE8BC00, fmmac1);
525 LOG_DEBUG("set fmmac1 = 0x%04" PRIx32 "", fmmac1);
526
527 /*
528 * FMTCREG = 0x2fc0;
529 */
530 target_write_u32(target, 0xFFE8BC10, 0x2fc0);
531 LOG_DEBUG("set fmtcreg = 0x2fc0");
532
533 /*
534 * MAXPP = 50
535 */
536 target_write_u32(target, 0xFFE8A07C, 50);
537 LOG_DEBUG("set fmmaxpp = 50");
538
539 /*
540 * MAXCP = 0xf000 + 2000
541 */
542 target_write_u32(target, 0xFFE8A084, 0xf000 + 2000);
543 LOG_DEBUG("set fmmaxcp = 0x%04x", 0xf000 + 2000);
544
545 /*
546 * configure VHV
547 */
548 target_read_u32(target, 0xFFE8A080, &fmmaxep);
549 if (fmmaxep == 0xf000) {
550 fmmaxep = 0xf000 + 4095;
551 target_write_u32(target, 0xFFE8A80C, 0x9964);
552 LOG_DEBUG("set fmptr3 = 0x9964");
553 } else {
554 fmmaxep = 0xa000 + 4095;
555 target_write_u32(target, 0xFFE8A80C, 0x9b64);
556 LOG_DEBUG("set fmptr3 = 0x9b64");
557 }
558 target_write_u32(target, 0xFFE8A080, fmmaxep);
559 LOG_DEBUG("set fmmaxep = 0x%04" PRIx32 "", fmmaxep);
560
561 /*
562 * FMPTR4 = 0xa000
563 */
564 target_write_u32(target, 0xFFE8A810, 0xa000);
565 LOG_DEBUG("set fmptr4 = 0xa000");
566
567 /*
568 * FMPESETUP, delay parameter selected based on clock frequency.
569 *
570 * According to the TI App Note SPNU257 and flashing code, delay is
571 * int((sysclk(MHz) + 1) / 2), with a minimum of 5. The system
572 * clock is usually derived from the ZPLL module, and selected by
573 * the plldis global.
574 */
575 target_read_u32(target, 0xFFFFFFDC, &glbctrl);
576 sysclk = (plldis ? 1 : (glbctrl & 0x08) ? 4 : 8) * oscMHz / (1 + (glbctrl & 7));
577 delay = (sysclk > 10) ? (sysclk + 1) / 2 : 5;
578 target_write_u32(target, 0xFFE8A018, (delay << 4) | (delay << 8));
579 LOG_DEBUG("set fmpsetup = 0x%04" PRIx32 "", (delay << 4) | (delay << 8));
580
581 /*
582 * FMPVEVACCESS, based on delay.
583 */
584 k = delay | (delay << 8);
585 target_write_u32(target, 0xFFE8A05C, k);
586 LOG_DEBUG("set fmpvevaccess = 0x%04" PRIx32 "", k);
587
588 /*
589 * FMPCHOLD, FMPVEVHOLD, FMPVEVSETUP, based on delay.
590 */
591 k <<= 1;
592 target_write_u32(target, 0xFFE8A034, k);
593 LOG_DEBUG("set fmpchold = 0x%04" PRIx32 "", k);
594 target_write_u32(target, 0xFFE8A040, k);
595 LOG_DEBUG("set fmpvevhold = 0x%04" PRIx32 "", k);
596 target_write_u32(target, 0xFFE8A024, k);
597 LOG_DEBUG("set fmpvevsetup = 0x%04" PRIx32 "", k);
598
599 /*
600 * FMCVACCESS, based on delay.
601 */
602 k = delay * 16;
603 target_write_u32(target, 0xFFE8A060, k);
604 LOG_DEBUG("set fmcvaccess = 0x%04" PRIx32 "", k);
605
606 /*
607 * FMCSETUP, based on delay.
608 */
609 k = 0x3000 | delay * 20;
610 target_write_u32(target, 0xFFE8A020, k);
611 LOG_DEBUG("set fmcsetup = 0x%04" PRIx32 "", k);
612
613 /*
614 * FMEHOLD, based on delay.
615 */
616 k = (delay * 20) << 2;
617 target_write_u32(target, 0xFFE8A038, k);
618 LOG_DEBUG("set fmehold = 0x%04" PRIx32 "", k);
619
620 /*
621 * PWIDTH, CWIDTH, EWIDTH, based on delay.
622 */
623 target_write_u32(target, 0xFFE8A050, delay * 8);
624 LOG_DEBUG("set fmpwidth = 0x%04" PRIx32 "", delay * 8);
625 target_write_u32(target, 0xFFE8A058, delay * 1000);
626 LOG_DEBUG("set fmcwidth = 0x%04" PRIx32 "", delay * 1000);
627 target_write_u32(target, 0xFFE8A054, delay * 5400);
628 LOG_DEBUG("set fmewidth = 0x%04" PRIx32 "", delay * 5400);
629
630 return result;
631 }
632
633 /* ---------------------------------------------------------------------- */
634
635 static int tms470_flash_status(struct flash_bank *bank)
636 {
637 struct target *target = bank->target;
638 int result = ERROR_OK;
639 uint32_t fmmstat;
640
641 target_read_u32(target, 0xFFE8BC0C, &fmmstat);
642 LOG_DEBUG("set fmmstat = 0x%04" PRIx32 "", fmmstat);
643
644 if (fmmstat & 0x0080) {
645 LOG_WARNING("tms470 flash command: erase still active after busy clear.");
646 result = ERROR_FLASH_OPERATION_FAILED;
647 }
648
649 if (fmmstat & 0x0040) {
650 LOG_WARNING("tms470 flash command: program still active after busy clear.");
651 result = ERROR_FLASH_OPERATION_FAILED;
652 }
653
654 if (fmmstat & 0x0020) {
655 LOG_WARNING("tms470 flash command: invalid data command.");
656 result = ERROR_FLASH_OPERATION_FAILED;
657 }
658
659 if (fmmstat & 0x0010) {
660 LOG_WARNING("tms470 flash command: program, erase or validate sector failed.");
661 result = ERROR_FLASH_OPERATION_FAILED;
662 }
663
664 if (fmmstat & 0x0008) {
665 LOG_WARNING("tms470 flash command: voltage instability detected.");
666 result = ERROR_FLASH_OPERATION_FAILED;
667 }
668
669 if (fmmstat & 0x0006) {
670 LOG_WARNING("tms470 flash command: command suspend detected.");
671 result = ERROR_FLASH_OPERATION_FAILED;
672 }
673
674 if (fmmstat & 0x0001) {
675 LOG_WARNING("tms470 flash command: sector was locked.");
676 result = ERROR_FLASH_OPERATION_FAILED;
677 }
678
679 return result;
680 }
681
682 /* ---------------------------------------------------------------------- */
683
684 static int tms470_erase_sector(struct flash_bank *bank, int sector)
685 {
686 uint32_t glbctrl, orig_fmregopt, fmbsea, fmbseb, fmmstat;
687 struct target *target = bank->target;
688 uint32_t flashAddr = bank->base + bank->sectors[sector].offset;
689 int result = ERROR_OK;
690
691 /*
692 * Set the bit GLBCTRL4 of the GLBCTRL register (in the System
693 * module) to enable writing to the flash registers }.
694 */
695 target_read_u32(target, 0xFFFFFFDC, &glbctrl);
696 target_write_u32(target, 0xFFFFFFDC, glbctrl | 0x10);
697 LOG_DEBUG("set glbctrl = 0x%08" PRIx32 "", glbctrl | 0x10);
698
699 /* Force normal read mode. */
700 target_read_u32(target, 0xFFE89C00, &orig_fmregopt);
701 target_write_u32(target, 0xFFE89C00, 0);
702 LOG_DEBUG("set fmregopt = 0x%08x", 0);
703
704 (void)tms470_flash_initialize_internal_state_machine(bank);
705
706 /*
707 * Select one or more bits in FMBSEA or FMBSEB to disable Level 1
708 * protection for the particular sector to be erased/written.
709 */
710 if (sector < 16) {
711 target_read_u32(target, 0xFFE88008, &fmbsea);
712 target_write_u32(target, 0xFFE88008, fmbsea | (1 << sector));
713 LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea | (1 << sector));
714 } else {
715 target_read_u32(target, 0xFFE8800C, &fmbseb);
716 target_write_u32(target, 0xFFE8800C, fmbseb | (1 << (sector - 16)));
717 LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb | (1 << (sector - 16)));
718 }
719 bank->sectors[sector].is_protected = 0;
720
721 /*
722 * clear status regiser, sent erase command, kickoff erase
723 */
724 target_write_u16(target, flashAddr, 0x0040);
725 LOG_DEBUG("write *(uint16_t *)0x%08" PRIx32 "=0x0040", flashAddr);
726 target_write_u16(target, flashAddr, 0x0020);
727 LOG_DEBUG("write *(uint16_t *)0x%08" PRIx32 "=0x0020", flashAddr);
728 target_write_u16(target, flashAddr, 0xffff);
729 LOG_DEBUG("write *(uint16_t *)0x%08" PRIx32 "=0xffff", flashAddr);
730
731 /*
732 * Monitor FMMSTAT, busy until clear, then check and other flags for
733 * ultimate result of the operation.
734 */
735 do {
736 target_read_u32(target, 0xFFE8BC0C, &fmmstat);
737 if (fmmstat & 0x0100)
738 alive_sleep(1);
739 } while (fmmstat & 0x0100);
740
741 result = tms470_flash_status(bank);
742
743 if (sector < 16) {
744 target_write_u32(target, 0xFFE88008, fmbsea);
745 LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea);
746 bank->sectors[sector].is_protected = fmbsea & (1 << sector) ? 0 : 1;
747 } else {
748 target_write_u32(target, 0xFFE8800C, fmbseb);
749 LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb);
750 bank->sectors[sector].is_protected = fmbseb & (1 << (sector - 16)) ? 0 : 1;
751 }
752 target_write_u32(target, 0xFFE89C00, orig_fmregopt);
753 LOG_DEBUG("set fmregopt = 0x%08" PRIx32 "", orig_fmregopt);
754 target_write_u32(target, 0xFFFFFFDC, glbctrl);
755 LOG_DEBUG("set glbctrl = 0x%08" PRIx32 "", glbctrl);
756
757 if (result == ERROR_OK)
758 bank->sectors[sector].is_erased = 1;
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 0x%08" PRIx32 "", count, bank->base +
906 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 if (bank->sectors[sector].is_erased != 1) {
1048 uint32_t i, addr = bank->base + bank->sectors[sector].offset;
1049
1050 LOG_INFO("checking flash bank %d sector %d", 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 LOG_WARNING("tms470 bank %d, sector %d, not erased.",
1058 tms470_info->ordinal,
1059 sector);
1060 LOG_WARNING(
1061 "at location 0x%08" PRIx32 ": flash data is 0x%02x.",
1062 addr + i,
1063 buffer[i]);
1064
1065 bank->sectors[sector].is_erased = 0;
1066 break;
1067 }
1068 }
1069 }
1070 if (bank->sectors[sector].is_erased != 1) {
1071 result = ERROR_FLASH_SECTOR_NOT_ERASED;
1072 break;
1073 } else
1074 LOG_INFO("sector erased");
1075 }
1076
1077 /* reset TEZ, wait states, read mode, GLBCTRL.4 */
1078 target_write_u32(target, 0xFFE88010, 0x0f);
1079 target_write_u32(target, 0xFFE88004, fmbac2);
1080 target_write_u32(target, 0xFFE89C00, orig_fmregopt);
1081 target_write_u32(target, 0xFFFFFFDC, glbctrl);
1082
1083 return result;
1084 }
1085
1086 /* ---------------------------------------------------------------------- */
1087
1088 static int tms470_protect_check(struct flash_bank *bank)
1089 {
1090 struct target *target = bank->target;
1091 struct tms470_flash_bank *tms470_info = bank->driver_priv;
1092 int sector, result = ERROR_OK;
1093 uint32_t fmmac2, fmbsea, fmbseb;
1094
1095 if (target->state != TARGET_HALTED) {
1096 LOG_ERROR("Target not halted");
1097 return ERROR_TARGET_NOT_HALTED;
1098 }
1099
1100 if (!tms470_info->device_ident_reg)
1101 tms470_read_part_info(bank);
1102
1103 /* enable the appropriate bank */
1104 target_read_u32(target, 0xFFE8BC04, &fmmac2);
1105 target_write_u32(target, 0xFFE8BC04, (fmmac2 & ~7) | tms470_info->ordinal);
1106
1107 target_read_u32(target, 0xFFE88008, &fmbsea);
1108 target_read_u32(target, 0xFFE8800C, &fmbseb);
1109
1110 for (sector = 0; sector < bank->num_sectors; sector++) {
1111 int protected;
1112
1113 if (sector < 16) {
1114 protected = fmbsea & (1 << sector) ? 0 : 1;
1115 bank->sectors[sector].is_protected = protected;
1116 } else {
1117 protected = fmbseb & (1 << (sector - 16)) ? 0 : 1;
1118 bank->sectors[sector].is_protected = protected;
1119 }
1120
1121 LOG_DEBUG("bank %d sector %d is %s",
1122 tms470_info->ordinal,
1123 sector,
1124 protected ? "protected" : "not protected");
1125 }
1126
1127 return result;
1128 }
1129
1130 /* ---------------------------------------------------------------------- */
1131
1132 static int get_tms470_info(struct flash_bank *bank, char *buf, int buf_size)
1133 {
1134 int used = 0;
1135 struct tms470_flash_bank *tms470_info = bank->driver_priv;
1136
1137 if (!tms470_info->device_ident_reg)
1138 tms470_read_part_info(bank);
1139
1140 if (!tms470_info->device_ident_reg) {
1141 (void)snprintf(buf, buf_size, "Cannot identify target as a TMS470\n");
1142 return ERROR_FLASH_OPERATION_FAILED;
1143 }
1144
1145 used =
1146 snprintf(buf, buf_size, "\ntms470 information: Chip is %s\n",
1147 tms470_info->part_name);
1148 buf += used;
1149 buf_size -= used;
1150
1151 snprintf(buf, buf_size, "Flash protection level 2 is %s\n",
1152 tms470_check_flash_unlocked(bank->target) == ERROR_OK ? "disabled" : "enabled");
1153
1154 return ERROR_OK;
1155 }
1156
1157 /* ---------------------------------------------------------------------- */
1158
1159 /*
1160 * flash bank tms470 <base> <size> <chip_width> <bus_width> <target>
1161 * [options...]
1162 */
1163
1164 FLASH_BANK_COMMAND_HANDLER(tms470_flash_bank_command)
1165 {
1166 bank->driver_priv = malloc(sizeof(struct tms470_flash_bank));
1167
1168 if (!bank->driver_priv)
1169 return ERROR_FLASH_OPERATION_FAILED;
1170
1171 (void)memset(bank->driver_priv, 0, sizeof(struct tms470_flash_bank));
1172
1173 return ERROR_OK;
1174 }
1175
1176 struct flash_driver tms470_flash = {
1177 .name = "tms470",
1178 .commands = tms470_command_handlers,
1179 .flash_bank_command = tms470_flash_bank_command,
1180 .erase = tms470_erase,
1181 .protect = tms470_protect,
1182 .write = tms470_write,
1183 .read = default_flash_read,
1184 .probe = tms470_probe,
1185 .auto_probe = tms470_auto_probe,
1186 .erase_check = tms470_erase_check,
1187 .protect_check = tms470_protect_check,
1188 .info = get_tms470_info,
1189 .free_driver_priv = default_flash_free_driver_priv,
1190 };

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)