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

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)