flash/nor/stm32h7x: fix option bytes handling to work with both banks
To achieve that we need to avoid using FLASH_REG_BASE_B0, and use bank registers instead: For dual bank devices, each option register is mapped in 2 addresses at the same offset from flash_bank_reg_base. This is true for OPTCR, OPTKEYR, OPTSR_CUR/PRG, OPTCCR according to RM0433 Rev6 (refer to section 3.9: FLASH registers) In stm32x_write_options, according to RM0433 Rev6, after OBL launch we should wait for OPTSR_CUR.BSY bit instead of FLASH_SR.QW Change-Id: Ie24a91f069d03c9233797390fc2e925c737dad90 Signed-off-by: Tarek BOCHKATI <tarek.bouchkati@gmail.com> Reviewed-on: http://openocd.zylin.com/5291 Tested-by: jenkins Reviewed-by: Christopher Head <chead@zaber.com> Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
This commit is contained in:
parent
1b276c0ad5
commit
8d8c6df557
|
@ -79,6 +79,9 @@
|
|||
#define OPT_LOCK (1 << 0)
|
||||
#define OPT_START (1 << 1)
|
||||
|
||||
/* FLASH_OPTSR register bits */
|
||||
#define OPT_BSY (1 << 0)
|
||||
|
||||
/* register unlock keys */
|
||||
#define KEY1 0x45670123
|
||||
#define KEY2 0xCDEF89AB
|
||||
|
@ -263,7 +266,7 @@ static int stm32x_unlock_option_reg(struct flash_bank *bank)
|
|||
uint32_t ctrl;
|
||||
struct target *target = bank->target;
|
||||
|
||||
int retval = target_read_u32(target, FLASH_REG_BASE_B0 + FLASH_OPTCR, &ctrl);
|
||||
int retval = target_read_u32(target, stm32x_get_flash_reg(bank, FLASH_OPTCR), &ctrl);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
|
@ -271,15 +274,15 @@ static int stm32x_unlock_option_reg(struct flash_bank *bank)
|
|||
return ERROR_OK;
|
||||
|
||||
/* unlock option registers */
|
||||
retval = target_write_u32(target, FLASH_REG_BASE_B0 + FLASH_OPTKEYR, OPTKEY1);
|
||||
retval = target_write_u32(target, stm32x_get_flash_reg(bank, FLASH_OPTKEYR), OPTKEY1);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
retval = target_write_u32(target, FLASH_REG_BASE_B0 + FLASH_OPTKEYR, OPTKEY2);
|
||||
retval = target_write_u32(target, stm32x_get_flash_reg(bank, FLASH_OPTKEYR), OPTKEY2);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
retval = target_read_u32(target, FLASH_REG_BASE_B0 + FLASH_OPTCR, &ctrl);
|
||||
retval = target_read_u32(target, stm32x_get_flash_reg(bank, FLASH_OPTCR), &ctrl);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
|
@ -310,7 +313,7 @@ static int stm32x_read_options(struct flash_bank *bank)
|
|||
struct target *target = bank->target;
|
||||
|
||||
/* read current option bytes */
|
||||
int retval = target_read_u32(target, FLASH_REG_BASE_B0 + FLASH_OPTSR_CUR, &optiondata);
|
||||
int retval = target_read_u32(target, stm32x_get_flash_reg(bank, FLASH_OPTSR_CUR), &optiondata);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
|
@ -349,7 +352,7 @@ static int stm32x_write_options(struct flash_bank *bank)
|
|||
optiondata |= (stm32x_info->option_bytes.user3_options & 0xa3) << 24;
|
||||
|
||||
/* program options */
|
||||
retval = target_write_u32(target, FLASH_REG_BASE_B0 + FLASH_OPTSR_PRG, optiondata);
|
||||
retval = target_write_u32(target, stm32x_get_flash_reg(bank, FLASH_OPTSR_PRG), optiondata);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
|
@ -361,12 +364,12 @@ static int stm32x_write_options(struct flash_bank *bank)
|
|||
|
||||
optiondata = 0x40000000;
|
||||
/* Remove OPT error flag before programming */
|
||||
retval = target_write_u32(target, FLASH_REG_BASE_B0 + FLASH_OPTCCR, optiondata);
|
||||
retval = target_write_u32(target, stm32x_get_flash_reg(bank, FLASH_OPTCCR), optiondata);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
/* start programming cycle */
|
||||
retval = target_write_u32(target, FLASH_REG_BASE_B0 + FLASH_OPTCR, OPT_START);
|
||||
retval = target_write_u32(target, stm32x_get_flash_reg(bank, FLASH_OPTCR), OPT_START);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
|
@ -374,23 +377,23 @@ static int stm32x_write_options(struct flash_bank *bank)
|
|||
int timeout = FLASH_ERASE_TIMEOUT;
|
||||
for (;;) {
|
||||
uint32_t status;
|
||||
retval = target_read_u32(target, FLASH_REG_BASE_B0 + FLASH_SR, &status);
|
||||
retval = target_read_u32(target, stm32x_get_flash_reg(bank, FLASH_OPTSR_CUR), &status);
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_INFO("stm32x_write_options: wait_flash_op_queue : error");
|
||||
LOG_INFO("stm32x_write_options: failed to read FLASH_OPTSR_CUR");
|
||||
return retval;
|
||||
}
|
||||
if ((status & FLASH_QW) == 0)
|
||||
if ((status & OPT_BSY) == 0)
|
||||
break;
|
||||
|
||||
if (timeout-- <= 0) {
|
||||
LOG_INFO("wait_flash_op_queue, time out expired, status: 0x%" PRIx32 "", status);
|
||||
LOG_INFO("waiting for OBL launch, time out expired, OPTSR: 0x%" PRIx32 "", status);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
alive_sleep(1);
|
||||
}
|
||||
|
||||
/* relock option registers */
|
||||
retval = target_write_u32(target, FLASH_REG_BASE_B0 + FLASH_OPTCR, OPT_LOCK);
|
||||
retval = target_write_u32(target, stm32x_get_flash_reg(bank, FLASH_OPTCR), OPT_LOCK);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
|
@ -904,13 +907,6 @@ COMMAND_HANDLER(stm32x_handle_lock_command)
|
|||
stm32x_info = bank->driver_priv;
|
||||
target = bank->target;
|
||||
|
||||
/* if we have a dual flash bank device then
|
||||
* we need to perform option byte lock on bank0 only */
|
||||
if (stm32x_info->flash_base != FLASH_REG_BASE_B0) {
|
||||
LOG_ERROR("Option Byte Lock Operation must use bank0");
|
||||
return ERROR_FLASH_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("Target not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
|
@ -921,6 +917,9 @@ COMMAND_HANDLER(stm32x_handle_lock_command)
|
|||
bank->driver->name);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
LOG_WARNING("locking the entire flash device");
|
||||
|
||||
/* set readout protection */
|
||||
stm32x_info->option_bytes.RDP = 0;
|
||||
|
||||
|
@ -950,13 +949,6 @@ COMMAND_HANDLER(stm32x_handle_unlock_command)
|
|||
stm32x_info = bank->driver_priv;
|
||||
target = bank->target;
|
||||
|
||||
/* if we have a dual flash bank device then
|
||||
* we need to perform option byte unlock on bank0 only */
|
||||
if (stm32x_info->flash_base != FLASH_REG_BASE_B0) {
|
||||
LOG_ERROR("Option Byte Unlock Operation must use bank0");
|
||||
return ERROR_FLASH_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("Target not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
|
@ -967,6 +959,8 @@ COMMAND_HANDLER(stm32x_handle_unlock_command)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
LOG_WARNING("unlocking the entire flash device");
|
||||
|
||||
/* clear readout protection option byte
|
||||
* this will also force a device unlock if set */
|
||||
stm32x_info->option_bytes.RDP = 0xAA;
|
||||
|
|
Loading…
Reference in New Issue