diff --git a/drivers/flash/Kconfig.stm32 b/drivers/flash/Kconfig.stm32 index caa28854331b7..f1090d6072488 100644 --- a/drivers/flash/Kconfig.stm32 +++ b/drivers/flash/Kconfig.stm32 @@ -49,9 +49,12 @@ 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_STM32H7X + depends on SOC_SERIES_STM32F4X || \ + SOC_SERIES_STM32F7X || \ + SOC_SERIES_STM32G0X || \ + SOC_SERIES_STM32G4X || \ + SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32L4X select FLASH_HAS_EX_OP default n help diff --git a/drivers/flash/flash_stm32_ex_op.c b/drivers/flash/flash_stm32_ex_op.c index 2d5f754261624..19c9e21bd2aeb 100644 --- a/drivers/flash/flash_stm32_ex_op.c +++ b/drivers/flash/flash_stm32_ex_op.c @@ -331,6 +331,7 @@ int flash_stm32_ex_op(const struct device *dev, uint16_t code, #if defined(CONFIG_FLASH_STM32_OPTION_BYTES) && ( \ defined(CONFIG_DT_HAS_ST_STM32F4_FLASH_CONTROLLER_ENABLED) || \ defined(CONFIG_DT_HAS_ST_STM32F7_FLASH_CONTROLLER_ENABLED) || \ + defined(CONFIG_DT_HAS_ST_STM32G0_FLASH_CONTROLLER_ENABLED) || \ defined(CONFIG_DT_HAS_ST_STM32G4_FLASH_CONTROLLER_ENABLED) || \ defined(CONFIG_DT_HAS_ST_STM32L4_FLASH_CONTROLLER_ENABLED)) case FLASH_STM32_EX_OP_OPTB_READ: diff --git a/drivers/flash/flash_stm32g0x.c b/drivers/flash/flash_stm32g0x.c index 5c232dacc64c1..718834cce9ddc 100644 --- a/drivers/flash/flash_stm32g0x.c +++ b/drivers/flash/flash_stm32g0x.c @@ -15,6 +15,7 @@ LOG_MODULE_REGISTER(LOG_DOMAIN); #include #include #include +#include #include #include @@ -195,6 +196,64 @@ int flash_stm32_write_range(const struct device *dev, unsigned int offset, return rc; } +int flash_stm32_option_bytes_write(const struct device *dev, uint32_t mask, + uint32_t value) +{ + FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); + int rc; + + if (regs->CR & FLASH_CR_OPTLOCK) { + return -EIO; + } + + if ((regs->OPTR & mask) == value) { + return 0; + } + + rc = flash_stm32_wait_flash_idle(dev); + if (rc < 0) { + return rc; + } + + regs->OPTR = (regs->OPTR & ~mask) | value; + regs->CR |= FLASH_CR_OPTSTRT; + + /* Make sure previous write is completed. */ + barrier_dsync_fence_full(); + + rc = flash_stm32_wait_flash_idle(dev); + if (rc < 0) { + return rc; + } + + /* Force the option byte loading */ + regs->CR |= FLASH_CR_OBL_LAUNCH; + + return flash_stm32_wait_flash_idle(dev); +} + +uint32_t flash_stm32_option_bytes_read(const struct device *dev) +{ + FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); + + return regs->OPTR; +} + +#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION) +uint8_t flash_stm32_get_rdp_level(const struct device *dev) +{ + FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); + + return (regs->OPTR & FLASH_OPTR_RDP_Msk) >> FLASH_OPTR_RDP_Pos; +} + +void flash_stm32_set_rdp_level(const struct device *dev, uint8_t level) +{ + flash_stm32_option_bytes_write(dev, FLASH_OPTR_RDP_Msk, + (uint32_t)level << FLASH_OPTR_RDP_Pos); +} +#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */ + /* * The address space is always continuous, even though a subset of G0 SoCs has * two flash banks.