Skip to content
Open
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
3 changes: 3 additions & 0 deletions boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,6 @@ CONFIG_EXTERNAL_CACHE=y

# Enable GPIO
CONFIG_GPIO=y

# Enable Multithreading by default
CONFIG_MULTITHREADING=y
3 changes: 3 additions & 0 deletions drivers/flash/Kconfig.nrf_mram
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ config SOC_FLASH_NRF_MRAM
select FLASH_HAS_DRIVER_ENABLED
select FLASH_HAS_PAGE_LAYOUT
select FLASH_HAS_NO_EXPLICIT_ERASE
select NRFS
select MRAM_LATENCY
select NRF_IRONSIDE_BOOT_REPORT
imply MPU_ALLOW_FLASH_WRITE if ARM_MPU
help
Enables Nordic Semiconductor flash driver for MRAM in direct write mode.
Expand Down
105 changes: 99 additions & 6 deletions drivers/flash/soc_flash_nrf_mram.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#include <zephyr/drivers/flash.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/barrier.h>
#include <zephyr/cache.h>
#include "../soc/nordic/common/mram_latency.h"
#include "../soc/nordic/ironside/include/nrf_ironside/boot_report.h"

LOG_MODULE_REGISTER(flash_nrf_mram, CONFIG_FLASH_LOG_LEVEL);

Expand All @@ -25,10 +28,37 @@

#define ERASE_VALUE 0xff

#define SOC_NRF_MRAM_BANK_11_OFFSET 0x100000
#define SOC_NRF_MRAM_BANK_11_ADDRESS (MRAM_START + SOC_NRF_MRAM_BANK_11_OFFSET)
#define SOC_NRF_MRAMC_BASE_ADDR_10 0x5f092000
#define SOC_NRF_MRAMC_BASE_ADDR_11 0x5f093000
#define SOC_NRF_MRAMC_READY_REG_0 (SOC_NRF_MRAMC_BASE_ADDR_10 + 0x400)
#define SOC_NRF_MRAMC_READY_REG_1 (SOC_NRF_MRAMC_BASE_ADDR_11 + 0x400)

#define IRONSIDE_SE_VER_MASK 0x000000FF /* This is the Mask for Ironside SE Seqnum */
#define IRONSIDE_SE_SUPPORT_READY_VER 21

Check notice on line 39 in drivers/flash/soc_flash_nrf_mram.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/flash/soc_flash_nrf_mram.c:39 -#define IRONSIDE_SE_VER_MASK 0x000000FF /* This is the Mask for Ironside SE Seqnum */ +#define IRONSIDE_SE_VER_MASK 0x000000FF /* This is the Mask for Ironside SE Seqnum */

BUILD_ASSERT(MRAM_START > 0, "nordic,mram: start address expected to be non-zero");
BUILD_ASSERT((ERASE_BLOCK_SIZE % WRITE_BLOCK_SIZE) == 0,
"erase-block-size expected to be a multiple of write-block-size");

struct nrf_mram_data_t {
uint8_t ironside_se_ver;
};

static inline uint32_t nrf_mram_ready(uint32_t addr, uint8_t ironside_se_ver)
{
if (ironside_se_ver < IRONSIDE_SE_SUPPORT_READY_VER) {
return 1;
}

if (addr < SOC_NRF_MRAM_BANK_11_ADDRESS) {
return sys_read32(SOC_NRF_MRAMC_READY_REG_0);
} else {
return sys_read32(SOC_NRF_MRAMC_READY_REG_1);
}
}

/**
* @param[in,out] offset Relative offset into memory, from the driver API.
* @param[in] len Number of bytes for the intended operation.
Expand Down Expand Up @@ -101,7 +131,8 @@

static int nrf_mram_write(const struct device *dev, off_t offset, const void *data, size_t len)
{
ARG_UNUSED(dev);
struct nrf_mram_data_t *nrf_mram_data = dev->data;
uint8_t ironside_se_ver = nrf_mram_data->ironside_se_ver;

const uintptr_t addr = validate_and_map_addr(offset, len, true);

Expand All @@ -111,15 +142,36 @@

LOG_DBG("write: %p:%zu", (void *)addr, len);

memcpy((void *)addr, data, len);
if (ironside_se_ver >= IRONSIDE_SE_SUPPORT_READY_VER) {
mram_no_latency_sync_request();
}
for (uint32_t i = 0; i < (len / MRAM_WORD_SIZE); i++) {
while (!nrf_mram_ready(addr + (i * MRAM_WORD_SIZE), ironside_se_ver)) {
/* Wait until MRAM controller is ready */
}
memcpy((void *)(addr + (i * MRAM_WORD_SIZE)),
(void *)((uintptr_t)data + (i * MRAM_WORD_SIZE)), MRAM_WORD_SIZE);
}

