Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion drivers/flash/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ if(CONFIG_FLASH_MCUX_FLEXSPI_XIP)
endif()

if(CONFIG_SOC_FLASH_STM32)
zephyr_library_sources_ifdef(CONFIG_FLASH_EX_OP_ENABLED flash_stm32_ex_op.c)
if(CONFIG_SOC_SERIES_STM32H7X)
zephyr_library_sources_ifdef(CONFIG_DT_HAS_ST_STM32H7_FLASH_CONTROLLER_ENABLED flash_stm32h7x.c)
elseif(CONFIG_SOC_SERIES_STM32H7RSX)
Expand All @@ -106,7 +107,6 @@ if(CONFIG_SOC_FLASH_STM32)
else()
if(CONFIG_DT_HAS_ST_STM32_FLASH_CONTROLLER_ENABLED)
zephyr_library_sources(flash_stm32.c)
zephyr_library_sources_ifdef(CONFIG_FLASH_EX_OP_ENABLED flash_stm32_ex_op.c)

# zephyr-keep-sorted-start
zephyr_library_sources_ifdef(CONFIG_DT_HAS_ST_STM32F1_FLASH_CONTROLLER_ENABLED flash_stm32f1x.c)
Expand Down
3 changes: 2 additions & 1 deletion drivers/flash/Kconfig.stm32
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ config FLASH_STM32_WRITE_PROTECT_DISABLE_PREVENTION
config FLASH_STM32_READOUT_PROTECTION
bool "Extended operation for flash readout protection control"
depends on SOC_SERIES_STM32F4X || SOC_SERIES_STM32L4X || \
SOC_SERIES_STM32G4X || SOC_SERIES_STM32F7X
SOC_SERIES_STM32G4X || SOC_SERIES_STM32F7X || \
SOC_SERIES_STM32H7X
select FLASH_HAS_EX_OP
default n
help
Expand Down
75 changes: 6 additions & 69 deletions drivers/flash/flash_stm32.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
#include <zephyr/logging/log.h>

#include "flash_stm32.h"
#include "stm32_hsem.h"

LOG_MODULE_REGISTER(flash_stm32, CONFIG_FLASH_LOG_LEVEL);

Expand Down Expand Up @@ -59,32 +58,6 @@ int __weak flash_stm32_check_configuration(void)
return 0;
}

#if defined(CONFIG_MULTITHREADING)
/*
* This is named flash_stm32_sem_take instead of flash_stm32_lock (and
* similarly for flash_stm32_sem_give) to avoid confusion with locking
* actual flash pages.
*/
static inline void _flash_stm32_sem_take(const struct device *dev)
{
k_sem_take(&FLASH_STM32_PRIV(dev)->sem, K_FOREVER);
z_stm32_hsem_lock(CFG_HW_FLASH_SEMID, HSEM_LOCK_WAIT_FOREVER);
}

static inline void _flash_stm32_sem_give(const struct device *dev)
{
z_stm32_hsem_unlock(CFG_HW_FLASH_SEMID);
k_sem_give(&FLASH_STM32_PRIV(dev)->sem);
}

#define flash_stm32_sem_init(dev) k_sem_init(&FLASH_STM32_PRIV(dev)->sem, 1, 1)
#define flash_stm32_sem_take(dev) _flash_stm32_sem_take(dev)
#define flash_stm32_sem_give(dev) _flash_stm32_sem_give(dev)
#else
#define flash_stm32_sem_init(dev)
#define flash_stm32_sem_take(dev)
#define flash_stm32_sem_give(dev)
#endif

#if !defined(CONFIG_SOC_SERIES_STM32WBX)
static int flash_stm32_check_status(const struct device *dev)
Expand Down Expand Up @@ -319,7 +292,7 @@ int flash_stm32_option_bytes_lock(const struct device *dev, bool enable)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);

#if defined(FLASH_OPTCR_OPTLOCK) /* F2, F4, F7 and H7 */
#if defined(FLASH_OPTCR_OPTLOCK) /* F2, F4, F7 */
if (enable) {
regs->OPTCR |= FLASH_OPTCR_OPTLOCK;
} else if (regs->OPTCR & FLASH_OPTCR_OPTLOCK) {
Expand Down Expand Up @@ -391,12 +364,11 @@ int flash_stm32_option_bytes_lock(const struct device *dev, bool enable)
}

