Skip to content

Commit def973f

Browse files
niedzwiecki-dawidkartben
authored andcommitted
drivers: flash: stm32h7: add support for write protection
Add support for setting flash write protection per sector for STM32H7x chips. Signed-off-by: Dawid Niedzwiecki <[email protected]>
1 parent 4c6b097 commit def973f

File tree

5 files changed

+123
-1
lines changed

5 files changed

+123
-1
lines changed

drivers/flash/Kconfig.stm32

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ if SOC_FLASH_STM32
3333

3434
config FLASH_STM32_WRITE_PROTECT
3535
bool "Extended operation for flash write protection control"
36-
depends on SOC_SERIES_STM32F4X
36+
depends on SOC_SERIES_STM32F4X || SOC_SERIES_STM32H7X
3737
select FLASH_HAS_EX_OP
3838
default n
3939
help

drivers/flash/flash_stm32h7x.c

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ LOG_MODULE_REGISTER(LOG_DOMAIN);
5555
* the serie, there is a discontinuty between bank1 and bank2.
5656
*/
5757
#define DISCONTINUOUS_BANKS (REAL_FLASH_SIZE_KB < STM32H7_SERIES_MAX_FLASH_KB)
58+
#define NUMBER_OF_BANKS 2
59+
#else
60+
#define NUMBER_OF_BANKS 1
5861
#endif
5962

6063
struct flash_stm32_sector_t {
@@ -129,6 +132,25 @@ static __unused int write_optsr(const struct device *dev, uint32_t mask, uint32_
129132
return write_opt(dev, mask, value, cur, true);
130133
}
131134

135+
static __unused int write_optwp(const struct device *dev, uint32_t mask, uint32_t value,
136+
uint32_t bank)
137+
{
138+
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
139+
uintptr_t cur = (uintptr_t)regs + offsetof(FLASH_TypeDef, WPSN_CUR1);
140+
141+
if (bank >= NUMBER_OF_BANKS) {
142+
return -EINVAL;
143+
}
144+
145+
#ifdef DUAL_BANK
146+
if (bank == 1) {
147+
cur = (uintptr_t)regs + offsetof(FLASH_TypeDef, WPSN_CUR2);
148+
}
149+
#endif /* DUAL_BANK */
150+
151+
return write_opt(dev, mask, value, cur, false);
152+
}
153+
132154
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
133155
uint8_t flash_stm32_get_rdp_level(const struct device *dev)
134156
{
@@ -143,6 +165,83 @@ void flash_stm32_set_rdp_level(const struct device *dev, uint8_t level)
143165
}
144166
#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */
145167

168+
#if defined(CONFIG_FLASH_STM32_WRITE_PROTECT)
169+
170+
#define WP_MSK FLASH_WPSN_WRPSN_Msk
171+
#define WP_POS FLASH_WPSN_WRPSN_Pos
172+
173+
int flash_stm32_update_wp_sectors(const struct device *dev, uint64_t changed_sectors,
174+
uint64_t protected_sectors)
175+
{
176+
/* All banks share the same sector mask. */
177+
const uint64_t bank_mask = WP_MSK >> WP_POS;
178+
const uint32_t sectors_per_bank = __builtin_popcount(WP_MSK);
179+
uint64_t sectors_mask = 0;
180+
uint32_t protected_sectors_reg;
181+
uint32_t changed_sectors_reg;
182+
int ret, ret2 = 0;
183+
bool commit = false;
184+
185+
for (int i = 0; i < NUMBER_OF_BANKS; i++) {
186+
sectors_mask |= bank_mask << (sectors_per_bank * i);
187+
}
188+
189+
if ((changed_sectors & sectors_mask) != changed_sectors) {
190+
return -EINVAL;
191+
}
192+
193+
for (int i = 0; i < NUMBER_OF_BANKS; i++) {
194+
/* Prepare protected and changed masks per bank. */
195+
protected_sectors_reg = (protected_sectors >> sectors_per_bank * i) & bank_mask;
196+
changed_sectors_reg = (changed_sectors >> sectors_per_bank * i) & bank_mask;
197+
198+
if (changed_sectors_reg == 0) {
199+
continue;
200+
}
201+
changed_sectors_reg <<= WP_POS;
202+
protected_sectors_reg <<= WP_POS;
203+
/* Sector is protected when bit == 0. Flip protected_sectors bits */
204+
protected_sectors_reg = ~protected_sectors_reg;
205+
206+
ret = write_optwp(dev, changed_sectors_reg, protected_sectors_reg, i);
207+
/* Option byte was successfully changed if the return value is greater than 0. */
208+
if (ret > 0) {
209+
commit = true;
210+
} else if (ret < 0) {
211+
/* Do not continue changing WP on error. */
212+
ret2 = ret;
213+
break;
214+
}
215+
}
216+
217+
if (commit) {
218+
ret = commit_optb(dev);
219+
/* Make sure to return the first error. */
220+
if (ret < 0 && ret2 == 0) {
221+
ret2 = ret;
222+
}
223+
}
224+
225+
return ret2;
226+
}
227+
228+
int flash_stm32_get_wp_sectors(const struct device *dev, uint64_t *protected_sectors)
229+
{
230+
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
231+
232+
*protected_sectors = (~regs->WPSN_CUR1 & WP_MSK) >> WP_POS;
233+
#ifdef DUAL_BANK
234+
/* Available only for STM32H7x */
235+
uint64_t proctected_sectors_2 =
236+
(~regs->WPSN_CUR2 & WP_MSK) >> WP_POS;
237+
const uint32_t sectors_per_bank = __builtin_popcount(WP_MSK);
238+
*protected_sectors |= proctected_sectors_2 << sectors_per_bank;
239+
#endif /* DUAL_BANK */
240+
241+
return 0;
242+
}
243+
#endif /* CONFIG_FLASH_STM32_WRITE_PROTECT */
244+
146245
int flash_stm32_option_bytes_lock(const struct device *dev, bool enable)
147246
{
148247
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright (c) 2024 Google Inc
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
&flash0 {
8+
partitions {
9+
compatible = "fixed-partitions";
10+
#address-cells = <1>;
11+
#size-cells = <1>;
12+
13+
/* Reserve 4KiB of flash for storage_partition. */
14+
storage_partition: partition@1f000 {
15+
label = "storage";
16+
reg = <0x0001f000 DT_SIZE_K(4)>;
17+
};
18+
};
19+
};

tests/drivers/flash/stm32/prj.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ CONFIG_FLASH=y
55
CONFIG_FLASH_EX_OP_ENABLED=y
66

77
CONFIG_MAIN_STACK_SIZE=2048
8+
CONFIG_ZTEST_STACK_SIZE=2048

tests/drivers/flash/stm32/testcase.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ tests:
4747
- stm32h735g_disco
4848
- stm32h750b_dk
4949
- stm32h745i_disco/stm32h745xx/m7
50+
- nucleo_h743zi
51+
- google_icetower
5052
extra_configs:
5153
- CONFIG_FLASH_STM32_READOUT_PROTECTION=y
54+
- CONFIG_FLASH_STM32_WRITE_PROTECT=y
5255
filter: dt_compat_enabled("st,stm32h7-flash-controller") and
5356
dt_label_with_parent_compat_enabled("storage_partition", "fixed-partitions")

0 commit comments

Comments
 (0)