if (len % MRAM_WORD_SIZE) {
while (!nrf_mram_ready(addr + (len & ~MRAM_WORD_MASK), ironside_se_ver)) {
/* Wait until MRAM controller is ready */
}
memcpy((void *)(addr + (len & ~MRAM_WORD_MASK)),
(void *)((uintptr_t)data + (len & ~MRAM_WORD_MASK)), len & MRAM_WORD_MASK);
}
commit_changes(addr + len);
if (ironside_se_ver >= IRONSIDE_SE_SUPPORT_READY_VER) {
mram_no_latency_sync_release();
}

return 0;
}

static int nrf_mram_erase(const struct device *dev, off_t offset, size_t size)
{
ARG_UNUSED(dev);
struct nrf_mram_data_t *nrf_mram_data = dev->data;
uint8_t ironside_se_ver = nrf_mram_data->ironside_se_ver;

const uintptr_t addr = validate_and_map_addr(offset, size, true);

Expand All @@ -129,8 +181,27 @@

LOG_DBG("erase: %p:%zu", (void *)addr, size);

memset((void *)addr, ERASE_VALUE, size);
/* Ensure that the mramc banks are powered on */
if (ironside_se_ver >= IRONSIDE_SE_SUPPORT_READY_VER) {
mram_no_latency_sync_request();
}
for (uint32_t i = 0; i < (size / MRAM_WORD_SIZE); i++) {
while (!nrf_mram_ready(addr + (i * MRAM_WORD_SIZE), ironside_se_ver)) {
/* Wait until MRAM controller is ready */
}
memset((void *)(addr + (i * MRAM_WORD_SIZE)), ERASE_VALUE, MRAM_WORD_SIZE);
}
if (size % MRAM_WORD_SIZE) {
while (!nrf_mram_ready(addr + (size & ~MRAM_WORD_MASK), ironside_se_ver)) {
/* Wait until MRAM controller is ready */
}
memset((void *)(addr + (size & ~MRAM_WORD_MASK)), ERASE_VALUE,
size & MRAM_WORD_MASK);
}
commit_changes(addr + size);
if (ironside_se_ver >= IRONSIDE_SE_SUPPORT_READY_VER) {
mram_no_latency_sync_release();
}

return 0;
}
Expand Down Expand Up @@ -186,5 +257,27 @@
#endif
};

DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, NULL, POST_KERNEL, CONFIG_FLASH_INIT_PRIORITY,
&nrf_mram_api);
static int nrf_mram_init(const struct device *dev)
{
struct nrf_mram_data_t *nrf_mram_data = dev->data;
const struct ironside_boot_report *report;
int rc = 0;

rc = ironside_boot_report_get(&report);

if (rc) {
LOG_ERR("Failed to get Ironside boot report");
return rc;
}

nrf_mram_data->ironside_se_ver = FIELD_GET(IRONSIDE_SE_VER_MASK,
report->ironside_se_version_int);
LOG_DBG("Ironside SE version: %u", nrf_mram_data->ironside_se_ver);

Check notice on line 275 in drivers/flash/soc_flash_nrf_mram.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/flash/soc_flash_nrf_mram.c:275 - nrf_mram_data->ironside_se_ver = FIELD_GET(IRONSIDE_SE_VER_MASK, - report->ironside_se_version_int); + nrf_mram_data->ironside_se_ver = + FIELD_GET(IRONSIDE_SE_VER_MASK, report->ironside_se_version_int);

return 0;
}

static struct nrf_mram_data_t nrf_mram_data;

DEVICE_DT_INST_DEFINE(0, nrf_mram_init, NULL, &nrf_mram_data, NULL, POST_KERNEL,
CONFIG_FLASH_INIT_PRIORITY, &nrf_mram_api);
2 changes: 1 addition & 1 deletion tests/drivers/mspi/flash/testcase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ tests:
- CONFIG_MSPI_DW_HANDLE_FIFOS_IN_SYSTEM_WORKQUEUE=y
drivers.mspi.flash.mspi_nor_no_multithreading:
filter: dt_alias_exists("mspi0") and CONFIG_FLASH_MSPI_NOR
integration_platforms:
platform_exclude:
- nrf54h20dk/nrf54h20/cpuapp
extra_configs:
- CONFIG_MULTITHREADING=n
Loading