From 8b4e882a1630d63bbc9840fa3f968e36b6ac3702 Mon Sep 17 00:00:00 2001 From: drath Date: Fri, 2 Jun 2006 10:36:31 +0000 Subject: - prepare OpenOCD for branching, created ./trunk/ git-svn-id: svn://svn.berlios.de/openocd/trunk@64 b42882b7-edfa-0310-969c-e2dbd0fdcd60 --- src/flash/str7x.c | 469 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 469 insertions(+) create mode 100644 src/flash/str7x.c (limited to 'src/flash/str7x.c') diff --git a/src/flash/str7x.c b/src/flash/str7x.c new file mode 100644 index 0000000..2e3a6c8 --- /dev/null +++ b/src/flash/str7x.c @@ -0,0 +1,469 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ + +#include "str7x.h" +#include "flash.h" +#include "target.h" +#include "log.h" +#include "armv4_5.h" +#include "algorithm.h" +#include "binarybuffer.h" + +#include +#include +#include + +str7x_mem_layout_t mem_layout[] = { + {0x00000000, 0x02000, 0x01}, + {0x00002000, 0x02000, 0x01}, + {0x00004000, 0x02000, 0x01}, + {0x00006000, 0x02000, 0x01}, + {0x00008000, 0x08000, 0x01}, + {0x00010000, 0x10000, 0x01}, + {0x00020000, 0x10000, 0x01}, + {0x00030000, 0x10000, 0x01}, + {0x000C0000, 0x02000, 0x10}, + {0x000C2000, 0x02000, 0x10}, + {0,0}, +}; + +int str7x_register_commands(struct command_context_s *cmd_ctx); +int str7x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank); +int str7x_erase(struct flash_bank_s *bank, int first, int last); +int str7x_protect(struct flash_bank_s *bank, int set, int first, int last); +int str7x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count); +int str7x_probe(struct flash_bank_s *bank); +int str7x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int str7x_protect_check(struct flash_bank_s *bank); +int str7x_erase_check(struct flash_bank_s *bank); +int str7x_info(struct flash_bank_s *bank, char *buf, int buf_size); + +flash_driver_t str7x_flash = +{ + .name = "str7x", + .register_commands = str7x_register_commands, + .flash_bank_command = str7x_flash_bank_command, + .erase = str7x_erase, + .protect = str7x_protect, + .write = str7x_write, + .probe = str7x_probe, + .erase_check = str7x_erase_check, + .protect_check = str7x_protect_check, + .info = str7x_info +}; + +int str7x_register_commands(struct command_context_s *cmd_ctx) +{ + + return ERROR_OK; +} + +int str7x_get_flash_adr(struct flash_bank_s *bank, u32 reg) +{ + str7x_flash_bank_t *str7x_info = bank->driver_priv; + return (str7x_info->flash_base|reg); +} + +int str7x_build_block_list(struct flash_bank_s *bank) +{ + str7x_flash_bank_t *str7x_info = bank->driver_priv; + + int i; + int num_sectors; + + switch (bank->size) + { + case 16 * 1024: + num_sectors = 2; + break; + case 64 * 1024: + num_sectors = 5; + break; + case 128 * 1024: + num_sectors = 6; + break; + case 256 * 1024: + num_sectors = 8; + break; + default: + ERROR("BUG: unknown bank->size encountered"); + exit(-1); + } + + if( str7x_info->bank1 == 1 ) + { + num_sectors += 2; + } + + bank->num_sectors = num_sectors; + bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors); + + for (i = 0; i < num_sectors; i++) + { + bank->sectors[i].offset = mem_layout[i].sector_start; + bank->sectors[i].size = mem_layout[i].sector_size; + bank->sectors[i].is_erased = -1; + bank->sectors[i].is_protected = 1; + } + + return ERROR_OK; +} + +/* flash bank str7x 0 0 + */ +int str7x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank) +{ + str7x_flash_bank_t *str7x_info; + + if (argc < 7) + { + WARNING("incomplete flash_bank str7x configuration"); + return ERROR_FLASH_BANK_INVALID; + } + + str7x_info = malloc(sizeof(str7x_flash_bank_t)); + bank->driver_priv = str7x_info; + + if (strcmp(args[5], "STR71x") == 0) + { + str7x_info->bank1 = 1; + str7x_info->flash_base = 0x40000000; + } + else if (strcmp(args[5], "STR73x") == 0) + { + str7x_info->bank1 = 0; + str7x_info->flash_base = 0x80000000; + } + else + { + ERROR("unknown STR7x variant"); + free(str7x_info); + return ERROR_FLASH_BANK_INVALID; + } + + str7x_info->target = get_target_by_num(strtoul(args[6], NULL, 0)); + if (!str7x_info->target) + { + ERROR("no target '%i' configured", args[6]); + exit(-1); + } + + str7x_build_block_list(bank); + + return ERROR_OK; +} + +u32 str7x_status(struct flash_bank_s *bank) +{ + str7x_flash_bank_t *str7x_info = bank->driver_priv; + target_t *target = str7x_info->target; + u32 retval; + + target->type->read_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&retval); + + return retval; +} + +u32 str7x_result(struct flash_bank_s *bank) +{ + str7x_flash_bank_t *str7x_info = bank->driver_priv; + target_t *target = str7x_info->target; + u32 retval; + + target->type->read_memory(target, str7x_get_flash_adr(bank, FLASH_ER), 4, 1, (u8*)&retval); + + return retval; +} + +int str7x_blank_check(struct flash_bank_s *bank, int first, int last) +{ + str7x_flash_bank_t *str7x_info = bank->driver_priv; + target_t *target = str7x_info->target; + u8 *buffer; + int i; + int nBytes; + + if ((first < 0) || (last > bank->num_sectors)) + return ERROR_FLASH_SECTOR_INVALID; + + if (str7x_info->target->state != TARGET_HALTED) + { + return ERROR_TARGET_NOT_HALTED; + } + + buffer = malloc(256); + + for (i = first; i <= last; i++) + { + bank->sectors[i].is_erased = 1; + + target->type->read_memory(target, bank->base + bank->sectors[i].offset, 4, 256/4, buffer); + + for (nBytes = 0; nBytes < 256; nBytes++) + { + if (buffer[nBytes] != 0xFF) + { + bank->sectors[i].is_erased = 0; + break; + } + } + } + + free(buffer); + + return ERROR_OK; +} + +int str7x_protect_check(struct flash_bank_s *bank) +{ + str7x_flash_bank_t *str7x_info = bank->driver_priv; + target_t *target = str7x_info->target; + + int i; + int retval; + + if (str7x_info->target->state != TARGET_HALTED) + { + return ERROR_TARGET_NOT_HALTED; + } + + target->type->read_memory(target, str7x_get_flash_adr(bank, FLASH_NVWPAR), 4, 1, (u8*)&retval); + + for (i = 0; i < bank->num_sectors; i++) + { + if (retval & (mem_layout[i].reg_offset << i)) + bank->sectors[i].is_protected = 0; + else + bank->sectors[i].is_protected = 1; + } + + return ERROR_OK; +} + +int str7x_erase(struct flash_bank_s *bank, int first, int last) +{ + str7x_flash_bank_t *str7x_info = bank->driver_priv; + target_t *target = str7x_info->target; + + int i; + u32 cmd; + u32 retval; + u32 erase_blocks; + + if (str7x_info->target->state != TARGET_HALTED) + { + return ERROR_TARGET_NOT_HALTED; + } + + erase_blocks = 0; + + for (i = first; i <= last; i++) + erase_blocks |= (mem_layout[i].reg_offset << i); + + cmd = FLASH_SER; + target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd); + + cmd = erase_blocks; + target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR1), 4, 1, (u8*)&cmd); + + cmd = FLASH_SER|FLASH_WMS; + target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd); + + while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){ + usleep(1000); + } + + retval = str7x_result(bank); + + if (retval & FLASH_ERER) + return ERROR_FLASH_SECTOR_NOT_ERASED; + else if (retval & FLASH_WPF) + return ERROR_FLASH_OPERATION_FAILED; + + for (i = first; i <= last; i++) + bank->sectors[i].is_erased = 1; + + return ERROR_OK; +} + +int str7x_protect(struct flash_bank_s *bank, int set, int first, int last) +{ + str7x_flash_bank_t *str7x_info = bank->driver_priv; + target_t *target = str7x_info->target; + int i; + u32 cmd; + u32 retval; + u32 protect_blocks; + + if (str7x_info->target->state != TARGET_HALTED) + { + return ERROR_TARGET_NOT_HALTED; + } + + protect_blocks = 0xFFFFFFFF; + + if( set ) + { + for (i = first; i <= last; i++) + protect_blocks &= ~(mem_layout[i].reg_offset << i); + } + + cmd = FLASH_SPR; + target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd); + + cmd = str7x_get_flash_adr(bank, FLASH_NVWPAR); + target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_AR), 4, 1, (u8*)&cmd); + + cmd = protect_blocks; + target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, (u8*)&cmd); + + cmd = FLASH_SPR|FLASH_WMS; + target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd); + + while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){ + usleep(1000); + } + + retval = str7x_result(bank); + + if (retval & FLASH_ERER) + return ERROR_FLASH_SECTOR_NOT_ERASED; + else if (retval & FLASH_WPF) + return ERROR_FLASH_OPERATION_FAILED; + + return ERROR_OK; +} + +int str7x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) +{ + str7x_flash_bank_t *str7x_info = bank->driver_priv; + target_t *target = str7x_info->target; + u32 dwords_remaining = (count / 8); + u32 bytes_remaining = (count & 0x00000007); + u32 address = bank->base + offset; + u32 *wordbuffer = (u32*)buffer; + u32 bytes_written = 0; + u32 cmd; + u32 retval; + + if (str7x_info->target->state != TARGET_HALTED) + { + return ERROR_TARGET_NOT_HALTED; + } + + if (offset + count > bank->size) + return ERROR_FLASH_DST_OUT_OF_BANK; + + while (dwords_remaining > 0) + { + // command + cmd = FLASH_DWPG; + target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd); + + // address + cmd = address; + target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_AR), 4, 1, (u8*)&cmd); + + // data byte 1 + cmd = wordbuffer[bytes_written/4]; + target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, (u8*)&cmd); + bytes_written += 4; + + // data byte 2 + cmd = wordbuffer[bytes_written/4]; + target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1), 4, 1, (u8*)&cmd); + bytes_written += 4; + + /* start programming cycle */ + cmd = FLASH_DWPG|FLASH_WMS; + target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd); + + while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){ + usleep(1000); + } + + retval = str7x_result(bank); + + if (retval & FLASH_PGER) + return ERROR_FLASH_OPERATION_FAILED; + else if (retval & FLASH_WPF) + return ERROR_FLASH_OPERATION_FAILED; + + dwords_remaining--; + address += 8; + } + + while( bytes_remaining > 0 ) + { + // command + cmd = FLASH_WPG; + target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd); + + // address + cmd = address; + target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_AR), 4, 1, (u8*)&cmd); + + // data byte + cmd = buffer[bytes_written]; + target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, (u8*)&cmd); + + /* start programming cycle */ + cmd = FLASH_WPG|FLASH_WMS; + target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd); + + while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){ + usleep(1000); + } + + retval = str7x_result(bank); + + if (retval & FLASH_PGER) + return ERROR_FLASH_OPERATION_FAILED; + else if (retval & FLASH_WPF) + return ERROR_FLASH_OPERATION_FAILED; + + address++; + bytes_remaining--; + bytes_written++; + } + + return ERROR_OK; +} + +int str7x_probe(struct flash_bank_s *bank) +{ + return ERROR_OK; +} + +int str7x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + return ERROR_OK; +} + +int str7x_erase_check(struct flash_bank_s *bank) +{ + return str7x_blank_check(bank, 0, bank->num_sectors - 1); +} + +int str7x_info(struct flash_bank_s *bank, char *buf, int buf_size) +{ + snprintf(buf, buf_size, "str7x flash driver info" ); + return ERROR_OK; +} -- cgit v1.1