#if defined(CONFIG_FLASH_EX_OP_ENABLED) && defined(CONFIG_FLASH_STM32_BLOCK_REGISTERS)
static int flash_stm32_control_register_disable(const struct device *dev)
int flash_stm32_control_register_disable(const struct device *dev)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);

#if defined(FLASH_CR_LOCK) /* F0, F1, F2, F3, F4, F7, L4, G0, G4, H7, WB, WL \
*/
#if defined(FLASH_CR_LOCK) /* F0, F1, F2, F3, F4, F7, L4, G0, G4, WB, WL */
/*
* Access to control register can be disabled by writing wrong key to
* the key register. Option register will remain disabled until reset.
Expand All @@ -421,11 +393,11 @@ static int flash_stm32_control_register_disable(const struct device *dev)
#endif
}

static int flash_stm32_option_bytes_disable(const struct device *dev)
int flash_stm32_option_bytes_disable(const struct device *dev)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);

#if defined(FLASH_OPTCR_OPTLOCK) /* F2, F4, F7 and H7 */
#if defined(FLASH_OPTCR_OPTLOCK) /* F2, F4, F7 */
/*
* Access to option register can be disabled by writing wrong key to
* the key register. Option register will remain disabled until reset.
Expand Down Expand Up @@ -459,41 +431,6 @@ flash_stm32_get_parameters(const struct device *dev)
return &flash_stm32_parameters;
}

#ifdef CONFIG_FLASH_EX_OP_ENABLED
static int flash_stm32_ex_op(const struct device *dev, uint16_t code,
const uintptr_t in, void *out)
{
int rv = -ENOTSUP;

flash_stm32_sem_take(dev);

switch (code) {
#if defined(CONFIG_FLASH_STM32_WRITE_PROTECT)
case FLASH_STM32_EX_OP_SECTOR_WP:
rv = flash_stm32_ex_op_sector_wp(dev, in, out);
break;
#endif /* CONFIG_FLASH_STM32_WRITE_PROTECT */
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
case FLASH_STM32_EX_OP_RDP:
rv = flash_stm32_ex_op_rdp(dev, in, out);
break;
#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */
#if defined(CONFIG_FLASH_STM32_BLOCK_REGISTERS)
case FLASH_STM32_EX_OP_BLOCK_OPTION_REG:
rv = flash_stm32_option_bytes_disable(dev);
break;
case FLASH_STM32_EX_OP_BLOCK_CONTROL_REG:
rv = flash_stm32_control_register_disable(dev);
break;
#endif /* CONFIG_FLASH_STM32_BLOCK_REGISTERS */
}

flash_stm32_sem_give(dev);

return rv;
}
#endif

