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

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)