- added autoprobe functionality
authormifi <mifi@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Sun, 27 Jan 2008 14:05:59 +0000 (14:05 +0000)
committermifi <mifi@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Sun, 27 Jan 2008 14:05:59 +0000 (14:05 +0000)
- corrected blocksize handling from GDB "info mem" command
(thanks to √ėyvind and Spen for these patches)

git-svn-id: svn://svn.berlios.de/openocd/trunk@278 b42882b7-edfa-0310-969c-e2dbd0fdcd60

16 files changed:
src/flash/at91sam7.c
src/flash/at91sam7.h
src/flash/cfi.c
src/flash/cfi.h
src/flash/flash.c
src/flash/flash.h
src/flash/lpc2000.c
src/flash/stellaris.c
src/flash/stellaris.h
src/flash/stm32x.c
src/flash/str7x.c
src/flash/str9x.c
src/flash/str9xpec.c
src/flash/tms470.c
src/flash/tms470.h
src/server/gdb_server.c

index cf3547942d39638ac95dd4162327c762b2c67b5c..0347742360b44c3877b4ae29554ce2a88480139c 100644 (file)
@@ -57,6 +57,7 @@ int at91sam7_erase(struct flash_bank_s *bank, int first, int last);
 int at91sam7_protect(struct flash_bank_s *bank, int set, int first, int last);
 int at91sam7_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
 int at91sam7_probe(struct flash_bank_s *bank);
+int at91sam7_auto_probe(struct flash_bank_s *bank);
 int at91sam7_erase_check(struct flash_bank_s *bank);
 int at91sam7_protect_check(struct flash_bank_s *bank);
 int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size);
@@ -76,6 +77,7 @@ flash_driver_t at91sam7_flash =
        .protect = at91sam7_protect,
        .write = at91sam7_write,
        .probe = at91sam7_probe,
+       .auto_probe = at91sam7_auto_probe,
        .erase_check = at91sam7_erase_check,
        .protect_check = at91sam7_protect_check,
        .info = at91sam7_info
@@ -617,6 +619,7 @@ int at91sam7_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, ch
        
        at91sam7_info = malloc(sizeof(at91sam7_flash_bank_t));
        bank->driver_priv = at91sam7_info;
+       at91sam7_info->probed = 0;
        
        /* part wasn't probed for info yet */
        at91sam7_info->cidr = 0;
@@ -806,6 +809,7 @@ int at91sam7_probe(struct flash_bank_s *bank)
         * if this is an at91sam7, it has the configured flash
         */
        at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
+       at91sam7_info->probed = 0;
        
        if (at91sam7_info->cidr == 0)
        {
@@ -818,9 +822,20 @@ int at91sam7_probe(struct flash_bank_s *bank)
                return ERROR_FLASH_OPERATION_FAILED;
        }
        
+       at91sam7_info->probed = 1;
+       
        return ERROR_OK;
 }
 
+
+int at91sam7_auto_probe(struct flash_bank_s *bank)
+{
+       at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
+       if (at91sam7_info->probed)
+               return ERROR_OK;
+       return at91sam7_probe(bank);
+}
+
 int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size)
 {
        int printed, flashplane;
index 20e0737d382f233fd8b18c893ed7236001fc6a1e..43961d5e4121741191c3dc010e3ca66b335b0ae0 100644 (file)
@@ -60,6 +60,8 @@ typedef struct at91sam7_flash_bank_s
        u8  mck_valid;
        u32 mck_freq;
        
+       int probed;
+       
 } at91sam7_flash_bank_t;
 
 /* AT91SAM7 control registers */
index 395cf8af97c343eea72ad31c8725bcdfaffaefaf..c52933854ebe6bd00cb14fc7f5da247cb9c54bf1 100644 (file)
@@ -43,6 +43,7 @@ int cfi_erase(struct flash_bank_s *bank, int first, int last);
 int cfi_protect(struct flash_bank_s *bank, int set, int first, int last);
 int cfi_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
 int cfi_probe(struct flash_bank_s *bank);
+int cfi_auto_probe(struct flash_bank_s *bank);
 int cfi_erase_check(struct flash_bank_s *bank);
 int cfi_protect_check(struct flash_bank_s *bank);
 int cfi_info(struct flash_bank_s *bank, char *buf, int buf_size);
@@ -64,6 +65,7 @@ flash_driver_t cfi_flash =
        .protect = cfi_protect,
        .write = cfi_write,
        .probe = cfi_probe,
+       .auto_probe = cfi_auto_probe,
        .erase_check = cfi_erase_check,
        .protect_check = cfi_protect_check,
        .info = cfi_info
@@ -617,6 +619,7 @@ int cfi_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **
        }
 
        cfi_info = malloc(sizeof(cfi_flash_bank_t));
+       cfi_info->probed = 0;
        bank->driver_priv = cfi_info;
 
        cfi_info->write_algorithm = NULL;
@@ -1864,6 +1867,8 @@ int cfi_probe(struct flash_bank_s *bank)
        u32 unlock1 = 0x555;
        u32 unlock2 = 0x2aa;
 
+       cfi_info->probed = 0;
+
        /* JEDEC standard JESD21C uses 0x5555 and 0x2aaa as unlock addresses,
         * while CFI compatible AMD/Spansion flashes use 0x555 and 0x2aa
         */
@@ -2071,10 +2076,20 @@ int cfi_probe(struct flash_bank_s *bank)
                        }
                }
        }
+       
+       cfi_info->probed = 1;
 
        return ERROR_OK;
 }
 
+int cfi_auto_probe(struct flash_bank_s *bank)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       if (cfi_info->probed)
+               return ERROR_OK;
+       return cfi_probe(bank);
+}
+
 int cfi_erase_check(struct flash_bank_s *bank)
 {
        cfi_flash_bank_t *cfi_info = bank->driver_priv;
index 9572c83a2aa1cb7d28a65efc9f6c53c7fe2b5f99..8099c4ea6ff37711f6f10d38f26a6b8c48b0cac6 100644 (file)
@@ -31,6 +31,7 @@ typedef struct cfi_flash_bank_s
        int x16_as_x8;
        int jedec_probe;
        int not_cfi;
+       int probed;
 
        u16 manufacturer;
        u16 device_id;
index 2e7cc4537e2f7e41421bbe6b8536d71d22ef5217..9d82e09ac7c35e9f41648cc52b5412e91e56f51b 100644 (file)
@@ -127,7 +127,7 @@ int flash_init_drivers(struct command_context_s *cmd_ctx)
        return ERROR_OK;
 }
 
-flash_bank_t *get_flash_bank_by_num(int num)
+flash_bank_t *get_flash_bank_by_num_noprobe(int num)
 {
        flash_bank_t *p;
        int i = 0;
@@ -143,6 +143,24 @@ flash_bank_t *get_flash_bank_by_num(int num)
        return NULL;
 }
 
+flash_bank_t *get_flash_bank_by_num(int num)
+{
+       flash_bank_t *p = get_flash_bank_by_num_noprobe(num);
+       int retval;
+       
+       if (p == NULL)
+               return NULL;
+       
+       retval = p->driver->auto_probe(p);
+       
+       if (retval != ERROR_OK)
+       {
+               ERROR("auto_probe failed %d\n", retval);
+               return NULL;
+       }
+       return p;
+}
+
 /* flash_bank <driver> <base> <size> <chip_width> <bus_width> <target> [driver_options ...]
  */
 int handle_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
@@ -305,7 +323,7 @@ int handle_flash_probe_command(struct command_context_s *cmd_ctx, char *cmd, cha
                return ERROR_OK;
        }
        
-       p = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+       p = get_flash_bank_by_num_noprobe(strtoul(args[0], NULL, 0));
        if (p)
        {
                if ((retval = p->driver->probe(p)) == ERROR_OK)
@@ -794,6 +812,14 @@ flash_bank_t *get_flash_bank_by_addr(target_t *target, u32 addr)
        /* cycle through bank list */
        for (c = flash_banks; c; c = c->next)
        {
+               int retval;
+               retval = c->driver->auto_probe(c);
+               
+               if (retval != ERROR_OK)
+               {
+                       ERROR("auto_probe failed %d\n", retval);
+                       return NULL;
+               }
                /* check whether address belongs to this flash bank */
                if ((addr >= c->base) && (addr < c->base + c->size) && target == c->target)
                        return c;
index a0529aa41968759f196b4e02e065bacf77209056..1ef74c8909f79282fa6a05fbda3216e1a982aa0a 100644 (file)
@@ -47,6 +47,7 @@ typedef struct flash_driver_s
        int (*erase_check)(struct flash_bank_s *bank);
        int (*protect_check)(struct flash_bank_s *bank);
        int (*info)(struct flash_bank_s *bank, char *buf, int buf_size);
+       int (*auto_probe)(struct flash_bank_s *bank);
 } flash_driver_t;
 
 typedef struct flash_bank_s
index 2252ca42802bbcad94cdc0a500c72371077fad04..d887c80565db50f759c5290590997677c64d9b09 100644 (file)
@@ -72,6 +72,7 @@ flash_driver_t lpc2000_flash =
        .protect = lpc2000_protect,
        .write = lpc2000_write,
        .probe = lpc2000_probe,
+       .auto_probe = lpc2000_probe,
        .erase_check = lpc2000_erase_check,
        .protect_check = lpc2000_protect_check,
        .info = lpc2000_info
@@ -185,7 +186,7 @@ int lpc2000_build_sector_list(struct flash_bank_s *bank)
                
                bank->num_sectors = num_sectors;
                bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);
-
+               
                for (i = 0; i < num_sectors; i++)
                {
                        if ((i >= 0) && (i < 8))
index 60dd96b0e2f7d11139d2217eed919ec854ac2750..b944c34e9f7c32005cf317b9111d30505cc884ad 100644 (file)
@@ -49,6 +49,7 @@ int stellaris_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, c
 int stellaris_erase(struct flash_bank_s *bank, int first, int last);
 int stellaris_protect(struct flash_bank_s *bank, int set, int first, int last);
 int stellaris_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
+int stellaris_auto_probe(struct flash_bank_s *bank);
 int stellaris_probe(struct flash_bank_s *bank);
 int stellaris_erase_check(struct flash_bank_s *bank);
 int stellaris_protect_check(struct flash_bank_s *bank);
@@ -70,6 +71,7 @@ flash_driver_t stellaris_flash =
        .protect = stellaris_protect,
        .write = stellaris_write,
        .probe = stellaris_probe,
+       .auto_probe = stellaris_auto_probe,
        .erase_check = stellaris_erase_check,
        .protect_check = stellaris_protect_check,
        .info = stellaris_info
@@ -916,6 +918,8 @@ int stellaris_probe(struct flash_bank_s *bank)
         */
        stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
        
+       stellaris_info->probed = 0;
+       
        if (stellaris_info->did1 == 0)
        {
                stellaris_read_part_info(bank);
@@ -927,5 +931,15 @@ int stellaris_probe(struct flash_bank_s *bank)
                return ERROR_FLASH_OPERATION_FAILED;
        }
        
+       stellaris_info->probed = 1;
+       
        return ERROR_OK;
 }
+
+int stellaris_auto_probe(struct flash_bank_s *bank)
+{
+       stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
+       if (stellaris_info->probed)
+               return ERROR_OK;
+       return stellaris_probe(bank);
+}
index 8024258ea498287eb91e355bc185c5d06e6f27cb..1dffc363da750487d27abed7d8b2ab6695466bed 100644 (file)
@@ -49,6 +49,8 @@ typedef struct stellaris_flash_bank_s
        u8  mck_valid;
        u32 mck_freq;
        
+       int probed;
+       
 } stellaris_flash_bank_t;
 
 /* STELLARIS control registers */
index acbe116aca222e3031d77c8d9b830a2abc5b54b2..e87e0cceba8b95068ae5354687683c6d77a733d0 100644 (file)
@@ -60,6 +60,7 @@ flash_driver_t stm32x_flash =
        .protect = stm32x_protect,
        .write = stm32x_write,
        .probe = stm32x_probe,
+       .auto_probe = stm32x_probe,
        .erase_check = stm32x_erase_check,
        .protect_check = stm32x_protect_check,
        .info = stm32x_info
index 2b3e47fd15c8a8a9e3d71cce7a60d1c5dd849ea5..dc94ae0a8839f3f70c9fc56dee9c22bb407fc43f 100644 (file)
@@ -70,6 +70,7 @@ flash_driver_t str7x_flash =
        .protect = str7x_protect,
        .write = str7x_write,
        .probe = str7x_probe,
+       .auto_probe = str7x_probe,
        .erase_check = str7x_erase_check,
        .protect_check = str7x_protect_check,
        .info = str7x_info
index 753abc33786af852b4db0ecc05c56bddd245da2b..d79e984f5f4f89e4db095ce9cd4f2d4e7d1531af 100644 (file)
@@ -78,6 +78,7 @@ flash_driver_t str9x_flash =
        .protect = str9x_protect,
        .write = str9x_write,
        .probe = str9x_probe,
+       .auto_probe = str9x_probe,
        .erase_check = str9x_erase_check,
        .protect_check = str9x_protect_check,
        .info = str9x_info
index eb08eb244eeefdbb7705e7ed5f3ba68fced25804..a9a24bfb58bb5a74dd9301e79b1b8f6f4f1eff70 100644 (file)
@@ -87,6 +87,7 @@ flash_driver_t str9xpec_flash =
        .protect = str9xpec_protect,
        .write = str9xpec_write,
        .probe = str9xpec_probe,
+       .auto_probe = str9xpec_probe,
        .erase_check = str9xpec_erase_check,
        .protect_check = str9xpec_protect_check,
        .info = str9xpec_info
