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

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)