Nicolas Pitre nico at cam.org The ECC data is automatically computed and written...
[fw/openocd] / src / flash / str9x.c
index c07bc757f1814a131c00c66cad2cf36511c67593..1160c7090a91ca36f2240cfdd0e97c21fca653d6 100644 (file)
@@ -2,6 +2,12 @@
  *   Copyright (C) 2005 by Dominic Rath                                    *
  *   Dominic.Rath@gmx.de                                                   *
  *                                                                         *
+ *   Copyright (C) 2008 by Spencer Oliver                                  *
+ *   spen@spen-soft.co.uk                                                  *
+ *
+ *   Copyright (C) 2008 by Oyvind Harboe                                   *
+ *   oyvind.harboe@zylin.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     *
@@ -28,6 +34,7 @@
 #include "target.h"
 #include "log.h"
 #include "armv4_5.h"
+#include "arm966e.h"
 #include "algorithm.h"
 #include "binarybuffer.h"
 
 #include <string.h>
 #include <unistd.h>
 
-str9x_mem_layout_t mem_layout_str9[] = {
-       {0x00000000, 0x10000, 0x01},
-       {0x00010000, 0x10000, 0x02},
-       {0x00020000, 0x10000, 0x04},
-       {0x00030000, 0x10000, 0x08},
-       {0x00040000, 0x10000, 0x10},
-       {0x00050000, 0x10000, 0x20},
-       {0x00060000, 0x10000, 0x40},
-       {0x00070000, 0x10000, 0x80},
-       {0x00080000, 0x02000, 0x100},
-       {0x00082000, 0x02000, 0x200},
-       {0x00084000, 0x02000, 0x400},
-       {0x00086000, 0x02000, 0x800}
-};
+static u32 bank1start = 0x00080000;
 
 int str9x_register_commands(struct command_context_s *cmd_ctx);
 int str9x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
@@ -58,7 +52,6 @@ int str9x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
 int str9x_probe(struct flash_bank_s *bank);
 int str9x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 int str9x_protect_check(struct flash_bank_s *bank);
-int str9x_erase_check(struct flash_bank_s *bank);
 int str9x_info(struct flash_bank_s *bank, char *buf, int buf_size);
 
 int str9x_handle_flash_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
@@ -72,7 +65,8 @@ flash_driver_t str9x_flash =
        .protect = str9x_protect,
        .write = str9x_write,
        .probe = str9x_probe,
-       .erase_check = str9x_erase_check,
+       .auto_probe = str9x_probe,
+       .erase_check = default_flash_blank_check,
        .protect_check = str9x_protect_check,
        .info = str9x_info
 };
@@ -92,22 +86,49 @@ int str9x_build_block_list(struct flash_bank_s *bank)
        str9x_flash_bank_t *str9x_info = bank->driver_priv;
        
        int i;
-       int num_sectors = 0, b0_sectors = 0;
-               
+       int num_sectors;
+       int b0_sectors = 0, b1_sectors = 0;
+       u32 offset = 0;
+       
+       /* set if we have large flash str9 */
+       str9x_info->variant = 0;
+       str9x_info->bank1 = 0;
+       
        switch (bank->size)
        {
-               case 256 * 1024:
+               case (256 * 1024):
                        b0_sectors = 4;
                        break;
-               case 512 * 1024:
+               case (512 * 1024):
                        b0_sectors = 8;
                        break;
+               case (1024 * 1024):
+                       bank1start = 0x00100000;
+                       str9x_info->variant = 1;
+                       b0_sectors = 16;
+                       break;
+               case (2048 * 1024):
+                       bank1start = 0x00200000;
+                       str9x_info->variant = 1;
+                       b0_sectors = 32;
+                       break;
+               case (128 * 1024):
+                       str9x_info->variant = 1;
+                       str9x_info->bank1 = 1;
+                       b1_sectors = 8;
+                       bank1start = bank->base;
+                       break;
+               case (32 * 1024):
+                       str9x_info->bank1 = 1;
+                       b1_sectors = 4;
+                       bank1start = bank->base;
+                       break;
                default:
-                       ERROR("BUG: unknown bank->size encountered");
+                       LOG_ERROR("BUG: unknown bank->size encountered");
                        exit(-1);
        }
