From 1f3605de21ef1ace85ba4aeced725411c1ed8ef4 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 20 Sep 2023 19:17:26 +0000 Subject: [PATCH] drivers/flash/nrf: Workaround for nrf91 errata 7 Fix UICR read access. Signed-off-by: Dominik Ermel --- drivers/flash/soc_flash_nrf.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/drivers/flash/soc_flash_nrf.c b/drivers/flash/soc_flash_nrf.c index fa433d1044b..cc840309264 100644 --- a/drivers/flash/soc_flash_nrf.c +++ b/drivers/flash/soc_flash_nrf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 Nordic Semiconductor ASA + * Copyright (c) 2017-2023 Nordic Semiconductor ASA * Copyright (c) 2016 Linaro Limited * Copyright (c) 2016 Intel Corporation * @@ -116,6 +116,26 @@ static inline bool is_uicr_addr_valid(off_t addr, size_t len) #endif /* CONFIG_SOC_FLASH_NRF_UICR */ } +#if CONFIG_SOC_FLASH_NRF_UICR && IS_ENABLED(NRF91_ERRATA_7_ENABLE_WORKAROUND) +static inline void nrf91_errata_7_enter(void) +{ + __disable_irq(); +} + +static inline void nrf91_errata_7_exit(void) +{ + __DSB(); + __enable_irq(); +} + +static void nrf_buffer_read_91_uicr(void *data, off_t addr, size_t len) +{ + nrf91_errata_7_enter(); + nrf_nvmc_buffer_read(data, (uint32_t)addr, len); + nrf91_errata_7_exit(); +} +#endif + static void nvmc_wait_ready(void) { while (!nrfx_nvmc_write_done_check()) { @@ -125,9 +145,11 @@ static void nvmc_wait_ready(void) static int flash_nrf_read(const struct device *dev, off_t addr, void *data, size_t len) { + const bool within_uicr = is_uicr_addr_valid(addr, len); + if (is_regular_addr_valid(addr, len)) { addr += DT_REG_ADDR(SOC_NV_FLASH_NODE); - } else if (!is_uicr_addr_valid(addr, len)) { + } else if (!within_uicr) { LOG_ERR("invalid address: 0x%08lx:%zu", (unsigned long)addr, len); return -EINVAL; @@ -137,6 +159,13 @@ static int flash_nrf_read(const struct device *dev, off_t addr, return 0; } +#if CONFIG_SOC_FLASH_NRF_UICR && IS_ENABLED(NRF91_ERRATA_7_ENABLE_WORKAROUND) + if (within_uicr) { + nrf_buffer_read_91_uicr(data, (uint32_t)addr, len); + return 0; + } +#endif + nrf_nvmc_buffer_read(data, (uint32_t)addr, len); return 0;