static struct flash_stm32_priv flash_data = {
.regs = (FLASH_TypeDef *) DT_INST_REG_ADDR(0),
/* Getting clocks information from device tree description depending
Expand Down Expand Up @@ -524,7 +461,7 @@ static int stm32_flash_init(const struct device *dev)
{
int rc;
/* Below is applicable to F0, F1, F3, G0, G4, L1, L4, L5, U5 & WB55 series.
* For F2, F4, F7 & H7 series, this is not applicable.
* For F2, F4, F7 series, this is not applicable.
*/
#if DT_INST_NODE_HAS_PROP(0, clocks)
struct flash_stm32_priv *p = FLASH_STM32_PRIV(dev);
Expand Down
46 changes: 38 additions & 8 deletions drivers/flash/flash_stm32.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define ZEPHYR_DRIVERS_FLASH_FLASH_STM32_H_

#include <zephyr/drivers/flash.h>
#include "stm32_hsem.h"

#if DT_NODE_HAS_PROP(DT_INST(0, st_stm32_flash_controller), clocks) || \
DT_NODE_HAS_PROP(DT_INST(0, st_stm32h7_flash_controller), clocks)
Expand Down Expand Up @@ -271,6 +272,40 @@ static inline bool flash_stm32_range_exists(const struct device *dev,
}
#endif /* CONFIG_FLASH_PAGE_LAYOUT */


#if defined(CONFIG_MULTITHREADING) || defined(CONFIG_STM32H7_DUAL_CORE)
/*
* This is named flash_stm32_sem_take instead of flash_stm32_lock (and
* similarly for flash_stm32_sem_give) to avoid confusion with locking
* actual flash pages.
*/

static inline void _flash_stm32_sem_take(const struct device *dev)
{
k_sem_take(&FLASH_STM32_PRIV(dev)->sem, K_FOREVER);
z_stm32_hsem_lock(CFG_HW_FLASH_SEMID, HSEM_LOCK_WAIT_FOREVER);
}

static inline void _flash_stm32_sem_give(const struct device *dev)
{
z_stm32_hsem_unlock(CFG_HW_FLASH_SEMID);
k_sem_give(&FLASH_STM32_PRIV(dev)->sem);
}

#define flash_stm32_sem_init(dev) k_sem_init(&FLASH_STM32_PRIV(dev)->sem, 1, 1)
#define flash_stm32_sem_take(dev) _flash_stm32_sem_take(dev)
#define flash_stm32_sem_give(dev) _flash_stm32_sem_give(dev)
#else
#define flash_stm32_sem_init(dev)
#define flash_stm32_sem_take(dev)
#define flash_stm32_sem_give(dev)
#endif /* CONFIG_MULTITHREADING */

#ifdef CONFIG_FLASH_EX_OP_ENABLED
int flash_stm32_ex_op(const struct device *dev, uint16_t code,
const uintptr_t in, void *out);
#endif /* CONFIG_FLASH_EX_OP_ENABLED */

static inline bool flash_stm32_valid_write(off_t offset, uint32_t len)
{
return ((offset % FLASH_STM32_WRITE_BLOCK_SIZE == 0) &&
Expand Down Expand Up @@ -316,14 +351,9 @@ uint8_t flash_stm32_get_rdp_level(const struct device *dev);
void flash_stm32_set_rdp_level(const struct device *dev, uint8_t level);
#endif

/* Flash extended operations */
#if defined(CONFIG_FLASH_STM32_WRITE_PROTECT)
int flash_stm32_ex_op_sector_wp(const struct device *dev, const uintptr_t in,
void *out);
#endif
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
int flash_stm32_ex_op_rdp(const struct device *dev, const uintptr_t in,
void *out);
#if defined(CONFIG_FLASH_STM32_BLOCK_REGISTERS)
int flash_stm32_control_register_disable(const struct device *dev);
int flash_stm32_option_bytes_disable(const struct device *dev);
#endif

#endif /* ZEPHYR_DRIVERS_FLASH_FLASH_STM32_H_ */
33 changes: 33 additions & 0 deletions drivers/flash/flash_stm32_ex_op.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,36 @@ int flash_stm32_ex_op_rdp(const struct device *dev, const uintptr_t in,
return rc;
}
#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */

int flash_stm32_ex_op(const struct device *dev, uint16_t code,
const uintptr_t in, void *out)
{
int rv = -ENOTSUP;

flash_stm32_sem_take(dev);

switch (code) {
#if defined(CONFIG_FLASH_STM32_WRITE_PROTECT)
case FLASH_STM32_EX_OP_SECTOR_WP:
rv = flash_stm32_ex_op_sector_wp(dev, in, out);
break;
#endif /* CONFIG_FLASH_STM32_WRITE_PROTECT */
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
case FLASH_STM32_EX_OP_RDP:
rv = flash_stm32_ex_op_rdp(dev, in, out);
break;
#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */
#if defined(CONFIG_FLASH_STM32_BLOCK_REGISTERS)
case FLASH_STM32_EX_OP_BLOCK_OPTION_REG:
rv = flash_stm32_option_bytes_disable(dev);
break;
case FLASH_STM32_EX_OP_BLOCK_CONTROL_REG:
rv = flash_stm32_control_register_disable(dev);
break;
#endif /* CONFIG_FLASH_STM32_BLOCK_REGISTERS */
}

flash_stm32_sem_give(dev);

return rv;
}
88 changes: 68 additions & 20 deletions drivers/flash/flash_stm32h7x.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,32 +62,77 @@ struct flash_stm32_sector_t {
volatile uint32_t *sr;
};

#if defined(CONFIG_MULTITHREADING) || defined(CONFIG_STM32H7_DUAL_CORE)
/*
* This is named flash_stm32_sem_take instead of flash_stm32_lock (and
* similarly for flash_stm32_sem_give) to avoid confusion with locking
* actual flash sectors.
*/
static inline void _flash_stm32_sem_take(const struct device *dev)
static __unused int write_optb(const struct device *dev, uint32_t mask,
uint32_t value)
{
k_sem_take(&FLASH_STM32_PRIV(dev)->sem, K_FOREVER);
z_stm32_hsem_lock(CFG_HW_FLASH_SEMID, HSEM_LOCK_WAIT_FOREVER);
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
int rc;

if (regs->OPTCR & FLASH_OPTCR_OPTLOCK) {
LOG_ERR("Option bytes locked");
return -EIO;
}

if ((regs->OPTCR & mask) == value) {
/* Done already */
return 0;
}

rc = flash_stm32_wait_flash_idle(dev);
if (rc < 0) {
LOG_ERR("Err flash no idle");
return rc;
}

regs->OPTCR = (regs->OPTCR & ~mask) | value;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't OPTSR_PRG be used here? Sorry for late comment.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@FRASTM ping :-)

regs->OPTCR |= FLASH_OPTCR_OPTSTART;

/* Make sure previous write is completed. */
barrier_dsync_fence_full();

rc = flash_stm32_wait_flash_idle(dev);
if (rc < 0) {
LOG_ERR("Err flash no idle");
return rc;
}

return 0;
}

static inline void _flash_stm32_sem_give(const struct device *dev)
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
uint8_t flash_stm32_get_rdp_level(const struct device *dev)
{
z_stm32_hsem_unlock(CFG_HW_FLASH_SEMID);
k_sem_give(&FLASH_STM32_PRIV(dev)->sem);
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);

return (regs->OPTSR_CUR & FLASH_OPTSR_RDP_Msk) >> FLASH_OPTSR_RDP_Pos;
}

#define flash_stm32_sem_init(dev) k_sem_init(&FLASH_STM32_PRIV(dev)->sem, 1, 1)
#define flash_stm32_sem_take(dev) _flash_stm32_sem_take(dev)
#define flash_stm32_sem_give(dev) _flash_stm32_sem_give(dev)
#else
#define flash_stm32_sem_init(dev)
#define flash_stm32_sem_take(dev)
#define flash_stm32_sem_give(dev)
#endif
void flash_stm32_set_rdp_level(const struct device *dev, uint8_t level)
{
write_optb(dev, FLASH_OPTSR_RDP_Msk,
(uint32_t)level << FLASH_OPTSR_RDP_Pos);
}
#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */

int flash_stm32_option_bytes_lock(const struct device *dev, bool enable)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);

if (enable) {
regs->OPTCR |= FLASH_OPTCR_OPTLOCK;
} else if (regs->OPTCR & FLASH_OPTCR_OPTLOCK) {
regs->OPTKEYR = FLASH_OPT_KEY1;
regs->OPTKEYR = FLASH_OPT_KEY2;
}

if (enable) {
LOG_DBG("Option bytes locked");
} else {
LOG_DBG("Option bytes unlocked");
}

return 0;
}

bool flash_stm32_valid_range(const struct device *dev, off_t offset, uint32_t len, bool write)
{
Expand Down Expand Up @@ -676,6 +721,9 @@ static const struct flash_driver_api flash_stm32h7_api = {
#ifdef CONFIG_FLASH_PAGE_LAYOUT
.page_layout = flash_stm32_page_layout,
#endif
#ifdef CONFIG_FLASH_EX_OP_ENABLED
.ex_op = flash_stm32_ex_op,
#endif
};

static int stm32h7_flash_init(const struct device *dev)
Expand Down
1 change: 1 addition & 0 deletions tests/drivers/flash/stm32/boards/stm32h735g_disco.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CONFIG_FLASH_STM32_QSPI=n
19 changes: 19 additions & 0 deletions tests/drivers/flash/stm32/boards/stm32h735g_disco.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright (c) 2024 STMicroelectronics
*
* SPDX-License-Identifier: Apache-2.0
*/

&flash0 {
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;

/* Reserve 4KiB of flash for storage_partition. */
storage_partition: partition@f0000 {
label = "storage";
reg = <0x000f0000 DT_SIZE_K(4)>;
};
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CONFIG_FLASH_STM32_QSPI=n
Loading
Loading