diff options
author | Tim Newsome <tim@sifive.com> | 2022-05-03 13:44:25 -0700 |
---|---|---|
committer | Tim Newsome <tim@sifive.com> | 2022-05-03 13:48:07 -0700 |
commit | 8e1064f1fec5b15957c552526c49f42c41be5b6d (patch) | |
tree | 128dae056ca236ba50a82f220592808c9190c995 | |
parent | 9460f43dc356829858bcb0057c7fe0dd7153c0c6 (diff) | |
download | riscv-openocd-8e1064f1fec5b15957c552526c49f42c41be5b6d.zip riscv-openocd-8e1064f1fec5b15957c552526c49f42c41be5b6d.tar.gz riscv-openocd-8e1064f1fec5b15957c552526c49f42c41be5b6d.tar.bz2 |
Remove gd32vf103 flash driver.
Per mainline, use stm32f1x instead. Tested that this is working.
Change-Id: Icda4b2a39e06e2adf9bbfb984bd578347f43d7d1
Signed-off-by: Tim Newsome <tim@sifive.com>
-rw-r--r-- | src/flash/nor/Makefile.am | 1 | ||||
-rw-r--r-- | src/flash/nor/drivers.c | 2 | ||||
-rw-r--r-- | src/flash/nor/gd32vf103.c | 1344 |
3 files changed, 0 insertions, 1347 deletions
diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am index a091744..a5ef422 100644 --- a/src/flash/nor/Makefile.am +++ b/src/flash/nor/Makefile.am @@ -66,7 +66,6 @@ NOR_DRIVERS = \ %D%/stm32lx.c \ %D%/stm32l4x.c \ %D%/stm32h7x.c \ - %D%/gd32vf103.c \ %D%/str7x.c \ %D%/str9x.c \ %D%/str9xpec.c \ diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index dc966ed..3e35c09 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -44,7 +44,6 @@ extern const struct flash_driver faux_flash; extern const struct flash_driver fm3_flash; extern const struct flash_driver fm4_flash; extern const struct flash_driver fespi_flash; -extern const struct flash_driver gd32vf103_flash; extern const struct flash_driver jtagspi_flash; extern const struct flash_driver kinetis_flash; extern const struct flash_driver kinetis_ke_flash; @@ -153,7 +152,6 @@ static const struct flash_driver * const flash_drivers[] = { &stm32lx_flash, &stm32l4x_flash, &stm32h7x_flash, - &gd32vf103_flash, &stmsmi_flash, &stmqspi_flash, &str7x_flash, diff --git a/src/flash/nor/gd32vf103.c b/src/flash/nor/gd32vf103.c deleted file mode 100644 index 562f41e..0000000 --- a/src/flash/nor/gd32vf103.c +++ /dev/null @@ -1,1344 +0,0 @@ -/*************************************************************************** - * - * 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, see <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "imp.h" -#include <helper/binarybuffer.h> -#include <target/algorithm.h> - -/* gd32vf103 register locations */ - -#define FLASH_REG_BASE_B0 0x40022000 -#define FLASH_REG_BASE_B1 0x40022040 - -#define FMC_WS 0x00 -#define FMC_KEY 0x04 -#define FMC_OBKEY 0x08 -#define FMC_STAT 0x0C -#define FMC_CTL 0x10 -#define FMC_ADDR 0x14 -#define FMC_OBSTAT 0x1C - -/* TODO: Check if code using these really should be hard coded to bank 0. - * There are valid cases, on dual flash devices the protection of the - * second bank is done on the bank0 reg's. */ -#define FMC_WS_B0 0x40022000 -#define FMC_KEY_B0 0x40022004 -#define FMC_OBKEY_B0 0x40022008 -#define FMC_STAT_B0 0x4002200C -#define FMC_CTL_B0 0x40022010 -#define FMC_ADDR_B0 0x40022014 -#define FMC_OBSTAT_B0 0x4002201C -#define FMC_WP_B0 0x40022020 - -/* option byte location */ - -#define FMC_OB_RDP 0x1FFFF800 - -/* FMC_CTL register bits */ - -#define FMC_CTL_PG (1 << 0) -#define FMC_CTL_PER (1 << 1) -#define FMC_CTL_MER (1 << 2) -#define FMC_CTL_OBPG (1 << 4) -#define FMC_CTL_OBER (1 << 5) -#define FMC_CTL_START (1 << 6) -#define FMC_CTL_LK (1 << 7) -#define FMC_CTL_OBWEN (1 << 9) - -/* FMC_STAT register bits */ - -#define FMC_STAT_BUSY (1 << 0) -#define FMC_STAT_PGERR (1 << 2) -#define FMC_STAT_WPERR (1 << 4) -#define FMC_STAT_ENDF (1 << 5) - -/* FMC_OBSTAT bit definitions (reading) */ - -#define FMC_OBSTAT_OBERR 0 -#define FMC_OBSTAT_SPC 1 -#define FMC_OBSTAT_WDG_SW 2 -#define FMC_OBSTAT_RST_DSLEEP 3 -#define FMC_OBSTAT_RST_STDBY 4 -#define FMC_OBSTAT_BB 5 /* dual flash bank only */ - -/* register unlock keys */ - -#define UNLOCK_KEY0 0x45670123 -#define UNLOCK_KEY1 0xCDEF89AB - -/* timeout values */ - -#define FLASH_WRITE_TIMEOUT 500 -#define FLASH_ERASE_TIMEOUT 5000 - -struct gd32vf103_options { - uint16_t RDP; - uint16_t user_options; - uint16_t user_data; - uint16_t protection[4]; -}; - -struct gd32vf103_flash_bank { - struct gd32vf103_options option_bytes; - int ppage_size; - int probed; - - bool has_dual_banks; - /* used to access dual flash bank gd32vf103 */ - uint32_t register_base; - uint16_t default_rdp; - int user_data_offset; - int option_offset; - uint32_t user_bank_size; -}; - -static int gd32vf103_mass_erase(struct flash_bank *bank); -static int get_gd32vf103_info(struct flash_bank *bank, struct command_invocation *cmd); -static int gd32vf103_write_block(struct flash_bank *bank, const uint8_t *buffer, - uint32_t offset, uint32_t count); - -/* flash bank gd32vf103 <base> <size> 0 0 <target#> - */ -FLASH_BANK_COMMAND_HANDLER(gd32vf103_flash_bank_command) -{ - struct gd32vf103_flash_bank *gd32vf103_info; - - if (CMD_ARGC < 6) - return ERROR_COMMAND_SYNTAX_ERROR; - - gd32vf103_info = malloc(sizeof(struct gd32vf103_flash_bank)); - - bank->driver_priv = gd32vf103_info; - gd32vf103_info->probed = 0; - gd32vf103_info->has_dual_banks = false; - gd32vf103_info->register_base = FLASH_REG_BASE_B0; - gd32vf103_info->user_bank_size = bank->size; - - return ERROR_OK; -} - -static inline int gd32vf103_get_flash_reg(struct flash_bank *bank, uint32_t reg) -{ - struct gd32vf103_flash_bank *gd32vf103_info = bank->driver_priv; - return reg + gd32vf103_info->register_base; -} - -static inline int gd32vf103_get_flash_status(struct flash_bank *bank, uint32_t *status) -{ - struct target *target = bank->target; - return target_read_u32(target, gd32vf103_get_flash_reg(bank, FMC_STAT), status); -} - -static int gd32vf103_wait_status_busy(struct flash_bank *bank, int timeout) -{ - struct target *target = bank->target; - uint32_t status; - int retval = ERROR_OK; - - /* wait for busy to clear */ - for (;;) { - retval = gd32vf103_get_flash_status(bank, &status); - if (retval != ERROR_OK) - return retval; - LOG_DEBUG("status: 0x%" PRIx32 "", status); - if ((status & FMC_STAT_BUSY) == 0) - break; - if (timeout-- <= 0) { - LOG_ERROR("timed out waiting for flash"); - return ERROR_FAIL; - } - alive_sleep(1); - } - - if (status & FMC_STAT_WPERR) { - LOG_ERROR("gd32vf103 device protected"); - retval = ERROR_FAIL; - } - - if (status & FMC_STAT_PGERR) { - LOG_ERROR("gd32vf103 device programming failed"); - retval = ERROR_FAIL; - } - - /* Clear but report errors */ - if (status & (FMC_STAT_WPERR | FMC_STAT_PGERR)) { - /* If this operation fails, we ignore it and report the original - * retval - */ - target_write_u32(target, gd32vf103_get_flash_reg(bank, FMC_STAT), - FMC_STAT_WPERR | FMC_STAT_PGERR); - } - return retval; -} - -static int gd32vf103_check_operation_supported(struct flash_bank *bank) -{ - struct gd32vf103_flash_bank *gd32vf103_info = bank->driver_priv; - - /* if we have a dual flash bank device then - * we need to perform option byte stuff on bank0 only */ - if (gd32vf103_info->register_base != FLASH_REG_BASE_B0) { - LOG_ERROR("Option Byte Operation's must use bank0"); - return ERROR_FLASH_OPERATION_FAILED; - } - - return ERROR_OK; -} - -static int gd32vf103_read_options(struct flash_bank *bank) -{ - uint32_t optiondata; - struct gd32vf103_flash_bank *gd32vf103_info = NULL; - struct target *target = bank->target; - - gd32vf103_info = bank->driver_priv; - - /* read current option bytes */ - int retval = target_read_u32(target, FMC_OBSTAT_B0, &optiondata); - if (retval != ERROR_OK) - return retval; - - gd32vf103_info->option_bytes.user_options = (optiondata >> gd32vf103_info->option_offset >> 2) & 0xffff; - gd32vf103_info->option_bytes.user_data = (optiondata >> gd32vf103_info->user_data_offset) & 0xffff; - gd32vf103_info->option_bytes.RDP = (optiondata & (1 << FMC_OBSTAT_SPC)) ? 0xFFFF : 0x5AA5; - - if (optiondata & (1 << FMC_OBSTAT_SPC)) - LOG_INFO("Device Security Bit Set"); - - /* each bit refers to a 4bank protection */ - retval = target_read_u32(target, FMC_WP_B0, &optiondata); - if (retval != ERROR_OK) - return retval; - - gd32vf103_info->option_bytes.protection[0] = (uint16_t)optiondata; - gd32vf103_info->option_bytes.protection[1] = (uint16_t)(optiondata >> 8); - gd32vf103_info->option_bytes.protection[2] = (uint16_t)(optiondata >> 16); - gd32vf103_info->option_bytes.protection[3] = (uint16_t)(optiondata >> 24); - - return ERROR_OK; -} - -static int gd32vf103_erase_options(struct flash_bank *bank) -{ - struct gd32vf103_flash_bank *gd32vf103_info = NULL; - struct target *target = bank->target; - - gd32vf103_info = bank->driver_priv; - - /* read current options */ - gd32vf103_read_options(bank); - - /* unlock flash registers */ - int retval = target_write_u32(target, FMC_KEY_B0, UNLOCK_KEY0); - if (retval != ERROR_OK) - return retval; - - retval = target_write_u32(target, FMC_KEY_B0, UNLOCK_KEY1); - if (retval != ERROR_OK) - return retval; - - /* unlock option flash registers */ - retval = target_write_u32(target, FMC_OBKEY_B0, UNLOCK_KEY0); - if (retval != ERROR_OK) - return retval; - retval = target_write_u32(target, FMC_OBKEY_B0, UNLOCK_KEY1); - if (retval != ERROR_OK) - return retval; - - /* erase option bytes */ - retval = target_write_u32(target, FMC_CTL_B0, FMC_CTL_OBER | FMC_CTL_OBWEN); - if (retval != ERROR_OK) - return retval; - retval = target_write_u32(target, FMC_CTL_B0, FMC_CTL_OBER | FMC_CTL_START | FMC_CTL_OBWEN); - if (retval != ERROR_OK) - return retval; - - retval = gd32vf103_wait_status_busy(bank, FLASH_ERASE_TIMEOUT); - if (retval != ERROR_OK) - return retval; - - /* clear readout protection and complementary option bytes - * this will also force a device unlock if set */ - gd32vf103_info->option_bytes.RDP = gd32vf103_info->default_rdp; - - return ERROR_OK; -} - -static int gd32vf103_write_options(struct flash_bank *bank) -{ - struct gd32vf103_flash_bank *gd32vf103_info = NULL; - struct target *target = bank->target; - - gd32vf103_info = bank->driver_priv; - - /* unlock flash registers */ - int retval = target_write_u32(target, FMC_KEY_B0, UNLOCK_KEY0); - if (retval != ERROR_OK) - return retval; - retval = target_write_u32(target, FMC_KEY_B0, UNLOCK_KEY1); - if (retval != ERROR_OK) - return retval; - - /* unlock option flash registers */ - retval = target_write_u32(target, FMC_OBKEY_B0, UNLOCK_KEY0); - if (retval != ERROR_OK) - return retval; - retval = target_write_u32(target, FMC_OBKEY_B0, UNLOCK_KEY1); - if (retval != ERROR_OK) - return retval; - - /* program option bytes */ - retval = target_write_u32(target, FMC_CTL_B0, FMC_CTL_OBPG | FMC_CTL_OBWEN); - if (retval != ERROR_OK) - return retval; - - uint8_t opt_bytes[16]; - - target_buffer_set_u16(target, opt_bytes, gd32vf103_info->option_bytes.RDP); /* SPC */ - target_buffer_set_u16(target, opt_bytes + 2, gd32vf103_info->option_bytes.user_options); /* USER */ - target_buffer_set_u16(target, opt_bytes + 4, gd32vf103_info->option_bytes.user_data & 0xff); /* DATA[7:0] */ - target_buffer_set_u16(target, opt_bytes + 6, (gd32vf103_info->option_bytes.user_data >> 8) & 0xff); /* DATA[15:8] */ - target_buffer_set_u16(target, opt_bytes + 8, gd32vf103_info->option_bytes.protection[0]); /* WP[7:0] */ - target_buffer_set_u16(target, opt_bytes + 10, gd32vf103_info->option_bytes.protection[1]); /* WP[15:8] */ - target_buffer_set_u16(target, opt_bytes + 12, gd32vf103_info->option_bytes.protection[2]); /* WP[23:16] */ - target_buffer_set_u16(target, opt_bytes + 14, gd32vf103_info->option_bytes.protection[3]); /* WP[31:24] */ - - uint32_t offset = FMC_OB_RDP - bank->base; - retval = gd32vf103_write_block(bank, opt_bytes, offset, sizeof(opt_bytes) / 2); - if (retval != ERROR_OK) { - if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) - LOG_ERROR("working area required to erase options bytes"); - return retval; - } - - retval = target_write_u32(target, FMC_CTL_B0, FMC_CTL_LK); - if (retval != ERROR_OK) - return retval; - - return ERROR_OK; -} - -static int gd32vf103_protect_check(struct flash_bank *bank) -{ - struct target *target = bank->target; - struct gd32vf103_flash_bank *gd32vf103_info = bank->driver_priv; - - uint32_t protection; - int i; - int num_bits; - int set; - - int retval = gd32vf103_check_operation_supported(bank); - if (ERROR_OK != retval) - return retval; - - /* medium density - each bit refers to a 4bank protection - * high density - each bit refers to a 2bank protection */ - retval = target_read_u32(target, FMC_WP_B0, &protection); - if (retval != ERROR_OK) - return retval; - - /* medium density - each protection bit is for 4 * 1K pages - * high density - each protection bit is for 2 * 2K pages */ - num_bits = (bank->num_sectors / gd32vf103_info->ppage_size); - - if (gd32vf103_info->ppage_size == 2) { - /* high density flash/connectivity line protection */ - - set = 1; - - if (protection & (1 << 31)) - set = 0; - - /* bit 31 controls sector 62 - 255 protection for high density - * bit 31 controls sector 62 - 127 protection for connectivity line */ - for (unsigned s = 62; s < bank->num_sectors; s++) - bank->sectors[s].is_protected = set; - - if (bank->num_sectors > 61) - num_bits = 31; - - for (i = 0; i < num_bits; i++) { - set = 1; - - if (protection & (1 << i)) - set = 0; - - for (int s = 0; s < gd32vf103_info->ppage_size; s++) - bank->sectors[(i * gd32vf103_info->ppage_size) + s].is_protected = set; - } - } else { - /* low/medium density flash protection */ - for (i = 0; i < num_bits; i++) { - set = 1; - - if (protection & (1 << i)) - set = 0; - - for (int s = 0; s < gd32vf103_info->ppage_size; s++) - bank->sectors[(i * gd32vf103_info->ppage_size) + s].is_protected = set; - } - } - - return ERROR_OK; -} - -static int gd32vf103_erase(struct flash_bank *bank, unsigned first, unsigned last) -{ - struct target *target = bank->target; - uint32_t optiondata; - uint32_t obstat; - - struct gd32vf103_flash_bank *gd32vf103_info = NULL; - gd32vf103_info = bank->driver_priv; - - if (bank->target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - target_read_u32(target, FMC_WP_B0, &optiondata); - target_read_u32(target, FMC_OBSTAT_B0, &obstat); - if ((0xFFFFFFFF != optiondata) || ((obstat & 0x2) != 0)) { - gd32vf103_erase_options(bank); - optiondata = 0xFFFFFFFF; - gd32vf103_info->option_bytes.RDP = 0x5AA5; - gd32vf103_info->option_bytes.protection[0] = (uint16_t)optiondata; - gd32vf103_info->option_bytes.protection[1] = (uint16_t)(optiondata >> 8); - gd32vf103_info->option_bytes.protection[2] = (uint16_t)(optiondata >> 16); - gd32vf103_info->option_bytes.protection[3] = (uint16_t)(optiondata >> 24); - - gd32vf103_write_options(bank); - LOG_INFO(" Unlock flash Sucess !!! Pls Reset Platfrom !!\n"); - return ERROR_FAIL; - } - if ((first == 0) && (last == (bank->num_sectors - 1))) - return gd32vf103_mass_erase(bank); - - /* unlock flash registers */ - int retval = target_write_u32(target, gd32vf103_get_flash_reg(bank, FMC_KEY), UNLOCK_KEY0); - if (retval != ERROR_OK) - return retval; - retval = target_write_u32(target, gd32vf103_get_flash_reg(bank, FMC_KEY), UNLOCK_KEY1); - if (retval != ERROR_OK) - return retval; - - for (unsigned i = first; i <= last; i++) { - retval = target_write_u32(target, gd32vf103_get_flash_reg(bank, FMC_CTL), FMC_CTL_PER); - if (retval != ERROR_OK) - return retval; - retval = target_write_u32(target, gd32vf103_get_flash_reg(bank, FMC_ADDR), - bank->base + bank->sectors[i].offset); - if (retval != ERROR_OK) - return retval; - retval = target_write_u32(target, - gd32vf103_get_flash_reg(bank, FMC_CTL), FMC_CTL_PER | FMC_CTL_START); - if (retval != ERROR_OK) - return retval; - - retval = gd32vf103_wait_status_busy(bank, FLASH_ERASE_TIMEOUT); - if (retval != ERROR_OK) - return retval; - - bank->sectors[i].is_erased = 1; - } - - retval = target_write_u32(target, gd32vf103_get_flash_reg(bank, FMC_CTL), FMC_CTL_LK); - if (retval != ERROR_OK) - return retval; - - return ERROR_OK; -} - -static int gd32vf103_protect(struct flash_bank *bank, int set, unsigned first, unsigned last) -{ - struct gd32vf103_flash_bank *gd32vf103_info = NULL; - struct target *target = bank->target; - uint16_t prot_reg[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}; - int reg, bit; - int status; - uint32_t protection; - - gd32vf103_info = bank->driver_priv; - - if (target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - int retval = gd32vf103_check_operation_supported(bank); - if (ERROR_OK != retval) - return retval; - - if ((first % gd32vf103_info->ppage_size) != 0) { - LOG_WARNING("aligned start protect sector to a %d sector boundary", - gd32vf103_info->ppage_size); - first = first - (first % gd32vf103_info->ppage_size); - } - if (((last + 1) % gd32vf103_info->ppage_size) != 0) { - LOG_WARNING("aligned end protect sector to a %d sector boundary", - gd32vf103_info->ppage_size); - last++; - last = last - (last % gd32vf103_info->ppage_size); - last--; - } - - /* medium density - each bit refers to a 4bank protection - * high density - each bit refers to a 2bank protection */ - retval = target_read_u32(target, FMC_WP_B0, &protection); - if (retval != ERROR_OK) - return retval; - - prot_reg[0] = (uint16_t)protection; - prot_reg[1] = (uint16_t)(protection >> 8); - prot_reg[2] = (uint16_t)(protection >> 16); - prot_reg[3] = (uint16_t)(protection >> 24); - - if (gd32vf103_info->ppage_size == 2) { - /* high density flash */ - - /* bit 7 controls sector 62 - 255 protection */ - if (last > 61) { - if (set) - prot_reg[3] &= ~(1 << 7); - else - prot_reg[3] |= (1 << 7); - } - - if (first > 61) - first = 62; - if (last > 61) - last = 61; - - for (unsigned i = first; i <= last; i++) { - reg = (i / gd32vf103_info->ppage_size) / 8; - bit = (i / gd32vf103_info->ppage_size) - (reg * 8); - - if (set) - prot_reg[reg] &= ~(1 << bit); - else - prot_reg[reg] |= (1 << bit); - } - } else { - /* medium density flash */ - for (unsigned i = first; i <= last; i++) { - reg = (i / gd32vf103_info->ppage_size) / 8; - bit = (i / gd32vf103_info->ppage_size) - (reg * 8); - - if (set) - prot_reg[reg] &= ~(1 << bit); - else - prot_reg[reg] |= (1 << bit); - } - } - - status = gd32vf103_erase_options(bank); - if (status != ERROR_OK) - return status; - - gd32vf103_info->option_bytes.protection[0] = prot_reg[0]; - gd32vf103_info->option_bytes.protection[1] = prot_reg[1]; - gd32vf103_info->option_bytes.protection[2] = prot_reg[2]; - gd32vf103_info->option_bytes.protection[3] = prot_reg[3]; - - return gd32vf103_write_options(bank); -} - -static int gd32vf103_write_block(struct flash_bank *bank, const uint8_t *buffer, - uint32_t offset, uint32_t count) -{ - struct gd32vf103_flash_bank *gd32vf103_info = bank->driver_priv; - struct target *target = bank->target; - uint32_t buffer_size = 16384; - struct working_area *write_algorithm; - struct working_area *source; - uint32_t address = bank->base + offset; - struct reg_param reg_params[5]; - int retval = ERROR_OK; - - static const uint8_t gd32vf103_flash_write_code[] = { -#include "../../../contrib/loaders/flash/gd32v/gd32vf103.inc" - }; - - /* flash write code */ - if (target_alloc_working_area(target, sizeof(gd32vf103_flash_write_code), - &write_algorithm) != ERROR_OK) { - LOG_WARNING("no working area available, can't do block memory writes"); - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - } - - retval = target_write_buffer(target, write_algorithm->address, - sizeof(gd32vf103_flash_write_code), gd32vf103_flash_write_code); - if (retval != ERROR_OK) { - target_free_working_area(target, write_algorithm); - return retval; - } - - /* memory buffer */ - while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { - buffer_size /= 2; - buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */ - if (buffer_size <= 256) { - /* we already allocated the writing code, but failed to get a - * buffer, free the algorithm */ - target_free_working_area(target, write_algorithm); - - LOG_WARNING("no large enough working area available, can't do block memory writes"); - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - } - } - - init_reg_param(®_params[0], "a0", 32, PARAM_IN_OUT); /* flash base (in), status (out) */ - init_reg_param(®_params[1], "a1", 32, PARAM_OUT); /* count (halfword-16bit) */ - init_reg_param(®_params[2], "a2", 32, PARAM_OUT); /* buffer start */ - init_reg_param(®_params[3], "a3", 32, PARAM_OUT); /* buffer end */ - init_reg_param(®_params[4], "a4", 32, PARAM_IN_OUT); /* target address */ - - - uint32_t wp_addr = source->address; - uint32_t rp_addr = source->address + 4; - uint32_t fifo_start_addr = source->address + 8; - uint32_t fifo_end_addr = source->address + source->size; - - uint32_t wp = fifo_start_addr; - uint32_t rp = fifo_start_addr; - uint32_t thisrun_bytes = fifo_end_addr-fifo_start_addr-2; /* (2:block size) */ - - retval = target_write_u32(target, rp_addr, rp); - if (retval != ERROR_OK) - return retval; - - while (count > 0) { - retval = target_read_u32(target, rp_addr, &rp); - if (retval != ERROR_OK) { - LOG_ERROR("failed to get read pointer"); - break; - } - - if (wp != rp) { - LOG_ERROR("Failed to write flash ;; rp = 0x%x ;;; wp = 0x%x", rp, wp); - break; - } - wp = fifo_start_addr; - rp = fifo_start_addr; - retval = target_write_u32(target, rp_addr, rp); - if (retval != ERROR_OK) - break; - /* Limit to the amount of data we actually want to write */ - if (thisrun_bytes > count * 2) - thisrun_bytes = count * 2; - - /* Write data to fifo */ - retval = target_write_buffer(target, wp, thisrun_bytes, buffer); - if (retval != ERROR_OK) - break; - - /* Update counters and wrap write pointer */ - buffer += thisrun_bytes; - count -= thisrun_bytes / 2; - rp = fifo_start_addr; - wp = fifo_start_addr+thisrun_bytes; - - /* Store updated write pointer to target */ - retval = target_write_u32(target, wp_addr, wp); - if (retval != ERROR_OK) - break; - retval = target_write_u32(target, rp_addr, rp); - if (retval != ERROR_OK) - return retval; - - buf_set_u32(reg_params[0].value, 0, 32, gd32vf103_info->register_base); - buf_set_u32(reg_params[1].value, 0, 32, thisrun_bytes/2); - buf_set_u32(reg_params[2].value, 0, 32, source->address); - buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size); - buf_set_u32(reg_params[4].value, 0, 32, address); - - retval = target_run_algorithm(target, 0, NULL, 5, reg_params, - write_algorithm->address, write_algorithm->address+4, - 10000, NULL); - - if (retval != ERROR_OK) { - LOG_ERROR("Failed to execute algorithm at 0x%" TARGET_PRIxADDR ": %d", - write_algorithm->address, retval); - return retval; - } - address += thisrun_bytes; - - } - - - if (retval == ERROR_FLASH_OPERATION_FAILED) { - LOG_ERROR("flash write failed at address 0x%"PRIx32, - buf_get_u32(reg_params[4].value, 0, 32)); - - if (buf_get_u32(reg_params[0].value, 0, 32) & FMC_STAT_PGERR) { - LOG_ERROR("flash memory not erased before writing"); - /* Clear but report errors */ - target_write_u32(target, gd32vf103_get_flash_reg(bank, FMC_STAT), FMC_STAT_PGERR); - } - - if (buf_get_u32(reg_params[0].value, 0, 32) & FMC_STAT_WPERR) { - LOG_ERROR("flash memory write protected"); - /* Clear but report errors */ - target_write_u32(target, gd32vf103_get_flash_reg(bank, FMC_STAT), FMC_STAT_WPERR); - } - } - - target_free_working_area(target, source); - target_free_working_area(target, write_algorithm); - - destroy_reg_param(®_params[0]); - destroy_reg_param(®_params[1]); - destroy_reg_param(®_params[2]); - destroy_reg_param(®_params[3]); - destroy_reg_param(®_params[4]); - - return retval; -} - -static int gd32vf103_write(struct flash_bank *bank, const uint8_t *buffer, - uint32_t offset, uint32_t count) -{ - struct target *target = bank->target; - uint8_t *new_buffer = NULL; - - - if (bank->target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - if (offset & 0x1) { - LOG_ERROR("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset); - return ERROR_FLASH_DST_BREAKS_ALIGNMENT; - } - - /* If there's an odd number of bytes, the data has to be padded. Duplicate - * the buffer and use the normal code path with a single block write since - * it's probably cheaper than to special case the last odd write using - * discrete accesses. */ - if (count & 1) { - new_buffer = malloc(count + 1); - if (new_buffer == NULL) { - LOG_ERROR("odd number of bytes to write and no memory for padding buffer"); - return ERROR_FAIL; - } - LOG_INFO("odd number of bytes to write, padding with 0xff"); - buffer = memcpy(new_buffer, buffer, count); - new_buffer[count++] = 0xff; - } - - uint32_t words_remaining = count / 2; - int retval, retval2; - - /* unlock flash registers */ - retval = target_write_u32(target, gd32vf103_get_flash_reg(bank, FMC_KEY), UNLOCK_KEY0); - if (retval != ERROR_OK) - goto cleanup; - retval = target_write_u32(target, gd32vf103_get_flash_reg(bank, FMC_KEY), UNLOCK_KEY1); - if (retval != ERROR_OK) - goto cleanup; - - retval = target_write_u32(target, gd32vf103_get_flash_reg(bank, FMC_CTL), FMC_CTL_PG); - if (retval != ERROR_OK) - goto cleanup; - - /* try using a block write */ - retval = gd32vf103_write_block(bank, buffer, offset, words_remaining); - - if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { - /* if block write failed (no sufficient working area), - * we use normal (slow) single halfword accesses */ - LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); - - while (words_remaining > 0) { - uint16_t value; - memcpy(&value, buffer, sizeof(uint16_t)); - - retval = target_write_u16(target, bank->base + offset, value); - if (retval != ERROR_OK) - goto reset_pg_and_lock; - - retval = gd32vf103_wait_status_busy(bank, 5); - if (retval != ERROR_OK) - goto reset_pg_and_lock; - - words_remaining--; - buffer += 2; - offset += 2; - } - } - -reset_pg_and_lock: - retval2 = target_write_u32(target, gd32vf103_get_flash_reg(bank, FMC_CTL), FMC_CTL_LK); - if (retval == ERROR_OK) - retval = retval2; - -cleanup: - if (new_buffer) - free(new_buffer); - - return retval; -} - -static int gd32vf103_get_device_id(struct flash_bank *bank, uint32_t *device_id) -{ - - struct target *target = bank->target; - uint32_t device_id_register = 0xE0042000; - /* read GD32VF103 device id register */ - int retval = target_read_u32(target, device_id_register, device_id); - if (retval != ERROR_OK) - return retval; - - return retval; -} - -static int gd32vf103_get_flash_size(struct flash_bank *bank, uint16_t *flash_size_in_kb) -{ - struct target *target = bank->target; - uint32_t flash_size_reg = 0x1FFFF7E0; - - int retval = target_read_u16(target, flash_size_reg, flash_size_in_kb); - if (retval != ERROR_OK) - return retval; - - return retval; -} - -static int gd32vf103_probe(struct flash_bank *bank) -{ - struct gd32vf103_flash_bank *gd32vf103_info = bank->driver_priv; - int i; - uint16_t flash_size_in_kb; - uint16_t max_flash_size_in_kb; - uint32_t device_id; - int page_size; - uint32_t base_address = 0x08000000; - - gd32vf103_info->probed = 0; - gd32vf103_info->register_base = FLASH_REG_BASE_B0; - gd32vf103_info->user_data_offset = 10; - gd32vf103_info->option_offset = 0; - - /* default factory protection level */ - gd32vf103_info->default_rdp = 0x5AA5; - - /* read gd32vf103 device id register */ - int retval = gd32vf103_get_device_id(bank, &device_id); - if (retval != ERROR_OK) - return retval; - - LOG_INFO("device id = 0x%08" PRIx32 "", device_id); - - /* set page size, protection granularity and max flash size depending on family */ - switch (device_id & 0xfff) { - case 0x410: - case 0x418: /* connectivity line density */ - page_size = 1024; - gd32vf103_info->ppage_size = 4; - max_flash_size_in_kb = 128; - break; - default: - LOG_WARNING("Cannot identify target as a gd32vf103 family."); - return ERROR_FAIL; - } - - /* get flash size from target. */ - retval = gd32vf103_get_flash_size(bank, &flash_size_in_kb); - LOG_INFO("flash_size_in_kb = 0x%08" PRIx32 "", flash_size_in_kb); - /* failed reading flash size or flash size invalid, default to max target family */ - if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) { - LOG_WARNING("gd32vf103 flash size failed, probe inaccurate - assuming %dk flash", - max_flash_size_in_kb); - flash_size_in_kb = max_flash_size_in_kb; - } - - if (gd32vf103_info->has_dual_banks) { - /* split reported size into matching bank */ - if (bank->base != 0x08080000) { - /* bank 0 will be fixed 512k */ - flash_size_in_kb = 512; - } else { - flash_size_in_kb -= 512; - /* bank1 also uses a register offset */ - gd32vf103_info->register_base = FLASH_REG_BASE_B1; - base_address = 0x08080000; - } - } - - /* if the user sets the size manually then ignore the probed value - * this allows us to work around devices that have a invalid flash size register value */ - if (gd32vf103_info->user_bank_size) { - LOG_INFO("ignoring flash probed value, using configured bank size"); - flash_size_in_kb = gd32vf103_info->user_bank_size / 1024; - } - - LOG_INFO("flash size = %dkbytes", flash_size_in_kb); - - /* did we assign flash size? */ - assert(flash_size_in_kb != 0xffff); - - /* calculate numbers of pages */ - int num_pages = flash_size_in_kb * 1024 / page_size; - - /* check that calculation result makes sense */ - assert(num_pages > 0); - - if (bank->sectors) { - free(bank->sectors); - bank->sectors = NULL; - } - - bank->base = base_address; - bank->size = (num_pages * page_size); - bank->num_sectors = num_pages; - bank->sectors = malloc(sizeof(struct flash_sector) * num_pages); - - for (i = 0; i < num_pages; i++) { - bank->sectors[i].offset = i * page_size; - bank->sectors[i].size = page_size; - bank->sectors[i].is_erased = -1; - bank->sectors[i].is_protected = 1; - } - - gd32vf103_info->probed = 1; - - return ERROR_OK; -} - -static int gd32vf103_auto_probe(struct flash_bank *bank) -{ - struct gd32vf103_flash_bank *gd32vf103_info = bank->driver_priv; - if (gd32vf103_info->probed) - return ERROR_OK; - return gd32vf103_probe(bank); -} - -static int get_gd32vf103_info(struct flash_bank *bank, struct command_invocation *cmd) -{ - uint32_t dbgmcu_idcode; - - /* read gd32vf103 device id register */ - int retval = gd32vf103_get_device_id(bank, &dbgmcu_idcode); - if (retval != ERROR_OK) - return retval; - - uint16_t device_id = dbgmcu_idcode & 0xfff; - uint16_t rev_id = dbgmcu_idcode >> 16; - const char *device_str; - const char *rev_str = NULL; - - switch (device_id) { - - case 0x418: - device_str = "gd32vf103 (gdm32501)"; - - switch (rev_id) { - case 0x1000: - rev_str = "A"; - break; - - case 0x1001: - rev_str = "B"; - break; - } - break; - default: - command_print_sameline(cmd, "Cannot identify target as a GD32VF103 x\n"); - return ERROR_FAIL; - } - - if (rev_str != NULL) - command_print_sameline(cmd, "%s - Rev: %s\n", device_str, rev_str); - else - command_print_sameline(cmd, "%s - Rev: unknown (0x%04x)\n", device_str, rev_id); - - return ERROR_OK; -} - -COMMAND_HANDLER(gd32vf103_handle_lock_command) -{ - struct target *target = NULL; - struct gd32vf103_flash_bank *gd32vf103_info = NULL; - - if (CMD_ARGC < 1) - return ERROR_COMMAND_SYNTAX_ERROR; - - struct flash_bank *bank; - int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); - if (ERROR_OK != retval) - return retval; - - gd32vf103_info = bank->driver_priv; - - target = bank->target; - - if (target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - retval = gd32vf103_check_operation_supported(bank); - if (ERROR_OK != retval) - return retval; - - if (gd32vf103_erase_options(bank) != ERROR_OK) { - command_print(CMD, "gd32vf103 failed to erase options"); - return ERROR_OK; - } - - /* set readout protection */ - gd32vf103_info->option_bytes.RDP = 0; - - if (gd32vf103_write_options(bank) != ERROR_OK) { - command_print(CMD, "gd32vf103 failed to lock device"); - return ERROR_OK; - } - - command_print(CMD, "gd32vf103 locked"); - - return ERROR_OK; -} - -COMMAND_HANDLER(gd32vf103_handle_unlock_command) -{ - struct target *target = NULL; - - if (CMD_ARGC < 1) - return ERROR_COMMAND_SYNTAX_ERROR; - - struct flash_bank *bank; - int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); - if (ERROR_OK != retval) - return retval; - - target = bank->target; - - if (target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - retval = gd32vf103_check_operation_supported(bank); - if (ERROR_OK != retval) - return retval; - - if (gd32vf103_erase_options(bank) != ERROR_OK) { - command_print(CMD, "gd32vf103 failed to unlock device"); - return ERROR_OK; - } - - if (gd32vf103_write_options(bank) != ERROR_OK) { - command_print(CMD, "gd32vf103 failed to lock device"); - return ERROR_OK; - } - - command_print(CMD, "gd32vf103 unlocked.\n" - "INFO: a reset or power cycle is required " - "for the new settings to take effect."); - - return ERROR_OK; -} - -COMMAND_HANDLER(gd32vf103_handle_options_read_command) -{ - uint32_t optionbyte; - struct target *target = NULL; - struct gd32vf103_flash_bank *gd32vf103_info = NULL; - - if (CMD_ARGC < 1) - return ERROR_COMMAND_SYNTAX_ERROR; - - struct flash_bank *bank; - int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); - if (ERROR_OK != retval) - return retval; - - gd32vf103_info = bank->driver_priv; - - target = bank->target; - - if (target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - retval = gd32vf103_check_operation_supported(bank); - if (ERROR_OK != retval) - return retval; - - retval = target_read_u32(target, FMC_OBSTAT_B0, &optionbyte); - if (retval != ERROR_OK) - return retval; - command_print(CMD, "Option Byte: 0x%" PRIx32 "", optionbyte); - - int user_data = optionbyte; - - if (optionbyte >> FMC_OBSTAT_OBERR & 1) - command_print(CMD, "Option Byte Complement Error"); - - if (optionbyte >> FMC_OBSTAT_SPC & 1) - command_print(CMD, "Readout Protection On"); - else - command_print(CMD, "Readout Protection Off"); - - /* user option bytes are offset depending on variant */ - optionbyte >>= gd32vf103_info->option_offset; - - if (optionbyte >> FMC_OBSTAT_WDG_SW & 1) - command_print(CMD, "Software Watchdog"); - else - command_print(CMD, "Hardware Watchdog"); - - if (optionbyte >> FMC_OBSTAT_RST_DSLEEP & 1) - command_print(CMD, "Stop: No reset generated"); - else - command_print(CMD, "Stop: Reset generated"); - - if (optionbyte >> FMC_OBSTAT_RST_STDBY & 1) - command_print(CMD, "Standby: No reset generated"); - else - command_print(CMD, "Standby: Reset generated"); - - if (gd32vf103_info->has_dual_banks) { - if (optionbyte >> FMC_OBSTAT_BB & 1) - command_print(CMD, "Boot: Bank 0"); - else - command_print(CMD, "Boot: Bank 1"); - } - - command_print(CMD, "User Option0: 0x%02" PRIx8, - (uint8_t)((user_data >> gd32vf103_info->user_data_offset) & 0xff)); - command_print(CMD, "User Option1: 0x%02" PRIx8, - (uint8_t)((user_data >> (gd32vf103_info->user_data_offset + 8)) & 0xff)); - - return ERROR_OK; -} - -COMMAND_HANDLER(gd32vf103_handle_options_write_command) -{ - struct target *target = NULL; - struct gd32vf103_flash_bank *gd32vf103_info = NULL; - uint16_t optionbyte; - - if (CMD_ARGC < 2) - return ERROR_COMMAND_SYNTAX_ERROR; - - struct flash_bank *bank; - int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); - if (ERROR_OK != retval) - return retval; - - gd32vf103_info = bank->driver_priv; - - target = bank->target; - - if (target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - retval = gd32vf103_check_operation_supported(bank); - if (ERROR_OK != retval) - return retval; - - retval = gd32vf103_read_options(bank); - if (ERROR_OK != retval) - return retval; - - /* start with current options */ - optionbyte = gd32vf103_info->option_bytes.user_options; - - /* skip over flash bank */ - CMD_ARGC--; - CMD_ARGV++; - - while (CMD_ARGC) { - if (strcmp("SWWDG", CMD_ARGV[0]) == 0) - optionbyte |= (1 << 0); - else if (strcmp("HWWDG", CMD_ARGV[0]) == 0) - optionbyte &= ~(1 << 0); - else if (strcmp("NORSTSTOP", CMD_ARGV[0]) == 0) - optionbyte |= (1 << 1); - else if (strcmp("RSTSTOP", CMD_ARGV[0]) == 0) - optionbyte &= ~(1 << 1); - else if (strcmp("NORSTSTNDBY", CMD_ARGV[0]) == 0) - optionbyte |= (1 << 2); - else if (strcmp("RSTSTNDBY", CMD_ARGV[0]) == 0) - optionbyte &= ~(1 << 2); - else if (gd32vf103_info->has_dual_banks) { - if (strcmp("BOOT0", CMD_ARGV[0]) == 0) - optionbyte |= (1 << 3); - else if (strcmp("BOOT1", CMD_ARGV[0]) == 0) - optionbyte &= ~(1 << 3); - else - return ERROR_COMMAND_SYNTAX_ERROR; - } else - return ERROR_COMMAND_SYNTAX_ERROR; - CMD_ARGC--; - CMD_ARGV++; - } - - if (gd32vf103_erase_options(bank) != ERROR_OK) { - command_print(CMD, "gd32vf103 failed to erase options"); - return ERROR_OK; - } - - gd32vf103_info->option_bytes.user_options = optionbyte; - - if (gd32vf103_write_options(bank) != ERROR_OK) { - command_print(CMD, "gd32vf103 failed to write options"); - return ERROR_OK; - } - - command_print(CMD, "gd32vf103 write options complete.\n" - "INFO: a reset or power cycle is required " - "for the new settings to take effect."); - - return ERROR_OK; -} - -static int gd32vf103_mass_erase(struct flash_bank *bank) -{ - struct target *target = bank->target; - - if (target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - /* unlock option flash registers */ - int retval = target_write_u32(target, gd32vf103_get_flash_reg(bank, FMC_KEY), UNLOCK_KEY0); - if (retval != ERROR_OK) - return retval; - retval = target_write_u32(target, gd32vf103_get_flash_reg(bank, FMC_KEY), UNLOCK_KEY1); - if (retval != ERROR_OK) - return retval; - - /* mass erase flash memory */ - retval = target_write_u32(target, gd32vf103_get_flash_reg(bank, FMC_CTL), FMC_CTL_MER); - if (retval != ERROR_OK) - return retval; - retval = target_write_u32(target, gd32vf103_get_flash_reg(bank, FMC_CTL), - FMC_CTL_MER | FMC_CTL_START); - if (retval != ERROR_OK) - return retval; - - retval = gd32vf103_wait_status_busy(bank, FLASH_ERASE_TIMEOUT); - if (retval != ERROR_OK) - return retval; - - retval = target_write_u32(target, gd32vf103_get_flash_reg(bank, FMC_CTL), FMC_CTL_LK); - if (retval != ERROR_OK) - return retval; - - return ERROR_OK; -} - -COMMAND_HANDLER(gd32vf103_handle_mass_erase_command) -{ - if (CMD_ARGC < 1) - return ERROR_COMMAND_SYNTAX_ERROR; - - struct flash_bank *bank; - int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); - if (ERROR_OK != retval) - return retval; - - retval = gd32vf103_mass_erase(bank); - if (retval == ERROR_OK) { - /* set all sectors as erased */ - for (unsigned i = 0; i < bank->num_sectors; i++) - bank->sectors[i].is_erased = 1; - - command_print(CMD, "gd32vf103 mass erase complete"); - } else - command_print(CMD, "gd32vf103 mass erase failed"); - - return retval; -} - -static const struct command_registration gd32vf103_exec_command_handlers[] = { - { - .name = "lock", - .handler = gd32vf103_handle_lock_command, - .mode = COMMAND_EXEC, - .usage = "bank_id", - .help = "Lock entire flash device.", - }, - { - .name = "unlock", - .handler = gd32vf103_handle_unlock_command, - .mode = COMMAND_EXEC, - .usage = "bank_id", - .help = "Unlock entire protected flash device.", - }, - { - .name = "mass_erase", - .handler = gd32vf103_handle_mass_erase_command, - .mode = COMMAND_EXEC, - .usage = "bank_id", - .help = "Erase entire flash device.", - }, - { - .name = "options_read", - .handler = gd32vf103_handle_options_read_command, - .mode = COMMAND_EXEC, - .usage = "bank_id", - .help = "Read and display device option byte.", - }, - { - .name = "options_write", - .handler = gd32vf103_handle_options_write_command, - .mode = COMMAND_EXEC, - .usage = "bank_id ('SWWDG'|'HWWDG') " - "('RSTSTNDBY'|'NORSTSTNDBY') " - "('RSTSTOP'|'NORSTSTOP')", - .help = "Replace bits in device option byte.", - }, - COMMAND_REGISTRATION_DONE -}; - -static const struct command_registration gd32vf103_command_handlers[] = { - { - .name = "gd32vf103", - .mode = COMMAND_ANY, - .help = "gd32vf103 flash command group", - .usage = "", - .chain = gd32vf103_exec_command_handlers, - }, - COMMAND_REGISTRATION_DONE -}; - -struct flash_driver gd32vf103_flash = { - .name = "gd32vf103", - .commands = gd32vf103_command_handlers, - .flash_bank_command = gd32vf103_flash_bank_command, - .erase = gd32vf103_erase, - .protect = gd32vf103_protect, - .write = gd32vf103_write, - .read = default_flash_read, - .probe = gd32vf103_probe, - .auto_probe = gd32vf103_auto_probe, - .erase_check = default_flash_blank_check, - .protect_check = gd32vf103_protect_check, - .info = get_gd32vf103_info, - .free_driver_priv = default_flash_free_driver_priv, -}; |