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