1 /*
2  * Copyright 2018-2021 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  */
8 
9 #include "fsl_k4_flash.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.flash_k4"
18 #endif
19 
20 #if defined(FLASH_DRIVER_IS_FLASH_RESIDENT) && FLASH_DRIVER_IS_FLASH_RESIDENT
21 /*!
22  * @brief Constants for execute-in-RAM flash function.
23  */
24 enum _ftfx_ram_func_constants
25 {
26     Flash_RunCommandCodeSize     = 6U,  /*!< The flash_run_command code size of execute-in-RAM.*/
27     Flash_ErsSequenceCommandSize = 25U, /*!< The flash_erase_sequence func code size of execute-in-RAM.*/
28     Flash_PgmSequenceCommandSize = 30U, /*!< The flash_program_sequence func size of execute-in-RAM.*/
29 };
30 #endif
31 /*******************************************************************************
32  * Prototypes
33  ******************************************************************************/
34 /*! @brief Init IFR memory related info */
35 static status_t flash_check_param(
36     flash_config_t *config, FMU_Type *base, uint32_t start, uint32_t lengthInBytes, uint32_t alignmentBaseline);
37 static status_t pflash_check_param(
38     flash_config_t *config, FMU_Type *base, uint32_t *start, uint32_t lengthInBytes, uint32_t alignmentBaseline);
39 static status_t ifr_check_param(
40     flash_config_t *config, FMU_Type *base, uint32_t *start, uint32_t lengthInBytes, uint32_t alignmentBaseline);
41 static status_t flash_check_user_key(uint32_t key);
42 
43 /*******************************************************************************
44  * Variables
45  ******************************************************************************/
46 
47 /*******************************************************************************
48  * Code
49  ******************************************************************************/
50 
FLASH_Init(flash_config_t * config)51 status_t FLASH_Init(flash_config_t *config)
52 {
53     status_t status = kStatus_Fail;
54 
55     if (config == NULL)
56     {
57         status = kStatus_FLASH_InvalidArgument;
58     }
59     else
60     {
61         /* CM33 flash */
62         config->msf1Config[0].flashDesc.blockBase  = FLASH_FEATURE_PFLASH0_START_ADDRESS;
63         config->msf1Config[0].flashDesc.blockCount = FLASH_FEATURE_PFLASH0_BLOCK_COUNT;
64 
65 #if (defined(CPU_KW45B41Z82AFPA) || defined(CPU_KW45B41Z82AFTA) || defined(CPU_KW45B41Z83AFPA) || \
66      defined(CPU_KW45B41Z83AFTA) || defined(CPU_KW45Z41082AFPA) || defined(CPU_KW45Z41082AFTA) || \
67      defined(CPU_KW45Z41083AFPA) || defined(CPU_KW45Z41083AFTA) || defined(CPU_K32W1480VFTA))
68         /* M33 flash size 1MB */
69         config->msf1Config[0].flashDesc.totalSize =
70             FLASH_FEATURE_PFLASH0_BLOCK_COUNT * FLASH_FEATURE_PFLASH0_BLOCK_SIZE;
71 #elif (defined(CPU_KW45B41Z52AFPA) || defined(CPU_KW45B41Z52AFTA) || defined(CPU_KW45B41Z53AFPA) || \
72        defined(CPU_KW45B41Z53AFTA) || defined(CPU_KW45Z41052AFPA) || defined(CPU_KW45Z41052AFTA) || \
73        defined(CPU_KW45Z41053AFPA) || defined(CPU_KW45Z41053AFTA))
74         /* M33 flash size 512KB */
75         config->msf1Config[0].flashDesc.totalSize =
76             FLASH_FEATURE_PFLASH0_BLOCK_COUNT * FLASH_FEATURE_PFLASH0_BLOCK_SIZE_512KB;
77 #elif (defined(CPU_KW47B42ZB7AFTA_cm33_core0))
78         config->msf1Config[0].flashDesc.totalSize =
79             FLASH_FEATURE_PFLASH0_BLOCK_COUNT * FLASH_FEATURE_PFLASH0_BLOCK_SIZE;
80 #elif (defined(CPU_MCXW716CMFTA) || (CPU_MCXW716CMFPA) || (CPU_MCXW716AMFTA) || (CPU_MCXW716AMFPA) || defined(CPU_MCXW727CMFTA_cm33_core0))
81         config->msf1Config[0].flashDesc.totalSize =
82             FLASH_FEATURE_PFLASH0_BLOCK_COUNT * FLASH_FEATURE_PFLASH0_BLOCK_SIZE;
83 #else
84 #error "No valid CPU defined!"
85 #endif
86 
87         config->msf1Config[0].ifrDesc.pflashIfr0Start   = FLASH_FEATURE_PFLASH0_IFR0_START_ADDRESS;
88         config->msf1Config[0].ifrDesc.pflashIfr0MemSize = FLASH_FEATURE_PFLASH0_IFR0_SIZE;
89 
90         /* RF flash */
91 #if (defined(CPU_KW45B41Z82AFPA) || defined(CPU_KW45B41Z82AFTA) || defined(CPU_KW45B41Z83AFPA) || \
92      defined(CPU_KW45B41Z83AFTA) || defined(CPU_KW45B41Z52AFPA) || defined(CPU_KW45B41Z52AFTA) || \
93      defined(CPU_KW45B41Z53AFPA) || defined(CPU_KW45B41Z53AFTA) || defined(CPU_K32W1480VFTA))
94         config->msf1Config[1].flashDesc.blockBase  = FLASH_FEATURE_PFLASH1_START_ADDRESS;
95         config->msf1Config[1].flashDesc.blockCount = FLASH_FEATURE_PFLASH1_BLOCK_COUNT;
96         config->msf1Config[1].flashDesc.totalSize =
97             FLASH_FEATURE_PFLASH1_BLOCK_COUNT * FLASH_FEATURE_PFLASH1_BLOCK_SIZE;
98 
99         config->msf1Config[1].ifrDesc.pflashIfr0Start   = FLASH_FEATURE_PFLASH1_IFR0_START_ADDRESS;
100         config->msf1Config[1].ifrDesc.pflashIfr0MemSize = FLASH_FEATURE_PFLASH1_IFR0_SIZE;
101 
102 #elif (defined(CPU_KW45Z41082AFPA) || defined(CPU_KW45Z41082AFTA) || defined(CPU_KW45Z41083AFPA) || \
103        defined(CPU_KW45Z41083AFTA) || defined(CPU_KW45Z41052AFPA) || defined(CPU_KW45Z41052AFTA) || \
104        defined(CPU_KW45Z41053AFPA) || defined(CPU_KW45Z41053AFTA))
105         config->msf1Config[1].flashDesc.blockBase  = FLASH_FEATURE_PFLASH1_START_ADDRESS;
106         config->msf1Config[1].flashDesc.blockCount = 0U;
107         config->msf1Config[1].flashDesc.totalSize  = 0U;
108 
109         config->msf1Config[1].ifrDesc.pflashIfr0Start   = FLASH_FEATURE_PFLASH1_IFR0_START_ADDRESS;
110         config->msf1Config[1].ifrDesc.pflashIfr0MemSize = 0U;
111 #elif (defined(CPU_KW47B42ZB7AFTA_cm33_core0))
112         config->msf1Config[1].flashDesc.blockBase  = FLASH_FEATURE_PFLASH1_START_ADDRESS;
113         config->msf1Config[1].flashDesc.blockCount = FLASH_FEATURE_PFLASH1_BLOCK_COUNT;
114         config->msf1Config[1].flashDesc.totalSize =
115             FLASH_FEATURE_PFLASH1_BLOCK_COUNT * FLASH_FEATURE_PFLASH1_BLOCK_SIZE;
116 
117         config->msf1Config[1].ifrDesc.pflashIfr0Start   = FLASH_FEATURE_PFLASH1_IFR0_START_ADDRESS;
118         config->msf1Config[1].ifrDesc.pflashIfr0MemSize = FLASH_FEATURE_PFLASH1_IFR0_SIZE;
119 #elif (defined(CPU_MCXW716CMFTA) || (CPU_MCXW716CMFPA) || (CPU_MCXW716AMFTA) || (CPU_MCXW716AMFPA)|| defined(CPU_MCXW727CMFTA_cm33_core0))
120         config->msf1Config[1].flashDesc.blockBase  = FLASH_FEATURE_PFLASH1_START_ADDRESS;
121         config->msf1Config[1].flashDesc.blockCount = FLASH_FEATURE_PFLASH1_BLOCK_COUNT;
122         config->msf1Config[1].flashDesc.totalSize =
123             FLASH_FEATURE_PFLASH1_BLOCK_COUNT * FLASH_FEATURE_PFLASH1_BLOCK_SIZE;
124 
125         config->msf1Config[1].ifrDesc.pflashIfr0Start   = FLASH_FEATURE_PFLASH1_IFR0_START_ADDRESS;
126         config->msf1Config[1].ifrDesc.pflashIfr0MemSize = FLASH_FEATURE_PFLASH1_IFR0_SIZE;
127 #else
128 #error "No valid CPU defined!"
129 #endif
130 
131         status = kStatus_FLASH_Success;
132     }
133 
134     return status;
135 }
136 
FLASH_Erase(flash_config_t * config,FMU_Type * base,uint32_t start,uint32_t lengthInBytes,uint32_t key)137 status_t FLASH_Erase(flash_config_t *config, FMU_Type *base, uint32_t start, uint32_t lengthInBytes, uint32_t key)
138 {
139     status_t status = kStatus_Fail;
140 
141     status = flash_check_param(config, base, start, lengthInBytes, FLASH_FEATURE_PHRASE_SIZE);
142     if ((status == kStatus_FLASH_Success) && (flash_check_user_key(key) == kStatus_FLASH_Success))
143     {
144         uint32_t endAddress = start + lengthInBytes - 1U;
145 
146         while (start <= endAddress)
147         {
148             status = FLASH_CMD_EraseSector(base, start);
149             if (kStatus_FLASH_Success != status)
150             {
151                 break;
152             }
153             else
154             {
155                 /* Increment to the next sector */
156                 start += FLASH_FEATURE_SECTOR_SIZE;
157             }
158         }
159     }
160     else
161     {
162         ; // MISRA
163     }
164 
165     return status;
166 }
167 
FLASH_EraseAll(FMU_Type * base,uint32_t key)168 status_t FLASH_EraseAll(FMU_Type *base, uint32_t key)
169 {
170     status_t status   = kStatus_Fail;
171     FMU_Type *baseTmp = (FMU_Type *)((uint32_t)base & FLASH_ADDR_MASK);
172 #if defined(RF_FMU)
173     if (base == NULL || (baseTmp != FLASH && baseTmp != NBU_FLASH))
174 #else
175     if (base == NULL || baseTmp != FLASH)
176 #endif
177     {
178         status = kStatus_FLASH_InvalidArgument;
179     }
180     else
181     {
182         /* Validate the user key */
183         status = flash_check_user_key(key);
184     }
185 
186     if (kStatus_FLASH_Success == status)
187     {
188         status = FLASH_CMD_EraseAll(base);
189     }
190     else
191     {
192         ; // MISRA
193     }
194 
195     return status;
196 }
197 
FLASH_Program(flash_config_t * config,FMU_Type * base,uint32_t start,uint8_t * src,uint32_t lengthInBytes)198 status_t FLASH_Program(flash_config_t *config, FMU_Type *base, uint32_t start, uint8_t *src, uint32_t lengthInBytes)
199 {
200     status_t status = kStatus_Fail;
201 
202     status = flash_check_param(config, base, start, lengthInBytes, FLASH_FEATURE_PHRASE_SIZE);
203     if (status == kStatus_FLASH_Success)
204     {
205         // Align length to whole phrase.
206         uint32_t alignedLength = ALIGN_DOWN(lengthInBytes, sizeof(uint8_t) * FLASH_FEATURE_PHRASE_SIZE);
207         uint32_t extraBytes    = lengthInBytes - alignedLength;
208         uint32_t *srcWord      = (uint32_t *)(uintptr_t)src;
209 
210         if (alignedLength > 0U)
211         {
212             uint32_t endAddress = start + alignedLength - 1U;
213             while (start <= endAddress)
214             {
215                 status = FLASH_CMD_ProgramPhrase(base, start, srcWord);
216                 if (kStatus_FLASH_Success != status)
217                 {
218                     break;
219                 }
220                 else
221                 {
222                     /* Increment to the next sector */
223                     start += FLASH_FEATURE_PHRASE_SIZE;
224                     srcWord += FLASH_FEATURE_PHRASE_SIZE_IN_WORD;
225                 }
226             }
227         }
228         else
229         {
230             ; // MISRA
231         }
232 
233         if ((kStatus_FLASH_Success == status) && (extraBytes > 0U))
234         {
235             uint32_t extraData[4] = {0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu};
236 
237             // Copy extra bytes to phrase buffer.
238             union
239             {
240                 uint32_t *src;
241                 const void *srcVoid;
242             } srcPtr;
243             srcPtr.src = srcWord;
244 
245             union
246             {
247                 uint32_t *xData;
248                 void *xDataVoid;
249             } xDataPtr;
250             xDataPtr.xData = (uint32_t *)&extraData[0];
251 
252             (void)memcpy(xDataPtr.xDataVoid, srcPtr.srcVoid, extraBytes);
253 
254             status = FLASH_CMD_ProgramPhrase(base, start, extraData);
255         }
256     }
257     else
258     {
259         ; // MISRA
260     }
261 
262     return status;
263 }
264 
FLASH_ProgramPage(flash_config_t * config,FMU_Type * base,uint32_t start,uint8_t * src,uint32_t lengthInBytes)265 status_t FLASH_ProgramPage(flash_config_t *config, FMU_Type *base, uint32_t start, uint8_t *src, uint32_t lengthInBytes)
266 {
267     status_t status = kStatus_Fail;
268 
269     status = flash_check_param(config, base, start, lengthInBytes, FLASH_FEATURE_PAGE_SIZE);
270     if (status == kStatus_FLASH_Success)
271     {
272         // Align length to whole phrase.
273         uint32_t alignedLength = ALIGN_DOWN(lengthInBytes, sizeof(uint8_t) * FLASH_FEATURE_PAGE_SIZE);
274         uint32_t extraBytes    = lengthInBytes - alignedLength;
275         uint32_t *srcWord      = (uint32_t *)(uintptr_t)src;
276 
277         if (alignedLength > 0U)
278         {
279             uint32_t endAddress = start + alignedLength - 1U;
280             while (start <= endAddress)
281             {
282                 status = FLASH_CMD_ProgramPage(base, start, srcWord);
283                 if (kStatus_FLASH_Success != status)
284                 {
285                     break;
286                 }
287                 else
288                 {
289                     /* Increment to the next sector */
290                     start += FLASH_FEATURE_PAGE_SIZE;
291                     srcWord += FLASH_FEATURE_PAGE_SIZE_IN_WORD;
292                 }
293             }
294         }
295         else
296         {
297             ; // MISRA
298         }
299 
300         if ((kStatus_FLASH_Success == status) && (extraBytes > 0U))
301         {
302             uint32_t extraData[32] = {
303                 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu,
304                 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu,
305                 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu,
306                 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu};
307 
308             // Copy extra bytes to page buffer.
309             union
310             {
311                 uint32_t *src;
312                 const void *srcVoid;
313             } srcPtr;
314             srcPtr.src = srcWord;
315 
316             union
317             {
318                 uint32_t *xData;
319                 void *xDataVoid;
320             } xDataPtr;
321             xDataPtr.xData = (uint32_t *)&extraData[0];
322 
323             (void)memcpy(xDataPtr.xDataVoid, srcPtr.srcVoid, extraBytes);
324 
325             status = FLASH_CMD_ProgramPage(base, start, extraData);
326         }
327     }
328     else
329     {
330         ; // MISRA
331     }
332 
333     return status;
334 }
335 
FLASH_VerifyErasePhrase(flash_config_t * config,FMU_Type * base,uint32_t start,uint32_t lengthInBytes)336 status_t FLASH_VerifyErasePhrase(flash_config_t *config, FMU_Type *base, uint32_t start, uint32_t lengthInBytes)
337 {
338     status_t status    = kStatus_Fail;
339     uint32_t startaddr = start;
340 
341     status = pflash_check_param(config, base, &startaddr, lengthInBytes, FLASH_FEATURE_PHRASE_SIZE);
342     if (status == kStatus_FLASH_Success)
343     {
344         uint32_t endAddress = startaddr + lengthInBytes - 1U;
345         while (startaddr <= endAddress)
346         {
347             status = FLASH_CMD_VerifyErasePhrase(base, startaddr);
348             if (kStatus_FLASH_Success != status)
349             {
350                 break;
351             }
352             else
353             {
354                 /* Increment to the next phrase */
355                 startaddr += FLASH_FEATURE_PHRASE_SIZE;
356             }
357         }
358     }
359     else
360     {
361         ; // MISRA
362     }
363 
364     return status;
365 }
366 
FLASH_VerifyErasePage(flash_config_t * config,FMU_Type * base,uint32_t start,uint32_t lengthInBytes)367 status_t FLASH_VerifyErasePage(flash_config_t *config, FMU_Type *base, uint32_t start, uint32_t lengthInBytes)
368 {
369     status_t status    = kStatus_Fail;
370     uint32_t startaddr = start;
371 
372     status = pflash_check_param(config, base, &startaddr, lengthInBytes, FLASH_FEATURE_PAGE_SIZE);
373     if (status == kStatus_FLASH_Success)
374     {
375         uint32_t endAddress = startaddr + lengthInBytes - 1U;
376         while (startaddr <= endAddress)
377         {
378             status = FLASH_CMD_VerifyErasePage(base, startaddr);
379             if (kStatus_FLASH_Success != status)
380             {
381                 break;
382             }
383             else
384             {
385                 /* Increment to the next page */
386                 startaddr += FLASH_FEATURE_PAGE_SIZE;
387             }
388         }
389     }
390     else
391     {
392         ; // MISRA
393     }
394 
395     return status;
396 }
397 
FLASH_VerifyEraseSector(flash_config_t * config,FMU_Type * base,uint32_t start,uint32_t lengthInBytes)398 status_t FLASH_VerifyEraseSector(flash_config_t *config, FMU_Type *base, uint32_t start, uint32_t lengthInBytes)
399 {
400     status_t status    = kStatus_Fail;
401     uint32_t startaddr = start;
402 
403     status = pflash_check_param(config, base, &startaddr, lengthInBytes, FLASH_FEATURE_SECTOR_SIZE);
404     if (status == kStatus_FLASH_Success)
405     {
406         uint32_t endAddress = startaddr + lengthInBytes - 1U;
407         while (startaddr <= endAddress)
408         {
409             status = FLASH_CMD_VerifyEraseSector(base, startaddr);
410             if (kStatus_FLASH_Success != status)
411             {
412                 break;
413             }
414             else
415             {
416                 /* Increment to the next sector */
417                 startaddr += FLASH_FEATURE_SECTOR_SIZE;
418             }
419         }
420     }
421     else
422     {
423         ; // MISRA
424     }
425 
426     return status;
427 }
428 
FLASH_VerifyEraseIFRPhrase(flash_config_t * config,FMU_Type * base,uint32_t start,uint32_t lengthInBytes)429 status_t FLASH_VerifyEraseIFRPhrase(flash_config_t *config, FMU_Type *base, uint32_t start, uint32_t lengthInBytes)
430 {
431     status_t status    = kStatus_Fail;
432     uint32_t startaddr = start;
433 
434     status = ifr_check_param(config, base, &startaddr, lengthInBytes, FLASH_FEATURE_PHRASE_SIZE);
435     if (status == kStatus_FLASH_Success)
436     {
437         uint32_t endAddress = startaddr + lengthInBytes - 1U;
438         while (startaddr <= endAddress)
439         {
440             status = FLASH_CMD_VerifyEraseIFRPhrase(base, startaddr);
441             if (kStatus_FLASH_Success != status)
442             {
443                 break;
444             }
445             else
446             {
447                 /* Increment to the next phrase */
448                 startaddr += FLASH_FEATURE_PHRASE_SIZE;
449             }
450         }
451     }
452     else
453     {
454         ; // MISRA
455     }
456 
457     return status;
458 }
459 
FLASH_VerifyEraseIFRPage(flash_config_t * config,FMU_Type * base,uint32_t start,uint32_t lengthInBytes)460 status_t FLASH_VerifyEraseIFRPage(flash_config_t *config, FMU_Type *base, uint32_t start, uint32_t lengthInBytes)
461 {
462     status_t status    = kStatus_Fail;
463     uint32_t startaddr = start;
464 
465     status = ifr_check_param(config, base, &startaddr, lengthInBytes, FLASH_FEATURE_PAGE_SIZE);
466     if (status == kStatus_FLASH_Success)
467     {
468         uint32_t endAddress = startaddr + lengthInBytes - 1U;
469         while (startaddr <= endAddress)
470         {
471             status = FLASH_CMD_VerifyEraseIFRPage(base, startaddr);
472             if (kStatus_FLASH_Success != status)
473             {
474                 break;
475             }
476             else
477             {
478                 /* Increment to the next page */
479                 startaddr += FLASH_FEATURE_PAGE_SIZE;
480             }
481         }
482     }
483     else
484     {
485         ; // MISRA
486     }
487 
488     return status;
489 }
490 
FLASH_VerifyEraseIFRSector(flash_config_t * config,FMU_Type * base,uint32_t start,uint32_t lengthInBytes)491 status_t FLASH_VerifyEraseIFRSector(flash_config_t *config, FMU_Type *base, uint32_t start, uint32_t lengthInBytes)
492 {
493     status_t status    = kStatus_Fail;
494     uint32_t startaddr = start;
495 
496     status = ifr_check_param(config, base, &startaddr, lengthInBytes, FLASH_FEATURE_SECTOR_SIZE);
497     if (status == kStatus_FLASH_Success)
498     {
499         uint32_t endAddress = startaddr + lengthInBytes - 1U;
500         while (startaddr <= endAddress)
501         {
502             status = FLASH_CMD_VerifyEraseIFRSector(base, startaddr);
503             if (kStatus_FLASH_Success != status)
504             {
505                 break;
506             }
507             else
508             {
509                 /* Increment to the next sector */
510                 startaddr += FLASH_FEATURE_SECTOR_SIZE;
511             }
512         }
513     }
514     else
515     {
516         ; // MISRA
517     }
518 
519     return status;
520 }
521 
FLASH_VerifyEraseAll(FMU_Type * base)522 status_t FLASH_VerifyEraseAll(FMU_Type *base)
523 {
524     status_t status   = kStatus_Fail;
525     FMU_Type *baseTmp = (FMU_Type *)((uint32_t)base & FLASH_ADDR_MASK);
526 #if defined(RF_FMU)
527     if (base == NULL || ((baseTmp != FLASH) && (baseTmp != NBU_FLASH)))
528 #else
529     if (base == NULL || baseTmp != FLASH)
530 #endif
531     {
532         status = kStatus_FLASH_InvalidArgument;
533     }
534     else
535     {
536         status = FLASH_CMD_VerifyEraseAll(base);
537     }
538 
539     return status;
540 }
541 
FLASH_VerifyEraseBlock(flash_config_t * config,FMU_Type * base,uint32_t blockaddr)542 status_t FLASH_VerifyEraseBlock(flash_config_t *config, FMU_Type *base, uint32_t blockaddr)
543 {
544     status_t status      = kStatus_Fail;
545     uint32_t nsblockaddr = blockaddr & FLASH_ADDR_MASK;
546     FMU_Type *baseTmp    = (FMU_Type *)((uint32_t)base & FLASH_ADDR_MASK);
547 
548 #if defined(RF_FMU)
549     if (config == NULL || base == NULL || ((baseTmp != FLASH) && (baseTmp != NBU_FLASH)))
550 #else
551     if (config == NULL || base == NULL || baseTmp != FLASH)
552 #endif
553     {
554         status = kStatus_FLASH_InvalidArgument;
555     }
556     else if ((nsblockaddr != config->msf1Config[0].flashDesc.blockBase) &&
557              (nsblockaddr != config->msf1Config[1].flashDesc.blockBase))
558     {
559         status = kStatus_FLASH_AddressError;
560     }
561     else
562     {
563         /* K4W1 M33 and NBU flash both have only one block, so 0U is sufficient here */
564         status = FLASH_CMD_VerifyEraseBlock(base, 0U);
565     }
566 
567     return status;
568 }
569 
Read_Into_MISR(flash_config_t * config,FMU_Type * base,uint32_t start,uint32_t ending,uint32_t * seed,uint32_t * signature)570 status_t Read_Into_MISR(
571     flash_config_t *config, FMU_Type *base, uint32_t start, uint32_t ending, uint32_t *seed, uint32_t *signature)
572 {
573     status_t status    = kStatus_Fail;
574     uint32_t startAddr = start;
575 
576     if ((start >= ending) || (seed == NULL) ||
577         (((ending + FLASH_FEATURE_PHRASE_SIZE) & (FLASH_FEATURE_PAGE_SIZE - 1U)) != 0u))
578     {
579         status = kStatus_FLASH_InvalidArgument;
580     }
581     else if ((ending & (FLASH_FEATURE_PHRASE_SIZE - 1U)) != 0u)
582     {
583         status = kStatus_FLASH_AlignmentError;
584     }
585     else
586     {
587         status = pflash_check_param(config, base, &startAddr, (ending - start), FLASH_FEATURE_PAGE_SIZE);
588         if (status == kStatus_FLASH_Success)
589         {
590             uint32_t endAddr = startAddr + ending - start;
591             status           = FLASH_CMD_ReadIntoMISR(base, startAddr, endAddr, seed, signature);
592         }
593         else
594         {
595             ; // MISRA
596         }
597     }
598 
599     return status;
600 }
601 
Read_IFR_Into_MISR(flash_config_t * config,FMU_Type * base,uint32_t start,uint32_t ending,uint32_t * seed,uint32_t * signature)602 status_t Read_IFR_Into_MISR(
603     flash_config_t *config, FMU_Type *base, uint32_t start, uint32_t ending, uint32_t *seed, uint32_t *signature)
604 {
605     status_t status    = kStatus_Fail;
606     uint32_t startAddr = start;
607 
608     if ((start >= ending) || (seed == NULL) ||
609         (((ending + FLASH_FEATURE_PHRASE_SIZE) & (FLASH_FEATURE_PAGE_SIZE - 1U)) != 0U))
610     {
611         status = kStatus_FLASH_InvalidArgument;
612     }
613     else if ((ending & (FLASH_FEATURE_PHRASE_SIZE - 1U)) != 0u)
614     {
615         status = kStatus_FLASH_AlignmentError;
616     }
617     else
618     {
619         status = ifr_check_param(config, base, &startAddr, (ending - start), FLASH_FEATURE_PAGE_SIZE);
620         if (status == kStatus_FLASH_Success)
621         {
622             uint32_t endAddr = startAddr + ending - start;
623             status           = FLASH_CMD_ReadIFRIntoMISR(base, startAddr, endAddr, seed, signature);
624         }
625         else
626         {
627             ; // MISRA
628         }
629     }
630 
631     return status;
632 }
633 
FLASH_GetProperty(flash_config_t * config,flash_property_tag_t whichProperty,uint32_t * value)634 status_t FLASH_GetProperty(flash_config_t *config, flash_property_tag_t whichProperty, uint32_t *value)
635 {
636     status_t status = kStatus_FLASH_Success;
637 
638     switch (whichProperty)
639     {
640         case kFLASH_PropertyPflash0TotalSize:
641             *value = config->msf1Config[0].flashDesc.totalSize;
642             break;
643         case kFLASH_PropertyPflash0BlockSize:
644             *value = config->msf1Config[0].flashDesc.totalSize / config->msf1Config[0].flashDesc.blockCount;
645             break;
646         case kFLASH_PropertyPflash0BlockCount:
647             *value = config->msf1Config[0].flashDesc.blockCount;
648             break;
649         case kFLASH_PropertyPflash0BlockBaseAddr:
650             *value = config->msf1Config[0].flashDesc.blockBase;
651             break;
652         case kFLASH_PropertyPflash0SectorSize:
653             *value = FLASH_FEATURE_SECTOR_SIZE;
654             break;
655         case kFLASH_PropertyPflash1TotalSize:
656             *value = config->msf1Config[1].flashDesc.totalSize;
657             break;
658         case kFLASH_PropertyPflash1BlockSize:
659             *value = config->msf1Config[1].flashDesc.totalSize / config->msf1Config[1].flashDesc.blockCount;
660             break;
661         case kFLASH_PropertyPflash1BlockCount:
662             *value = config->msf1Config[1].flashDesc.blockCount;
663             break;
664         case kFLASH_PropertyPflash1BlockBaseAddr:
665             *value = config->msf1Config[1].flashDesc.blockBase;
666             break;
667         default:
668             status = kStatus_FLASH_UnknownProperty;
669             /* To avoid MISRA-C 2012 rule 16.4 issue. */
670             break;
671     }
672     return status;
673 }
674 
675 #if defined(FLASH_DRIVER_IS_FLASH_RESIDENT) && (FLASH_DRIVER_IS_FLASH_RESIDENT == 1)
676 #if defined(__IAR_SYSTEMS_ICC__)
677 __ramfunc
678 #elif defined(__GNUC__)
679 __attribute__ ((section (".ramfunc")))
680 #endif
681 #endif
682     void
flash_cache_disable(void)683     flash_cache_disable(void)
684 {
685     SMSCM->OCMDR0 = (SMSCM->OCMDR0 & (~SMSCM_FLASH_CACHE_CTRL_MASK)) | SMSCM_FLASH_CACHE_CTRL(0x1);
686     SMSCM->OCMDR0 = (SMSCM->OCMDR0 & (~SMSCM_FLASH_CACHE_CTRL_MASK)) | SMSCM_FLASH_CACHE_CTRL(0x8);
687     SMSCM->OCMDR0 = (SMSCM->OCMDR0 & (~SMSCM_FLASH_SPECULATION_CTRL_MASK)) | SMSCM_FLASH_SPECULATION_CTRL(0x3);
688     __ISB();
689     __DSB();
690 }
691 
692 #if defined(FLASH_DRIVER_IS_FLASH_RESIDENT) && (FLASH_DRIVER_IS_FLASH_RESIDENT == 1)
693 #if defined(__IAR_SYSTEMS_ICC__)
694 __ramfunc
695 #elif defined(__GNUC__)
696 __attribute__ ((section (".ramfunc")))
697 #endif
698 #endif
699     void
flash_cache_speculation_control(bool isPreProcess,FMU_Type * base)700     flash_cache_speculation_control(bool isPreProcess, FMU_Type *base)
701 {
702     if (base == FLASH)
703     {
704         if (isPreProcess == false)
705         {
706             SMSCM->OCMDR0 = (SMSCM->OCMDR0 & (~SMSCM_FLASH_CACHE_CTRL_MASK)) | SMSCM_FLASH_CACHE_CTRL(0x1);
707             SMSCM->OCMDR0 = (SMSCM->OCMDR0 & (~SMSCM_FLASH_SPECULATION_CTRL_MASK)) | SMSCM_FLASH_SPECULATION_CTRL(0x0);
708         }
709         else
710         {
711             SMSCM->OCMDR0 = (SMSCM->OCMDR0 & (~SMSCM_FLASH_SPECULATION_CTRL_MASK)) | SMSCM_FLASH_SPECULATION_CTRL(0x3);
712         }
713     }
714 #if defined(RF_FMU)
715     else if (base == NBU_FLASH)
716     {
717         if (isPreProcess == false)
718         {
719             RF_FMCCFG->RFMCCFG = (RF_FMCCFG->RFMCCFG & (~NBU_FLASH_CACHE_CTRL_MASK)) | NBU_FLASH_CACHE_CTRL(0x1);
720             RF_FMCCFG->RFMCCFG =
721                 (RF_FMCCFG->RFMCCFG & (~NBU_FLASH_SPECULATION_CTRL_MASK)) | NBU_FLASH_SPECULATION_CTRL(0x0);
722         }
723         else
724         {
725             RF_FMCCFG->RFMCCFG =
726                 (RF_FMCCFG->RFMCCFG & (~NBU_FLASH_SPECULATION_CTRL_MASK)) | NBU_FLASH_SPECULATION_CTRL(0x3);
727         }
728     }
729 #endif
730     else
731     {
732         ; /* No action required */
733     }
734     /* Memory barriers for good measure.
735      * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */
736     __ISB();
737     __DSB();
738 }
739 
flash_check_param(flash_config_t * config,FMU_Type * base,uint32_t start,uint32_t lengthInBytes,uint32_t alignmentBaseline)740 static status_t flash_check_param(
741     flash_config_t *config, FMU_Type *base, uint32_t start, uint32_t lengthInBytes, uint32_t alignmentBaseline)
742 {
743     status_t status   = kStatus_FLASH_InvalidArgument;
744     FMU_Type *baseTmp = (FMU_Type *)((uint32_t)base & FLASH_ADDR_MASK);
745 
746     if (lengthInBytes == 0U)
747     {
748         status = kStatus_FLASH_Success;
749     }
750 #if defined(RF_FMU)
751     else if (config == NULL || base == NULL || ((baseTmp != FLASH) && (baseTmp != NBU_FLASH)))
752 #else
753     else if (config == NULL || base == NULL || baseTmp != FLASH)
754 #endif
755     {
756         status = kStatus_FLASH_InvalidArgument;
757     }
758     else if ((start & (alignmentBaseline - 1U)) != 0u)
759     {
760         /* Verify the start is alignmentBaseline aligned. */
761         status = kStatus_FLASH_AlignmentError;
762     }
763     else
764     {
765         start = start & FLASH_ADDR_MASK;
766 
767         if (baseTmp == FLASH)
768         {
769             /* Validates the range of the given address */
770             if ((start >= config->msf1Config[0].flashDesc.blockBase) &&
771                 ((start + lengthInBytes) <=
772                  (config->msf1Config[0].flashDesc.blockBase + config->msf1Config[0].flashDesc.totalSize)))
773             {
774                 status = kStatus_FLASH_Success;
775             }
776             else
777 
778                 if ((start >= config->msf1Config[0].ifrDesc.pflashIfr0Start) &&
779                     ((start + lengthInBytes) <=
780                      (config->msf1Config[0].ifrDesc.pflashIfr0Start + config->msf1Config[0].ifrDesc.pflashIfr0MemSize)))
781             {
782                 status = kStatus_FLASH_Success;
783             }
784             else
785             {
786                 status = kStatus_FLASH_AddressError;
787             }
788         }
789         else // if (base == NBU_FLASH || base == NBU_FLASH_NS)
790         {
791             /* Validates the range of the given address */
792             if ((start >= config->msf1Config[1].flashDesc.blockBase) &&
793                 ((start + lengthInBytes) <=
794                  (config->msf1Config[1].flashDesc.blockBase + config->msf1Config[1].flashDesc.totalSize)))
795             {
796                 status = kStatus_FLASH_Success;
797             }
798             else
799 
800                 if ((start >= config->msf1Config[1].ifrDesc.pflashIfr0Start) &&
801                     ((start + lengthInBytes) <=
802                      (config->msf1Config[1].ifrDesc.pflashIfr0Start + config->msf1Config[1].ifrDesc.pflashIfr0MemSize)))
803             {
804                 status = kStatus_FLASH_Success;
805             }
806             else
807             {
808                 status = kStatus_FLASH_AddressError;
809             }
810         }
811     }
812 
813     return status;
814 }
815 
pflash_check_param(flash_config_t * config,FMU_Type * base,uint32_t * start,uint32_t lengthInBytes,uint32_t alignmentBaseline)816 static status_t pflash_check_param(
817     flash_config_t *config, FMU_Type *base, uint32_t *start, uint32_t lengthInBytes, uint32_t alignmentBaseline)
818 {
819     status_t status   = kStatus_FLASH_InvalidArgument;
820     FMU_Type *baseTmp = (FMU_Type *)((uint32_t)base & FLASH_ADDR_MASK);
821 
822     if (lengthInBytes == 0U)
823     {
824         status = kStatus_FLASH_Success;
825     }
826 #if defined(RF_FMU)
827     else if ((config == NULL) || (base == NULL) || ((baseTmp != FLASH) && (baseTmp != NBU_FLASH)))
828 #else
829     else if ((config == NULL) || (base == NULL) || (baseTmp != FLASH))
830 #endif
831     {
832         status = kStatus_FLASH_InvalidArgument;
833     }
834     else if ((*start & (alignmentBaseline - 1U)) != 0u)
835     {
836         /* Verify the start is alignmentBaseline aligned. */
837         status = kStatus_FLASH_AlignmentError;
838     }
839     else
840     {
841         *start &= FLASH_ADDR_MASK;
842 
843         if (baseTmp == FLASH)
844         {
845             /* Validates the range of the given address */
846             if ((*start >= config->msf1Config[0].flashDesc.blockBase) &&
847                 ((*start + lengthInBytes) <=
848                  (config->msf1Config[0].flashDesc.blockBase + config->msf1Config[0].flashDesc.totalSize)))
849             {
850                 *start -= config->msf1Config[0].flashDesc.blockBase;
851                 status = kStatus_FLASH_Success;
852             }
853             else
854             {
855                 status = kStatus_FLASH_AddressError;
856             }
857         }
858         else // if (base == NBU_FLASH || base == NBU_FLASH_NS)
859         {
860             /* Validates the range of the given address */
861             if ((*start >= config->msf1Config[1].flashDesc.blockBase) &&
862                 ((*start + lengthInBytes) <=
863                  (config->msf1Config[1].flashDesc.blockBase + config->msf1Config[1].flashDesc.totalSize)))
864             {
865                 *start -= config->msf1Config[1].flashDesc.blockBase;
866                 status = kStatus_FLASH_Success;
867             }
868             else
869             {
870                 status = kStatus_FLASH_AddressError;
871             }
872         }
873     }
874 
875     return status;
876 }
877 
ifr_check_param(flash_config_t * config,FMU_Type * base,uint32_t * start,uint32_t lengthInBytes,uint32_t alignmentBaseline)878 static status_t ifr_check_param(
879     flash_config_t *config, FMU_Type *base, uint32_t *start, uint32_t lengthInBytes, uint32_t alignmentBaseline)
880 {
881     status_t status   = kStatus_FLASH_InvalidArgument;
882     FMU_Type *baseTmp = (FMU_Type *)((uint32_t)base & FLASH_ADDR_MASK);
883 
884     if (lengthInBytes == 0U)
885     {
886         status = kStatus_FLASH_Success;
887     }
888 #if defined(RF_FMU)
889     else if (config == NULL || base == NULL || ((baseTmp != FLASH) && (baseTmp != NBU_FLASH)))
890 #else
891     else if (config == NULL || base == NULL || baseTmp != FLASH)
892 #endif
893     {
894         status = kStatus_FLASH_InvalidArgument;
895     }
896     else
897 
898         /* Verify the start is alignmentBaseline aligned. */
899         if ((*start & (alignmentBaseline - 1U)) != 0u)
900     {
901         status = kStatus_FLASH_AlignmentError;
902     }
903     else
904     {
905         *start &= FLASH_ADDR_MASK;
906 
907         if (baseTmp == FLASH)
908         {
909             if ((*start >= config->msf1Config[0].ifrDesc.pflashIfr0Start) &&
910                 ((*start + lengthInBytes) <=
911                  (config->msf1Config[0].ifrDesc.pflashIfr0Start + config->msf1Config[0].ifrDesc.pflashIfr0MemSize)))
912             {
913                 *start -= config->msf1Config[0].ifrDesc.pflashIfr0Start;
914                 status = kStatus_FLASH_Success;
915             }
916             else
917             {
918                 status = kStatus_FLASH_AddressError;
919             }
920         }
921         else // if (base == NBU_FLASH || base == NBU_FLASH_NS)
922         {
923             if ((*start >= config->msf1Config[1].ifrDesc.pflashIfr0Start) &&
924                 ((*start + lengthInBytes) <=
925                  (config->msf1Config[1].ifrDesc.pflashIfr0Start + config->msf1Config[1].ifrDesc.pflashIfr0MemSize)))
926             {
927                 *start -= config->msf1Config[1].ifrDesc.pflashIfr0Start;
928                 status = kStatus_FLASH_Success;
929             }
930             else
931             {
932                 status = kStatus_FLASH_AddressError;
933             }
934         }
935     }
936 
937     return status;
938 }
939 
940 /*! @brief Validates the given user key for flash erase APIs.*/
flash_check_user_key(uint32_t key)941 static status_t flash_check_user_key(uint32_t key)
942 {
943     status_t status = kStatus_Fail;
944 
945     /* Validate the user key */
946     if (key != (uint32_t)kFLASH_ApiEraseKey)
947     {
948         status = kStatus_FLASH_EraseKeyError;
949     }
950     else
951     {
952         status = kStatus_FLASH_Success;
953     }
954 
955     return status;
956 }
957