-       
-       num_sectors = b0_sectors + 4;
+               
+       num_sectors = b0_sectors + b1_sectors;
        
        bank->num_sectors = num_sectors;
        bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);
@@ -117,20 +138,25 @@ int str9x_build_block_list(struct flash_bank_s *bank)
        
        for (i = 0; i < b0_sectors; i++)
        {
-               bank->sectors[num_sectors].offset = mem_layout_str9[i].sector_start;
-               bank->sectors[num_sectors].size = mem_layout_str9[i].sector_size;
+               bank->sectors[num_sectors].offset = offset;
+               bank->sectors[num_sectors].size = 0x10000;
+               offset += bank->sectors[i].size;
                bank->sectors[num_sectors].is_erased = -1;
                bank->sectors[num_sectors].is_protected = 1;
-               str9x_info->sector_bits[num_sectors++] = mem_layout_str9[i].sector_bit;
+               str9x_info->sector_bits[num_sectors++] = (1<<i);
        }
-       
-       for (i = 8; i < 12; i++)
+
+       for (i = 0; i < b1_sectors; i++)
        {
-               bank->sectors[num_sectors].offset = mem_layout_str9[i].sector_start;
-               bank->sectors[num_sectors].size = mem_layout_str9[i].sector_size;
+               bank->sectors[num_sectors].offset = offset;
+               bank->sectors[num_sectors].size = str9x_info->variant == 0 ? 0x2000 : 0x4000;
+               offset += bank->sectors[i].size;
                bank->sectors[num_sectors].is_erased = -1;
                bank->sectors[num_sectors].is_protected = 1;
-               str9x_info->sector_bits[num_sectors++] = mem_layout_str9[i].sector_bit;
+               if (str9x_info->variant)
+                       str9x_info->sector_bits[num_sectors++] = (1<<i);
+               else
+                       str9x_info->sector_bits[num_sectors++] = (1<<(i+8));
        }
        
        return ERROR_OK;
@@ -144,26 +170,13 @@ int str9x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char
        
        if (argc < 6)
        {
-               WARNING("incomplete flash_bank str9x configuration");
+               LOG_WARNING("incomplete flash_bank str9x configuration");
                return ERROR_FLASH_BANK_INVALID;
        }
        
        str9x_info = malloc(sizeof(str9x_flash_bank_t));
        bank->driver_priv = str9x_info;
        
-       if (bank->base != 0x00000000)
-       {
-               WARNING("overriding flash base address for STR91x device with 0x00000000");
-               bank->base = 0x00000000;
-       }
-       
-       str9x_info->target = get_target_by_num(strtoul(args[5], NULL, 0));
-       if (!str9x_info->target)
-       {
-               ERROR("no target '%s' configured", args[5]);
-               exit(-1);
-       }
-
        str9x_build_block_list(bank);
        
        str9x_info->write_algorithm = NULL;
@@ -171,66 +184,69 @@ int str9x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char
        return ERROR_OK;
 }
 