index 0a97f562c72760af15ef926af16c566e8da24f57..b7adf5aa66eef95efec296ccd91647f65d66bbd4 100644 (file)
-/***************************************************************************\r
- *   (c) Copyright 2007, 2008 by Christopher Kilgour                       *\r
- *   techie |_at_| whiterocker |_dot_| com                                 *\r
- *                                                                         *\r
- *   This program is free software; you can redistribute it and/or modify  *\r
- *   it under the terms of the GNU General Public License as published by  *\r
- *   the Free Software Foundation; either version 2 of the License, or     *\r
- *   (at your option) any later version.                                   *\r
- *                                                                         *\r
- *   This program is distributed in the hope that it will be useful,       *\r
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\r
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\r
- *   GNU General Public License for more details.                          *\r
- *                                                                         *\r
- *   You should have received a copy of the GNU General Public License     *\r
- *   along with this program; if not, write to the                         *\r
- *   Free Software Foundation, Inc.,                                       *\r
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *\r
- ***************************************************************************/\r
-\r
-#ifdef HAVE_CONFIG_H\r
-#include "config.h"\r
-#endif\r
-\r
-#include "log.h"\r
-#include "tms470.h"\r
-#include <string.h>\r
-#include <unistd.h>\r
-\r
-int \r
-tms470_register_commands( struct command_context_s *cmd_ctx );\r
-\r
-int \r
-tms470_flash_bank_command( struct command_context_s *cmd_ctx, \r
-                           char *cmd, \r
-                           char **args, \r
-                           int argc, \r
-                           struct flash_bank_s *bank );\r
-\r
-int \r
-tms470_erase( struct flash_bank_s *bank, \r
-              int first, \r
-              int last );\r
-\r
-int \r
-tms470_protect( struct flash_bank_s *bank, \r
-                int set, \r
-                int first, \r
-                int last );\r
-\r
-int \r
-tms470_write( struct flash_bank_s *bank, \r
-              u8 *buffer, \r
-              u32 offset, \r
-              u32 count );\r
-\r
-int \r
-tms470_probe( struct flash_bank_s *bank );\r
-\r
-int \r
-tms470_erase_check( struct flash_bank_s *bank );\r
-\r
-int \r
-tms470_protect_check( struct flash_bank_s *bank );\r
-\r
-int \r
-tms470_info( struct flash_bank_s *bank, \r
-             char *buf, \r
-             int buf_size );\r
-\r
-flash_driver_t tms470_flash =\r
-  {\r
-    .name =               "tms470",\r
-    .register_commands =  tms470_register_commands,\r
-    .flash_bank_command = tms470_flash_bank_command,\r
-    .erase =              tms470_erase,\r
-    .protect =            tms470_protect,\r
-    .write =              tms470_write,\r
-    .probe =              tms470_probe,\r
-    .erase_check =        tms470_erase_check,\r
-    .protect_check =      tms470_protect_check,\r
-    .info =               tms470_info\r
-  };\r
-\r
-/* ---------------------------------------------------------------------- \r
-                      Internal Support, Helpers\r
-   ---------------------------------------------------------------------- */\r
-\r
-const flash_sector_t TMS470R1A256_SECTORS[] =\r
-  {\r
-    { 0x00000000, 0x00002000, -1, -1 },\r
-    { 0x00002000, 0x00002000, -1, -1 },\r
-    { 0x00004000, 0x00002000, -1, -1 },\r
-    { 0x00006000, 0x00002000, -1, -1 },\r
-    { 0x00008000, 0x00008000, -1, -1 },\r
-    { 0x00010000, 0x00008000, -1, -1 },\r
-    { 0x00018000, 0x00008000, -1, -1 },\r
-    { 0x00020000, 0x00008000, -1, -1 },\r
-    { 0x00028000, 0x00008000, -1, -1 },\r
-    { 0x00030000, 0x00008000, -1, -1 },\r
-    { 0x00038000, 0x00002000, -1, -1 },\r
-    { 0x0003A000, 0x00002000, -1, -1 },\r
-    { 0x0003C000, 0x00002000, -1, -1 },\r
-    { 0x0003E000, 0x00002000, -1, -1 },\r
-  };\r
-\r
-#define TMS470R1A256_NUM_SECTORS \\r
-  (sizeof(TMS470R1A256_SECTORS)/sizeof(TMS470R1A256_SECTORS[0]))\r
-\r
-const flash_sector_t TMS470R1A288_BANK0_SECTORS[] =\r
-  {\r
-    { 0x00000000, 0x00002000, -1, -1 },\r
-    { 0x00002000, 0x00002000, -1, -1 },\r
-    { 0x00004000, 0x00002000, -1, -1 },\r
-    { 0x00006000, 0x00002000, -1, -1 },\r
-  };\r
-\r
-#define TMS470R1A288_BANK0_NUM_SECTORS \\r
-  (sizeof(TMS470R1A288_BANK0_SECTORS)/sizeof(TMS470R1A288_BANK0_SECTORS[0]))\r
-\r
-const flash_sector_t TMS470R1A288_BANK1_SECTORS[] =\r
-  {\r
-    { 0x00040000, 0x00010000, -1, -1 },\r
-    { 0x00050000, 0x00010000, -1, -1 },\r
-    { 0x00060000, 0x00010000, -1, -1 },\r
-    { 0x00070000, 0x00010000, -1, -1 },\r
-  };\r
-\r
-#define TMS470R1A288_BANK1_NUM_SECTORS \\r
-  (sizeof(TMS470R1A288_BANK1_SECTORS)/sizeof(TMS470R1A288_BANK1_SECTORS[0]))\r
-\r
-/* ---------------------------------------------------------------------- */\r
-\r
-int \r
-tms470_read_part_info( struct flash_bank_s *bank )\r
-{\r
-  tms470_flash_bank_t *tms470_info = bank->driver_priv;\r
-  target_t *target = bank->target;\r
-  u32    device_ident_reg;\r
-  u32    silicon_version;\r
-  u32    technology_family;\r
-  u32    rom_flash;\r
-  u32    part_number;\r
-  char * part_name;\r
-\r
-  if (target->state != TARGET_HALTED)\r
-    {\r
-      WARNING( "Cannot communicate... target not halted." );\r
-      return ERROR_TARGET_NOT_HALTED;\r
-    }\r
-\r
-  /* read and parse the device identification register */\r
-  target_read_u32( target, 0xFFFFFFF0, &device_ident_reg );\r
-\r
-  INFO( "device_ident_reg=0x%08x", device_ident_reg );\r
-  \r
-  if ((device_ident_reg & 7) == 0)\r
-    {\r
-      WARNING( "Cannot identify target as a TMS470 family." );\r
-      return ERROR_FLASH_OPERATION_FAILED;\r
-    }\r
-\r
-  silicon_version = (device_ident_reg >> 12) & 0xF;\r
-  technology_family = (device_ident_reg >> 11) & 1;\r
-  rom_flash = (device_ident_reg >> 10) & 1;\r
-  part_number = (device_ident_reg >> 3) & 0x7f;\r
-\r
-  /*\r
-   * If the part number is known, determine if the flash bank is valid\r
-   * based on the base address being within the known flash bank\r
-   * ranges.  Then fixup/complete the remaining fields of the flash\r
-   * bank structure.\r
-   */\r
-  switch( part_number )\r
-    {\r
-    case 0x0a:\r
-      part_name = "TMS470R1A256";\r
-\r
-      if (bank->base >= 0x00040000)\r
-        {\r
-          ERROR( "No %s flash bank contains base address 0x%08x.", \r
-                 part_name, bank->base );\r
-          return ERROR_FLASH_OPERATION_FAILED;\r
-        }\r
-      tms470_info->ordinal = 0;\r
-      bank->base           = 0x00000000;\r
-      bank->size           = 256*1024;\r
-      bank->num_sectors    = TMS470R1A256_NUM_SECTORS;\r
-      bank->sectors = malloc( sizeof( TMS470R1A256_SECTORS ) );\r
-      if (!bank->sectors)\r
-        {\r
-          return ERROR_FLASH_OPERATION_FAILED;\r
-        }\r
-      (void) memcpy( bank->sectors,\r
-                     TMS470R1A256_SECTORS,\r
-                     sizeof( TMS470R1A256_SECTORS ) );\r
-      break;\r
-\r
-    case 0x2b:\r
-      part_name = "TMS470R1A288";\r
-\r
-      if ((bank->base >= 0x00000000) && (bank->base < 0x00008000))\r
-        {\r
-          tms470_info->ordinal = 0;\r
-          bank->base           = 0x00000000;\r
-          bank->size           = 32*1024;\r
-          bank->num_sectors    = TMS470R1A288_BANK0_NUM_SECTORS;\r
-          bank->sectors = malloc( sizeof( TMS470R1A288_BANK0_SECTORS ) );\r
-          if (!bank->sectors)\r
-            {\r
-              return ERROR_FLASH_OPERATION_FAILED;\r
-            }\r
-          (void) memcpy( bank->sectors,\r
-                         TMS470R1A288_BANK0_SECTORS,\r
-                         sizeof( TMS470R1A288_BANK0_SECTORS ) );\r
-        }\r
-      else if ((bank->base >= 0x00040000) && (bank->base < 0x00080000))\r
-        {\r
-          tms470_info->ordinal = 1;\r
-          bank->base           = 0x00040000;\r
-          bank->size           = 256*1024;\r
-          bank->num_sectors    = TMS470R1A288_BANK1_NUM_SECTORS;\r
-          bank->sectors = malloc( sizeof( TMS470R1A288_BANK1_SECTORS ) );\r
-          if (!bank->sectors)\r
-            {\r
-              return ERROR_FLASH_OPERATION_FAILED;\r
-            }\r
-          (void) memcpy( bank->sectors,\r
-                         TMS470R1A288_BANK1_SECTORS,\r
-                         sizeof( TMS470R1A288_BANK1_SECTORS ) );\r
-        }\r
-      else\r
-        {\r
-          ERROR( "No %s flash bank contains base address 0x%08x.", \r
-                 part_name, bank->base );\r
-          return ERROR_FLASH_OPERATION_FAILED;\r
-        }\r
-      break;\r
-\r
-    default:\r
-      WARNING( "Could not identify part 0x%02x as a member of the TMS470 family.", \r
-               part_number );\r
-      return ERROR_FLASH_OPERATION_FAILED;\r
-    }\r
-\r
-  /* turn off memory selects */\r
-  target_write_u32( target, 0xFFFFFFE4, 0x00000000 );\r
-  target_write_u32( target, 0xFFFFFFE0, 0x00000000 );\r
-\r
-  bank->chip_width = 32;\r
-  bank->bus_width  = 32;\r
-  \r
-  INFO( "Identified %s, ver=%d, core=%s, nvmem=%s.",\r
-        part_name,\r
-        silicon_version,\r
-        (technology_family ? "1.8v" : "3.3v"),\r
-        (rom_flash ? "rom" : "flash") );\r
-\r
-  tms470_info->device_ident_reg  = device_ident_reg;\r
-  tms470_info->silicon_version   = silicon_version;\r
-  tms470_info->technology_family = technology_family;\r
-  tms470_info->rom_flash         = rom_flash;\r
-  tms470_info->part_number       = part_number;\r
-  tms470_info->part_name         = part_name;\r
-\r
-  /*\r
-   * Disable reset on address access violation.\r
-   */\r
-  target_write_u32( target, 0xFFFFFFE0, 0x00004007 );\r
-\r
-  return ERROR_OK;\r
-}\r
-\r
-/* ---------------------------------------------------------------------- */\r
-\r
-u32 keysSet = 0;\r
-u32 flashKeys[4];\r
-\r
-int \r
-tms470_handle_flash_keyset_command( struct command_context_s * cmd_ctx, \r
-                                    char *                     cmd, \r
-                                    char **                    args, \r
-                                    int                        argc )\r
-{\r
-  if (argc > 4)\r
-    {\r
-      command_print( cmd_ctx, "tms470 flash_keyset <key0> <key1> <key2> <key3>" );\r
-      return ERROR_INVALID_ARGUMENTS;\r
-    }\r
-  else if (argc == 4)\r
-    {\r
-      int i;\r
-\r
-      for( i=0; i<4; i++ )\r
-        {\r
-          int start = (0 == strncmp( args[i], "0x", 2 )) ? 2 : 0;\r
-          if (1 != sscanf( &args[i][start], "%x", &flashKeys[i] ))\r
-            {\r
-              command_print( cmd_ctx, "could not process flash key %s", args[i] );\r
-              ERROR( "could not process flash key %s", args[i] );\r
-              return ERROR_INVALID_ARGUMENTS;\r
-            }\r
-        }\r
-\r
-      keysSet = 1;\r
-    }\r
-  else if (argc != 0)\r
-    {\r
-      command_print( cmd_ctx, "tms470 flash_keyset <key0> <key1> <key2> <key3>" );\r
-      return ERROR_INVALID_ARGUMENTS;\r
-    }\r
-\r
-  if (keysSet)\r
-    {\r
-      command_print( cmd_ctx, "using flash keys 0x%08x, 0x%08x, 0x%08x, 0x%08x",\r
-                     flashKeys[0], flashKeys[1], flashKeys[2], flashKeys[3] );\r
-    }\r
-  else\r
-    {\r
-      command_print( cmd_ctx, "flash keys not set" );\r
-    }\r
-\r
-  return ERROR_OK;\r
-}\r
-\r
-const u32 FLASH_KEYS_ALL_ONES[] = { 0xFFFFFFFF, 0xFFFFFFFF, \r
-                                    0xFFFFFFFF, 0xFFFFFFFF, };\r
-\r
-const u32 FLASH_KEYS_ALL_ZEROS[] = { 0x00000000, 0x00000000, \r
-                                     0x00000000, 0x00000000, };\r
-\r
-const u32 FLASH_KEYS_MIX1[] = { 0xf0fff0ff, 0xf0fff0ff,\r
-                                0xf0fff0ff, 0xf0fff0ff };\r
-\r
-const u32 FLASH_KEYS_MIX2[] = { 0x0000ffff, 0x0000ffff,\r
-                                0x0000ffff, 0x0000ffff };\r
-\r
-/* ---------------------------------------------------------------------- */\r
-\r
-int oscMHz = 12;\r
-\r
-int\r
-tms470_handle_osc_megahertz_command( struct command_context_s * cmd_ctx, \r
-                                     char *                     cmd, \r
-                                     char **                    args, \r
-                                     int                        argc )\r
-{\r
-  if (argc > 1)\r
-    {\r
-      command_print( cmd_ctx, "tms470 osc_megahertz <MHz>" );\r
-      return ERROR_INVALID_ARGUMENTS;\r
-    }\r
-  else if (argc == 1)\r
-    {\r
-      sscanf( args[0], "%d", &oscMHz );\r
-    }\r
-\r
-  if (oscMHz <= 0)\r
-    {\r
-      ERROR( "osc_megahertz must be positive and non-zero!" );\r
-      command_print( cmd_ctx, "osc_megahertz must be positive and non-zero!" );\r
-      oscMHz = 12;\r
-      return ERROR_INVALID_ARGUMENTS;\r
-    }\r
-\r
-  command_print( cmd_ctx, "osc_megahertz=%d", oscMHz );\r
-\r
-  return ERROR_OK;\r
-}\r
-\r
-/* ---------------------------------------------------------------------- */\r
-\r
-int plldis = 0;\r
-\r
-int\r
-tms470_handle_plldis_command( struct command_context_s * cmd_ctx, \r
-                              char *                     cmd, \r
-                              char **                    args, \r
-                              int                        argc )\r
-{\r
-  if (argc > 1)\r
-    {\r
-      command_print( cmd_ctx, "tms470 plldis <0|1>" );\r
-      return ERROR_INVALID_ARGUMENTS;\r
-    }\r
-  else if (argc == 1)\r
-    {\r
-      sscanf( args[0], "%d", &plldis );\r
-      plldis = plldis ? 1 : 0;\r
-    }\r
-\r
-  command_print( cmd_ctx, "plldis=%d", plldis );\r
-\r
-  return ERROR_OK;\r
-}\r
-\r
-/* ---------------------------------------------------------------------- */\r
-\r
-int\r
-tms470_check_flash_unlocked( target_t * target )\r
-{\r
-  u32 fmbbusy;\r
-\r
-  target_read_u32( target, 0xFFE89C08, &fmbbusy );\r
-  INFO( "tms470 fmbbusy=0x%08x -> %s", \r
-         fmbbusy,\r
-         fmbbusy & 0x8000 ? "unlocked" : "LOCKED" );\r
-  return fmbbusy & 0x8000 ? ERROR_OK : ERROR_FLASH_OPERATION_FAILED;\r
-}\r
-\r
-/* ---------------------------------------------------------------------- */\r
-\r
-int\r
-tms470_try_flash_keys( target_t *  target, \r
-                       const u32 * key_set )\r
-{\r
-  u32 glbctrl, fmmstat;\r
-  int retval = ERROR_FLASH_OPERATION_FAILED;\r
-\r
-  /* set GLBCTRL.4  */\r
-  target_read_u32( target, 0xFFFFFFDC, &glbctrl );\r
-  target_write_u32( target, 0xFFFFFFDC, glbctrl | 0x10 );\r
-\r
-  /* only perform the key match when 3VSTAT is clear */\r
-  target_read_u32( target, 0xFFE8BC0C, &fmmstat );\r
-  if (!(fmmstat & 0x08))\r
-    {\r
-      unsigned i;\r
-      u32 fmmac2, fmbptr, fmbac2, fmbbusy, orig_fmregopt;\r
-      \r
-      target_write_u32( target, 0xFFE8BC04, fmmstat & ~0x07 );\r
-\r
-      /* wait for pump ready */\r
-      do\r
-        {\r
-          target_read_u32( target, 0xFFE8A814, &fmbptr );\r
-          usleep( 1000 );\r
-        }\r
-      while( !(fmbptr & 0x0200) );\r
-\r
-      /* force max wait states */\r
-      target_read_u32( target, 0xFFE88004, &fmbac2 );\r
-      target_write_u32( target, 0xFFE88004, fmbac2 | 0xff );\r
-\r
-      /* save current access mode, force normal read mode */\r
-      target_read_u32( target, 0xFFE89C00, &orig_fmregopt );\r
-      target_write_u32( target, 0xFFE89C00, 0x00 );\r
-\r
-      for( i=0; i<4; i++ )\r
-        {\r
-          u32 tmp;\r
-\r
-          /* There is no point displaying the value of tmp, it is\r
-           * filtered by the chip.  The purpose of this read is to\r
-           * prime the unlocking logic rather than read out the value.\r
-           */\r
-          target_read_u32( target, 0x00001FF0+4*i, &tmp );\r
-\r
-          INFO( "tms470 writing fmpkey=0x%08x", key_set[i] );\r
-          target_write_u32( target, 0xFFE89C0C, key_set[i] );\r
-        }\r
-\r
-      if (ERROR_OK == tms470_check_flash_unlocked( target ))\r
-        {\r
-          /* \r
-           * There seems to be a side-effect of reading the FMPKEY\r
-           * register in that it re-enables the protection.  So we\r
-           * re-enable it.\r
-           */\r
-          for( i=0; i<4; i++ )\r
-            {\r
-              u32 tmp;\r
-              target_read_u32( target, 0x00001FF0+4*i, &tmp );\r
-              target_write_u32( target, 0xFFE89C0C, key_set[i] );\r
-            }\r
-          retval = ERROR_OK;\r
-        }\r
-\r
-      /* restore settings */\r
-      target_write_u32( target, 0xFFE89C00, orig_fmregopt );\r
-      target_write_u32( target, 0xFFE88004, fmbac2 );\r
-    }\r
-\r
-  /* clear config bit */\r
-  target_write_u32( target, 0xFFFFFFDC, glbctrl );\r
-\r
-  return retval;\r
-}\r
-\r
-/* ---------------------------------------------------------------------- */\r
-\r
-int\r
-tms470_unlock_flash( struct flash_bank_s * bank )\r
-{\r
-  tms470_flash_bank_t * tms470_info = bank->driver_priv;\r
-  target_t *            target =      bank->target;\r
-  const u32 *           p_key_sets[5];\r
-  unsigned              i, key_set_count;\r
-\r
-  if (keysSet)\r
-    {\r
-      p_key_sets[0] = flashKeys;\r
-      p_key_sets[1] = FLASH_KEYS_ALL_ONES;\r
-      p_key_sets[2] = FLASH_KEYS_ALL_ZEROS;\r
-      p_key_sets[3] = FLASH_KEYS_MIX1;\r
-      p_key_sets[4] = FLASH_KEYS_MIX2;\r
-    }\r
-  else\r
-    {\r
-      key_set_count = 4;\r
-      p_key_sets[0] = FLASH_KEYS_ALL_ONES;\r
-      p_key_sets[1] = FLASH_KEYS_ALL_ZEROS;\r
-      p_key_sets[2] = FLASH_KEYS_MIX1;\r
-      p_key_sets[3] = FLASH_KEYS_MIX2;\r
-    }\r
-\r
-  for( i=0; i<key_set_count; i++ )\r
-    {\r
-      if (tms470_try_flash_keys( target, p_key_sets[i] ) == ERROR_OK)\r
-        {\r
-          INFO( "tms470 flash is unlocked" );\r
-          return ERROR_OK;\r
-        }\r
-    }\r
-\r
-  WARNING( "tms470 could not unlock flash memory protection level 2" );\r
-  return ERROR_FLASH_OPERATION_FAILED;\r
-}\r
-\r
-/* ---------------------------------------------------------------------- */\r
-\r
-int\r
-tms470_flash_initialize_internal_state_machine( struct flash_bank_s * bank )\r
-{\r
-  u32 fmmac2, fmmac1, fmmaxep, k, delay, glbctrl, sysclk;\r
-  target_t *target = bank->target;\r
-  tms470_flash_bank_t * tms470_info = bank->driver_priv;\r
-  int result = ERROR_OK;\r
-\r
-  /*\r
-   * Select the desired bank to be programmed by writing BANK[2:0] of\r
-   * FMMAC2.\r
-   */\r
-  target_read_u32( target, 0xFFE8BC04, &fmmac2 );\r
-  fmmac2 &= ~0x0007;\r
-  fmmac2 |= (tms470_info->ordinal & 7);\r
-  target_write_u32( target, 0xFFE8BC04, fmmac2 );\r
-  DEBUG( "set fmmac2=0x%04x", fmmac2 );\r
-\r
-  /*\r
-   * Disable level 1 sector protection by setting bit 15 of FMMAC1.\r
-   */\r
-  target_read_u32( target, 0xFFE8BC00, &fmmac1 );\r
-  fmmac1 |= 0x8000;\r
-  target_write_u32( target, 0xFFE8BC00, fmmac1 );\r
-  DEBUG( "set fmmac1=0x%04x", fmmac1 );\r
-\r
-  /*\r
-   * FMTCREG=0x2fc0;\r
-   */\r
-  target_write_u32( target, 0xFFE8BC10, 0x2fc0 );\r
-  DEBUG( "set fmtcreg=0x2fc0" );\r
-\r
-  /*\r
-   * MAXPP=50\r
-   */\r
-  target_write_u32( target, 0xFFE8A07C, 50 );\r
-  DEBUG( "set fmmaxpp=50" );\r
-\r
-  /*\r
-   * MAXCP=0xf000+2000\r
-   */\r
-  target_write_u32( target, 0xFFE8A084, 0xf000+2000 );\r
-  DEBUG( "set fmmaxcp=0x%04x", 0xf000+2000 );\r
-\r
-    /*\r
-   * configure VHV\r
-   */\r
-  target_read_u32( target, 0xFFE8A080, &fmmaxep );\r
-  if (fmmaxep == 0xf000) \r
-    {\r
-      fmmaxep = 0xf000+4095;\r
-      target_write_u32( target, 0xFFE8A80C, 0x9964 );\r
-      DEBUG( "set fmptr3=0x9964" );\r
-    }\r
-  else\r
-    {\r
-      fmmaxep = 0xa000+4095;\r
-      target_write_u32( target, 0xFFE8A80C, 0x9b64 );\r
-      DEBUG( "set fmptr3=0x9b64" );\r
-    }\r
-  target_write_u32( target, 0xFFE8A080, fmmaxep );\r
-  DEBUG( "set fmmaxep=0x%04x", fmmaxep );\r
-\r
-  /*\r
-   * FMPTR4=0xa000\r
-   */\r
-  target_write_u32( target, 0xFFE8A810, 0xa000 );\r
-  DEBUG( "set fmptr4=0xa000" );\r
-\r
-  /*\r
-   * FMPESETUP, delay parameter selected based on clock frequency.\r
-   *\r
-   * According to the TI App Note SPNU257 and flashing code, delay is\r
-   * int((sysclk(MHz) + 1) / 2), with a minimum of 5.  The system\r
-   * clock is usually derived from the ZPLL module, and selected by\r
-   * the plldis global.\r
-   */\r
-  target_read_u32( target, 0xFFFFFFDC, &glbctrl );\r
-  sysclk = (plldis ? 1 : (glbctrl & 0x08) ? 4 : 8 ) * oscMHz / (1 + (glbctrl & 7));\r
-  delay = (sysclk > 10) ? (sysclk + 1) / 2 : 5;\r
-  target_write_u32( target, 0xFFE8A018, (delay<<4)|(delay<<8) );\r
-  DEBUG( "set fmpsetup=0x%04x", (delay<<4)|(delay<<8) );\r
-\r
-  /*\r
-   * FMPVEVACCESS, based on delay.\r
-   */\r
-  k = delay|(delay<<8);\r
-  target_write_u32( target, 0xFFE8A05C, k );\r
-  DEBUG( "set fmpvevaccess=0x%04x", k );\r
-  \r
-  /*\r
-   * FMPCHOLD, FMPVEVHOLD, FMPVEVSETUP, based on delay.\r
-   */\r
-  k <<= 1;\r
-  target_write_u32( target, 0xFFE8A034, k );\r
-  DEBUG( "set fmpchold=0x%04x", k );\r
-  target_write_u32( target, 0xFFE8A040, k );\r
-  DEBUG( "set fmpvevhold=0x%04x", k );\r
-  target_write_u32( target, 0xFFE8A024, k );\r
-  DEBUG( "set fmpvevsetup=0x%04x", k );\r
-\r
-  /*\r
-   * FMCVACCESS, based on delay.\r
-   */\r
-  k = delay*16;\r
-  target_write_u32( target, 0xFFE8A060, k );\r
-  DEBUG( "set fmcvaccess=0x%04x", k );\r
-\r
-  /*\r
-   * FMCSETUP, based on delay.\r
-   */\r
-  k = 0x3000 | delay*20;\r
-  target_write_u32( target, 0xFFE8A020, k );\r
-  DEBUG( "set fmcsetup=0x%04x", k );\r
-\r
-  /*\r
-   * FMEHOLD, based on delay.\r
-   */\r
-  k = (delay*20) << 2;\r
-  target_write_u32( target, 0xFFE8A038, k );\r
-  DEBUG( "set fmehold=0x%04x", k );\r
-\r
-  /*\r
-   * PWIDTH, CWIDTH, EWIDTH, based on delay.\r
-   */\r
-  target_write_u32( target, 0xFFE8A050, delay*8 );\r
-  DEBUG( "set fmpwidth=0x%04x", delay*8 );\r
-  target_write_u32( target, 0xFFE8A058, delay*1000 );\r
-  DEBUG( "set fmcwidth=0x%04x", delay*1000 );\r
-  target_write_u32( target, 0xFFE8A054, delay*5400 );\r
-  DEBUG( "set fmewidth=0x%04x", delay*5400 );\r
-\r
-  return result;\r
-}\r
-                                                \r
-\r
-/* ---------------------------------------------------------------------- */\r
-\r
-int\r
-tms470_flash_status( struct flash_bank_s * bank )\r
-{\r
-  target_t *target = bank->target;\r
-  int result = ERROR_OK;\r
-  u32 fmmstat;\r
-\r
-  target_read_u32( target, 0xFFE8BC0C, &fmmstat );\r
-  DEBUG( "set fmmstat=0x%04x", fmmstat );\r
-\r
-  if (fmmstat & 0x0080)\r
-    {\r
-      WARNING( "tms470 flash command: erase still active after busy clear." );\r
-      result = ERROR_FLASH_OPERATION_FAILED;\r
-    }\r
-\r
-  if (fmmstat & 0x0040)\r
-    {\r
-      WARNING( "tms470 flash command: program still active after busy clear." );\r
-      result = ERROR_FLASH_OPERATION_FAILED;\r
-    }\r
-\r
-  if (fmmstat & 0x0020)\r
-    {\r
-      WARNING( "tms470 flash command: invalid data command." );\r
-      result = ERROR_FLASH_OPERATION_FAILED;\r
-    }\r
-\r
-  if (fmmstat & 0x0010)\r
-    {\r
-      WARNING( "tms470 flash command: program, erase or validate sector failed." );\r
-      result = ERROR_FLASH_OPERATION_FAILED;\r
-    }\r
-\r
-  if (fmmstat & 0x0008)\r
-    {\r
-      WARNING( "tms470 flash command: voltage instability detected." );\r
-      result = ERROR_FLASH_OPERATION_FAILED;\r
-    }\r
-\r
-  if (fmmstat & 0x0006)\r
-    {\r
-      WARNING( "tms470 flash command: command suspend detected." );\r
-      result = ERROR_FLASH_OPERATION_FAILED;\r
-    }\r
-\r
-  if (fmmstat & 0x0001)\r
-    {\r
-      WARNING( "tms470 flash command: sector was locked." );\r
-      result = ERROR_FLASH_OPERATION_FAILED;\r
-    }\r
-\r
-  return result;\r
-}\r
-\r
-/* ---------------------------------------------------------------------- */\r
-\r
-int\r
-tms470_erase_sector( struct flash_bank_s * bank, \r
-                     int                   sector )\r
-{\r
-  u32 glbctrl, orig_fmregopt, fmbsea, fmbseb, fmmstat;\r
-  target_t *target = bank->target;\r
-  u32 flashAddr = bank->base + bank->sectors[sector].offset;\r
-  int result = ERROR_OK;\r
-\r
-  /* \r
-   * Set the bit GLBCTRL4 of the GLBCTRL register (in the System\r
-   * module) to enable writing to the flash registers }.\r
-   */\r
-  target_read_u32( target, 0xFFFFFFDC, &glbctrl );\r
-  target_write_u32( target, 0xFFFFFFDC, glbctrl | 0x10 );\r
-  DEBUG( "set glbctrl=0x%08x", glbctrl | 0x10 );\r
-\r
-  /* Force normal read mode. */\r
-  target_read_u32( target, 0xFFE89C00, &orig_fmregopt );\r
-  target_write_u32( target, 0xFFE89C00, 0 );\r
-  DEBUG( "set fmregopt=0x%08x", 0 );\r
-\r
-  (void) tms470_flash_initialize_internal_state_machine( bank );\r
-  \r
-  /*\r
-   * Select one or more bits in FMBSEA or FMBSEB to disable Level 1\r
-   * protection for the particular sector to be erased/written.\r
-   */\r
-  if (sector < 16)\r
-    {\r
-      target_read_u32( target, 0xFFE88008, &fmbsea );\r
-      target_write_u32( target, 0xFFE88008, fmbsea | (1<<sector) );\r
-      DEBUG( "set fmbsea=0x%04x", fmbsea | (1<<sector) );\r
-    }\r
-  else\r
-    {\r
-      target_read_u32( target, 0xFFE8800C, &fmbseb );\r
-      target_write_u32( target, 0xFFE8800C, fmbseb | (1<<(sector-16)) );\r
-      DEBUG( "set fmbseb=0x%04x", fmbseb | (1<<(sector-16)) );\r
-    }\r
-  bank->sectors[sector].is_protected = 0;\r
-\r
-  /* \r
-   * clear status regiser, sent erase command, kickoff erase \r
-   */\r
-  target_write_u16( target, flashAddr, 0x0040 );\r
-  DEBUG( "write *(u16 *)0x%08x=0x0040", flashAddr );\r
-  target_write_u16( target, flashAddr, 0x0020 );\r
-  DEBUG( "write *(u16 *)0x%08x=0x0020", flashAddr );\r
-  target_write_u16( target, flashAddr, 0xffff );\r
-  DEBUG( "write *(u16 *)0x%08x=0xffff", flashAddr );\r
-\r
-  /*\r
-   * Monitor FMMSTAT, busy until clear, then check and other flags for\r
-   * ultimate result of the operation.\r
-   */\r
-  do\r
-    {\r
-      target_read_u32( target, 0xFFE8BC0C, &fmmstat );\r
-      if (fmmstat & 0x0100)\r
-        {\r
-          usleep( 1000 );\r
-        }\r
-    }\r
-  while( fmmstat & 0x0100 );\r
-\r
-  result = tms470_flash_status( bank );\r
-\r
-  if (sector < 16)\r
-    {\r
-      target_write_u32( target, 0xFFE88008, fmbsea );\r
-      DEBUG( "set fmbsea=0x%04x", fmbsea );\r
-      bank->sectors[sector].is_protected = \r
-        fmbsea & (1<<sector) ? 0 : 1;\r
-    }\r
-  else\r
-    {\r
-      target_write_u32( target, 0xFFE8800C, fmbseb );\r
-      DEBUG( "set fmbseb=0x%04x", fmbseb );\r
-      bank->sectors[sector].is_protected = \r
-        fmbseb & (1<<(sector-16)) ? 0 : 1;\r
-    }\r
-  target_write_u32( target, 0xFFE89C00, orig_fmregopt );\r
-  DEBUG( "set fmregopt=0x%08x", orig_fmregopt );\r
-  target_write_u32( target, 0xFFFFFFDC, glbctrl );\r
-  DEBUG( "set glbctrl=0x%08x", glbctrl );\r
-\r
-  if (result == ERROR_OK)\r
-    {\r
-      bank->sectors[sector].is_erased = 1;\r
-    }\r
-\r
-  return result;\r
-}\r
-\r
-/* ---------------------------------------------------------------------- \r
-              Implementation of Flash Driver Interfaces\r
-   ---------------------------------------------------------------------- */\r
-\r
-int \r
-tms470_register_commands( struct command_context_s *cmd_ctx )\r
-{\r
-  command_t *tms470_cmd = register_command( cmd_ctx, \r
-                                            NULL, \r
-                                            "tms470", \r
-                                            NULL, \r
-                                            COMMAND_ANY, \r
-                                            "applies to TI tms470 family" );\r
-\r
-  register_command( cmd_ctx, \r
-                    tms470_cmd, \r
-                    "flash_keyset", \r
-                    tms470_handle_flash_keyset_command, \r
-                    COMMAND_ANY,\r
-                   "tms470 flash_keyset <key0> <key1> <key2> <key3>" );\r
-\r
-  register_command( cmd_ctx,\r
-                    tms470_cmd,\r
-                    "osc_megahertz",\r
-                    tms470_handle_osc_megahertz_command,\r
-                    COMMAND_ANY,\r
-                    "tms470 osc_megahertz <MHz>" );\r
-\r
-  register_command( cmd_ctx,\r
-                    tms470_cmd,\r
-                    "plldis",\r
-                    tms470_handle_plldis_command,\r
-                    COMMAND_ANY,\r
-                    "tms470 plldis <0/1>" );\r
-  \r
-  return ERROR_OK;\r
-}\r
-\r
-/* ---------------------------------------------------------------------- */\r
-\r
-int \r
-tms470_erase( struct flash_bank_s * bank, \r
-              int                   first, \r
-              int                   last )\r
-{\r
-  tms470_flash_bank_t *tms470_info = bank->driver_priv;\r
-  target_t *target = bank->target;\r
-  int sector, result = ERROR_OK;\r
-\r
-  if (!tms470_info->device_ident_reg)\r
-    {\r
-      tms470_read_part_info( bank );\r
-    }\r
-\r
-  if ((first < 0) || \r
-      (first >= bank->num_sectors) ||\r
-      (last < 0) ||\r
-      (last >= bank->num_sectors) ||\r
-      (first > last))\r
-    {\r
-      ERROR( "Sector range %d to %d invalid.", first, last );\r
-      return ERROR_FLASH_SECTOR_INVALID;\r
-    }\r
-\r
-  result = tms470_unlock_flash( bank );\r
-  if (result != ERROR_OK)\r
-    {\r
-      return result;\r
-    }\r
-\r
-  for( sector=first; sector<=last; sector++ )\r
-    {\r
-      INFO( "Erasing tms470 bank %d sector %d...",\r
-            tms470_info->ordinal, sector );\r
-\r
-      result = tms470_erase_sector( bank, sector );\r
-\r
-      if (result != ERROR_OK)\r
-        {\r
-          ERROR( "tms470 could not erase flash sector." );\r
-          break;\r
-        }\r
-      else\r
-        {\r
-          INFO( "sector erased successfully." );\r
-        }\r
-    }\r
-  \r
-  return result;\r
-}\r
-\r
-/* ---------------------------------------------------------------------- */\r
-\r
-int \r
-tms470_protect( struct flash_bank_s * bank, \r
-                int                   set, \r
-                int                   first, \r
-                int                   last )\r
-{\r
-  tms470_flash_bank_t *tms470_info = bank->driver_priv;\r
-  target_t *target = bank->target;\r
-  u32 fmmac2, fmbsea, fmbseb;\r
-  int sector;\r
-\r
-  if (!tms470_info->device_ident_reg)\r
-    {\r
-      tms470_read_part_info( bank );\r
-    }\r
-\r
-  if ((first < 0) || \r
-      (first >= bank->num_sectors) ||\r
-      (last < 0) ||\r
-      (last >= bank->num_sectors) ||\r
-      (first > last))\r
-    {\r
-      ERROR( "Sector range %d to %d invalid.", first, last );\r
-      return ERROR_FLASH_SECTOR_INVALID;\r
-    }\r
-\r
-  /* enable the appropriate bank */\r
-  target_read_u32( target, 0xFFE8BC04, &fmmac2 );\r
-  target_write_u32( target, 0xFFE8BC04, \r
-                    (fmmac2 & ~7) | tms470_info->ordinal );\r
-\r
-  /* get the original sector proection flags for this bank */\r
-  target_read_u32( target, 0xFFE88008, &fmbsea );\r
-  target_read_u32( target, 0xFFE8800C, &fmbseb );\r
-  \r
-  for( sector=0; sector<bank->num_sectors; sector++ )\r
-    {\r
-      if (sector < 16)\r
-        {\r
-          fmbsea = set ? fmbsea & ~(1<<sector) : \r
-                         fmbsea | (1<<sector);\r
-          bank->sectors[sector].is_protected = set ? 1 : 0;\r
-        }\r
-      else\r
-        {\r
-          fmbseb = set ? fmbseb & ~(1<<(sector-16)) : \r
-                         fmbseb | (1<<(sector-16));\r
-          bank->sectors[sector].is_protected = set ? 1 : 0;\r
-        }\r
-    }\r
-\r
-  /* update the protection bits */\r
-  target_write_u32( target, 0xFFE88008, fmbsea );\r
-  target_write_u32( target, 0xFFE8800C, fmbseb );\r
-\r
-  return ERROR_OK;\r
-}\r
-\r
-/* ---------------------------------------------------------------------- */\r
-\r
-int \r
-tms470_write( struct flash_bank_s * bank, \r
-              u8 *                  buffer, \r
-              u32                   offset, \r
-              u32                   count )\r
-{\r
-  target_t *target = bank->target;\r
-  tms470_flash_bank_t *tms470_info = bank->driver_priv;\r
-  u32 glbctrl, fmbac2, orig_fmregopt, fmbsea, fmbseb, fmmaxpp, fmmstat;\r
-  int i, result = ERROR_OK;\r
-\r
-  if (!tms470_info->device_ident_reg)\r
-    {\r
-      tms470_read_part_info( bank );\r
-    }\r
-\r
-  INFO( "Writing %d bytes starting at 0x%08x",\r
-        count, bank->base + offset );\r
-\r
-  /* set GLBCTRL.4  */\r
-  target_read_u32( target, 0xFFFFFFDC, &glbctrl );\r
-  target_write_u32( target, 0xFFFFFFDC, glbctrl | 0x10 );\r
-\r
-  (void) tms470_flash_initialize_internal_state_machine( bank );\r
-\r
-  /* force max wait states */\r
-  target_read_u32( target, 0xFFE88004, &fmbac2 );\r
-  target_write_u32( target, 0xFFE88004, fmbac2 | 0xff );\r
-\r
-  /* save current access mode, force normal read mode */\r
-  target_read_u32( target, 0xFFE89C00, &orig_fmregopt );\r
-  target_write_u32( target, 0xFFE89C00, 0x00 );\r
-\r
-  /*\r
-   * Disable Level 1 protection for all sectors to be erased/written.\r
-   */\r
-  target_read_u32( target, 0xFFE88008, &fmbsea );\r
-  target_write_u32( target, 0xFFE88008, 0xffff );\r
-  target_read_u32( target, 0xFFE8800C, &fmbseb );\r
-  target_write_u32( target, 0xFFE8800C, 0xffff );\r
-\r
-  /* read MAXPP */\r
-  target_read_u32( target, 0xFFE8A07C, &fmmaxpp );\r
-\r
-  for( i=0; i<count; i+=2 )\r
-    {\r
-      u32 addr = bank->base + offset + i;\r
-      u16 word = (((u16) buffer[i]) << 8) | (u16) buffer[i+1];\r
-\r
-      if (word != 0xffff)\r
-        {\r
-          INFO( "writing 0x%04x at 0x%08x", word, addr );\r
-\r
-          /* clear status register */\r
-          target_write_u16( target, addr, 0x0040 );\r
-          /* program flash command */\r
-          target_write_u16( target, addr, 0x0010 );\r
-          /* burn the 16-bit word (big-endian) */\r
-          target_write_u16( target, addr, word );\r
-\r
-          /*\r
-           * Monitor FMMSTAT, busy until clear, then check and other flags\r
-           * for ultimate result of the operation.\r
-           */\r
-          do\r
-            {\r
-              target_read_u32( target, 0xFFE8BC0C, &fmmstat );\r
-              if (fmmstat & 0x0100)\r
-                {\r
-                  usleep( 1000 );\r
-                }\r
-            }\r
-          while( fmmstat & 0x0100 );\r
-\r
-          if (fmmstat & 0x3ff)\r
-            {\r
-              ERROR( "fmstat=0x%04x", fmmstat );\r
-              ERROR( "Could not program word 0x%04x at address 0x%08x.",\r
-                     word, addr );\r
-              result = ERROR_FLASH_OPERATION_FAILED;\r
-              break;\r
-            }\r
-        }\r
-      else\r
-        {\r
-          INFO( "skipping 0xffff at 0x%08x", addr );\r
-        }\r
-    }\r
-\r
-  /* restore */\r
-  target_write_u32( target, 0xFFE88008, fmbsea );\r
-  target_write_u32( target, 0xFFE8800C, fmbseb );\r
-  target_write_u32( target, 0xFFE88004, fmbac2 );\r
-  target_write_u32( target, 0xFFE89C00, orig_fmregopt );\r
-  target_write_u32( target, 0xFFFFFFDC, glbctrl );\r
-\r
-  return result;\r
-}\r
-\r
-/* ---------------------------------------------------------------------- */\r
-\r
-int \r
-tms470_probe( struct flash_bank_s * bank )\r
-{\r
-  tms470_flash_bank_t * tms470_info = bank->driver_priv;\r
-\r
-  if (!tms470_info->device_ident_reg)\r
-    {\r
-      tms470_read_part_info( bank );\r
-    }\r
-\r
-  return ERROR_OK;\r
-}\r
-\r
-/* ---------------------------------------------------------------------- */\r
-\r
-int \r
-tms470_erase_check( struct flash_bank_s * bank )\r
-{\r
-  target_t *target = bank->target;\r
-  tms470_flash_bank_t * tms470_info = bank->driver_priv;\r
-  int sector, result = ERROR_OK;\r
-  u32 fmmac2, fmbac2, glbctrl, orig_fmregopt;\r
-  static u8 buffer[64*1024];\r
-\r
-  if (!tms470_info->device_ident_reg)\r
-    {\r
-      tms470_read_part_info( bank );\r
-    }\r
-\r
-  /* set GLBCTRL.4  */\r
-  target_read_u32( target, 0xFFFFFFDC, &glbctrl );\r
-  target_write_u32( target, 0xFFFFFFDC, glbctrl | 0x10 );\r
-\r
-  /* save current access mode, force normal read mode */\r
-  target_read_u32( target, 0xFFE89C00, &orig_fmregopt );\r
-  target_write_u32( target, 0xFFE89C00, 0x00 );\r
-\r
-  /* enable the appropriate bank */\r
-  target_read_u32( target, 0xFFE8BC04, &fmmac2 );\r
-  target_write_u32( target, 0xFFE8BC04, \r
-                    (fmmac2 & ~7) | tms470_info->ordinal );\r
-\r
-  /* TCR=0 */\r
-  target_write_u32( target, 0xFFE8BC10, 0x2fc0 );\r
-\r
-  /* clear TEZ in fmbrdy */\r
-  target_write_u32( target, 0xFFE88010, 0x0b );\r
-\r
-  /* save current wait states, force max */\r
-  target_read_u32( target, 0xFFE88004, &fmbac2 );\r
-  target_write_u32( target, 0xFFE88004, fmbac2 | 0xff );\r
-\r
-  /* \r
-   * The TI primitives inspect the flash memory by reading one 32-bit\r
-   * word at a time.  Here we read an entire sector and inspect it in\r
-   * an attempt to reduce the JTAG overhead.\r
-   */\r
-  for( sector=0; sector<bank->num_sectors; sector++ )\r
-    {\r
-      if (bank->sectors[sector].is_erased != 1)\r
-        {\r
-          u32 i, addr = bank->base + bank->sectors[sector].offset;\r
-          \r
-          INFO( "checking flash bank %d sector %d",\r
-                tms470_info->ordinal,\r
-                sector );\r
-\r
-          target_read_buffer( target, \r
-                              addr,\r
-                              bank->sectors[sector].size,\r
-                              buffer );\r
-\r
-          bank->sectors[sector].is_erased = 1;\r
-          for( i=0; i<bank->sectors[sector].size; i++ )\r
-            {\r
-              if (buffer[i] != 0xff)\r
-                {\r
-                  WARNING( "tms470 bank %d, sector %d, not erased.",\r
-                           tms470_info->ordinal,\r
-                           sector );\r
-                  WARNING( "at location 0x%08x: flash data is 0x%02x.",\r
-                           addr+i, \r
-                           buffer[i] );\r
-                           \r
-                  bank->sectors[sector].is_erased = 0;\r
-                  break;\r
-                }\r
-            }\r
-        }\r
-      if (bank->sectors[sector].is_erased != 1)\r
-        {\r
-          result = ERROR_FLASH_SECTOR_NOT_ERASED;\r
-          break;\r
-        }\r
-      else\r
-        {\r
-          INFO( "sector erased" );\r
-        }\r
-    }\r
-\r
-  /* reset TEZ, wait states, read mode, GLBCTRL.4 */\r
-  target_write_u32( target, 0xFFE88010, 0x0f );\r
-  target_write_u32( target, 0xFFE88004, fmbac2 );\r
-  target_write_u32( target, 0xFFE89C00, orig_fmregopt );\r
-  target_write_u32( target, 0xFFFFFFDC, glbctrl );\r
-\r
-  return result;\r
-}\r
-\r
-/* ---------------------------------------------------------------------- */\r
-\r
-int \r
-tms470_protect_check( struct flash_bank_s * bank )\r
-{\r
-  target_t *target = bank->target;\r
-  tms470_flash_bank_t * tms470_info = bank->driver_priv;\r
-  int sector, result = ERROR_OK;\r
-  u32 fmmac2, fmbsea, fmbseb;\r
-\r
-  if (!tms470_info->device_ident_reg)\r
-    {\r
-      tms470_read_part_info( bank );\r
-    }\r
-\r
-  /* enable the appropriate bank */\r
-  target_read_u32( target, 0xFFE8BC04, &fmmac2 );\r
-  target_write_u32( target, 0xFFE8BC04, \r
-                    (fmmac2 & ~7) | tms470_info->ordinal );\r
-\r
-  target_read_u32( target, 0xFFE88008, &fmbsea );\r
-  target_read_u32( target, 0xFFE8800C, &fmbseb );\r
-  \r
-  for( sector=0; sector<bank->num_sectors; sector++ )\r
-    {\r
-      int protected;\r
-\r
-      if (sector < 16)\r
-        {\r
-          protected = fmbsea & (1<<sector) ? 0 : 1;\r
-          bank->sectors[sector].is_protected = protected;\r
-        }\r
-      else\r
-        {\r
-          protected = fmbseb & (1<<(sector-16)) ? 0 : 1;\r
-          bank->sectors[sector].is_protected = protected;\r
-        }\r
-\r
-      DEBUG( "bank %d sector %d is %s",\r
-             tms470_info->ordinal,\r
-             sector,\r
-             protected ? "protected" : "not protected" );\r
-    }\r
-\r
-  return result;\r
-}\r
-\r
-/* ---------------------------------------------------------------------- */\r
-\r
-int \r
-tms470_info( struct flash_bank_s * bank, \r
-             char *                buf, \r
-             int                   buf_size )\r
-{\r
-  int used = 0;\r
-  tms470_flash_bank_t * tms470_info = bank->driver_priv;\r
-\r
-  if (!tms470_info->device_ident_reg)\r
-    {\r
-      tms470_read_part_info( bank );\r
-    }\r
-\r
-  if (!tms470_info->device_ident_reg)\r
-    {\r
-      (void) snprintf(buf, buf_size, "Cannot identify target as a TMS470\n");\r
-      return ERROR_FLASH_OPERATION_FAILED;\r
-    }\r
-\r
-  used += snprintf( buf, buf_size, \r
-                    "\ntms470 information: Chip is %s\n",\r
-                    tms470_info->part_name );\r
-  buf += used;\r
-  buf_size -= used;\r
-\r
-  used += snprintf( buf, buf_size,\r
-                    "Flash protection level 2 is %s\n",\r
-                    tms470_check_flash_unlocked( bank->target ) == ERROR_OK ? "disabled" : "enabled" );\r
-  buf += used;\r
-  buf_size -= used;\r
-\r
-  return ERROR_OK;\r
-}\r
-\r
-/* ---------------------------------------------------------------------- */\r
-\r
-/*\r
- * flash bank tms470 <base> <size> <chip_width> <bus_width> <target>\r
- * [options...]\r
- */\r
-\r
-int \r
-tms470_flash_bank_command( struct command_context_s *cmd_ctx, \r
-                           char *cmd, \r
-                           char **args, \r
-                           int argc, \r
-                           struct flash_bank_s *bank )\r
-{\r
-  bank->driver_priv = malloc( sizeof( tms470_flash_bank_t ) );\r
-\r
-  if (!bank->driver_priv)\r
-    {\r
-      return ERROR_FLASH_OPERATION_FAILED;\r
-    }\r
-\r
-  (void) memset( bank->driver_priv, 0, sizeof( tms470_flash_bank_t ) );\r
-\r
-  return ERROR_OK;\r
-}\r
+/***************************************************************************
+ *   (c) Copyright 2007, 2008 by Christopher Kilgour                       *
+ *   techie |_at_| whiterocker |_dot_| com                                 *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "log.h"
+#include "tms470.h"
+#include <string.h>
+#include <unistd.h>
+
+int 
+tms470_register_commands( struct command_context_s *cmd_ctx );
+
+int 
+tms470_flash_bank_command( struct command_context_s *cmd_ctx, 
+                           char *cmd, 
+                           char **args, 
+                           int argc, 
+                           struct flash_bank_s *bank );
+
+int 
+tms470_erase( struct flash_bank_s *bank, 
+              int first, 
+              int last );
+
+int 
+tms470_protect( struct flash_bank_s *bank, 
+                int set, 
+                int first, 
+                int last );
+
+int 
+tms470_write( struct flash_bank_s *bank, 
+              u8 *buffer, 
+              u32 offset, 
+              u32 count );
+
+int 
+tms470_probe( struct flash_bank_s *bank );
+
+int 
+tms470_auto_probe( struct flash_bank_s *bank );
+
+int 
+tms470_erase_check( struct flash_bank_s *bank );
+
+int 
+tms470_protect_check( struct flash_bank_s *bank );
+
+int 
+tms470_info( struct flash_bank_s *bank, 
+             char *buf, 
+             int buf_size );
+
+flash_driver_t tms470_flash =
+  {
+    .name =               "tms470",
+    .register_commands =  tms470_register_commands,
+    .flash_bank_command = tms470_flash_bank_command,
+    .erase =              tms470_erase,
+    .protect =            tms470_protect,
+    .write =              tms470_write,
+    .probe =              tms470_probe,
+    .auto_probe =         tms470_auto_probe,
+    .erase_check =        tms470_erase_check,
+    .protect_check =      tms470_protect_check,
+    .info =               tms470_info
+  };
+
+/* ---------------------------------------------------------------------- 
+                      Internal Support, Helpers
+   ---------------------------------------------------------------------- */
+
+const flash_sector_t TMS470R1A256_SECTORS[] =
+  {
+    { 0x00000000, 0x00002000, -1, -1 },
+    { 0x00002000, 0x00002000, -1, -1 },
+    { 0x00004000, 0x00002000, -1, -1 },
+    { 0x00006000, 0x00002000, -1, -1 },
+    { 0x00008000, 0x00008000, -1, -1 },
+    { 0x00010000, 0x00008000, -1, -1 },
+    { 0x00018000, 0x00008000, -1, -1 },
+    { 0x00020000, 0x00008000, -1, -1 },
+    { 0x00028000, 0x00008000, -1, -1 },
+    { 0x00030000, 0x00008000, -1, -1 },
+    { 0x00038000, 0x00002000, -1, -1 },
+    { 0x0003A000, 0x00002000, -1, -1 },
+    { 0x0003C000, 0x00002000, -1, -1 },
+    { 0x0003E000, 0x00002000, -1, -1 },
+  };
+
+#define TMS470R1A256_NUM_SECTORS \
+  (sizeof(TMS470R1A256_SECTORS)/sizeof(TMS470R1A256_SECTORS[0]))
+
+const flash_sector_t TMS470R1A288_BANK0_SECTORS[] =
+  {
+    { 0x00000000, 0x00002000, -1, -1 },
+    { 0x00002000, 0x00002000, -1, -1 },
+    { 0x00004000, 0x00002000, -1, -1 },
+    { 0x00006000, 0x00002000, -1, -1 },
+  };
+
+#define TMS470R1A288_BANK0_NUM_SECTORS \
+  (sizeof(TMS470R1A288_BANK0_SECTORS)/sizeof(TMS470R1A288_BANK0_SECTORS[0]))
+
+const flash_sector_t TMS470R1A288_BANK1_SECTORS[] =
+  {
+    { 0x00040000, 0x00010000, -1, -1 },
+    { 0x00050000, 0x00010000, -1, -1 },
+    { 0x00060000, 0x00010000, -1, -1 },
+    { 0x00070000, 0x00010000, -1, -1 },
+  };
+
+#define TMS470R1A288_BANK1_NUM_SECTORS \
+  (sizeof(TMS470R1A288_BANK1_SECTORS)/sizeof(TMS470R1A288_BANK1_SECTORS[0]))
+
+/* ---------------------------------------------------------------------- */
+
+int 
+tms470_read_part_info( struct flash_bank_s *bank )
+{
+  tms470_flash_bank_t *tms470_info = bank->driver_priv;
+  target_t *target = bank->target;
+  u32    device_ident_reg;
+  u32    silicon_version;
+  u32    technology_family;
+  u32    rom_flash;
+  u32    part_number;
+  char * part_name;
+
+  if (target->state != TARGET_HALTED)
+    {
+      WARNING( "Cannot communicate... target not halted." );
+      return ERROR_TARGET_NOT_HALTED;
+    }
+
+  /* read and parse the device identification register */
+  target_read_u32( target, 0xFFFFFFF0, &device_ident_reg );
+
+  INFO( "device_ident_reg=0x%08x", device_ident_reg );
+  
+  if ((device_ident_reg & 7) == 0)
+    {
+      WARNING( "Cannot identify target as a TMS470 family." );
+      return ERROR_FLASH_OPERATION_FAILED;
+    }
+
+  silicon_version = (device_ident_reg >> 12) & 0xF;
+  technology_family = (device_ident_reg >> 11) & 1;
+  rom_flash = (device_ident_reg >> 10) & 1;
+  part_number = (device_ident_reg >> 3) & 0x7f;
+
+  /*
+   * If the part number is known, determine if the flash bank is valid
+   * based on the base address being within the known flash bank
+   * ranges.  Then fixup/complete the remaining fields of the flash
+   * bank structure.
+   */
+  switch( part_number )
+    {
+    case 0x0a:
+      part_name = "TMS470R1A256";
+
+      if (bank->base >= 0x00040000)
+        {
+          ERROR( "No %s flash bank contains base address 0x%08x.", 
+                 part_name, bank->base );
+          return ERROR_FLASH_OPERATION_FAILED;
+        }
+      tms470_info->ordinal = 0;
+      bank->base           = 0x00000000;
+      bank->size           = 256*1024;
+      bank->num_sectors    = TMS470R1A256_NUM_SECTORS;
+      bank->sectors = malloc( sizeof( TMS470R1A256_SECTORS ) );
+      if (!bank->sectors)
+        {
+          return ERROR_FLASH_OPERATION_FAILED;
+        }
+      (void) memcpy( bank->sectors,
+                     TMS470R1A256_SECTORS,
+                     sizeof( TMS470R1A256_SECTORS ) );
+      break;
+
+    case 0x2b:
+      part_name = "TMS470R1A288";
+
+      if ((bank->base >= 0x00000000) && (bank->base < 0x00008000))
+        {
+          tms470_info->ordinal = 0;
+          bank->base           = 0x00000000;
+          bank->size           = 32*1024;
+          bank->num_sectors    = TMS470R1A288_BANK0_NUM_SECTORS;
+          bank->sectors = malloc( sizeof( TMS470R1A288_BANK0_SECTORS ) );
+          if (!bank->sectors)
+            {
+              return ERROR_FLASH_OPERATION_FAILED;
+            }
+          (void) memcpy( bank->sectors,
+                         TMS470R1A288_BANK0_SECTORS,
+                         sizeof( TMS470R1A288_BANK0_SECTORS ) );
+        }
+      else if ((bank->base >= 0x00040000) && (bank->base < 0x00080000))
+        {
+          tms470_info->ordinal = 1;
+          bank->base           = 0x00040000;
+          bank->size           = 256*1024;
+          bank->num_sectors    = TMS470R1A288_BANK1_NUM_SECTORS;
+          bank->sectors = malloc( sizeof( TMS470R1A288_BANK1_SECTORS ) );
+          if (!bank->sectors)
+            {
+              return ERROR_FLASH_OPERATION_FAILED;
+            }
+          (void) memcpy( bank->sectors,
+                         TMS470R1A288_BANK1_SECTORS,
+                         sizeof( TMS470R1A288_BANK1_SECTORS ) );
+        }
+      else
+        {
+          ERROR( "No %s flash bank contains base address 0x%08x.", 
+                 part_name, bank->base );
+          return ERROR_FLASH_OPERATION_FAILED;
+        }
+      break;
+
+    default:
+      WARNING( "Could not identify part 0x%02x as a member of the TMS470 family.", 
+               part_number );
+      return ERROR_FLASH_OPERATION_FAILED;
+    }
+
+  /* turn off memory selects */
+  target_write_u32( target, 0xFFFFFFE4, 0x00000000 );
+  target_write_u32( target, 0xFFFFFFE0, 0x00000000 );
+
+  bank->chip_width = 32;
+  bank->bus_width  = 32;
+  
+  INFO( "Identified %s, ver=%d, core=%s, nvmem=%s.",
+        part_name,
+        silicon_version,
+        (technology_family ? "1.8v" : "3.3v"),
+        (rom_flash ? "rom" : "flash") );
+
+  tms470_info->device_ident_reg  = device_ident_reg;
+  tms470_info->silicon_version   = silicon_version;
+  tms470_info->technology_family = technology_family;
+  tms470_info->rom_flash         = rom_flash;
+  tms470_info->part_number       = part_number;
+  tms470_info->part_name         = part_name;
+
+  /*
+   * Disable reset on address access violation.
+   */
+  target_write_u32( target, 0xFFFFFFE0, 0x00004007 );
+
+  return ERROR_OK;
+}
+
+/* ---------------------------------------------------------------------- */
+
+u32 keysSet = 0;
+u32 flashKeys[4];
+
+int 
+tms470_handle_flash_keyset_command( struct command_context_s * cmd_ctx, 
+                                    char *                     cmd, 
+                                    char **                    args, 
+                                    int                        argc )
+{
+  if (argc > 4)
+    {
+      command_print( cmd_ctx, "tms470 flash_keyset <key0> <key1> <key2> <key3>" );
+      return ERROR_INVALID_ARGUMENTS;
+    }
+  else if (argc == 4)
+    {
+      int i;
+
+      for( i=0; i<4; i++ )
+        {
+          int start = (0 == strncmp( args[i], "0x", 2 )) ? 2 : 0;
+          if (1 != sscanf( &args[i][start], "%x", &flashKeys[i] ))
+            {
+              command_print( cmd_ctx, "could not process flash key %s", args[i] );
+              ERROR( "could not process flash key %s", args[i] );
+              return ERROR_INVALID_ARGUMENTS;
+            }
+        }
+
+      keysSet = 1;
+    }
+  else if (argc != 0)
+    {
+      command_print( cmd_ctx, "tms470 flash_keyset <key0> <key1> <key2> <key3>" );
+      return ERROR_INVALID_ARGUMENTS;
+    }
+
+  if (keysSet)
+    {
+      command_print( cmd_ctx, "using flash keys 0x%08x, 0x%08x, 0x%08x, 0x%08x",
+                     flashKeys[0], flashKeys[1], flashKeys[2], flashKeys[3] );
+    }
+  else
+    {
+      command_print( cmd_ctx, "flash keys not set" );
+    }
+
+  return ERROR_OK;
+}
+
+const u32 FLASH_KEYS_ALL_ONES[] = { 0xFFFFFFFF, 0xFFFFFFFF, 
+                                    0xFFFFFFFF, 0xFFFFFFFF, };
+
+const u32 FLASH_KEYS_ALL_ZEROS[] = { 0x00000000, 0x00000000, 
+                                     0x00000000, 0x00000000, };
+
+const u32 FLASH_KEYS_MIX1[] = { 0xf0fff0ff, 0xf0fff0ff,
+                                0xf0fff0ff, 0xf0fff0ff };
+
+const u32 FLASH_KEYS_MIX2[] = { 0x0000ffff, 0x0000ffff,
+                                0x0000ffff, 0x0000ffff };
+
+/* ---------------------------------------------------------------------- */
+
+int oscMHz = 12;
+
+int
+tms470_handle_osc_megahertz_command( struct command_context_s * cmd_ctx, 
+                                     char *                     cmd, 
+                                     char **                    args, 
+                                     int                        argc )
+{
+  if (argc > 1)
+    {
+      command_print( cmd_ctx, "tms470 osc_megahertz <MHz>" );
+      return ERROR_INVALID_ARGUMENTS;
+    }
+  else if (argc == 1)
+    {
+      sscanf( args[0], "%d", &oscMHz );
+    }
+
+  if (oscMHz <= 0)
+    {
+      ERROR( "osc_megahertz must be positive and non-zero!" );
+      command_print( cmd_ctx, "osc_megahertz must be positive and non-zero!" );
+      oscMHz = 12;
+      return ERROR_INVALID_ARGUMENTS;
+    }
+
+  command_print( cmd_ctx, "osc_megahertz=%d", oscMHz );
+
+  return ERROR_OK;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int plldis = 0;
+
+int
+tms470_handle_plldis_command( struct command_context_s * cmd_ctx, 
+                              char *                     cmd, 
+                              char **                    args, 
+                              int                        argc )
+{
+  if (argc > 1)
+    {
+      command_print( cmd_ctx, "tms470 plldis <0|1>" );
+      return ERROR_INVALID_ARGUMENTS;
+    }
+  else if (argc == 1)
+    {
+      sscanf( args[0], "%d", &plldis );
+      plldis = plldis ? 1 : 0;
+    }
+
+  command_print( cmd_ctx, "plldis=%d", plldis );
+
+  return ERROR_OK;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int
+tms470_check_flash_unlocked( target_t * target )
+{
+  u32 fmbbusy;
+
+  target_read_u32( target, 0xFFE89C08, &fmbbusy );
+  INFO( "tms470 fmbbusy=0x%08x -> %s", 
+         fmbbusy,
+         fmbbusy & 0x8000 ? "unlocked" : "LOCKED" );
+  return fmbbusy & 0x8000 ? ERROR_OK : ERROR_FLASH_OPERATION_FAILED;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int
+tms470_try_flash_keys( target_t *  target, 
+                       const u32 * key_set )
+{
+  u32 glbctrl, fmmstat;
+  int retval = ERROR_FLASH_OPERATION_FAILED;
+
+  /* set GLBCTRL.4  */
+  target_read_u32( target, 0xFFFFFFDC, &glbctrl );
+  target_write_u32( target, 0xFFFFFFDC, glbctrl | 0x10 );
+
+  /* only perform the key match when 3VSTAT is clear */
+  target_read_u32( target, 0xFFE8BC0C, &fmmstat );
+  if (!(fmmstat & 0x08))
+    {
+      unsigned i;
+      u32 fmmac2, fmbptr, fmbac2, fmbbusy, orig_fmregopt;
+      
+      target_write_u32( target, 0xFFE8BC04, fmmstat & ~0x07 );
+
+      /* wait for pump ready */
+      do
+        {
+          target_read_u32( target, 0xFFE8A814, &fmbptr );
+          usleep( 1000 );
+        }
+      while( !(fmbptr & 0x0200) );
+
+      /* force max wait states */
+      target_read_u32( target, 0xFFE88004, &fmbac2 );
+      target_write_u32( target, 0xFFE88004, fmbac2 | 0xff );
+
+      /* save current access mode, force normal read mode */
+      target_read_u32( target, 0xFFE89C00, &orig_fmregopt );
+      target_write_u32( target, 0xFFE89C00, 0x00 );
+
+      for( i=0; i<4; i++ )
+        {
+          u32 tmp;
+
+          /* There is no point displaying the value of tmp, it is
+           * filtered by the chip.  The purpose of this read is to
+           * prime the unlocking logic rather than read out the value.
+           */
+          target_read_u32( target, 0x00001FF0+4*i, &tmp );
+
+          INFO( "tms470 writing fmpkey=0x%08x", key_set[i] );
+          target_write_u32( target, 0xFFE89C0C, key_set[i] );
+        }
+
+      if (ERROR_OK == tms470_check_flash_unlocked( target ))
+        {
+          /* 
+           * There seems to be a side-effect of reading the FMPKEY
+           * register in that it re-enables the protection.  So we
+           * re-enable it.
+           */
+          for( i=0; i<4; i++ )
+            {
+              u32 tmp;
+              target_read_u32( target, 0x00001FF0+4*i, &tmp );
+              target_write_u32( target, 0xFFE89C0C, key_set[i] );
+            }
+          retval = ERROR_OK;
+        }
+
+      /* restore settings */
+      target_write_u32( target, 0xFFE89C00, orig_fmregopt );
+      target_write_u32( target, 0xFFE88004, fmbac2 );
+    }
+
+  /* clear config bit */
+  target_write_u32( target, 0xFFFFFFDC, glbctrl );
+
+  return retval;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int
+tms470_unlock_flash( struct flash_bank_s * bank )
+{
+  tms470_flash_bank_t * tms470_info = bank->driver_priv;
+  target_t *            target =      bank->target;
+  const u32 *           p_key_sets[5];
+  unsigned              i, key_set_count;
+
+  if (keysSet)
+    {
+      p_key_sets[0] = flashKeys;
+      p_key_sets[1] = FLASH_KEYS_ALL_ONES;
+      p_key_sets[2] = FLASH_KEYS_ALL_ZEROS;
+      p_key_sets[3] = FLASH_KEYS_MIX1;
+      p_key_sets[4] = FLASH_KEYS_MIX2;
+    }
+  else
+    {
+      key_set_count = 4;
+      p_key_sets[0] = FLASH_KEYS_ALL_ONES;
+      p_key_sets[1] = FLASH_KEYS_ALL_ZEROS;
+      p_key_sets[2] = FLASH_KEYS_MIX1;
+      p_key_sets[3] = FLASH_KEYS_MIX2;
+    }
+
+  for( i=0; i<key_set_count; i++ )
+    {
+      if (tms470_try_flash_keys( target, p_key_sets[i] ) == ERROR_OK)
+        {
+          INFO( "tms470 flash is unlocked" );
+          return ERROR_OK;
+        }
+    }
+
+  WARNING( "tms470 could not unlock flash memory protection level 2" );
+  return ERROR_FLASH_OPERATION_FAILED;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int
+tms470_flash_initialize_internal_state_machine( struct flash_bank_s * bank )
+{
+  u32 fmmac2, fmmac1, fmmaxep, k, delay, glbctrl, sysclk;
+  target_t *target = bank->target;
+  tms470_flash_bank_t * tms470_info = bank->driver_priv;
+  int result = ERROR_OK;
+
+  /*
+   * Select the desired bank to be programmed by writing BANK[2:0] of
+   * FMMAC2.
+   */
+  target_read_u32( target, 0xFFE8BC04, &fmmac2 );
+  fmmac2 &= ~0x0007;
+  fmmac2 |= (tms470_info->ordinal & 7);
+  target_write_u32( target, 0xFFE8BC04, fmmac2 );
+  DEBUG( "set fmmac2=0x%04x", fmmac2 );
+
+  /*
+   * Disable level 1 sector protection by setting bit 15 of FMMAC1.
+   */
+  target_read_u32( target, 0xFFE8BC00, &fmmac1 );
+  fmmac1 |= 0x8000;
+  target_write_u32( target, 0xFFE8BC00, fmmac1 );
+  DEBUG( "set fmmac1=0x%04x", fmmac1 );
+
+  /*
+   * FMTCREG=0x2fc0;
+   */
+  target_write_u32( target, 0xFFE8BC10, 0x2fc0 );
+  DEBUG( "set fmtcreg=0x2fc0" );
+
+  /*
+   * MAXPP=50
+   */
+  target_write_u32( target, 0xFFE8A07C, 50 );
+  DEBUG( "set fmmaxpp=50" );
+
+  /*
+   * MAXCP=0xf000+2000
+   */
+  target_write_u32( target, 0xFFE8A084, 0xf000+2000 );
+  DEBUG( "set fmmaxcp=0x%04x", 0xf000+2000 );
+
+    /*
+   * configure VHV
+   */
+  target_read_u32( target, 0xFFE8A080, &fmmaxep );
+  if (fmmaxep == 0xf000) 
+    {
+      fmmaxep = 0xf000+4095;
+      target_write_u32( target, 0xFFE8A80C, 0x9964 );
+      DEBUG( "set fmptr3=0x9964" );
+    }
+  else
+    {
+      fmmaxep = 0xa000+4095;
+      target_write_u32( target, 0xFFE8A80C, 0x9b64 );
+      DEBUG( "set fmptr3=0x9b64" );
+    }
+  target_write_u32( target, 0xFFE8A080, fmmaxep );
+  DEBUG( "set fmmaxep=0x%04x", fmmaxep );
+
+  /*
+   * FMPTR4=0xa000
+   */
+  target_write_u32( target, 0xFFE8A810, 0xa000 );
+  DEBUG( "set fmptr4=0xa000" );
+
+  /*
+   * FMPESETUP, delay parameter selected based on clock frequency.
+   *
+   * According to the TI App Note SPNU257 and flashing code, delay is
+   * int((sysclk(MHz) + 1) / 2), with a minimum of 5.  The system
+   * clock is usually derived from the ZPLL module, and selected by
+   * the plldis global.
+   */
+  target_read_u32( target, 0xFFFFFFDC, &glbctrl );
+  sysclk = (plldis ? 1 : (glbctrl & 0x08) ? 4 : 8 ) * oscMHz / (1 + (glbctrl & 7));
+  delay = (sysclk > 10) ? (sysclk + 1) / 2 : 5;
+  target_write_u32( target, 0xFFE8A018, (delay<<4)|(delay<<8) );
+  DEBUG( "set fmpsetup=0x%04x", (delay<<4)|(delay<<8) );
+
+  /*
+   * FMPVEVACCESS, based on delay.
+   */
+  k = delay|(delay<<8);
+  target_write_u32( target, 0xFFE8A05C, k );
+  DEBUG( "set fmpvevaccess=0x%04x", k );
+  
+  /*
+   * FMPCHOLD, FMPVEVHOLD, FMPVEVSETUP, based on delay.
+   */
+  k <<= 1;
+  target_write_u32( target, 0xFFE8A034, k );
+  DEBUG( "set fmpchold=0x%04x", k );
+  target_write_u32( target, 0xFFE8A040, k );
+  DEBUG( "set fmpvevhold=0x%04x", k );
+  target_write_u32( target, 0xFFE8A024, k );
+  DEBUG( "set fmpvevsetup=0x%04x", k );
+
+  /*
+   * FMCVACCESS, based on delay.
+   */
+  k = delay*16;
+  target_write_u32( target, 0xFFE8A060, k );
+  DEBUG( "set fmcvaccess=0x%04x", k );
+
+  /*
+   * FMCSETUP, based on delay.
+   */
+  k = 0x3000 | delay*20;
+  target_write_u32( target, 0xFFE8A020, k );
+  DEBUG( "set fmcsetup=0x%04x", k );
+
+  /*
+   * FMEHOLD, based on delay.
+   */
+  k = (delay*20) << 2;
+  target_write_u32( target, 0xFFE8A038, k );
+  DEBUG( "set fmehold=0x%04x", k );
+
+  /*
+   * PWIDTH, CWIDTH, EWIDTH, based on delay.
+   */
+  target_write_u32( target, 0xFFE8A050, delay*8 );
+  DEBUG( "set fmpwidth=0x%04x", delay*8 );
+  target_write_u32( target, 0xFFE8A058, delay*1000 );
+  DEBUG( "set fmcwidth=0x%04x", delay*1000 );
+  target_write_u32( target, 0xFFE8A054, delay*5400 );
+  DEBUG( "set fmewidth=0x%04x", delay*5400 );
+
+  return result;
+}
+                                                
+
+/* ---------------------------------------------------------------------- */
+
+int
+tms470_flash_status( struct flash_bank_s * bank )
+{
+  target_t *target = bank->target;
+  int result = ERROR_OK;
+  u32 fmmstat;
+
+  target_read_u32( target, 0xFFE8BC0C, &fmmstat );
+  DEBUG( "set fmmstat=0x%04x", fmmstat );
+
+  if (fmmstat & 0x0080)
+    {
+      WARNING( "tms470 flash command: erase still active after busy clear." );
+      result = ERROR_FLASH_OPERATION_FAILED;
+    }
+
+  if (fmmstat & 0x0040)
+    {
+      WARNING( "tms470 flash command: program still active after busy clear." );
+      result = ERROR_FLASH_OPERATION_FAILED;
+    }
+
+  if (fmmstat & 0x0020)
+    {
+      WARNING( "tms470 flash command: invalid data command." );
+      result = ERROR_FLASH_OPERATION_FAILED;
+    }
+
+  if (fmmstat & 0x0010)
+    {
+      WARNING( "tms470 flash command: program, erase or validate sector failed." );
+      result = ERROR_FLASH_OPERATION_FAILED;
+    }
+
+  if (fmmstat & 0x0008)
+    {
+      WARNING( "tms470 flash command: voltage instability detected." );
+      result = ERROR_FLASH_OPERATION_FAILED;
+    }
+
+  if (fmmstat & 0x0006)
+    {
+      WARNING( "tms470 flash command: command suspend detected." );
+      result = ERROR_FLASH_OPERATION_FAILED;
+    }
+
+  if (fmmstat & 0x0001)
+    {
+      WARNING( "tms470 flash command: sector was locked." );
+      result = ERROR_FLASH_OPERATION_FAILED;
+    }
+
+  return result;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int
+tms470_erase_sector( struct flash_bank_s * bank, 
+                     int                   sector )
+{
+  u32 glbctrl, orig_fmregopt, fmbsea, fmbseb, fmmstat;
+  target_t *target = bank->target;
+  u32 flashAddr = bank->base + bank->sectors[sector].offset;
+  int result = ERROR_OK;
+
+  /* 
+   * Set the bit GLBCTRL4 of the GLBCTRL register (in the System
+   * module) to enable writing to the flash registers }.
+   */
+  target_read_u32( target, 0xFFFFFFDC, &glbctrl );
+  target_write_u32( target, 0xFFFFFFDC, glbctrl | 0x10 );
+  DEBUG( "set glbctrl=0x%08x", glbctrl | 0x10 );
+
+  /* Force normal read mode. */
+  target_read_u32( target, 0xFFE89C00, &orig_fmregopt );
+  target_write_u32( target, 0xFFE89C00, 0 );
+  DEBUG( "set fmregopt=0x%08x", 0 );
+
+  (void) tms470_flash_initialize_internal_state_machine( bank );
+  
+  /*
+   * Select one or more bits in FMBSEA or FMBSEB to disable Level 1
+   * protection for the particular sector to be erased/written.
+   */
+  if (sector < 16)
+    {
+      target_read_u32( target, 0xFFE88008, &fmbsea );
+      target_write_u32( target, 0xFFE88008, fmbsea | (1<<sector) );
+      DEBUG( "set fmbsea=0x%04x", fmbsea | (1<<sector) );
+    }
+  else
+    {
+      target_read_u32( target, 0xFFE8800C, &fmbseb );
+      target_write_u32( target, 0xFFE8800C, fmbseb | (1<<(sector-16)) );
+      DEBUG( "set fmbseb=0x%04x", fmbseb | (1<<(sector-16)) );
+    }
+  bank->sectors[sector].is_protected = 0;
+
+  /* 
+   * clear status regiser, sent erase command, kickoff erase 
+   */
+  target_write_u16( target, flashAddr, 0x0040 );
+  DEBUG( "write *(u16 *)0x%08x=0x0040", flashAddr );
+  target_write_u16( target, flashAddr, 0x0020 );
+  DEBUG( "write *(u16 *)0x%08x=0x0020", flashAddr );
+  target_write_u16( target, flashAddr, 0xffff );
+  DEBUG( "write *(u16 *)0x%08x=0xffff", flashAddr );
+
+  /*
+   * Monitor FMMSTAT, busy until clear, then check and other flags for
+   * ultimate result of the operation.
+   */
+  do
+    {
+      target_read_u32( target, 0xFFE8BC0C, &fmmstat );
+      if (fmmstat & 0x0100)
+        {
+          usleep( 1000 );
+        }
+    }
+  while( fmmstat & 0x0100 );
+
+  result = tms470_flash_status( bank );
+
+  if (sector < 16)
+    {
+      target_write_u32( target, 0xFFE88008, fmbsea );
+      DEBUG( "set fmbsea=0x%04x", fmbsea );
+      bank->sectors[sector].is_protected = 
+        fmbsea & (1<<sector) ? 0 : 1;
+    }
+  else
+    {
+      target_write_u32( target, 0xFFE8800C, fmbseb );
+      DEBUG( "set fmbseb=0x%04x", fmbseb );
+      bank->sectors[sector].is_protected = 
+        fmbseb & (1<<(sector-16)) ? 0 : 1;
+    }
+  target_write_u32( target, 0xFFE89C00, orig_fmregopt );
+  DEBUG( "set fmregopt=0x%08x", orig_fmregopt );
+  target_write_u32( target, 0xFFFFFFDC, glbctrl );
+  DEBUG( "set glbctrl=0x%08x", glbctrl );
+
+  if (result == ERROR_OK)
+    {
+      bank->sectors[sector].is_erased = 1;
+    }
+
+  return result;
+}
+
+/* ---------------------------------------------------------------------- 
+              Implementation of Flash Driver Interfaces
+   ---------------------------------------------------------------------- */
+
+int 
+tms470_register_commands( struct command_context_s *cmd_ctx )
+{
+  command_t *tms470_cmd = register_command( cmd_ctx, 
+                                            NULL, 
+                                            "tms470", 
+                                            NULL, 
+                                            COMMAND_ANY, 
+                                            "applies to TI tms470 family" );
+
+  register_command( cmd_ctx, 
+                    tms470_cmd, 
+                    "flash_keyset", 
+                    tms470_handle_flash_keyset_command, 
+                    COMMAND_ANY,
+                   "tms470 flash_keyset <key0> <key1> <key2> <key3>" );
+
+  register_command( cmd_ctx,
+                    tms470_cmd,
+                    "osc_megahertz",
+                    tms470_handle_osc_megahertz_command,
+                    COMMAND_ANY,
+                    "tms470 osc_megahertz <MHz>" );
+
+  register_command( cmd_ctx,
+                    tms470_cmd,
+                    "plldis",
+                    tms470_handle_plldis_command,
+                    COMMAND_ANY,
+                    "tms470 plldis <0/1>" );
+  
+  return ERROR_OK;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int 
+tms470_erase( struct flash_bank_s * bank, 
+              int                   first, 
+              int                   last )
+{
+  tms470_flash_bank_t *tms470_info = bank->driver_priv;
+  target_t *target = bank->target;
+  int sector, result = ERROR_OK;
+
+  if (!tms470_info->device_ident_reg)
+    {
+      tms470_read_part_info( bank );
+    }
+
+  if ((first < 0) || 
+      (first >= bank->num_sectors) ||
+      (last < 0) ||
+      (last >= bank->num_sectors) ||
+      (first > last))
+    {
+      ERROR( "Sector range %d to %d invalid.", first, last );
+      return ERROR_FLASH_SECTOR_INVALID;
+    }
+
+  result = tms470_unlock_flash( bank );
+  if (result != ERROR_OK)
+    {
+      return result;
+    }
+
+  for( sector=first; sector<=last; sector++ )
+    {
+      INFO( "Erasing tms470 bank %d sector %d...",
+            tms470_info->ordinal, sector );
+
+      result = tms470_erase_sector( bank, sector );
+
+      if (result != ERROR_OK)
+        {
+          ERROR( "tms470 could not erase flash sector." );
+          break;
+        }
+      else
+        {
+          INFO( "sector erased successfully." );
+        }
+    }
+  
+  return result;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int 
+tms470_protect( struct flash_bank_s * bank, 
+                int                   set, 
+                int                   first, 
+                int                   last )
+{
+  tms470_flash_bank_t *tms470_info = bank->driver_priv;
+  target_t *target = bank->target;
+  u32 fmmac2, fmbsea, fmbseb;
+  int sector;
+
+  if (!tms470_info->device_ident_reg)
+    {
+      tms470_read_part_info( bank );
+    }
+
+  if ((first < 0) || 
+      (first >= bank->num_sectors) ||
+      (last < 0) ||
+      (last >= bank->num_sectors) ||
+      (first > last))
+    {
+      ERROR( "Sector range %d to %d invalid.", first, last );
+      return ERROR_FLASH_SECTOR_INVALID;
+    }
+
+  /* enable the appropriate bank */
+  target_read_u32( target, 0xFFE8BC04, &fmmac2 );
+  target_write_u32( target, 0xFFE8BC04, 
+                    (fmmac2 & ~7) | tms470_info->ordinal );
+
+  /* get the original sector proection flags for this bank */
+  target_read_u32( target, 0xFFE88008, &fmbsea );
+  target_read_u32( target, 0xFFE8800C, &fmbseb );
+  
+  for( sector=0; sector<bank->num_sectors; sector++ )
+    {
+      if (sector < 16)
+        {
+          fmbsea = set ? fmbsea & ~(1<<sector) : 
+                         fmbsea | (1<<sector);
+          bank->sectors[sector].is_protected = set ? 1 : 0;
+        }
+      else
+        {
+          fmbseb = set ? fmbseb & ~(1<<(sector-16)) : 
+                         fmbseb | (1<<(sector-16));
+          bank->sectors[sector].is_protected = set ? 1 : 0;
+        }
+    }
+
+  /* update the protection bits */
+  target_write_u32( target, 0xFFE88008, fmbsea );
+  target_write_u32( target, 0xFFE8800C, fmbseb );
+
+  return ERROR_OK;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int 
+tms470_write( struct flash_bank_s * bank, 
+              u8 *                  buffer, 
+              u32                   offset, 
+              u32                   count )
+{
+  target_t *target = bank->target;
+  tms470_flash_bank_t *tms470_info = bank->driver_priv;
+  u32 glbctrl, fmbac2, orig_fmregopt, fmbsea, fmbseb, fmmaxpp, fmmstat;
+  int i, result = ERROR_OK;
+
+  if (!tms470_info->device_ident_reg)
+    {
+      tms470_read_part_info( bank );
+    }
+
+  INFO( "Writing %d bytes starting at 0x%08x",
+        count, bank->base + offset );
+
+  /* set GLBCTRL.4  */
+  target_read_u32( target, 0xFFFFFFDC, &glbctrl );
+  target_write_u32( target, 0xFFFFFFDC, glbctrl | 0x10 );
+
+  (void) tms470_flash_initialize_internal_state_machine( bank );
+
+  /* force max wait states */
+  target_read_u32( target, 0xFFE88004, &fmbac2 );
+  target_write_u32( target, 0xFFE88004, fmbac2 | 0xff );
+
+  /* save current access mode, force normal read mode */
+  target_read_u32( target, 0xFFE89C00, &orig_fmregopt );
+  target_write_u32( target, 0xFFE89C00, 0x00 );
+
+  /*
+   * Disable Level 1 protection for all sectors to be erased/written.
+   */
+  target_read_u32( target, 0xFFE88008, &fmbsea );
+  target_write_u32( target, 0xFFE88008, 0xffff );
+  target_read_u32( target, 0xFFE8800C, &fmbseb );
+  target_write_u32( target, 0xFFE8800C, 0xffff );
+
+  /* read MAXPP */
+  target_read_u32( target, 0xFFE8A07C, &fmmaxpp );
+
+  for( i=0; i<count; i+=2 )
+    {
+      u32 addr = bank->base + offset + i;
+      u16 word = (((u16) buffer[i]) << 8) | (u16) buffer[i+1];
+
+      if (word != 0xffff)
+        {
+          INFO( "writing 0x%04x at 0x%08x", word, addr );
+
+          /* clear status register */
+          target_write_u16( target, addr, 0x0040 );
+          /* program flash command */
+          target_write_u16( target, addr, 0x0010 );
+          /* burn the 16-bit word (big-endian) */
+          target_write_u16( target, addr, word );
+
+          /*
+           * Monitor FMMSTAT, busy until clear, then check and other flags
+           * for ultimate result of the operation.
+           */
+          do
+            {
+              target_read_u32( target, 0xFFE8BC0C, &fmmstat );
+              if (fmmstat & 0x0100)
+                {
+                  usleep( 1000 );
+                }
+            }
+          while( fmmstat & 0x0100 );
+
+          if (fmmstat & 0x3ff)
+            {
+              ERROR( "fmstat=0x%04x", fmmstat );
+              ERROR( "Could not program word 0x%04x at address 0x%08x.",
+                     word, addr );
+              result = ERROR_FLASH_OPERATION_FAILED;
+              break;
+            }
+        }
+      else
+        {
+          INFO( "skipping 0xffff at 0x%08x", addr );
+        }
+    }
+
+  /* restore */
+  target_write_u32( target, 0xFFE88008, fmbsea );
+  target_write_u32( target, 0xFFE8800C, fmbseb );
+  target_write_u32( target, 0xFFE88004, fmbac2 );
+  target_write_u32( target, 0xFFE89C00, orig_fmregopt );
+  target_write_u32( target, 0xFFFFFFDC, glbctrl );
+
+  return result;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int 
+tms470_probe( struct flash_bank_s * bank )
+{
+  tms470_flash_bank_t * tms470_info = bank->driver_priv;
+
+  tms470_info->probed = 0;
+  
+  if (!tms470_info->device_ident_reg)
+    {
+      tms470_read_part_info( bank );
+    }
+  
+  tms470_info->probed = 1;
+
+  return ERROR_OK;
+}
+
+int 
+tms470_auto_probe( struct flash_bank_s * bank )
+{
+       tms470_flash_bank_t * tms470_info = bank->driver_priv;
+       if (tms470_info->probed)
+               return ERROR_OK;
+       return tms470_probe(bank);
+}
+/* ---------------------------------------------------------------------- */
+
+int 
+tms470_erase_check( struct flash_bank_s * bank )
+{
+  target_t *target = bank->target;
+  tms470_flash_bank_t * tms470_info = bank->driver_priv;
+  int sector, result = ERROR_OK;
+  u32 fmmac2, fmbac2, glbctrl, orig_fmregopt;
+  static u8 buffer[64*1024];
+
+  if (!tms470_info->device_ident_reg)
+    {
+      tms470_read_part_info( bank );
+    }
+
+  /* set GLBCTRL.4  */
+  target_read_u32( target, 0xFFFFFFDC, &glbctrl );
+  target_write_u32( target, 0xFFFFFFDC, glbctrl | 0x10 );
+
+  /* save current access mode, force normal read mode */
+  target_read_u32( target, 0xFFE89C00, &orig_fmregopt );
+  target_write_u32( target, 0xFFE89C00, 0x00 );
+
+  /* enable the appropriate bank */
+  target_read_u32( target, 0xFFE8BC04, &fmmac2 );
+  target_write_u32( target, 0xFFE8BC04, 
+                    (fmmac2 & ~7) | tms470_info->ordinal );
+
+  /* TCR=0 */
+  target_write_u32( target, 0xFFE8BC10, 0x2fc0 );
+
+  /* clear TEZ in fmbrdy */
+  target_write_u32( target, 0xFFE88010, 0x0b );
+
+  /* save current wait states, force max */
+  target_read_u32( target, 0xFFE88004, &fmbac2 );
+  target_write_u32( target, 0xFFE88004, fmbac2 | 0xff );
+
+  /* 
+   * The TI primitives inspect the flash memory by reading one 32-bit
+   * word at a time.  Here we read an entire sector and inspect it in
+   * an attempt to reduce the JTAG overhead.
+   */
+  for( sector=0; sector<bank->num_sectors; sector++ )
+    {
+      if (bank->sectors[sector].is_erased != 1)
+        {
+          u32 i, addr = bank->base + bank->sectors[sector].offset;
+          
+          INFO( "checking flash bank %d sector %d",
+                tms470_info->ordinal,
+                sector );
+
+          target_read_buffer( target, 
+                              addr,
+                              bank->sectors[sector].size,
+                              buffer );
+
+          bank->sectors[sector].is_erased = 1;
+          for( i=0; i<bank->sectors[sector].size; i++ )
+            {
+              if (buffer[i] != 0xff)
+                {
+                  WARNING( "tms470 bank %d, sector %d, not erased.",
+                           tms470_info->ordinal,
+                           sector );
+                  WARNING( "at location 0x%08x: flash data is 0x%02x.",
+                           addr+i, 
+                           buffer[i] );
+                           
+                  bank->sectors[sector].is_erased = 0;
+                  break;
+                }
+            }
+        }
+      if (bank->sectors[sector].is_erased != 1)
+        {
+          result = ERROR_FLASH_SECTOR_NOT_ERASED;
+          break;
+        }
+      else
+        {
+          INFO( "sector erased" );
+        }
+    }
+
+  /* reset TEZ, wait states, read mode, GLBCTRL.4 */
+  target_write_u32( target, 0xFFE88010, 0x0f );
+  target_write_u32( target, 0xFFE88004, fmbac2 );
+  target_write_u32( target, 0xFFE89C00, orig_fmregopt );
+  target_write_u32( target, 0xFFFFFFDC, glbctrl );
+
+  return result;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int 
+tms470_protect_check( struct flash_bank_s * bank )
+{
+  target_t *target = bank->target;
+  tms470_flash_bank_t * tms470_info = bank->driver_priv;
+  int sector, result = ERROR_OK;
+  u32 fmmac2, fmbsea, fmbseb;
+
+  if (!tms470_info->device_ident_reg)
+    {
+      tms470_read_part_info( bank );
+    }
+
+  /* enable the appropriate bank */
+  target_read_u32( target, 0xFFE8BC04, &fmmac2 );
+  target_write_u32( target, 0xFFE8BC04, 
+                    (fmmac2 & ~7) | tms470_info->ordinal );
+
+  target_read_u32( target, 0xFFE88008, &fmbsea );
+  target_read_u32( target, 0xFFE8800C, &fmbseb );
+  
+  for( sector=0; sector<bank->num_sectors; sector++ )
+    {
+      int protected;
+
+      if (sector < 16)
+        {
+          protected = fmbsea & (1<<sector) ? 0 : 1;
+          bank->sectors[sector].is_protected = protected;
+        }
+      else
+        {
+          protected = fmbseb & (1<<(sector-16)) ? 0 : 1;
+          bank->sectors[sector].is_protected = protected;
+        }
+
+      DEBUG( "bank %d sector %d is %s",
+             tms470_info->ordinal,
+             sector,
+             protected ? "protected" : "not protected" );
+    }
+
+  return result;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int 
+tms470_info( struct flash_bank_s * bank, 
+             char *                buf, 
+             int                   buf_size )
+{
+  int used = 0;
+  tms470_flash_bank_t * tms470_info = bank->driver_priv;
+
+  if (!tms470_info->device_ident_reg)
+    {
+      tms470_read_part_info( bank );
+    }
+
+  if (!tms470_info->device_ident_reg)
+    {
+      (void) snprintf(buf, buf_size, "Cannot identify target as a TMS470\n");
+      return ERROR_FLASH_OPERATION_FAILED;
+    }
+
+  used += snprintf( buf, buf_size, 
+                    "\ntms470 information: Chip is %s\n",
+                    tms470_info->part_name );
+  buf += used;
+  buf_size -= used;
+
+  used += snprintf( buf, buf_size,
+                    "Flash protection level 2 is %s\n",
+                    tms470_check_flash_unlocked( bank->target ) == ERROR_OK ? "disabled" : "enabled" );
+  buf += used;
+  buf_size -= used;
+
+  return ERROR_OK;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * flash bank tms470 <base> <size> <chip_width> <bus_width> <target>
+ * [options...]
+ */
+
+int 
+tms470_flash_bank_command( struct command_context_s *cmd_ctx, 
+                           char *cmd, 
+                           char **args, 
+                           int argc, 
+                           struct flash_bank_s *bank )
+{
+  bank->driver_priv = malloc( sizeof( tms470_flash_bank_t ) );
+
+  if (!bank->driver_priv)
+    {
+      return ERROR_FLASH_OPERATION_FAILED;
+    }
+
+  (void) memset( bank->driver_priv, 0, sizeof( tms470_flash_bank_t ) );
+
+  return ERROR_OK;
+}
index ee4afb2ab718cc47b9d7395afb0d9059ea523572..c17a60fa450f41c645767691a585b1ab568c5801 100644 (file)
@@ -1,39 +1,41 @@
-/***************************************************************************\r
- *   (c) Copyright 2007, 2008 by Christopher Kilgour                       *\r
- *   techie |_at_| whiterocker |_dot_| com                                 *\r
- *                                                                         *\r
- *   This program is free software; you can redistribute it and/or modify  *\r
- *   it under the terms of the GNU General Public License as published by  *\r
- *   the Free Software Foundation; either version 2 of the License, or     *\r
- *   (at your option) any later version.                                   *\r
- *                                                                         *\r
- *   This program is distributed in the hope that it will be useful,       *\r
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\r
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\r
- *   GNU General Public License for more details.                          *\r
- *                                                                         *\r
- *   You should have received a copy of the GNU General Public License     *\r
- *   along with this program; if not, write to the                         *\r
- *   Free Software Foundation, Inc.,                                       *\r
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *\r
- ***************************************************************************/\r
-\r
-#ifndef TMS470_DOT_H\r
-#define TMS470_DOT_H\r
-\r
-#include "flash.h"\r
-\r
-typedef struct tms470_flash_bank_s\r
-{\r
-  unsigned ordinal;\r
-\r
-  /* device identification register */\r
-  u32 device_ident_reg;\r
-  u32 silicon_version;\r
-  u32 technology_family;\r
-  u32 rom_flash;\r
-  u32 part_number;\r
-  char * part_name;\r
-} tms470_flash_bank_t;\r
-\r
-#endif /* TMS470_DOT_H */\r
+/***************************************************************************
+ *   (c) Copyright 2007, 2008 by Christopher Kilgour                       *
+ *   techie |_at_| whiterocker |_dot_| com                                 *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef TMS470_DOT_H
+#define TMS470_DOT_H
+
+#include "flash.h"
+
+typedef struct tms470_flash_bank_s
+{
+  unsigned ordinal;
+
+  /* device identification register */
+  u32 device_ident_reg;
+  u32 silicon_version;
+  u32 technology_family;
+  u32 rom_flash;
+  u32 part_number;
+  char * part_name;
+  
+  int probed;
+} tms470_flash_bank_t;
+
+#endif /* TMS470_DOT_H */
index d094a0c96f4f0078485b9b5d2d4677b46e33c79b..d48101f4591a6b39d3111a39188ed8d03f4262d6 100644 (file)
@@ -1364,6 +1364,22 @@ static int decode_xfer_read (char *buf, char **annex, int *ofs, unsigned int *le
        return 0;
 }
 
+int gdb_calc_blocksize(flash_bank_t *bank)
+{
+       int i;
+       int block_size = 0xffffffff;
+       
+       /* loop through all sectors and return smallest sector size */
+       
+       for (i = 0; i < bank->num_sectors; i++)
+       {
+               if (bank->sectors[i].size < block_size)
+                       block_size = bank->sectors[i].size;
+       }
+       
+       return block_size;
+}
+
 int gdb_query_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
 {
        command_context_t *cmd_ctx = connection->cmd_ctx;
@@ -1470,6 +1486,7 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
                int offset;
                int length;
                char *separator;
+               int blocksize;
                
                /* skip command character */
                packet += 23;
@@ -1486,10 +1503,14 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
                        if (p == NULL)
                                break;
                        
+                       /* if device has uneven sector sizes, eg. str7, lpc
+                        * we pass the smallest sector size to gdb memory map */
+                       blocksize = gdb_calc_blocksize(p);
+                       
                        xml_printf(&retval, &xml, &pos, &size, "<memory type=\"flash\" start=\"0x%x\" length=\"0x%x\">\n" \
                                "<property name=\"blocksize\">0x%x</property>\n" \
                                "</memory>\n", \
-                               p->base, p->size, p->size/p->num_sectors);
+                               p->base, p->size, blocksize);
                        i++;
                }
                

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)