remove flash_driver->register_callbacks
[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 *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 (CMD_ARGC > 4)
295 {
296 command_print(CMD_CTX, "tms470 flash_keyset <key0> <key1> <key2> <key3>");
297 return ERROR_INVALID_ARGUMENTS;
298 }
299 else if (CMD_ARGC == 4)
300 {
301 int i;
302
303 for (i = 0; i < 4; i++)
304 {
305 int start = (0 == strncmp(CMD_ARGV[i], "0x", 2)) ? 2 : 0;
306
307 if (1 != sscanf(&CMD_ARGV[i][start], "%" SCNx32 "", &flashKeys[i]))
308 {
309 command_print(CMD_CTX, "could not process flash key %s", CMD_ARGV[i]);
310 LOG_ERROR("could not process flash key %s", CMD_ARGV[i]);
311 return ERROR_INVALID_ARGUMENTS;
312 }
313 }
314
315 keysSet = 1;
316 }
317 else if (CMD_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 (CMD_ARGC > 1)
359 {
360 command_print(CMD_CTX, "tms470 osc_megahertz <MHz>");
361 return ERROR_INVALID_ARGUMENTS;
362 }
363 else if (CMD_ARGC == 1)
364 {
365 sscanf(CMD_ARGV[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 (CMD_ARGC > 1)
388 {
389 command_print(CMD_CTX, "tms470 plldis <0 | 1>");
390 return ERROR_INVALID_ARGUMENTS;
391 }
392 else if (CMD_ARGC == 1)
393 {
394 sscanf(CMD_ARGV[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 *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 *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 *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 *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 const struct command_registration tms470_any_command_handlers[] = {
821 {
822 .name = "flash_keyset",
823 .handler = &tms470_handle_flash_keyset_command,
824 .mode = COMMAND_ANY,
825 .help = "tms470 flash_keyset <key0> <key1> <key2> <key3>",
826 },
827 {
828 .name = "osc_megahertz",
829 .handler = &tms470_handle_osc_megahertz_command,
830 .mode = COMMAND_ANY,
831 .help = "tms470 osc_megahertz <MHz>",
832 },
833 {
834 .name = "plldis",
835 .handler = &tms470_handle_plldis_command,
836 .mode = COMMAND_ANY,
837 .help = "tms470 plldis <0/1>",
838 },
839 COMMAND_REGISTRATION_DONE
840 };
841 static const struct command_registration tms470_command_handlers[] = {
842 {
843 .name = "tms470",
844 .mode = COMMAND_ANY,
845 .help = "TI tms470 flash command group",
846 .chain = tms470_any_command_handlers,
847 },
848 COMMAND_REGISTRATION_DONE
849 };
850
851 /* ---------------------------------------------------------------------- */
852
853 static int tms470_erase(struct flash_bank *bank, int first, int last)
854 {
855 struct tms470_flash_bank *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 *bank, int set, int first, int last)
901 {
902 struct tms470_flash_bank *tms470_info = bank->driver_priv;
903 struct target *target = bank->target;
904 uint32_t 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 *bank, uint8_t * buffer, uint32_t offset, uint32_t count)
953 {
954 struct target *target = bank->target;
955 uint32_t glbctrl, fmbac2, orig_fmregopt, fmbsea, fmbseb, fmmaxpp, fmmstat;
956 int result = ERROR_OK;
957 uint32_t 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 %" PRId32 " bytes starting at 0x%08" PRIx32 "", 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 uint32_t addr = bank->base + offset + i;
997 uint16_t word = (((uint16_t) buffer[i]) << 8) | (uint16_t) buffer[i + 1];
998
999 if (word != 0xffff)
1000 {
1001 LOG_INFO("writing 0x%04x at 0x%08" PRIx32 "", 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%04" PRIx32 "", fmmstat);
1027 LOG_ERROR("Could not program word 0x%04x at address 0x%08" PRIx32 ".", word, addr);
1028 result = ERROR_FLASH_OPERATION_FAILED;
1029 break;
1030 }
1031 }
1032 else
1033 {
1034 LOG_INFO("skipping 0xffff at 0x%08" PRIx32 "", 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 *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 *bank)
1062 {
1063 struct tms470_flash_bank *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 *bank)
1073 {
1074 struct target *target = bank->target;
1075 struct tms470_flash_bank *tms470_info = bank->driver_priv;
1076 int sector, result = ERROR_OK;
1077 uint32_t 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 uint32_t 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%08" PRIx32 ": 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 *bank)
1164 {
1165 struct target *target = bank->target;
1166 struct tms470_flash_bank *tms470_info = bank->driver_priv;
1167 int sector, result = ERROR_OK;
1168 uint32_t 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 *bank, char *buf, int buf_size)
1212 {
1213 int used = 0;
1214 struct tms470_flash_bank *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 FLASH_BANK_COMMAND_HANDLER(tms470_flash_bank_command)
1246 {
1247 bank->driver_priv = malloc(sizeof(struct tms470_flash_bank));
1248
1249 if (!bank->driver_priv)
1250 {
1251 return ERROR_FLASH_OPERATION_FAILED;
1252 }
1253
1254 (void)memset(bank->driver_priv, 0, sizeof(struct tms470_flash_bank));
1255
1256 return ERROR_OK;
1257 }
1258
1259 struct flash_driver tms470_flash = {
1260 .name = "tms470",
1261 .commands = tms470_command_handlers,
1262 .flash_bank_command = &tms470_flash_bank_command,
1263 .erase = &tms470_erase,
1264 .protect = &tms470_protect,
1265 .write = &tms470_write,
1266 .probe = &tms470_probe,
1267 .auto_probe = &tms470_auto_probe,
1268 .erase_check = &tms470_erase_check,
1269 .protect_check = &tms470_protect_check,
1270 .info = &tms470_info,
1271 };

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)