99#include <zephyr/drivers/flash.h>
1010#include <zephyr/logging/log.h>
1111#include <zephyr/sys/barrier.h>
12+ #include <zephyr/cache.h>
13+ #include "../soc/nordic/common/mram_latency.h"
14+ #include "../soc/nordic/ironside/include/nrf_ironside/boot_report.h"
1215
1316LOG_MODULE_REGISTER (flash_nrf_mram , CONFIG_FLASH_LOG_LEVEL );
1417
@@ -25,10 +28,37 @@ LOG_MODULE_REGISTER(flash_nrf_mram, CONFIG_FLASH_LOG_LEVEL);
2528
2629#define ERASE_VALUE 0xff
2730
31+ #define SOC_NRF_MRAM_BANK_11_OFFSET 0x100000
32+ #define SOC_NRF_MRAM_BANK_11_ADDRESS (MRAM_START + SOC_NRF_MRAM_BANK_11_OFFSET)
33+ #define SOC_NRF_MRAMC_BASE_ADDR_10 0x5f092000
34+ #define SOC_NRF_MRAMC_BASE_ADDR_11 0x5f093000
35+ #define SOC_NRF_MRAMC_READY_REG_0 (SOC_NRF_MRAMC_BASE_ADDR_10 + 0x400)
36+ #define SOC_NRF_MRAMC_READY_REG_1 (SOC_NRF_MRAMC_BASE_ADDR_11 + 0x400)
37+
38+ #define IRONSIDE_SE_VER_MASK 0x000000FF /* This is the Mask for Ironside SE Seqnum */
39+ #define IRONSIDE_SE_SUPPORT_READY_VER 21
40+
2841BUILD_ASSERT (MRAM_START > 0 , "nordic,mram: start address expected to be non-zero" );
2942BUILD_ASSERT ((ERASE_BLOCK_SIZE % WRITE_BLOCK_SIZE ) == 0 ,
3043 "erase-block-size expected to be a multiple of write-block-size" );
3144
45+ struct nrf_mram_data_t {
46+ uint8_t ironside_se_ver ;
47+ };
48+
49+ static inline uint32_t nrf_mram_ready (uint32_t addr , uint8_t ironside_se_ver )
50+ {
51+ if (ironside_se_ver < IRONSIDE_SE_SUPPORT_READY_VER ) {
52+ return 1 ;
53+ }
54+
55+ if (addr < SOC_NRF_MRAM_BANK_11_ADDRESS ) {
56+ return sys_read32 (SOC_NRF_MRAMC_READY_REG_0 );
57+ } else {
58+ return sys_read32 (SOC_NRF_MRAMC_READY_REG_1 );
59+ }
60+ }
61+
3262/**
3363 * @param[in,out] offset Relative offset into memory, from the driver API.
3464 * @param[in] len Number of bytes for the intended operation.
@@ -101,7 +131,8 @@ static int nrf_mram_read(const struct device *dev, off_t offset, void *data, siz
101131
102132static int nrf_mram_write (const struct device * dev , off_t offset , const void * data , size_t len )
103133{
104- ARG_UNUSED (dev );
134+ struct nrf_mram_data_t * nrf_mram_data = dev -> data ;
135+ uint8_t ironside_se_ver = nrf_mram_data -> ironside_se_ver ;
105136
106137 const uintptr_t addr = validate_and_map_addr (offset , len , true);
107138
@@ -111,15 +142,36 @@ static int nrf_mram_write(const struct device *dev, off_t offset, const void *da
111142
112143 LOG_DBG ("write: %p:%zu" , (void * )addr , len );
113144
114- memcpy ((void * )addr , data , len );
145+ if (ironside_se_ver >= IRONSIDE_SE_SUPPORT_READY_VER ) {
146+ mram_no_latency_sync_request ();
147+ }
148+ for (uint32_t i = 0 ; i < (len / MRAM_WORD_SIZE ); i ++ ) {
149+ while (!nrf_mram_ready (addr + (i * MRAM_WORD_SIZE ), ironside_se_ver )) {
150+ /* Wait until MRAM controller is ready */
151+ }
152+ memcpy ((void * )(addr + (i * MRAM_WORD_SIZE )),
153+ (void * )((uintptr_t )data + (i * MRAM_WORD_SIZE )), MRAM_WORD_SIZE );
154+ }
155+
156+ if (len % MRAM_WORD_SIZE ) {
157+ while (!nrf_mram_ready (addr + (len & ~MRAM_WORD_MASK ), ironside_se_ver )) {
158+ /* Wait until MRAM controller is ready */
159+ }
160+ memcpy ((void * )(addr + (len & ~MRAM_WORD_MASK )),
161+ (void * )((uintptr_t )data + (len & ~MRAM_WORD_MASK )), len & MRAM_WORD_MASK );
162+ }
115163 commit_changes (addr + len );
164+ if (ironside_se_ver >= IRONSIDE_SE_SUPPORT_READY_VER ) {
165+ mram_no_latency_sync_release ();
166+ }
116167
117168 return 0 ;
118169}
119170
120171static int nrf_mram_erase (const struct device * dev , off_t offset , size_t size )
121172{
122- ARG_UNUSED (dev );
173+ struct nrf_mram_data_t * nrf_mram_data = dev -> data ;
174+ uint8_t ironside_se_ver = nrf_mram_data -> ironside_se_ver ;
123175
124176 const uintptr_t addr = validate_and_map_addr (offset , size , true);
125177
@@ -129,8 +181,27 @@ static int nrf_mram_erase(const struct device *dev, off_t offset, size_t size)
129181
130182 LOG_DBG ("erase: %p:%zu" , (void * )addr , size );
131183
132- memset ((void * )addr , ERASE_VALUE , size );
184+ /* Ensure that the mramc banks are powered on */
185+ if (ironside_se_ver >= IRONSIDE_SE_SUPPORT_READY_VER ) {
186+ mram_no_latency_sync_request ();
187+ }
188+ for (uint32_t i = 0 ; i < (size / MRAM_WORD_SIZE ); i ++ ) {
189+ while (!nrf_mram_ready (addr + (i * MRAM_WORD_SIZE ), ironside_se_ver )) {
190+ /* Wait until MRAM controller is ready */
191+ }
192+ memset ((void * )(addr + (i * MRAM_WORD_SIZE )), ERASE_VALUE , MRAM_WORD_SIZE );
193+ }
194+ if (size % MRAM_WORD_SIZE ) {
195+ while (!nrf_mram_ready (addr + (size & ~MRAM_WORD_MASK ), ironside_se_ver )) {
196+ /* Wait until MRAM controller is ready */
197+ }
198+ memset ((void * )(addr + (size & ~MRAM_WORD_MASK )), ERASE_VALUE ,
199+ size & MRAM_WORD_MASK );
200+ }
133201 commit_changes (addr + size );
202+ if (ironside_se_ver >= IRONSIDE_SE_SUPPORT_READY_VER ) {
203+ mram_no_latency_sync_release ();
204+ }
134205
135206 return 0 ;
136207}
@@ -186,5 +257,27 @@ static DEVICE_API(flash, nrf_mram_api) = {
186257#endif
187258};
188259
189- DEVICE_DT_INST_DEFINE (0 , NULL , NULL , NULL , NULL , POST_KERNEL , CONFIG_FLASH_INIT_PRIORITY ,
190- & nrf_mram_api );
260+ static int nrf_mram_init (const struct device * dev )
261+ {
262+ struct nrf_mram_data_t * nrf_mram_data = dev -> data ;
263+ const struct ironside_boot_report * report ;
264+ int rc = 0 ;
265+
266+ rc = ironside_boot_report_get (& report );
267+
268+ if (rc ) {
269+ LOG_ERR ("Failed to get Ironside boot report" );
270+ return rc ;
271+ }
272+
273+ nrf_mram_data -> ironside_se_ver = FIELD_GET (IRONSIDE_SE_VER_MASK ,
274+ report -> ironside_se_version_int );
275+ LOG_DBG ("Ironside SE version: %u" , nrf_mram_data -> ironside_se_ver );
276+
277+ return 0 ;
278+ }
279+
280+ static struct nrf_mram_data_t nrf_mram_data ;
281+
282+ DEVICE_DT_INST_DEFINE (0 , nrf_mram_init , NULL , & nrf_mram_data , NULL , POST_KERNEL ,
283+ CONFIG_FLASH_INIT_PRIORITY , & nrf_mram_api );
0 commit comments