diff options
Diffstat (limited to 'src/flash/nor/mini51.c')
-rw-r--r-- | src/flash/nor/mini51.c | 584 |
1 files changed, 0 insertions, 584 deletions
diff --git a/src/flash/nor/mini51.c b/src/flash/nor/mini51.c deleted file mode 100644 index df6e7cef..00000000 --- a/src/flash/nor/mini51.c +++ /dev/null @@ -1,584 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2013 Cosmin Gorgovan * - * cosmin [at] linux-geek [dot] org * - * * - * 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., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - ***************************************************************************/ - -/* - Flash driver for the Nuvoton NuMicro Mini51 and M051 series microcontrollers - - Part |APROM Size |Part ID (at 0x5000_0000) - ---------------------------------------------- - MINI51LAN 4 KB 0x00205100 - MINI51ZAN 4 KB 0x00205103 - MINI51TAN 4 KB 0x00205104 - MINI52LAN 8 KB 0x00205200 - MINI52ZAN 8 KB 0x00205203 - MINI52TAN 8 KB 0x00205204 - MINI54LAN 16 KB 0x00205400 - MINI54ZAN 16 KB 0x00205403 - MINI54TAN 16 KB 0x00205404 - M052LBN 8 KB 0x10005200 - M054LBN 16 KB 0x10005400 - M058LBN 32 KB 0x10005800 - M0516LBN 64 KB 0x10005A00 - M052ZBN 8 KB 0x10005203 - M054ZBN 16 KB 0x10005403 - M058ZBN 32 KB 0x10005803 - M0516ZBN 64 KB 0x10005A03 - M052LDN 8 KB 0x20005200 - M054LDN 16 KB 0x20005400 - M058LDN 32 KB 0x20005800 - M0516LDN 64 KB 0x20005A00 - M052ZDN 8 KB 0x20005203 - M054ZDN 16 KB 0x20005403 - M058ZDN 32 KB 0x20005803 - M0516ZDN 64 KB 0x20005A03 - M052LDE 8 KB 0x30005200 - M054LDE 16 KB 0x30005400 - M058LDE 32 KB 0x30005800 - M0516LDE 64 KB 0x30005A00 - M052ZDE 8 KB 0x30005203 - M054ZDE 16 KB 0x30005403 - M058ZDE 32 KB 0x30005803 - M0516ZDE 64 KB 0x30005A03 - - Datasheet & TRM - --------------- - - The ISP flash programming procedure is described on pages 130 and 131 of the (not very verbose) TRM. - - http://www.keil.com/dd/docs/datashts/nuvoton/mini51/da00-mini51_52_54c1.pdf - - M051 ISP datasheet pages 190-206: - http://www.nuvoton.com/hq/resource-download.jsp?tp_GUID=DA05-M052-54-58-516 - - This driver - ----------- - - * chip_erase, erase, read and write operations have been implemented; - * All operations support APROM, LDROM, FLASH DATA and CONFIG; - - Flash access limitations - ------------------------ - - For implementing the read operation, please note that the APROM isn't memory mapped when booted from LDROM. -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "imp.h" - -#define PART_ID_REG 0x50000000 -#define IPRSTC1 0x50000008 -#define REGLOCKADDR 0x50000100 -#define ISPCON 0x5000C000 -#define ISPADR 0x5000C004 -#define ISPDAT 0x5000C008 -#define ISPCMD 0x5000C00C -#define ISPTRG 0x5000C010 -/* Undocumented isp register */ -#define ISPUNKNOWN 0x5000C01C - -#define IPRSTC_CPU_RST 0x02 - -#define ISPCON_ISPFF 0x40 -#define ISPCON_LDUEN 0x20 -#define ISPCON_CFGUEN 0x10 -#define ISPCON_APUEN 0x08 -#define ISPCON_BS_LDROM 0x02 -#define ISPCON_ISPEN 0x01 - -#define ISPCMD_READ 0x00 -#define ISPCMD_PROGRAM 0x21 -#define ISPCMD_ERASE 0x22 -#define ISPCMD_CHIP_ERASE 0x26 - -#define ISPTRG_ISPGO 0x01 - -#define MINI51_APROM_BASE 0x00000000 -#define MINI51_DATA_BASE 0x0001F000 -#define MINI51_LDROM_BASE 0x00100000 -#define MINI51_CONFIG_BASE 0x00300000 - -#define MINI51_KB 1024 -#define MINI51_PAGE_SIZE 512 -#define MINI51_TIMEOUT 1000 - - -#define ENSURE_OK(status) if (status != ERROR_OK) return status - -#define MINI51_MAX_FLASH_BANKS 4 - -struct mini51_flash_bank_type { - uint32_t base; - uint32_t size; -}; - -struct mini51_cpu_type { - char *name; - uint32_t ppid; - unsigned n_banks; - struct mini51_flash_bank_type bank[MINI51_MAX_FLASH_BANKS]; -}; - -#define MINI51_BANKS_MINI51(aprom_size) \ - .n_banks = 3, \ - { {MINI51_APROM_BASE, (aprom_size)}, {MINI51_LDROM_BASE, 2*1024}, {MINI51_CONFIG_BASE, 512} } - -#define MINI51_BANKS_M051(aprom_size) \ - .n_banks = 4, \ - { {MINI51_APROM_BASE, (aprom_size)}, {MINI51_DATA_BASE, 4*1024}, {MINI51_LDROM_BASE, 4*1024}, \ - {MINI51_CONFIG_BASE, 1024} } - -static const struct mini51_cpu_type mini51_cpu[] = { - { "MINI51LAN", 0x00205100, MINI51_BANKS_MINI51(4*1024) }, - { "MINI51ZAN", 0x00205103, MINI51_BANKS_MINI51(4*1024) }, - { "MINI51TAN", 0x00205104, MINI51_BANKS_MINI51(4*1024) }, - { "MINI52LAN", 0x00205200, MINI51_BANKS_MINI51(8*1024) }, - { "MINI52ZAN", 0x00205203, MINI51_BANKS_MINI51(8*1024) }, - { "MINI52TAN", 0x00205204, MINI51_BANKS_MINI51(8*1024) }, - { "MINI54LAN", 0x00205400, MINI51_BANKS_MINI51(16*1024) }, - { "MINI54ZAN", 0x00205403, MINI51_BANKS_MINI51(16*1024) }, - { "MINI54TAN", 0x00205404, MINI51_BANKS_MINI51(16*1024) }, - - { "M052LBN", 0x10005200, MINI51_BANKS_M051(8*1024) }, - { "M054LBN", 0x10005400, MINI51_BANKS_M051(16*1024) }, - { "M058LBN", 0x10005800, MINI51_BANKS_M051(32*1024) }, - { "M0516LBN", 0x10005A00, MINI51_BANKS_M051(64*1024) }, - { "M052ZBN", 0x10005203, MINI51_BANKS_M051(8*1024) }, - { "M054ZBN", 0x10005403, MINI51_BANKS_M051(16*1024) }, - { "M058ZBN", 0x10005803, MINI51_BANKS_M051(32*1024) }, - { "M0516ZBN", 0x10005A03, MINI51_BANKS_M051(64*1024) }, - { "M052LDN", 0x20005200, MINI51_BANKS_M051(8*1024) }, - { "M054LDN", 0x20005400, MINI51_BANKS_M051(16*1024) }, - { "M058LDN", 0x20005800, MINI51_BANKS_M051(32*1024) }, - { "M0516LDN", 0x20005A00, MINI51_BANKS_M051(64*1024) }, - { "M052ZDN", 0x20005203, MINI51_BANKS_M051(8*1024) }, - { "M054ZDN", 0x20005403, MINI51_BANKS_M051(16*1024) }, - { "M058ZDN", 0x20005803, MINI51_BANKS_M051(32*1024) }, - { "M0516ZDN", 0x20005A03, MINI51_BANKS_M051(64*1024) }, - { "M052LDE", 0x30005200, MINI51_BANKS_M051(8*1024) }, - { "M054LDE", 0x30005400, MINI51_BANKS_M051(16*1024) }, - { "M058LDE", 0x30005800, MINI51_BANKS_M051(32*1024) }, - { "M0516LDE", 0x30005A00, MINI51_BANKS_M051(64*1024) }, - { "M052ZDE", 0x30005203, MINI51_BANKS_M051(8*1024) }, - { "M054ZDE", 0x30005403, MINI51_BANKS_M051(16*1024) }, - { "M058ZDE", 0x30005803, MINI51_BANKS_M051(32*1024) }, - { "M0516ZDE", 0x30005A03, MINI51_BANKS_M051(64*1024) }, -}; - -struct mini51_flash_bank { - bool probed; - const struct mini51_cpu_type *cpu; -}; - -/* Private methods */ - -static int mini51_unlock_reg(struct target *target) -{ - int status; - status = target_write_u32(target, REGLOCKADDR, 0x59); - if (status != ERROR_OK) - return status; - status = target_write_u32(target, REGLOCKADDR, 0x16); - if (status != ERROR_OK) - return status; - status = target_write_u32(target, REGLOCKADDR, 0x88); - if (status != ERROR_OK) - return status; - - return ERROR_OK; -} - - -static int mini51_get_part_id(struct target *target, uint32_t *part_id) -{ - int retu = target_read_u32(target, PART_ID_REG, part_id); - LOG_INFO("device id = 0x%08" PRIx32 "", *part_id); - return retu; -} - -static int mini51_get_cpu_type(struct target *target, const struct mini51_cpu_type** cpu) -{ - uint32_t part_id; - int status; - - status = mini51_get_part_id(target, &part_id); - ENSURE_OK(status); - - for (size_t i = 0; i < sizeof(mini51_cpu)/sizeof(mini51_cpu[0]); i++) { - if (part_id == mini51_cpu[i].ppid) { - *cpu = &mini51_cpu[i]; - LOG_INFO("device name = %s", (*cpu)->name); - return ERROR_OK; - } - } - - return ERROR_FLASH_OPERATION_FAILED; -} - -static int mini51_get_flash_size(struct flash_bank *bank, const struct mini51_cpu_type *cpu, uint32_t *flash_size) -{ - for (size_t i = 0; i < cpu->n_banks; i++) { - if (bank->base == cpu->bank[i].base) { - *flash_size = cpu->bank[i].size; - LOG_INFO("bank base = 0x%08" PRIx32 ", size = 0x%08" PRIx32 "", bank->base, *flash_size); - return ERROR_OK; - } - } - return ERROR_FLASH_OPERATION_FAILED; -} - -static int mini51_isp_execute(struct target *target) -{ - int status; - uint32_t ispcon; - int timeout; - uint32_t isptrg; - - /* start ISP operation */ - status = target_write_u32(target, ISPTRG, ISPTRG_ISPGO); - ENSURE_OK(status); - - /* Wait for for command to finish executing */ - timeout = MINI51_TIMEOUT; - do { - target_read_u32(target, ISPTRG, &isptrg); - timeout--; - } while ((isptrg & ISPTRG_ISPGO) && (timeout > 0)); - if (timeout == 0) { - LOG_WARNING("Mini51 flash driver: Timeout executing flash command\n"); - return ERROR_FLASH_OPERATION_FAILED; - } - - /* Check for errors */ - status = target_read_u32(target, ISPCON, &ispcon); - ENSURE_OK(status); - if (ispcon & ISPCON_ISPFF) { - LOG_WARNING("Mini51 flash driver: operation failed\n"); - return ERROR_FLASH_OPERATION_FAILED; - } - return status; -} - -static int mini51_isp_execute_cmd(struct target *target, uint32_t cmd, uint32_t address, uint32_t data) -{ - int status; - status = target_write_u32(target, ISPDAT, data); - ENSURE_OK(status); - status = target_write_u32(target, ISPADR, address); - ENSURE_OK(status); - status = target_write_u32(target, ISPCMD, cmd); - ENSURE_OK(status); - - status = mini51_isp_execute(target); - return status; -} - -static int mini51_isp_execute_cmd_read(struct target *target, uint32_t cmd, uint32_t address, uint32_t *data) -{ - int status; - status = target_write_u32(target, ISPADR, address); - ENSURE_OK(status); - status = target_write_u32(target, ISPCMD, cmd); - ENSURE_OK(status); - - status = mini51_isp_execute(target); - ENSURE_OK(status); - - status = target_read_u32(target, ISPDAT, data); - ENSURE_OK(status); - - return status; -} - -static int mini51_isp_enable(struct target *target) -{ - int status; - uint32_t ispcon; - - if (target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - status = mini51_unlock_reg(target); - ENSURE_OK(status); - status = target_read_u32(target, ISPCON, &ispcon); - ENSURE_OK(status); - ispcon |= ISPCON_ISPEN | ISPCON_LDUEN | ISPCON_APUEN | ISPCON_CFGUEN; - status = target_write_u32(target, ISPCON, ispcon); - return status; -} - -/* Public (API) methods */ - -FLASH_BANK_COMMAND_HANDLER(mini51_flash_bank_command) -{ - struct mini51_flash_bank *mini51_info; - mini51_info = malloc(sizeof(struct mini51_flash_bank)); - mini51_info->probed = false; - bank->driver_priv = mini51_info; - - return ERROR_OK; -} - -static int mini51_protect_check(struct flash_bank *bank) -{ - LOG_WARNING("Mini51 flash driver: protect_check not implemented yet\n"); - - return ERROR_FLASH_OPERATION_FAILED; -} - -static int mini51_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) -{ - int status; - uint32_t ispdat; - struct target *target = bank->target; - - if ((offset & 0x3) || (count & 0x3)) { - LOG_WARNING("Mini51 flash driver: unaligned access not supported\n"); - return ERROR_FLASH_OPERATION_FAILED; - } - - status = mini51_isp_enable(target); - ENSURE_OK(status); - - for (uint32_t i = offset; i < offset + count; i += 4) { - status = mini51_isp_execute_cmd_read(target, ISPCMD_READ, bank->base + i, &ispdat); - memcpy(buffer, &ispdat, sizeof(ispdat)); - ENSURE_OK(status); - buffer += sizeof(ispdat); - } - - return ERROR_OK; -} - - -static int mini51_erase(struct flash_bank *bank, int first, int last) -{ - int status; - struct target *target = bank->target; - - /* Enable ISP */ - status = mini51_isp_enable(target); - ENSURE_OK(status); - - for (int page_start = first; page_start <= last; page_start++) { - /* Set up erase command */ - uint32_t address = bank->base + page_start*MINI51_PAGE_SIZE; - status = mini51_isp_execute_cmd(target, ISPCMD_ERASE, address, 0); - ENSURE_OK(status); - } - - return ERROR_OK; -} - -static int mini51_protect(struct flash_bank *bank, int set, int first, int last) -{ - LOG_WARNING("Mini51 flash driver: protect operation not implemented yet\n"); - - return ERROR_FLASH_OPERATION_FAILED; -} - -static int mini51_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) -{ - int status; - uint32_t ispdat; - struct target *target = bank->target; - - if ((offset & 0x3) || (count & 0x3)) { - LOG_WARNING("Mini51 flash driver: unaligned access not supported\n"); - return ERROR_FLASH_OPERATION_FAILED; - } - - status = mini51_isp_enable(target); - ENSURE_OK(status); - - for (uint32_t i = offset; i < offset + count; i += 4) { - memcpy(&ispdat, buffer, sizeof(ispdat)); - status = mini51_isp_execute_cmd(target, ISPCMD_PROGRAM, bank->base + i, ispdat); - ENSURE_OK(status); - buffer += sizeof(ispdat); - } - - return ERROR_OK; -} - -static int mini51_probe(struct flash_bank *bank) -{ - uint32_t flash_size; - int status; - int num_pages; - uint32_t offset = 0; - const struct mini51_cpu_type *cpu; - struct target *target = bank->target; - - status = mini51_get_cpu_type(target, &cpu); - if (status != ERROR_OK) { - LOG_WARNING("Mini51 flash driver: Failed to detect a known part\n"); - return ERROR_FLASH_OPERATION_FAILED; - } - - status = mini51_get_flash_size(bank, cpu, &flash_size); - if (status != ERROR_OK) { - LOG_WARNING("Mini51 flash driver: Failed to detect flash size\n"); - return ERROR_FLASH_OPERATION_FAILED; - } - - num_pages = flash_size / MINI51_PAGE_SIZE; - - bank->num_sectors = num_pages; - bank->sectors = malloc(sizeof(struct flash_sector) * num_pages); - bank->size = flash_size; - - for (int i = 0; i < num_pages; i++) { - bank->sectors[i].offset = offset; - bank->sectors[i].size = MINI51_PAGE_SIZE; - bank->sectors[i].is_erased = -1; - bank->sectors[i].is_protected = 0; - offset += MINI51_PAGE_SIZE; - } - - struct mini51_flash_bank *mini51_info = bank->driver_priv; - mini51_info->probed = true; - mini51_info->cpu = cpu; - - return ERROR_OK; -} - -static int mini51_auto_probe(struct flash_bank *bank) -{ - struct mini51_flash_bank *mini51_info = bank->driver_priv; - if (mini51_info->probed) - return ERROR_OK; - return mini51_probe(bank); -} - -COMMAND_HANDLER(mini51_handle_read_isp_command) -{ - uint32_t address; - uint32_t ispdat; - int status; - - if (CMD_ARGC != 1) - return ERROR_COMMAND_SYNTAX_ERROR; - - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); - - struct target *target = get_current_target(CMD_CTX); - - status = mini51_isp_enable(target); - ENSURE_OK(status); - status = mini51_isp_execute_cmd_read(target, ISPCMD_READ, address, &ispdat); - ENSURE_OK(status); - LOG_INFO("0x%08" PRIx32 ": 0x%08" PRIx32, address, ispdat); - return ERROR_OK; -} - -COMMAND_HANDLER(mini51_handle_write_isp_command) -{ - uint32_t address; - uint32_t ispdat; - int status; - - if (CMD_ARGC != 2) - return ERROR_COMMAND_SYNTAX_ERROR; - - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], ispdat); - - struct target *target = get_current_target(CMD_CTX); - - status = mini51_isp_enable(target); - ENSURE_OK(status); - status = mini51_isp_execute_cmd(target, ISPCMD_PROGRAM, address, ispdat); - ENSURE_OK(status); - LOG_INFO("0x%08" PRIx32 ": 0x%08" PRIx32, address, ispdat); - return ERROR_OK; -} - -COMMAND_HANDLER(mini51_handle_chip_erase_command) -{ - int status; - if (CMD_ARGC != 0) - return ERROR_COMMAND_SYNTAX_ERROR; - - struct target *target = get_current_target(CMD_CTX); - - status = mini51_isp_enable(target); - ENSURE_OK(status); - /* Write one to undocumented flash control register */ - status = target_write_u32(target, ISPUNKNOWN, 1); - ENSURE_OK(status); - - status = mini51_isp_execute_cmd(target, ISPCMD_CHIP_ERASE, 0, 0); - ENSURE_OK(status); - return ERROR_OK; -} - -static const struct command_registration mini51_exec_command_handlers[] = { - { - .name = "read_isp", - .handler = mini51_handle_read_isp_command, - .usage = "address", - .mode = COMMAND_EXEC, - .help = "read flash through ISP.", - }, - { - .name = "write_isp", - .handler = mini51_handle_write_isp_command, - .usage = "address value", - .mode = COMMAND_EXEC, - .help = "write flash through ISP.", - }, - { - .name = "chip_erase", - .handler = mini51_handle_chip_erase_command, - .mode = COMMAND_EXEC, - .help = "chip erase.", - }, - COMMAND_REGISTRATION_DONE -}; - -static const struct command_registration mini51_command_handlers[] = { - { - .name = "mini51", - .mode = COMMAND_ANY, - .help = "mini51 flash command group", - .usage = "", - .chain = mini51_exec_command_handlers, - }, - COMMAND_REGISTRATION_DONE -}; - -struct flash_driver mini51_flash = { - .name = "mini51", - .commands = mini51_command_handlers, - .flash_bank_command = mini51_flash_bank_command, - .erase = mini51_erase, - .protect = mini51_protect, - .write = mini51_write, - .read = mini51_read, - .probe = mini51_probe, - .auto_probe = mini51_auto_probe, - .erase_check = default_flash_blank_check, - .protect_check = mini51_protect_check, -}; |