- "flash write_binary" is now "flash write_bank" to clarify the focus of the
[openocd.git] / src / flash / str9xpec.c
index a9a24bfb58bb5a74dd9301e79b1b8f6f4f1eff70..4d3093eefca25b80b6447395945919899b874559 100644 (file)
-/***************************************************************************
- *   Copyright (C) 2005 by Dominic Rath                                    *
- *   Dominic.Rath@gmx.de                                                   *
- *                                                                         *
- *   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 "replacements.h"
-
-#include "str9xpec.h"
-#include "flash.h"
-#include "target.h"
-#include "log.h"
-#include "armv4_5.h"
-#include "arm7_9_common.h"
-#include "jtag.h"
-#include "binarybuffer.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <getopt.h>
-
-str9xpec_mem_layout_t mem_layout_str9pec[] = {
-       {0x00000000, 0x10000, 0},
-       {0x00010000, 0x10000, 1},
-       {0x00020000, 0x10000, 2},
-       {0x00030000, 0x10000, 3},
-       {0x00040000, 0x10000, 4},
-       {0x00050000, 0x10000, 5},
-       {0x00060000, 0x10000, 6},
-       {0x00070000, 0x10000, 7},
-       {0x00080000, 0x02000, 32},
-       {0x00082000, 0x02000, 33},
-       {0x00084000, 0x02000, 34},
-       {0x00086000, 0x02000, 35}
-};
-
-int str9xpec_register_commands(struct command_context_s *cmd_ctx);
-int str9xpec_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
-int str9xpec_erase(struct flash_bank_s *bank, int first, int last);
-int str9xpec_protect(struct flash_bank_s *bank, int set, int first, int last);
-int str9xpec_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
-int str9xpec_probe(struct flash_bank_s *bank);
-int str9xpec_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int str9xpec_protect_check(struct flash_bank_s *bank);
-int str9xpec_erase_check(struct flash_bank_s *bank);
-int str9xpec_info(struct flash_bank_s *bank, char *buf, int buf_size);
-
-int str9xpec_erase_area(struct flash_bank_s *bank, int first, int last);
-int str9xpec_set_address(struct flash_bank_s *bank, u8 sector);
-int str9xpec_write_options(struct flash_bank_s *bank);
-
-int str9xpec_handle_flash_options_cmap_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int str9xpec_handle_flash_options_lvdthd_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int str9xpec_handle_flash_options_lvdsel_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int str9xpec_handle_flash_options_lvdwarn_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int str9xpec_handle_flash_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int str9xpec_handle_flash_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int str9xpec_handle_flash_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int str9xpec_handle_flash_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int str9xpec_handle_flash_enable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int str9xpec_handle_flash_disable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-
-flash_driver_t str9xpec_flash =
-{
-       .name = "str9xpec",
-       .register_commands = str9xpec_register_commands,
-       .flash_bank_command = str9xpec_flash_bank_command,
-       .erase = str9xpec_erase,
-       .protect = str9xpec_protect,
-       .write = str9xpec_write,
-       .probe = str9xpec_probe,
-       .auto_probe = str9xpec_probe,
-       .erase_check = str9xpec_erase_check,
-       .protect_check = str9xpec_protect_check,
-       .info = str9xpec_info
-};
-
-int str9xpec_register_commands(struct command_context_s *cmd_ctx)
-{
-       command_t *str9xpec_cmd = register_command(cmd_ctx, NULL, "str9xpec", NULL, COMMAND_ANY, "str9xpec flash specific commands");
-       
-       register_command(cmd_ctx, str9xpec_cmd, "enable_turbo", str9xpec_handle_flash_enable_turbo_command, COMMAND_EXEC,
-                                        "enable str9xpec turbo mode");
-       register_command(cmd_ctx, str9xpec_cmd, "disable_turbo", str9xpec_handle_flash_disable_turbo_command, COMMAND_EXEC,
-                                        "disable str9xpec turbo mode");
-       register_command(cmd_ctx, str9xpec_cmd, "options_cmap", str9xpec_handle_flash_options_cmap_command, COMMAND_EXEC,
-                                        "configure str9xpec boot sector");
-       register_command(cmd_ctx, str9xpec_cmd, "options_lvdthd", str9xpec_handle_flash_options_lvdthd_command, COMMAND_EXEC,
-                                        "configure str9xpec lvd threshold");
-       register_command(cmd_ctx, str9xpec_cmd, "options_lvdsel", str9xpec_handle_flash_options_lvdsel_command, COMMAND_EXEC,
-                                        "configure str9xpec lvd selection");
-       register_command(cmd_ctx, str9xpec_cmd, "options_lvdwarn", str9xpec_handle_flash_options_lvdwarn_command, COMMAND_EXEC,
-                                        "configure str9xpec lvd warning");
-       register_command(cmd_ctx, str9xpec_cmd, "options_read", str9xpec_handle_flash_options_read_command, COMMAND_EXEC,
-                                        "read str9xpec options");
-       register_command(cmd_ctx, str9xpec_cmd, "options_write", str9xpec_handle_flash_options_write_command, COMMAND_EXEC,
-                                        "write str9xpec options");
-       register_command(cmd_ctx, str9xpec_cmd, "lock", str9xpec_handle_flash_lock_command, COMMAND_EXEC,
-                                        "lock str9xpec device");
-       register_command(cmd_ctx, str9xpec_cmd, "unlock", str9xpec_handle_flash_unlock_command, COMMAND_EXEC,
-                                        "unlock str9xpec device");
-       register_command(cmd_ctx, str9xpec_cmd, "part_id", str9xpec_handle_part_id_command, COMMAND_EXEC,
-                                        "print part id of str9xpec flash bank <num>");
-       
-       return ERROR_OK;
-}
-
-int str9xpec_set_instr(int chain_pos, u32 new_instr, enum tap_state end_state)
-{
-       jtag_device_t *device = jtag_get_device(chain_pos);
-       
-       if (device == NULL)
-       {
-               DEBUG("Invalid Target");
-               return ERROR_TARGET_INVALID;
-       }
-               
-       if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)
-       {
-               scan_field_t field;
-                               
-               field.device = chain_pos;
-               field.num_bits = device->ir_length;
-               field.out_value = calloc(CEIL(field.num_bits, 8), 1);
-               buf_set_u32(field.out_value, 0, field.num_bits, new_instr);
-               field.out_mask = NULL;
-               field.in_value = NULL;
-               field.in_check_value = NULL;
-               field.in_check_mask = NULL;
-               field.in_handler = NULL;
-               field.in_handler_priv = NULL;
-               
-               jtag_add_ir_scan(1, &field, end_state, NULL);
-               
-               free(field.out_value);
-       }
-       
-       return ERROR_OK;
-}
-
-u8 str9xpec_isc_status(int chain_pos)
-{
-       scan_field_t field;
-       u8 status;
-       
-       if (str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI) != ERROR_OK)
-               return ISC_STATUS_ERROR;
-       
-       field.device = chain_pos;
-       field.num_bits = 8;
-       field.out_value = NULL;
-       field.out_mask = NULL;
-       field.in_value = &status;
-       field.in_check_value = NULL;
-       field.in_check_mask = NULL;
-       field.in_handler = NULL;
-       field.in_handler_priv = NULL;
-       
-       jtag_add_dr_scan(1, &field, TAP_RTI, NULL);
-       jtag_execute_queue();
-       
-       DEBUG("status: 0x%2.2x", status);
-       
-       if (status & ISC_STATUS_SECURITY)
-               INFO("Device Security Bit Set");
-       
-       return status;
-}
-
-int str9xpec_isc_enable(struct flash_bank_s *bank)
-{
-       u8 status;
-       u32 chain_pos;
-       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
-       
-       chain_pos = str9xpec_info->chain_pos;
-       
-       if (str9xpec_info->isc_enable)
-               return ERROR_OK;
-       
-       /* enter isc mode */
-       if (str9xpec_set_instr(chain_pos, ISC_ENABLE, TAP_RTI) != ERROR_OK)
-               return ERROR_TARGET_INVALID;
-       
-       /* check ISC status */
-       status = str9xpec_isc_status(chain_pos);
-       if (status & ISC_STATUS_MODE)
-       {
-               /* we have entered isc mode */
-               str9xpec_info->isc_enable = 1;
-               DEBUG("ISC_MODE Enabled");
-       }
-       
-       return ERROR_OK;
-}
-
-int str9xpec_isc_disable(struct flash_bank_s *bank)
-{
-       u8 status;
-       u32 chain_pos;
-       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
-       
-       chain_pos = str9xpec_info->chain_pos;
-       
-       if (!str9xpec_info->isc_enable)
-               return ERROR_OK;
-       
-       if (str9xpec_set_instr(chain_pos, ISC_DISABLE, TAP_RTI) != ERROR_OK)
-               return ERROR_TARGET_INVALID;
-       
-       /* delay to handle aborts */
-       jtag_add_sleep(50);
-       
-       /* check ISC status */
-       status = str9xpec_isc_status(chain_pos);
-       if (!(status & ISC_STATUS_MODE))
-       {
-               /* we have left isc mode */
-               str9xpec_info->isc_enable = 0;
-               DEBUG("ISC_MODE Disabled");
-       }
-       
-       return ERROR_OK;
-}
-
-int str9xpec_read_config(struct flash_bank_s *bank)
-{
-       scan_field_t field;
-       u8 status;
-       u32 chain_pos;
-               
-       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
-       
-       chain_pos = str9xpec_info->chain_pos;
-       
-       DEBUG("ISC_CONFIGURATION");
-       
-       /* execute ISC_CONFIGURATION command */
-       str9xpec_set_instr(chain_pos, ISC_CONFIGURATION, TAP_PI);
-       
-       field.device = chain_pos;
-       field.num_bits = 64;
-       field.out_value = NULL;
-       field.out_mask = NULL;
-       field.in_value = str9xpec_info->options;
-       field.in_check_value = NULL;
-       field.in_check_mask = NULL;
-       field.in_handler = NULL;
-       field.in_handler_priv = NULL;
-       
-       jtag_add_dr_scan(1, &field, TAP_RTI, NULL);
-       jtag_execute_queue();
-       
-       status = str9xpec_isc_status(chain_pos);
-       
-       return status;
-}
-
-int str9xpec_build_block_list(struct flash_bank_s *bank)
-{
-       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
-       
-       int i;
-       int num_sectors = 0, b0_sectors = 0;
-               
-       switch (bank->size)
-       {
-               case (256 * 1024):
-                       b0_sectors = 4;
-                       break;
-               case (512 * 1024):
-                       b0_sectors = 8;
-                       break;
-               default:
-                       ERROR("BUG: unknown bank->size encountered");
-                       exit(-1);
-       }
-       
-       /* include bank 1 sectors */
-       num_sectors = b0_sectors + 4;
-       bank->size += (32 * 1024);
-       
-       bank->num_sectors = num_sectors;
-       bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);
-       str9xpec_info->sector_bits = malloc(sizeof(u32) * num_sectors);
-       
-       num_sectors = 0;
-       
-       for (i = 0; i < b0_sectors; i++)
-       {
-               bank->sectors[num_sectors].offset = mem_layout_str9pec[i].sector_start;
-               bank->sectors[num_sectors].size = mem_layout_str9pec[i].sector_size;
-               bank->sectors[num_sectors].is_erased = -1;
-               bank->sectors[num_sectors].is_protected = 1;
-               str9xpec_info->sector_bits[num_sectors++] = mem_layout_str9pec[i].sector_bit;
-       }
-       
-       for (i = 8; i < 12; i++)
-       {
-               bank->sectors[num_sectors].offset = mem_layout_str9pec[i].sector_start;
-               bank->sectors[num_sectors].size = mem_layout_str9pec[i].sector_size;
-               bank->sectors[num_sectors].is_erased = -1;
-               bank->sectors[num_sectors].is_protected = 1;
-               str9xpec_info->sector_bits[num_sectors++] = mem_layout_str9pec[i].sector_bit;
-       }
-       
-       return ERROR_OK;
-}
-
-/* flash bank str9x <base> <size> 0 0 <target#>
- */
-int str9xpec_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
-{
-       str9xpec_flash_controller_t *str9xpec_info;
-       armv4_5_common_t *armv4_5 = NULL;
-       arm7_9_common_t *arm7_9 = NULL;
-       arm_jtag_t *jtag_info = NULL;
-       
-       if (argc < 6)
-       {
-               WARNING("incomplete flash_bank str9x configuration");
-               return ERROR_FLASH_BANK_INVALID;
-       }
-       
-       str9xpec_info = malloc(sizeof(str9xpec_flash_controller_t));
-       bank->driver_priv = str9xpec_info;
-       
-       if (bank->base != 0x00000000)
-       {
-               WARNING("overriding flash base address for STR91x device with 0x00000000");
-               bank->base = 0x00000000;
-       }
-
-       /* find out jtag position of flash controller
-        * it is always after the arm966 core */
-       
-       armv4_5 = bank->target->arch_info;
-       arm7_9 = armv4_5->arch_info;
-       jtag_info = &arm7_9->jtag_info;
-       
-       str9xpec_info->chain_pos = (jtag_info->chain_pos - 1);
-       str9xpec_info->isc_enable = 0;
-       str9xpec_info->devarm = NULL;
-       
-       str9xpec_build_block_list(bank);
-       
-       /* clear option byte register */
-       buf_set_u32(str9xpec_info->options, 0, 64, 0);
-       
-       return ERROR_OK;
-}
-
-int str9xpec_blank_check(struct flash_bank_s *bank, int first, int last)
-{
-       scan_field_t field;
-       u8 status;
-       u32 chain_pos;
-       int i;
-       u8 *buffer = NULL;
-               
-       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
-       
-       chain_pos = str9xpec_info->chain_pos;
-       
-       if (!str9xpec_info->isc_enable) {
-               str9xpec_isc_enable( bank );
-       }
-       
-       if (!str9xpec_info->isc_enable) {
-               return ERROR_FLASH_OPERATION_FAILED;
-       }
-       
-       buffer = calloc(CEIL(64, 8), 1);
-
-       DEBUG("blank check: first_bank: %i, last_bank: %i", first, last);
-       
-       for (i = first; i <= last; i++) {
-               buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
-       }
-       
-       /* execute ISC_BLANK_CHECK command */
-       str9xpec_set_instr(chain_pos, ISC_BLANK_CHECK, TAP_PI);
-       
-       field.device = chain_pos;
-       field.num_bits = 64;
-       field.out_value = buffer;
-       field.out_mask = NULL;
-       field.in_value = NULL;
-       field.in_check_value = NULL;
-       field.in_check_mask = NULL;
-       field.in_handler = NULL;
-       field.in_handler_priv = NULL;
-       
-       jtag_add_dr_scan(1, &field, TAP_RTI, NULL);
-       jtag_add_sleep(40000);
-       
-       /* read blank check result */
-       field.device = chain_pos;
-       field.num_bits = 64;
-       field.out_value = NULL;
-       field.out_mask = NULL;
-       field.in_value = buffer;
-       field.in_check_value = NULL;
-       field.in_check_mask = NULL;
-       field.in_handler = NULL;
-       field.in_handler_priv = NULL;
-       
-       jtag_add_dr_scan(1, &field, TAP_PI, NULL);
-       jtag_execute_queue();
-       
-       status = str9xpec_isc_status(chain_pos);
-       
-       for (i = first; i <= last; i++)
-       {
-               if (buf_get_u32(buffer, str9xpec_info->sector_bits[i], 1))
-                       bank->sectors[i].is_erased = 0;
-               else
-                       bank->sectors[i].is_erased = 1;
-       }
-       
-       free(buffer);
-       
-       str9xpec_isc_disable(bank);
-       
-       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-               return ERROR_FLASH_OPERATION_FAILED; 
-       return ERROR_OK;
-}
-
-int str9xpec_protect_check(struct flash_bank_s *bank)
-{
-       u8 status;
-       int i;
-               
-       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
-       
-       status = str9xpec_read_config(bank);
-       
-       for (i = 0; i < bank->num_sectors; i++)
-       {
-               if (buf_get_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1))
-                       bank->sectors[i].is_protected = 1;
-               else
-                       bank->sectors[i].is_protected = 0;
-       }
-       
-       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-               return ERROR_FLASH_OPERATION_FAILED;
-       return ERROR_OK;
-}
-
-int str9xpec_erase_area(struct flash_bank_s *bank, int first, int last)
-{
-       scan_field_t field;
-       u8 status;
-       u32 chain_pos;
-       int i;
-       u8 *buffer = NULL;
-       
-       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
-       
-       chain_pos = str9xpec_info->chain_pos;
-       
-       if (!str9xpec_info->isc_enable) {
-               str9xpec_isc_enable( bank );
-       }
-       
-       if (!str9xpec_info->isc_enable) {
-               return ISC_STATUS_ERROR;
-       }
-       
-       buffer = calloc(CEIL(64, 8), 1);
-       
-       DEBUG("erase: first_bank: %i, last_bank: %i", first, last);
-       
-       /* last bank: 0xFF signals a full erase (unlock complete device) */
-       /* last bank: 0xFE signals a option byte erase */
-       if (last == 0xFF)
-       {
-               for (i = 0; i < 64; i++) {
-                       buf_set_u32(buffer, i, 1, 1);
-               }       
-       }
-       else if (last == 0xFE)
-       {
-               buf_set_u32(buffer, 49, 1, 1);
-       }
-       else
-       {       
-               for (i = first; i <= last; i++) {
-                       buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
-               }
-       }
-       
-       DEBUG("ISC_ERASE");
-       
-       /* execute ISC_ERASE command */
-       str9xpec_set_instr(chain_pos, ISC_ERASE, TAP_PI);
-       
-       field.device = chain_pos;
-       field.num_bits = 64;
-       field.out_value = buffer;
-       field.out_mask = NULL;
-       field.in_value = NULL;
-       field.in_check_value = NULL;
-       field.in_check_mask = NULL;
-       field.in_handler = NULL;
-       field.in_handler_priv = NULL;
-       
-       jtag_add_dr_scan(1, &field, TAP_RTI, NULL);
-       jtag_execute_queue();
-       
-       jtag_add_sleep(10);
-       
-       /* wait for erase completion */
-       while (!((status = str9xpec_isc_status(chain_pos)) & ISC_STATUS_BUSY)) {
-               usleep(1000);
-       }
-       
-       free(buffer);
-       
-       str9xpec_isc_disable(bank);
-       
-       return status;
-}
-
-int str9xpec_erase(struct flash_bank_s *bank, int first, int last)
-{
-       int status;
-       
-       status = str9xpec_erase_area(bank, first, last);
-       
-       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-               return ERROR_FLASH_OPERATION_FAILED;
-       
-       return ERROR_OK;
-}
-
-int str9xpec_lock_device(struct flash_bank_s *bank)
-{
-       scan_field_t field;
-       u8 status;
-       u32 chain_pos;
-       str9xpec_flash_controller_t *str9xpec_info = NULL;
-       
-       str9xpec_info = bank->driver_priv;
-       chain_pos = str9xpec_info->chain_pos;
-       
-       if (!str9xpec_info->isc_enable) {
-               str9xpec_isc_enable( bank );
-       }
-       
-       if (!str9xpec_info->isc_enable) {
-               return ISC_STATUS_ERROR;
-       }
-       
-       /* set security address */
-       str9xpec_set_address(bank, 0x80);
-       
-       /* execute ISC_PROGRAM command */
-       str9xpec_set_instr(chain_pos, ISC_PROGRAM_SECURITY, TAP_RTI);
-       
-       str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);
-       
-       do {
-               field.device = chain_pos;
-               field.num_bits = 8;
-               field.out_value = NULL;
-               field.out_mask = NULL;
-               field.in_value = &status;
-               field.in_check_value = NULL;
-               field.in_check_mask = NULL;
-               field.in_handler = NULL;
-               field.in_handler_priv = NULL;
-               
-               jtag_add_dr_scan(1, &field, -1, NULL);
-               jtag_execute_queue();
-               
-       } while(!(status & ISC_STATUS_BUSY));
-       
-       str9xpec_isc_disable(bank);
-       
-       return status;
-}
-
-int str9xpec_unlock_device(struct flash_bank_s *bank)
-{
-       u8 status;
-       
-       status = str9xpec_erase_area(bank, 0, 255);
-       
-       return status;
-}
-
-int str9xpec_protect(struct flash_bank_s *bank, int set, int first, int last)
-{
-       u8 status;
-       int i;
-       
-       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
-       
-       status = str9xpec_read_config(bank);
-       
-       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-               return ERROR_FLASH_OPERATION_FAILED;
-
-       DEBUG("protect: first_bank: %i, last_bank: %i", first, last);
-       
-       /* last bank: 0xFF signals a full device protect */
-       if (last == 0xFF)
-       {
-               if( set )
-               {
-                       status = str9xpec_lock_device(bank);
-               }
-               else
-               {
-                       /* perform full erase to unlock device */
-                       status = str9xpec_unlock_device(bank);
-               }
-       }
-       else
-       {       
-               for (i = first; i <= last; i++)
-               {
-                       if( set )
-                               buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 1);
-                       else
-                               buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 0);
-               }
-               
-               status = str9xpec_write_options(bank);
-       }
-       
-       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-               return ERROR_FLASH_OPERATION_FAILED;
-       
-       return ERROR_OK;
-}
-
-int str9xpec_set_address(struct flash_bank_s *bank, u8 sector)
-{
-       u32 chain_pos;
-       scan_field_t field;
-       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
-       
-       chain_pos = str9xpec_info->chain_pos;
-       
-       /* set flash controller address */
-       str9xpec_set_instr(chain_pos, ISC_ADDRESS_SHIFT, TAP_PI);
-       
-       field.device = chain_pos;
-       field.num_bits = 8;
-       field.out_value = &sector;
-       field.out_mask = NULL;
-       field.in_value = NULL;
-       field.in_check_value = NULL;
-       field.in_check_mask = NULL;
-       field.in_handler = NULL;
-       field.in_handler_priv = NULL;
-       
-       jtag_add_dr_scan(1, &field, -1, NULL);
-               
-       return ERROR_OK;
-}
-
-int str9xpec_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
-{
-       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
-       u32 dwords_remaining = (count / 8);
-       u32 bytes_remaining = (count & 0x00000007);
-       u32 bytes_written = 0;
-       u8 status;
-       u32 check_address = offset;
-       u32 chain_pos;
-       scan_field_t field;
-       u8 *scanbuf;
-       int i;
-       u32 first_sector = 0;
-       u32 last_sector = 0;
-       
-       chain_pos = str9xpec_info->chain_pos;
-       
-       if (!str9xpec_info->isc_enable) {
-               str9xpec_isc_enable(bank);
-       }
-       
-       if (!str9xpec_info->isc_enable) {
-               return ERROR_FLASH_OPERATION_FAILED;
-       }
-       
-       if (offset & 0x7)
-       {
-               WARNING("offset 0x%x breaks required 8-byte alignment", offset);
-               return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
-       }
-       
-       for (i = 0; i < bank->num_sectors; i++)
-       {
-               u32 sec_start = bank->sectors[i].offset;
-               u32 sec_end = sec_start + bank->sectors[i].size;
-               
-               /* check if destination falls within the current sector */
-               if ((check_address >= sec_start) && (check_address < sec_end))
-               {
-                       /* check if destination ends in the current sector */
-                       if (offset + count < sec_end)
-                               check_address = offset + count;
-                       else
-                               check_address = sec_end;
-               }
-               
-               if ((offset >= sec_start) && (offset < sec_end)){
-                       first_sector = i;
-               }
-               
-               if ((offset + count >= sec_start) && (offset + count < sec_end)){
-                       last_sector = i;
-               }
-       }
-       
-       if (check_address != offset + count)
-               return ERROR_FLASH_DST_OUT_OF_BANK;
-
-       DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);
-       
-       scanbuf = calloc(CEIL(64, 8), 1);
-       
-       DEBUG("ISC_PROGRAM");
-       
-       for (i = first_sector; i <= last_sector; i++)
-       {
-               str9xpec_set_address(bank, str9xpec_info->sector_bits[i]);
-               
-               dwords_remaining = dwords_remaining < (bank->sectors[i].size/8) ? dwords_remaining : (bank->sectors[i].size/8);
-
-               while (dwords_remaining > 0)
-               {       
-                       str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);
-                       
-                       field.device = chain_pos;
-                       field.num_bits = 64;
-                       field.out_value = (buffer + bytes_written);
-                       field.out_mask = NULL;
-                       field.in_value = NULL;
-                       field.in_check_value = NULL;
-                       field.in_check_mask = NULL;
-                       field.in_handler = NULL;
-                       field.in_handler_priv = NULL;
-                       
-                       jtag_add_dr_scan(1, &field, TAP_RTI, NULL);
-                       
-                       /* small delay before polling */
-                       jtag_add_sleep(50);
-                       
-                       str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);
-                       
-                       do {
-                               field.device = chain_pos;
-                               field.num_bits = 8;
-                               field.out_value = NULL;
-                               field.out_mask = NULL;
-                               field.in_value = scanbuf;
-                               field.in_check_value = NULL;
-                               field.in_check_mask = NULL;
-                               field.in_handler = NULL;
-                               field.in_handler_priv = NULL;
-                               
-                               jtag_add_dr_scan(1, &field, -1, NULL);
-                               jtag_execute_queue();
-                               
-                               status = buf_get_u32(scanbuf, 0, 8);
-                               
-                       } while(!(status & ISC_STATUS_BUSY));
-                       
-                       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-                               return ERROR_FLASH_OPERATION_FAILED;
-                       
-                       //if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)
-                       //      return ERROR_FLASH_OPERATION_FAILED;
-               
-                       dwords_remaining--;
-                       bytes_written += 8;
-               }
-       }
-       
-       if (bytes_remaining)
-       {
-               u8 last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-               int i = 0;
-                               
-               while(bytes_remaining > 0)
-               {
-                       last_dword[i++] = *(buffer + bytes_written); 
-                       bytes_remaining--;
-                       bytes_written++;
-               }
-               
-               str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);
-               
-               field.device = chain_pos;
-               field.num_bits = 64;
-               field.out_value = last_dword;
-               field.out_mask = NULL;
-               field.in_value = NULL;
-               field.in_check_value = NULL;
-               field.in_check_mask = NULL;
-               field.in_handler = NULL;
-               field.in_handler_priv = NULL;
-               
-               jtag_add_dr_scan(1, &field, TAP_RTI, NULL);
-               
-               /* small delay before polling */
-               jtag_add_sleep(50);
-               
-               str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);
-               
-               do {
-                       field.device = chain_pos;
-                       field.num_bits = 8;
-                       field.out_value = NULL;
-                       field.out_mask = NULL;
-                       field.in_value = scanbuf;
-                       field.in_check_value = NULL;
-                       field.in_check_mask = NULL;
-                       field.in_handler = NULL;
-                       field.in_handler_priv = NULL;
-                       
-                       jtag_add_dr_scan(1, &field, -1, NULL);
-                       jtag_execute_queue();
-                       
-                       status = buf_get_u32(scanbuf, 0, 8);
-                       
-               } while(!(status & ISC_STATUS_BUSY));
-               
-               if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-                       return ERROR_FLASH_OPERATION_FAILED;
-               
-               //if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)
-               //      return ERROR_FLASH_OPERATION_FAILED;
-       }
-
-       free(scanbuf);
-
-       str9xpec_isc_disable(bank);
-                               
-       return ERROR_OK;
-}
-
-int str9xpec_probe(struct flash_bank_s *bank)
-{
-       return ERROR_OK;
-}
-
-int str9xpec_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-       flash_bank_t *bank;
-       scan_field_t field;
-       u8 *buffer = NULL;
-       u32 chain_pos;
-       u32 idcode;
-       str9xpec_flash_controller_t *str9xpec_info = NULL;
-
-       if (argc < 1)
-       {
-               command_print(cmd_ctx, "usage: str9xpec part_id <num>");
-               return ERROR_OK;
-       }
-       
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-       if (!bank)
-       {
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-               return ERROR_OK;
-       }
-       
-       str9xpec_info = bank->driver_priv;
-       chain_pos = str9xpec_info->chain_pos;
-       
-       buffer = calloc(CEIL(32, 8), 1);
-       
-       str9xpec_set_instr(chain_pos, ISC_IDCODE, TAP_PI);
-       
-       field.device = chain_pos;
-       field.num_bits = 32;
-       field.out_value = NULL;
-       field.out_mask = NULL;
-       field.in_value = buffer;
-       field.in_check_value = NULL;
-       field.in_check_mask = NULL;
-       field.in_handler = NULL;
-       field.in_handler_priv = NULL;
-       
-       jtag_add_dr_scan(1, &field, TAP_RTI, NULL);
-       jtag_execute_queue();
-       
-       idcode = buf_get_u32(buffer, 0, 32);
-       
-       command_print(cmd_ctx, "str9xpec part id: 0x%8.8x", idcode);
-       
-       free(buffer);
-       
-       return ERROR_OK;
-}
-
-int str9xpec_erase_check(struct flash_bank_s *bank)
-{
-       return str9xpec_blank_check(bank, 0, bank->num_sectors - 1);
-}
-
-int str9xpec_info(struct flash_bank_s *bank, char *buf, int buf_size)
-{
-       snprintf(buf, buf_size, "str9xpec flash driver info" );
-       return ERROR_OK;
-}
-
-int str9xpec_handle_flash_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-       flash_bank_t *bank;
-       u8 status;
-       str9xpec_flash_controller_t *str9xpec_info = NULL;
-       
-       if (argc < 1)
-       {
-               command_print(cmd_ctx, "str9xpec options_read <bank>");
-               return ERROR_OK;        
-       }
-       
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-       if (!bank)
-       {
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-               return ERROR_OK;
-       }
-       
-       str9xpec_info = bank->driver_priv;
-       
-       status = str9xpec_read_config(bank);
-       
-       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-               return ERROR_FLASH_OPERATION_FAILED;
-       
-       /* boot bank */
-       if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1))
-               command_print(cmd_ctx, "CS Map: bank1");
-       else
-               command_print(cmd_ctx, "CS Map: bank0");
-       
-       /* OTP lock */
-       if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_OTPBIT, 1))
-               command_print(cmd_ctx, "OTP Lock: OTP Locked");
-       else
-               command_print(cmd_ctx, "OTP Lock: OTP Unlocked");
-       
-       /* LVD Threshold */
-       if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1))
-               command_print(cmd_ctx, "LVD Threshold: 2.7v");
-       else
-               command_print(cmd_ctx, "LVD Threshold: 2.4v");
-       
-       /* LVD reset warning */
-       if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1))
-               command_print(cmd_ctx, "LVD Reset Warning: VDD or VDDQ Inputs");
-       else
-               command_print(cmd_ctx, "LVD Reset Warning: VDD Input Only");
-       
-       /* LVD reset select */
-       if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1))
-               command_print(cmd_ctx, "LVD Reset Selection: VDD or VDDQ Inputs");
-       else
-               command_print(cmd_ctx, "LVD Reset Selection: VDD Input Only");
-       
-       return ERROR_OK;
-}
-
-int str9xpec_write_options(struct flash_bank_s *bank)
-{
-       scan_field_t field;
-       u8 status;
-       u32 chain_pos;
-       str9xpec_flash_controller_t *str9xpec_info = NULL;
-       
-       str9xpec_info = bank->driver_priv;
-       chain_pos = str9xpec_info->chain_pos;
-       
-       /* erase config options first */
-       status = str9xpec_erase_area( bank, 0xFE, 0xFE );
-       
-       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-               return status; 
-       
-       if (!str9xpec_info->isc_enable) {
-               str9xpec_isc_enable( bank );
-       }
-       
-       if (!str9xpec_info->isc_enable) {
-               return ISC_STATUS_ERROR;
-       }
-       
-       /* according to data 64th bit has to be set */
-       buf_set_u32(str9xpec_info->options, 63, 1, 1);
-       
-       /* set option byte address */
-       str9xpec_set_address(bank, 0x50);
-       
-       /* execute ISC_PROGRAM command */
-       str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);
-               
-       field.device = chain_pos;
-       field.num_bits = 64;
-       field.out_value = str9xpec_info->options;
-       field.out_mask = NULL;
-       field.in_value = NULL;
-       field.in_check_value = NULL;
-       field.in_check_mask = NULL;
-       field.in_handler = NULL;
-       field.in_handler_priv = NULL;
-       
-       jtag_add_dr_scan(1, &field, TAP_RTI, NULL);
-       
-       /* small delay before polling */
-       jtag_add_sleep(50);
-       
-       str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);
-       
-       do {
-               field.device = chain_pos;
-               field.num_bits = 8;
-               field.out_value = NULL;
-               field.out_mask = NULL;
-               field.in_value = &status;
-               field.in_check_value = NULL;
-               field.in_check_mask = NULL;
-               field.in_handler = NULL;
-               field.in_handler_priv = NULL;
-               
-               jtag_add_dr_scan(1, &field, -1, NULL);
-               jtag_execute_queue();
-               
-       } while(!(status & ISC_STATUS_BUSY));
-       
-       str9xpec_isc_disable(bank);
-       
-       return status;
-}
-
-int str9xpec_handle_flash_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-       flash_bank_t *bank;
-       u8 status;
-       
-       if (argc < 1)
-       {
-               command_print(cmd_ctx, "str9xpec options_write <bank>");
-               return ERROR_OK;        
-       }
-       
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-       if (!bank)
-       {
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-               return ERROR_OK;
-       }
-       
-       status = str9xpec_write_options(bank);
-       
-       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-               return ERROR_FLASH_OPERATION_FAILED;
-       
-       return ERROR_OK;
-}
-
-int str9xpec_handle_flash_options_cmap_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-       flash_bank_t *bank;
-       str9xpec_flash_controller_t *str9xpec_info = NULL;
-       
-       if (argc < 2)
-       {
-               command_print(cmd_ctx, "str9xpec options_cmap <bank> <bank0|bank1>");
-               return ERROR_OK;        
-       }
-       
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-       if (!bank)
-       {
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-               return ERROR_OK;
-       }
-       
-       str9xpec_info = bank->driver_priv;
-       
-       if (strcmp(args[1], "bank1") == 0)
-       {
-               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 1);
-       }
-       else
-       {
-               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 0);
-       }
-       
-       return ERROR_OK;
-}
-
-int str9xpec_handle_flash_options_lvdthd_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-       flash_bank_t *bank;
-       str9xpec_flash_controller_t *str9xpec_info = NULL;
-       
-       if (argc < 2)
-       {
-               command_print(cmd_ctx, "str9xpec options_lvdthd <bank> <2.4v|2.7v>");
-               return ERROR_OK;        
-       }
-       
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-       if (!bank)
-       {
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-               return ERROR_OK;
-       }
-       
-       str9xpec_info = bank->driver_priv;
-       
-       if (strcmp(args[1], "2.7v") == 0)
-       {
-               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 1);
-       }
-       else
-       {
-               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 0);
-       }
-       
-       return ERROR_OK;
-}
-
-int str9xpec_handle_flash_options_lvdsel_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-       flash_bank_t *bank;
-       str9xpec_flash_controller_t *str9xpec_info = NULL;
-       
-       if (argc < 2)
-       {
-               command_print(cmd_ctx, "str9xpec options_lvdsel <bank> <vdd|vdd_vddq>");
-               return ERROR_OK;        
-       }
-       
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-       if (!bank)
-       {
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-               return ERROR_OK;
-       }
-       
-       str9xpec_info = bank->driver_priv;
-       
-       if (strcmp(args[1], "vdd_vddq") == 0)
-       {
-               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 1);
-       }
-       else
-       {
-               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 0);
-       }
-       
-       return ERROR_OK;
-}
-
-int str9xpec_handle_flash_options_lvdwarn_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-       flash_bank_t *bank;
-       str9xpec_flash_controller_t *str9xpec_info = NULL;
-       
-       if (argc < 2)
-       {
-               command_print(cmd_ctx, "str9xpec options_lvdwarn <bank> <vdd|vdd_vddq>");
-               return ERROR_OK;        
-       }
-       
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-       if (!bank)
-       {
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-               return ERROR_OK;
-       }
-       
-       str9xpec_info = bank->driver_priv;
-       
-       if (strcmp(args[1], "vdd_vddq") == 0)
-       {
-               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 1);
-       }
-       else
-       {
-               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 0);
-       }
-       
-       return ERROR_OK;
-}
-
-int str9xpec_handle_flash_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-       u8 status;
-       flash_bank_t *bank;
-       
-       if (argc < 1)
-       {
-               command_print(cmd_ctx, "str9xpec lock <bank>");
-               return ERROR_OK;        
-       }
-       
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-       if (!bank)
-       {
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-               return ERROR_OK;
-       }
-       
-       status = str9xpec_lock_device(bank);
-       
-       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-               return ERROR_FLASH_OPERATION_FAILED;
-       
-       return ERROR_OK;
-}
-
-int str9xpec_handle_flash_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-       u8 status;
-       flash_bank_t *bank;
-       
-       if (argc < 1)
-       {
-               command_print(cmd_ctx, "str9xpec unlock <bank>");
-               return ERROR_OK;        
-       }
-       
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-       if (!bank)
-       {
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-               return ERROR_OK;
-       }
-       
-       status = str9xpec_unlock_device(bank);
-       
-       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-               return ERROR_FLASH_OPERATION_FAILED;
-       
-       return ERROR_OK;
-}
-
-int str9xpec_handle_flash_enable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-       flash_bank_t *bank;
-       u32 chain_pos;
-       jtag_device_t* dev0;
-       jtag_device_t* dev2;
-       str9xpec_flash_controller_t *str9xpec_info = NULL;
-       
-       if (argc < 1)
-       {
-               command_print(cmd_ctx, "str9xpec enable_turbo <bank>");
-               return ERROR_OK;        
-       }
-       
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-       if (!bank)
-       {
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-               return ERROR_OK;
-       }
-       
-       str9xpec_info = bank->driver_priv;
-       
-       chain_pos = str9xpec_info->chain_pos;
-       
-       /* remove arm core from chain - enter turbo mode */
-       
-       str9xpec_set_instr(chain_pos+2, 0xD, TAP_RTI);
-       jtag_execute_queue();
-       
-       /* modify scan chain - str9 core has been removed */
-       dev0 = jtag_get_device(chain_pos);
-       str9xpec_info->devarm = jtag_get_device(chain_pos+1);
-       dev2 = jtag_get_device(chain_pos+2);
-       dev0->next = dev2;
-       jtag_num_devices--;
-       
-       return ERROR_OK;
-}
-
-int str9xpec_handle_flash_disable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-       flash_bank_t *bank;
-       u32 chain_pos;
-       jtag_device_t* dev0;
-       str9xpec_flash_controller_t *str9xpec_info = NULL;
-       
-       if (argc < 1)
-       {
-               command_print(cmd_ctx, "str9xpec disable_turbo <bank>");
-               return ERROR_OK;        
-       }
-       
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-       if (!bank)
-       {
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-               return ERROR_OK;
-       }
-       
-       str9xpec_info = bank->driver_priv;
-       
-       chain_pos = str9xpec_info->chain_pos;
-       
-       dev0 = jtag_get_device(chain_pos);
-       
-       /* exit turbo mode via TLR */
-       str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_TLR);
-       jtag_execute_queue();
-       
-       /* restore previous scan chain */
-       if( str9xpec_info->devarm ) {
-               dev0->next = str9xpec_info->devarm;
-               jtag_num_devices++;
-               str9xpec_info->devarm = NULL;
-       }
-       
-       return ERROR_OK;
-}
+/***************************************************************************\r
+ *   Copyright (C) 2005 by Dominic Rath                                    *\r
+ *   Dominic.Rath@gmx.de                                                   *\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
+#include "str9xpec.h"\r
+#include "flash.h"\r
+#include "target.h"\r
+#include "log.h"\r
+#include "armv4_5.h"\r
+#include "arm7_9_common.h"\r
+#include "jtag.h"\r
+#include "binarybuffer.h"\r
+\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <unistd.h>\r
+#include <getopt.h>\r
+\r
+str9xpec_mem_layout_t mem_layout_str9pec[] = {\r
+       {0x00000000, 0x10000, 0},\r
+       {0x00010000, 0x10000, 1},\r
+       {0x00020000, 0x10000, 2},\r
+       {0x00030000, 0x10000, 3},\r
+       {0x00040000, 0x10000, 4},\r
+       {0x00050000, 0x10000, 5},\r
+       {0x00060000, 0x10000, 6},\r
+       {0x00070000, 0x10000, 7},\r
+       {0x00080000, 0x02000, 32},\r
+       {0x00082000, 0x02000, 33},\r
+       {0x00084000, 0x02000, 34},\r
+       {0x00086000, 0x02000, 35}\r
+};\r
+\r
+int str9xpec_register_commands(struct command_context_s *cmd_ctx);\r
+int str9xpec_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);\r
+int str9xpec_erase(struct flash_bank_s *bank, int first, int last);\r
+int str9xpec_protect(struct flash_bank_s *bank, int set, int first, int last);\r
+int str9xpec_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);\r
+int str9xpec_probe(struct flash_bank_s *bank);\r
+int str9xpec_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
+int str9xpec_protect_check(struct flash_bank_s *bank);\r
+int str9xpec_erase_check(struct flash_bank_s *bank);\r
+int str9xpec_info(struct flash_bank_s *bank, char *buf, int buf_size);\r
+\r
+int str9xpec_erase_area(struct flash_bank_s *bank, int first, int last);\r
+int str9xpec_set_address(struct flash_bank_s *bank, u8 sector);\r
+int str9xpec_write_options(struct flash_bank_s *bank);\r
+\r
+int str9xpec_handle_flash_options_cmap_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
+int str9xpec_handle_flash_options_lvdthd_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
+int str9xpec_handle_flash_options_lvdsel_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
+int str9xpec_handle_flash_options_lvdwarn_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
+int str9xpec_handle_flash_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
+int str9xpec_handle_flash_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
+int str9xpec_handle_flash_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
+int str9xpec_handle_flash_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
+int str9xpec_handle_flash_enable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
+int str9xpec_handle_flash_disable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
+\r
+flash_driver_t str9xpec_flash =\r
+{\r
+       .name = "str9xpec",\r
+       .register_commands = str9xpec_register_commands,\r
+       .flash_bank_command = str9xpec_flash_bank_command,\r
+       .erase = str9xpec_erase,\r
+       .protect = str9xpec_protect,\r
+       .write = str9xpec_write,\r
+       .probe = str9xpec_probe,\r
+       .auto_probe = str9xpec_probe,\r
+       .erase_check = str9xpec_erase_check,\r
+       .protect_check = str9xpec_protect_check,\r
+       .info = str9xpec_info\r
+};\r
+\r
+int str9xpec_register_commands(struct command_context_s *cmd_ctx)\r
+{\r
+       command_t *str9xpec_cmd = register_command(cmd_ctx, NULL, "str9xpec", NULL, COMMAND_ANY, "str9xpec flash specific commands");\r
+       \r
+       register_command(cmd_ctx, str9xpec_cmd, "enable_turbo", str9xpec_handle_flash_enable_turbo_command, COMMAND_EXEC,\r
+                                        "enable str9xpec turbo mode");\r
+       register_command(cmd_ctx, str9xpec_cmd, "disable_turbo", str9xpec_handle_flash_disable_turbo_command, COMMAND_EXEC,\r
+                                        "disable str9xpec turbo mode");\r
+       register_command(cmd_ctx, str9xpec_cmd, "options_cmap", str9xpec_handle_flash_options_cmap_command, COMMAND_EXEC,\r
+                                        "configure str9xpec boot sector");\r
+       register_command(cmd_ctx, str9xpec_cmd, "options_lvdthd", str9xpec_handle_flash_options_lvdthd_command, COMMAND_EXEC,\r
+                                        "configure str9xpec lvd threshold");\r
+       register_command(cmd_ctx, str9xpec_cmd, "options_lvdsel", str9xpec_handle_flash_options_lvdsel_command, COMMAND_EXEC,\r
+                                        "configure str9xpec lvd selection");\r
+       register_command(cmd_ctx, str9xpec_cmd, "options_lvdwarn", str9xpec_handle_flash_options_lvdwarn_command, COMMAND_EXEC,\r
+                                        "configure str9xpec lvd warning");\r
+       register_command(cmd_ctx, str9xpec_cmd, "options_read", str9xpec_handle_flash_options_read_command, COMMAND_EXEC,\r
+                                        "read str9xpec options");\r
+       register_command(cmd_ctx, str9xpec_cmd, "options_write", str9xpec_handle_flash_options_write_command, COMMAND_EXEC,\r
+                                        "write str9xpec options");\r
+       register_command(cmd_ctx, str9xpec_cmd, "lock", str9xpec_handle_flash_lock_command, COMMAND_EXEC,\r
+                                        "lock str9xpec device");\r
+       register_command(cmd_ctx, str9xpec_cmd, "unlock", str9xpec_handle_flash_unlock_command, COMMAND_EXEC,\r
+                                        "unlock str9xpec device");\r
+       register_command(cmd_ctx, str9xpec_cmd, "part_id", str9xpec_handle_part_id_command, COMMAND_EXEC,\r
+                                        "print part id of str9xpec flash bank <num>");\r
+       \r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_set_instr(int chain_pos, u32 new_instr, enum tap_state end_state)\r
+{\r
+       jtag_device_t *device = jtag_get_device(chain_pos);\r
+       \r
+       if (device == NULL)\r
+       {\r
+               DEBUG("Invalid Target");\r
+               return ERROR_TARGET_INVALID;\r
+       }\r
+               \r
+       if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)\r
+       {\r
+               scan_field_t field;\r
+                               \r
+               field.device = chain_pos;\r
+               field.num_bits = device->ir_length;\r
+               field.out_value = calloc(CEIL(field.num_bits, 8), 1);\r
+               buf_set_u32(field.out_value, 0, field.num_bits, new_instr);\r
+               field.out_mask = NULL;\r
+               field.in_value = NULL;\r
+               field.in_check_value = NULL;\r
+               field.in_check_mask = NULL;\r
+               field.in_handler = NULL;\r
+               field.in_handler_priv = NULL;\r
+               \r
+               jtag_add_ir_scan(1, &field, end_state, NULL);\r
+               \r
+               free(field.out_value);\r
+       }\r
+       \r
+       return ERROR_OK;\r
+}\r
+\r
+u8 str9xpec_isc_status(int chain_pos)\r
+{\r
+       scan_field_t field;\r
+       u8 status;\r
+       \r
+       if (str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI) != ERROR_OK)\r
+               return ISC_STATUS_ERROR;\r
+       \r
+       field.device = chain_pos;\r
+       field.num_bits = 8;\r
+       field.out_value = NULL;\r
+       field.out_mask = NULL;\r
+       field.in_value = &status;\r
+       field.in_check_value = NULL;\r
+       field.in_check_mask = NULL;\r
+       field.in_handler = NULL;\r
+       field.in_handler_priv = NULL;\r
+       \r
+       jtag_add_dr_scan(1, &field, TAP_RTI, NULL);\r
+       jtag_execute_queue();\r
+       \r
+       DEBUG("status: 0x%2.2x", status);\r
+       \r
+       if (status & ISC_STATUS_SECURITY)\r
+               INFO("Device Security Bit Set");\r
+       \r
+       return status;\r
+}\r
+\r
+int str9xpec_isc_enable(struct flash_bank_s *bank)\r
+{\r
+       u8 status;\r
+       u32 chain_pos;\r
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
+       \r
+       chain_pos = str9xpec_info->chain_pos;\r
+       \r
+       if (str9xpec_info->isc_enable)\r
+               return ERROR_OK;\r
+       \r
+       /* enter isc mode */\r
+       if (str9xpec_set_instr(chain_pos, ISC_ENABLE, TAP_RTI) != ERROR_OK)\r
+               return ERROR_TARGET_INVALID;\r
+       \r
+       /* check ISC status */\r
+       status = str9xpec_isc_status(chain_pos);\r
+       if (status & ISC_STATUS_MODE)\r
+       {\r
+               /* we have entered isc mode */\r
+               str9xpec_info->isc_enable = 1;\r
+               DEBUG("ISC_MODE Enabled");\r
+       }\r
+       \r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_isc_disable(struct flash_bank_s *bank)\r
+{\r
+       u8 status;\r
+       u32 chain_pos;\r
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
+       \r
+       chain_pos = str9xpec_info->chain_pos;\r
+       \r
+       if (!str9xpec_info->isc_enable)\r
+               return ERROR_OK;\r
+       \r
+       if (str9xpec_set_instr(chain_pos, ISC_DISABLE, TAP_RTI) != ERROR_OK)\r
+               return ERROR_TARGET_INVALID;\r
+       \r
+       /* delay to handle aborts */\r
+       jtag_add_sleep(50);\r
+       \r
+       /* check ISC status */\r
+       status = str9xpec_isc_status(chain_pos);\r
+       if (!(status & ISC_STATUS_MODE))\r
+       {\r
+               /* we have left isc mode */\r
+               str9xpec_info->isc_enable = 0;\r
+               DEBUG("ISC_MODE Disabled");\r
+       }\r
+       \r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_read_config(struct flash_bank_s *bank)\r
+{\r
+       scan_field_t field;\r
+       u8 status;\r
+       u32 chain_pos;\r
+               \r
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
+       \r
+       chain_pos = str9xpec_info->chain_pos;\r
+       \r
+       DEBUG("ISC_CONFIGURATION");\r
+       \r
+       /* execute ISC_CONFIGURATION command */\r
+       str9xpec_set_instr(chain_pos, ISC_CONFIGURATION, TAP_PI);\r
+       \r
+       field.device = chain_pos;\r
+       field.num_bits = 64;\r
+       field.out_value = NULL;\r
+       field.out_mask = NULL;\r
+       field.in_value = str9xpec_info->options;\r
+       field.in_check_value = NULL;\r
+       field.in_check_mask = NULL;\r
+       field.in_handler = NULL;\r
+       field.in_handler_priv = NULL;\r
+       \r
+       jtag_add_dr_scan(1, &field, TAP_RTI, NULL);\r
+       jtag_execute_queue();\r
+       \r
+       status = str9xpec_isc_status(chain_pos);\r
+       \r
+       return status;\r
+}\r
+\r
+int str9xpec_build_block_list(struct flash_bank_s *bank)\r
+{\r
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
+       \r
+       int i;\r
+       int num_sectors = 0, b0_sectors = 0;\r
+               \r
+       switch (bank->size)\r
+       {\r
+               case (256 * 1024):\r
+                       b0_sectors = 4;\r
+                       break;\r
+               case (512 * 1024):\r
+                       b0_sectors = 8;\r
+                       break;\r
+               default:\r
+                       ERROR("BUG: unknown bank->size encountered");\r
+                       exit(-1);\r
+       }\r
+       \r
+       /* include bank 1 sectors */\r
+       num_sectors = b0_sectors + 4;\r
+       bank->size += (32 * 1024);\r
+       \r
+       bank->num_sectors = num_sectors;\r
+       bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);\r
+       str9xpec_info->sector_bits = malloc(sizeof(u32) * num_sectors);\r
+       \r
+       num_sectors = 0;\r
+       \r
+       for (i = 0; i < b0_sectors; i++)\r
+       {\r
+               bank->sectors[num_sectors].offset = mem_layout_str9pec[i].sector_start;\r
+               bank->sectors[num_sectors].size = mem_layout_str9pec[i].sector_size;\r
+               bank->sectors[num_sectors].is_erased = -1;\r
+               bank->sectors[num_sectors].is_protected = 1;\r
+               str9xpec_info->sector_bits[num_sectors++] = mem_layout_str9pec[i].sector_bit;\r
+       }\r
+       \r
+       for (i = 8; i < 12; i++)\r
+       {\r
+               bank->sectors[num_sectors].offset = mem_layout_str9pec[i].sector_start;\r
+               bank->sectors[num_sectors].size = mem_layout_str9pec[i].sector_size;\r
+               bank->sectors[num_sectors].is_erased = -1;\r
+               bank->sectors[num_sectors].is_protected = 1;\r
+               str9xpec_info->sector_bits[num_sectors++] = mem_layout_str9pec[i].sector_bit;\r
+       }\r
+       \r
+       return ERROR_OK;\r
+}\r
+\r
+/* flash bank str9x <base> <size> 0 0 <target#>\r
+ */\r
+int str9xpec_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)\r
+{\r
+       str9xpec_flash_controller_t *str9xpec_info;\r
+       armv4_5_common_t *armv4_5 = NULL;\r
+       arm7_9_common_t *arm7_9 = NULL;\r
+       arm_jtag_t *jtag_info = NULL;\r
+       \r
+       if (argc < 6)\r
+       {\r
+               WARNING("incomplete flash_bank str9x configuration");\r
+               return ERROR_FLASH_BANK_INVALID;\r
+       }\r
+       \r
+       str9xpec_info = malloc(sizeof(str9xpec_flash_controller_t));\r
+       bank->driver_priv = str9xpec_info;\r
+       \r
+       if (bank->base != 0x00000000)\r
+       {\r
+               WARNING("overriding flash base address for STR91x device with 0x00000000");\r
+               bank->base = 0x00000000;\r
+       }\r
+\r
+       /* find out jtag position of flash controller\r
+        * it is always after the arm966 core */\r
+       \r
+       armv4_5 = bank->target->arch_info;\r
+       arm7_9 = armv4_5->arch_info;\r
+       jtag_info = &arm7_9->jtag_info;\r
+       \r
+       str9xpec_info->chain_pos = (jtag_info->chain_pos - 1);\r
+       str9xpec_info->isc_enable = 0;\r
+       str9xpec_info->devarm = NULL;\r
+       \r
+       str9xpec_build_block_list(bank);\r
+       \r
+       /* clear option byte register */\r
+       buf_set_u32(str9xpec_info->options, 0, 64, 0);\r
+       \r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_blank_check(struct flash_bank_s *bank, int first, int last)\r
+{\r
+       scan_field_t field;\r
+       u8 status;\r
+       u32 chain_pos;\r
+       int i;\r
+       u8 *buffer = NULL;\r
+               \r
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
+       \r
+       chain_pos = str9xpec_info->chain_pos;\r
+       \r
+       if (!str9xpec_info->isc_enable) {\r
+               str9xpec_isc_enable( bank );\r
+       }\r
+       \r
+       if (!str9xpec_info->isc_enable) {\r
+               return ERROR_FLASH_OPERATION_FAILED;\r
+       }\r
+       \r
+       buffer = calloc(CEIL(64, 8), 1);\r
+\r
+       DEBUG("blank check: first_bank: %i, last_bank: %i", first, last);\r
+       \r
+       for (i = first; i <= last; i++) {\r
+               buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);\r
+       }\r
+       \r
+       /* execute ISC_BLANK_CHECK command */\r
+       str9xpec_set_instr(chain_pos, ISC_BLANK_CHECK, TAP_PI);\r
+       \r
+       field.device = chain_pos;\r
+       field.num_bits = 64;\r
+       field.out_value = buffer;\r
+       field.out_mask = NULL;\r
+       field.in_value = NULL;\r
+       field.in_check_value = NULL;\r
+       field.in_check_mask = NULL;\r
+       field.in_handler = NULL;\r
+       field.in_handler_priv = NULL;\r
+       \r
+       jtag_add_dr_scan(1, &field, TAP_RTI, NULL);\r
+       jtag_add_sleep(40000);\r
+       \r
+       /* read blank check result */\r
+       field.device = chain_pos;\r
+       field.num_bits = 64;\r
+       field.out_value = NULL;\r
+       field.out_mask = NULL;\r
+       field.in_value = buffer;\r
+       field.in_check_value = NULL;\r
+       field.in_check_mask = NULL;\r
+       field.in_handler = NULL;\r
+       field.in_handler_priv = NULL;\r
+       \r
+       jtag_add_dr_scan(1, &field, TAP_PI, NULL);\r
+       jtag_execute_queue();\r
+       \r
+       status = str9xpec_isc_status(chain_pos);\r
+       \r
+       for (i = first; i <= last; i++)\r
+       {\r
+               if (buf_get_u32(buffer, str9xpec_info->sector_bits[i], 1))\r
+                       bank->sectors[i].is_erased = 0;\r
+               else\r
+                       bank->sectors[i].is_erased = 1;\r
+       }\r
+       \r
+       free(buffer);\r
+       \r
+       str9xpec_isc_disable(bank);\r
+       \r
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
+               return ERROR_FLASH_OPERATION_FAILED; \r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_protect_check(struct flash_bank_s *bank)\r
+{\r
+       u8 status;\r
+       int i;\r
+               \r
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
+       \r
+       status = str9xpec_read_config(bank);\r
+       \r
+       for (i = 0; i < bank->num_sectors; i++)\r
+       {\r
+               if (buf_get_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1))\r
+                       bank->sectors[i].is_protected = 1;\r
+               else\r
+                       bank->sectors[i].is_protected = 0;\r
+       }\r
+       \r
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
+               return ERROR_FLASH_OPERATION_FAILED;\r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_erase_area(struct flash_bank_s *bank, int first, int last)\r
+{\r
+       scan_field_t field;\r
+       u8 status;\r
+       u32 chain_pos;\r
+       int i;\r
+       u8 *buffer = NULL;\r
+       \r
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
+       \r
+       chain_pos = str9xpec_info->chain_pos;\r
+       \r
+       if (!str9xpec_info->isc_enable) {\r
+               str9xpec_isc_enable( bank );\r
+       }\r
+       \r
+       if (!str9xpec_info->isc_enable) {\r
+               return ISC_STATUS_ERROR;\r
+       }\r
+       \r
+       buffer = calloc(CEIL(64, 8), 1);\r
+       \r
+       DEBUG("erase: first_bank: %i, last_bank: %i", first, last);\r
+       \r
+       /* last bank: 0xFF signals a full erase (unlock complete device) */\r
+       /* last bank: 0xFE signals a option byte erase */\r
+       if (last == 0xFF)\r
+       {\r
+               for (i = 0; i < 64; i++) {\r
+                       buf_set_u32(buffer, i, 1, 1);\r
+               }       \r
+       }\r
+       else if (last == 0xFE)\r
+       {\r
+               buf_set_u32(buffer, 49, 1, 1);\r
+       }\r
+       else\r
+       {       \r
+               for (i = first; i <= last; i++) {\r
+                       buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);\r
+               }\r
+       }\r
+       \r
+       DEBUG("ISC_ERASE");\r
+       \r
+       /* execute ISC_ERASE command */\r
+       str9xpec_set_instr(chain_pos, ISC_ERASE, TAP_PI);\r
+       \r
+       field.device = chain_pos;\r
+       field.num_bits = 64;\r
+       field.out_value = buffer;\r
+       field.out_mask = NULL;\r
+       field.in_value = NULL;\r
+       field.in_check_value = NULL;\r
+       field.in_check_mask = NULL;\r
+       field.in_handler = NULL;\r
+       field.in_handler_priv = NULL;\r
+       \r
+       jtag_add_dr_scan(1, &field, TAP_RTI, NULL);\r
+       jtag_execute_queue();\r
+       \r
+       jtag_add_sleep(10);\r
+       \r
+       /* wait for erase completion */\r
+       while (!((status = str9xpec_isc_status(chain_pos)) & ISC_STATUS_BUSY)) {\r
+               usleep(1000);\r
+       }\r
+       \r
+       free(buffer);\r
+       \r
+       str9xpec_isc_disable(bank);\r
+       \r
+       return status;\r
+}\r
+\r
+int str9xpec_erase(struct flash_bank_s *bank, int first, int last)\r
+{\r
+       int status;\r
+       \r
+       status = str9xpec_erase_area(bank, first, last);\r
+       \r
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
+               return ERROR_FLASH_OPERATION_FAILED;\r
+       \r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_lock_device(struct flash_bank_s *bank)\r
+{\r
+       scan_field_t field;\r
+       u8 status;\r
+       u32 chain_pos;\r
+       str9xpec_flash_controller_t *str9xpec_info = NULL;\r
+       \r
+       str9xpec_info = bank->driver_priv;\r
+       chain_pos = str9xpec_info->chain_pos;\r
+       \r
+       if (!str9xpec_info->isc_enable) {\r
+               str9xpec_isc_enable( bank );\r
+       }\r
+       \r
+       if (!str9xpec_info->isc_enable) {\r
+               return ISC_STATUS_ERROR;\r
+       }\r
+       \r
+       /* set security address */\r
+       str9xpec_set_address(bank, 0x80);\r
+       \r
+       /* execute ISC_PROGRAM command */\r
+       str9xpec_set_instr(chain_pos, ISC_PROGRAM_SECURITY, TAP_RTI);\r
+       \r
+       str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);\r
+       \r
+       do {\r
+               field.device = chain_pos;\r
+               field.num_bits = 8;\r
+               field.out_value = NULL;\r
+               field.out_mask = NULL;\r
+               field.in_value = &status;\r
+               field.in_check_value = NULL;\r
+               field.in_check_mask = NULL;\r
+               field.in_handler = NULL;\r
+               field.in_handler_priv = NULL;\r
+               \r
+               jtag_add_dr_scan(1, &field, -1, NULL);\r
+               jtag_execute_queue();\r
+               \r
+       } while(!(status & ISC_STATUS_BUSY));\r
+       \r
+       str9xpec_isc_disable(bank);\r
+       \r
+       return status;\r
+}\r
+\r
+int str9xpec_unlock_device(struct flash_bank_s *bank)\r
+{\r
+       u8 status;\r
+       \r
+       status = str9xpec_erase_area(bank, 0, 255);\r
+       \r
+       return status;\r
+}\r
+\r
+int str9xpec_protect(struct flash_bank_s *bank, int set, int first, int last)\r
+{\r
+       u8 status;\r
+       int i;\r
+       \r
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
+       \r
+       status = str9xpec_read_config(bank);\r
+       \r
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
+               return ERROR_FLASH_OPERATION_FAILED;\r
+\r
+       DEBUG("protect: first_bank: %i, last_bank: %i", first, last);\r
+       \r
+       /* last bank: 0xFF signals a full device protect */\r
+       if (last == 0xFF)\r
+       {\r
+               if( set )\r
+               {\r
+                       status = str9xpec_lock_device(bank);\r
+               }\r
+               else\r
+               {\r
+                       /* perform full erase to unlock device */\r
+                       status = str9xpec_unlock_device(bank);\r
+               }\r
+       }\r
+       else\r
+       {       \r
+               for (i = first; i <= last; i++)\r
+               {\r
+                       if( set )\r
+                               buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 1);\r
+                       else\r
+                               buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 0);\r
+               }\r
+               \r
+               status = str9xpec_write_options(bank);\r
+       }\r
+       \r
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
+               return ERROR_FLASH_OPERATION_FAILED;\r
+       \r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_set_address(struct flash_bank_s *bank, u8 sector)\r
+{\r
+       u32 chain_pos;\r
+       scan_field_t field;\r
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
+       \r
+       chain_pos = str9xpec_info->chain_pos;\r
+       \r
+       /* set flash controller address */\r
+       str9xpec_set_instr(chain_pos, ISC_ADDRESS_SHIFT, TAP_PI);\r
+       \r
+       field.device = chain_pos;\r
+       field.num_bits = 8;\r
+       field.out_value = &sector;\r
+       field.out_mask = NULL;\r
+       field.in_value = NULL;\r
+       field.in_check_value = NULL;\r
+       field.in_check_mask = NULL;\r
+       field.in_handler = NULL;\r
+       field.in_handler_priv = NULL;\r
+       \r
+       jtag_add_dr_scan(1, &field, -1, NULL);\r
+               \r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)\r
+{\r
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
+       u32 dwords_remaining = (count / 8);\r
+       u32 bytes_remaining = (count & 0x00000007);\r
+       u32 bytes_written = 0;\r
+       u8 status;\r
+       u32 check_address = offset;\r
+       u32 chain_pos;\r
+       scan_field_t field;\r
+       u8 *scanbuf;\r
+       int i;\r
+       u32 first_sector = 0;\r
+       u32 last_sector = 0;\r
+       \r
+       chain_pos = str9xpec_info->chain_pos;\r
+       \r
+       if (!str9xpec_info->isc_enable) {\r
+               str9xpec_isc_enable(bank);\r
+       }\r
+       \r
+       if (!str9xpec_info->isc_enable) {\r
+               return ERROR_FLASH_OPERATION_FAILED;\r
+       }\r
+       \r
+       if (offset & 0x7)\r
+       {\r
+               WARNING("offset 0x%x breaks required 8-byte alignment", offset);\r
+               return ERROR_FLASH_DST_BREAKS_ALIGNMENT;\r
+       }\r
+       \r
+       for (i = 0; i < bank->num_sectors; i++)\r
+       {\r
+               u32 sec_start = bank->sectors[i].offset;\r
+               u32 sec_end = sec_start + bank->sectors[i].size;\r
+               \r
+               /* check if destination falls within the current sector */\r
+               if ((check_address >= sec_start) && (check_address < sec_end))\r
+               {\r
+                       /* check if destination ends in the current sector */\r
+                       if (offset + count < sec_end)\r
+                               check_address = offset + count;\r
+                       else\r
+                               check_address = sec_end;\r
+               }\r
+               \r
+               if ((offset >= sec_start) && (offset < sec_end)){\r
+                       first_sector = i;\r
+               }\r
+               \r
+               if ((offset + count >= sec_start) && (offset + count < sec_end)){\r
+                       last_sector = i;\r
+               }\r
+       }\r
+       \r
+       if (check_address != offset + count)\r
+               return ERROR_FLASH_DST_OUT_OF_BANK;\r
+\r
+       DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);\r
+       \r
+       scanbuf = calloc(CEIL(64, 8), 1);\r
+       \r
+       DEBUG("ISC_PROGRAM");\r
+       \r
+       for (i = first_sector; i <= last_sector; i++)\r
+       {\r
+               str9xpec_set_address(bank, str9xpec_info->sector_bits[i]);\r
+               \r
+               dwords_remaining = dwords_remaining < (bank->sectors[i].size/8) ? dwords_remaining : (bank->sectors[i].size/8);\r
+\r
+               while (dwords_remaining > 0)\r
+               {       \r
+                       str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);\r
+                       \r
+                       field.device = chain_pos;\r
+                       field.num_bits = 64;\r
+                       field.out_value = (buffer + bytes_written);\r
+                       field.out_mask = NULL;\r
+                       field.in_value = NULL;\r
+                       field.in_check_value = NULL;\r
+                       field.in_check_mask = NULL;\r
+                       field.in_handler = NULL;\r
+                       field.in_handler_priv = NULL;\r
+                       \r
+                       jtag_add_dr_scan(1, &field, TAP_RTI, NULL);\r
+                       \r
+                       /* small delay before polling */\r
+                       jtag_add_sleep(50);\r
+                       \r
+                       str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);\r
+                       \r
+                       do {\r
+                               field.device = chain_pos;\r
+                               field.num_bits = 8;\r
+                               field.out_value = NULL;\r
+                               field.out_mask = NULL;\r
+                               field.in_value = scanbuf;\r
+                               field.in_check_value = NULL;\r
+                               field.in_check_mask = NULL;\r
+                               field.in_handler = NULL;\r
+                               field.in_handler_priv = NULL;\r
+                               \r
+                               jtag_add_dr_scan(1, &field, -1, NULL);\r
+                               jtag_execute_queue();\r
+                               \r
+                               status = buf_get_u32(scanbuf, 0, 8);\r
+                               \r
+                       } while(!(status & ISC_STATUS_BUSY));\r
+                       \r
+                       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
+                               return ERROR_FLASH_OPERATION_FAILED;\r
+                       \r
+                       //if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)\r
+                       //      return ERROR_FLASH_OPERATION_FAILED;\r
+               \r
+                       dwords_remaining--;\r
+                       bytes_written += 8;\r
+               }\r
+       }\r
+       \r
+       if (bytes_remaining)\r
+       {\r
+               u8 last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};\r
+               int i = 0;\r
+                               \r
+               while(bytes_remaining > 0)\r
+               {\r
+                       last_dword[i++] = *(buffer + bytes_written); \r
+                       bytes_remaining--;\r
+                       bytes_written++;\r
+               }\r
+               \r
+               str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);\r
+               \r
+               field.device = chain_pos;\r
+               field.num_bits = 64;\r
+               field.out_value = last_dword;\r
+               field.out_mask = NULL;\r
+               field.in_value = NULL;\r
+               field.in_check_value = NULL;\r
+               field.in_check_mask = NULL;\r
+               field.in_handler = NULL;\r
+               field.in_handler_priv = NULL;\r
+               \r
+               jtag_add_dr_scan(1, &field, TAP_RTI, NULL);\r
+               \r
+               /* small delay before polling */\r
+               jtag_add_sleep(50);\r
+               \r
+               str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);\r
+               \r
+               do {\r
+                       field.device = chain_pos;\r
+                       field.num_bits = 8;\r
+                       field.out_value = NULL;\r
+                       field.out_mask = NULL;\r
+                       field.in_value = scanbuf;\r
+                       field.in_check_value = NULL;\r
+                       field.in_check_mask = NULL;\r
+                       field.in_handler = NULL;\r
+                       field.in_handler_priv = NULL;\r
+                       \r
+                       jtag_add_dr_scan(1, &field, -1, NULL);\r
+                       jtag_execute_queue();\r
+                       \r
+                       status = buf_get_u32(scanbuf, 0, 8);\r
+                       \r
+               } while(!(status & ISC_STATUS_BUSY));\r
+               \r
+               if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
+                       return ERROR_FLASH_OPERATION_FAILED;\r
+               \r
+               //if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)\r
+               //      return ERROR_FLASH_OPERATION_FAILED;\r
+       }\r
+\r
+       free(scanbuf);\r
+\r
+       str9xpec_isc_disable(bank);\r
+                               \r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_probe(struct flash_bank_s *bank)\r
+{\r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       flash_bank_t *bank;\r
+       scan_field_t field;\r
+       u8 *buffer = NULL;\r
+       u32 chain_pos;\r
+       u32 idcode;\r
+       str9xpec_flash_controller_t *str9xpec_info = NULL;\r
+\r
+       if (argc < 1)\r
+       {\r
+               return ERROR_COMMAND_SYNTAX_ERROR;\r
+       }\r
+       \r
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
+       if (!bank)\r
+       {\r
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
+               return ERROR_OK;\r
+       }\r
+       \r
+       str9xpec_info = bank->driver_priv;\r
+       chain_pos = str9xpec_info->chain_pos;\r
+       \r
+       buffer = calloc(CEIL(32, 8), 1);\r
+       \r
+       str9xpec_set_instr(chain_pos, ISC_IDCODE, TAP_PI);\r
+       \r
+       field.device = chain_pos;\r
+       field.num_bits = 32;\r
+       field.out_value = NULL;\r
+       field.out_mask = NULL;\r
+       field.in_value = buffer;\r
+       field.in_check_value = NULL;\r
+       field.in_check_mask = NULL;\r
+       field.in_handler = NULL;\r
+       field.in_handler_priv = NULL;\r
+       \r
+       jtag_add_dr_scan(1, &field, TAP_RTI, NULL);\r
+       jtag_execute_queue();\r
+       \r
+       idcode = buf_get_u32(buffer, 0, 32);\r
+       \r
+       command_print(cmd_ctx, "str9xpec part id: 0x%8.8x", idcode);\r
+       \r
+       free(buffer);\r
+       \r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_erase_check(struct flash_bank_s *bank)\r
+{\r
+       return str9xpec_blank_check(bank, 0, bank->num_sectors - 1);\r
+}\r
+\r
+int str9xpec_info(struct flash_bank_s *bank, char *buf, int buf_size)\r
+{\r
+       snprintf(buf, buf_size, "str9xpec flash driver info" );\r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_handle_flash_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       flash_bank_t *bank;\r
+       u8 status;\r
+       str9xpec_flash_controller_t *str9xpec_info = NULL;\r
+       \r
+       if (argc < 1)\r
+       {\r
+               command_print(cmd_ctx, "str9xpec options_read <bank>");\r
+               return ERROR_OK;        \r
+       }\r
+       \r
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
+       if (!bank)\r
+       {\r
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
+               return ERROR_OK;\r
+       }\r
+       \r
+       str9xpec_info = bank->driver_priv;\r
+       \r
+       status = str9xpec_read_config(bank);\r
+       \r
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
+               return ERROR_FLASH_OPERATION_FAILED;\r
+       \r
+       /* boot bank */\r
+       if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1))\r
+               command_print(cmd_ctx, "CS Map: bank1");\r
+       else\r
+               command_print(cmd_ctx, "CS Map: bank0");\r
+       \r
+       /* OTP lock */\r
+       if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_OTPBIT, 1))\r
+               command_print(cmd_ctx, "OTP Lock: OTP Locked");\r
+       else\r
+               command_print(cmd_ctx, "OTP Lock: OTP Unlocked");\r
+       \r
+       /* LVD Threshold */\r
+       if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1))\r
+               command_print(cmd_ctx, "LVD Threshold: 2.7v");\r
+       else\r
+               command_print(cmd_ctx, "LVD Threshold: 2.4v");\r
+       \r
+       /* LVD reset warning */\r
+       if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1))\r
+               command_print(cmd_ctx, "LVD Reset Warning: VDD or VDDQ Inputs");\r
+       else\r
+               command_print(cmd_ctx, "LVD Reset Warning: VDD Input Only");\r
+       \r
+       /* LVD reset select */\r
+       if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1))\r
+               command_print(cmd_ctx, "LVD Reset Selection: VDD or VDDQ Inputs");\r
+       else\r
+               command_print(cmd_ctx, "LVD Reset Selection: VDD Input Only");\r
+       \r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_write_options(struct flash_bank_s *bank)\r
+{\r
+       scan_field_t field;\r
+       u8 status;\r
+       u32 chain_pos;\r
+       str9xpec_flash_controller_t *str9xpec_info = NULL;\r
+       \r
+       str9xpec_info = bank->driver_priv;\r
+       chain_pos = str9xpec_info->chain_pos;\r
+       \r
+       /* erase config options first */\r
+       status = str9xpec_erase_area( bank, 0xFE, 0xFE );\r
+       \r
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
+               return status; \r
+       \r
+       if (!str9xpec_info->isc_enable) {\r
+               str9xpec_isc_enable( bank );\r
+       }\r
+       \r
+       if (!str9xpec_info->isc_enable) {\r
+               return ISC_STATUS_ERROR;\r
+       }\r
+       \r
+       /* according to data 64th bit has to be set */\r
+       buf_set_u32(str9xpec_info->options, 63, 1, 1);\r
+       \r
+       /* set option byte address */\r
+       str9xpec_set_address(bank, 0x50);\r
+       \r
+       /* execute ISC_PROGRAM command */\r
+       str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);\r
+               \r
+       field.device = chain_pos;\r
+       field.num_bits = 64;\r
+       field.out_value = str9xpec_info->options;\r
+       field.out_mask = NULL;\r
+       field.in_value = NULL;\r
+       field.in_check_value = NULL;\r
+       field.in_check_mask = NULL;\r
+       field.in_handler = NULL;\r
+       field.in_handler_priv = NULL;\r
+       \r
+       jtag_add_dr_scan(1, &field, TAP_RTI, NULL);\r
+       \r
+       /* small delay before polling */\r
+       jtag_add_sleep(50);\r
+       \r
+       str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);\r
+       \r
+       do {\r
+               field.device = chain_pos;\r
+               field.num_bits = 8;\r
+               field.out_value = NULL;\r
+               field.out_mask = NULL;\r
+               field.in_value = &status;\r
+               field.in_check_value = NULL;\r
+               field.in_check_mask = NULL;\r
+               field.in_handler = NULL;\r
+               field.in_handler_priv = NULL;\r
+               \r
+               jtag_add_dr_scan(1, &field, -1, NULL);\r
+               jtag_execute_queue();\r
+               \r
+       } while(!(status & ISC_STATUS_BUSY));\r
+       \r
+       str9xpec_isc_disable(bank);\r
+       \r
+       return status;\r
+}\r
+\r
+int str9xpec_handle_flash_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       flash_bank_t *bank;\r
+       u8 status;\r
+       \r
+       if (argc < 1)\r
+       {\r
+               command_print(cmd_ctx, "str9xpec options_write <bank>");\r
+               return ERROR_OK;        \r
+       }\r
+       \r
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
+       if (!bank)\r
+       {\r
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
+               return ERROR_OK;\r
+       }\r
+       \r
+       status = str9xpec_write_options(bank);\r
+       \r
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
+               return ERROR_FLASH_OPERATION_FAILED;\r
+       \r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_handle_flash_options_cmap_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       flash_bank_t *bank;\r
+       str9xpec_flash_controller_t *str9xpec_info = NULL;\r
+       \r
+       if (argc < 2)\r
+       {\r
+               command_print(cmd_ctx, "str9xpec options_cmap <bank> <bank0|bank1>");\r
+               return ERROR_OK;        \r
+       }\r
+       \r
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
+       if (!bank)\r
+       {\r
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
+               return ERROR_OK;\r
+       }\r
+       \r
+       str9xpec_info = bank->driver_priv;\r
+       \r
+       if (strcmp(args[1], "bank1") == 0)\r
+       {\r
+               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 1);\r
+       }\r
+       else\r
+       {\r
+               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 0);\r
+       }\r
+       \r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_handle_flash_options_lvdthd_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       flash_bank_t *bank;\r
+       str9xpec_flash_controller_t *str9xpec_info = NULL;\r
+       \r
+       if (argc < 2)\r
+       {\r
+               command_print(cmd_ctx, "str9xpec options_lvdthd <bank> <2.4v|2.7v>");\r
+               return ERROR_OK;        \r
+       }\r
+       \r
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
+       if (!bank)\r
+       {\r
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
+               return ERROR_OK;\r
+       }\r
+       \r
+       str9xpec_info = bank->driver_priv;\r
+       \r
+       if (strcmp(args[1], "2.7v") == 0)\r
+       {\r
+               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 1);\r
+       }\r
+       else\r
+       {\r
+               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 0);\r
+       }\r
+       \r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_handle_flash_options_lvdsel_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       flash_bank_t *bank;\r
+       str9xpec_flash_controller_t *str9xpec_info = NULL;\r
+       \r
+       if (argc < 2)\r
+       {\r
+               command_print(cmd_ctx, "str9xpec options_lvdsel <bank> <vdd|vdd_vddq>");\r
+               return ERROR_OK;        \r
+       }\r
+       \r
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
+       if (!bank)\r
+       {\r
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
+               return ERROR_OK;\r
+       }\r
+       \r
+       str9xpec_info = bank->driver_priv;\r
+       \r
+       if (strcmp(args[1], "vdd_vddq") == 0)\r
+       {\r
+               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 1);\r
+       }\r
+       else\r
+       {\r
+               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 0);\r
+       }\r
+       \r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_handle_flash_options_lvdwarn_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       flash_bank_t *bank;\r
+       str9xpec_flash_controller_t *str9xpec_info = NULL;\r
+       \r
+       if (argc < 2)\r
+       {\r
+               command_print(cmd_ctx, "str9xpec options_lvdwarn <bank> <vdd|vdd_vddq>");\r
+               return ERROR_OK;        \r
+       }\r
+       \r
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
+       if (!bank)\r
+       {\r
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
+               return ERROR_OK;\r
+       }\r
+       \r
+       str9xpec_info = bank->driver_priv;\r
+       \r
+       if (strcmp(args[1], "vdd_vddq") == 0)\r
+       {\r
+               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 1);\r
+       }\r
+       else\r
+       {\r
+               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 0);\r
+       }\r
+       \r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_handle_flash_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       u8 status;\r
+       flash_bank_t *bank;\r
+       \r
+       if (argc < 1)\r
+       {\r
+               command_print(cmd_ctx, "str9xpec lock <bank>");\r
+               return ERROR_OK;        \r
+       }\r
+       \r
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
+       if (!bank)\r
+       {\r
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
+               return ERROR_OK;\r
+       }\r
+       \r
+       status = str9xpec_lock_device(bank);\r
+       \r
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
+               return ERROR_FLASH_OPERATION_FAILED;\r
+       \r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_handle_flash_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       u8 status;\r
+       flash_bank_t *bank;\r
+       \r
+       if (argc < 1)\r
+       {\r
+               command_print(cmd_ctx, "str9xpec unlock <bank>");\r
+               return ERROR_OK;        \r
+       }\r
+       \r
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
+       if (!bank)\r
+       {\r
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
+               return ERROR_OK;\r
+       }\r
+       \r
+       status = str9xpec_unlock_device(bank);\r
+       \r
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
+               return ERROR_FLASH_OPERATION_FAILED;\r
+       \r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_handle_flash_enable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       flash_bank_t *bank;\r
+       u32 chain_pos;\r
+       jtag_device_t* dev0;\r
+       jtag_device_t* dev2;\r
+       str9xpec_flash_controller_t *str9xpec_info = NULL;\r
+       \r
+       if (argc < 1)\r
+       {\r
+               command_print(cmd_ctx, "str9xpec enable_turbo <bank>");\r
+               return ERROR_OK;        \r
+       }\r
+       \r
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
+       if (!bank)\r
+       {\r
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
+               return ERROR_OK;\r
+       }\r
+       \r
+       str9xpec_info = bank->driver_priv;\r
+       \r
+       chain_pos = str9xpec_info->chain_pos;\r
+       \r
+       /* remove arm core from chain - enter turbo mode */\r
+       \r
+       str9xpec_set_instr(chain_pos+2, 0xD, TAP_RTI);\r
+       jtag_execute_queue();\r
+       \r
+       /* modify scan chain - str9 core has been removed */\r
+       dev0 = jtag_get_device(chain_pos);\r
+       str9xpec_info->devarm = jtag_get_device(chain_pos+1);\r
+       dev2 = jtag_get_device(chain_pos+2);\r
+       dev0->next = dev2;\r
+       jtag_num_devices--;\r
+       \r
+       return ERROR_OK;\r
+}\r
+\r
+int str9xpec_handle_flash_disable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       flash_bank_t *bank;\r
+       u32 chain_pos;\r
+       jtag_device_t* dev0;\r
+       str9xpec_flash_controller_t *str9xpec_info = NULL;\r
+       \r
+       if (argc < 1)\r
+       {\r
+               command_print(cmd_ctx, "str9xpec disable_turbo <bank>");\r
+               return ERROR_OK;        \r
+       }\r
+       \r
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
+       if (!bank)\r
+       {\r
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
+               return ERROR_OK;\r
+       }\r
+       \r
+       str9xpec_info = bank->driver_priv;\r
+       \r
+       chain_pos = str9xpec_info->chain_pos;\r
+       \r
+       dev0 = jtag_get_device(chain_pos);\r
+       \r
+       /* exit turbo mode via TLR */\r
+       str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_TLR);\r
+       jtag_execute_queue();\r
+       \r
+       /* restore previous scan chain */\r
+       if( str9xpec_info->devarm ) {\r
+               dev0->next = str9xpec_info->devarm;\r
+               jtag_num_devices++;\r
+               str9xpec_info->devarm = NULL;\r
+       }\r
+       \r
+       return ERROR_OK;\r
+}\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)