- add missing files from previous commit (tms470 flash driver)
authorntfreak <ntfreak@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Thu, 17 Jan 2008 08:02:02 +0000 (08:02 +0000)
committerntfreak <ntfreak@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Thu, 17 Jan 2008 08:02:02 +0000 (08:02 +0000)
git-svn-id: svn://svn.berlios.de/openocd/trunk@258 b42882b7-edfa-0310-969c-e2dbd0fdcd60

doc/scripts/tms470r1a288_startup.script [new file with mode: 0644]
src/flash/at91sam7.c
src/flash/at91sam7.h
src/flash/flash.c
src/flash/tms470.c [new file with mode: 0644]
src/flash/tms470.h [new file with mode: 0644]

diff --git a/doc/scripts/tms470r1a288_startup.script b/doc/scripts/tms470r1a288_startup.script
new file mode 100644 (file)
index 0000000..9e97895
--- /dev/null
@@ -0,0 +1,9 @@
+# Resets and unlocks the MSM of TMS470R1A288 (an others with an MSM).\r
+# Assumes default MSM keys (all 0xFFFFFFFF).\r
+#\r
+resume\r
+jtag_reset 0 1\r
+halt\r
+jtag_reset 0 0\r
+poll                   # hack-ish, but effective version of 'reset halt'\r
+mdw 0x1fe0 4           # unlock MSM\r
index 907302eb2b75f15de3b56ffbe219b326f592e4ca..cf3547942d39638ac95dd4162327c762b2c67b5c 100644 (file)
@@ -1,21 +1,21 @@
 /***************************************************************************
- *   Copyright (C) 2006 by Magnus Lundin                                       *
- *   lundin@mlu.mine.nu                                                                                *
- *                                                                                                                     *
- *   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.                           *
- *                                                                                *
+ *   Copyright (C) 2006 by Magnus Lundin                                   *
+ *   lundin@mlu.mine.nu                                                    *
+ *                                                                         *
+ *   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.       *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
 /***************************************************************************
index 19d5e4cc2dd8d7a58236db3db8f6f7d496681160..20e0737d382f233fd8b18c893ed7236001fc6a1e 100644 (file)
@@ -1,6 +1,6 @@
 /***************************************************************************
  *   Copyright (C) 2006 by Magnus Lundin                                   *
- *   lundinªmlu.mine.nu                                                    *
+ *   lundin@mlu.mine.nu                                                   *
  *                                                                         *
  *   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  *
index 925a11258f2d6ea41543efbabac769e2fc321ecd..2e7cc4537e2f7e41421bbe6b8536d71d22ef5217 100644 (file)
@@ -75,7 +75,7 @@ flash_driver_t *flash_drivers[] =
        &stellaris_flash,
        &str9xpec_flash,
        &stm32x_flash,
-        &tms470_flash,
+       &tms470_flash,
        NULL,
 };
 
diff --git a/src/flash/tms470.c b/src/flash/tms470.c
new file mode 100644 (file)
index 0000000..0a97f56
--- /dev/null
@@ -0,0 +1,1292 @@
+/***************************************************************************\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
diff --git a/src/flash/tms470.h b/src/flash/tms470.h
new file mode 100644 (file)
index 0000000..ee4afb2
--- /dev/null
@@ -0,0 +1,39 @@
+/***************************************************************************\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

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)