drivers: flash: stm32h7: add support for blocking registers
Add support for blocking flash control registers and option bytes for STM32H7 chips. Signed-off-by: Dawid Niedzwiecki <dawidn@google.com>
This commit is contained in:
parent
def973f5b9
commit
3d372c048a
@ -242,6 +242,70 @@ int flash_stm32_get_wp_sectors(const struct device *dev, uint64_t *protected_sec
|
||||
}
|
||||
#endif /* CONFIG_FLASH_STM32_WRITE_PROTECT */
|
||||
|
||||
#ifdef CONFIG_FLASH_STM32_BLOCK_REGISTERS
|
||||
int flash_stm32_control_register_disable(const struct device *dev)
|
||||
{
|
||||
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
|
||||
|
||||
/*
|
||||
* Access to control register can be disabled by writing wrong key to
|
||||
* the key register. Option register will remain disabled until reset.
|
||||
* Writing wrong key causes a bus fault, so we need to set FAULTMASK to
|
||||
* disable faults, and clear bus fault pending bit before enabling them
|
||||
* again.
|
||||
*/
|
||||
regs->CR1 |= FLASH_CR_LOCK;
|
||||
#ifdef DUAL_BANK
|
||||
regs->CR2 |= FLASH_CR_LOCK;
|
||||
#endif /* DUAL_BANK */
|
||||
|
||||
__set_FAULTMASK(1);
|
||||
regs->KEYR1 = 0xffffffff;
|
||||
|
||||
#ifdef DUAL_BANK
|
||||
regs->KEYR2 = 0xffffffff;
|
||||
#endif /* DUAL_BANK */
|
||||
/* Make sure that the fault occurs before we clear it. */
|
||||
barrier_dsync_fence_full();
|
||||
|
||||
/* Clear Bus Fault pending bit */
|
||||
SCB->SHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk;
|
||||
/* Make sure to clear the fault before changing the fault mask. */
|
||||
barrier_dsync_fence_full();
|
||||
|
||||
__set_FAULTMASK(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flash_stm32_option_bytes_disable(const struct device *dev)
|
||||
{
|
||||
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
|
||||
|
||||
/*
|
||||
* Access to option register can be disabled by writing wrong key to
|
||||
* the key register. Option register will remain disabled until reset.
|
||||
* Writing wrong key causes a bus fault, so we need to set FAULTMASK to
|
||||
* disable faults, and clear bus fault pending bit before enabling them
|
||||
* again.
|
||||
*/
|
||||
regs->OPTCR |= FLASH_OPTCR_OPTLOCK;
|
||||
|
||||
__set_FAULTMASK(1);
|
||||
regs->OPTKEYR = 0xffffffff;
|
||||
/* Make sure that the fault occurs before we clear it. */
|
||||
barrier_dsync_fence_full();
|
||||
|
||||
/* Clear Bus Fault pending bit */
|
||||
SCB->SHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk;
|
||||
/* Make sure to clear the fault before changing the fault mask. */
|
||||
barrier_dsync_fence_full();
|
||||
__set_FAULTMASK(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_FLASH_STM32_BLOCK_REGISTERS */
|
||||
|
||||
int flash_stm32_option_bytes_lock(const struct device *dev, bool enable)
|
||||
{
|
||||
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include <zephyr/drivers/flash/stm32_flash_api_extensions.h>
|
||||
#include <zephyr/devicetree.h>
|
||||
#include <zephyr/storage/flash_map.h>
|
||||
#include <zephyr/sys/barrier.h>
|
||||
|
||||
#define TEST_AREA storage_partition
|
||||
#define TEST_AREA_OFFSET FIXED_PARTITION_OFFSET(TEST_AREA)
|
||||
@ -200,15 +201,46 @@ static void flash_cr_unlock(void)
|
||||
{
|
||||
FLASH_TypeDef *regs = (FLASH_TypeDef *)TEST_AREA_DEVICE_REG;
|
||||
|
||||
#ifdef CONFIG_SOC_SERIES_STM32H7X
|
||||
regs->KEYR1 = FLASH_KEY1;
|
||||
regs->KEYR1 = FLASH_KEY2;
|
||||
#ifdef DUAL_BANK
|
||||
regs->KEYR2 = FLASH_KEY1;
|
||||
regs->KEYR2 = FLASH_KEY2;
|
||||
#endif /* DUAL_BANK */
|
||||
#else /* CONFIG_SOC_SERIES_STM32H7X */
|
||||
regs->KEYR = FLASH_KEY1;
|
||||
regs->KEYR = FLASH_KEY2;
|
||||
#endif /* CONFIG_SOC_SERIES_STM32H7X */
|
||||
barrier_dsync_fence_full();
|
||||
}
|
||||
|
||||
static bool flash_cr_locked(void)
|
||||
static bool flash_cr_is_locked(void)
|
||||
{
|
||||
FLASH_TypeDef *regs = (FLASH_TypeDef *)TEST_AREA_DEVICE_REG;
|
||||
|
||||
#ifdef CONFIG_SOC_SERIES_STM32H7X
|
||||
return regs->CR1 & FLASH_CR_LOCK;
|
||||
#ifdef DUAL_BANK
|
||||
return (regs->CR1 & FLASH_CR_LOCK) && (regs->CR2 & FLASH_CR_LOCK);
|
||||
#endif /* DUAL_BANK */
|
||||
#else /* CONFIG_SOC_SERIES_STM32H7X */
|
||||
return regs->CR & FLASH_CR_LOCK;
|
||||
#endif /* CONFIG_SOC_SERIES_STM32H7X */
|
||||
}
|
||||
|
||||
static bool flash_cr_is_unlocked(void)
|
||||
{
|
||||
FLASH_TypeDef *regs = (FLASH_TypeDef *)TEST_AREA_DEVICE_REG;
|
||||
|
||||
#ifdef CONFIG_SOC_SERIES_STM32H7X
|
||||
return !(regs->CR1 & FLASH_CR_LOCK);
|
||||
#ifdef DUAL_BANK
|
||||
return !((regs->CR1 & FLASH_CR_LOCK) || (regs->CR2 & FLASH_CR_LOCK));
|
||||
#endif /* DUAL_BANK */
|
||||
#else /* CONFIG_SOC_SERIES_STM32H7X */
|
||||
return !(regs->CR & FLASH_CR_LOCK);
|
||||
#endif /* CONFIG_SOC_SERIES_STM32H7X */
|
||||
}
|
||||
|
||||
ZTEST(flash_stm32, test_stm32_block_registers)
|
||||
@ -227,24 +259,27 @@ ZTEST(flash_stm32, test_stm32_block_registers)
|
||||
flash_stm32_option_bytes_lock(flash_dev, false);
|
||||
/* Clear Bus Fault pending bit */
|
||||
SCB->SHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk;
|
||||
barrier_dsync_fence_full();
|
||||
__set_FAULTMASK(0);
|
||||
zassert_true(flash_opt_locked(), "OPT unlocked after being blocked");
|
||||
|
||||
/* Test CR lock. */
|
||||
zassert_true(flash_cr_locked(), "CR should be locked by default");
|
||||
zassert_true(flash_cr_is_locked(), "CR should be locked by default");
|
||||
TC_PRINT("Unlocking CR\n");
|
||||
flash_cr_unlock();
|
||||
zassert_false(flash_cr_locked(), "Unable to unlock CR");
|
||||
zassert_true(flash_cr_is_unlocked(), "Unable to unlock CR");
|
||||
TC_PRINT("Blocking CR\n");
|
||||
flash_ex_op(flash_dev, FLASH_STM32_EX_OP_BLOCK_CONTROL_REG, (uintptr_t)NULL, NULL);
|
||||
zassert_true(flash_cr_locked(), "Blocking CR didn't lock CR");
|
||||
zassert_true(flash_cr_is_locked(), "Blocking CR didn't lock CR");
|
||||
__set_FAULTMASK(1);
|
||||
TC_PRINT("Try to unlock blocked CR\n");
|
||||
flash_cr_unlock();
|
||||
/* Clear Bus Fault pending bit */
|
||||
SCB->SHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk;
|
||||
barrier_dsync_fence_full();
|
||||
__set_FAULTMASK(0);
|
||||
zassert_true(flash_cr_locked(), "CR unlocked after being blocked");
|
||||
/* Make sure previous write is completed. */
|
||||
zassert_true(flash_cr_is_locked(), "CR unlocked after being blocked");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -54,3 +54,12 @@ tests:
|
||||
- CONFIG_FLASH_STM32_WRITE_PROTECT=y
|
||||
filter: dt_compat_enabled("st,stm32h7-flash-controller") and
|
||||
dt_label_with_parent_compat_enabled("storage_partition", "fixed-partitions")
|
||||
drivers.flash.stm32.h7.block_registers:
|
||||
platform_allow:
|
||||
- nucleo_h743zi
|
||||
- google_icetower
|
||||
extra_configs:
|
||||
- CONFIG_FLASH_STM32_BLOCK_REGISTERS=y
|
||||
filter: dt_compat_enabled("st,stm32h7-flash-controller") and
|
||||
dt_label_with_parent_compat_enabled("storage_partition", "fixed-partitions") and
|
||||
CONFIG_SOC_SERIES_STM32H7X
|
||||
|
||||
Loading…
Reference in New Issue
Block a user