-int str9x_blank_check(struct flash_bank_s *bank, int first, int last)
+int str9x_protect_check(struct flash_bank_s *bank)
 {
+       int retval;
        str9x_flash_bank_t *str9x_info = bank->driver_priv;
-       target_t *target = str9x_info->target;
-       u8 *buffer;
-       int i;
-       int nBytes;
+       target_t *target = bank->target;
        
-       if ((first < 0) || (last > bank->num_sectors))
-               return ERROR_FLASH_SECTOR_INVALID;
+       int i;
+       u32 adr;
+       u32 status = 0;
 
-       if (str9x_info->target->state != TARGET_HALTED)
+       if (bank->target->state != TARGET_HALTED)
        {
+               LOG_ERROR("Target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
+
+       /* read level one protection */
        
-       buffer = malloc(256);
-       
-       for (i = first; i <= last; i++)
+       if (str9x_info->variant)
        {
-               bank->sectors[i].is_erased = 1;
-
-               target->type->read_memory(target, bank->base + bank->sectors[i].offset, 4, 256/4, buffer);
-               
-               for (nBytes = 0; nBytes < 256; nBytes++)
+               if (str9x_info->bank1)
                {
-                       if (buffer[nBytes] != 0xFF)
+                       adr = bank1start + 0x18;
+                       if ((retval=target_write_u16(target, adr, 0x90))!=ERROR_OK)
                        {
-                               bank->sectors[i].is_erased = 0;
-                               break;
+                               return retval;
                        }
-               }       
+                       if ((retval=target_read_u16(target, adr, (u16*)&status))!=ERROR_OK)
+                       {
+                               return retval;
+                       }
+               }
+               else
+               {
+                       adr = bank1start + 0x14;
+                       if ((retval=target_write_u16(target, adr, 0x90))!=ERROR_OK)
+                       {
+                               return retval;
+                       }
+                       if ((retval=target_read_u32(target, adr, &status))!=ERROR_OK)
+                       {
+                               return retval;
+                       }
+               }
        }
-       
-       free(buffer);
-
-       return ERROR_OK;
-}
-
-int str9x_protect_check(struct flash_bank_s *bank)
-{
-       str9x_flash_bank_t *str9x_info = bank->driver_priv;
-       target_t *target = str9x_info->target;
-       
-       int i;
-       u32 adr;
-       u16 status;
-
-       if (str9x_info->target->state != TARGET_HALTED)
+       else
        {
-               return ERROR_TARGET_NOT_HALTED;
+               adr = bank1start + 0x10;
+               if ((retval=target_write_u16(target, adr, 0x90))!=ERROR_OK)
+               {
+                       return retval;
+               }
+               if ((retval=target_read_u16(target, adr, (u16*)&status))!=ERROR_OK)
+               {
+                       return retval;
+               }
        }
-
-       /* read level one protection */
-       
-       adr = mem_layout_str9[10].sector_start + 4;
        
-       target_write_u32(target, adr, 0x90);
-       target_read_u16(target, adr, &status);
-       target_write_u32(target, adr, 0xFF);
+       /* read array command */
+       if ((retval=target_write_u16(target, adr, 0xFF))!=ERROR_OK)
+       {
+               return retval;
+       }
        
        for (i = 0; i < bank->num_sectors; i++)
        {
@@ -245,46 +261,88 @@ int str9x_protect_check(struct flash_bank_s *bank)
 
 int str9x_erase(struct flash_bank_s *bank, int first, int last)
 {
-       str9x_flash_bank_t *str9x_info = bank->driver_priv;
-       target_t *target = str9x_info->target;
+       target_t *target = bank->target;
        int i;
        u32 adr;
        u8 status;
+       u8 erase_cmd;
        
-       if (str9x_info->target->state != TARGET_HALTED)
+       if (bank->target->state != TARGET_HALTED)
        {
+               LOG_ERROR("Target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
-    
+
+       /* Check if we erase whole bank */
+       if ((first == 0) && (last == (bank->num_sectors - 1)))
+       {
+               /* Optimize to run erase bank command instead of sector */
+               erase_cmd = 0x80;
+       }
+       else
+       {
+               /* Erase sector command */
+               erase_cmd = 0x20;
+       }
+       
        for (i = first; i <= last; i++)
        {
-               adr = bank->sectors[i].offset;
+               int retval;
+               adr = bank->base + bank->sectors[i].offset;
                
-       /* erase sectors */
-               target_write_u16(target, adr, 0x20);
-               target_write_u16(target, adr, 0xD0);
+               /* erase sectors */
+               if ((retval=target_write_u16(target, adr, erase_cmd))!=ERROR_OK)
+               {
+                       return retval;
+               }
+               if ((retval=target_write_u16(target, adr, 0xD0))!=ERROR_OK)
+               {
+                       return retval;
+               }
                
                /* get status */
-               target_write_u16(target, adr, 0x70);
-               
-               while (1) {
-                       target_read_u8(target, adr, &status);
+               if ((retval=target_write_u16(target, adr, 0x70))!=ERROR_OK)
+               {
+                       return retval;
+               }
+
+               int timeout;            
+               for (timeout=0; timeout<1000; timeout++) {
+                       if ((retval=target_read_u8(target, adr, &status))!=ERROR_OK)
+                       {
+                               return retval;
+                       }
                        if( status & 0x80 )
                                break;
-                       usleep(1000);
+                       alive_sleep(1);
+               }
+               if (timeout==1000)
+               {
+                       LOG_ERROR("erase timed out");
+                       return ERROR_FAIL;
                }
                
                /* clear status, also clear read array */
-               target_write_u16(target, adr, 0x50);
+               if ((retval=target_write_u16(target, adr, 0x50))!=ERROR_OK)
+               {
+                       return retval;
+               }
                
                /* read array command */
-               target_write_u16(target, adr, 0xFF);
+               if ((retval=target_write_u16(target, adr, 0xFF))!=ERROR_OK)
+               {
+                       return retval;
+               }
                
                if( status & 0x22 )
                {
-                       ERROR("error erasing flash bank, status: 0x%x", status);
+                       LOG_ERROR("error erasing flash bank, status: 0x%x", status);
                        return ERROR_FLASH_OPERATION_FAILED;
                }
+               
+               /* If we ran erase bank command, we are finished */
+               if (erase_cmd == 0x80)
+                       break;
        }
        
        for (i = first; i <= last; i++)
@@ -295,14 +353,14 @@ int str9x_erase(struct flash_bank_s *bank, int first, int last)
 
 int str9x_protect(struct flash_bank_s *bank, int set, int first, int last)
 {
-       str9x_flash_bank_t *str9x_info = bank->driver_priv;
-       target_t *target = str9x_info->target;
+       target_t *target = bank->target;
        int i;
        u32 adr;
        u8 status;
        
-       if (str9x_info->target->state != TARGET_HALTED)
+       if (bank->target->state != TARGET_HALTED)
        {
+               LOG_ERROR("Target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
        
@@ -310,7 +368,7 @@ int str9x_protect(struct flash_bank_s *bank, int set, int first, int last)
        {
                /* Level One Protection */
        
-               adr = bank->sectors[i].offset;
+               adr = bank->base + bank->sectors[i].offset;
                
                target_write_u16(target, adr, 0x60);
                if( set )
@@ -320,6 +378,12 @@ int str9x_protect(struct flash_bank_s *bank, int set, int first, int last)
                
                /* query status */
                target_read_u8(target, adr, &status);
+               
+               /* clear status, also clear read array */
+               target_write_u16(target, adr, 0x50);
+               
+               /* read array command */
+               target_write_u16(target, adr, 0xFF);
        }
        
        return ERROR_OK;
@@ -328,13 +392,13 @@ int str9x_protect(struct flash_bank_s *bank, int set, int first, int last)
 int str9x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
 {
        str9x_flash_bank_t *str9x_info = bank->driver_priv;
-       target_t *target = str9x_info->target;
+       target_t *target = bank->target;
        u32 buffer_size = 8192;
        working_area_t *source;
        u32 address = bank->base + offset;
        reg_param_t reg_params[4];
        armv4_5_algorithm_t armv4_5_info;
-       int retval;
+       int retval = ERROR_OK;
        
        u32 str9x_flash_write_code[] = {
                                        /* write:                               */
@@ -361,24 +425,14 @@ int str9x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 cou
                0xeafffffe,     /*      b exit                          */
        };
        
-       u8 str9x_flash_write_code_buf[76];
-       int i;
-       
        /* flash write code */
-       if (!str9x_info->write_algorithm)
+       if (target_alloc_working_area(target, 4 * 19, &str9x_info->write_algorithm) != ERROR_OK)
        {
-               if (target_alloc_working_area(target, 4 * 19, &str9x_info->write_algorithm) != ERROR_OK)
-               {
-                       WARNING("no working area available, can't do block memory writes");
-                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-               };
-
-               /* convert flash writing code into a buffer in target endianness */
-               for (i = 0; i < 19; i++)
-                       target_buffer_set_u32(target, str9x_flash_write_code_buf + i*4, str9x_flash_write_code[i]);
-                       
-               target_write_buffer(target, str9x_info->write_algorithm->address, 19 * 4, str9x_flash_write_code_buf);
-       }
+               LOG_WARNING("no working area available, can't do block memory writes");
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       };
+               
+       target_write_buffer(target, str9x_info->write_algorithm->address, 19 * 4, (u8*)str9x_flash_write_code);
 
        /* memory buffer */
        while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
@@ -390,10 +444,10 @@ int str9x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 cou
                        if (str9x_info->write_algorithm)
                                target_free_working_area(target, str9x_info->write_algorithm);
                        
-                       WARNING("no large enough working area available, can't do block memory writes");
+                       LOG_WARNING("no large enough working area available, can't do block memory writes");
                        return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
                }
-       };
+       }
        
        armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
        armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
@@ -416,13 +470,15 @@ int str9x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 cou
 
                if ((retval = target->type->run_algorithm(target, 0, NULL, 4, reg_params, str9x_info->write_algorithm->address, str9x_info->write_algorithm->address + (18 * 4), 10000, &armv4_5_info)) != ERROR_OK)
                {
-                       ERROR("error executing str9x flash write algorithm");
-                       return ERROR_FLASH_OPERATION_FAILED;
+                       LOG_ERROR("error executing str9x flash write algorithm");
+                       retval = ERROR_FLASH_OPERATION_FAILED;
+                       break;
                }
        
                if (buf_get_u32(reg_params[3].value, 0, 32) != 0x80)
                {
-                       return ERROR_FLASH_OPERATION_FAILED;
+                       retval = ERROR_FLASH_OPERATION_FAILED;
+                       break;
                }
                
                buffer += thisrun_count * 2;
@@ -430,18 +486,20 @@ int str9x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 cou
                count -= thisrun_count;
        }
        
+       target_free_working_area(target, source);
+       target_free_working_area(target, str9x_info->write_algorithm);
+       
        destroy_reg_param(&reg_params[0]);
        destroy_reg_param(&reg_params[1]);
        destroy_reg_param(&reg_params[2]);
        destroy_reg_param(&reg_params[3]);
        
-       return ERROR_OK;
+       return retval;
 }
 
 int str9x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
 {
-       str9x_flash_bank_t *str9x_info = bank->driver_priv;
-       target_t *target = str9x_info->target;
+       target_t *target = bank->target;
        u32 words_remaining = (count / 2);
        u32 bytes_remaining = (count & 0x00000001);
        u32 address = bank->base + offset;
@@ -452,14 +510,15 @@ int str9x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
        u32 bank_adr;
        int i;
        
-       if (str9x_info->target->state != TARGET_HALTED)
+       if (bank->target->state != TARGET_HALTED)
        {
+               LOG_ERROR("Target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
-       
+
        if (offset & 0x1)
        {
-               WARNING("offset 0x%x breaks required 2-byte alignment", offset);
+               LOG_WARNING("offset 0x%x breaks required 2-byte alignment", offset);
                return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
        }
        
@@ -492,11 +551,11 @@ int str9x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
                        {
                                /* if block write failed (no sufficient working area),
                                 * we use normal (slow) single dword accesses */ 
-                               WARNING("couldn't use block writes, falling back to single memory accesses");
+                               LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
                        }
                        else if (retval == ERROR_FLASH_OPERATION_FAILED)
                        {
-                               ERROR("flash writing failed with error code: 0x%x", retval);
+                               LOG_ERROR("flash writing failed with error code: 0x%x", retval);
                                return ERROR_FLASH_OPERATION_FAILED;
                        }
                }
@@ -518,12 +577,19 @@ int str9x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
                
                /* get status command */
                target_write_u16(target, bank_adr, 0x70);
-               
-               while (1) {
+       
+               int timeout;
+               for (timeout=0; timeout<1000; timeout++)
+               {       
                        target_read_u8(target, bank_adr, &status);
                        if( status & 0x80 )
                                break;
-                       usleep(1000);
+                       alive_sleep(1);
+               }
+               if (timeout==1000)
+               {
+                       LOG_ERROR("write timed out");
+                       return ERROR_FAIL;
                }
                
                /* clear status reg and read array */
@@ -561,11 +627,18 @@ int str9x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
                /* query status command */
                target_write_u16(target, bank_adr, 0x70);
                
-               while (1) {
+               int timeout;
+               for (timeout=0; timeout<1000; timeout++)
+               {       
                        target_read_u8(target, bank_adr, &status);
                        if( status & 0x80 )
                                break;
-                       usleep(1000);
+                       alive_sleep(1);
+               }
+               if (timeout==1000)
+               {
+                       LOG_ERROR("write timed out");
+                       return ERROR_FAIL;
                }
                
                /* clear status reg and read array */
@@ -591,11 +664,6 @@ int str9x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, c
        return ERROR_OK;
 }
 
-int str9x_erase_check(struct flash_bank_s *bank)
-{
-       return str9x_blank_check(bank, 0, bank->num_sectors - 1);
-}
-
 int str9x_info(struct flash_bank_s *bank, char *buf, int buf_size)
 {
        snprintf(buf, buf_size, "str9x flash driver info" );
@@ -608,28 +676,38 @@ int str9x_handle_flash_config_command(struct command_context_s *cmd_ctx, char *c
        flash_bank_t *bank;
        target_t *target = NULL;
        
-       if (argc < 4)
+       if (argc < 5)
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+       
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+       if (!bank)
        {
-               command_print(cmd_ctx, "usage: str9x flash_config b0size b1size b0start b1start");
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
                return ERROR_OK;
        }
        
-       bank = get_flash_bank_by_num(0);
        str9x_info = bank->driver_priv;
-       target = str9x_info->target;
        
-       if (str9x_info->target->state != TARGET_HALTED)
+       target = bank->target;
+       
+       if (bank->target->state != TARGET_HALTED)
        {
+               LOG_ERROR("Target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
        
        /* config flash controller */
-       target_write_u32(target, FLASH_BBSR, strtoul(args[0], NULL, 0));
-       target_write_u32(target, FLASH_NBBSR, strtoul(args[1], NULL, 0));
-    target_write_u32(target, FLASH_BBADR, (strtoul(args[2], NULL, 0) >> 2));
-    target_write_u32(target, FLASH_NBBADR, (strtoul(args[3], NULL, 0) >> 2));
+       target_write_u32(target, FLASH_BBSR, strtoul(args[1], NULL, 0));
+       target_write_u32(target, FLASH_NBBSR, strtoul(args[2], NULL, 0));
+       target_write_u32(target, FLASH_BBADR, (strtoul(args[3], NULL, 0) >> 2));
+       target_write_u32(target, FLASH_NBBADR, (strtoul(args[4], NULL, 0) >> 2));
 
+       /* set bit 18 instruction TCM order as per flash programming manual */
+       arm966e_write_cp15(target, 62, 0x40000);
+       
        /* enable flash bank 1 */
-    target_write_u32(target, FLASH_CR, 0x18);
+       target_write_u32(target, FLASH_CR, 0x18);
        return ERROR_OK;
 }