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

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)