flash/nor/stm32l4x: fix permanent write protection on STM32U5

Unlike other devices supported by this driver STM32U5 devices
have a new UNLOCK bit in FLASH_WRP1AR, WRP1BR, WRP2AR, WRP2BR
registers. Writing zero to this bit makes the write protection
block permanent with no way to unprotect.

Commit 6554d176e9 ("flash/stm32l4x: support STM32U59/U5Ax devices")
and later commits with additional U5 devices lack support for
the UNLOCK bit and therefore makes write protection permanent
without warning.

Introduce the new bit flag F_WRP_HAS_LOCK and mark U5 devices by it.
Set UNLOCK bit in stm32l4_write_one_wrpxy() if F_WRP_HAS_LOCK is set.

Change-Id: I26b97d855e094a21540e3377f367520683af2eac
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: https://review.openocd.org/c/openocd/+/8981
Tested-by: jenkins
This commit is contained in:
Tomas Vanek
2025-07-03 06:52:29 +02:00
parent 09a54c3a89
commit cbc32c3831
2 changed files with 16 additions and 4 deletions

View File

@@ -152,6 +152,9 @@
/* this flag indicates that programming should be done in quad-word
* the default programming word size is double-word */
#define F_QUAD_WORD_PROG BIT(4)
/* the registers WRPxyR have UNLOCK bit - writing zero locks the write
* protection region permanently! */
#define F_WRP_HAS_LOCK BIT(5)
/* end of STM32L4 flags ******************************************************/
@@ -500,7 +503,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
.num_revs = ARRAY_SIZE(stm32u53_u54xx_revs),
.device_str = "STM32U535/U545",
.max_flash_size_kb = 512,
.flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ | F_HAS_L5_FLASH_REGS,
.flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ
| F_HAS_L5_FLASH_REGS | F_WRP_HAS_LOCK,
.flash_regs_base = 0x40022000,
.fsize_addr = 0x0BFA07A0,
.otp_base = 0x0BFA0000,
@@ -692,7 +696,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
.num_revs = ARRAY_SIZE(stm32u59_u5axx_revs),
.device_str = "STM32U59/U5Axx",
.max_flash_size_kb = 4096,
.flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ | F_HAS_L5_FLASH_REGS,
.flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ
| F_HAS_L5_FLASH_REGS | F_WRP_HAS_LOCK,
.flash_regs_base = 0x40022000,
.fsize_addr = 0x0BFA07A0,
.otp_base = 0x0BFA0000,
@@ -704,7 +709,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
.num_revs = ARRAY_SIZE(stm32u57_u58xx_revs),
.device_str = "STM32U57/U58xx",
.max_flash_size_kb = 2048,
.flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ | F_HAS_L5_FLASH_REGS,
.flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ
| F_HAS_L5_FLASH_REGS | F_WRP_HAS_LOCK,
.flash_regs_base = 0x40022000,
.fsize_addr = 0x0BFA07A0,
.otp_base = 0x0BFA0000,
@@ -716,7 +722,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
.num_revs = ARRAY_SIZE(stm32u5f_u5gxx_revs),
.device_str = "STM32U5F/U5Gxx",
.max_flash_size_kb = 4096,
.flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ | F_HAS_L5_FLASH_REGS,
.flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ
| F_HAS_L5_FLASH_REGS | F_WRP_HAS_LOCK,
.flash_regs_base = 0x40022000,
.fsize_addr = 0x0BFA07A0,
.otp_base = 0x0BFA0000,
@@ -1287,6 +1294,8 @@ static int stm32l4_write_one_wrpxy(struct flash_bank *bank, struct stm32l4_wrp *
int wrp_end = wrpxy->last - wrpxy->offset;
uint32_t wrp_value = (wrp_start & stm32l4_info->wrpxxr_mask) | ((wrp_end & stm32l4_info->wrpxxr_mask) << 16);
if (stm32l4_info->part_info->flags & F_WRP_HAS_LOCK)
wrp_value |= FLASH_WRPXYR_UNLOCK;
return stm32l4_write_option(bank, stm32l4_info->flash_regs[wrpxy->reg_idx], wrp_value, 0xffffffff);
}

View File

@@ -69,6 +69,9 @@
#define FLASH_U5_DUALBANK BIT(21)
#define FLASH_TZEN BIT(31)
/* FLASH_WRPxyR register bits */
#define FLASH_WRPXYR_UNLOCK BIT(31)
/* FLASH secure block based bank 1/2 register offsets */
#define FLASH_SECBB1(X) (0x80 + 4 * (X - 1))
#define FLASH_SECBB2(X) (0xA0 + 4 * (X - 1))