summaryrefslogtreecommitdiff
path: root/chip/stm32
diff options
context:
space:
mode:
authorScott Collyer <scollyer@google.com>2021-05-21 11:33:37 -0700
committerCommit Bot <commit-bot@chromium.org>2021-05-27 01:38:30 +0000
commitebede7bc951cbaa75dc24bd66d8705ae62a6dab0 (patch)
tree8b7305194cbedd640f5a4b4da9dc1f44934b9676 /chip/stm32
parent2a85f58b5c17afc725784de5c9d86dcd3a1ba9d8 (diff)
downloadchrome-ec-ebede7bc951cbaa75dc24bd66d8705ae62a6dab0.tar.gz
stm32g4: flash: Add DBANK support to option bytes WRP
This CL adds support for the option bytes for dual-bank (DBANK) mode in category 3 devices. The MCU being used on honeybuns, is a category 3 flash device and DBANK mode is enalbed in the option bytes by default. When DBANK mode is enabled, then more than 1 WRP register is needed to protect the RW image. In this mode, WRP register can only protect 64 flash pages in one flash bank. BUG=b:183686750 BRANCH=quiche TEST= Case 1: HW WP active and code executing in RW > flashinfo Usable: 256 KB Write: 4 B (ideal 4 B) Erase: 2048 B (to 1-bits) Protect: 2048 B flash-phy: WRP_RO: start = 0, end = 31 flash-phy: WRP_RW: start = 32, end = 127 Flags: wp_gpio_asserted ro_at_boot ro_now all_now Protected now: YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY Case 2: HW WP active active and code executing in RO flashinfo Usable: 256 KB Write: 4 B (ideal 4 B) Erase: 2048 B (to 1-bits) Protect: 2048 B flash-phy: WRP_RO: start = 0, end = 31 flash-phy: WRP_RW: start = 127, end = 0 Flags: wp_gpio_asserted ro_at_boot ro_now Protected now: YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ Case 3: HW WP disabled > flashinfo Usable: 256 KB Write: 4 B (ideal 4 B) Erase: 2048 B (to 1-bits) Protect: 2048 B flash-phy: WRP_RO: start = 127, end = 0 flash-phy: WRP_RW: start = 127, end = 0 Flags: ro_at_boot Protected now: ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ Signed-off-by: Scott Collyer <scollyer@google.com> Change-Id: I72c03029b0231ee864afc967905c50acba4ba5de Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2911738 Tested-by: Scott Collyer <scollyer@chromium.org> Reviewed-by: Aseda Aboagye <aaboagye@chromium.org> Commit-Queue: Scott Collyer <scollyer@chromium.org>
Diffstat (limited to 'chip/stm32')
-rw-r--r--chip/stm32/config-stm32g473xc.h2
-rw-r--r--chip/stm32/flash-stm32g4-l4.c269
-rw-r--r--chip/stm32/registers-stm32g4.h51
3 files changed, 262 insertions, 60 deletions
diff --git a/chip/stm32/config-stm32g473xc.h b/chip/stm32/config-stm32g473xc.h
index 8771ff455b..1cb5133121 100644
--- a/chip/stm32/config-stm32g473xc.h
+++ b/chip/stm32/config-stm32g473xc.h
@@ -25,6 +25,8 @@
#define CONFIG_FLASH_BANK_SIZE (2 * 1024)
#define CONFIG_FLASH_ERASE_SIZE CONFIG_FLASH_BANK_SIZE
+/* Dual-bank (DBANK) mode is enabled by default for this chip */
+#define STM32_FLASH_DBANK_MODE
/* Erasing 128K can take up to 2s, need to defer erase. */
#define CONFIG_FLASH_DEFERRED_ERASE
diff --git a/chip/stm32/flash-stm32g4-l4.c b/chip/stm32/flash-stm32g4-l4.c
index 360d63a739..c04c17bb3b 100644
--- a/chip/stm32/flash-stm32g4-l4.c
+++ b/chip/stm32/flash-stm32g4-l4.c
@@ -30,17 +30,6 @@
* used in the STM32 TRMs. Redifining macros here in terms of pages in order to
* match STM32 documentation for write protect computations in this file.
*
- * Two write protect (WRP) regions can be defined in the option bytes. The
- * assumption is that 1st WRP area is for RO and the 2nd WRP is for RW if RW WRP
- * config is selected. If RW is being write-protected, it is assume to be the
- * 1st page following the RO section until the last flash page. WRP areas are
- * specified in terms of page indices with a start index and an end index.
- * start == end means a single page is protected.
- *
- * WRP1a_start = WRP1a_end --> WRP1a_start page is protected
- * WRP1a_start > WRP1a_end --> No WRP area is specified
- * WRP1a_start < WRP1a_end --> Pages WRP1a_start to WRP1a_end protected
- *
* These macros are from the common flash API and mean the following:
* WP_BANK_OFFSET -> index of first RO page
* CONFIG_WP_STORAGE_SIZE -> size of RO region in bytes
@@ -59,7 +48,11 @@
#define FLASH_PAGE_ROLLBACK_LAST_IDX (FLASH_PAGE_ROLLBACK_FIRST_IDX +\
FLASH_PAGE_ROLLBACK_COUNT -1)
+#ifdef STM32_FLASH_DBANK_MODE
#define FLASH_WRP_MASK (FLASH_PAGE_MAX_COUNT - 1)
+#else
+#define FLASH_WRP_MASK ((FLASH_PAGE_MAX_COUNT) / 2 - 1)
+#endif /* CONFIG_FLASH_DBANK_MODE */
#define FLASH_WRP_START(val) ((val) & FLASH_WRP_MASK)
#define FLASH_WRP_END(val) (((val) >> 16) & FLASH_WRP_MASK)
#define FLASH_WRP_RANGE(start, end) (((start) & FLASH_WRP_MASK) | \
@@ -67,6 +60,17 @@
#define FLASH_WRP_RANGE_DISABLED FLASH_WRP_RANGE(FLASH_WRP_MASK, 0x00)
#define FLASH_WRP1X_MASK FLASH_WRP_RANGE(FLASH_WRP_MASK, FLASH_WRP_MASK)
+enum wrp_region {
+ WRP_RO,
+ WRP_RW,
+};
+
+struct wrp_info {
+ int enable;
+ int start;
+ int end;
+};
+
static inline int calculate_flash_timeout(void)
{
return (FLASH_TIMEOUT_US *
@@ -166,31 +170,195 @@ static int commit_optb(void)
return EC_SUCCESS;
}
+/*
+ * There are a minimum of 2 WRP regions that can be set. The STM32G4
+ * family has both category 2, and category 3 devices. Category 2
+ * devices have only 2 WRP regions, but category 3 devices have 4 WRP
+ * regions that can be configured. Category 3 devices also support dual
+ * flash banks, and this mode is the default setting. When DB mode is enabled,
+ * then each WRP register can only protect up to 64 2kB pages. This means that
+ * one WRP register is needed per bank.
+ *
+ * 1. WRP1A -> used always for RO
+ * 2. WRP1B -> used always for RW
+ * 3. WRP2A -> may be used for RW if dual-bank (DB) mode is enabled
+ * 4. WRP2B -> currently never used
+ *
+ * WRP areas are specified in terms of page indices with a start index
+ * and an end index. start == end means a single page is protected.
+ *
+ * WRPnx_start = WRPnx_end --> WRPnx_start page is protected
+ * WRPnx_start > WRPnx_end --> No WRP area is specified
+ * WRPnx_start < WRPnx_end --> Pages WRPnx_start to WRPnx_end
+ */
+static void optb_get_wrp(enum wrp_region region, struct wrp_info *wrp)
+{
+#ifdef STM32_FLASH_DBANK_MODE
+ int start;
+ int end;
+#endif
+ /* Assume WRP regions are not configured */
+ wrp->start = FLASH_WRP_MASK;
+ wrp->end = 0;
+ wrp->enable = 0;
+
+ if (region == WRP_RO) {
+ /*
+ * RO write protect is fully described by WRP1AR. Get the
+ * start/end indices. If end >= start, then RO write protect is
+ * enabled.
+ */
+ wrp->start = FLASH_WRP_START(STM32_FLASH_WRP1AR);
+ wrp->end = FLASH_WRP_END(STM32_FLASH_WRP1AR);
+ wrp->enable = wrp->end >= wrp->start;
+ } else if (region == WRP_RW) {
+ /*
+ * RW write always uses WRP1BR. If dual-bank mode is being used,
+ * then WRP2AR must also be check to determine the full range of
+ * flash page indices being protected.
+ */
+ wrp->start = FLASH_WRP_START(STM32_FLASH_WRP1BR);
+ wrp->end = FLASH_WRP_END(STM32_FLASH_WRP1BR);
+ wrp->enable = wrp->end >= wrp->start;
+#ifdef STM32_FLASH_DBANK_MODE
+ start = FLASH_WRP_START(STM32_FLASH_WRP2AR);
+ end = FLASH_WRP_END(STM32_FLASH_WRP2AR);
+ /*
+ * If WRP2AR protection is enabled, then need to adjust either
+ * the start, end, or both indices.
+ */
+ if (end >= start) {
+ if (wrp->enable) {
+ /* WRP1BR is active, only need to adjust end */
+ wrp->end += end;
+ } else {
+ /*
+ * WRP1BR is not active, so RW protection, if
+ * enabled, is fully controlled by WRP2AR.
+ */
+ wrp->start = start;
+ wrp->end = end;
+ wrp->enable = 1;
+ }
+ }
+#endif
+ }
+}
+
+static void optb_set_wrp(enum wrp_region region, struct wrp_info *wrp)
+{
+ int start = wrp->start;
+ int end = wrp->end;
+
+ if (!wrp->enable) {
+ /*
+ * If enable is not set, then ignore the passed in start/end
+ * values and set start/end to the default not protected range
+ * which satisfies start > end
+ */
+ start = FLASH_WRP_MASK;
+ end = 0;
+ }
+
+ if (region == WRP_RO) {
+ /* For RO can always use start/end directly */
+ STM32_FLASH_WRP1AR = FLASH_WRP_RANGE(start, end);
+ } else if (region == WRP_RW) {
+#ifdef STM32_FLASH_DBANK_MODE
+ /*
+ * In the dual-bank flash case (STM32G4 Category 3 devices with
+ * DB bit set), RW write protect can use both WRP1BR and WRP2AR
+ * registers in order to span the full flash memory range.
+ */
+ if (wrp->enable) {
+ int rw_end;
+
+ /*
+ * If the 1st RW flash page is in the 1st half of
+ * memory, then at least one block will be protected by
+ * WRP1BR. If the end flash page is in the 2nd half of
+ * memory, then cap the end for WRP1BR to its max
+ * value. Otherwise, can use end passed in directly.
+ */
+ if (start <= FLASH_WRP_MASK) {
+ rw_end = end > FLASH_WRP_MASK ?
+ FLASH_WRP_MASK : end;
+ STM32_FLASH_WRP1BR = FLASH_WRP_RANGE(start,
+ rw_end);
+ }
+ /*
+ * If the last RW flash page is in the 2nd half of
+ * memory, then at least one block will be protected by
+ * WRP2AR. If the start flash page is in the 2nd half of
+ * memory, can use start directly. Otherwise, start
+ * needs to be set to 0 here.
+ */
+ if (end > FLASH_WRP_MASK) {
+ rw_end = end & FLASH_WRP_MASK;
+ STM32_FLASH_WRP2AR = FLASH_WRP_RANGE(0, rw_end);
+ }
+ } else {
+ /*
+ * RW write protect is being disabled. Set both WRP1BR
+ * and WRP2AR to default start > end not protected
+ * state.
+ */
+ STM32_FLASH_WRP1BR = FLASH_WRP_RANGE(start, end);
+ STM32_FLASH_WRP2AR = FLASH_WRP_RANGE(start, end);
+ }
+#else
+ /* Single bank case, WRP1BR can cover the full memory range */
+ STM32_FLASH_WRP1BR = FLASH_WRP_RANGE(start, end);
+#endif
+ }
+}
+
static void unprotect_all_blocks(void)
{
+ struct wrp_info wrp;
+
+ /* Set info values to unprotected */
+ wrp.start = FLASH_WRP_MASK;
+ wrp.end = 0;
+ wrp.enable = 0;
+
unlock_optb();
- STM32_FLASH_WRP1AR = FLASH_WRP_RANGE_DISABLED;
- STM32_FLASH_WRP1BR = FLASH_WRP_RANGE_DISABLED;
+ /* Disable RO WRP */
+ optb_set_wrp(WRP_RO, &wrp);
+ /* Disable RW WRP */
+ optb_set_wrp(WRP_RW, &wrp);
commit_optb();
}
int flash_physical_protect_at_boot(uint32_t new_flags)
{
- uint32_t ro_range = FLASH_WRP_RANGE_DISABLED;
- uint32_t rb_rw_range = FLASH_WRP_RANGE_DISABLED;
+ struct wrp_info wrp_ro;
+ struct wrp_info wrp_rw;
+
+ wrp_ro.start = FLASH_WRP_MASK;
+ wrp_ro.end = 0;
+ wrp_ro.enable = 0;
+
+ wrp_rw.start = FLASH_WRP_MASK;
+ wrp_rw.end = 0;
+ wrp_rw.enable = 0;
+
/*
- * WRP1AR is storing the write-protection range for the RO region.
- * WRP1BR is storing the write-protection range for the
- * rollback and RW regions.
+ * Default operation for this function is to disable both RO and RW
+ * write protection in the option bytes. Based on new_flags either RO or
+ * RW or both regions write protect may be set.
*/
if (new_flags & (EC_FLASH_PROTECT_ALL_AT_BOOT |
- EC_FLASH_PROTECT_RO_AT_BOOT))
- ro_range = FLASH_WRP_RANGE(FLASH_RO_FIRST_PAGE_IDX,
- FLASH_RO_LAST_PAGE_IDX);
+ EC_FLASH_PROTECT_RO_AT_BOOT)) {
+ wrp_ro.start = FLASH_RO_FIRST_PAGE_IDX;
+ wrp_ro.end = FLASH_RO_LAST_PAGE_IDX;
+ wrp_ro.enable = 1;
+ }
if (new_flags & EC_FLASH_PROTECT_ALL_AT_BOOT) {
- rb_rw_range = FLASH_WRP_RANGE(FLASH_RW_FIRST_PAGE_IDX,
- FLASH_RW_LAST_PAGE_IDX);
+ wrp_rw.start = FLASH_RW_FIRST_PAGE_IDX;
+ wrp_rw.end = FLASH_RW_LAST_PAGE_IDX;
+ wrp_rw.enable = 1;
} else {
/*
* Start index will be 1st index following RO region index. The
@@ -199,7 +367,7 @@ int flash_physical_protect_at_boot(uint32_t new_flags)
* the 2nd memory protection area get written in option bytes.
*/
int start = FLASH_RW_FIRST_PAGE_IDX;
- int end = FLASH_WRP_END(FLASH_WRP_RANGE_DISABLED);
+ int end = 0;
#ifdef CONFIG_ROLLBACK
if (new_flags & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT) {
start = FLASH_PAGE_ROLLBACK_FIRST_IDX;
@@ -213,8 +381,11 @@ int flash_physical_protect_at_boot(uint32_t new_flags)
end = FLASH_RW_LAST_PAGE_IDX;
#endif /* CONFIG_FLASH_PROTECT_RW */
- if (end != FLASH_WRP_END(FLASH_WRP_RANGE_DISABLED))
- rb_rw_range = FLASH_WRP_RANGE(start, end);
+ if (end) {
+ wrp_rw.start = start;
+ wrp_rw.end = end;
+ wrp_rw.enable = 1;
+ }
}
unlock_optb();
@@ -225,8 +396,8 @@ int flash_physical_protect_at_boot(uint32_t new_flags)
*/
STM32_FLASH_OPTR = (STM32_FLASH_OPTR & ~0xff) | 0x11;
#endif
- STM32_FLASH_WRP1AR = ro_range;
- STM32_FLASH_WRP1BR = rb_rw_range;
+ optb_set_wrp(WRP_RO, &wrp_ro);
+ optb_set_wrp(WRP_RW, &wrp_rw);
commit_optb();
return EC_SUCCESS;
@@ -391,13 +562,14 @@ exit_er:
int flash_physical_get_protect(int block)
{
- uint32_t wrp1ar = STM32_FLASH_WRP1AR;
- uint32_t wrp1br = STM32_FLASH_WRP1BR;
+ struct wrp_info wrp_ro;
+ struct wrp_info wrp_rw;
+
+ optb_get_wrp(WRP_RO, &wrp_ro);
+ optb_get_wrp(WRP_RW, &wrp_rw);
- return ((block >= FLASH_WRP_START(wrp1ar)) &&
- (block <= FLASH_WRP_END(wrp1ar))) ||
- ((block >= FLASH_WRP_START(wrp1br)) &&
- (block <= FLASH_WRP_END(wrp1br)));
+ return ((block >= wrp_ro.start) && (block <= wrp_ro.end)) ||
+ ((block >= wrp_rw.start) && (block <= wrp_rw.end));
}
/*
@@ -407,29 +579,30 @@ int flash_physical_get_protect(int block)
uint32_t flash_physical_get_protect_flags(void)
{
uint32_t flags = 0;
- uint32_t wrp1ar = STM32_OPTB_WRP1AR;
- uint32_t wrp1br = STM32_OPTB_WRP1BR;
+ struct wrp_info wrp_ro;
+ struct wrp_info wrp_rw;
+
+ optb_get_wrp(WRP_RO, &wrp_ro);
+ optb_get_wrp(WRP_RW, &wrp_rw);
- /* RO region protection range is in WRP1AR range */
- if (wrp1ar == FLASH_WRP_RANGE(FLASH_RO_FIRST_PAGE_IDX,
- FLASH_RO_LAST_PAGE_IDX))
+ /* Check if RO is fully protected */
+ if (wrp_ro.start == FLASH_RO_FIRST_PAGE_IDX &&
+ wrp_ro.end == FLASH_RO_LAST_PAGE_IDX)
flags |= EC_FLASH_PROTECT_RO_AT_BOOT;
- /* Rollback and RW regions protection range is in WRP1BR range */
- if (wrp1br != FLASH_WRP_RANGE_DISABLED) {
- int end = FLASH_WRP_END(wrp1br);
- int strt = FLASH_WRP_START(wrp1br);
+
+ if (wrp_rw.enable) {
#ifdef CONFIG_ROLLBACK
- if (strt <= FLASH_PAGE_ROLLBACK_FIRST_IDX &&
- end >= FLASH_PAGE_ROLLBACK_LAST_IDX)
+ if (wrp_rw.start <= FLASH_PAGE_ROLLBACK_FIRST_IDX &&
+ wrp_rw.end >= FLASH_PAGE_ROLLBACK_LAST_IDX)
flags |= EC_FLASH_PROTECT_ROLLBACK_AT_BOOT;
#endif /* CONFIG_ROLLBACK */
#ifdef CONFIG_FLASH_PROTECT_RW
- if (end == PHYSICAL_BANKS)
+ if (wrp_rw.end == PHYSICAL_BANKS)
flags |= EC_FLASH_PROTECT_RW_AT_BOOT;
#endif /* CONFIG_FLASH_PROTECT_RW */
- if (end == PHYSICAL_BANKS &&
- strt == WP_BANK_OFFSET + WP_BANK_COUNT &&
+ if (wrp_rw.end == PHYSICAL_BANKS &&
+ wrp_rw.start == WP_BANK_OFFSET + WP_BANK_COUNT &&
flags & EC_FLASH_PROTECT_RO_AT_BOOT)
flags |= EC_FLASH_PROTECT_ALL_AT_BOOT;
}
diff --git a/chip/stm32/registers-stm32g4.h b/chip/stm32/registers-stm32g4.h
index 12d2c7ff40..e3a73a0fe9 100644
--- a/chip/stm32/registers-stm32g4.h
+++ b/chip/stm32/registers-stm32g4.h
@@ -111,7 +111,8 @@
#endif
/* Embedded flash option bytes base address */
-#define STM32_OPTB_BASE 0x1FFF7800
+#define STM32_OPTB_BANK1_BASE 0x1FFF7800UL
+#define STM32_OPTB_BANK2_BASE 0x1FFF8000UL
/* Peripheral base addresses */
#define STM32_PERIPH_BASE (0x40000000UL)
@@ -950,11 +951,27 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t;
#define STM32_FLASH_SR STM32_FLASH_REG(0x10)
#define STM32_FLASH_CR STM32_FLASH_REG(0x14)
#define STM32_FLASH_ECCR STM32_FLASH_REG(0x18)
+/*
+ * Bank 1 Option Byte Copy Registers. These registers are loaded from the option
+ * bytes location in flash at reset, assuming that option byte loading has not
+ * been disabled.
+ */
#define STM32_FLASH_OPTR STM32_FLASH_REG(0x20)
#define STM32_FLASH_PCROP1SR STM32_FLASH_REG(0x24)
#define STM32_FLASH_PCROP1ER STM32_FLASH_REG(0x28)
#define STM32_FLASH_WRP1AR STM32_FLASH_REG(0x2C)
#define STM32_FLASH_WRP1BR STM32_FLASH_REG(0x30)
+/*
+ * Bank 2 Option Byte Copy Registers. These will only exist for category 3
+ * devices.
+ */
+#define STM32_FLASH_PCROP2SR STM32_FLASH_REG(0x44)
+#define STM32_FLASH_PCROP2ER STM32_FLASH_REG(0x48)
+#define STM32_FLASH_WRP2AR STM32_FLASH_REG(0x4C)
+#define STM32_FLASH_WRP2BR STM32_FLASH_REG(0x50)
+
+#define STM32_FLASH_SEC_SIZE1 STM32_FLASH_REG(0x70)
+#define STM32_FLASH_SEC_SIZE2 STM32_FLASH_REG(0x74)
/* --- FLASH CR Bit Definitions --- */
#define STM32_FLASH_ACR_LATENCY_SHIFT (0)
@@ -1005,17 +1022,27 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t;
#define STM32_FLASH_MIN_WRITE_SIZE (CONFIG_FLASH_WRITE_SIZE * 2)
/* --- FLASH Option bytes --- */
-#define STM32_OPTB_USER_RDP REG32(STM32_OPTB_BASE + 0x00)
-#define STM32_OPTB_PCROP1_START REG32(STM32_OPTB_BASE + 0x08)
-#define STM32_OPTB_PCROP1_END REG32(STM32_OPTB_BASE + 0x10)
-#define STM32_OPTB_WRP1AR REG32(STM32_OPTB_BASE + 0x18)
-#define STM32_OPTB_WRP1BR REG32(STM32_OPTB_BASE + 0x20)
-#define STM32_OPTB_SECURE_MEM REG32(STM32_OPTB_BASE + 0x28)
-
-#define STM32_OPTB_REG_READ(n) REG32(STM32_FLASH_REG(0x20) + (n * 4))
-#define STM32_OPTB_READ(n) REG32(STM32_OPTB_BASE + ((n) * 8))
-#define STM32_OPTB_COMP_READ(n) REG32(STM32_OPTB_BASE + ((n) * 8) + 0x4)
-
+#define STM32_OPTB_USER_RDP REG32(STM32_OPTB_BANK1_BASE + 0x00)
+#define STM32_OPTB_PCROP1_START REG32(STM32_OPTB_BANK1_BASE + 0x08)
+#define STM32_OPTB_PCROP1_END REG32(STM32_OPTB_BANK1_BASE + 0x10)
+#define STM32_OPTB_WRP1AR REG32(STM32_OPTB_BANK1_BASE + 0x18)
+#define STM32_OPTB_WRP1BR REG32(STM32_OPTB_BANK1_BASE + 0x20)
+#define STM32_OPTB_SECURE1_MEM REG32(STM32_OPTB_BANK1_BASE + 0x28)
+
+#define STM32_OPTB_UNUSED REG32(STM32_OPTB_BANK2_BASE + 0x00)
+#define STM32_OPTB_PCROP2_START REG32(STM32_OPTB_BANK2_BASE + 0x08)
+#define STM32_OPTB_PCROP2_END REG32(STM32_OPTB_BANK2_BASE + 0x10)
+#define STM32_OPTB_WRP2AR REG32(STM32_OPTB_BANK2_BASE + 0x18)
+#define STM32_OPTB_WRP2BR REG32(STM32_OPTB_BANK2_BASE + 0x20)
+#define STM32_OPTB_SECURE2_MEM REG32(STM32_OPTB_BANK2_BASE + 0x28)
+
+/* Read option bytes from flash memory for Bank 1 */
+#define STM32_OPTB_BANK1_READ(n) REG32(STM32_OPTB_BANK1_BASE + ((n) * 8))
+#define STM32_OPTB_BANK1_COMP_READ(n) REG32(STM32_OPTB_BANK1_BASE + ((n) * 8) + 0x4)
+#define STM32_OPTB_BANK2_READ(n) REG32(STM32_OPTB_BANK2_BASE + ((n) * 8))
+#define STM32_OPTB_BANK2_COMP_READ(n) REG32(STM32_OPTB_BANK2_BASE + ((n) * 8) + 0x4)
+
+#define STM32_OPTB_USER_DBANK BIT(22)
#define STM32_OPTB_USER_nBOOT1 BIT(23)
#define STM32_OPTB_USER_nSWBOOT0 BIT(26)
#define STM32_OPTB_USER_nBOOT0 BIT(27)