Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drivers: flash: stm32h7 fix RDP #84430

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
68 changes: 44 additions & 24 deletions drivers/flash/flash_stm32h7x.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ LOG_MODULE_REGISTER(LOG_DOMAIN);
/* Let's wait for double the max erase time to be sure that the operation is
* completed.
*/
#define STM32H7_FLASH_TIMEOUT (2 * DT_PROP(DT_INST(0, st_stm32_nv_flash), max_erase_time))
#define STM32H7_FLASH_TIMEOUT (2 * DT_PROP(DT_INST(0, st_stm32_nv_flash), max_erase_time))
/* No information in documentation about that. */
#define STM32H7_FLASH_OPT_TIMEOUT_MS 800

#define STM32H7_M4_FLASH_SIZE DT_PROP_OR(DT_INST(0, st_stm32_nv_flash), bank2_flash_size, 0)
#ifdef CONFIG_CPU_CORTEX_M4
Expand Down Expand Up @@ -62,44 +64,63 @@ struct flash_stm32_sector_t {
volatile uint32_t *sr;
};

static __unused int write_optb(const struct device *dev, uint32_t mask,
uint32_t value)
static __unused int commit_optb(const struct device *dev)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
int rc;
int64_t timeout_time = k_uptime_get() + STM32H7_FLASH_OPT_TIMEOUT_MS;

regs->OPTCR |= FLASH_OPTCR_OPTSTART;
niedzwiecki-dawid marked this conversation as resolved.
Show resolved Hide resolved
barrier_dsync_fence_full();
while (regs->OPTSR_CUR & FLASH_OPTSR_OPT_BUSY) {
if (k_uptime_get() > timeout_time) {
LOG_ERR("Timeout writing option bytes.");
return -ETIMEDOUT;
}
}

return 0;
}

static __unused int write_opt(const struct device *dev, uint32_t mask, uint32_t value,
uintptr_t cur, bool commit)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
/* PRG register always follows CUR register. */
uintptr_t prg = cur + 4;
int rc = 0;

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;
#ifdef CONFIG_SOC_SERIES_STM32H7RSX
regs->OPTCR |= FLASH_OPTCR_PG_OPT;
#else
duda-patryk marked this conversation as resolved.
Show resolved Hide resolved
regs->OPTCR |= FLASH_OPTCR_OPTSTART;
#endif /* CONFIG_SOC_SERIES_STM32H7RSX */
/* Make sure previous write is completed. */
barrier_dsync_fence_full();
if ((sys_read32(cur) & mask) == value) {
return 0;
}

rc = flash_stm32_wait_flash_idle(dev);
if (rc < 0) {
LOG_ERR("Err flash no idle");
return rc;
sys_write32((sys_read32(cur) & ~mask) | value, prg);

if (commit) {
/* Make sure previous write is completed before committing option bytes. */
barrier_dsync_fence_full();
rc = commit_optb(dev);
}

return 0;
return rc;
}

static __unused int write_optsr(const struct device *dev, uint32_t mask, uint32_t value)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
uintptr_t cur = (uintptr_t)regs + offsetof(FLASH_TypeDef, OPTSR_CUR);

return write_opt(dev, mask, value, cur, true);
}

#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
Expand All @@ -112,8 +133,7 @@ uint8_t flash_stm32_get_rdp_level(const struct device *dev)

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);
write_optsr(dev, FLASH_OPTSR_RDP_Msk, (uint32_t)level << FLASH_OPTSR_RDP_Pos);
}
#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */

Expand Down
Loading