Andreas Fritiofson <andreas.fritiofson@gmail.com> UTF8 fixes
[fw/openocd] / src / flash / ecos.c
index 6aec41d6a370b83a0553e404b3ee9c5a38e884a0..76859df5db90046fbd8894bf965f3d8b96cde1cb 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2008 Øyvind Harboe                                      *\r
- *   oyvind.harboe@zylin.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
-#ifdef HAVE_CONFIG_H\r
-#include "config.h"\r
-#endif\r
-\r
-#include "replacements.h"\r
-\r
-\r
-#include "flash.h"\r
-\r
-#include "target.h"\r
-\r
-#include "flash.h"\r
-#include "target.h"\r
-#include "log.h"\r
-#include "binarybuffer.h"\r
-#include "../target/embeddedice.h"\r
-#include "types.h"\r
-\r
-\r
-\r
-int ecosflash_register_commands(struct command_context_s *cmd_ctx);\r
-int ecosflash_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);\r
-int ecosflash_erase(struct flash_bank_s *bank, int first, int last);\r
-int ecosflash_protect(struct flash_bank_s *bank, int set, int first, int last);\r
-int ecosflash_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);\r
-int ecosflash_probe(struct flash_bank_s *bank);\r
-int ecosflash_erase_check(struct flash_bank_s *bank);\r
-int ecosflash_protect_check(struct flash_bank_s *bank);\r
-int ecosflash_info(struct flash_bank_s *bank, char *buf, int buf_size);\r
-\r
-u32 ecosflash_get_flash_status(flash_bank_t *bank);\r
-void ecosflash_set_flash_mode(flash_bank_t *bank,int mode);\r
-u32 ecosflash_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout);\r
-int ecosflash_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-flash_driver_t ecosflash_flash =\r
-{\r
-       .name = "ecosflash",\r
-       .register_commands = ecosflash_register_commands,\r
-       .flash_bank_command = ecosflash_flash_bank_command,\r
-       .erase = ecosflash_erase,\r
-       .protect = ecosflash_protect,\r
-       .write = ecosflash_write,\r
-       .probe = ecosflash_probe,\r
-       .auto_probe = ecosflash_probe,\r
-       .erase_check = ecosflash_erase_check,\r
-       .protect_check = ecosflash_protect_check,\r
-       .info = ecosflash_info\r
-};\r
-\r
-typedef struct ecosflash_flash_bank_s\r
-{\r
-       struct target_s *target;\r
-       working_area_t *write_algorithm;\r
-       working_area_t *erase_check_algorithm;\r
-       char *driverPath;\r
-       u32 start_address;\r
-} ecosflash_flash_bank_t;\r
-\r
-static const int sectorSize=0x10000;\r
-\r
-#define FLASH_ERR_OK              0x00  // No error - operation complete\r
-#define FLASH_ERR_INVALID         0x01  // Invalid FLASH address\r
-#define FLASH_ERR_ERASE           0x02  // Error trying to erase\r
-#define FLASH_ERR_LOCK            0x03  // Error trying to lock/unlock\r
-#define FLASH_ERR_PROGRAM         0x04  // Error trying to program\r
-#define FLASH_ERR_PROTOCOL        0x05  // Generic error\r
-#define FLASH_ERR_PROTECT         0x06  // Device/region is write-protected\r
-#define FLASH_ERR_NOT_INIT        0x07  // FLASH info not yet initialized\r
-#define FLASH_ERR_HWR             0x08  // Hardware (configuration?) problem\r
-#define FLASH_ERR_ERASE_SUSPEND   0x09  // Device is in erase suspend mode\r
-#define FLASH_ERR_PROGRAM_SUSPEND 0x0a  // Device is in in program suspend mode\r
-#define FLASH_ERR_DRV_VERIFY      0x0b  // Driver failed to verify data\r
-#define FLASH_ERR_DRV_TIMEOUT     0x0c  // Driver timed out waiting for device\r
-#define FLASH_ERR_DRV_WRONG_PART  0x0d  // Driver does not support device\r
-#define FLASH_ERR_LOW_VOLTAGE     0x0e  // Not enough juice to complete job\r
-\r
-\r
-char *\r
-flash_errmsg(int err)\r
-{\r
-    switch (err) {\r
-    case FLASH_ERR_OK:\r
-        return "No error - operation complete";\r
-    case FLASH_ERR_ERASE_SUSPEND:\r
-        return "Device is in erase suspend state";\r
-    case FLASH_ERR_PROGRAM_SUSPEND:\r
-        return "Device is in program suspend state";\r
-    case FLASH_ERR_INVALID:\r
-        return "Invalid FLASH address";\r
-    case FLASH_ERR_ERASE:\r
-        return "Error trying to erase";\r
-    case FLASH_ERR_LOCK:\r
-        return "Error trying to lock/unlock";\r
-    case FLASH_ERR_PROGRAM:\r
-        return "Error trying to program";\r
-    case FLASH_ERR_PROTOCOL:\r
-        return "Generic error";\r
-    case FLASH_ERR_PROTECT:\r
-        return "Device/region is write-protected";\r
-    case FLASH_ERR_NOT_INIT:\r
-        return "FLASH sub-system not initialized";\r
-    case FLASH_ERR_DRV_VERIFY:\r
-        return "Data verify failed after operation";\r
-    case FLASH_ERR_DRV_TIMEOUT:\r
-        return "Driver timed out waiting for device";\r
-    case FLASH_ERR_DRV_WRONG_PART:\r
-        return "Driver does not support device";\r
-    case FLASH_ERR_LOW_VOLTAGE:\r
-        return "Device reports low voltage";\r
-    default:\r
-        return "Unknown error";\r
-    }\r
-}\r
-\r
-\r
-/* flash bank ecosflash <base> <size> <chip_width> <bus_width> <target#> <driverPath>\r
- */\r
-int ecosflash_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)\r
-{\r
-       ecosflash_flash_bank_t *info;\r
-       \r
-       if (argc < 7)\r
-       {\r
-               WARNING("incomplete flash_bank ecosflash configuration");\r
-               return ERROR_FLASH_BANK_INVALID;\r
-       }\r
-       \r
-       info = malloc(sizeof(ecosflash_flash_bank_t));\r
-       if(info == NULL)\r
-       {\r
-               ERROR("no memory for flash bank info");\r
-               exit(-1);\r
-       }\r
-       bank->driver_priv = info;\r
-       info->driverPath=strdup(args[6]);\r
-\r
-       // eCos flash sector sizes are not exposed to OpenOCD, use 0x10000 as \r
-       // a way to improve impeadance matach between OpenOCD and eCos flash\r
-       // driver\r
-       int i = 0;\r
-       u32 offset = 0;\r
-       bank->num_sectors=bank->size/sectorSize;\r
-       bank->sectors = malloc(sizeof(flash_sector_t) * bank->num_sectors);\r
-       for (i = 0; i < bank->num_sectors; i++)\r
-       {\r
-               bank->sectors[i].offset = offset;\r
-               bank->sectors[i].size = sectorSize;\r
-               offset += bank->sectors[i].size;\r
-               bank->sectors[i].is_erased = -1;\r
-               bank->sectors[i].is_protected = 0;\r
-       }\r
-       \r
-       info->target = get_target_by_num(strtoul(args[5], NULL, 0));\r
-       if (info->target == NULL)\r
-       {\r
-               ERROR("no target '%i' configured", (int)strtoul(args[5], NULL, 0));\r
-               exit(-1);\r
-       }\r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-int loadDriver(ecosflash_flash_bank_t *info)\r
-{\r
-       u32 buf_cnt;\r
-       u32 image_size;\r
-       image_t image;  \r
-       \r
-       image.base_address_set = 0;\r
-       image.start_address_set = 0;\r
-       target_t *target=info->target;\r
-       \r
-       if (image_open(&image, info->driverPath, NULL) != ERROR_OK)\r
-       {\r
-               ERROR("load_image error: %s", image.error_str);\r
-               return ERROR_FLASH_BANK_INVALID;\r
-       }\r
-       \r
-       info->start_address=image.start_address;\r
-       \r
-       image_size = 0x0;\r
-       int i;\r
-       for (i = 0; i < image.num_sections; i++)\r
-       {\r
-               void *buffer = malloc(image.sections[i].size);\r
-               int retval;\r
-               if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)\r
-               {\r
-                       ERROR("image_read_section failed with error code: %i", retval);\r
-                       free(buffer);\r
-                       image_close(&image);\r
-                       return ERROR_FLASH_BANK_INVALID;\r
-               }\r
-               target_write_buffer(target, image.sections[i].base_address, buf_cnt, buffer);\r
-               image_size += buf_cnt;\r
-               DEBUG("%u byte written at address 0x%8.8x", buf_cnt, image.sections[i].base_address);\r
-               \r
-               free(buffer);\r
-       }\r
-\r
-       image_close(&image);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-static int const OFFSET_ERASE=0x0;\r
-static int const OFFSET_ERASE_SIZE=0x8;\r
-static int const OFFSET_FLASH=0xc;\r
-static int const OFFSET_FLASH_SIZE=0x8;\r
-static int const OFFSET_GET_WORKAREA=0x18;\r
-static int const OFFSET_GET_WORKAREA_SIZE=0x4;\r
-\r
-\r
-int runCode(ecosflash_flash_bank_t *info, \r
-               u32 codeStart, u32 codeStop, u32 r0, u32 r1, u32 r2, \r
-               u32 *result,\r
-               // timeout in ms\r
-               int timeout)\r
-{\r
-       target_t *target=info->target;\r
-\r
-       reg_param_t reg_params[3];\r
-       armv4_5_algorithm_t armv4_5_info;\r
-       armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;\r
-       armv4_5_info.core_mode = ARMV4_5_MODE_SVC;\r
-       armv4_5_info.core_state = ARMV4_5_STATE_ARM;\r
-       \r
-       init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);\r
-       init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);\r
-       init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);\r
-       \r
-       buf_set_u32(reg_params[0].value, 0, 32, r0);\r
-       buf_set_u32(reg_params[1].value, 0, 32, r1);\r
-       buf_set_u32(reg_params[2].value, 0, 32, r2);\r
-       \r
-       int retval;\r
-       if ((retval = target->type->run_algorithm(target, 0, NULL, 3, reg_params,\r
-                       codeStart,\r
-                       codeStop, timeout, \r
-                       &armv4_5_info)) != ERROR_OK)\r
-       {\r
-               ERROR("error executing eCos flash algorithm");\r
-               return retval;\r
-       }\r
-       \r
-       *result=buf_get_u32(reg_params[0].value, 0, 32);\r
-       \r
-       destroy_reg_param(&reg_params[0]);\r
-       destroy_reg_param(&reg_params[1]);\r
-       destroy_reg_param(&reg_params[2]);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int eCosBoard_erase(ecosflash_flash_bank_t *info, u32 address, u32 len)\r
-{\r
-       int retval;\r
-       int timeout = (len / 20480 + 1) * 1000; /*asume 20 KB/s*/ \r
-\r
-       retval=loadDriver(info);\r
-       if (retval!=ERROR_OK)\r
-               return retval;\r
-       \r
-       u32 flashErr;\r
-       retval=runCode(info, \r
-                       info->start_address+OFFSET_ERASE,\r
-                       info->start_address+OFFSET_ERASE+OFFSET_ERASE_SIZE,\r
-                       address,\r
-                       len,\r
-                       0,\r
-                       &flashErr,\r
-                       timeout\r
-                       );\r
-       if (retval!=ERROR_OK)\r
-               return retval;\r
-       \r
-       if (flashErr != 0x0)\r
-       {\r
-               ERROR("Flash erase failed with %d (%s)\n", flashErr, flash_errmsg(flashErr));\r
-               return ERROR_JTAG_DEVICE_ERROR;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int eCosBoard_flash(ecosflash_flash_bank_t *info, void *data, u32 address, u32 len)\r
-{\r
-       target_t *target=info->target;\r
-       const int chunk=8192;\r
-       int retval=ERROR_OK;\r
-       int timeout = (chunk / 20480 + 1) * 1000; /*asume 20 KB/s + 1 second*/\r
-       \r
-       retval=loadDriver(info);\r
-       if (retval!=ERROR_OK)\r
-               return retval;\r
-       \r
-       u32 buffer;\r
-       retval=runCode(info, \r
-                       info->start_address+OFFSET_GET_WORKAREA,\r
-                       info->start_address+OFFSET_GET_WORKAREA+OFFSET_GET_WORKAREA_SIZE,\r
-                       0,\r
-                       0,\r
-                       0,\r
-                       &buffer,\r
-                       1000);\r
-       if (retval!=ERROR_OK)\r
-               return retval;\r
-       \r
-       \r
-       int i;\r
-    for (i=0; i<len; i+=chunk)\r
-    {\r
-               int t=len-i;\r
-               if (t>chunk)\r
-               {\r
-                       t=chunk;\r
-               }\r
-               \r
-               int retval;\r
-       retval=target_write_buffer(target, buffer, t, ((char *)data)+i);\r
-       if (retval != ERROR_OK)\r
-               return retval;\r
-       \r
-       u32 flashErr;\r
-       retval=runCode(info, \r
-                       info->start_address+OFFSET_FLASH,\r
-                       info->start_address+OFFSET_FLASH+OFFSET_FLASH_SIZE,\r
-                       buffer,\r
-                       address+i,\r
-                       t,\r
-                       &flashErr,\r
-                       timeout);\r
-       if (retval != ERROR_OK)\r
-               return retval;\r
-\r
-               if (flashErr != 0x0)\r
-               {\r
-                       ERROR("Flash prog failed with %d (%s)\n", flashErr, flash_errmsg(flashErr));\r
-                       return ERROR_JTAG_DEVICE_ERROR;\r
-               }\r
-    }\r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-int ecosflash_probe(struct flash_bank_s *bank)\r
-{\r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-int ecosflash_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       register_command(cmd_ctx, NULL, "ecosflash", NULL, COMMAND_ANY, NULL);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-/*\r
-static void command(flash_bank_t *bank, u8 cmd, u8 *cmd_buf)\r
-{\r
-       ecosflash_flash_bank_t *info = bank->driver_priv;\r
-       int i;\r
-       \r
-       if (info->target->endianness == TARGET_LITTLE_ENDIAN)\r
-       {\r
-               for (i = bank->bus_width; i > 0; i--)\r
-               {\r
-                       *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;\r
-               }\r
-       }\r
-       else\r
-       {\r
-               for (i = 1; i <= bank->bus_width; i++)\r
-               {\r
-                       *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;\r
-               }\r
-       }\r
-}\r
-*/\r
-\r
-u32 ecosflash_address(struct flash_bank_s *bank, u32 address)\r
-{\r
-       u32 retval = 0;\r
-       switch(bank->bus_width)\r
-       {\r
-               case 4:\r
-                       retval = address & 0xfffffffc;\r
-               case 2:\r
-                       retval = address & 0xfffffffe;\r
-               case 1:\r
-                       retval = address;\r
-       }\r
-       \r
-       return retval + bank->base;\r
-} \r
-\r
-\r
-int ecosflash_erase(struct flash_bank_s *bank, int first, int last)\r
-{\r
-       struct flash_bank_s *c=bank;\r
-       ecosflash_flash_bank_t *info = bank->driver_priv;\r
-       return eCosBoard_erase(info, c->base+first*sectorSize, sectorSize*(last-first+1)); \r
-}\r
-\r
-int ecosflash_protect(struct flash_bank_s *bank, int set, int first, int last)\r
-{\r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-int ecosflash_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)\r
-{\r
-       ecosflash_flash_bank_t *info = bank->driver_priv;\r
-       struct flash_bank_s *c=bank;\r
-       return eCosBoard_flash(info, buffer, c->base+offset, count);\r
-}\r
-\r
-\r
-int ecosflash_erase_check(struct flash_bank_s *bank)\r
-{\r
-       return ERROR_OK;\r
-}\r
-\r
-int ecosflash_protect_check(struct flash_bank_s *bank)\r
-{\r
-       return ERROR_OK;\r
-}\r
-\r
-int ecosflash_info(struct flash_bank_s *bank, char *buf, int buf_size)\r
-{\r
-       ecosflash_flash_bank_t *info = bank->driver_priv;\r
-       snprintf(buf, buf_size, "eCos flash driver: %s", info->driverPath);\r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-u32 ecosflash_get_flash_status(flash_bank_t *bank)\r
-{\r
-       return ERROR_OK;\r
-}\r
-\r
-void ecosflash_set_flash_mode(flash_bank_t *bank,int mode)\r
-{\r
-       \r
-}\r
-\r
-u32 ecosflash_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout)\r
-{\r
-       return ERROR_OK;\r
-}\r
-\r
-int ecosflash_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-\r
-\r
+/***************************************************************************
+ *   Copyright (C) 2007,2008 Øyvind 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     *
+ *   (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 "flash.h"
+#include "embeddedice.h"
+#include "image.h"
+
+
+static int ecosflash_register_commands(struct command_context_s *cmd_ctx);
+static int ecosflash_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
+static int ecosflash_erase(struct flash_bank_s *bank, int first, int last);
+static int ecosflash_protect(struct flash_bank_s *bank, int set, int first, int last);
+static int ecosflash_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count);
+static int ecosflash_probe(struct flash_bank_s *bank);
+static int ecosflash_protect_check(struct flash_bank_s *bank);
+static int ecosflash_info(struct flash_bank_s *bank, char *buf, int buf_size);
+
+#if 0
+static uint32_t ecosflash_get_flash_status(flash_bank_t *bank);
+static void ecosflash_set_flash_mode(flash_bank_t *bank,int mode);
+static uint32_t ecosflash_wait_status_busy(flash_bank_t *bank, uint32_t waitbits, int timeout);
+static int ecosflash_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+#endif
+
+flash_driver_t ecosflash_flash =
+{
+       .name = "ecosflash",
+       .register_commands = ecosflash_register_commands,
+       .flash_bank_command = ecosflash_flash_bank_command,
+       .erase = ecosflash_erase,
+       .protect = ecosflash_protect,
+       .write = ecosflash_write,
+       .probe = ecosflash_probe,
+       .auto_probe = ecosflash_probe,
+       .erase_check = default_flash_blank_check,
+       .protect_check = ecosflash_protect_check,
+       .info = ecosflash_info
+};
+
+typedef struct ecosflash_flash_bank_s
+{
+       struct target_s *target;
+       working_area_t *write_algorithm;
+       working_area_t *erase_check_algorithm;
+       char *driverPath;
+       uint32_t start_address;
+} ecosflash_flash_bank_t;
+
+static const int sectorSize = 0x10000;
+
+char *
+flash_errmsg(int err);
+
+#ifndef __ECOS
+#define FLASH_ERR_OK              0x00  /* No error - operation complete */
+#define FLASH_ERR_INVALID         0x01  /* Invalid FLASH address */
+#define FLASH_ERR_ERASE           0x02  /* Error trying to erase */
+#define FLASH_ERR_LOCK            0x03  /* Error trying to lock/unlock */
+#define FLASH_ERR_PROGRAM         0x04  /* Error trying to program */
+#define FLASH_ERR_PROTOCOL        0x05  /* Generic error */
+#define FLASH_ERR_PROTECT         0x06  /* Device/region is write-protected */
+#define FLASH_ERR_NOT_INIT        0x07  /* FLASH info not yet initialized */
+#define FLASH_ERR_HWR             0x08  /* Hardware (configuration?) problem */
+#define FLASH_ERR_ERASE_SUSPEND   0x09  /* Device is in erase suspend mode */
+#define FLASH_ERR_PROGRAM_SUSPEND 0x0a  /* Device is in in program suspend mode */
+#define FLASH_ERR_DRV_VERIFY      0x0b  /* Driver failed to verify data */
+#define FLASH_ERR_DRV_TIMEOUT     0x0c  /* Driver timed out waiting for device */
+#define FLASH_ERR_DRV_WRONG_PART  0x0d  /* Driver does not support device */
+#define FLASH_ERR_LOW_VOLTAGE     0x0e  /* Not enough juice to complete job */
+
+char *
+flash_errmsg(int err)
+{
+       switch (err) {
+       case FLASH_ERR_OK:
+               return "No error - operation complete";
+       case FLASH_ERR_ERASE_SUSPEND:
+               return "Device is in erase suspend state";
+       case FLASH_ERR_PROGRAM_SUSPEND:
+               return "Device is in program suspend state";
+       case FLASH_ERR_INVALID:
+               return "Invalid FLASH address";
+       case FLASH_ERR_ERASE:
+               return "Error trying to erase";
+       case FLASH_ERR_LOCK:
+               return "Error trying to lock/unlock";
+       case FLASH_ERR_PROGRAM:
+               return "Error trying to program";
+       case FLASH_ERR_PROTOCOL:
+               return "Generic error";
+       case FLASH_ERR_PROTECT:
+               return "Device/region is write-protected";
+       case FLASH_ERR_NOT_INIT:
+               return "FLASH sub-system not initialized";
+       case FLASH_ERR_DRV_VERIFY:
+               return "Data verify failed after operation";
+       case FLASH_ERR_DRV_TIMEOUT:
+               return "Driver timed out waiting for device";
+       case FLASH_ERR_DRV_WRONG_PART:
+               return "Driver does not support device";
+       case FLASH_ERR_LOW_VOLTAGE:
+               return "Device reports low voltage";
+       default:
+               return "Unknown error";
+       }
+}
+#endif
+
+/* flash bank ecosflash <base> <size> <chip_width> <bus_width> <target#> <driverPath>
+ */
+static int ecosflash_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
+{
+       ecosflash_flash_bank_t *info;
+
+       if (argc < 7)
+       {
+               LOG_WARNING("incomplete flash_bank ecosflash configuration");
+               return ERROR_FLASH_BANK_INVALID;
+       }
+
+       info = malloc(sizeof(ecosflash_flash_bank_t));
+       if (info == NULL)
+       {
+               LOG_ERROR("no memory for flash bank info");
+               exit(-1);
+       }
+       bank->driver_priv = info;
+       info->driverPath = strdup(args[6]);
+
+       /* eCos flash sector sizes are not exposed to OpenOCD, use 0x10000 as
+        * a way to improve impeadance matach between OpenOCD and eCos flash
+        * driver.
+        */
+       int i = 0;
+       uint32_t offset = 0;
+       bank->num_sectors = bank->size/sectorSize;
+       bank->sectors = malloc(sizeof(flash_sector_t) * bank->num_sectors);
+       for (i = 0; i < bank->num_sectors; i++)
+       {
+               bank->sectors[i].offset = offset;
+               bank->sectors[i].size = sectorSize;
+               offset += bank->sectors[i].size;
+               bank->sectors[i].is_erased = -1;
+               bank->sectors[i].is_protected = 0;
+       }
+
+       info->target = get_target(args[5]);
+       if (info->target == NULL)
+       {
+               LOG_ERROR("target '%s' not defined", args[5]);
+               return ERROR_FAIL;
+       }
+       return ERROR_OK;
+}
+
+static int loadDriver(ecosflash_flash_bank_t *info)
+{
+       uint32_t buf_cnt;
+       uint32_t image_size;
+       image_t image;
+
+       image.base_address_set = 0;
+       image.start_address_set = 0;
+       target_t *target = info->target;
+       int retval;
+
+       if ((retval = image_open(&image, info->driverPath, NULL)) != ERROR_OK)
+       {
+               return retval;
+       }
+
+       info->start_address = image.start_address;
+
+       image_size = 0x0;
+       int i;
+       for (i = 0; i < image.num_sections; i++)
+       {
+               void *buffer = malloc(image.sections[i].size);
+               int retval;
+               if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
+               {
+                       free(buffer);
+                       image_close(&image);
+                       return retval;
+               }
+               target_write_buffer(target, image.sections[i].base_address, buf_cnt, buffer);
+               image_size += buf_cnt;
+               LOG_DEBUG("%" PRIu32 " byte written at address 0x%8.8" PRIx32 "", buf_cnt, image.sections[i].base_address);
+
+               free(buffer);
+       }
+
+       image_close(&image);
+
+       return ERROR_OK;
+}
+
+static int const OFFSET_ERASE = 0x0;
+static int const OFFSET_ERASE_SIZE = 0x8;
+static int const OFFSET_FLASH = 0xc;
+static int const OFFSET_FLASH_SIZE = 0x8;
+static int const OFFSET_GET_WORKAREA = 0x18;
+static int const OFFSET_GET_WORKAREA_SIZE = 0x4;
+
+static int runCode(ecosflash_flash_bank_t *info,
+               uint32_t codeStart, uint32_t codeStop, uint32_t r0, uint32_t r1, uint32_t r2,
+               uint32_t *result,
+               /* timeout in ms */
+               int timeout)
+{
+       target_t *target = info->target;
+
+       reg_param_t reg_params[3];
+       armv4_5_algorithm_t armv4_5_info;
+       armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
+       armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
+       armv4_5_info.core_state = ARMV4_5_STATE_ARM;
+
+       init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
+       init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
+       init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
+
+       buf_set_u32(reg_params[0].value, 0, 32, r0);
+       buf_set_u32(reg_params[1].value, 0, 32, r1);
+       buf_set_u32(reg_params[2].value, 0, 32, r2);
+
+       int retval;
+       if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
+                       codeStart,
+                       codeStop, timeout,
+                       &armv4_5_info)) != ERROR_OK)
+       {
+               LOG_ERROR("error executing eCos flash algorithm");
+               return retval;
+       }
+
+       *result = buf_get_u32(reg_params[0].value, 0, 32);
+
+       destroy_reg_param(&reg_params[0]);
+       destroy_reg_param(&reg_params[1]);
+       destroy_reg_param(&reg_params[2]);
+
+       return ERROR_OK;
+}
+
+static int eCosBoard_erase(ecosflash_flash_bank_t *info, uint32_t address, uint32_t len)
+{
+       int retval;
+       int timeout = (len / 20480 + 1) * 1000; /*asume 20 KB/s*/
+
+       retval = loadDriver(info);
+       if (retval != ERROR_OK)
+               return retval;
+
+       uint32_t flashErr;
+       retval = runCode(info,
+                       info->start_address + OFFSET_ERASE,
+                       info->start_address + OFFSET_ERASE + OFFSET_ERASE_SIZE,
+                       address,
+                       len,
+                       0,
+                       &flashErr,
+                       timeout
+);
+       if (retval != ERROR_OK)
+               return retval;
+
+       if (flashErr != 0x0)
+       {
+               LOG_ERROR("Flash erase failed with %d (%s)\n", (int)flashErr, flash_errmsg(flashErr));
+               return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+static int eCosBoard_flash(ecosflash_flash_bank_t *info, void *data, uint32_t address, uint32_t len)
+{
+       target_t *target = info->target;
+       const int chunk = 8192;
+       int retval = ERROR_OK;
+       int timeout = (chunk / 20480 + 1) * 1000; /*asume 20 KB/s + 1 second*/
+
+       retval = loadDriver(info);
+       if (retval != ERROR_OK)
+               return retval;
+
+       uint32_t buffer;
+       retval = runCode(info,
+                       info->start_address + OFFSET_GET_WORKAREA,
+                       info->start_address + OFFSET_GET_WORKAREA + OFFSET_GET_WORKAREA_SIZE,
+                       0,
+                       0,
+                       0,
+                       &buffer,
+                       1000);
+       if (retval != ERROR_OK)
+               return retval;
+
+
+       uint32_t i;
+       for (i = 0; i < len; i += chunk)
+       {
+               int t = len-i;
+               if (t > chunk)
+               {
+                       t = chunk;
+               }
+
+               int retval;
+               retval = target_write_buffer(target, buffer, t, ((uint8_t *)data) + i);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               uint32_t flashErr;
+               retval = runCode(info,
+                               info->start_address + OFFSET_FLASH,
+                               info->start_address + OFFSET_FLASH + OFFSET_FLASH_SIZE,
+                               buffer,
+                               address + i,
+                               t,
+                               &flashErr,
+                               timeout);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               if (flashErr != 0x0)
+               {
+                       LOG_ERROR("Flash prog failed with %d (%s)\n", (int)flashErr, flash_errmsg(flashErr));
+                       return ERROR_FAIL;
+               }
+       }
+       return ERROR_OK;
+}
+
+static int ecosflash_probe(struct flash_bank_s *bank)
+{
+       return ERROR_OK;
+}
+
+static int ecosflash_register_commands(struct command_context_s *cmd_ctx)
+{
+       register_command(cmd_ctx, NULL, "ecosflash", NULL, COMMAND_ANY, NULL);
+
+       return ERROR_OK;
+}
+
+#if 0
+static void command(flash_bank_t *bank, uint8_t cmd, uint8_t *cmd_buf)
+{
+       ecosflash_flash_bank_t *info = bank->driver_priv;
+       int i;
+
+       if (info->target->endianness == TARGET_LITTLE_ENDIAN)
+       {
+               for (i = bank->bus_width; i > 0; i--)
+               {
+                       *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
+               }
+       }
+       else
+       {
+               for (i = 1; i <= bank->bus_width; i++)
+               {
+                       *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
+               }
+       }
+}
+#endif
+
+#if 0
+static uint32_t ecosflash_address(struct flash_bank_s *bank, uint32_t address)
+{
+       uint32_t retval = 0;
+       switch (bank->bus_width)
+       {
+               case 4:
+                       retval = address & 0xfffffffc;
+               case 2:
+                       retval = address & 0xfffffffe;
+               case 1:
+                       retval = address;
+       }
+
+       return retval + bank->base;
+}
+#endif
+
+static int ecosflash_erase(struct flash_bank_s *bank, int first, int last)
+{
+       struct flash_bank_s *c = bank;
+       ecosflash_flash_bank_t *info = bank->driver_priv;
+       return eCosBoard_erase(info, c->base + first*sectorSize, sectorSize*(last-first + 1));
+}
+
+static int ecosflash_protect(struct flash_bank_s *bank, int set, int first, int last)
+{
+       return ERROR_OK;
+}
+
+static int ecosflash_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
+{
+       ecosflash_flash_bank_t *info = bank->driver_priv;
+       struct flash_bank_s *c = bank;
+       return eCosBoard_flash(info, buffer, c->base + offset, count);
+}
+
+static int ecosflash_protect_check(struct flash_bank_s *bank)
+{
+       return ERROR_OK;
+}
+
+static int ecosflash_info(struct flash_bank_s *bank, char *buf, int buf_size)
+{
+       ecosflash_flash_bank_t *info = bank->driver_priv;
+       snprintf(buf, buf_size, "eCos flash driver: %s", info->driverPath);
+       return ERROR_OK;
+}
+
+#if 0
+static uint32_t ecosflash_get_flash_status(flash_bank_t *bank)
+{
+       return ERROR_OK;
+}
+
+static void ecosflash_set_flash_mode(flash_bank_t *bank,int mode)
+{
+
+}
+
+static uint32_t ecosflash_wait_status_busy(flash_bank_t *bank, uint32_t waitbits, int timeout)
+{
+       return ERROR_OK;
+}
+
+static int ecosflash_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       return ERROR_OK;
+}
+#endif