use FLASH_BANK_COMMAND_HANDLER macro
[openocd.git] / src / flash / str9xpec.c
index 4d3093eefca25b80b6447395945919899b874559..4056ba7e5c392e1128226c100877262ccf3a4827 100644 (file)
-/***************************************************************************\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
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   Copyright (C) 2008 by Spencer Oliver                                  *
+ *   spen@spen-soft.co.uk                                                  *
+ *                                                                         *
+ *   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 "str9xpec.h"
+#include "arm7_9_common.h"
+
+
+static int str9xpec_erase_area(struct flash_bank_s *bank, int first, int last);
+static int str9xpec_set_address(struct flash_bank_s *bank, uint8_t sector);
+static int str9xpec_write_options(struct flash_bank_s *bank);
+
+int str9xpec_set_instr(jtag_tap_t *tap, uint32_t new_instr, tap_state_t end_state)
+{
+       if (tap == NULL) {
+               return ERROR_TARGET_INVALID;
+       }
+
+       if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr)
+       {
+               scan_field_t field;
+
+               field.tap = tap;
+               field.num_bits = tap->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.in_value = NULL;
+
+               jtag_add_ir_scan(1, &field, end_state);
+
+               free(field.out_value);
+       }
+
+       return ERROR_OK;
+}
+
+static uint8_t str9xpec_isc_status(jtag_tap_t *tap)
+{
+       scan_field_t field;
+       uint8_t status;
+
+       if (str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE) != ERROR_OK)
+               return ISC_STATUS_ERROR;
+
+       field.tap = tap;
+       field.num_bits = 8;
+       field.out_value = NULL;
+       field.in_value = &status;
+
+
+       jtag_add_dr_scan(1, &field, jtag_set_end_state(TAP_IDLE));
+       jtag_execute_queue();
+
+       LOG_DEBUG("status: 0x%2.2x", status);
+
+       if (status & ISC_STATUS_SECURITY)
+               LOG_INFO("Device Security Bit Set");
+
+       return status;
+}
+
+static int str9xpec_isc_enable(struct flash_bank_s *bank)
+{
+       uint8_t status;
+       jtag_tap_t *tap;
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+
+       tap = str9xpec_info->tap;
+
+       if (str9xpec_info->isc_enable)
+               return ERROR_OK;
+
+       /* enter isc mode */
+       if (str9xpec_set_instr(tap, ISC_ENABLE, TAP_IDLE) != ERROR_OK)
+               return ERROR_TARGET_INVALID;
+
+       /* check ISC status */
+       status = str9xpec_isc_status(tap);
+       if (status & ISC_STATUS_MODE)
+       {
+               /* we have entered isc mode */
+               str9xpec_info->isc_enable = 1;
+               LOG_DEBUG("ISC_MODE Enabled");
+       }
+
+       return ERROR_OK;
+}
+
+static int str9xpec_isc_disable(struct flash_bank_s *bank)
+{
+       uint8_t status;
+       jtag_tap_t *tap;
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+
+       tap = str9xpec_info->tap;
+
+       if (!str9xpec_info->isc_enable)
+               return ERROR_OK;
+
+       if (str9xpec_set_instr(tap, ISC_DISABLE, TAP_IDLE) != ERROR_OK)
+               return ERROR_TARGET_INVALID;
+
+       /* delay to handle aborts */
+       jtag_add_sleep(50);
+
+       /* check ISC status */
+       status = str9xpec_isc_status(tap);
+       if (!(status & ISC_STATUS_MODE))
+       {
+               /* we have left isc mode */
+               str9xpec_info->isc_enable = 0;
+               LOG_DEBUG("ISC_MODE Disabled");
+       }
+
+       return ERROR_OK;
+}
+
+static int str9xpec_read_config(struct flash_bank_s *bank)
+{
+       scan_field_t field;
+       uint8_t status;
+       jtag_tap_t *tap;
+
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+
+       tap = str9xpec_info->tap;
+
+       LOG_DEBUG("ISC_CONFIGURATION");
+
+       /* execute ISC_CONFIGURATION command */
+       str9xpec_set_instr(tap, ISC_CONFIGURATION, TAP_IRPAUSE);
+
+       field.tap = tap;
+       field.num_bits = 64;
+       field.out_value = NULL;
+       field.in_value = str9xpec_info->options;
+
+
+       jtag_add_dr_scan(1, &field, jtag_set_end_state(TAP_IDLE));
+       jtag_execute_queue();
+
+       status = str9xpec_isc_status(tap);
+
+       return status;
+}
+
+static int str9xpec_build_block_list(struct flash_bank_s *bank)
+{
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+
+       int i;
+       int num_sectors;
+       int b0_sectors = 0, b1_sectors = 0;
+       uint32_t offset = 0;
+       int b1_size = 0x2000;
+
+       switch (bank->size)
+       {
+               case (256 * 1024):
+                       b0_sectors = 4;
+                       break;
+               case (512 * 1024):
+                       b0_sectors = 8;
+                       break;
+               case (1024 * 1024):
+                       b0_sectors = 16;
+                       break;
+               case (2048 * 1024):
+                       b0_sectors = 32;
+                       break;
+               case (128 * 1024):
+                       b1_size = 0x4000;
+                       b1_sectors = 8;
+                       break;
+               case (32 * 1024):
+                       b1_sectors = 4;
+                       break;
+               default:
+                       LOG_ERROR("BUG: unknown bank->size encountered");
+                       exit(-1);
+       }
+
+       num_sectors = b0_sectors + b1_sectors;
+
+       bank->num_sectors = num_sectors;
+       bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);
+       str9xpec_info->sector_bits = malloc(sizeof(uint32_t) * num_sectors);
+
+       num_sectors = 0;
+
+       for (i = 0; i < b0_sectors; i++)
+       {
+               bank->sectors[num_sectors].offset = offset;
+               bank->sectors[num_sectors].size = 0x10000;
+               offset += bank->sectors[i].size;
+               bank->sectors[num_sectors].is_erased = -1;
+               bank->sectors[num_sectors].is_protected = 1;
+               str9xpec_info->sector_bits[num_sectors++] = i;
+       }
+
+       for (i = 0; i < b1_sectors; i++)
+       {
+               bank->sectors[num_sectors].offset = offset;
+               bank->sectors[num_sectors].size = b1_size;
+               offset += bank->sectors[i].size;
+               bank->sectors[num_sectors].is_erased = -1;
+               bank->sectors[num_sectors].is_protected = 1;
+               str9xpec_info->sector_bits[num_sectors++] = i + 32;
+       }
+
+       return ERROR_OK;
+}
+
+/* flash bank str9x <base> <size> 0 0 <target#>
+ */
+FLASH_BANK_COMMAND_HANDLER(str9xpec_flash_bank_command)
+{
+       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)
+       {
+               LOG_WARNING("incomplete flash_bank str9x configuration");
+               return ERROR_FLASH_BANK_INVALID;
+       }
+
+       str9xpec_info = malloc(sizeof(str9xpec_flash_controller_t));
+       bank->driver_priv = str9xpec_info;
+
+       /* REVISIT verify that the jtag position of flash controller is
+        * right after *THIS* core, which must be a STR9xx core ...
+        */
+       armv4_5 = bank->target->arch_info;
+       arm7_9 = armv4_5->arch_info;
+       jtag_info = &arm7_9->jtag_info;
+
+       str9xpec_info->tap = bank->target->tap;
+       str9xpec_info->isc_enable = 0;
+
+       str9xpec_build_block_list(bank);
+
+       /* clear option byte register */
+       buf_set_u32(str9xpec_info->options, 0, 64, 0);
+
+       return ERROR_OK;
+}
+
+static int str9xpec_blank_check(struct flash_bank_s *bank, int first, int last)
+{
+       scan_field_t field;
+       uint8_t status;
+       jtag_tap_t *tap;
+       int i;
+       uint8_t *buffer = NULL;
+
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+
+       tap = str9xpec_info->tap;
+
+       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);
+
+       LOG_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(tap, ISC_BLANK_CHECK, TAP_IRPAUSE);
+
+       field.tap = tap;
+       field.num_bits = 64;
+       field.out_value = buffer;
+       field.in_value = NULL;
+
+       jtag_add_dr_scan(1, &field, jtag_set_end_state(TAP_IDLE));
+       jtag_add_sleep(40000);
+
+       /* read blank check result */
+       field.tap = tap;
+       field.num_bits = 64;
+       field.out_value = NULL;
+       field.in_value = buffer;
+
+       jtag_add_dr_scan(1, &field, TAP_IRPAUSE);
+       jtag_execute_queue();
+
+       status = str9xpec_isc_status(tap);
+
+       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;
+}
+
+static int str9xpec_protect_check(struct flash_bank_s *bank)
+{
+       uint8_t 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;
+}
+
+static int str9xpec_erase_area(struct flash_bank_s *bank, int first, int last)
+{
+       scan_field_t field;
+       uint8_t status;
+       jtag_tap_t *tap;
+       int i;
+       uint8_t *buffer = NULL;
+
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+
+       tap = str9xpec_info->tap;
+
+       if (!str9xpec_info->isc_enable) {
+               str9xpec_isc_enable(bank);
+       }
+
+       if (!str9xpec_info->isc_enable) {
+               return ISC_STATUS_ERROR;
+       }
+
+       buffer = calloc(CEIL(64, 8), 1);
+
+       LOG_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);
+               }
+       }
+
+       LOG_DEBUG("ISC_ERASE");
+
+       /* execute ISC_ERASE command */
+       str9xpec_set_instr(tap, ISC_ERASE, TAP_IRPAUSE);
+
+       field.tap = tap;
+       field.num_bits = 64;
+       field.out_value = buffer;
+       field.in_value = NULL;
+
+       jtag_add_dr_scan(1, &field, jtag_set_end_state(TAP_IDLE));
+       jtag_execute_queue();
+
+       jtag_add_sleep(10);
+
+       /* wait for erase completion */
+       while (!((status = str9xpec_isc_status(tap)) & ISC_STATUS_BUSY)) {
+               alive_sleep(1);
+       }
+
+       free(buffer);
+
+       str9xpec_isc_disable(bank);
+
+       return status;
+}
+
+static 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;
+}
+
+static int str9xpec_lock_device(struct flash_bank_s *bank)
+{
+       scan_field_t field;
+       uint8_t status;
+       jtag_tap_t *tap;
+       str9xpec_flash_controller_t *str9xpec_info = NULL;
+
+       str9xpec_info = bank->driver_priv;
+       tap = str9xpec_info->tap;
+
+       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(tap, ISC_PROGRAM_SECURITY, TAP_IDLE);
+
+       str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE);
+
+       do {
+               field.tap = tap;
+               field.num_bits = 8;
+               field.out_value = NULL;
+               field.in_value = &status;
+
+               jtag_add_dr_scan(1, &field, jtag_get_end_state());
+               jtag_execute_queue();
+
+       } while (!(status & ISC_STATUS_BUSY));
+
+       str9xpec_isc_disable(bank);
+
+       return status;
+}
+
+static int str9xpec_unlock_device(struct flash_bank_s *bank)
+{
+       uint8_t status;
+
+       status = str9xpec_erase_area(bank, 0, 255);
+
+       return status;
+}
+
+static int str9xpec_protect(struct flash_bank_s *bank, int set, int first, int last)
+{
+       uint8_t 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;
+
+       LOG_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;
+}
+
+static int str9xpec_set_address(struct flash_bank_s *bank, uint8_t sector)
+{
+       jtag_tap_t *tap;
+       scan_field_t field;
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+
+       tap = str9xpec_info->tap;
+
+       /* set flash controller address */
+       str9xpec_set_instr(tap, ISC_ADDRESS_SHIFT, TAP_IRPAUSE);
+
+       field.tap = tap;
+       field.num_bits = 8;
+       field.out_value = &sector;
+       field.in_value = NULL;
+
+       jtag_add_dr_scan(1, &field, jtag_get_end_state());
+
+       return ERROR_OK;
+}
+
+static int str9xpec_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
+{
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+       uint32_t dwords_remaining = (count / 8);
+       uint32_t bytes_remaining = (count & 0x00000007);
+       uint32_t bytes_written = 0;
+       uint8_t status;
+       uint32_t check_address = offset;
+       jtag_tap_t *tap;
+       scan_field_t field;
+       uint8_t *scanbuf;
+       int i;
+       int first_sector = 0;
+       int last_sector = 0;
+
+       tap = str9xpec_info->tap;
+
+       if (!str9xpec_info->isc_enable) {
+               str9xpec_isc_enable(bank);
+       }
+
+       if (!str9xpec_info->isc_enable) {
+               return ERROR_FLASH_OPERATION_FAILED;
+       }
+
+       if (offset & 0x7)
+       {
+               LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset);
+               return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
+       }
+
+       for (i = 0; i < bank->num_sectors; i++)
+       {
+               uint32_t sec_start = bank->sectors[i].offset;
+               uint32_t 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;
+
+       LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);
+
+       scanbuf = calloc(CEIL(64, 8), 1);
+
+       LOG_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(tap, ISC_PROGRAM, TAP_IRPAUSE);
+
+                       field.tap = tap;
+                       field.num_bits = 64;
+                       field.out_value = (buffer + bytes_written);
+                       field.in_value = NULL;
+
+                       jtag_add_dr_scan(1, &field, jtag_set_end_state(TAP_IDLE));
+
+                       /* small delay before polling */
+                       jtag_add_sleep(50);
+
+                       str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE);
+
+                       do {
+                               field.tap = tap;
+                               field.num_bits = 8;
+                               field.out_value = NULL;
+                               field.in_value = scanbuf;
+
+                               jtag_add_dr_scan(1, &field, jtag_get_end_state());
+                               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)
+       {
+               uint8_t 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(tap, ISC_PROGRAM, TAP_IRPAUSE);
+
+               field.tap = tap;
+               field.num_bits = 64;
+               field.out_value = last_dword;
+               field.in_value = NULL;
+
+               jtag_add_dr_scan(1, &field, jtag_set_end_state(TAP_IDLE));
+
+               /* small delay before polling */
+               jtag_add_sleep(50);
+
+               str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE);
+
+               do {
+                       field.tap = tap;
+                       field.num_bits = 8;
+                       field.out_value = NULL;
+                       field.in_value = scanbuf;
+
+                       jtag_add_dr_scan(1, &field, jtag_get_end_state());
+                       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;
+}
+
+static int str9xpec_probe(struct flash_bank_s *bank)
+{
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(str9xpec_handle_part_id_command)
+{
+       scan_field_t field;
+       uint8_t *buffer = NULL;
+       jtag_tap_t *tap;
+       uint32_t idcode;
+       str9xpec_flash_controller_t *str9xpec_info = NULL;
+
+       if (argc < 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       flash_bank_t *bank;
+       int retval = flash_command_get_bank_by_num(cmd_ctx, args[0], &bank);
+       if (ERROR_OK != retval)
+               return retval;
+
+       str9xpec_info = bank->driver_priv;
+       tap = str9xpec_info->tap;
+
+       buffer = calloc(CEIL(32, 8), 1);
+
+       str9xpec_set_instr(tap, ISC_IDCODE, TAP_IRPAUSE);
+
+       field.tap = tap;
+       field.num_bits = 32;
+       field.out_value = NULL;
+       field.in_value = buffer;
+
+       jtag_add_dr_scan(1, &field, jtag_set_end_state(TAP_IDLE));
+       jtag_execute_queue();
+
+       idcode = buf_get_u32(buffer, 0, 32);
+
+       command_print(cmd_ctx, "str9xpec part id: 0x%8.8" PRIx32 "", idcode);
+
+       free(buffer);
+
+       return ERROR_OK;
+}
+
+static int str9xpec_erase_check(struct flash_bank_s *bank)
+{
+       return str9xpec_blank_check(bank, 0, bank->num_sectors - 1);
+}
+
+static int str9xpec_info(struct flash_bank_s *bank, char *buf, int buf_size)
+{
+       snprintf(buf, buf_size, "str9xpec flash driver info");
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(str9xpec_handle_flash_options_read_command)
+{
+       uint8_t status;
+       str9xpec_flash_controller_t *str9xpec_info = NULL;
+
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "str9xpec options_read <bank>");
+               return ERROR_OK;
+       }
+
+       flash_bank_t *bank;
+       int retval = flash_command_get_bank_by_num(cmd_ctx, args[0], &bank);
+       if (ERROR_OK != retval)
+               return retval;
+
+       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;
+}
+
+static int str9xpec_write_options(struct flash_bank_s *bank)
+{
+       scan_field_t field;
+       uint8_t status;
+       jtag_tap_t *tap;
+       str9xpec_flash_controller_t *str9xpec_info = NULL;
+
+       str9xpec_info = bank->driver_priv;
+       tap = str9xpec_info->tap;
+
+       /* 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(tap, ISC_PROGRAM, TAP_IRPAUSE);
+
+       field.tap = tap;
+       field.num_bits = 64;
+       field.out_value = str9xpec_info->options;
+       field.in_value = NULL;
+
+       jtag_add_dr_scan(1, &field, jtag_set_end_state(TAP_IDLE));
+
+       /* small delay before polling */
+       jtag_add_sleep(50);
+
+       str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE);
+
+       do {
+               field.tap = tap;
+               field.num_bits = 8;
+               field.out_value = NULL;
+               field.in_value = &status;
+
+               jtag_add_dr_scan(1, &field, jtag_get_end_state());
+               jtag_execute_queue();
+
+       } while (!(status & ISC_STATUS_BUSY));
+
+       str9xpec_isc_disable(bank);
+
+       return status;
+}
+
+COMMAND_HANDLER(str9xpec_handle_flash_options_write_command)
+{
+       uint8_t status;
+
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "str9xpec options_write <bank>");
+               return ERROR_OK;
+       }
+
+       flash_bank_t *bank;
+       int retval = flash_command_get_bank_by_num(cmd_ctx, args[0], &bank);
+       if (ERROR_OK != retval)
+               return retval;
+
+       status = str9xpec_write_options(bank);
+
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+               return ERROR_FLASH_OPERATION_FAILED;
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(str9xpec_handle_flash_options_cmap_command)
+{
+       str9xpec_flash_controller_t *str9xpec_info = NULL;
+
+       if (argc < 2)
+       {
+               command_print(cmd_ctx, "str9xpec options_cmap <bank> <bank0 | bank1>");
+               return ERROR_OK;
+       }
+
+       flash_bank_t *bank;
+       int retval = flash_command_get_bank_by_num(cmd_ctx, args[0], &bank);
+       if (ERROR_OK != retval)
+               return retval;
+
+       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;
+}
+
+COMMAND_HANDLER(str9xpec_handle_flash_options_lvdthd_command)
+{
+       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;
+       }
+
+       flash_bank_t *bank;
+       int retval = flash_command_get_bank_by_num(cmd_ctx, args[0], &bank);
+       if (ERROR_OK != retval)
+               return retval;
+
+       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;
+}
+
+COMMAND_HANDLER(str9xpec_handle_flash_options_lvdsel_command)
+{
+       str9xpec_flash_controller_t *str9xpec_info = NULL;
+
+       if (argc < 2)
+       {
+               command_print(cmd_ctx, "str9xpec options_lvdsel <bank> <vdd | vdd_vddq>");
+               return ERROR_OK;
+       }
+
+       flash_bank_t *bank;
+       int retval = flash_command_get_bank_by_num(cmd_ctx, args[0], &bank);
+       if (ERROR_OK != retval)
+               return retval;
+
+       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;
+}
+
+COMMAND_HANDLER(str9xpec_handle_flash_options_lvdwarn_command)
+{
+       str9xpec_flash_controller_t *str9xpec_info = NULL;
+
+       if (argc < 2)
+       {
+               command_print(cmd_ctx, "str9xpec options_lvdwarn <bank> <vdd | vdd_vddq>");
+               return ERROR_OK;
+       }
+
+       flash_bank_t *bank;
+       int retval = flash_command_get_bank_by_num(cmd_ctx, args[0], &bank);
+       if (ERROR_OK != retval)
+               return retval;
+
+       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;
+}
+
+COMMAND_HANDLER(str9xpec_handle_flash_lock_command)
+{
+       uint8_t status;
+
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "str9xpec lock <bank>");
+               return ERROR_OK;
+       }
+
+       flash_bank_t *bank;
+       int retval = flash_command_get_bank_by_num(cmd_ctx, args[0], &bank);
+       if (ERROR_OK != retval)
+               return retval;
+
+       status = str9xpec_lock_device(bank);
+
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+               return ERROR_FLASH_OPERATION_FAILED;
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(str9xpec_handle_flash_unlock_command)
+{
+       uint8_t status;
+
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "str9xpec unlock <bank>");
+               return ERROR_OK;
+       }
+
+       flash_bank_t *bank;
+       int retval = flash_command_get_bank_by_num(cmd_ctx, args[0], &bank);
+       if (ERROR_OK != retval)
+               return retval;
+
+       status = str9xpec_unlock_device(bank);
+
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+               return ERROR_FLASH_OPERATION_FAILED;
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(str9xpec_handle_flash_enable_turbo_command)
+{
+       jtag_tap_t *tap0;
+       jtag_tap_t *tap1;
+       jtag_tap_t *tap2;
+       str9xpec_flash_controller_t *str9xpec_info = NULL;
+
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "str9xpec enable_turbo <bank>");
+               return ERROR_OK;
+       }
+
+       flash_bank_t *bank;
+       int retval = flash_command_get_bank_by_num(cmd_ctx, args[0], &bank);
+       if (ERROR_OK != retval)
+               return retval;
+
+       str9xpec_info = bank->driver_priv;
+
+       tap0 = str9xpec_info->tap;
+
+       /* remove arm core from chain - enter turbo mode */
+       tap1 = tap0->next_tap;
+       if (tap1 == NULL)
+       {
+               /* things are *WRONG* */
+               command_print(cmd_ctx,"**STR9FLASH** (tap1) invalid chain?");
+               return ERROR_OK;
+       }
+       tap2 = tap1->next_tap;
+       if (tap2 == NULL)
+       {
+               /* things are *WRONG* */
+               command_print(cmd_ctx,"**STR9FLASH** (tap2) invalid chain?");
+               return ERROR_OK;
+       }
+
+       /* enable turbo mode - TURBO-PROG-ENABLE */
+       str9xpec_set_instr(tap2, 0xD, TAP_IDLE);
+       if ((retval = jtag_execute_queue()) != ERROR_OK)
+               return retval;
+
+       /* modify scan chain - str9 core has been removed */
+       tap1->enabled = 0;
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(str9xpec_handle_flash_disable_turbo_command)
+{
+       jtag_tap_t *tap;
+       str9xpec_flash_controller_t *str9xpec_info = NULL;
+
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "str9xpec disable_turbo <bank>");
+               return ERROR_OK;
+       }
+
+       flash_bank_t *bank;
+       int retval = flash_command_get_bank_by_num(cmd_ctx, args[0], &bank);
+       if (ERROR_OK != retval)
+               return retval;
+
+       str9xpec_info = bank->driver_priv;
+       tap = str9xpec_info->tap;
+
+       if (tap == NULL)
+               return ERROR_FAIL;
+
+       /* exit turbo mode via RESET */
+       str9xpec_set_instr(tap, ISC_NOOP, TAP_IDLE);
+       jtag_add_tlr();
+       jtag_execute_queue();
+
+       /* restore previous scan chain */
+       if (tap->next_tap) {
+               tap->next_tap->enabled = 1;
+       }
+
+       return ERROR_OK;
+}
+
+static 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;
+}
+
+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,
+       };

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)