1 /*
2  * Copyright 2017 - 2021 NXP
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_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"
18 #endif
19 
20 /*!
21  * @name Misc utility defines
22  * @{
23  */
24 /*! @brief Alignment utility. */
25 #ifndef ALIGN_DOWN
26 #define ALIGN_DOWN(x, a) (((uint32_t)(x)) & ~((uint32_t)(a)-1u))
27 #endif
28 #ifndef ALIGN_UP
29 #define ALIGN_UP(x, a) ALIGN_DOWN((uint32_t)(x) + (uint32_t)(a)-1u, a)
30 #endif
31 
32 /*! @brief Join bytes to word utility. */
33 #define B1P2(b)                      (((uint32_t)(b)&0xFFU) << 8U)
34 #define B1P1(b)                      ((uint32_t)(b)&0xFFU)
35 #define B2P1(b)                      ((uint32_t)(b)&0xFFFFU)
36 #define BYTES_JOIN_TO_WORD_1_1(x, y) (B1P1(x) | B1P2(y))
37 #define BYTES_JOIN_TO_WORD_1_2(x, y) (B1P2(x) | B2P1(y))
38 /*@}*/
39 
40 /*!
41  * @name Secondary flash configuration
42  * @{
43  */
44 /*! @brief Indicates whether the secondary flash has its own protection register
45  * in flash module. */
46 #define FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER (0)
47 /*@}*/
48 
49 /*!
50  * @name Flash cache ands speculation control defines
51  * @{
52  */
53 #if defined(MCM_PLACR_CFCC_MASK) || defined(MCM_CPCR2_CCBC_MASK)
54 #define FLASH_CACHE_IS_CONTROLLED_BY_MCM (1U)
55 #else
56 #define FLASH_CACHE_IS_CONTROLLED_BY_MCM (0U)
57 #endif
58 #if defined(FMC_PFB0CR_CINV_WAY_MASK) || defined(FMC_PFB01CR_CINV_WAY_MASK)
59 #define FLASH_CACHE_IS_CONTROLLED_BY_FMC (1U)
60 #else
61 #define FLASH_CACHE_IS_CONTROLLED_BY_FMC (0U)
62 #endif
63 #if defined(MCM_PLACR_DFCS_MASK)
64 #define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM (1U)
65 #else
66 #define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM (0U)
67 #endif
68 #if defined(FMC_PFB0CR_S_INV_MASK) || defined(FMC_PFB0CR_S_B_INV_MASK) || defined(FMC_PFB01CR_S_INV_MASK) || \
69     defined(FMC_PFB01CR_S_B_INV_MASK)
70 #define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC (1U)
71 #else
72 #define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC (0U)
73 #endif
74 /*@}*/
75 
76 /*!
77  * @name Reserved EEPROM size (For a variety of purposes) defines
78  * @{
79  */
80 #define NVM_EEPROM_SIZE_FOR_EEESIZE_RESERVED 0x100UL
81 /*@}*/
82 
83 /*!
84  * @name Flash Program Once Field defines
85  * @{
86  */
87 #if defined(FSL_FEATURE_FLASH_IS_FTMRE) || defined(FSL_FEATURE_FLASH_IS_FTMRH)
88 /* FTMRE and FTMRH only support 8-bytes unit size */
89 #define FLASH_PROGRAM_ONCE_IS_4BYTES_UNIT_SUPPORT 0U
90 #define FLASH_PROGRAM_ONCE_IS_8BYTES_UNIT_SUPPORT 1U
91 #endif
92 /*@}*/
93 
94 /*!
95  * @name Flash security status defines
96  * @{
97  */
98 #define FLASH_SECURITY_STATE_KEYEN     0x80U
99 #define FLASH_SECURITY_STATE_UNSECURED 0x02U
100 #define FLASH_NOT_SECURE               0x01U
101 #define FLASH_SECURE_BACKDOOR_ENABLED  0x02U
102 #define FLASH_SECURE_BACKDOOR_DISABLED 0x04U
103 /*@}*/
104 
105 /*!
106  * @name Flash controller command numbers
107  * @{
108  */
109 #define FTMRx_ERASE_VERIFY_ALL_BLOCK      0x01U /*!< ERSVERALL*/
110 #define FTMRx_ERASE_VERIFY_BLOCK          0x02U /*!< ERSVERBLK*/
111 #define FTMRx_ERASE_VERIFY_SECTION        0x03U /*!< ERSVERSECT*/
112 #define FTMRx_READ_ONCE                   0x04U /*!< RDONCE or RDINDEX*/
113 #define FTMRx_PROGRAM                     0x06U /*!< PGM*/
114 #define FTMRx_PROGRAM_ONCE                0x07U /*!< PGMONCE or PGMINDEX*/
115 #define FTMRx_ERASE_ALL_BLOCK             0x08U /*!< ERSALL*/
116 #define FTMRx_ERASE_BLOCK                 0x09U /*!< ERSBLK*/
117 #define FTMRx_ERASE_SECTOR                0x0AU /*!< ERSSCR*/
118 #define FTMRx_ERASE_ALL_BLOCK_UNSECURE    0x0BU /*!< ERSALLU*/
119 #define FTMRx_SECURITY_BY_PASS            0x0CU /*!< VFYKEY*/
120 #define FTMRx_SET_USER_MARGIN_LEVEL       0x0DU /*!< SETUSERLVL*/
121 #define FTMRx_SET_FACTORY_MARGIN_LEVEL    0x0EU /*!< SETFTYLVL*/
122 #define FTMRx_CONFIGURE_NVM               0x0FU /*!< CONNVM*/
123 #define FTMRx_ERASE_VERIFY_EEPROM_SECTION 0x10U /*!< ERSVES*/
124 #define FTMRx_PROGRAM_EEPROM              0x11U /*!< PGME*/
125 #define FTMRx_ERASE_EEPROM_SECTOR         0x12U /*!< ERSESCR*/
126                                                 /*@}*/
127 
128 /*!
129  * @name Common flash register info defines
130  * @{
131  */
132 #if defined(FTMRE)
133 #define FTMRx                      FTMRE
134 #define FTMRx_BASE                 FTMRE_BASE
135 #define FTMRx_FCCOBIX_CCOBIX(x)    FTMRE_FCCOBIX_CCOBIX(x)
136 #define FTMRx_FCCOBLO_CCOB(x)      FTMRE_FCCOBLO_CCOB(x)
137 #define FTMRx_FCCOBHI_CCOB(x)      FTMRE_FCCOBHI_CCOB(x)
138 #define FTMRx_FCLKDIV_FDIVLCK_MASK FTMRE_FCLKDIV_FDIVLCK_MASK
139 #define FTMRx_FCLKDIV_FDIVLD_MASK  FTMRE_FCLKDIV_FDIVLD_MASK
140 #define FTMRx_FCLKDIV_FDIV_MASK    FTMRE_FCLKDIV_FDIV_MASK
141 #define FTMRx_FSTAT_CCIF_MASK      FTMRE_FSTAT_CCIF_MASK
142 #define FTMRx_FCLKDIV_FDIV(x)      FTMRE_FCLKDIV_FDIV(x)
143 #define FTMRx_FSTAT_ACCERR_MASK    FTMRE_FSTAT_ACCERR_MASK
144 #define FTMRx_FSTAT_FPVIOL_MASK    FTMRE_FSTAT_FPVIOL_MASK
145 #define FTMRx_FSTAT_MGBUSY_MASK    FTMRE_FSTAT_MGBUSY_MASK
146 #define FTMRx_FSTAT_MGSTAT_MASK    FTMRE_FSTAT_MGSTAT_MASK
147 #define FTMRx_FSTAT_MGSTAT0_MASK   FTMRE_FSTAT_MGSTAT(1)
148 #define FTMRx_FSTAT_MGSTAT1_MASK   FTMRE_FSTAT_MGSTAT(2)
149 #define FTMRx_FSEC_SEC_MASK        FTMRE_FSEC_SEC_MASK
150 #define FTMRx_FSEC_KEYEN_MASK      FTMRE_FSEC_KEYEN_MASK
151 #if defined(FTMRE_FPROT_FPHDIS_MASK)
152 #define FTMRx_FPROT_FPHDIS_MASK FTMRE_FPROT_FPHDIS_MASK
153 #endif
154 #if defined(FTMRE_FERSTAT_SFDIF_MASK)
155 #define FTMRx_FERSTAT_SFDIF_MASK FTMRE_FERSTAT_SFDIF_MASK
156 #define FTMRx_FERSTAT_DFDIF_MASK FTMRE_FERSTAT_DFDIF_MASK
157 #endif
158 #elif defined(FTMRH)
159 #define FTMRx                      FTMRH
160 #define FTMRx_BASE                 FTMRH_BASE
161 #define FTMRx_FCCOBIX_CCOBIX(x)    FTMRH_FCCOBIX_CCOBIX(x)
162 #define FTMRx_FCCOBLO_CCOB(x)      FTMRH_FCCOBLO_CCOB(x)
163 #define FTMRx_FCCOBHI_CCOB(x)      FTMRH_FCCOBHI_CCOB(x)
164 #define FTMRx_FCLKDIV_FDIVLCK_MASK FTMRH_FCLKDIV_FDIVLCK_MASK
165 #define FTMRx_FCLKDIV_FDIVLD_MASK  FTMRH_FCLKDIV_FDIVLD_MASK
166 #define FTMRx_FCLKDIV_FDIV_MASK    FTMRH_FCLKDIV_FDIV_MASK
167 #define FTMRx_FCLKDIV_FDIV(x)      FTMRH_FCLKDIV_FDIV(x)
168 #define FTMRx_FSTAT_CCIF_MASK      FTMRH_FSTAT_CCIF_MASK
169 #define FTMRx_FSTAT_ACCERR_MASK    FTMRH_FSTAT_ACCERR_MASK
170 #define FTMRx_FSTAT_FPVIOL_MASK    FTMRH_FSTAT_FPVIOL_MASK
171 #define FTMRx_FSTAT_MGBUSY_MASK    FTMRH_FSTAT_MGBUSY_MASK
172 #define FTMRx_FSTAT_MGSTAT_MASK    FTMRH_FSTAT_MGSTAT_MASK
173 #define FTMRx_FSTAT_MGSTAT0_MASK   FTMRH_FSTAT_MGSTAT(1U)
174 #define FTMRx_FSTAT_MGSTAT1_MASK   FTMRH_FSTAT_MGSTAT(2U)
175 #define FTMRx_FSEC_SEC_MASK        FTMRH_FSEC_SEC_MASK
176 #define FTMRx_FSEC_KEYEN_MASK      FTMRH_FSEC_KEYEN_MASK
177 #if defined(FTMRH_FPROT_FPHDIS_MASK)
178 #define FTMRx_FPROT_FPHDIS_MASK FTMRH_FPROT_FPHDIS_MASK
179 #endif
180 #if defined(FTMRH_FERSTAT_SFDIF_MASK)
181 #define FTMRx_FERSTAT_SFDIF_MASK FTMRH_FERSTAT_SFDIF_MASK
182 #define FTMRx_FERSTAT_DFDIF_MASK FTMRH_FERSTAT_DFDIF_MASK
183 #endif
184 #else
185 #error "Unknown flash controller"
186 #endif
187 /*@}*/
188 
189 /*!
190  * @brief Enumeration for flash config area.
191  */
192 enum _flash_config_area_range
193 {
194     kFLASH_ConfigAreaStart = 0x400UL,
195     kFLASH_ConfigAreaEnd   = 0x40FUL
196 };
197 
198 /*!
199  * @name Flash register access type defines
200  * @{
201  */
202 #define FTMRx_REG8_ACCESS_TYPE  volatile uint8_t *
203 #define FTMRx_REG32_ACCESS_TYPE volatile uint32_t *
204 /*@}*/
205 
206 /*!
207  * @brief MCM cache register access info defines.
208  */
209 #if defined(MCM_PLACR_CFCC_MASK)
210 #define MCM_CACHE_CLEAR_MASK  MCM_PLACR_CFCC_MASK
211 #define MCM_CACHE_CLEAR_SHIFT MCM_PLACR_CFCC_SHIFT
212 #if defined(MCM)
213 #define MCM0_CACHE_REG MCM->PLACR
214 #elif defined(MCM0)
215 #define MCM0_CACHE_REG MCM0->PLACR
216 #endif
217 #if defined(MCM1)
218 #define MCM1_CACHE_REG MCM1->PLACR
219 #endif
220 #elif defined(MCM_CPCR2_CCBC_MASK)
221 #define MCM_CACHE_CLEAR_MASK  MCM_CPCR2_CCBC_MASK
222 #define MCM_CACHE_CLEAR_SHIFT MCM_CPCR2_CCBC_SHIFT
223 #if defined(MCM)
224 #define MCM0_CACHE_REG MCM->CPCR2
225 #elif defined(MCM0)
226 #define MCM0_CACHE_REG MCM0->CPCR2
227 #endif
228 #if defined(MCM1)
229 #define MCM1_CACHE_REG MCM1->CPCR2
230 #endif
231 #endif
232 
233 /*******************************************************************************
234  * Prototypes
235  ******************************************************************************/
236 
237 #if FLASH_DRIVER_IS_FLASH_RESIDENT
238 /*! @brief Copy flash_run_command() to RAM*/
239 static void copy_flash_run_command(flash_config_t *config);
240 /*! @brief Copy flash_cache_clear_command() to RAM*/
241 static void copy_flash_common_bit_operation(flash_config_t *config);
242 /*! @brief Check whether flash execute-in-ram functions are ready*/
243 static status_t flash_check_execute_in_ram_function_info(flash_config_t *config);
244 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
245 
246 /*! @brief Internal function Flash command sequence. Called by driver APIs
247  * only
248  */
249 static status_t flash_command_sequence(flash_config_t *config);
250 
251 /*! @brief Internal function Flash common bit operation command sequence. Called by driver APIs
252  * only
253  */
254 #if FLASH_DRIVER_IS_FLASH_RESIDENT
255 static void flash_common_bit_operation_command_sequence(
256     flash_config_t *config, FTMRx_REG32_ACCESS_TYPE base, uint32_t bitMask, uint32_t bitShift, uint32_t bitValue);
257 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
258 
259 /*! @brief Internal function Flash set command. Called by driver APIs only*/
260 void flash_set_command(uint32_t index, uint32_t fValue, uint32_t sValue);
261 
262 /*! @brief Perform the cache clear to the flash*/
263 void flash_cache_clear(flash_config_t *config);
264 
265 /*! @brief Process the cache to the flash*/
266 static void flash_cache_clear_process(flash_config_t *config, flash_cache_clear_process_t process);
267 
268 /*! @brief Validates the range and alignment of the given address range.*/
269 static status_t flash_check_range(flash_config_t *config,
270                                   uint32_t startAddress,
271                                   uint32_t lengthInBytes,
272                                   uint32_t alignmentBaseline);
273 
274 /*! @brief Validates the range and alignment of the given address range.*/
275 #if FLASH_SSD_IS_EEPROM_ENABLED
276 static status_t EEPROM_check_range(flash_config_t *config,
277                                    uint32_t startAddress,
278                                    uint32_t lengthInBytes,
279                                    uint32_t alignmentBaseline);
280 #endif /* FLASH_SSD_IS_EEPROM_ENABLED */
281 
282 /*! @brief Gets the right address, sector and block size of current flash type
283  * which is indicated by address.*/
284 static status_t flash_get_matched_operation_info(flash_config_t *config,
285                                                  uint32_t address,
286                                                  flash_operation_config_t *info);
287 /*! @brief Validates the given user key for flash erase APIs.*/
288 static status_t flash_check_user_key(uint32_t key);
289 
290 /*! @brief Gets the flash protection information.*/
291 static status_t flash_get_protection_info(flash_config_t *config, flash_protection_config_t *info);
292 
293 #if FLASH_CACHE_IS_CONTROLLED_BY_MCM
294 /*! @brief Performs the cache clear to the flash by MCM.*/
295 void mcm_flash_cache_clear(flash_config_t *config);
296 #endif /* FLASH_CACHE_IS_CONTROLLED_BY_MCM */
297 
298 #if FLASH_CACHE_IS_CONTROLLED_BY_FMC
299 /*! @brief Performs the cache clear to the flash by FMC.*/
300 void fmc_flash_cache_clear(void);
301 #endif /* FLASH_CACHE_IS_CONTROLLED_BY_FMC */
302 
303 #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC
304 /*! @brief Performs the prefetch speculation buffer clear to the flash by FMC.*/
305 void fmc_flash_prefetch_speculation_clear(void);
306 #endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC */
307 
308 /*! @brief Set the flash and eeprom to the specified user margin level.*/
309 status_t flash_setusermarginlevel(flash_config_t *config,
310                                   uint32_t start,
311                                   uint8_t iseeprom,
312                                   flash_user_margin_value_t margin);
313 
314 /*! @brief Set the flash and eeprom to the specified factory margin level.*/
315 status_t flash_setfactorymarginlevel(flash_config_t *config,
316                                      uint32_t start,
317                                      uint8_t iseeprom,
318                                      flash_factory_margin_value_t margin);
319 
320 /*******************************************************************************
321  * Variables
322  ******************************************************************************/
323 
324 #if FLASH_DRIVER_IS_FLASH_RESIDENT
325 /*! @brief A function pointer used to point to relocated flash_run_command() */
326 static void (*callFlashRunCommand)(FTMRx_REG8_ACCESS_TYPE FTMRx_fstat);
327 /*! @brief A function pointer used to point to relocated
328  * flash_common_bit_operation() */
329 static void (*callFlashCommonBitOperation)(FTMRx_REG32_ACCESS_TYPE base,
330                                            uint32_t bitMask,
331                                            uint32_t bitShift,
332                                            uint32_t bitValue);
333 
334 /*!
335  * @brief Position independent code of flash_run_command()
336  *
337  * Note1: The prototype of C function is shown as below:
338  * @code
339  *   void flash_run_command(FTMRx_REG8_ACCESS_TYPE FTMRx_fstat)
340  *   {
341  *       PRINT("\r\nClear CCIF bit.\r\n);
342  *       *FTMRx_fstat = FTMRx_FSTAT_CCIF_MASK;
343  *
344  *       PRINT("\r\nCheck CCIF bit of the flash status register, wait till it is set.\r\n");
345  *       PRINT("\r\nIP team indicates that this loop will always complete.\r\n");
346  *       while (!((*FTMRx_fstat) & FTMRx_FSTAT_CCIF_MASK))
347  *       {
348  *       }
349  *   }
350  * @endcode
351  * Note2: The binary code is generated by IAR 7.70.1
352  */
353 const static uint16_t s_flashRunCommandFunctionCode[] = {0x2180, 0x7001, 0x7802, 0x420a, 0xd0fc, 0x4770};
354 
355 /*!
356  * @brief Position independent code of flash_common_bit_operation()
357  *
358  * Note1: The prototype of C function is shown as below:
359  * @code
360  *   void flash_common_bit_operation(FTMRx_REG32_ACCESS_TYPE base, uint32_t
361  * bitMask, uint32_t bitShift, uint32_t
362  * bitValue)
363  *   {
364  *       if (bitMask)
365  *       {
366  *           uint32_t value = (((uint32_t)(((uint32_t)(bitValue)) << bitShift))
367  * & bitMask);
368  *           *base = (*base & (~bitMask)) | value;
369  *       }
370  *
371  *       __ISB();
372  *       __DSB();
373  *   }
374  * @endcode
375  * Note2: The binary code is generated by IAR 7.70.1
376  */
377 const static uint16_t s_flashCommonBitOperationFunctionCode[] = {
378     0xb510, 0x2900, 0xd005, 0x6804, 0x438c, 0x4093, 0x4019, 0x4321, 0x6001, 0xf3bf, 0x8f6f, 0xf3bf, 0x8f4f, 0xbd10};
379 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
380 
381 #if (FLASH_DRIVER_IS_FLASH_RESIDENT && !FLASH_DRIVER_IS_EXPORTED)
382 /*! @brief A static buffer used to hold flash_run_command() */
383 static uint32_t s_flashRunCommand[kFLASH_ExecuteInRamFunctionMaxSizeInWords];
384 /*! @brief A static buffer used to hold flash_common_bit_operation() */
385 static uint32_t s_flashCommonBitOperation[kFLASH_ExecuteInRamFunctionMaxSizeInWords];
386 #endif
387 
388 /*******************************************************************************
389  * Code
390  ******************************************************************************/
391 
392 /*!
393  * brief Initializes the global flash properties structure members.
394  *
395  * This function checks and initializes the Flash module for the other Flash
396  * APIs.
397  *
398  * param config Pointer to the storage for the driver runtime state.
399  *
400  * retval #kStatus_FLASH_Success API was executed successfully.
401  * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
402  * retval #kStatus_FLASH_ClockDivider Flash clock prescaler is wrong.
403  * retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is
404  * not available.
405  */
FLASH_Init(flash_config_t * config)406 status_t FLASH_Init(flash_config_t *config)
407 {
408     status_t returnCode;
409     uint8_t clkDiver;
410 
411     if (config == NULL)
412     {
413         return kStatus_FLASH_InvalidArgument;
414     }
415     clkDiver = (uint8_t)(config->PFlashClockFreq / 1000000UL - 1UL);
416 
417     /* Initialize the flash clock to be within spec 1MHz. */
418     if ((0U == (FTMRx->FCLKDIV & FTMRx_FCLKDIV_FDIVLCK_MASK)) && (0U != (FTMRx->FSTAT & FTMRx_FSTAT_CCIF_MASK)))
419     {
420         /* FCLKDIV register is not locked.*/
421         FTMRx->FCLKDIV = (uint8_t)(FTMRx->FCLKDIV & (~FTMRx_FCLKDIV_FDIV_MASK)) | FTMRx_FCLKDIV_FDIV(clkDiver);
422         if ((FTMRx->FCLKDIV & FTMRx_FCLKDIV_FDIV_MASK) != FTMRx_FCLKDIV_FDIV(clkDiver))
423         {
424             return kStatus_FLASH_ClockDivider;
425         }
426     }
427     else
428     {
429         /* FCLKDIV register is locked. */
430         if ((FTMRx->FCLKDIV & FTMRx_FCLKDIV_FDIV_MASK) != FTMRx_FCLKDIV_FDIV(clkDiver))
431         {
432             return kStatus_FLASH_ClockDivider;
433         }
434     }
435 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED
436     if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash)
437     {
438         config->PFlashBlockBase = SECONDARY_FLASH_FEATURE_PFLASH_START_ADDRESS;
439         config->PFlashTotalSize =
440             SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_COUNT * SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_SIZE;
441         config->PFlashBlockCount = SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_COUNT;
442         config->PFlashSectorSize = SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_SECTOR_SIZE;
443     }
444     else
445 #endif
446     {
447         /* fill out a few of the structure members */
448         config->PFlashBlockBase  = FSL_FEATURE_FLASH_PFLASH_START_ADDRESS;
449         config->PFlashTotalSize  = FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE;
450         config->PFlashBlockCount = FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT;
451         config->PFlashSectorSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE;
452     }
453     config->PFlashCallback = NULL;
454 
455 /* copy required flash commands to RAM */
456 #if (FLASH_DRIVER_IS_FLASH_RESIDENT && !FLASH_DRIVER_IS_EXPORTED)
457     if (kStatus_FLASH_Success != flash_check_execute_in_ram_function_info(config))
458     {
459         config->executeInRamFunction.activeFunctionCount                     = 0UL;
460         config->executeInRamFunction.runCmdFuncAddr.commadAddr               = (uint32_t)s_flashRunCommand;
461         config->executeInRamFunction.CommonBitOperationAddr.bitOperationAddr = (uint32_t)s_flashCommonBitOperation;
462         config->flashExecuteInRamFunctionInfo = &config->executeInRamFunction.activeFunctionCount;
463         returnCode                            = FLASH_PrepareExecuteInRamFunctions(config);
464         if (returnCode != kStatus_FLASH_Success)
465         {
466             return returnCode;
467         }
468     }
469 #endif
470 #if FLASH_SSD_IS_EEPROM_ENABLED
471     config->EEpromBlockBase  = FSL_FEATURE_FLASH_EEPROM_START_ADDRESS;
472     config->EEpromBlockCount = FSL_FEATURE_FLASH_EEPROM_BLOCK_COUNT;
473     config->EEpromTotalSize  = FSL_FEATURE_FLASH_EEPROM_BLOCK_SIZE * FSL_FEATURE_FLASH_EEPROM_BLOCK_COUNT;
474     config->EEpromSectorSize = FSL_FEATURE_FLASH_EEPROM_BLOCK_SECTOR_SIZE;
475 #endif
476     config->PFlashMarginLevel = (uint32_t)kFLASH_MarginValueNormal;
477 
478     return kStatus_FLASH_Success;
479 }
480 
481 /*!
482  * brief Sets the desired flash callback function.
483  *
484  * param config Pointer to the storage for the driver runtime state.
485  * param callback A callback function to be stored in the driver.
486  *
487  * retval #kStatus_FLASH_Success API was executed successfully.
488  * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
489  */
FLASH_SetCallback(flash_config_t * config,flash_callback_t callback)490 status_t FLASH_SetCallback(flash_config_t *config, flash_callback_t callback)
491 {
492     if (config == NULL)
493     {
494         return kStatus_FLASH_InvalidArgument;
495     }
496 
497     config->PFlashCallback = callback;
498 
499     return kStatus_FLASH_Success;
500 }
501 
502 #if defined(FLASH_DRIVER_IS_FLASH_RESIDENT) && FLASH_DRIVER_IS_FLASH_RESIDENT
FLASH_PrepareExecuteInRamFunctions(flash_config_t * config)503 status_t FLASH_PrepareExecuteInRamFunctions(flash_config_t *config)
504 {
505     flash_execute_in_ram_function_config_t *flashExecuteInRamFunctionInfo = &config->executeInRamFunction;
506 
507     if ((config == NULL) || (config->flashExecuteInRamFunctionInfo == NULL))
508     {
509         return kStatus_FLASH_InvalidArgument;
510     }
511     /* copy flash run command to ram*/
512     copy_flash_run_command(config);
513 
514     /* copy flash common bit operation command to ram*/
515     copy_flash_common_bit_operation(config);
516     flashExecuteInRamFunctionInfo->activeFunctionCount = kFLASH_ExecuteInRamFunctionTotalNum;
517 
518     return kStatus_FLASH_Success;
519 }
520 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
521 
522 /*!
523  * brief Erases entire flash
524  *
525  * param config Pointer to the storage for the driver runtime state.
526  * param key A value used to validate all flash erase APIs.
527  *
528  * retval #kStatus_FLASH_Success API was executed successfully.
529  * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
530  * retval #kStatus_FLASH_EraseKeyError API erase key is invalid.
531  * retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is
532  * not available.
533  * retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds
534  * addresses.
535  * retval #kStatus_FLASH_ProtectionViolation The program/erase operation is
536  * requested to execute on protected areas.
537  * retval #kStatus_FLASH_CommandFailure Run-time error during command execution.
538  * retval #kStatus_FLASH_EepromSingleBitFault EEPROM single bit fault error
539  * code.
540  * retval #kStatus_FLASH_EepromDoubleBitFault EEPROM double bit fault error
541  * code.
542  */
FLASH_EraseAll(flash_config_t * config,uint32_t key)543 status_t FLASH_EraseAll(flash_config_t *config, uint32_t key)
544 {
545     status_t returnCode;
546 
547     if (config == NULL)
548     {
549         return kStatus_FLASH_InvalidArgument;
550     }
551 
552     /* preparing passing parameter to erase all flash & EEPROM blocks */
553     FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
554 
555     /* Write index to specify the command code to be loaded */
556     flash_set_command(0UL, 0UL, FTMRx_ERASE_ALL_BLOCK);
557 
558     /* Validate the user key */
559     returnCode = flash_check_user_key(key);
560     if (returnCode != kStatus_FLASH_Success)
561     {
562         return returnCode;
563     }
564 
565     flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
566 
567     /* calling flash command sequence function to execute the command */
568     returnCode = flash_command_sequence(config);
569 
570     flash_cache_clear(config);
571 
572     return returnCode;
573 }
574 
575 /*!
576  * brief Erases the flash sectors encompassed by parameters passed into
577  * function.
578  *
579  * This function erases the appropriate number of flash sectors based on the
580  * desired start address and length.
581  *
582  * param config The pointer to the storage for the driver runtime state.
583  * param start The start address of the desired flash memory to be erased.
584  *              The start address does not need to be sector-aligned but must be
585  * word-aligned.
586  * param lengthInBytes The length, given in bytes (not words or long-words)
587  *                      to be erased. Must be word-aligned.
588  * param key The value used to validate all flash erase APIs.
589  *
590  * retval #kStatus_FLASH_Success API was executed successfully.
591  * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
592  * retval #kStatus_FLASH_AlignmentError The parameter is not aligned with the
593  * specified baseline.
594  * retval #kStatus_FLASH_AddressError The address is out of range.
595  * retval #kStatus_FLASH_EraseKeyError The API erase key is invalid.
596  * retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is
597  * not available.
598  * retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds
599  * addresses.
600  * retval #kStatus_FLASH_ProtectionViolation The program/erase operation is
601  * requested to execute on protected areas.
602  * retval #kStatus_FLASH_CommandFailure Run-time error during the command
603  * execution.
604  */
FLASH_Erase(flash_config_t * config,uint32_t start,uint32_t lengthInBytes,uint32_t key)605 status_t FLASH_Erase(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, uint32_t key)
606 {
607     uint32_t sectorSize;
608     flash_operation_config_t flashOperationInfo;
609     uint32_t endAddress;      /* storing end address */
610     uint32_t numberOfSectors; /* number of sectors calculated by endAddress */
611     status_t returnCode;
612 
613     returnCode = flash_get_matched_operation_info(config, start, &flashOperationInfo);
614     if (returnCode != kStatus_FLASH_Success)
615     {
616         return returnCode;
617     }
618 
619     /* Check the supplied address range. */
620     returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.sectorCmdAddressAligment);
621     if (returnCode != kStatus_FLASH_Success)
622     {
623         return returnCode;
624     }
625     /* Validate the user key */
626     returnCode = flash_check_user_key(key);
627     if (returnCode != kStatus_FLASH_Success)
628     {
629         return returnCode;
630     }
631 
632     start      = flashOperationInfo.convertedAddress;
633     sectorSize = flashOperationInfo.activeSectorSize;
634 
635     /* calculating Flash end address */
636     endAddress = start + lengthInBytes - 1U;
637 
638     /* re-calculate the endAddress and align it to the start of the next sector
639      * which will be used in the comparison below */
640     if (0U != (endAddress % sectorSize))
641     {
642         numberOfSectors = (endAddress / sectorSize) + 1UL;
643         endAddress      = (numberOfSectors * sectorSize) - 1UL;
644     }
645 
646     flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
647 
648     /* the start address will increment to the next sector address
649      * until it reaches the endAdddress */
650     while (start <= endAddress)
651     {
652         /* clear error flags */
653         FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
654         /* preparing passing parameter to erase a flash block */
655         /* Write index to specify the command code to be loaded */
656         flash_set_command(0UL, start >> 16UL, FTMRx_ERASE_SECTOR);
657 
658         /* Write index to specify the lower byte memory address bits[15:0] to be
659          * loaded */
660         flash_set_command(1UL, start, start >> 8UL);
661 
662         /* calling flash command sequence function to execute the command */
663         returnCode = flash_command_sequence(config);
664 
665         /* calling flash callback function if it is available */
666         if ((config->PFlashCallback) != NULL)
667         {
668             config->PFlashCallback();
669         }
670 
671         /* checking the success of command execution */
672         if (kStatus_FLASH_Success != returnCode)
673         {
674             break;
675         }
676         /* Increment to the next sector */
677         start += sectorSize;
678     }
679 
680     flash_cache_clear(config);
681 
682     return (returnCode);
683 }
684 
685 /*!
686  * brief Erases the eeprom sectors encompassed by parameters passed into
687  * function.
688  *
689  * This function erases the appropriate number of eeprom sectors based on the
690  * desired start address and length.
691  *
692  * param config The pointer to the storage for the driver runtime state.
693  * param start The start address of the desired eeprom memory to be erased.
694  *              The start address does not need to be sector-aligned but must be
695  * word-aligned.
696  * param lengthInBytes The length, given in bytes (not words or long-words)
697  *                      to be erased. Must be word-aligned.
698  * param key The value used to validate all eeprom erase APIs.
699  *
700  * retval #kStatus_FLASH_Success API was executed successfully.
701  * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
702  * retval #kStatus_FLASH_AlignmentError The parameter is not aligned with the
703  * specified baseline.
704  * retval #kStatus_FLASH_AddressError The address is out of range.
705  * retval #kStatus_FLASH_EraseKeyError The API erase key is invalid.
706  * retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is
707  * not available.
708  * retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds
709  * addresses.
710  * retval #kStatus_FLASH_ProtectionViolation The program/erase operation is
711  * requested to execute on protected areas.
712  * retval #kStatus_FLASH_CommandFailure Run-time error during the command
713  * execution.
714  */
715 #if defined(FLASH_SSD_IS_EEPROM_ENABLED) && FLASH_SSD_IS_EEPROM_ENABLED
FLASH_EraseEEprom(flash_config_t * config,uint32_t start,uint32_t lengthInBytes,uint32_t key)716 status_t FLASH_EraseEEprom(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, uint32_t key)
717 {
718     uint32_t sectorSize;
719     flash_operation_config_t flashOperationInfo;
720     uint32_t endAddress;      /* storing end address */
721     uint32_t numberOfSectors; /* number of sectors calculated by endAddress */
722     status_t returnCode;
723 
724     returnCode = flash_get_matched_operation_info(config, start, &flashOperationInfo);
725     if (returnCode != kStatus_FLASH_Success)
726     {
727         return returnCode;
728     }
729     /* Check the supplied address range. */
730     returnCode = EEPROM_check_range(config, start, lengthInBytes, config->EEpromSectorSize);
731     if (returnCode != kStatus_FLASH_Success)
732     {
733         return returnCode;
734     }
735     /* Validate the user key */
736     returnCode = flash_check_user_key(key);
737     if (returnCode != kStatus_FLASH_Success)
738     {
739         return returnCode;
740     }
741 
742     sectorSize = config->EEpromSectorSize;
743 
744     /* calculating Flash end address */
745     endAddress = start + lengthInBytes - 1UL;
746 
747     /* re-calculate the endAddress and align it to the start of the next sector
748      * which will be used in the comparison below */
749     if (0UL != (endAddress % sectorSize))
750     {
751         numberOfSectors = (endAddress / sectorSize) + 1UL;
752         endAddress      = (numberOfSectors * sectorSize) - 1UL;
753     }
754 
755     flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
756 
757     /* the start address will increment to the next sector address
758      * until it reaches the endAdddress */
759     while (start <= endAddress)
760     {
761         /* clear error flags */
762         FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
763         /* preparing passing parameter to erase a flash block */
764         /* Write index to specify the command code to be loaded */
765         flash_set_command(0UL, start >> 16UL, FTMRx_ERASE_EEPROM_SECTOR);
766 
767         /* Write index to specify the lower byte memory address bits[15:0] to be
768          * loaded */
769         flash_set_command(1UL, start, start >> 8UL);
770 
771         /* calling flash command sequence function to execute the command */
772         returnCode = flash_command_sequence(config);
773 
774         /* calling flash callback function if it is available */
775         if (config->PFlashCallback != NULL)
776         {
777             config->PFlashCallback();
778         }
779 
780         /* checking the success of command execution */
781         if (kStatus_FLASH_Success != returnCode)
782         {
783             break;
784         }
785         /* Increment to the next sector */
786         start += sectorSize;
787     }
788 
789     flash_cache_clear(config);
790 
791     return (returnCode);
792 }
793 #endif /* FLASH_SSD_IS_EEPROM_ENABLED */
794 
795 #if defined(FSL_FEATURE_FLASH_HAS_UNSECURE_FLASH_CMD) && FSL_FEATURE_FLASH_HAS_UNSECURE_FLASH_CMD
FLASH_EraseAllUnsecure(flash_config_t * config,uint32_t key)796 status_t FLASH_EraseAllUnsecure(flash_config_t *config, uint32_t key)
797 {
798     status_t returnCode;
799 
800     if (config == NULL)
801     {
802         return kStatus_FLASH_InvalidArgument;
803     }
804 
805     /* Prepare passing parameter to erase all flash blocks (unsecure). */
806     /* clear error flags */
807     FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
808 
809     /* Write index to specify the command code to be loaded */
810     flash_set_command(0UL, 0UL, FTMRx_ERASE_ALL_BLOCK_UNSECURE);
811 
812     /* Validate the user key */
813     returnCode = flash_check_user_key(key);
814     if (returnCode != kStatus_FLASH_Success)
815     {
816         return returnCode;
817     }
818 
819     flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
820 
821     /* calling flash command sequence function to execute the command */
822     returnCode = flash_command_sequence(config);
823 
824     flash_cache_clear(config);
825 
826     return returnCode;
827 }
828 #endif /* FSL_FEATURE_FLASH_HAS_UNSECURE_FLASH_CMD */
829 
830 /*!
831  * brief Programs flash with data at locations passed in through parameters.
832  *
833  * This function programs the flash memory with the desired data for a given
834  * flash area as determined by the start address and the length.
835  *
836  * param config A pointer to the storage for the driver runtime state.
837  * param start The start address of the desired flash memory to be programmed.
838  * Must be
839  *              word-aligned.
840  * param src A pointer to the source buffer of data that is to be programmed
841  *            into the flash.
842  * param lengthInBytes The length, given in bytes (not words or long-words),
843  *                      to be programmed. Must be word-aligned.
844  *
845  * retval #kStatus_FLASH_Success API was executed successfully.
846  * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
847  * retval #kStatus_FLASH_AlignmentError Parameter is not aligned with the
848  * specified baseline.
849  * retval #kStatus_FLASH_AddressError Address is out of range.
850  * retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is
851  * not available.
852  * retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds
853  * addresses.
854  * retval #kStatus_FLASH_ProtectionViolation The program/erase operation is
855  * requested to execute on protected areas.
856  * retval #kStatus_FLASH_CommandFailure Run-time error during the command
857  * execution.
858  */
FLASH_Program(flash_config_t * config,uint32_t start,uint32_t * src,uint32_t lengthInBytes)859 status_t FLASH_Program(flash_config_t *config, uint32_t start, uint32_t *src, uint32_t lengthInBytes)
860 {
861     status_t returnCode;
862     flash_operation_config_t flashOperationInfo;
863 
864     if (src == NULL)
865     {
866         return kStatus_FLASH_InvalidArgument;
867     }
868 
869     returnCode = flash_get_matched_operation_info(config, start, &flashOperationInfo);
870     if (returnCode != kStatus_FLASH_Success)
871     {
872         return returnCode;
873     }
874 
875     /* Check the supplied address range. */
876     returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.blockWriteUnitSize);
877     if (returnCode != kStatus_FLASH_Success)
878     {
879         return returnCode;
880     }
881 
882     flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
883 
884     while (lengthInBytes > 0UL)
885     {
886         /* pass paramters to FTMRx */
887         FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
888 
889         /* Write index to specify the command code to be loaded */
890         flash_set_command(0UL, start >> 16UL, FTMRx_PROGRAM);
891         flash_set_command(1UL, start, start >> 8UL);
892         /*Small endian by default.*/
893         /* Write index to specify the word0 (MSB word) to be programmed */
894         flash_set_command(2UL, *src, *src >> 8UL);
895 
896         /* Write index to specify the word1 (LSB word) to be programmed */
897         flash_set_command(3UL, *src >> 16UL, *src >> 24UL);
898         /* preparing passing parameter to program the flash block */
899 
900         if (4UL == flashOperationInfo.blockWriteUnitSize)
901         {
902             /* calling flash command sequence function to execute the command */
903             returnCode = flash_command_sequence(config);
904         }
905         else if (8UL == flashOperationInfo.blockWriteUnitSize)
906         {
907             src++;
908             /* Write index to specify the word (MSB word) to be programmed */
909             flash_set_command(4UL, *src, *src >> 8UL);
910             /* Write index to specify the word (LSB word) to be programmed */
911             flash_set_command(5UL, *src >> 16UL, *src >> 24UL);
912 
913             /* calling flash command sequence function to execute the command */
914             returnCode = flash_command_sequence(config);
915         }
916         else
917         {
918             /*"There's nothing to do here."*/
919         }
920         src++;
921         /* calling flash callback function if it is available */
922         if (config->PFlashCallback != NULL)
923         {
924             config->PFlashCallback();
925         }
926 
927         /* checking for the success of command execution */
928         if (kStatus_FLASH_Success != returnCode)
929         {
930             break;
931         }
932         else
933         {
934             /* update start address for next iteration */
935             start += flashOperationInfo.blockWriteUnitSize;
936 
937             /* update lengthInBytes for next iteration */
938             lengthInBytes -= flashOperationInfo.blockWriteUnitSize;
939         }
940     }
941 
942     flash_cache_clear(config);
943 
944     return (returnCode);
945 }
946 
947 /*!
948  * brief Programs Program Once Field through parameters.
949  *
950  * This function programs the Program Once Field with the desired data for a
951  * given
952  * flash area as determined by the index and length.
953  *
954  * param config A pointer to the storage for the driver runtime state.
955  * param index The index indicating which area of the Program Once Field to be
956  * programmed.
957  * param src A pointer to the source buffer of data that is to be programmed
958  *            into the Program Once Field.
959  * param lengthInBytes The length, given in bytes (not words or long-words),
960  *                      to be programmed. Must be word-aligned.
961  *
962  * retval #kStatus_FLASH_Success API was executed successfully.
963  * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
964  * retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is
965  * not available.
966  * retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds
967  * addresses.
968  * retval #kStatus_FLASH_ProtectionViolation The program/erase operation is
969  * requested to execute on protected areas.
970  * retval #kStatus_FLASH_CommandFailure Run-time error during the command
971  * execution.
972  */
FLASH_ProgramOnce(flash_config_t * config,uint32_t index,uint32_t * src,uint32_t lengthInBytes)973 status_t FLASH_ProgramOnce(flash_config_t *config, uint32_t index, uint32_t *src, uint32_t lengthInBytes)
974 {
975     status_t returnCode;
976 
977     if ((config == NULL) || (src == NULL))
978     {
979         return kStatus_FLASH_InvalidArgument;
980     }
981 
982     /* pass paramters to FTMRx */
983     FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
984 
985     /* Write index to specify the command code to be loaded. */
986     flash_set_command(0UL, 0UL, FTMRx_PROGRAM_ONCE);
987     flash_set_command(1UL, index, index >> 8UL);
988 
989     /* Write index to specify the word0 (MSB word) to be programmed. */
990     flash_set_command(2UL, *src, *src >> 8UL);
991 
992     /* Write index to specify the word1 (LSB word) to be programmed. */
993     flash_set_command(3UL, *src >> 16UL, *src >> 24UL);
994 
995 #if FLASH_PROGRAM_ONCE_IS_8BYTES_UNIT_SUPPORT
996 
997     /* Write index to specify the word2 (MSB word) to be programmed. */
998     flash_set_command(4UL, *(src + 1UL), *(src + 1UL) >> 8UL);
999 
1000     /* Write index to specify the word3 (LSB word) to be programmed. */
1001     flash_set_command(5UL, *(src + 1UL) >> 16UL, *(src + 1UL) >> 24UL);
1002 #endif
1003     flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
1004 
1005     /* calling flash command sequence function to execute the command */
1006     returnCode = flash_command_sequence(config);
1007 
1008     flash_cache_clear(config);
1009 
1010     return returnCode;
1011 }
1012 
1013 #if defined(FLASH_SSD_IS_EEPROM_ENABLED) && FLASH_SSD_IS_EEPROM_ENABLED
FLASH_EepromWrite(flash_config_t * config,uint32_t start,uint8_t * src,uint32_t lengthInBytes)1014 status_t FLASH_EepromWrite(flash_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes)
1015 {
1016     status_t returnCode;
1017     uint32_t i;
1018     if ((config == NULL) || (src == NULL))
1019     {
1020         return kStatus_FLASH_InvalidArgument;
1021     }
1022 
1023     /* Check the supplied address range. */
1024     /* Validates the range of the given address */
1025     if ((start < config->EEpromBlockBase) ||
1026         ((start + lengthInBytes) > (config->EEpromBlockBase + config->EEpromTotalSize)))
1027     {
1028         return kStatus_FLASH_AddressError;
1029     }
1030 
1031     returnCode = kStatus_FLASH_Success;
1032 
1033     flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
1034 
1035     while (lengthInBytes > 0UL)
1036     {
1037         /* pass paramters to FTMRx */
1038         FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
1039 
1040         if (lengthInBytes >= 4UL)
1041         {
1042             /* Write index to specify the command code to be loaded */
1043             flash_set_command(0UL, start >> 16UL, FTMRx_PROGRAM_EEPROM);
1044             flash_set_command(1UL, (start & 0x000000FFUL), start >> 8UL);
1045 
1046             for (i = 0UL; i < 4UL; i++)
1047             {
1048                 flash_set_command(0x02UL + i, *src++, 0UL);
1049             }
1050 
1051             /* calling flash command sequence function to execute the command */
1052             returnCode = flash_command_sequence(config);
1053 
1054             /* calling flash callback function if it is available */
1055             if (config->PFlashCallback != NULL)
1056             {
1057                 config->PFlashCallback();
1058             }
1059 
1060             /* checking for the success of command execution */
1061             if (returnCode != kStatus_FLASH_Success)
1062             {
1063                 break;
1064             }
1065             else
1066             {
1067                 /* update start address for next iteration */
1068                 start += 4UL;
1069                 /* update lengthInBytes for next iteration */
1070                 lengthInBytes -= 4UL;
1071             }
1072         }
1073         else if (lengthInBytes > 0UL)
1074         {
1075             /* Write index to specify the command code to be loaded */
1076             flash_set_command(0UL, start >> 16UL, FTMRx_PROGRAM_EEPROM);
1077             flash_set_command(1UL, (start & 0x000000FFUL), start >> 8UL);
1078 
1079             /* Write index to specify the byte (MSB word) to be programmed */
1080             for (i = 0UL; i < lengthInBytes; i++)
1081             {
1082                 flash_set_command(0x02UL + i, *src++, 0UL);
1083             }
1084             /* calling flash command sequence function to execute the command */
1085             returnCode    = flash_command_sequence(config);
1086             lengthInBytes = 0UL;
1087         }
1088         else
1089         {
1090             /*"There's nothing to do here."*/
1091         }
1092     }
1093     flash_cache_clear(config);
1094     return (returnCode);
1095 }
1096 #endif /* FLASH_SSD_IS_EEPROM_ENABLED */
1097 
1098 /*!
1099  * brief Reads the Program Once Field through parameters.
1100  *
1101  * This function reads the read once feild with given index and length.
1102  *
1103  * param config A pointer to the storage for the driver runtime state.
1104  * param index The index indicating the area of program once field to be read.
1105  * param dst A pointer to the destination buffer of data that is used to store
1106  *        data to be read.
1107  * param lengthInBytes The length, given in bytes (not words or long-words),
1108  *        to be programmed. Must be word-aligned.
1109  *
1110  * retval #kStatus_FLASH_Success API was executed successfully.
1111  * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
1112  * retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is
1113  * not available.
1114  * retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds
1115  * addresses.
1116  * retval #kStatus_FLASH_ProtectionViolation The program/erase operation is
1117  * requested to execute on protected areas.
1118  * retval #kStatus_FLASH_CommandFailure Run-time error during the command
1119  * execution.
1120  */
FLASH_ReadOnce(flash_config_t * config,uint32_t index,uint32_t * dst,uint32_t lengthInBytes)1121 status_t FLASH_ReadOnce(flash_config_t *config, uint32_t index, uint32_t *dst, uint32_t lengthInBytes)
1122 {
1123     uint32_t fccobloValue, fccobhiValue;
1124     status_t returnCode;
1125 
1126     if ((config == NULL) || (dst == NULL))
1127     {
1128         return kStatus_FLASH_InvalidArgument;
1129     }
1130 
1131     flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
1132     /* clear error flags */
1133     FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
1134 
1135     /* Write index to specify the command code to be loaded */
1136     flash_set_command(0UL, 0UL, FTMRx_READ_ONCE);
1137     flash_set_command(1UL, index, index >> 8UL);
1138 
1139     /* calling flash command sequence function to execute the command */
1140     returnCode = flash_command_sequence(config);
1141 
1142     if (kStatus_FLASH_Success == returnCode)
1143     {
1144         fccobloValue = FTMRx->FCCOBLO;
1145         fccobhiValue = FTMRx->FCCOBHI;
1146         /* Read lengthInBytes words. */
1147         FTMRx->FCCOBIX = FTMRx_FCCOBIX_CCOBIX(2UL);
1148         *dst           = (uint32_t)BYTES_JOIN_TO_WORD_1_1(fccobloValue, fccobhiValue);
1149         FTMRx->FCCOBIX = FTMRx_FCCOBIX_CCOBIX(3UL);
1150         *dst |= ((uint32_t)BYTES_JOIN_TO_WORD_1_1(fccobloValue, fccobhiValue)) << 16UL;
1151 #if FLASH_PROGRAM_ONCE_IS_8BYTES_UNIT_SUPPORT
1152         FTMRx->FCCOBIX = FTMRx_FCCOBIX_CCOBIX(4UL);
1153         *(dst + 1UL)   = (uint32_t)BYTES_JOIN_TO_WORD_1_1(fccobloValue, fccobhiValue);
1154         FTMRx->FCCOBIX = FTMRx_FCCOBIX_CCOBIX(5UL);
1155         *(dst + 1UL) |= ((uint32_t)BYTES_JOIN_TO_WORD_1_1(fccobloValue, fccobhiValue)) << 16UL;
1156 #endif
1157     }
1158     flash_cache_clear(config);
1159 
1160     return returnCode;
1161 }
1162 
1163 /*!
1164  * brief Returns the security state via the pointer passed into the function.
1165  *
1166  * This function retrieves the current flash security status, including the
1167  * security enabling state and the backdoor key enabling state.
1168  *
1169  * param config A pointer to storage for the driver runtime state.
1170  * param state A pointer to the value returned for the current security status
1171  * code:
1172  *
1173  * retval #kStatus_FLASH_Success API was executed successfully.
1174  * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
1175  */
FLASH_GetSecurityState(flash_config_t * config,flash_security_state_t * state)1176 status_t FLASH_GetSecurityState(flash_config_t *config, flash_security_state_t *state)
1177 {
1178     /* store data read from flash register */
1179     uint8_t registerValue;
1180 
1181     if ((config == NULL) || (state == NULL))
1182     {
1183         return kStatus_FLASH_InvalidArgument;
1184     }
1185 
1186     /* Get flash security register value */
1187     registerValue = FTMRx->FSEC;
1188 
1189     /* check the status of the flash security bits in the security register */
1190     if (FLASH_SECURITY_STATE_UNSECURED == (registerValue & FTMRx_FSEC_SEC_MASK))
1191     {
1192         /* Flash in unsecured state */
1193         *state = kFLASH_SecurityStateNotSecure;
1194     }
1195     else
1196     {
1197         /* Flash in secured state
1198          * check for backdoor key security enable bit */
1199         if (FLASH_SECURITY_STATE_KEYEN == (registerValue & FTMRx_FSEC_KEYEN_MASK))
1200         {
1201             /* Backdoor key security enabled */
1202             *state = kFLASH_SecurityStateBackdoorEnabled;
1203         }
1204         else
1205         {
1206             /* Backdoor key security disabled */
1207             *state = kFLASH_SecurityStateBackdoorDisabled;
1208         }
1209     }
1210 
1211     return (kStatus_FLASH_Success);
1212 }
1213 
1214 /*!
1215  * brief Allows users to bypass security with a backdoor key.
1216  *
1217  * If the MCU is in secured state, this function unsecures the MCU by
1218  * comparing the provided backdoor key with ones in the flash configuration
1219  * field.
1220  *
1221  * param config A pointer to the storage for the driver runtime state.
1222  * param backdoorKey A pointer to the user buffer containing the backdoor key.
1223  *
1224  * retval #kStatus_FLASH_Success API was executed successfully.
1225  * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
1226  * retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is
1227  * not available.
1228  * retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds
1229  * addresses.
1230  * retval #kStatus_FLASH_ProtectionViolation The program/erase operation is
1231  * requested to execute on protected areas.
1232  * retval #kStatus_FLASH_CommandFailure Run-time error during the command
1233  * execution.
1234  */
FLASH_SecurityBypass(flash_config_t * config,const uint8_t * backdoorKey)1235 status_t FLASH_SecurityBypass(flash_config_t *config, const uint8_t *backdoorKey)
1236 {
1237     uint8_t registerValue; /* registerValue */
1238     status_t returnCode;   /* return code variable */
1239     uint8_t tmpKey;
1240     uint32_t i;
1241 
1242     if ((config == NULL) || (backdoorKey == NULL))
1243     {
1244         return kStatus_FLASH_InvalidArgument;
1245     }
1246 
1247     /* set the default return code as kStatus_Success */
1248     returnCode = kStatus_FLASH_Success;
1249 
1250     /* Get flash security register value */
1251     registerValue = FTMRx->FSEC;
1252 
1253     /* Check to see if flash is in secure state (any state other than 0x2)
1254      * If not, then skip this since flash is not secure */
1255     if (0x02UL != (registerValue & 0x03UL))
1256     {
1257         /* clear error flags */
1258         FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
1259         /* preparing passing parameter to erase a flash block */
1260         /* Write index to specify the command code to be loaded */
1261         flash_set_command(0UL, 0UL, FTMRx_SECURITY_BY_PASS);
1262 
1263         for (i = 0UL; i < 4UL; i++)
1264         {
1265             tmpKey = *backdoorKey++;
1266             flash_set_command(i + 1UL, tmpKey, *backdoorKey++);
1267         }
1268 
1269         /* calling flash command sequence function to execute the command */
1270         returnCode = flash_command_sequence(config);
1271     }
1272 
1273     return (returnCode);
1274 }
1275 
1276 /*!
1277  * brief Verifies erasure of the entire flash at a specified margin level.
1278  *
1279  * This function checks whether the flash is erased to the
1280  * specified read margin level.
1281  *
1282  * param config A pointer to the storage for the driver runtime state.
1283  * param margin Read margin choice.
1284  *
1285  * retval #kStatus_FLASH_Success API was executed successfully.
1286  * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
1287  * retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is
1288  * not available.
1289  * retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds
1290  * addresses.
1291  * retval #kStatus_FLASH_ProtectionViolation The program/erase operation is
1292  * requested to execute on protected areas.
1293  * retval #kStatus_FLASH_CommandFailure Run-time error during the command
1294  * execution.
1295  * retval #kStatus_FLASH_EepromSingleBitFault EEPROM single bit fault error
1296  * code.
1297  * retval #kStatus_FLASH_EepromDoubleBitFault EEPROM double bit fault error
1298  * code.
1299  */
FLASH_VerifyEraseAll(flash_config_t * config,flash_margin_value_t margin)1300 status_t FLASH_VerifyEraseAll(flash_config_t *config, flash_margin_value_t margin)
1301 {
1302     status_t returnCode;
1303     if (config == NULL)
1304     {
1305         return kStatus_FLASH_InvalidArgument;
1306     }
1307     /* set the default return code as kStatus_Success */
1308     returnCode = kStatus_FLASH_Success;
1309 
1310     if ((uint32_t)margin != config->PFlashMarginLevel)
1311     {
1312         switch (margin)
1313         {
1314             case kFLASH_MarginValueUser:
1315                 returnCode = flash_setusermarginlevel(config, config->PFlashBlockBase, 0U, kFLASH_UserMarginValue1);
1316                 break;
1317             case kFLASH_MarginValueFactory:
1318                 returnCode =
1319                     flash_setfactorymarginlevel(config, config->PFlashBlockBase, 0U, kFLASH_FactoryMarginValue1);
1320                 break;
1321             case kFLASH_MarginValueNormal:
1322                 returnCode =
1323                     flash_setusermarginlevel(config, config->PFlashBlockBase, 0U, kFLASH_ReadMarginValueNormal);
1324                 break;
1325             default:
1326                 returnCode = kStatus_FLASH_InvalidArgument;
1327                 break;
1328         }
1329         config->PFlashMarginLevel = (uint32_t)margin;
1330     }
1331     if (returnCode != kStatus_FLASH_Success)
1332     {
1333         return returnCode;
1334     }
1335 #if FLASH_SSD_IS_EEPROM_ENABLED
1336     if ((uint32_t)margin != config->PFlashMarginLevel)
1337     {
1338         switch (margin)
1339         {
1340             case kFLASH_MarginValueUser:
1341                 returnCode = flash_setusermarginlevel(config, config->EEpromBlockBase, 1U, kFLASH_UserMarginValue1);
1342                 break;
1343             case kFLASH_MarginValueFactory:
1344                 returnCode =
1345                     flash_setfactorymarginlevel(config, config->EEpromBlockBase, 1U, kFLASH_FactoryMarginValue1);
1346                 break;
1347             case kFLASH_MarginValueNormal:
1348                 returnCode =
1349                     flash_setusermarginlevel(config, config->EEpromBlockBase, 1U, kFLASH_ReadMarginValueNormal);
1350                 break;
1351             default:
1352                 returnCode = kStatus_FLASH_InvalidArgument;
1353                 break;
1354         }
1355         config->PFlashMarginLevel = (uint32_t)margin;
1356     }
1357     if (returnCode != kStatus_FLASH_Success)
1358     {
1359         return returnCode;
1360     }
1361 #endif
1362 
1363     /* clear error flags */
1364     FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
1365 
1366     /* Erase verify all flash & EEPROM blocks */
1367     flash_set_command(0UL, 0UL, FTMRx_ERASE_VERIFY_ALL_BLOCK);
1368 
1369     returnCode = flash_command_sequence(config);
1370 
1371     return returnCode;
1372 }
1373 
1374 /*!
1375  * brief Verifies an erasure of the desired flash area at a specified margin
1376  * level.
1377  *
1378  * This function checks the appropriate number of flash sectors based on
1379  * the desired start address and length to check whether the flash is erased
1380  * to the specified read margin level.
1381  *
1382  * param config A pointer to the storage for the driver runtime state.
1383  * param margin Read margin choice.
1384  * param start The start address of the desired flash memory to be verified.
1385  *        The start address does not need to be sector-aligned but must be
1386  * word-aligned.
1387  * param lengthInBytes The length, given in bytes (not words or long-words),
1388  *        to be verified. Must be word-aligned.
1389  *
1390  * retval #kStatus_FLASH_Success API was executed successfully.
1391  * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
1392  * retval #kStatus_FLASH_AlignmentError Parameter is not aligned with specified
1393  * baseline.
1394  * retval #kStatus_FLASH_AddressError Address is out of range.
1395  * retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is
1396  * not available.
1397  * retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds
1398  * addresses.
1399  * retval #kStatus_FLASH_ProtectionViolation The program/erase operation is
1400  * requested to execute on protected areas.
1401  * retval #kStatus_FLASH_CommandFailure Run-time error during the command
1402  * execution.
1403  */
FLASH_VerifyErase(flash_config_t * config,uint32_t start,uint32_t lengthInBytes,flash_margin_value_t margin)1404 status_t FLASH_VerifyErase(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, flash_margin_value_t margin)
1405 {
1406     uint32_t blockSize;
1407     flash_operation_config_t flashOperationInfo;
1408     uint32_t nextBlockStartAddress;
1409     uint32_t remainingBytes;
1410     status_t returnCode;
1411 
1412     returnCode = flash_get_matched_operation_info(config, start, &flashOperationInfo);
1413     if (kStatus_FLASH_Success != returnCode)
1414     {
1415         return returnCode;
1416     }
1417 
1418     returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.sectionCmdAddressAligment);
1419     if (kStatus_FLASH_Success != returnCode)
1420     {
1421         return returnCode;
1422     }
1423 
1424     returnCode = flash_get_matched_operation_info(config, start, &flashOperationInfo);
1425     if (kStatus_FLASH_Success != returnCode)
1426     {
1427         return returnCode;
1428     }
1429     start     = flashOperationInfo.convertedAddress;
1430     blockSize = flashOperationInfo.activeBlockSize;
1431 
1432     nextBlockStartAddress = ALIGN_UP(start, blockSize);
1433     if (nextBlockStartAddress == start)
1434     {
1435         nextBlockStartAddress += blockSize;
1436     }
1437 
1438     remainingBytes = lengthInBytes;
1439 
1440     while (remainingBytes != 0UL)
1441     {
1442         uint32_t numberOfPhrases;
1443         uint32_t verifyLength = nextBlockStartAddress - start;
1444         if (verifyLength > remainingBytes)
1445         {
1446             verifyLength = remainingBytes;
1447         }
1448         numberOfPhrases = verifyLength >> flashOperationInfo.sectionCmdAddressAligment;
1449         if ((uint32_t)margin != config->PFlashMarginLevel)
1450         {
1451             switch (margin)
1452             {
1453                 case kFLASH_MarginValueUser:
1454                     returnCode = flash_setusermarginlevel(config, start, 0U, kFLASH_UserMarginValue1);
1455                     break;
1456                 case kFLASH_MarginValueFactory:
1457                     returnCode = flash_setfactorymarginlevel(config, start, 0U, kFLASH_FactoryMarginValue1);
1458                     break;
1459                 case kFLASH_MarginValueNormal:
1460                     returnCode = flash_setusermarginlevel(config, start, 0U, kFLASH_ReadMarginValueNormal);
1461                     break;
1462                 default:
1463                     returnCode = kStatus_FLASH_InvalidArgument;
1464                     break;
1465             }
1466             config->PFlashMarginLevel = (uint32_t)margin;
1467         }
1468         if (kStatus_FLASH_Success != returnCode)
1469         {
1470             return returnCode;
1471         }
1472         flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
1473         /* clear error flags */
1474         FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
1475 
1476         /* Fill in verify FLASH section command parameters. */
1477         flash_set_command(0UL, start >> 16UL, FTMRx_ERASE_VERIFY_SECTION);
1478         flash_set_command(1UL, start, start >> 8UL);
1479         /* Write index to specify the # of longwords to be verified */
1480         flash_set_command(2UL, numberOfPhrases, numberOfPhrases >> 8UL);
1481 
1482         /* calling flash command sequence function to execute the command */
1483         returnCode = flash_command_sequence(config);
1484         if (kStatus_FLASH_Success != returnCode)
1485         {
1486             return returnCode;
1487         }
1488 
1489         remainingBytes -= verifyLength;
1490         start += verifyLength;
1491         nextBlockStartAddress += blockSize;
1492     }
1493 
1494     return kStatus_FLASH_Success;
1495 }
1496 
1497 /*!
1498  * brief Returns the protection state of the desired flash area via the pointer
1499  * passed into the function.
1500  *
1501  * This function retrieves the current flash protect status for a given
1502  * flash area as determined by the start address and length.
1503  *
1504  * param config A pointer to the storage for the driver runtime state.
1505  * param start The start address of the desired flash memory to be checked. Must
1506  * be word-aligned.
1507  * param lengthInBytes The length, given in bytes (not words or long-words)
1508  *        to be checked.  Must be word-aligned.
1509  * param protection_state A pointer to the value returned for the current
1510  *        protection status code for the desired flash area.
1511  *
1512  * retval #kStatus_FLASH_Success API was executed successfully.
1513  * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
1514  * retval #kStatus_FLASH_AlignmentError Parameter is not aligned with specified
1515  * baseline.
1516  * retval #kStatus_FLASH_AddressError The address is out of range.
1517  */
FLASH_IsProtected(flash_config_t * config,uint32_t start,uint32_t lengthInBytes,flash_protection_state_t * protection_state)1518 status_t FLASH_IsProtected(flash_config_t *config,
1519                            uint32_t start,
1520                            uint32_t lengthInBytes,
1521                            flash_protection_state_t *protection_state)
1522 {
1523     flash_protection_config_t flashProtectionInfo; /* flash protection information */
1524     uint32_t endAddress;                           /* end address for protection check */
1525     status_t returnCode;
1526 
1527     if ((protection_state == NULL) || (lengthInBytes == 0UL))
1528     {
1529         return kStatus_FLASH_InvalidArgument;
1530     }
1531 
1532     /* Check the supplied address range. */
1533     returnCode = flash_check_range(config, start, lengthInBytes, FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE);
1534     if (returnCode != kStatus_FLASH_Success)
1535     {
1536         return returnCode;
1537     }
1538 
1539     /* Get necessary flash protection information. */
1540     returnCode = flash_get_protection_info(config, &flashProtectionInfo);
1541     if (returnCode != kStatus_FLASH_Success)
1542     {
1543         return returnCode;
1544     }
1545 
1546     /* calculating Flash end address */
1547     endAddress = start + lengthInBytes;
1548 
1549     if (((start >= flashProtectionInfo.lowRegionStart) && (endAddress <= flashProtectionInfo.lowRegionEnd)) ||
1550         ((start >= flashProtectionInfo.highRegionStart) && (endAddress <= flashProtectionInfo.highRegionEnd)))
1551     {
1552         *protection_state = kFLASH_ProtectionStateProtected;
1553     }
1554     else if (((start >= flashProtectionInfo.lowRegionEnd) && (endAddress <= flashProtectionInfo.highRegionStart)) ||
1555              (start >= flashProtectionInfo.highRegionEnd) || (endAddress <= flashProtectionInfo.lowRegionStart))
1556     {
1557         *protection_state = kFLASH_ProtectionStateUnprotected;
1558     }
1559     else
1560     {
1561         *protection_state = kFLASH_ProtectionStateMixed;
1562     }
1563 
1564     return kStatus_FLASH_Success;
1565 }
1566 
1567 /*!
1568  * brief Returns the desired flash property.
1569  *
1570  * param config A pointer to the storage for the driver runtime state.
1571  * param whichProperty The desired property from the list of properties in
1572  *        enum flash_property_tag_t
1573  * param value A pointer to the value returned for the desired flash property.
1574  *
1575  * retval #kStatus_FLASH_Success API was executed successfully.
1576  * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
1577  * retval #kStatus_FLASH_UnknownProperty An unknown property tag.
1578  */
FLASH_GetProperty(flash_config_t * config,flash_property_tag_t whichProperty,uint32_t * value)1579 status_t FLASH_GetProperty(flash_config_t *config, flash_property_tag_t whichProperty, uint32_t *value)
1580 {
1581     status_t status = kStatus_FLASH_UnknownProperty;
1582     if ((config == NULL) || (value == NULL))
1583     {
1584         return kStatus_FLASH_InvalidArgument;
1585     }
1586 
1587     switch (whichProperty)
1588     {
1589         case kFLASH_PropertyPflashSectorSize:
1590             *value = config->PFlashSectorSize;
1591             status = kStatus_FLASH_Success;
1592             break;
1593 
1594         case kFLASH_PropertyPflashTotalSize:
1595             *value = config->PFlashTotalSize;
1596             status = kStatus_FLASH_Success;
1597             break;
1598 
1599         case kFLASH_PropertyPflashBlockSize:
1600             *value = config->PFlashTotalSize / (uint32_t)config->PFlashBlockCount;
1601             status = kStatus_FLASH_Success;
1602             break;
1603 
1604         case kFLASH_PropertyPflashBlockCount:
1605             *value = (uint32_t)config->PFlashBlockCount;
1606             status = kStatus_FLASH_Success;
1607             break;
1608 
1609         case kFLASH_PropertyPflashBlockBaseAddr:
1610             *value = config->PFlashBlockBase;
1611             status = kStatus_FLASH_Success;
1612             break;
1613 
1614         case kFLASH_PropertyPflashFacSupport:
1615 #if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL)
1616             *value = FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL;
1617 #else
1618             *value = 0UL;
1619 #endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */
1620             status = kStatus_FLASH_Success;
1621             break;
1622 
1623         case kFLASH_PropertyFlashClockFrequency:
1624             *value = config->PFlashClockFreq;
1625             status = kStatus_FLASH_Success;
1626             break;
1627 
1628 #if FLASH_SSD_IS_EEPROM_ENABLED
1629         case kFLASH_PropertyEepromBlockBaseAddr:
1630             *value = config->EEpromBlockBase;
1631             status = kStatus_FLASH_Success;
1632             break;
1633 
1634         case kFLASH_PropertyEepromTotalSize:
1635             *value = config->EEpromTotalSize;
1636             status = kStatus_FLASH_Success;
1637             break;
1638 
1639         case kFLASH_PropertyEepromSectorSize:
1640             *value = (uint32_t)config->EEpromSectorSize;
1641             status = kStatus_FLASH_Success;
1642             break;
1643 
1644         case kFLASH_PropertyEepromBlockSize:
1645             *value = config->EEpromTotalSize / (uint32_t)config->EEpromBlockCount;
1646             status = kStatus_FLASH_Success;
1647             break;
1648 
1649         case kFLASH_PropertyEepromBlockCount:
1650             *value = (uint32_t)config->EEpromBlockCount;
1651             status = kStatus_FLASH_Success;
1652             break;
1653 #endif /* FLASH_SSD_IS_EEPROM_ENABLED */
1654 
1655         default: /* catch inputs that are not recognized */
1656             status = kStatus_FLASH_UnknownProperty;
1657             break;
1658     }
1659 
1660     return status;
1661 }
1662 
1663 /*!
1664  * brief Sets the desired flash property.
1665  *
1666  * param config A pointer to the storage for the driver runtime state.
1667  * param whichProperty The desired property from the list of properties in
1668  *        enum flash_property_tag_t
1669  * param value A to set for the desired flash property.
1670  *
1671  * retval #kStatus_FLASH_Success API was executed successfully.
1672  * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
1673  * retval #kStatus_FLASH_UnknownProperty An unknown property tag.
1674  * retval #kStatus_FLASH_InvalidPropertyValue An invalid property value.
1675  * retval #kStatus_FLASH_ReadOnlyProperty An read-only property tag.
1676  */
FLASH_SetProperty(flash_config_t * config,flash_property_tag_t whichProperty,uint32_t value)1677 status_t FLASH_SetProperty(flash_config_t *config, flash_property_tag_t whichProperty, uint32_t value)
1678 {
1679     status_t status = kStatus_FLASH_Success;
1680 
1681     if (config == NULL)
1682     {
1683         return kStatus_FLASH_InvalidArgument;
1684     }
1685 
1686     switch (whichProperty)
1687     {
1688 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED
1689         case kFLASH_PropertyFlashMemoryIndex:
1690             if ((value != (uint32_t)kFLASH_MemoryIndexPrimaryFlash) &&
1691                 (value != (uint32_t)kFLASH_MemoryIndexSecondaryFlash))
1692             {
1693                 return kStatus_FLASH_InvalidPropertyValue;
1694             }
1695             config->FlashMemoryIndex = (uint8_t)value;
1696             break;
1697 #endif /* FLASH_SSD_IS_SECONDARY_FLASH_ENABLED */
1698 
1699         case kFLASH_PropertyFlashCacheControllerIndex:
1700             if ((value != (uint32_t)kFLASH_CacheControllerIndexForCore0) &&
1701                 (value != (uint32_t)kFLASH_CacheControllerIndexForCore1))
1702             {
1703                 return kStatus_FLASH_InvalidPropertyValue;
1704             }
1705             config->FlashCacheControllerIndex = (uint8_t)value;
1706             break;
1707         case kFLASH_PropertyFlashClockFrequency:
1708             config->PFlashClockFreq = value;
1709             break;
1710         case kFLASH_PropertyPflashSectorSize:
1711         case kFLASH_PropertyPflashTotalSize:
1712         case kFLASH_PropertyPflashBlockSize:
1713         case kFLASH_PropertyPflashBlockCount:
1714         case kFLASH_PropertyPflashBlockBaseAddr:
1715         case kFLASH_PropertyPflashFacSupport:
1716 #if FLASH_SSD_IS_EEPROM_ENABLED
1717         case kFLASH_PropertyEepromBlockBaseAddr:
1718         case kFLASH_PropertyEepromTotalSize:
1719         case kFLASH_PropertyEepromSectorSize:
1720         case kFLASH_PropertyEepromBlockSize:
1721         case kFLASH_PropertyEepromBlockCount:
1722 #endif /* FLASH_SSD_IS_EEPROM_ENABLED */
1723             status = kStatus_FLASH_ReadOnlyProperty;
1724             break;
1725         default: /* catch inputs that are not recognized */
1726             status = kStatus_FLASH_UnknownProperty;
1727             break;
1728     }
1729 
1730     return status;
1731 }
1732 
1733 /*!
1734  * brief Sets the PFlash Protection to the intended protection status.
1735  *
1736  * param config A pointer to storage for the driver runtime state.
1737  * param protectStatus The expected protect status to set to the PFlash
1738  * protection register.
1739  *
1740  * retval #kStatus_FLASH_Success API was executed successfully.
1741  * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
1742  * retval #kStatus_FLASH_CommandFailure Run-time error during command execution.
1743  */
FLASH_PflashSetProtection(flash_config_t * config,pflash_protection_status_t * protectStatus)1744 status_t FLASH_PflashSetProtection(flash_config_t *config, pflash_protection_status_t *protectStatus)
1745 {
1746     if (config == NULL)
1747     {
1748         return kStatus_FLASH_InvalidArgument;
1749     }
1750     /* The reserved bit6 value of FPROT is reset value, which cannot change.
1751      * If flash memory is only 8KB, the bit3 to bit5 of FPROT are also reserved.*/
1752     FTMRx->FPROT = protectStatus->fprotvalue;
1753     if (protectStatus->fprotvalue != FTMRx->FPROT)
1754     {
1755         return kStatus_FLASH_CommandFailure;
1756     }
1757 
1758     return kStatus_FLASH_Success;
1759 }
1760 
1761 /*!
1762  * brief Gets the PFlash protection status.
1763  *
1764  * param config A pointer to the storage for the driver runtime state.
1765  * param protectStatus  Protect status returned by the PFlash IP.
1766  *
1767  * retval #kStatus_FLASH_Success API was executed successfully.
1768  * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
1769  */
FLASH_PflashGetProtection(flash_config_t * config,pflash_protection_status_t * protectStatus)1770 status_t FLASH_PflashGetProtection(flash_config_t *config, pflash_protection_status_t *protectStatus)
1771 {
1772     if ((config == NULL) || (protectStatus == NULL))
1773     {
1774         return kStatus_FLASH_InvalidArgument;
1775     }
1776 
1777     protectStatus->fprotvalue = FTMRx->FPROT;
1778 
1779     return kStatus_FLASH_Success;
1780 }
1781 
1782 #if defined(FLASH_SSD_IS_EEPROM_ENABLED) && FLASH_SSD_IS_EEPROM_ENABLED
FLASH_EepromSetProtection(flash_config_t * config,uint8_t protectStatus)1783 status_t FLASH_EepromSetProtection(flash_config_t *config, uint8_t protectStatus)
1784 {
1785     if (config == NULL)
1786     {
1787         return kStatus_FLASH_InvalidArgument;
1788     }
1789 
1790     if ((config->EEpromTotalSize == 0UL) || (config->EEpromTotalSize == NVM_EEPROM_SIZE_FOR_EEESIZE_RESERVED))
1791     {
1792         return kStatus_FLASH_CommandNotSupported;
1793     }
1794 
1795     FTMRx->EEPROT = protectStatus;
1796 
1797     if (FTMRx->EEPROT != protectStatus)
1798     {
1799         return kStatus_FLASH_CommandFailure;
1800     }
1801 
1802     return kStatus_FLASH_Success;
1803 }
1804 #endif /* FLASH_SSD_IS_EEPROM_ENABLED */
1805 
1806 #if defined(FLASH_SSD_IS_EEPROM_ENABLED) && FLASH_SSD_IS_EEPROM_ENABLED
FLASH_EepromGetProtection(flash_config_t * config,uint8_t * protectStatus)1807 status_t FLASH_EepromGetProtection(flash_config_t *config, uint8_t *protectStatus)
1808 {
1809     if ((config == NULL) || (protectStatus == NULL))
1810     {
1811         return kStatus_FLASH_InvalidArgument;
1812     }
1813 
1814     if ((config->EEpromTotalSize == 0UL) || (config->EEpromTotalSize == NVM_EEPROM_SIZE_FOR_EEESIZE_RESERVED))
1815     {
1816         return kStatus_FLASH_CommandNotSupported;
1817     }
1818 
1819     *protectStatus = FTMRx->EEPROT;
1820 
1821     return kStatus_FLASH_Success;
1822 }
1823 #endif /* FLASH_SSD_IS_EEPROM_ENABLED */
1824 
1825 /*!
1826  * brief Sets the PFlash prefetch speculation to the intended speculation
1827  * status.
1828  *
1829  * param speculationStatus The expected protect status to set to the PFlash
1830  * protection register. Each bit is
1831  * retval #kStatus_FLASH_Success API was executed successfully.
1832  * retval #kStatus_FLASH_InvalidSpeculationOption An invalid speculation option
1833  * argument is provided.
1834  */
FLASH_PflashSetPrefetchSpeculation(flash_prefetch_speculation_status_t * speculationStatus)1835 status_t FLASH_PflashSetPrefetchSpeculation(flash_prefetch_speculation_status_t *speculationStatus)
1836 {
1837 #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM
1838     {
1839         FTMRx_REG32_ACCESS_TYPE regBase;
1840 #if defined(MCM)
1841         regBase = (FTMRx_REG32_ACCESS_TYPE)&MCM->PLACR;
1842 #elif defined(MCM0)
1843         regBase = (FTMRx_REG32_ACCESS_TYPE)&MCM0->PLACR;
1844 #endif
1845         if (speculationStatus->instructionOption == kFLASH_prefetchSpeculationOptionDisable)
1846         {
1847             if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable)
1848             {
1849                 return kStatus_FLASH_InvalidSpeculationOption;
1850             }
1851             else
1852             {
1853                 *regBase |= MCM_PLACR_DFCS_MASK;
1854             }
1855         }
1856         else
1857         {
1858             *regBase &= ~MCM_PLACR_DFCS_MASK;
1859             if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable)
1860             {
1861                 *regBase |= MCM_PLACR_EFDS_MASK;
1862             }
1863             else
1864             {
1865                 *regBase &= ~MCM_PLACR_EFDS_MASK;
1866             }
1867         }
1868     }
1869 #elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC
1870     {
1871         FTMRx_REG32_ACCESS_TYPE regBase;
1872         uint32_t b0dpeMask, b0ipeMask;
1873 #if defined(FMC_PFB01CR_B0DPE_MASK)
1874         regBase = (FTMRx_REG32_ACCESS_TYPE)&FMC->PFB01CR;
1875         b0dpeMask = FMC_PFB01CR_B0DPE_MASK;
1876         b0ipeMask = FMC_PFB01CR_B0IPE_MASK;
1877 #elif defined(FMC_PFB0CR_B0DPE_MASK)
1878         regBase   = (FTMRx_REG32_ACCESS_TYPE)&FMC->PFB0CR;
1879         b0dpeMask = FMC_PFB0CR_B0DPE_MASK;
1880         b0ipeMask = FMC_PFB0CR_B0IPE_MASK;
1881 #endif
1882         if (speculationStatus->instructionOption == kFLASH_prefetchSpeculationOptionEnable)
1883         {
1884             *regBase |= b0ipeMask;
1885         }
1886         else
1887         {
1888             *regBase &= ~b0ipeMask;
1889         }
1890         if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable)
1891         {
1892             *regBase |= b0dpeMask;
1893         }
1894         else
1895         {
1896             *regBase &= ~b0dpeMask;
1897         }
1898 
1899 /* Invalidate Prefetch Speculation Buffer */
1900 #if defined(FMC_PFB01CR_S_INV_MASK)
1901         FMC->PFB01CR |= FMC_PFB01CR_S_INV_MASK;
1902 #elif defined(FMC_PFB01CR_S_B_INV_MASK)
1903         FMC->PFB01CR |= FMC_PFB01CR_S_B_INV_MASK;
1904 #elif defined(FMC_PFB0CR_S_INV_MASK)
1905         FMC->PFB0CR |= FMC_PFB0CR_S_INV_MASK;
1906 #elif defined(FMC_PFB0CR_S_B_INV_MASK)
1907         FMC->PFB0CR |= FMC_PFB0CR_S_B_INV_MASK;
1908 #endif
1909     }
1910 #endif /* FSL_FEATURE_FTMRx_MCM_FLASH_CACHE_CONTROLS */
1911 
1912     return kStatus_FLASH_Success;
1913 }
1914 
1915 /*!
1916  * brief Gets the PFlash prefetch speculation status.
1917  *
1918  * param speculationStatus  Speculation status returned by the PFlash IP.
1919  * retval #kStatus_FLASH_Success API was executed successfully.
1920  */
FLASH_PflashGetPrefetchSpeculation(flash_prefetch_speculation_status_t * speculationStatus)1921 status_t FLASH_PflashGetPrefetchSpeculation(flash_prefetch_speculation_status_t *speculationStatus)
1922 {
1923     (void)memset(speculationStatus, 0, sizeof(flash_prefetch_speculation_status_t));
1924 
1925     /* Assuming that all speculation options are enabled. */
1926     speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionEnable;
1927     speculationStatus->dataOption        = kFLASH_prefetchSpeculationOptionEnable;
1928 
1929 #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM
1930     {
1931         uint32_t value;
1932 #if defined(MCM)
1933         value = MCM->PLACR;
1934 #elif defined(MCM0)
1935         value   = MCM0->PLACR;
1936 #endif
1937         if (0UL != (value & MCM_PLACR_DFCS_MASK))
1938         {
1939             /* Speculation buffer is off. */
1940             speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionDisable;
1941             speculationStatus->dataOption        = kFLASH_prefetchSpeculationOptionDisable;
1942         }
1943         else
1944         {
1945             /* Speculation buffer is on for instruction. */
1946             if (0UL == (value & MCM_PLACR_EFDS_MASK))
1947             {
1948                 /* Speculation buffer is off for data. */
1949                 speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable;
1950             }
1951         }
1952     }
1953 #elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC
1954     {
1955         uint32_t value;
1956         uint32_t b0dpeMask, b0ipeMask;
1957 #if defined(FMC_PFB01CR_B0DPE_MASK)
1958         value = FMC->PFB01CR;
1959         b0dpeMask = FMC_PFB01CR_B0DPE_MASK;
1960         b0ipeMask = FMC_PFB01CR_B0IPE_MASK;
1961 #elif defined(FMC_PFB0CR_B0DPE_MASK)
1962         value     = FMC->PFB0CR;
1963         b0dpeMask = FMC_PFB0CR_B0DPE_MASK;
1964         b0ipeMask = FMC_PFB0CR_B0IPE_MASK;
1965 #endif
1966         if (0UL == (value & b0dpeMask))
1967         {
1968             /* Do not prefetch in response to data references. */
1969             speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable;
1970         }
1971         if (0UL == (value & b0ipeMask))
1972         {
1973             /* Do not prefetch in response to instruction fetches. */
1974             speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionDisable;
1975         }
1976     }
1977 #endif
1978 
1979     return kStatus_FLASH_Success;
1980 }
1981 
1982 #if FLASH_DRIVER_IS_FLASH_RESIDENT
1983 /*!
1984  * @brief Copy PIC of flash_run_command() to RAM
1985  */
copy_flash_run_command(flash_config_t * config)1986 static void copy_flash_run_command(flash_config_t *config)
1987 {
1988     assert(sizeof(s_flashRunCommandFunctionCode) <= ((uint32_t)kFLASH_ExecuteInRamFunctionMaxSizeInWords * 4U));
1989 
1990     uint32_t flashRunCommand = config->executeInRamFunction.runCmdFuncAddr.commadAddr;
1991 
1992     /* copy required flash command to RAM */
1993     (void)memcpy((uint8_t *)flashRunCommand, (const uint8_t *)s_flashRunCommandFunctionCode,
1994                  sizeof(s_flashRunCommandFunctionCode));
1995 }
1996 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
1997 
1998 /*!
1999  * @brief Flash Set Command
2000  *
2001  * This function is used to write the command sequence to the flash reg.
2002  */
flash_set_command(uint32_t index,uint32_t fValue,uint32_t sValue)2003 void flash_set_command(uint32_t index, uint32_t fValue, uint32_t sValue)
2004 {
2005     FTMRx->FCCOBIX = FTMRx_FCCOBIX_CCOBIX(index);
2006     FTMRx->FCCOBLO = FTMRx_FCCOBLO_CCOB(fValue);
2007     FTMRx->FCCOBHI = FTMRx_FCCOBHI_CCOB(sValue);
2008 }
2009 
2010 /*!
2011  * @brief Flash Command Sequence
2012  *
2013  * This function is used to perform the command write sequence to the flash.
2014  *
2015  * @param driver Pointer to storage for the driver runtime state.
2016  * @return An error code or kStatus_FLASH_Success
2017  */
flash_command_sequence(flash_config_t * config)2018 static status_t flash_command_sequence(flash_config_t *config)
2019 {
2020     uint8_t registerValue;
2021 
2022 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2023     /* clear ACCERR & FPVIOL flag in flash status register */
2024     FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
2025 
2026     status_t returnCode = flash_check_execute_in_ram_function_info(config);
2027     if (kStatus_FLASH_Success != returnCode)
2028     {
2029         return returnCode;
2030     }
2031 
2032     /* Since the value of ARM function pointer is always odd, but the real start address
2033      * of function memory should be even, that's why +1 operation exist. */
2034     config->executeInRamFunction.runCmdFuncAddr.commadAddr += 1UL;
2035     callFlashRunCommand = config->executeInRamFunction.runCmdFuncAddr.callFlashCommand;
2036 
2037     /* We pass the FTMRx_fstat address as a parameter to flash_run_comamnd()
2038      * instead of using
2039      * pre-processed MICRO sentences or operating global variable in
2040      * flash_run_comamnd()
2041      * to make sure that flash_run_command() will be compiled into
2042      * position-independent code (PIC). */
2043     callFlashRunCommand((FTMRx_REG8_ACCESS_TYPE)(&FTMRx->FSTAT));
2044     config->executeInRamFunction.runCmdFuncAddr.commadAddr -= 1UL;
2045 #else
2046 #if FLASH_ENABLE_STALLING_FLASH_CONTROLLER
2047     MCM->PLACR |= MCM_PLACR_ESFC_MASK; /* enable stalling flash controller when
2048                                           flash is busy */
2049 #endif
2050     /* clear ACCERR & FPVIOL flag in flash status register */
2051     FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
2052     /* clear CCIF bit */
2053     FTMRx->FSTAT = FTMRx_FSTAT_CCIF_MASK;
2054     /* Check CCIF bit of the flash status register, wait till it is set.
2055      * IP team indicates that this loop will always complete. */
2056     while (!(FTMRx->FSTAT & FTMRx_FSTAT_CCIF_MASK))
2057         ;
2058     {
2059     }
2060 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
2061     /* Check error bits */
2062     /* Get flash status register value */
2063     registerValue = FTMRx->FSTAT;
2064     /* checking access error */
2065     if (0U != (registerValue & FTMRx_FSTAT_ACCERR_MASK))
2066     {
2067         return kStatus_FLASH_AccessError;
2068     }
2069     /* checking protection error */
2070     if (0U != (registerValue & FTMRx_FSTAT_FPVIOL_MASK))
2071     {
2072         return kStatus_FLASH_ProtectionViolation;
2073     }
2074     /* checking MGSTAT non-correctable error */
2075     if (0U != (registerValue & FTMRx_FSTAT_MGSTAT_MASK))
2076     {
2077         return kStatus_FLASH_CommandFailure;
2078     }
2079 
2080 #if FLASH_SSD_IS_EEPROM_ENABLED
2081     registerValue = FTMRx->FERSTAT;
2082 
2083     if (0U != (registerValue & (FTMRx_FERSTAT_SFDIF_MASK)))
2084     {
2085         return kStatus_FLASH_EepromDoubleBitFault;
2086     }
2087     if (0U != (registerValue & (FTMRx_FERSTAT_DFDIF_MASK)))
2088     {
2089         return kStatus_FLASH_EepromSingleBitFault;
2090     }
2091 #endif
2092     return kStatus_FLASH_Success;
2093 }
2094 
2095 /*!
2096  * @brief Flash common bit operation sequence Command Sequence
2097  */
2098 #if FLASH_DRIVER_IS_FLASH_RESIDENT
flash_common_bit_operation_command_sequence(flash_config_t * config,FTMRx_REG32_ACCESS_TYPE base,uint32_t bitMask,uint32_t bitShift,uint32_t bitValue)2099 static void flash_common_bit_operation_command_sequence(
2100     flash_config_t *config, FTMRx_REG32_ACCESS_TYPE base, uint32_t bitMask, uint32_t bitShift, uint32_t bitValue)
2101 {
2102     uint32_t *flashCommonBitOperationAddr;
2103     flashCommonBitOperationAddr = &config->executeInRamFunction.CommonBitOperationAddr.bitOperationAddr;
2104     /* Since the value of ARM function pointer is always odd, but the real start
2105      * address
2106      * of function memory should be even, that's why +1 operation exist. */
2107     *flashCommonBitOperationAddr += 1UL;
2108     callFlashCommonBitOperation = config->executeInRamFunction.CommonBitOperationAddr.callCommonBitOperationCommand;
2109     /* Workround for some devices which doesn't need this function */
2110     callFlashCommonBitOperation((FTMRx_REG32_ACCESS_TYPE)base, bitMask, bitShift, bitValue);
2111     *flashCommonBitOperationAddr -= 1UL;
2112 }
2113 #endif /*FLASH_DRIVER_IS_FLASH_RESIDENT*/
2114 
2115 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2116 /*!
2117  * @brief Copy PIC of flash_common_bit_operation() to RAM
2118  *
2119  */
copy_flash_common_bit_operation(flash_config_t * config)2120 static void copy_flash_common_bit_operation(flash_config_t *config)
2121 {
2122     assert(sizeof(s_flashCommonBitOperationFunctionCode) <=
2123            ((uint32_t)kFLASH_ExecuteInRamFunctionMaxSizeInWords * 4UL));
2124 
2125     uint32_t *flashCommonBitOperationAddr;
2126     flashCommonBitOperationAddr = &config->executeInRamFunction.CommonBitOperationAddr.bitOperationAddr;
2127     /* Since the value of ARM function pointer is always odd, but the real start
2128      * address
2129      * of function memory should be even, that's why +1 operation exist. */
2130     (void)memcpy((uint8_t *)(*flashCommonBitOperationAddr), (const uint8_t *)s_flashCommonBitOperationFunctionCode,
2131                  sizeof(s_flashCommonBitOperationFunctionCode));
2132 }
2133 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
2134 
2135 #if FLASH_CACHE_IS_CONTROLLED_BY_MCM
2136 /*! @brief Performs the cache clear to the flash by MCM.*/
mcm_flash_cache_clear(flash_config_t * config)2137 void mcm_flash_cache_clear(flash_config_t *config)
2138 {
2139     FTMRx_REG32_ACCESS_TYPE regBase = (FTMRx_REG32_ACCESS_TYPE)&MCM0_CACHE_REG;
2140 
2141 #if defined(MCM0) && defined(MCM1)
2142     if (config->FlashCacheControllerIndex == (uint8_t)kFLASH_CacheControllerIndexForCore1)
2143     {
2144         regBase = (FTMRx_REG32_ACCESS_TYPE)&MCM1_CACHE_REG;
2145     }
2146 #endif
2147 
2148 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2149     flash_common_bit_operation_command_sequence(config, regBase, MCM_CACHE_CLEAR_MASK, MCM_CACHE_CLEAR_SHIFT, 1U);
2150 #else  /* !FLASH_DRIVER_IS_FLASH_RESIDENT */
2151     *regBase |= MCM_CACHE_CLEAR_MASK;
2152 
2153     /* Memory barriers for good measure.
2154      * All Cache, Branch predictor and TLB maintenance operations before this
2155      * instruction complete */
2156     __ISB();
2157     __DSB();
2158 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
2159 }
2160 #endif /* FLASH_CACHE_IS_CONTROLLED_BY_MCM */
2161 
2162 #if FLASH_CACHE_IS_CONTROLLED_BY_FMC
2163 /*! @brief Performs the cache clear to the flash by FMC.*/
fmc_flash_cache_clear(void)2164 void fmc_flash_cache_clear(void)
2165 {
2166 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2167     FTMRx_REG32_ACCESS_TYPE regBase = (FTMRx_REG32_ACCESS_TYPE)0;
2168 #if defined(FMC_PFB01CR_CINV_WAY_MASK)
2169     regBase = (FTMRx_REG32_ACCESS_TYPE)&FMC->PFB01CR;
2170     flash_common_bit_operation_command_sequence(config, regBase, FMC_PFB01CR_CINV_WAY_MASK, FMC_PFB01CR_CINV_WAY_SHIFT,
2171                                                 0xFUL);
2172 #else
2173     regBase = (FTMRx_REG32_ACCESS_TYPE)&FMC->PFB0CR;
2174     flash_common_bit_operation_command_sequence(config, regBase, FMC_PFB0CR_CINV_WAY_MASK, FMC_PFB0CR_CINV_WAY_SHIFT,
2175                                                 0xFUL);
2176 #endif
2177 #else /* !FLASH_DRIVER_IS_FLASH_RESIDENT */
2178 #if defined(FMC_PFB01CR_CINV_WAY_MASK)
2179     FMC->PFB01CR = (FMC->PFB01CR & ~FMC_PFB01CR_CINV_WAY_MASK) | FMC_PFB01CR_CINV_WAY(~0);
2180 #else
2181     FMC->PFB0CR = (FMC->PFB0CR & ~FMC_PFB0CR_CINV_WAY_MASK) | FMC_PFB0CR_CINV_WAY(~0);
2182 #endif
2183     /* Memory barriers for good measure.
2184      * All Cache, Branch predictor and TLB maintenance operations before this
2185      * instruction complete */
2186     __ISB();
2187     __DSB();
2188 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
2189 }
2190 #endif /* FLASH_CACHE_IS_CONTROLLED_BY_FMC */
2191 
2192 #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC
2193 /*! @brief Performs the prefetch speculation buffer clear to the flash by FMC.*/
fmc_flash_prefetch_speculation_clear(void)2194 void fmc_flash_prefetch_speculation_clear(void)
2195 {
2196 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2197     FTMRx_REG32_ACCESS_TYPE regBase = (FTMRx_REG32_ACCESS_TYPE)0UL;
2198 #if defined(FMC_PFB01CR_S_INV_MASK)
2199     regBase = (FTMRx_REG32_ACCESS_TYPE)&FMC->PFB01CR;
2200     flash_common_bit_operation_command_sequence(config, regBase, FMC_PFB01CR_S_INV_MASK, FMC_PFB01CR_S_INV_SHIFT, 1UL);
2201 #elif defined(FMC_PFB01CR_S_B_INV_MASK)
2202     regBase = (FTMRx_REG32_ACCESS_TYPE)&FMC->PFB01CR;
2203     flash_common_bit_operation_command_sequence(config, regBase, FMC_PFB01CR_S_B_INV_MASK, FMC_PFB01CR_S_B_INV_SHIFT,
2204                                                 1UL);
2205 #elif defined(FMC_PFB0CR_S_INV_MASK)
2206     regBase = (FTMRx_REG32_ACCESS_TYPE)&FMC->PFB0CR;
2207     flash_common_bit_operation_command_sequence(config, regBase, FMC_PFB0CR_S_INV_MASK, FMC_PFB0CR_S_INV_SHIFT, 1UL);
2208 #elif defined(FMC_PFB0CR_S_B_INV_MASK)
2209     regBase = (FTMRx_REG32_ACCESS_TYPE)&FMC->PFB0CR;
2210     flash_common_bit_operation_command_sequence(config, regBase, FMC_PFB0CR_S_B_INV_MASK, FMC_PFB0CR_S_B_INV_SHIFT,
2211                                                 1UL);
2212 #endif
2213 #else /* !FLASH_DRIVER_IS_FLASH_RESIDENT */
2214 #if defined(FMC_PFB01CR_S_INV_MASK)
2215     FMC->PFB01CR |= FMC_PFB01CR_S_INV_MASK;
2216 #elif defined(FMC_PFB01CR_S_B_INV_MASK)
2217     FMC->PFB01CR |= FMC_PFB01CR_S_B_INV_MASK;
2218 #elif defined(FMC_PFB0CR_S_INV_MASK)
2219     FMC->PFB0CR |= FMC_PFB0CR_S_INV_MASK;
2220 #elif defined(FMC_PFB0CR_S_B_INV_MASK)
2221     FMC->PFB0CR |= FMC_PFB0CR_S_B_INV_MASK;
2222 #endif
2223     /* Memory barriers for good measure.
2224      * All Cache, Branch predictor and TLB maintenance operations before this
2225      * instruction complete */
2226     __ISB();
2227     __DSB();
2228 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
2229 }
2230 #endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC */
2231 
2232 /*!
2233  * @brief Flash Cache Clear
2234  *
2235  * This function is used to perform the cache and prefetch speculation clear to
2236  * the flash.
2237  */
flash_cache_clear(flash_config_t * config)2238 void flash_cache_clear(flash_config_t *config)
2239 {
2240     flash_cache_clear_process(config, kFLASH_CacheClearProcessPost);
2241 }
2242 
2243 /*!
2244  * @brief Flash Cache Clear Process
2245  *
2246  * This function is used to perform the cache and prefetch speculation clear
2247  * process to the flash.
2248  */
flash_cache_clear_process(flash_config_t * config,flash_cache_clear_process_t process)2249 static void flash_cache_clear_process(flash_config_t *config, flash_cache_clear_process_t process)
2250 {
2251 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2252     status_t returnCode = flash_check_execute_in_ram_function_info(config);
2253     if (kStatus_FLASH_Success != returnCode)
2254     {
2255         return;
2256     }
2257 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
2258 
2259     /* We pass the FTMRx register address as a parameter to
2260      * flash_common_bit_operation() instead of using
2261      * pre-processed MACROs or a global variable in flash_common_bit_operation()
2262      * to make sure that flash_common_bit_operation() will be compiled into
2263      * position-independent code (PIC). */
2264     if (process == kFLASH_CacheClearProcessPost)
2265     {
2266 #if FLASH_CACHE_IS_CONTROLLED_BY_MCM
2267         mcm_flash_cache_clear(config);
2268 #endif
2269 #if FLASH_CACHE_IS_CONTROLLED_BY_FMC
2270         fmc_flash_cache_clear();
2271 #endif
2272 
2273 #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC
2274         fmc_flash_prefetch_speculation_clear();
2275 #endif
2276     }
2277     if (process == kFLASH_CacheClearProcessPre)
2278     {
2279     }
2280 }
2281 
2282 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2283 /*! @brief Check whether flash execute-in-ram functions are ready  */
flash_check_execute_in_ram_function_info(flash_config_t * config)2284 static status_t flash_check_execute_in_ram_function_info(flash_config_t *config)
2285 {
2286     flash_execute_in_ram_function_config_t *flashExecuteInRamFunctionInfo;
2287 
2288     if (config == NULL)
2289     {
2290         return kStatus_FLASH_InvalidArgument;
2291     }
2292 
2293     flashExecuteInRamFunctionInfo =
2294         (flash_execute_in_ram_function_config_t *)((void *)(config->flashExecuteInRamFunctionInfo));
2295 
2296     if ((config->flashExecuteInRamFunctionInfo != NULL) &&
2297         ((uint32_t)kFLASH_ExecuteInRamFunctionTotalNum == flashExecuteInRamFunctionInfo->activeFunctionCount))
2298     {
2299         return kStatus_FLASH_Success;
2300     }
2301 
2302     return kStatus_FLASH_ExecuteInRamFunctionNotReady;
2303 }
2304 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
2305 
2306 /*! @brief Validates the range and alignment of the given address range.*/
flash_check_range(flash_config_t * config,uint32_t startAddress,uint32_t lengthInBytes,uint32_t alignmentBaseline)2307 static status_t flash_check_range(flash_config_t *config,
2308                                   uint32_t startAddress,
2309                                   uint32_t lengthInBytes,
2310                                   uint32_t alignmentBaseline)
2311 {
2312     if (config == NULL)
2313     {
2314         return kStatus_FLASH_InvalidArgument;
2315     }
2316 
2317     /* Verify the start and length are alignmentBaseline aligned, Global address
2318      * [1:0] must be 00.*/
2319     if ((0UL != (startAddress & (alignmentBaseline - 1UL))) || (0UL != (lengthInBytes & (alignmentBaseline - 1UL))))
2320     {
2321         return kStatus_FLASH_AlignmentError;
2322     }
2323 
2324     /* check for valid range of the target addresses */
2325     if ((startAddress >= config->PFlashBlockBase) &&
2326         ((startAddress + lengthInBytes) <= (config->PFlashBlockBase + config->PFlashTotalSize)))
2327     {
2328         return kStatus_FLASH_Success;
2329     }
2330 
2331     return kStatus_FLASH_AddressError;
2332 }
2333 
2334 /*! @brief Validates the range and alignment of the given address range.*/
2335 #if FLASH_SSD_IS_EEPROM_ENABLED
EEPROM_check_range(flash_config_t * config,uint32_t startAddress,uint32_t lengthInBytes,uint32_t alignmentBaseline)2336 static status_t EEPROM_check_range(flash_config_t *config,
2337                                    uint32_t startAddress,
2338                                    uint32_t lengthInBytes,
2339                                    uint32_t alignmentBaseline)
2340 {
2341     if (config == NULL)
2342     {
2343         return kStatus_FLASH_InvalidArgument;
2344     }
2345 
2346     /* Verify the start and length are alignmentBaseline aligned, Global address
2347      * [1:0] must be 00.*/
2348     if ((0UL != (startAddress & (alignmentBaseline - 1UL))) || (0UL != (lengthInBytes & (alignmentBaseline - 1UL))))
2349     {
2350         return kStatus_FLASH_AlignmentError;
2351     }
2352 
2353     /* check for valid range of the target addresses */
2354     if ((startAddress >= config->EEpromBlockBase) &&
2355         ((startAddress + lengthInBytes) <= (config->EEpromBlockBase + config->EEpromTotalSize)))
2356     {
2357         return kStatus_FLASH_Success;
2358     }
2359 
2360     return kStatus_FLASH_AddressError;
2361 }
2362 #endif /* FLASH_SSD_IS_EEPROM_ENABLED */
2363 
2364 /*! @brief Gets the right address, sector and block size of current flash type
2365  * which is indicated by address.*/
flash_get_matched_operation_info(flash_config_t * config,uint32_t address,flash_operation_config_t * info)2366 static status_t flash_get_matched_operation_info(flash_config_t *config,
2367                                                  uint32_t address,
2368                                                  flash_operation_config_t *info)
2369 {
2370     if ((config == NULL) || (info == NULL))
2371     {
2372         return kStatus_FLASH_InvalidArgument;
2373     }
2374 
2375     /* Clean up info Structure*/
2376     (void)memset(info, 0, sizeof(flash_operation_config_t));
2377 
2378     info->convertedAddress = address - config->PFlashBlockBase;
2379     info->activeSectorSize = config->PFlashSectorSize;
2380     info->activeBlockSize  = config->PFlashTotalSize / config->PFlashBlockCount;
2381 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED
2382     if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash)
2383     {
2384 #if FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER || FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER
2385         /* When required by the command, address bit 23 selects between main flash
2386          * memory
2387          * (=0) and secondary flash memory (=1).*/
2388         info->convertedAddress += 0x800000UL;
2389 #endif
2390         info->blockWriteUnitSize = SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE;
2391     }
2392     else
2393 #endif /* FLASH_SSD_IS_SECONDARY_FLASH_ENABLED */
2394     {
2395         info->blockWriteUnitSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE;
2396     }
2397 
2398     info->sectorCmdAddressAligment  = FSL_FEATURE_FLASH_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT;
2399     info->sectionCmdAddressAligment = FSL_FEATURE_FLASH_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT;
2400     info->programCmdAddressAligment = FSL_FEATURE_FLASH_PFLASH_PROGRAM_CMD_ADDRESS_ALIGMENT;
2401 
2402     return kStatus_FLASH_Success;
2403 }
2404 
2405 /*! @brief Validates the given user key for flash erase APIs.*/
flash_check_user_key(uint32_t key)2406 static status_t flash_check_user_key(uint32_t key)
2407 {
2408     /* Validate the user key */
2409     if (key != (uint32_t)kFLASH_ApiEraseKey)
2410     {
2411         return kStatus_FLASH_EraseKeyError;
2412     }
2413 
2414     return kStatus_FLASH_Success;
2415 }
2416 
2417 /*! @brief Gets the flash protection information.*/
flash_get_protection_info(flash_config_t * config,flash_protection_config_t * info)2418 static status_t flash_get_protection_info(flash_config_t *config, flash_protection_config_t *info)
2419 {
2420     uint32_t pflashTotalSize, regionBase;
2421     uint32_t pflashProtectionValue, pflashFPLS;
2422 #if defined(FTMRx_FPROT_FPHDIS_MASK)
2423     uint32_t pflashFPHS;
2424 #endif
2425 
2426     if ((config == NULL) || (info == NULL))
2427     {
2428         return kStatus_FLASH_InvalidArgument;
2429     }
2430 
2431     /* Clean up info Structure*/
2432     (void)memset(info, 0, sizeof(flash_protection_config_t));
2433 
2434 /* Note: KW40 has a secondary flash, but it doesn't have independent protection
2435  * register*/
2436 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && (!FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER)
2437     pflashTotalSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE +
2438                       FSL_FEATURE_FLASH_PFLASH_1_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SIZE;
2439     regionBase = FSL_FEATURE_FLASH_PFLASH_START_ADDRESS;
2440 #else
2441     pflashTotalSize = config->PFlashTotalSize;
2442     regionBase = config->PFlashBlockBase;
2443 #endif
2444 
2445     /* Calculate the flash protection region */
2446     pflashProtectionValue = FTMRx->FPROT & 0xA4UL;
2447     pflashFPLS            = (FTMRx->FPROT & 0x03UL);
2448 #if defined(FTMRx_FPROT_FPHDIS_MASK)
2449     pflashFPHS = (FTMRx->FPROT & 0x18UL) >> 3UL;
2450 #endif
2451 
2452     switch (pflashProtectionValue)
2453     {
2454 #if defined(FTMRx_FPROT_FPHDIS_MASK)
2455         case 0xA4UL:
2456             /*!< All flash region is not protected.*/
2457             info->lowRegionStart  = regionBase;
2458             info->lowRegionEnd    = regionBase;
2459             info->highRegionStart = regionBase + pflashTotalSize;
2460             info->highRegionEnd   = regionBase + pflashTotalSize;
2461             break;
2462 #endif
2463         case 0x84UL:
2464             info->lowRegionStart = regionBase;
2465             info->lowRegionEnd   = regionBase;
2466 #if defined(FTMRx_FPROT_FPHDIS_MASK)
2467             /*!< Only flash high region is protected.*/
2468             info->highRegionStart =
2469                 (uint32_t)FSL_FEATURE_FLASH_PFLASH_HIGH_START_ADDRESS - ((1UL << pflashFPLS) << 10UL);
2470             info->highRegionEnd = FSL_FEATURE_FLASH_PFLASH_HIGH_START_ADDRESS;
2471 #else
2472             /*!< All flash region is not protected.*/
2473             info->highRegionStart = regionBase + pflashTotalSize;
2474             info->highRegionEnd = regionBase + pflashTotalSize;
2475 #endif
2476             break;
2477 #if defined(FTMRx_FPROT_FPHDIS_MASK)
2478         case 0xA0UL:
2479             /*!< Only flash low region is protected.*/
2480             info->lowRegionStart  = regionBase;
2481             info->lowRegionEnd    = regionBase + ((2UL << pflashFPLS) << 10UL);
2482             info->highRegionStart = regionBase + pflashTotalSize;
2483             info->highRegionEnd   = regionBase + pflashTotalSize;
2484             break;
2485 #endif
2486         case 0x80UL:
2487             info->lowRegionStart = regionBase;
2488 #if defined(FTMRx_FPROT_FPHDIS_MASK)
2489             /*!< Flash high and low region are protected.*/
2490             info->lowRegionEnd = regionBase + ((2UL << pflashFPLS) << 10UL);
2491             info->highRegionStart =
2492                 (uint32_t)FSL_FEATURE_FLASH_PFLASH_HIGH_START_ADDRESS - ((1UL << pflashFPLS) << 10UL);
2493             info->highRegionEnd = FSL_FEATURE_FLASH_PFLASH_HIGH_START_ADDRESS;
2494 #else
2495             /*!< Only flash low region is protected.*/
2496             info->lowRegionEnd = regionBase + ((1UL << pflashFPLS) << 10UL);
2497             info->highRegionStart = regionBase + pflashTotalSize;
2498             info->highRegionEnd = regionBase + pflashTotalSize;
2499 #endif
2500             break;
2501 #if defined(FTMRx_FPROT_FPHDIS_MASK)
2502         case 0x24UL:
2503             /*!< All Flash region is protected.*/
2504             info->lowRegionStart  = regionBase;
2505             info->lowRegionEnd    = regionBase + pflashTotalSize;
2506             info->highRegionStart = regionBase;
2507             info->highRegionEnd   = regionBase + pflashTotalSize;
2508             break;
2509 #endif
2510         case 0x04UL:
2511             info->lowRegionStart = regionBase;
2512 #if defined(FTMRx_FPROT_FPHDIS_MASK)
2513             /*!< Flash high region is not protected.*/
2514             info->lowRegionEnd = (uint32_t)FSL_FEATURE_FLASH_PFLASH_HIGH_START_ADDRESS - ((1UL << pflashFPHS) << 10UL);
2515             info->highRegionStart = FSL_FEATURE_FLASH_PFLASH_HIGH_START_ADDRESS;
2516 
2517 #else
2518             /*!< All Flash region is protected.*/
2519             info->lowRegionEnd = regionBase + pflashTotalSize;
2520             info->highRegionStart = regionBase;
2521 #endif
2522             info->highRegionEnd = regionBase + pflashTotalSize;
2523             break;
2524 #if defined(FTMRx_FPROT_FPHDIS_MASK)
2525         case 0x20UL:
2526             /*!< Flash low region is not protected.*/
2527             info->lowRegionStart  = regionBase + ((2UL << pflashFPLS) << 10UL);
2528             info->lowRegionEnd    = regionBase + pflashTotalSize;
2529             info->highRegionStart = regionBase + ((2UL << pflashFPLS) << 10UL);
2530             info->highRegionEnd   = regionBase + pflashTotalSize;
2531             break;
2532 #endif
2533         case 0x00UL:
2534 #if defined(FTMRx_FPROT_FPHDIS_MASK)
2535             /*!< Flash high and low region are not protected.*/
2536             info->lowRegionStart = regionBase + ((2UL << pflashFPLS) << 10UL);
2537             info->lowRegionEnd = (uint32_t)FSL_FEATURE_FLASH_PFLASH_HIGH_START_ADDRESS - ((1UL << pflashFPHS) << 10UL);
2538             info->highRegionStart = FSL_FEATURE_FLASH_PFLASH_HIGH_START_ADDRESS;
2539 #else
2540             /*!< Flash low region is not protected.*/
2541             info->lowRegionStart = regionBase;
2542             info->lowRegionEnd = regionBase;
2543             info->highRegionStart = regionBase + ((1UL << pflashFPLS) << 10UL);
2544 #endif
2545             info->highRegionEnd = regionBase + pflashTotalSize;
2546             break;
2547         default:
2548             /* Do Nothing*/
2549             break;
2550     }
2551 
2552     return kStatus_FLASH_Success;
2553 }
2554 
2555 /*! @brief Set the flash and eeprom to the specified user margin level.*/
flash_setusermarginlevel(flash_config_t * config,uint32_t start,uint8_t iseeprom,flash_user_margin_value_t margin)2556 status_t flash_setusermarginlevel(flash_config_t *config,
2557                                   uint32_t start,
2558                                   uint8_t iseeprom,
2559                                   flash_user_margin_value_t margin)
2560 {
2561     uint32_t marginValue;
2562     status_t returnCode;
2563     if (config == NULL)
2564     {
2565         return kStatus_FLASH_InvalidArgument;
2566     }
2567     marginValue = (uint32_t)margin;
2568     flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
2569 
2570     /* clear error flags */
2571     FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
2572 
2573     /* Write index to specify the command code to be loaded */
2574     flash_set_command(0UL, start >> 16UL, FTMRx_SET_USER_MARGIN_LEVEL);
2575 
2576     /* memory address bits[23:16] with bit23 = 0 for Flash block, 1 for EEPROM
2577      * block */
2578     if (0UL != iseeprom)
2579     {
2580         FTMRx->FCCOBLO |= FTMRx_FCCOBLO_CCOB(128UL);
2581     }
2582     flash_set_command(1UL, start, start >> 8UL);
2583 
2584     flash_set_command(2UL, marginValue, marginValue >> 8UL);
2585 
2586     /* calling flash command sequence function to execute the command */
2587     returnCode = flash_command_sequence(config);
2588 
2589     flash_cache_clear(config);
2590     return returnCode;
2591 }
2592 
2593 /*! @brief Set the flash and eeprom to the specified factory margin level.*/
flash_setfactorymarginlevel(flash_config_t * config,uint32_t start,uint8_t iseeprom,flash_factory_margin_value_t margin)2594 status_t flash_setfactorymarginlevel(flash_config_t *config,
2595                                      uint32_t start,
2596                                      uint8_t iseeprom,
2597                                      flash_factory_margin_value_t margin)
2598 {
2599     uint32_t marginValue;
2600     status_t returnCode;
2601     if (config == NULL)
2602     {
2603         return kStatus_FLASH_InvalidArgument;
2604     }
2605 
2606     marginValue = (uint32_t)margin;
2607     flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
2608     /* clear error flags */
2609     FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
2610 
2611     /* Write index to specify the command code to be loaded */
2612     flash_set_command(0UL, start >> 16UL, FTMRx_SET_FACTORY_MARGIN_LEVEL);
2613     /* memory address bits[23:16] with bit23 = 0 for Flash block, 1 for EEPROM
2614      * block */
2615     if (0UL != iseeprom)
2616     {
2617         FTMRx->FCCOBLO |= FTMRx_FCCOBLO_CCOB(128UL);
2618     }
2619     flash_set_command(1UL, start, start >> 8UL);
2620 
2621     flash_set_command(2UL, marginValue, marginValue >> 8UL);
2622 
2623     /* calling flash command sequence function to execute the command */
2624     returnCode = flash_command_sequence(config);
2625 
2626     flash_cache_clear(config);
2627     return returnCode;
2628 }
2629