1 /*
2  * Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  *
7  * SPDX-License-Identifier: BSD-3-Clause
8  */
9 
10 #include "fsl_flash.h"
11 
12 /*******************************************************************************
13  * Definitions
14  ******************************************************************************/
15 
16 /*!
17  * @name Misc utility defines
18  * @{
19  */
20 /*! @brief Alignment utility. */
21 #ifndef ALIGN_DOWN
22 #define ALIGN_DOWN(x, a) ((x) & (uint32_t)(-((int32_t)(a))))
23 #endif
24 #ifndef ALIGN_UP
25 #define ALIGN_UP(x, a) (-((int32_t)((uint32_t)(-((int32_t)(x))) & (uint32_t)(-((int32_t)(a))))))
26 #endif
27 
28 /*! @brief Join bytes to word utility. */
29 #define B1P4(b) (((uint32_t)(b)&0xFFU) << 24)
30 #define B1P3(b) (((uint32_t)(b)&0xFFU) << 16)
31 #define B1P2(b) (((uint32_t)(b)&0xFFU) << 8)
32 #define B1P1(b) ((uint32_t)(b)&0xFFU)
33 #define B2P3(b) (((uint32_t)(b)&0xFFFFU) << 16)
34 #define B2P2(b) (((uint32_t)(b)&0xFFFFU) << 8)
35 #define B2P1(b) ((uint32_t)(b)&0xFFFFU)
36 #define B3P2(b) (((uint32_t)(b)&0xFFFFFFU) << 8)
37 #define B3P1(b) ((uint32_t)(b)&0xFFFFFFU)
38 #define BYTES_JOIN_TO_WORD_1_3(x, y) (B1P4(x) | B3P1(y))
39 #define BYTES_JOIN_TO_WORD_2_2(x, y) (B2P3(x) | B2P1(y))
40 #define BYTES_JOIN_TO_WORD_3_1(x, y) (B3P2(x) | B1P1(y))
41 #define BYTES_JOIN_TO_WORD_1_1_2(x, y, z) (B1P4(x) | B1P3(y) | B2P1(z))
42 #define BYTES_JOIN_TO_WORD_1_2_1(x, y, z) (B1P4(x) | B2P2(y) | B1P1(z))
43 #define BYTES_JOIN_TO_WORD_2_1_1(x, y, z) (B2P3(x) | B1P2(y) | B1P1(z))
44 #define BYTES_JOIN_TO_WORD_1_1_1_1(x, y, z, w) (B1P4(x) | B1P3(y) | B1P2(z) | B1P1(w))
45 /*@}*/
46 
47 /*!
48  * @name Secondary flash configuration
49  * @{
50  */
51 /*! @brief Indicates whether the secondary flash has its own protection register in flash module. */
52 #if defined(FSL_FEATURE_FLASH_HAS_MULTIPLE_FLASH) && defined(FTFE_FPROTS_PROTS_MASK)
53 #define FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER (1)
54 #else
55 #define FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER (0)
56 #endif
57 
58 /*! @brief Indicates whether the secondary flash has its own Execute-Only access register in flash module. */
59 #if defined(FSL_FEATURE_FLASH_HAS_MULTIPLE_FLASH) && defined(FTFE_FACSSS_SGSIZE_S_MASK)
60 #define FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER (1)
61 #else
62 #define FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER (0)
63 #endif
64 /*@}*/
65 
66 /*!
67  * @name Dual core/flash configuration
68  * @{
69  */
70 /*! @brief Redefines some flash features. */
71 #if defined(FSL_FEATURE_FLASH_CURRENT_CORE_ID)
72 #if (FSL_FEATURE_FLASH_CURRENT_CORE_ID == 0u)
73 #define MAIN_FLASH_FEATURE_PFLASH_START_ADDRESS FSL_FEATURE_FLASH_PFLASH_START_ADDRESS
74 #define MAIN_FLASH_FEATURE_PFLASH_BLOCK_COUNT FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT
75 #define MAIN_FLASH_FEATURE_PFLASH_BLOCK_SIZE FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE
76 #define MAIN_FLASH_FEATURE_PFLASH_BLOCK_SECTOR_SIZE FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE
77 #define MAIN_FLASH_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE
78 #define MAIN_FLASH_FEATURE_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT
79 #define MAIN_FLASH_FEATURE_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT
80 #define MAIN_FLASH_FEATURE_PFLASH_PROTECTION_REGION_COUNT FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT
81 #define SECONDARY_FLASH_FEATURE_PFLASH_START_ADDRESS FSL_FEATURE_FLASH_PFLASH_1_START_ADDRESS
82 #define SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_COUNT FSL_FEATURE_FLASH_PFLASH_1_BLOCK_COUNT
83 #define SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_SIZE FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SIZE
84 #define SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_SECTOR_SIZE FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SECTOR_SIZE
85 #define SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE FSL_FEATURE_FLASH_PFLASH_1_BLOCK_WRITE_UNIT_SIZE
86 #define SECONDARY_FLASH_FEATURE_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_1_SECTOR_CMD_ADDRESS_ALIGMENT
87 #define SECONDARY_FLASH_FEATURE_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_1_SECTION_CMD_ADDRESS_ALIGMENT
88 #define SECONDARY_FLASH_FEATURE_PFLASH_PROTECTION_REGION_COUNT FSL_FEATURE_FLASH_PFLASH_1_PROTECTION_REGION_COUNT
89 #elif (FSL_FEATURE_FLASH_CURRENT_CORE_ID == 1u)
90 #define MAIN_FLASH_FEATURE_PFLASH_START_ADDRESS FSL_FEATURE_FLASH_PFLASH_1_START_ADDRESS
91 #define MAIN_FLASH_FEATURE_PFLASH_BLOCK_COUNT FSL_FEATURE_FLASH_PFLASH_1_BLOCK_COUNT
92 #define MAIN_FLASH_FEATURE_PFLASH_BLOCK_SIZE FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SIZE
93 #define MAIN_FLASH_FEATURE_PFLASH_BLOCK_SECTOR_SIZE FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SECTOR_SIZE
94 #define MAIN_FLASH_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE FSL_FEATURE_FLASH_PFLASH_1_BLOCK_WRITE_UNIT_SIZE
95 #define MAIN_FLASH_FEATURE_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_1_SECTOR_CMD_ADDRESS_ALIGMENT
96 #define MAIN_FLASH_FEATURE_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_1_SECTION_CMD_ADDRESS_ALIGMENT
97 #define MAIN_FLASH_FEATURE_PFLASH_PROTECTION_REGION_COUNT FSL_FEATURE_FLASH_PFLASH_1_PROTECTION_REGION_COUNT
98 #define SECONDARY_FLASH_FEATURE_PFLASH_START_ADDRESS FSL_FEATURE_FLASH_PFLASH_START_ADDRESS
99 #define SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_COUNT FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT
100 #define SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_SIZE FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE
101 #define SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_SECTOR_SIZE FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE
102 #define SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE
103 #define SECONDARY_FLASH_FEATURE_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT
104 #define SECONDARY_FLASH_FEATURE_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT
105 #define SECONDARY_FLASH_FEATURE_PFLASH_PROTECTION_REGION_COUNT FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT
106 #endif
107 #else
108 #define MAIN_FLASH_FEATURE_PFLASH_START_ADDRESS FSL_FEATURE_FLASH_PFLASH_START_ADDRESS
109 #define MAIN_FLASH_FEATURE_PFLASH_BLOCK_COUNT FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT
110 #define MAIN_FLASH_FEATURE_PFLASH_BLOCK_SIZE FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE
111 #define MAIN_FLASH_FEATURE_PFLASH_BLOCK_SECTOR_SIZE FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE
112 #define MAIN_FLASH_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE
113 #define MAIN_FLASH_FEATURE_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT
114 #define MAIN_FLASH_FEATURE_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT
115 #define MAIN_FLASH_FEATURE_PFLASH_PROTECTION_REGION_COUNT FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT
116 #endif
117 /*@}*/
118 
119 /*!
120  * @name Flash cache and speculation control defines
121  * @{
122  */
123 #if defined(MCM_PLACR_CFCC_MASK) || defined(MCM_CPCR2_CCBC_MASK)
124 #define FLASH_CACHE_IS_CONTROLLED_BY_MCM (1)
125 #else
126 #define FLASH_CACHE_IS_CONTROLLED_BY_MCM (0)
127 #endif
128 #if defined(FMC_PFB0CR_CINV_WAY_MASK) || defined(FMC_PFB01CR_CINV_WAY_MASK)
129 #define FLASH_CACHE_IS_CONTROLLED_BY_FMC (1)
130 #else
131 #define FLASH_CACHE_IS_CONTROLLED_BY_FMC (0)
132 #endif
133 #if defined(MCM_PLACR_DFCS_MASK)
134 #define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM (1)
135 #else
136 #define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM (0)
137 #endif
138 #if defined(MSCM_OCMDR_OCMC1_MASK) || defined(MSCM_OCMDR_OCM1_MASK) || defined(MSCM_OCMDR0_OCM1_MASK) || \
139     defined(MSCM_OCMDR1_OCM1_MASK)
140 #define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM (1)
141 #else
142 #define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM (0)
143 #endif
144 #if defined(FMC_PFB0CR_S_INV_MASK) || defined(FMC_PFB0CR_S_B_INV_MASK) || defined(FMC_PFB01CR_S_INV_MASK) || \
145     defined(FMC_PFB01CR_S_B_INV_MASK)
146 #define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC (1)
147 #else
148 #define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC (0)
149 #endif
150 
151 #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM || FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC || \
152     FLASH_CACHE_IS_CONTROLLED_BY_MCM || FLASH_CACHE_IS_CONTROLLED_BY_FMC
153 #define FLASH_IS_CACHE_INVALIDATION_AVAILABLE (1)
154 #else
155 #define FLASH_IS_CACHE_INVALIDATION_AVAILABLE (0)
156 #endif
157 /*@}*/
158 
159 /*! @brief Data flash IFR map Field*/
160 #if defined(FSL_FEATURE_FLASH_IS_FTFE) && FSL_FEATURE_FLASH_IS_FTFE
161 #define DFLASH_IFR_READRESOURCE_START_ADDRESS 0x8003F8U
162 #else /* FSL_FEATURE_FLASH_IS_FTFL == 1 or FSL_FEATURE_FLASH_IS_FTFA = =1 */
163 #define DFLASH_IFR_READRESOURCE_START_ADDRESS 0x8000F8U
164 #endif
165 
166 /*!
167  * @name Reserved FlexNVM size (For a variety of purposes) defines
168  * @{
169  */
170 #define FLEX_NVM_DFLASH_SIZE_FOR_DEPART_RESERVED 0xFFFFFFFFU
171 #define FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_RESERVED 0xFFFFU
172 /*@}*/
173 
174 /*!
175  * @name Flash Program Once Field defines
176  * @{
177  */
178 #if defined(FSL_FEATURE_FLASH_IS_FTFA) && FSL_FEATURE_FLASH_IS_FTFA
179 /* FTFA parts(eg. K80, KL80, L5K) support both 4-bytes and 8-bytes unit size */
180 #define FLASH_PROGRAM_ONCE_MIN_ID_8BYTES \
181     0x10U /* Minimum Index indcating one of Progam Once Fields which is accessed in 8-byte records */
182 #define FLASH_PROGRAM_ONCE_MAX_ID_8BYTES \
183     0x13U /* Maximum Index indcating one of Progam Once Fields which is accessed in 8-byte records */
184 #define FLASH_PROGRAM_ONCE_IS_4BYTES_UNIT_SUPPORT 1
185 #define FLASH_PROGRAM_ONCE_IS_8BYTES_UNIT_SUPPORT 1
186 #elif defined(FSL_FEATURE_FLASH_IS_FTFE) && FSL_FEATURE_FLASH_IS_FTFE
187 /* FTFE parts(eg. K65, KE18) only support 8-bytes unit size */
188 #define FLASH_PROGRAM_ONCE_IS_4BYTES_UNIT_SUPPORT 0
189 #define FLASH_PROGRAM_ONCE_IS_8BYTES_UNIT_SUPPORT 1
190 #elif defined(FSL_FEATURE_FLASH_IS_FTFL) && FSL_FEATURE_FLASH_IS_FTFL
191 /* FTFL parts(eg. K20) only support 4-bytes unit size */
192 #define FLASH_PROGRAM_ONCE_IS_4BYTES_UNIT_SUPPORT 1
193 #define FLASH_PROGRAM_ONCE_IS_8BYTES_UNIT_SUPPORT 0
194 #endif
195 /*@}*/
196 
197 /*!
198  * @name Flash security status defines
199  * @{
200  */
201 #define FLASH_SECURITY_STATE_KEYEN 0x80U
202 #define FLASH_SECURITY_STATE_UNSECURED 0x02U
203 #define FLASH_NOT_SECURE 0x01U
204 #define FLASH_SECURE_BACKDOOR_ENABLED 0x02U
205 #define FLASH_SECURE_BACKDOOR_DISABLED 0x04U
206 /*@}*/
207 
208 /*!
209  * @name Flash controller command numbers
210  * @{
211  */
212 #define FTFx_VERIFY_BLOCK 0x00U                    /*!< RD1BLK*/
213 #define FTFx_VERIFY_SECTION 0x01U                  /*!< RD1SEC*/
214 #define FTFx_PROGRAM_CHECK 0x02U                   /*!< PGMCHK*/
215 #define FTFx_READ_RESOURCE 0x03U                   /*!< RDRSRC*/
216 #define FTFx_PROGRAM_LONGWORD 0x06U                /*!< PGM4*/
217 #define FTFx_PROGRAM_PHRASE 0x07U                  /*!< PGM8*/
218 #define FTFx_ERASE_BLOCK 0x08U                     /*!< ERSBLK*/
219 #define FTFx_ERASE_SECTOR 0x09U                    /*!< ERSSCR*/
220 #define FTFx_PROGRAM_SECTION 0x0BU                 /*!< PGMSEC*/
221 #define FTFx_GENERATE_CRC 0x0CU                    /*!< CRCGEN*/
222 #define FTFx_VERIFY_ALL_BLOCK 0x40U                /*!< RD1ALL*/
223 #define FTFx_READ_ONCE 0x41U                       /*!< RDONCE or RDINDEX*/
224 #define FTFx_PROGRAM_ONCE 0x43U                    /*!< PGMONCE or PGMINDEX*/
225 #define FTFx_ERASE_ALL_BLOCK 0x44U                 /*!< ERSALL*/
226 #define FTFx_SECURITY_BY_PASS 0x45U                /*!< VFYKEY*/
227 #define FTFx_SWAP_CONTROL 0x46U                    /*!< SWAP*/
228 #define FTFx_ERASE_ALL_BLOCK_UNSECURE 0x49U        /*!< ERSALLU*/
229 #define FTFx_VERIFY_ALL_EXECUTE_ONLY_SEGMENT 0x4AU /*!< RD1XA*/
230 #define FTFx_ERASE_ALL_EXECUTE_ONLY_SEGMENT 0x4BU  /*!< ERSXA*/
231 #define FTFx_PROGRAM_PARTITION 0x80U               /*!< PGMPART)*/
232 #define FTFx_SET_FLEXRAM_FUNCTION 0x81U            /*!< SETRAM*/
233                                                    /*@}*/
234 
235 /*!
236  * @name Common flash register info defines
237  * @{
238  */
239 #if defined(FTFA)
240 #define FTFx FTFA
241 #define FTFx_BASE FTFA_BASE
242 #define FTFx_FSTAT_CCIF_MASK FTFA_FSTAT_CCIF_MASK
243 #define FTFx_FSTAT_RDCOLERR_MASK FTFA_FSTAT_RDCOLERR_MASK
244 #define FTFx_FSTAT_ACCERR_MASK FTFA_FSTAT_ACCERR_MASK
245 #define FTFx_FSTAT_FPVIOL_MASK FTFA_FSTAT_FPVIOL_MASK
246 #define FTFx_FSTAT_MGSTAT0_MASK FTFA_FSTAT_MGSTAT0_MASK
247 #define FTFx_FSEC_SEC_MASK FTFA_FSEC_SEC_MASK
248 #define FTFx_FSEC_KEYEN_MASK FTFA_FSEC_KEYEN_MASK
249 #if defined(FSL_FEATURE_FLASH_HAS_FLEX_RAM) && FSL_FEATURE_FLASH_HAS_FLEX_RAM
250 #define FTFx_FCNFG_RAMRDY_MASK FTFA_FCNFG_RAMRDY_MASK
251 #endif /* FSL_FEATURE_FLASH_HAS_FLEX_RAM */
252 #if defined(FSL_FEATURE_FLASH_HAS_FLEX_NVM) && FSL_FEATURE_FLASH_HAS_FLEX_NVM
253 #define FTFx_FCNFG_EEERDY_MASK FTFA_FCNFG_EEERDY_MASK
254 #endif /* FSL_FEATURE_FLASH_HAS_FLEX_NVM */
255 #elif defined(FTFE)
256 #define FTFx FTFE
257 #define FTFx_BASE FTFE_BASE
258 #define FTFx_FSTAT_CCIF_MASK FTFE_FSTAT_CCIF_MASK
259 #define FTFx_FSTAT_RDCOLERR_MASK FTFE_FSTAT_RDCOLERR_MASK
260 #define FTFx_FSTAT_ACCERR_MASK FTFE_FSTAT_ACCERR_MASK
261 #define FTFx_FSTAT_FPVIOL_MASK FTFE_FSTAT_FPVIOL_MASK
262 #define FTFx_FSTAT_MGSTAT0_MASK FTFE_FSTAT_MGSTAT0_MASK
263 #define FTFx_FSEC_SEC_MASK FTFE_FSEC_SEC_MASK
264 #define FTFx_FSEC_KEYEN_MASK FTFE_FSEC_KEYEN_MASK
265 #if defined(FSL_FEATURE_FLASH_HAS_FLEX_RAM) && FSL_FEATURE_FLASH_HAS_FLEX_RAM
266 #define FTFx_FCNFG_RAMRDY_MASK FTFE_FCNFG_RAMRDY_MASK
267 #endif /* FSL_FEATURE_FLASH_HAS_FLEX_RAM */
268 #if defined(FSL_FEATURE_FLASH_HAS_FLEX_NVM) && FSL_FEATURE_FLASH_HAS_FLEX_NVM
269 #define FTFx_FCNFG_EEERDY_MASK FTFE_FCNFG_EEERDY_MASK
270 #endif /* FSL_FEATURE_FLASH_HAS_FLEX_NVM */
271 #elif defined(FTFL)
272 #define FTFx FTFL
273 #define FTFx_BASE FTFL_BASE
274 #define FTFx_FSTAT_CCIF_MASK FTFL_FSTAT_CCIF_MASK
275 #define FTFx_FSTAT_RDCOLERR_MASK FTFL_FSTAT_RDCOLERR_MASK
276 #define FTFx_FSTAT_ACCERR_MASK FTFL_FSTAT_ACCERR_MASK
277 #define FTFx_FSTAT_FPVIOL_MASK FTFL_FSTAT_FPVIOL_MASK
278 #define FTFx_FSTAT_MGSTAT0_MASK FTFL_FSTAT_MGSTAT0_MASK
279 #define FTFx_FSEC_SEC_MASK FTFL_FSEC_SEC_MASK
280 #define FTFx_FSEC_KEYEN_MASK FTFL_FSEC_KEYEN_MASK
281 #if defined(FSL_FEATURE_FLASH_HAS_FLEX_RAM) && FSL_FEATURE_FLASH_HAS_FLEX_RAM
282 #define FTFx_FCNFG_RAMRDY_MASK FTFL_FCNFG_RAMRDY_MASK
283 #endif /* FSL_FEATURE_FLASH_HAS_FLEX_RAM */
284 #if defined(FSL_FEATURE_FLASH_HAS_FLEX_NVM) && FSL_FEATURE_FLASH_HAS_FLEX_NVM
285 #define FTFx_FCNFG_EEERDY_MASK FTFL_FCNFG_EEERDY_MASK
286 #endif /* FSL_FEATURE_FLASH_HAS_FLEX_NVM */
287 #else
288 #error "Unknown flash controller"
289 #endif
290 /*@}*/
291 
292 /*!
293  * @name Common flash register access info defines
294  * @{
295  */
296 #define FTFx_FCCOB3_REG (FTFx->FCCOB3)
297 #define FTFx_FCCOB5_REG (FTFx->FCCOB5)
298 #define FTFx_FCCOB6_REG (FTFx->FCCOB6)
299 #define FTFx_FCCOB7_REG (FTFx->FCCOB7)
300 
301 #if defined(FTFA_FPROTH0_PROT_MASK) || defined(FTFE_FPROTH0_PROT_MASK) || defined(FTFL_FPROTH0_PROT_MASK)
302 #define FTFx_FPROT_HIGH_REG (FTFx->FPROTH3)
303 #define FTFx_FPROTH3_REG (FTFx->FPROTH3)
304 #define FTFx_FPROTH2_REG (FTFx->FPROTH2)
305 #define FTFx_FPROTH1_REG (FTFx->FPROTH1)
306 #define FTFx_FPROTH0_REG (FTFx->FPROTH0)
307 #endif
308 
309 #if defined(FTFA_FPROTL0_PROT_MASK) || defined(FTFE_FPROTL0_PROT_MASK) || defined(FTFL_FPROTL0_PROT_MASK)
310 #define FTFx_FPROT_LOW_REG (FTFx->FPROTL3)
311 #define FTFx_FPROTL3_REG (FTFx->FPROTL3)
312 #define FTFx_FPROTL2_REG (FTFx->FPROTL2)
313 #define FTFx_FPROTL1_REG (FTFx->FPROTL1)
314 #define FTFx_FPROTL0_REG (FTFx->FPROTL0)
315 #elif defined(FTFA_FPROT0_PROT_MASK) || defined(FTFE_FPROT0_PROT_MASK) || defined(FTFL_FPROT0_PROT_MASK)
316 #define FTFx_FPROT_LOW_REG (FTFx->FPROT3)
317 #define FTFx_FPROTL3_REG (FTFx->FPROT3)
318 #define FTFx_FPROTL2_REG (FTFx->FPROT2)
319 #define FTFx_FPROTL1_REG (FTFx->FPROT1)
320 #define FTFx_FPROTL0_REG (FTFx->FPROT0)
321 #endif
322 
323 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER
324 #define FTFx_FPROTSH_REG (FTFx->FPROTSH)
325 #define FTFx_FPROTSL_REG (FTFx->FPROTSL)
326 #endif
327 
328 #define FTFx_XACCH3_REG (FTFx->XACCH3)
329 #define FTFx_XACCL3_REG (FTFx->XACCL3)
330 
331 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER
332 #define FTFx_XACCSH_REG (FTFx->XACCSH)
333 #define FTFx_XACCSL_REG (FTFx->XACCSL)
334 #endif
335 /*@}*/
336 
337 /*!
338  * @brief Enumeration for access segment property.
339  */
340 enum _flash_access_segment_property
341 {
342     kFLASH_AccessSegmentBase = 256UL,
343 };
344 
345 /*!
346  * @brief Enumeration for flash config area.
347  */
348 enum _flash_config_area_range
349 {
350     kFLASH_ConfigAreaStart = 0x400U,
351     kFLASH_ConfigAreaEnd = 0x40FU
352 };
353 
354 /*!
355  * @name Flash register access type defines
356  * @{
357  */
358 #define FTFx_REG8_ACCESS_TYPE volatile uint8_t *
359 #define FTFx_REG32_ACCESS_TYPE volatile uint32_t *
360 /*@}*/
361 
362 /*!
363  * @brief MCM cache register access info defines.
364  */
365 #if defined(MCM_PLACR_CFCC_MASK)
366 #define MCM_CACHE_CLEAR_MASK MCM_PLACR_CFCC_MASK
367 #define MCM_CACHE_CLEAR_SHIFT MCM_PLACR_CFCC_SHIFT
368 #if defined(MCM0)
369 #define MCM0_CACHE_REG MCM0->PLACR
370 #elif defined(MCM) && (!defined(MCM1))
371 #define MCM0_CACHE_REG MCM->PLACR
372 #endif
373 #if defined(MCM1)
374 #define MCM1_CACHE_REG MCM1->PLACR
375 #elif defined(MCM) && (!defined(MCM0))
376 #define MCM1_CACHE_REG MCM->PLACR
377 #endif
378 #elif defined(MCM_CPCR2_CCBC_MASK)
379 #define MCM_CACHE_CLEAR_MASK MCM_CPCR2_CCBC_MASK
380 #define MCM_CACHE_CLEAR_SHIFT MCM_CPCR2_CCBC_SHIFT
381 #if defined(MCM0)
382 #define MCM0_CACHE_REG MCM0->CPCR2
383 #elif defined(MCM) && (!defined(MCM1))
384 #define MCM0_CACHE_REG MCM->CPCR2
385 #endif
386 #if defined(MCM1)
387 #define MCM1_CACHE_REG MCM1->CPCR2
388 #elif defined(MCM) && (!defined(MCM0))
389 #define MCM1_CACHE_REG MCM->CPCR2
390 #endif
391 #endif
392 
393 /*!
394  * @brief Enumeration for ARM core part number.
395  */
396 enum _arm_core_part_number
397 {
398     kARM_CorePartNumber_CM0 = 0xc20U,
399     kARM_CorePartNumber_CM0P = 0xc60U,
400     kARM_CorePartNumber_CM1 = 0xc21U,
401     kARM_CorePartNumber_CM3 = 0xc23U,
402     kARM_CorePartNumber_CM4 = 0xc24U,
403     kARM_CorePartNumber_CM7 = 0xc27U,
404     kARM_CorePartNumber_CM23 = 0xd20U,
405     kARM_CorePartNumber_CM33 = 0xd21U,
406 
407     kARM_CorePartNumber_Invalid = 0xFFFFU,
408 };
409 
410 #if defined(BL_TARGET_ROM) && defined(MCM0_CACHE_REG) && defined(MCM1_CACHE_REG) && \
411     defined(FSL_FEATURE_FLASH_CURRENT_CORE_ID)
412 FTFx_REG32_ACCESS_TYPE const s_mcmModuleAccessTypeArray[] = {
413     (FTFx_REG32_ACCESS_TYPE)&MCM0_CACHE_REG,
414     (FTFx_REG32_ACCESS_TYPE)&MCM1_CACHE_REG
415 };
416 
417 static const uint16_t s_armCorePartNumberArray[] = {
418     kARM_CorePartNumber_CM0P,
419     kARM_CorePartNumber_CM1,
420     kARM_CorePartNumber_Invalid,
421     kARM_CorePartNumber_CM3,
422     kARM_CorePartNumber_CM4,
423     kARM_CorePartNumber_Invalid,
424     kARM_CorePartNumber_Invalid,
425     kARM_CorePartNumber_CM7
426 };
427 #endif
428 
429 /*!
430  * @brief MSCM cache register access info defines.
431  */
432 #if defined(MSCM_OCMDR_OCM1_MASK)
433 #define MSCM_SPECULATION_DISABLE_MASK MSCM_OCMDR_OCM1_MASK
434 #define MSCM_SPECULATION_DISABLE_SHIFT MSCM_OCMDR_OCM1_SHIFT
435 #define MSCM_SPECULATION_DISABLE(x) MSCM_OCMDR_OCM1(x)
436 #elif defined(MSCM_OCMDR0_OCM1_MASK) || defined(MSCM_OCMDR1_OCM1_MASK)
437 #define MSCM_SPECULATION_DISABLE_MASK MSCM_OCMDR0_OCM1_MASK
438 #define MSCM_SPECULATION_DISABLE_SHIFT MSCM_OCMDR0_OCM1_SHIFT
439 #define MSCM_SPECULATION_DISABLE(x) MSCM_OCMDR0_OCM1(x)
440 #elif defined(MSCM_OCMDR_OCMC1_MASK)
441 #define MSCM_SPECULATION_DISABLE_MASK MSCM_OCMDR_OCMC1_MASK
442 #define MSCM_SPECULATION_DISABLE_SHIFT MSCM_OCMDR_OCMC1_SHIFT
443 #define MSCM_SPECULATION_DISABLE(x) MSCM_OCMDR_OCMC1(x)
444 #endif
445 
446 #if defined(MSCM_OCMDR_OCM1_MASK) || defined(MSCM_OCMDR_OCMC1_MASK)
447 #define MSCM_OCMDR0_REG MSCM->OCMDR[0]
448 #define MSCM_OCMDR1_REG MSCM->OCMDR[1]
449 #elif defined(MSCM_OCMDR0_OCM1_MASK) || defined(MSCM_OCMDR1_OCM1_MASK)
450 #define MSCM_OCMDR0_REG MSCM->OCMDR0
451 #define MSCM_OCMDR1_REG MSCM->OCMDR1
452 #endif
453 
454 /*!
455  * @brief MSCM prefetch speculation defines.
456  */
457 #define MSCM_OCMDR_OCMC1_DFDS_MASK (0x10U)
458 #define MSCM_OCMDR_OCMC1_DFCS_MASK (0x20U)
459 
460 #define MSCM_OCMDR_OCMC1_DFDS_SHIFT (4U)
461 #define MSCM_OCMDR_OCMC1_DFCS_SHIFT (5U)
462 
463 /*******************************************************************************
464  * Prototypes
465  ******************************************************************************/
466 
467 #if FLASH_DRIVER_IS_FLASH_RESIDENT
468 /*! @brief Copy flash_run_command() to RAM*/
469 static void copy_flash_run_command(uint32_t *flashRunCommand);
470 #if FLASH_IS_CACHE_INVALIDATION_AVAILABLE
471 /*! @brief Copy flash_cache_clear_command() to RAM*/
472 static void copy_flash_common_bit_operation(uint32_t *flashCommonBitOperation);
473 #endif
474 /*! @brief Check whether flash execute-in-ram functions are ready*/
475 static status_t flash_check_execute_in_ram_function_info(flash_config_t *config);
476 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
477 
478 /*! @brief Internal function Flash command sequence. Called by driver APIs only*/
479 static status_t flash_command_sequence(flash_config_t *config);
480 
481 /*! @brief Perform the cache clear to the flash*/
482 void flash_cache_clear(flash_config_t *config);
483 
484 /*! @brief Process the cache to the flash*/
485 static void flash_cache_clear_process(flash_config_t *config, flash_cache_clear_process_t process);
486 
487 /*! @brief Validates the range and alignment of the given address range.*/
488 static status_t flash_check_range(flash_config_t *config,
489                                   uint32_t startAddress,
490                                   uint32_t lengthInBytes,
491                                   uint32_t alignmentBaseline);
492 /*! @brief Gets the right address, sector and block size of current flash type which is indicated by address.*/
493 static status_t flash_get_matched_operation_info(flash_config_t *config,
494                                                  uint32_t address,
495                                                  flash_operation_config_t *info);
496 /*! @brief Validates the given user key for flash erase APIs.*/
497 static status_t flash_check_user_key(uint32_t key);
498 
499 #if FLASH_SSD_IS_FLEXNVM_ENABLED
500 /*! @brief Updates FlexNVM memory partition status according to data flash 0 IFR.*/
501 static status_t flash_update_flexnvm_memory_partition_status(flash_config_t *config);
502 #endif /* FLASH_SSD_IS_FLEXNVM_ENABLED */
503 
504 #if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD
505 /*! @brief Validates the range of the given resource address.*/
506 static status_t flash_check_resource_range(uint32_t start,
507                                            uint32_t lengthInBytes,
508                                            uint32_t alignmentBaseline,
509                                            flash_read_resource_option_t option);
510 #endif /* FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD */
511 
512 #if defined(FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD) && FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD
513 /*! @brief Validates the gived swap control option.*/
514 static status_t flash_check_swap_control_option(flash_swap_control_option_t option);
515 #endif /* FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD */
516 
517 #if defined(FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP) && FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP
518 /*! @brief Validates the gived address to see if it is equal to swap indicator address in pflash swap IFR.*/
519 static status_t flash_validate_swap_indicator_address(flash_config_t *config, uint32_t address);
520 #endif /* FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP */
521 
522 #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD
523 /*! @brief Validates the gived flexram function option.*/
524 static inline status_t flasn_check_flexram_function_option_range(flash_flexram_function_option_t option);
525 #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */
526 
527 /*! @brief Gets the flash protection information (region size, region count).*/
528 static status_t flash_get_protection_info(flash_config_t *config, flash_protection_config_t *info);
529 
530 #if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL
531 /*! @brief Gets the flash Execute-Only access information (Segment size, Segment count).*/
532 static status_t flash_get_access_info(flash_config_t *config, flash_access_config_t *info);
533 #endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */
534 
535 #if FLASH_CACHE_IS_CONTROLLED_BY_MCM
536 /*! @brief Performs the cache clear to the flash by MCM.*/
537 void mcm_flash_cache_clear(void);
538 #endif /* FLASH_CACHE_IS_CONTROLLED_BY_MCM */
539 
540 #if FLASH_CACHE_IS_CONTROLLED_BY_FMC
541 /*! @brief Performs the cache clear to the flash by FMC.*/
542 void fmc_flash_cache_clear(void);
543 #endif /* FLASH_CACHE_IS_CONTROLLED_BY_FMC */
544 
545 #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM
546 /*! @brief Sets the prefetch speculation buffer to the flash by MSCM.*/
547 void mscm_flash_prefetch_speculation_enable(uint32_t flashIndex, bool enable);
548 #endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM */
549 
550 #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC
551 /*! @brief Performs the prefetch speculation buffer clear to the flash by FMC.*/
552 void fmc_flash_prefetch_speculation_clear(void);
553 #endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC */
554 
555 /*******************************************************************************
556  * Variables
557  ******************************************************************************/
558 
559 /*! @brief Access to FTFx->FCCOB */
560 volatile uint32_t *const kFCCOBx = (volatile uint32_t *)&FTFx_FCCOB3_REG;
561 /*! @brief Access to FTFx->FPROT */
562 volatile uint32_t *const kFPROTL = (volatile uint32_t *)&FTFx_FPROT_LOW_REG;
563 #if defined(FTFx_FPROT_HIGH_REG)
564 volatile uint32_t *const kFPROTH = (volatile uint32_t *)&FTFx_FPROT_HIGH_REG;
565 #endif
566 
567 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER
568 volatile uint8_t *const kFPROTSL = (volatile uint8_t *)&FTFx_FPROTSL_REG;
569 volatile uint8_t *const kFPROTSH = (volatile uint8_t *)&FTFx_FPROTSH_REG;
570 #endif
571 
572 #if FLASH_DRIVER_IS_FLASH_RESIDENT
573 /*! @brief A function pointer used to point to relocated flash_run_command() */
574 static void (*callFlashRunCommand)(FTFx_REG8_ACCESS_TYPE ftfx_fstat);
575 
576 /*!
577  * @brief Position independent code of flash_run_command()
578  *
579  * Note1: The prototype of C function is shown as below:
580  * @code
581  *   void flash_run_command(FTFx_REG8_ACCESS_TYPE ftfx_fstat)
582  *   {
583  *       // clear CCIF bit
584  *       *ftfx_fstat = FTFx_FSTAT_CCIF_MASK;
585  *
586  *       // Check CCIF bit of the flash status register, wait till it is set.
587  *       // IP team indicates that this loop will always complete.
588  *       while (!((*ftfx_fstat) & FTFx_FSTAT_CCIF_MASK))
589  *       {
590  *       }
591  *   }
592  * @endcode
593  * Note2: The binary code is generated by IAR 7.70.1
594  */
595 #if defined(__riscv)
596 /* Build with zero riscy core configuration. */
597 static const uint16_t s_flashRunCommandFunctionCode[] = {
598       0x0793, 0xf800,    /* li  a5,-128 */
599       0x0023, 0x00f5,    /*  sb  a5,0(a0) */
600       0x4783, 0x0005,    /* lbu a5,0(a0) */
601       0x07e2,            /* slli    a5,a5,0x18 */
602       0x87e1,            /* srai    a5,a5,0x18 */
603       0xdce3, 0xfe07,    /* bgez    a5, <flash_run_command+0x8> */
604       0x8082             /* ret */
605 };
606 #else
607 static const uint16_t s_flashRunCommandFunctionCode[] = {
608     0x2180, /* MOVS  R1, #128 ; 0x80 */
609     0x7001, /* STRB  R1, [R0] */
610     /* @4: */
611     0x7802, /* LDRB  R2, [R0] */
612     0x420a, /* TST   R2, R1 */
613     0xd0fc, /* BEQ.N @4 */
614     0x4770  /* BX    LR */
615 };
616 #endif
617 
618 #if FLASH_IS_CACHE_INVALIDATION_AVAILABLE
619 /*! @brief A function pointer used to point to relocated flash_common_bit_operation() */
620 static void (*callFlashCommonBitOperation)(FTFx_REG32_ACCESS_TYPE base,
621                                            uint32_t bitMask,
622                                            uint32_t bitShift,
623                                            uint32_t bitValue);
624 
625 /*!
626  * @brief Position independent code of flash_common_bit_operation()
627  *
628  * Note1: The prototype of C function is shown as below:
629  * @code
630  *   void flash_common_bit_operation(FTFx_REG32_ACCESS_TYPE base, uint32_t bitMask, uint32_t bitShift, uint32_t
631  * bitValue)
632  *   {
633  *       if (bitMask)
634  *       {
635  *           uint32_t value = (((uint32_t)(((uint32_t)(bitValue)) << bitShift)) & bitMask);
636  *           *base = (*base & (~bitMask)) | value;
637  *       }
638  *
639  *       __ISB();
640  *       __DSB();
641  *   }
642  * @endcode
643  * Note2: The binary code is generated by IAR 7.70.1
644  */
645 #if defined(__riscv)
646 /* Build with zero riscy core configuration. */
647 static const uint16_t s_flashCommonBitOperationFunctionCode[] = {
648     0xc981,                    /* beqz    a1, <flash_common_bit_operation+0x10> */
649     0x411c,                    /* lw  a5,0(a0) */
650     0x96b3, 0x00c6,            /* sll a3,a3,a2 */
651     0x8ebd,                    /* xor a3,a3,a5 */
652     0x8df5,                    /* and a1,a1,a3 */
653     0x8dbd,                    /* xor a1,a1,a5 */
654     0xc10c,                    /* sw  a1,0(a0) */
655     0x0001,                    /* nop */
656     0x0001,                    /* nop */
657     0x8082,                    /* ret */
658 };
659 #else
660 static const uint16_t s_flashCommonBitOperationFunctionCode[] = {
661     0xb510, /* PUSH  {R4, LR} */
662     0x2900, /* CMP   R1, #0 */
663     0xd005, /* BEQ.N @12 */
664     0x6804, /* LDR   R4, [R0] */
665     0x438c, /* BICS  R4, R4, R1 */
666     0x4093, /* LSLS  R3, R3, R2 */
667     0x4019, /* ANDS  R1, R1, R3 */
668     0x4321, /* ORRS  R1, R1, R4 */
669     0x6001, /* STR   R1, [R0] */
670     /*  @12: */
671     0xf3bf, 0x8f6f, /* ISB */
672     0xf3bf, 0x8f4f, /* DSB */
673     0xbd10          /* POP   {R4, PC} */
674 };
675 #endif
676 #endif /* FLASH_IS_CACHE_INVALIDATION_AVAILABLE */
677 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
678 
679 #if (FLASH_DRIVER_IS_FLASH_RESIDENT && !FLASH_DRIVER_IS_EXPORTED)
680 /*! @brief A static buffer used to hold flash_run_command() */
681 static uint32_t s_flashRunCommand[kFLASH_ExecuteInRamFunctionMaxSizeInWords];
682 #if FLASH_IS_CACHE_INVALIDATION_AVAILABLE
683 /*! @brief A static buffer used to hold flash_common_bit_operation() */
684 static uint32_t s_flashCommonBitOperation[kFLASH_ExecuteInRamFunctionMaxSizeInWords];
685 #endif
686 /*! @brief Flash execute-in-ram function information */
687 static flash_execute_in_ram_function_config_t s_flashExecuteInRamFunctionInfo;
688 #endif
689 
690 /*!
691  * @brief Table of pflash sizes.
692  *
693  *  The index into this table is the value of the SIM_FCFG1.PFSIZE bitfield.
694  *
695  *  The values in this table have been right shifted 10 bits so that they will all fit within
696  *  an 16-bit integer. To get the actual flash density, you must left shift the looked up value
697  *  by 10 bits.
698  *
699  *  Elements of this table have a value of 0 in cases where the PFSIZE bitfield value is
700  *  reserved.
701  *
702  *  Code to use the table:
703  *  @code
704  *      uint8_t pfsize = (SIM->FCFG1 & SIM_FCFG1_PFSIZE_MASK) >> SIM_FCFG1_PFSIZE_SHIFT;
705  *      flashDensity = ((uint32_t)kPFlashDensities[pfsize]) << 10;
706  *  @endcode
707  */
708 #if defined(FSL_FEATURE_FLASH_SIZE_ENCODING_RULE_VERSION) && (FSL_FEATURE_FLASH_SIZE_ENCODING_RULE_VERSION == 1)
709 const uint16_t kPFlashDensities[] = {
710     0,    /* 0x0 - undefined */
711     0,    /* 0x1 - undefined */
712     0,    /* 0x2 - undefined */
713     0,    /* 0x3 - undefined */
714     0,    /* 0x4 - undefined */
715     0,    /* 0x5 - undefined */
716     0,    /* 0x6 - undefined */
717     0,    /* 0x7 - undefined */
718     0,    /* 0x8 - undefined */
719     0,    /* 0x9 - undefined */
720     256,  /* 0xa - 262144, 256KB */
721     0,    /* 0xb - undefined */
722     1024, /* 0xc - 1048576, 1MB */
723     0,    /* 0xd - undefined */
724     0,    /* 0xe - undefined */
725     0,    /* 0xf - undefined */
726 };
727 #else
728 const uint16_t kPFlashDensities[] = {
729     8,    /* 0x0 - 8192, 8KB */
730     16,   /* 0x1 - 16384, 16KB */
731     24,   /* 0x2 - 24576, 24KB */
732     32,   /* 0x3 - 32768, 32KB */
733     48,   /* 0x4 - 49152, 48KB */
734     64,   /* 0x5 - 65536, 64KB */
735     96,   /* 0x6 - 98304, 96KB */
736     128,  /* 0x7 - 131072, 128KB */
737     192,  /* 0x8 - 196608, 192KB */
738     256,  /* 0x9 - 262144, 256KB */
739     384,  /* 0xa - 393216, 384KB */
740     512,  /* 0xb - 524288, 512KB */
741     768,  /* 0xc - 786432, 768KB */
742     1024, /* 0xd - 1048576, 1MB */
743     1536, /* 0xe - 1572864, 1.5MB */
744     /* 2048,  0xf - 2097152, 2MB */
745 };
746 #endif
747 
748 /*******************************************************************************
749  * Code
750  ******************************************************************************/
751 
FLASH_Init(flash_config_t * config)752 status_t FLASH_Init(flash_config_t *config)
753 {
754     if (config == NULL)
755     {
756         return kStatus_FLASH_InvalidArgument;
757     }
758 
759 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED
760     if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash)
761     {
762 /* calculate the flash density from SIM_FCFG1.PFSIZE */
763 #if defined(SIM_FCFG1_CORE1_PFSIZE_MASK)
764         uint32_t flashDensity;
765         uint8_t pfsize = (SIM->FCFG1 & SIM_FCFG1_CORE1_PFSIZE_MASK) >> SIM_FCFG1_CORE1_PFSIZE_SHIFT;
766         if (pfsize == 0xf)
767         {
768             flashDensity = SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_COUNT * SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_SIZE;
769         }
770         else
771         {
772             flashDensity = ((uint32_t)kPFlashDensities[pfsize]) << 10;
773         }
774         config->PFlashTotalSize = flashDensity;
775 #else
776         /* Unused code to solve MISRA-C issue*/
777         config->PFlashBlockBase = kPFlashDensities[0];
778         config->PFlashTotalSize = SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_COUNT * SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_SIZE;
779 #endif
780         config->PFlashBlockBase = SECONDARY_FLASH_FEATURE_PFLASH_START_ADDRESS;
781         config->PFlashBlockCount = SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_COUNT;
782         config->PFlashSectorSize = SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_SECTOR_SIZE;
783     }
784     else
785 #endif /* FLASH_SSD_IS_SECONDARY_FLASH_ENABLED */
786     {
787         uint32_t flashDensity;
788 
789 /* calculate the flash density from SIM_FCFG1.PFSIZE */
790 #if defined(SIM_FCFG1_CORE0_PFSIZE_MASK)
791         uint8_t pfsize = (SIM->FCFG1 & SIM_FCFG1_CORE0_PFSIZE_MASK) >> SIM_FCFG1_CORE0_PFSIZE_SHIFT;
792 #elif defined(SIM_FCFG1_PFSIZE_MASK)
793         uint8_t pfsize = (SIM->FCFG1 & SIM_FCFG1_PFSIZE_MASK) >> SIM_FCFG1_PFSIZE_SHIFT;
794 #else
795 #error "Unknown flash size"
796 #endif
797         /* PFSIZE=0xf means that on customer parts the IFR was not correctly programmed.
798          * We just use the pre-defined flash size in feature file here to support pre-production parts */
799         if (pfsize == 0xf)
800         {
801             flashDensity = MAIN_FLASH_FEATURE_PFLASH_BLOCK_COUNT * MAIN_FLASH_FEATURE_PFLASH_BLOCK_SIZE;
802         }
803         else
804         {
805             flashDensity = ((uint32_t)kPFlashDensities[pfsize]) << 10;
806         }
807 
808         /* fill out a few of the structure members */
809         config->PFlashBlockBase = MAIN_FLASH_FEATURE_PFLASH_START_ADDRESS;
810         config->PFlashTotalSize = flashDensity;
811         config->PFlashBlockCount = MAIN_FLASH_FEATURE_PFLASH_BLOCK_COUNT;
812         config->PFlashSectorSize = MAIN_FLASH_FEATURE_PFLASH_BLOCK_SECTOR_SIZE;
813     }
814 
815     {
816 #if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL
817 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER
818         if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash)
819         {
820             config->PFlashAccessSegmentSize = kFLASH_AccessSegmentBase << FTFx->FACSSS;
821             config->PFlashAccessSegmentCount = FTFx->FACSNS;
822         }
823         else
824 #endif
825         {
826             config->PFlashAccessSegmentSize = kFLASH_AccessSegmentBase << FTFx->FACSS;
827             config->PFlashAccessSegmentCount = FTFx->FACSN;
828         }
829 #else
830         config->PFlashAccessSegmentSize = 0;
831         config->PFlashAccessSegmentCount = 0;
832 #endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */
833     }
834 
835 /* copy required flash commands to RAM */
836 #if (FLASH_DRIVER_IS_FLASH_RESIDENT && !FLASH_DRIVER_IS_EXPORTED)
837     if (kStatus_FLASH_Success != flash_check_execute_in_ram_function_info(config))
838     {
839         s_flashExecuteInRamFunctionInfo.activeFunctionCount = 0;
840         s_flashExecuteInRamFunctionInfo.flashRunCommand = s_flashRunCommand;
841 #if FLASH_IS_CACHE_INVALIDATION_AVAILABLE
842         s_flashExecuteInRamFunctionInfo.flashCommonBitOperation = s_flashCommonBitOperation;
843 #endif
844         config->flashExecuteInRamFunctionInfo = &s_flashExecuteInRamFunctionInfo.activeFunctionCount;
845         FLASH_PrepareExecuteInRamFunctions(config);
846     }
847 #endif
848 
849     config->FlexRAMBlockBase = FSL_FEATURE_FLASH_FLEX_RAM_START_ADDRESS;
850     config->FlexRAMTotalSize = FSL_FEATURE_FLASH_FLEX_RAM_SIZE;
851 
852 #if FLASH_SSD_IS_FLEXNVM_ENABLED
853     {
854         status_t returnCode;
855         config->DFlashBlockBase = FSL_FEATURE_FLASH_FLEX_NVM_START_ADDRESS;
856         returnCode = flash_update_flexnvm_memory_partition_status(config);
857         if (returnCode != kStatus_FLASH_Success)
858         {
859             return returnCode;
860         }
861     }
862 #endif
863 
864     return kStatus_FLASH_Success;
865 }
866 
867 #if FLASH_DRIVER_IS_FLASH_RESIDENT
FLASH_PrepareExecuteInRamFunctions(flash_config_t * config)868 status_t FLASH_PrepareExecuteInRamFunctions(flash_config_t *config)
869 {
870     flash_execute_in_ram_function_config_t *flashExecuteInRamFunctionInfo;
871 
872     if ((config == NULL) || (config->flashExecuteInRamFunctionInfo == NULL))
873     {
874         return kStatus_FLASH_InvalidArgument;
875     }
876 
877     flashExecuteInRamFunctionInfo = (flash_execute_in_ram_function_config_t *)config->flashExecuteInRamFunctionInfo;
878 
879     copy_flash_run_command(flashExecuteInRamFunctionInfo->flashRunCommand);
880 #if FLASH_IS_CACHE_INVALIDATION_AVAILABLE
881     copy_flash_common_bit_operation(flashExecuteInRamFunctionInfo->flashCommonBitOperation);
882 #endif
883     flashExecuteInRamFunctionInfo->activeFunctionCount = kFLASH_ExecuteInRamFunctionTotalNum;
884 
885     return kStatus_FLASH_Success;
886 }
887 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
888 
FLASH_EraseAll(flash_config_t * config,uint32_t key)889 status_t FLASH_EraseAll(flash_config_t *config, uint32_t key)
890 {
891     status_t returnCode;
892 
893     if (config == NULL)
894     {
895         return kStatus_FLASH_InvalidArgument;
896     }
897 
898     /* preparing passing parameter to erase all flash blocks */
899     kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_ERASE_ALL_BLOCK, 0xFFFFFFU);
900 
901     /* Validate the user key */
902     returnCode = flash_check_user_key(key);
903     if (returnCode)
904     {
905         return returnCode;
906     }
907 
908     flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
909 
910     /* calling flash command sequence function to execute the command */
911     returnCode = flash_command_sequence(config);
912 
913     flash_cache_clear(config);
914 
915 #if FLASH_SSD_IS_FLEXNVM_ENABLED
916     /* Data flash IFR will be erased by erase all command, so we need to
917      *  update FlexNVM memory partition status synchronously */
918     if (returnCode == kStatus_FLASH_Success)
919     {
920         returnCode = flash_update_flexnvm_memory_partition_status(config);
921     }
922 #endif
923 
924     return returnCode;
925 }
926 
FLASH_Erase(flash_config_t * config,uint32_t start,uint32_t lengthInBytes,uint32_t key)927 status_t FLASH_Erase(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, uint32_t key)
928 {
929     uint32_t sectorSize;
930     flash_operation_config_t flashOperationInfo;
931     uint32_t endAddress;      /* storing end address */
932     uint32_t numberOfSectors; /* number of sectors calculated by endAddress */
933     status_t returnCode;
934 
935     flash_get_matched_operation_info(config, start, &flashOperationInfo);
936 
937     /* Check the supplied address range. */
938     returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.sectorCmdAddressAligment);
939     if (returnCode)
940     {
941         return returnCode;
942     }
943 
944     /* Validate the user key */
945     returnCode = flash_check_user_key(key);
946     if (returnCode)
947     {
948         return returnCode;
949     }
950 
951     start = flashOperationInfo.convertedAddress;
952     sectorSize = flashOperationInfo.activeSectorSize;
953 
954     /* calculating Flash end address */
955     endAddress = start + lengthInBytes - 1;
956 
957     /* re-calculate the endAddress and align it to the start of the next sector
958      * which will be used in the comparison below */
959     if (endAddress % sectorSize)
960     {
961         numberOfSectors = endAddress / sectorSize + 1;
962         endAddress = numberOfSectors * sectorSize - 1;
963     }
964 
965     flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
966 
967     /* the start address will increment to the next sector address
968      * until it reaches the endAdddress */
969     while (start <= endAddress)
970     {
971         /* preparing passing parameter to erase a flash block */
972         kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_ERASE_SECTOR, start);
973 
974         /* calling flash command sequence function to execute the command */
975         returnCode = flash_command_sequence(config);
976 
977         /* checking the success of command execution */
978         if (kStatus_FLASH_Success != returnCode)
979         {
980             break;
981         }
982         else
983         {
984             /* Increment to the next sector */
985             start += sectorSize;
986         }
987     }
988 
989     flash_cache_clear(config);
990 
991     return (returnCode);
992 }
993 
994 #if defined(FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD) && FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD
FLASH_EraseAllUnsecure(flash_config_t * config,uint32_t key)995 status_t FLASH_EraseAllUnsecure(flash_config_t *config, uint32_t key)
996 {
997     status_t returnCode;
998 
999     if (config == NULL)
1000     {
1001         return kStatus_FLASH_InvalidArgument;
1002     }
1003 
1004     /* Prepare passing parameter to erase all flash blocks (unsecure). */
1005     kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_ERASE_ALL_BLOCK_UNSECURE, 0xFFFFFFU);
1006 
1007     /* Validate the user key */
1008     returnCode = flash_check_user_key(key);
1009     if (returnCode)
1010     {
1011         return returnCode;
1012     }
1013 
1014     flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
1015 
1016     /* calling flash command sequence function to execute the command */
1017     returnCode = flash_command_sequence(config);
1018 
1019     flash_cache_clear(config);
1020 
1021 #if FLASH_SSD_IS_FLEXNVM_ENABLED
1022     /* Data flash IFR will be erased by erase all unsecure command, so we need to
1023      *  update FlexNVM memory partition status synchronously */
1024     if (returnCode == kStatus_FLASH_Success)
1025     {
1026         returnCode = flash_update_flexnvm_memory_partition_status(config);
1027     }
1028 #endif
1029 
1030     return returnCode;
1031 }
1032 #endif /* FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD */
1033 
FLASH_EraseAllExecuteOnlySegments(flash_config_t * config,uint32_t key)1034 status_t FLASH_EraseAllExecuteOnlySegments(flash_config_t *config, uint32_t key)
1035 {
1036     status_t returnCode;
1037 
1038     if (config == NULL)
1039     {
1040         return kStatus_FLASH_InvalidArgument;
1041     }
1042 
1043     /* preparing passing parameter to erase all execute-only segments
1044      * 1st element for the FCCOB register */
1045     kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_ERASE_ALL_EXECUTE_ONLY_SEGMENT, 0xFFFFFFU);
1046 
1047     /* Validate the user key */
1048     returnCode = flash_check_user_key(key);
1049     if (returnCode)
1050     {
1051         return returnCode;
1052     }
1053 
1054     flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
1055 
1056     /* calling flash command sequence function to execute the command */
1057     returnCode = flash_command_sequence(config);
1058 
1059     flash_cache_clear(config);
1060 
1061     return returnCode;
1062 }
1063 
FLASH_Program(flash_config_t * config,uint32_t start,uint32_t * src,uint32_t lengthInBytes)1064 status_t FLASH_Program(flash_config_t *config, uint32_t start, uint32_t *src, uint32_t lengthInBytes)
1065 {
1066     status_t returnCode;
1067     flash_operation_config_t flashOperationInfo;
1068 
1069     if (src == NULL)
1070     {
1071         return kStatus_FLASH_InvalidArgument;
1072     }
1073 
1074     flash_get_matched_operation_info(config, start, &flashOperationInfo);
1075 
1076     /* Check the supplied address range. */
1077     returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.blockWriteUnitSize);
1078     if (returnCode)
1079     {
1080         return returnCode;
1081     }
1082 
1083     start = flashOperationInfo.convertedAddress;
1084 
1085     flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
1086 
1087     while (lengthInBytes > 0)
1088     {
1089         /* preparing passing parameter to program the flash block */
1090         kFCCOBx[1] = *src++;
1091         if (4 == flashOperationInfo.blockWriteUnitSize)
1092         {
1093             kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_PROGRAM_LONGWORD, start);
1094         }
1095         else if (8 == flashOperationInfo.blockWriteUnitSize)
1096         {
1097             kFCCOBx[2] = *src++;
1098             kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_PROGRAM_PHRASE, start);
1099         }
1100         else
1101         {
1102         }
1103 
1104         /* calling flash command sequence function to execute the command */
1105         returnCode = flash_command_sequence(config);
1106 
1107         /* checking for the success of command execution */
1108         if (kStatus_FLASH_Success != returnCode)
1109         {
1110             break;
1111         }
1112         else
1113         {
1114             /* update start address for next iteration */
1115             start += flashOperationInfo.blockWriteUnitSize;
1116 
1117             /* update lengthInBytes for next iteration */
1118             lengthInBytes -= flashOperationInfo.blockWriteUnitSize;
1119         }
1120     }
1121 
1122     flash_cache_clear(config);
1123 
1124     return (returnCode);
1125 }
1126 
FLASH_ProgramOnce(flash_config_t * config,uint32_t index,uint32_t * src,uint32_t lengthInBytes)1127 status_t FLASH_ProgramOnce(flash_config_t *config, uint32_t index, uint32_t *src, uint32_t lengthInBytes)
1128 {
1129     status_t returnCode;
1130 
1131     if ((config == NULL) || (src == NULL))
1132     {
1133         return kStatus_FLASH_InvalidArgument;
1134     }
1135 
1136     /* pass paramters to FTFx */
1137     kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_1_2(FTFx_PROGRAM_ONCE, index, 0xFFFFU);
1138 
1139     kFCCOBx[1] = *src;
1140 
1141 /* Note: Have to seperate the first index from the rest if it equals 0
1142  * to avoid a pointless comparison of unsigned int to 0 compiler warning */
1143 #if FLASH_PROGRAM_ONCE_IS_8BYTES_UNIT_SUPPORT
1144 #if FLASH_PROGRAM_ONCE_IS_4BYTES_UNIT_SUPPORT
1145     if (((index == FLASH_PROGRAM_ONCE_MIN_ID_8BYTES) ||
1146          /* Range check */
1147          ((index >= FLASH_PROGRAM_ONCE_MIN_ID_8BYTES + 1) && (index <= FLASH_PROGRAM_ONCE_MAX_ID_8BYTES))) &&
1148         (lengthInBytes == 8))
1149 #endif /* FLASH_PROGRAM_ONCE_IS_4BYTES_UNIT_SUPPORT */
1150     {
1151         kFCCOBx[2] = *(src + 1);
1152     }
1153 #endif /* FLASH_PROGRAM_ONCE_IS_8BYTES_UNIT_SUPPORT */
1154 
1155     flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
1156 
1157     /* calling flash command sequence function to execute the command */
1158     returnCode = flash_command_sequence(config);
1159 
1160     flash_cache_clear(config);
1161 
1162     return returnCode;
1163 }
1164 
1165 #if defined(FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD) && FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD
FLASH_ProgramSection(flash_config_t * config,uint32_t start,uint32_t * src,uint32_t lengthInBytes)1166 status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint32_t *src, uint32_t lengthInBytes)
1167 {
1168     status_t returnCode;
1169     uint32_t sectorSize;
1170     flash_operation_config_t flashOperationInfo;
1171 #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD
1172     bool needSwitchFlexRamMode = false;
1173 #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */
1174 
1175     if (src == NULL)
1176     {
1177         return kStatus_FLASH_InvalidArgument;
1178     }
1179 
1180     flash_get_matched_operation_info(config, start, &flashOperationInfo);
1181 
1182     /* Check the supplied address range. */
1183     returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.sectionCmdAddressAligment);
1184     if (returnCode)
1185     {
1186         return returnCode;
1187     }
1188 
1189     start = flashOperationInfo.convertedAddress;
1190     sectorSize = flashOperationInfo.activeSectorSize;
1191 
1192 #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD
1193     /* Switch function of FlexRAM if needed */
1194     if (!(FTFx->FCNFG & FTFx_FCNFG_RAMRDY_MASK))
1195     {
1196         needSwitchFlexRamMode = true;
1197 
1198         returnCode = FLASH_SetFlexramFunction(config, kFLASH_FlexramFunctionOptionAvailableAsRam);
1199         if (returnCode != kStatus_FLASH_Success)
1200         {
1201             return kStatus_FLASH_SetFlexramAsRamError;
1202         }
1203     }
1204 #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */
1205 
1206     flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
1207 
1208     while (lengthInBytes > 0)
1209     {
1210         /* Make sure the write operation doesn't span two sectors */
1211         uint32_t endAddressOfCurrentSector = ALIGN_UP(start, sectorSize);
1212         uint32_t lengthTobeProgrammedOfCurrentSector;
1213         uint32_t currentOffset = 0;
1214 
1215         if (endAddressOfCurrentSector == start)
1216         {
1217             endAddressOfCurrentSector += sectorSize;
1218         }
1219 
1220         if (lengthInBytes + start > endAddressOfCurrentSector)
1221         {
1222             lengthTobeProgrammedOfCurrentSector = endAddressOfCurrentSector - start;
1223         }
1224         else
1225         {
1226             lengthTobeProgrammedOfCurrentSector = lengthInBytes;
1227         }
1228 
1229         /* Program Current Sector */
1230         while (lengthTobeProgrammedOfCurrentSector > 0)
1231         {
1232             /* Make sure the program size doesn't exceeds Acceleration RAM size */
1233             uint32_t programSizeOfCurrentPass;
1234             uint32_t numberOfPhases;
1235 
1236             if (lengthTobeProgrammedOfCurrentSector > kFLASH_AccelerationRamSize)
1237             {
1238                 programSizeOfCurrentPass = kFLASH_AccelerationRamSize;
1239             }
1240             else
1241             {
1242                 programSizeOfCurrentPass = lengthTobeProgrammedOfCurrentSector;
1243             }
1244 
1245             /* Copy data to FlexRAM */
1246             memcpy((void *)FSL_FEATURE_FLASH_FLEX_RAM_START_ADDRESS, src + currentOffset / 4, programSizeOfCurrentPass);
1247             /* Set start address of the data to be programmed */
1248             kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_PROGRAM_SECTION, start + currentOffset);
1249             /* Set program size in terms of FEATURE_FLASH_SECTION_CMD_ADDRESS_ALIGMENT */
1250             numberOfPhases = programSizeOfCurrentPass / flashOperationInfo.sectionCmdAddressAligment;
1251 
1252             kFCCOBx[1] = BYTES_JOIN_TO_WORD_2_2(numberOfPhases, 0xFFFFU);
1253 
1254             /* Peform command sequence */
1255             returnCode = flash_command_sequence(config);
1256 
1257             if (returnCode != kStatus_FLASH_Success)
1258             {
1259                 flash_cache_clear(config);
1260                 return returnCode;
1261             }
1262 
1263             lengthTobeProgrammedOfCurrentSector -= programSizeOfCurrentPass;
1264             currentOffset += programSizeOfCurrentPass;
1265         }
1266 
1267         src += currentOffset / 4;
1268         start += currentOffset;
1269         lengthInBytes -= currentOffset;
1270     }
1271 
1272     flash_cache_clear(config);
1273 
1274 #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD
1275     /* Restore function of FlexRAM if needed. */
1276     if (needSwitchFlexRamMode)
1277     {
1278         returnCode = FLASH_SetFlexramFunction(config, kFLASH_FlexramFunctionOptionAvailableForEeprom);
1279         if (returnCode != kStatus_FLASH_Success)
1280         {
1281             return kStatus_FLASH_RecoverFlexramAsEepromError;
1282         }
1283     }
1284 #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */
1285 
1286     return returnCode;
1287 }
1288 #endif /* FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD */
1289 
1290 #if FLASH_SSD_IS_FLEXNVM_ENABLED
FLASH_EepromWrite(flash_config_t * config,uint32_t start,uint8_t * src,uint32_t lengthInBytes)1291 status_t FLASH_EepromWrite(flash_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes)
1292 {
1293     status_t returnCode;
1294     bool needSwitchFlexRamMode = false;
1295 
1296     if (config == NULL)
1297     {
1298         return kStatus_FLASH_InvalidArgument;
1299     }
1300 
1301     /* Validates the range of the given address */
1302     if ((start < config->FlexRAMBlockBase) ||
1303         ((start + lengthInBytes) > (config->FlexRAMBlockBase + config->EEpromTotalSize)))
1304     {
1305         return kStatus_FLASH_AddressError;
1306     }
1307 
1308     returnCode = kStatus_FLASH_Success;
1309 
1310     /* Switch function of FlexRAM if needed */
1311     if (!(FTFx->FCNFG & FTFx_FCNFG_EEERDY_MASK))
1312     {
1313         needSwitchFlexRamMode = true;
1314 
1315         returnCode = FLASH_SetFlexramFunction(config, kFLASH_FlexramFunctionOptionAvailableForEeprom);
1316         if (returnCode != kStatus_FLASH_Success)
1317         {
1318             return kStatus_FLASH_SetFlexramAsEepromError;
1319         }
1320     }
1321 
1322     /* Write data to FlexRAM when it is used as EEPROM emulator */
1323     while (lengthInBytes > 0)
1324     {
1325         if ((!(start & 0x3U)) && (lengthInBytes >= 4))
1326         {
1327             *(uint32_t *)start = *(uint32_t *)src;
1328             start += 4;
1329             src += 4;
1330             lengthInBytes -= 4;
1331         }
1332         else if ((!(start & 0x1U)) && (lengthInBytes >= 2))
1333         {
1334             *(uint16_t *)start = *(uint16_t *)src;
1335             start += 2;
1336             src += 2;
1337             lengthInBytes -= 2;
1338         }
1339         else
1340         {
1341             *(uint8_t *)start = *src;
1342             start += 1;
1343             src += 1;
1344             lengthInBytes -= 1;
1345         }
1346         /* Wait till EEERDY bit is set */
1347         while (!(FTFx->FCNFG & FTFx_FCNFG_EEERDY_MASK))
1348         {
1349         }
1350 
1351         /* Check for protection violation error */
1352         if (FTFx->FSTAT & FTFx_FSTAT_FPVIOL_MASK)
1353         {
1354             return kStatus_FLASH_ProtectionViolation;
1355         }
1356     }
1357 
1358     /* Switch function of FlexRAM if needed */
1359     if (needSwitchFlexRamMode)
1360     {
1361         returnCode = FLASH_SetFlexramFunction(config, kFLASH_FlexramFunctionOptionAvailableAsRam);
1362         if (returnCode != kStatus_FLASH_Success)
1363         {
1364             return kStatus_FLASH_RecoverFlexramAsRamError;
1365         }
1366     }
1367 
1368     return returnCode;
1369 }
1370 #endif /* FLASH_SSD_IS_FLEXNVM_ENABLED */
1371 
1372 #if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD
FLASH_ReadResource(flash_config_t * config,uint32_t start,uint32_t * dst,uint32_t lengthInBytes,flash_read_resource_option_t option)1373 status_t FLASH_ReadResource(
1374     flash_config_t *config, uint32_t start, uint32_t *dst, uint32_t lengthInBytes, flash_read_resource_option_t option)
1375 {
1376     status_t returnCode;
1377     flash_operation_config_t flashOperationInfo;
1378 
1379     if ((config == NULL) || (dst == NULL))
1380     {
1381         return kStatus_FLASH_InvalidArgument;
1382     }
1383 
1384     flash_get_matched_operation_info(config, start, &flashOperationInfo);
1385 
1386     /* Check the supplied address range. */
1387     returnCode =
1388         flash_check_resource_range(start, lengthInBytes, flashOperationInfo.resourceCmdAddressAligment, option);
1389     if (returnCode != kStatus_FLASH_Success)
1390     {
1391         return returnCode;
1392     }
1393 
1394     while (lengthInBytes > 0)
1395     {
1396         /* preparing passing parameter */
1397         kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_READ_RESOURCE, start);
1398         if (flashOperationInfo.resourceCmdAddressAligment == 4)
1399         {
1400             kFCCOBx[2] = BYTES_JOIN_TO_WORD_1_3(option, 0xFFFFFFU);
1401         }
1402         else if (flashOperationInfo.resourceCmdAddressAligment == 8)
1403         {
1404             kFCCOBx[1] = BYTES_JOIN_TO_WORD_1_3(option, 0xFFFFFFU);
1405         }
1406         else
1407         {
1408         }
1409 
1410         /* calling flash command sequence function to execute the command */
1411         returnCode = flash_command_sequence(config);
1412 
1413         if (kStatus_FLASH_Success != returnCode)
1414         {
1415             break;
1416         }
1417 
1418         /* fetch data */
1419         *dst++ = kFCCOBx[1];
1420         if (flashOperationInfo.resourceCmdAddressAligment == 8)
1421         {
1422             *dst++ = kFCCOBx[2];
1423         }
1424         /* update start address for next iteration */
1425         start += flashOperationInfo.resourceCmdAddressAligment;
1426         /* update lengthInBytes for next iteration */
1427         lengthInBytes -= flashOperationInfo.resourceCmdAddressAligment;
1428     }
1429 
1430     return (returnCode);
1431 }
1432 #endif /* FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD */
1433 
FLASH_ReadOnce(flash_config_t * config,uint32_t index,uint32_t * dst,uint32_t lengthInBytes)1434 status_t FLASH_ReadOnce(flash_config_t *config, uint32_t index, uint32_t *dst, uint32_t lengthInBytes)
1435 {
1436     status_t returnCode;
1437 
1438     if ((config == NULL) || (dst == NULL))
1439     {
1440         return kStatus_FLASH_InvalidArgument;
1441     }
1442 
1443     /* pass paramters to FTFx */
1444     kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_1_2(FTFx_READ_ONCE, index, 0xFFFFU);
1445 
1446     /* calling flash command sequence function to execute the command */
1447     returnCode = flash_command_sequence(config);
1448 
1449     if (kStatus_FLASH_Success == returnCode)
1450     {
1451         *dst = kFCCOBx[1];
1452 /* Note: Have to seperate the first index from the rest if it equals 0
1453  *       to avoid a pointless comparison of unsigned int to 0 compiler warning */
1454 #if FLASH_PROGRAM_ONCE_IS_8BYTES_UNIT_SUPPORT
1455 #if FLASH_PROGRAM_ONCE_IS_4BYTES_UNIT_SUPPORT
1456         if (((index == FLASH_PROGRAM_ONCE_MIN_ID_8BYTES) ||
1457              /* Range check */
1458              ((index >= FLASH_PROGRAM_ONCE_MIN_ID_8BYTES + 1) && (index <= FLASH_PROGRAM_ONCE_MAX_ID_8BYTES))) &&
1459             (lengthInBytes == 8))
1460 #endif /* FLASH_PROGRAM_ONCE_IS_4BYTES_UNIT_SUPPORT */
1461         {
1462             *(dst + 1) = kFCCOBx[2];
1463         }
1464 #endif /* FLASH_PROGRAM_ONCE_IS_8BYTES_UNIT_SUPPORT */
1465     }
1466 
1467     return returnCode;
1468 }
1469 
FLASH_GetSecurityState(flash_config_t * config,flash_security_state_t * state)1470 status_t FLASH_GetSecurityState(flash_config_t *config, flash_security_state_t *state)
1471 {
1472     /* store data read from flash register */
1473     uint8_t registerValue;
1474 
1475     if ((config == NULL) || (state == NULL))
1476     {
1477         return kStatus_FLASH_InvalidArgument;
1478     }
1479 
1480     /* Get flash security register value */
1481     registerValue = FTFx->FSEC;
1482 
1483     /* check the status of the flash security bits in the security register */
1484     if (FLASH_SECURITY_STATE_UNSECURED == (registerValue & FTFx_FSEC_SEC_MASK))
1485     {
1486         /* Flash in unsecured state */
1487         *state = kFLASH_SecurityStateNotSecure;
1488     }
1489     else
1490     {
1491         /* Flash in secured state
1492          * check for backdoor key security enable bit */
1493         if (FLASH_SECURITY_STATE_KEYEN == (registerValue & FTFx_FSEC_KEYEN_MASK))
1494         {
1495             /* Backdoor key security enabled */
1496             *state = kFLASH_SecurityStateBackdoorEnabled;
1497         }
1498         else
1499         {
1500             /* Backdoor key security disabled */
1501             *state = kFLASH_SecurityStateBackdoorDisabled;
1502         }
1503     }
1504 
1505     return (kStatus_FLASH_Success);
1506 }
1507 
FLASH_SecurityBypass(flash_config_t * config,const uint8_t * backdoorKey)1508 status_t FLASH_SecurityBypass(flash_config_t *config, const uint8_t *backdoorKey)
1509 {
1510     uint8_t registerValue; /* registerValue */
1511     status_t returnCode;   /* return code variable */
1512 
1513     if ((config == NULL) || (backdoorKey == NULL))
1514     {
1515         return kStatus_FLASH_InvalidArgument;
1516     }
1517 
1518     /* set the default return code as kStatus_Success */
1519     returnCode = kStatus_FLASH_Success;
1520 
1521     /* Get flash security register value */
1522     registerValue = FTFx->FSEC;
1523 
1524     /* Check to see if flash is in secure state (any state other than 0x2)
1525      * If not, then skip this since flash is not secure */
1526     if (0x02 != (registerValue & 0x03))
1527     {
1528         /* preparing passing parameter to erase a flash block */
1529         kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_SECURITY_BY_PASS, 0xFFFFFFU);
1530         kFCCOBx[1] = BYTES_JOIN_TO_WORD_1_1_1_1(backdoorKey[0], backdoorKey[1], backdoorKey[2], backdoorKey[3]);
1531         kFCCOBx[2] = BYTES_JOIN_TO_WORD_1_1_1_1(backdoorKey[4], backdoorKey[5], backdoorKey[6], backdoorKey[7]);
1532 
1533         /* calling flash command sequence function to execute the command */
1534         returnCode = flash_command_sequence(config);
1535     }
1536 
1537     return (returnCode);
1538 }
1539 
FLASH_VerifyEraseAll(flash_config_t * config,flash_margin_value_t margin)1540 status_t FLASH_VerifyEraseAll(flash_config_t *config, flash_margin_value_t margin)
1541 {
1542     if (config == NULL)
1543     {
1544         return kStatus_FLASH_InvalidArgument;
1545     }
1546 
1547     /* preparing passing parameter to verify all block command */
1548     kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_1_2(FTFx_VERIFY_ALL_BLOCK, margin, 0xFFFFU);
1549 
1550     /* calling flash command sequence function to execute the command */
1551     return flash_command_sequence(config);
1552 }
1553 
FLASH_VerifyErase(flash_config_t * config,uint32_t start,uint32_t lengthInBytes,flash_margin_value_t margin)1554 status_t FLASH_VerifyErase(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, flash_margin_value_t margin)
1555 {
1556     /* Check arguments. */
1557     uint32_t blockSize;
1558     flash_operation_config_t flashOperationInfo;
1559     uint32_t nextBlockStartAddress;
1560     uint32_t remainingBytes;
1561     status_t returnCode;
1562 
1563     flash_get_matched_operation_info(config, start, &flashOperationInfo);
1564 
1565     returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.sectionCmdAddressAligment);
1566     if (returnCode)
1567     {
1568         return returnCode;
1569     }
1570 
1571     flash_get_matched_operation_info(config, start, &flashOperationInfo);
1572     start = flashOperationInfo.convertedAddress;
1573     blockSize = flashOperationInfo.activeBlockSize;
1574 
1575     nextBlockStartAddress = ALIGN_UP(start, blockSize);
1576     if (nextBlockStartAddress == start)
1577     {
1578         nextBlockStartAddress += blockSize;
1579     }
1580 
1581     remainingBytes = lengthInBytes;
1582 
1583     while (remainingBytes)
1584     {
1585         uint32_t numberOfPhrases;
1586         uint32_t verifyLength = nextBlockStartAddress - start;
1587         if (verifyLength > remainingBytes)
1588         {
1589             verifyLength = remainingBytes;
1590         }
1591 
1592         numberOfPhrases = verifyLength / flashOperationInfo.sectionCmdAddressAligment;
1593 
1594         /* Fill in verify section command parameters. */
1595         kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_VERIFY_SECTION, start);
1596         kFCCOBx[1] = BYTES_JOIN_TO_WORD_2_1_1(numberOfPhrases, margin, 0xFFU);
1597 
1598         /* calling flash command sequence function to execute the command */
1599         returnCode = flash_command_sequence(config);
1600         if (returnCode)
1601         {
1602             return returnCode;
1603         }
1604 
1605         remainingBytes -= verifyLength;
1606         start += verifyLength;
1607         nextBlockStartAddress += blockSize;
1608     }
1609 
1610     return kStatus_FLASH_Success;
1611 }
1612 
FLASH_VerifyProgram(flash_config_t * config,uint32_t start,uint32_t lengthInBytes,const uint32_t * expectedData,flash_margin_value_t margin,uint32_t * failedAddress,uint32_t * failedData)1613 status_t FLASH_VerifyProgram(flash_config_t *config,
1614                              uint32_t start,
1615                              uint32_t lengthInBytes,
1616                              const uint32_t *expectedData,
1617                              flash_margin_value_t margin,
1618                              uint32_t *failedAddress,
1619                              uint32_t *failedData)
1620 {
1621     status_t returnCode;
1622     flash_operation_config_t flashOperationInfo;
1623 
1624     if (expectedData == NULL)
1625     {
1626         return kStatus_FLASH_InvalidArgument;
1627     }
1628 
1629     flash_get_matched_operation_info(config, start, &flashOperationInfo);
1630 
1631     returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.checkCmdAddressAligment);
1632     if (returnCode)
1633     {
1634         return returnCode;
1635     }
1636 
1637     start = flashOperationInfo.convertedAddress;
1638 
1639     while (lengthInBytes)
1640     {
1641         /* preparing passing parameter to program check the flash block */
1642         kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_PROGRAM_CHECK, start);
1643         kFCCOBx[1] = BYTES_JOIN_TO_WORD_1_3(margin, 0xFFFFFFU);
1644         kFCCOBx[2] = *expectedData;
1645 
1646         /* calling flash command sequence function to execute the command */
1647         returnCode = flash_command_sequence(config);
1648 
1649         /* checking for the success of command execution */
1650         if (kStatus_FLASH_Success != returnCode)
1651         {
1652             if (failedAddress)
1653             {
1654                 *failedAddress = start;
1655             }
1656             if (failedData)
1657             {
1658                 *failedData = 0;
1659             }
1660             break;
1661         }
1662 
1663         lengthInBytes -= flashOperationInfo.checkCmdAddressAligment;
1664         expectedData += flashOperationInfo.checkCmdAddressAligment / sizeof(*expectedData);
1665         start += flashOperationInfo.checkCmdAddressAligment;
1666     }
1667 
1668     return (returnCode);
1669 }
1670 
FLASH_VerifyEraseAllExecuteOnlySegments(flash_config_t * config,flash_margin_value_t margin)1671 status_t FLASH_VerifyEraseAllExecuteOnlySegments(flash_config_t *config, flash_margin_value_t margin)
1672 {
1673     if (config == NULL)
1674     {
1675         return kStatus_FLASH_InvalidArgument;
1676     }
1677 
1678     /* preparing passing parameter to verify erase all execute-only segments command */
1679     kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_1_2(FTFx_VERIFY_ALL_EXECUTE_ONLY_SEGMENT, margin, 0xFFFFU);
1680 
1681     /* calling flash command sequence function to execute the command */
1682     return flash_command_sequence(config);
1683 }
1684 
FLASH_IsProtected(flash_config_t * config,uint32_t start,uint32_t lengthInBytes,flash_protection_state_t * protection_state)1685 status_t FLASH_IsProtected(flash_config_t *config,
1686                            uint32_t start,
1687                            uint32_t lengthInBytes,
1688                            flash_protection_state_t *protection_state)
1689 {
1690     uint32_t endAddress;           /* end address for protection check */
1691     uint32_t regionCheckedCounter; /* increments each time the flash address was checked for
1692                                     * protection status */
1693     uint32_t regionCounter;        /* incrementing variable used to increment through the flash
1694                                     * protection regions */
1695     uint32_t protectStatusCounter; /* increments each time a flash region was detected as protected */
1696 
1697     uint8_t flashRegionProtectStatus[MAIN_FLASH_FEATURE_PFLASH_PROTECTION_REGION_COUNT]; /* array of the protection
1698                                                                       * status for each
1699                                                                       * protection region */
1700     uint32_t flashRegionAddress[MAIN_FLASH_FEATURE_PFLASH_PROTECTION_REGION_COUNT +
1701                                 1];                /* array of the start addresses for each flash
1702                                  * protection region. Note this is REGION_COUNT+1
1703                                  * due to requiring the next start address after
1704                                  * the end of flash for loop-check purposes below */
1705     flash_protection_config_t flashProtectionInfo; /* flash protection information */
1706     status_t returnCode;
1707 
1708     if (protection_state == NULL)
1709     {
1710         return kStatus_FLASH_InvalidArgument;
1711     }
1712 
1713     /* Check the supplied address range. */
1714     returnCode = flash_check_range(config, start, lengthInBytes, MAIN_FLASH_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE);
1715     if (returnCode)
1716     {
1717         return returnCode;
1718     }
1719 
1720     /* Get necessary flash protection information. */
1721     returnCode = flash_get_protection_info(config, &flashProtectionInfo);
1722     if (returnCode)
1723     {
1724         return returnCode;
1725     }
1726 
1727     /* calculating Flash end address */
1728     endAddress = start + lengthInBytes;
1729 
1730     /* populate the flashRegionAddress array with the start address of each flash region */
1731     regionCounter = 0; /* make sure regionCounter is initialized to 0 first */
1732 
1733     /* populate up to 33rd element of array, this is the next address after end of flash array */
1734     while (regionCounter <= flashProtectionInfo.regionCount)
1735     {
1736         flashRegionAddress[regionCounter] =
1737             flashProtectionInfo.regionBase + flashProtectionInfo.regionSize * regionCounter;
1738         regionCounter++;
1739     }
1740 
1741     /* populate flashRegionProtectStatus array with status information
1742      * Protection status for each region is stored in the FPROT[3:0] registers
1743      * Each bit represents one region of flash
1744      * 4 registers * 8-bits-per-register = 32-bits (32-regions)
1745      * The convention is:
1746      * FPROT3[bit 0] is the first protection region (start of flash memory)
1747      * FPROT0[bit 7] is the last protection region (end of flash memory)
1748      * regionCounter is used to determine which FPROT[3:0] register to check for protection status
1749      * Note: FPROT=1 means NOT protected, FPROT=0 means protected */
1750     regionCounter = 0; /* make sure regionCounter is initialized to 0 first */
1751     while (regionCounter < flashProtectionInfo.regionCount)
1752     {
1753 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER
1754         if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash)
1755         {
1756             if (regionCounter < 8)
1757             {
1758                 flashRegionProtectStatus[regionCounter] = (FTFx_FPROTSL_REG >> regionCounter) & (0x01u);
1759             }
1760             else if ((regionCounter >= 8) && (regionCounter < 16))
1761             {
1762                 flashRegionProtectStatus[regionCounter] = (FTFx_FPROTSH_REG >> (regionCounter - 8)) & (0x01u);
1763             }
1764             else
1765             {
1766                 break;
1767             }
1768         }
1769         else
1770 #endif
1771         {
1772             /* Note: So far protection region count may be 16/20/24/32/64 */
1773             if (regionCounter < 8)
1774             {
1775                 flashRegionProtectStatus[regionCounter] = (FTFx_FPROTL3_REG >> regionCounter) & (0x01u);
1776             }
1777             else if ((regionCounter >= 8) && (regionCounter < 16))
1778             {
1779                 flashRegionProtectStatus[regionCounter] = (FTFx_FPROTL2_REG >> (regionCounter - 8)) & (0x01u);
1780             }
1781 #if defined(MAIN_FLASH_FEATURE_PFLASH_PROTECTION_REGION_COUNT) && (MAIN_FLASH_FEATURE_PFLASH_PROTECTION_REGION_COUNT > 16)
1782 #if (MAIN_FLASH_FEATURE_PFLASH_PROTECTION_REGION_COUNT == 20)
1783             else if ((regionCounter >= 16) && (regionCounter < 20))
1784             {
1785                 flashRegionProtectStatus[regionCounter] = (FTFx_FPROTL1_REG >> (regionCounter - 16)) & (0x01u);
1786             }
1787 #else
1788             else if ((regionCounter >= 16) && (regionCounter < 24))
1789             {
1790                 flashRegionProtectStatus[regionCounter] = (FTFx_FPROTL1_REG >> (regionCounter - 16)) & (0x01u);
1791             }
1792 #endif /* (MAIN_FLASH_FEATURE_PFLASH_PROTECTION_REGION_COUNT == 20) */
1793 #endif
1794 #if defined(MAIN_FLASH_FEATURE_PFLASH_PROTECTION_REGION_COUNT) && (MAIN_FLASH_FEATURE_PFLASH_PROTECTION_REGION_COUNT > 24)
1795             else if ((regionCounter >= 24) && (regionCounter < 32))
1796             {
1797                 flashRegionProtectStatus[regionCounter] = (FTFx_FPROTL0_REG >> (regionCounter - 24)) & (0x01u);
1798             }
1799 #endif
1800 #if defined(MAIN_FLASH_FEATURE_PFLASH_PROTECTION_REGION_COUNT) && \
1801     (MAIN_FLASH_FEATURE_PFLASH_PROTECTION_REGION_COUNT == 64)
1802             else if (regionCounter < 40)
1803             {
1804                 flashRegionProtectStatus[regionCounter] = (FTFx_FPROTH3_REG >> (regionCounter - 32)) & (0x01u);
1805             }
1806             else if (regionCounter < 48)
1807             {
1808                 flashRegionProtectStatus[regionCounter] = (FTFx_FPROTH2_REG >> (regionCounter - 40)) & (0x01u);
1809             }
1810             else if (regionCounter < 56)
1811             {
1812                 flashRegionProtectStatus[regionCounter] = (FTFx_FPROTH1_REG >> (regionCounter - 48)) & (0x01u);
1813             }
1814             else if (regionCounter < 64)
1815             {
1816                 flashRegionProtectStatus[regionCounter] = (FTFx_FPROTH0_REG >> (regionCounter - 56)) & (0x01u);
1817             }
1818 #endif
1819             else
1820             {
1821                 break;
1822             }
1823         }
1824 
1825         regionCounter++;
1826     }
1827 
1828     /* loop through the flash regions and check
1829      * desired flash address range for protection status
1830      * loop stops when it is detected that start has exceeded the endAddress */
1831     regionCounter = 0; /* make sure regionCounter is initialized to 0 first */
1832     regionCheckedCounter = 0;
1833     protectStatusCounter = 0; /* make sure protectStatusCounter is initialized to 0 first */
1834     while (start < endAddress)
1835     {
1836         /* check to see if the address falls within this protection region
1837          * Note that if the entire flash is to be checked, the last protection
1838          * region checked would consist of the last protection start address and
1839          * the start address following the end of flash */
1840         if ((start >= flashRegionAddress[regionCounter]) && (start < flashRegionAddress[regionCounter + 1]))
1841         {
1842             /* increment regionCheckedCounter to indicate this region was checked */
1843             regionCheckedCounter++;
1844 
1845             /* check the protection status of this region
1846              * Note: FPROT=1 means NOT protected, FPROT=0 means protected */
1847             if (!flashRegionProtectStatus[regionCounter])
1848             {
1849                 /* increment protectStatusCounter to indicate this region is protected */
1850                 protectStatusCounter++;
1851             }
1852             start += flashProtectionInfo.regionSize; /* increment to an address within the next region */
1853         }
1854         regionCounter++; /* increment regionCounter to check for the next flash protection region */
1855     }
1856 
1857     /* if protectStatusCounter == 0, then no region of the desired flash region is protected */
1858     if (protectStatusCounter == 0)
1859     {
1860         *protection_state = kFLASH_ProtectionStateUnprotected;
1861     }
1862     /* if protectStatusCounter == regionCheckedCounter, then each region checked was protected */
1863     else if (protectStatusCounter == regionCheckedCounter)
1864     {
1865         *protection_state = kFLASH_ProtectionStateProtected;
1866     }
1867     /* if protectStatusCounter != regionCheckedCounter, then protection status is mixed
1868      * In other words, some regions are protected while others are unprotected */
1869     else
1870     {
1871         *protection_state = kFLASH_ProtectionStateMixed;
1872     }
1873 
1874     return (returnCode);
1875 }
1876 
FLASH_IsExecuteOnly(flash_config_t * config,uint32_t start,uint32_t lengthInBytes,flash_execute_only_access_state_t * access_state)1877 status_t FLASH_IsExecuteOnly(flash_config_t *config,
1878                              uint32_t start,
1879                              uint32_t lengthInBytes,
1880                              flash_execute_only_access_state_t *access_state)
1881 {
1882 #if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL
1883     flash_access_config_t flashAccessInfo; /* flash Execute-Only information */
1884 #endif                                     /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */
1885     status_t returnCode;
1886 
1887     if (access_state == NULL)
1888     {
1889         return kStatus_FLASH_InvalidArgument;
1890     }
1891 
1892     /* Check the supplied address range. */
1893     returnCode = flash_check_range(config, start, lengthInBytes, MAIN_FLASH_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE);
1894     if (returnCode)
1895     {
1896         return returnCode;
1897     }
1898 
1899 #if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL
1900     /* Get necessary flash Execute-Only information. */
1901     returnCode = flash_get_access_info(config, &flashAccessInfo);
1902     if (returnCode)
1903     {
1904         return returnCode;
1905     }
1906 
1907     {
1908         uint32_t executeOnlySegmentCounter = 0;
1909 
1910         /* calculating end address */
1911         uint32_t endAddress = start + lengthInBytes;
1912 
1913         /* Aligning start address and end address */
1914         uint32_t alignedStartAddress = ALIGN_DOWN(start, flashAccessInfo.SegmentSize);
1915         uint32_t alignedEndAddress = ALIGN_UP(endAddress, flashAccessInfo.SegmentSize);
1916 
1917         uint32_t segmentIndex = 0;
1918         uint32_t maxSupportedExecuteOnlySegmentCount =
1919             (alignedEndAddress - alignedStartAddress) / flashAccessInfo.SegmentSize;
1920 
1921         while (start < endAddress)
1922         {
1923             uint32_t xacc;
1924             bool isInvalidSegmentIndex = false;
1925 
1926             segmentIndex = (start - flashAccessInfo.SegmentBase) / flashAccessInfo.SegmentSize;
1927 
1928 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER
1929             if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash)
1930             {
1931                 /* For secondary flash, The two XACCS registers allow up to 16 restricted segments of equal memory size.
1932                  */
1933                 if (segmentIndex < 8)
1934                 {
1935                     xacc = *(const volatile uint8_t *)&FTFx_XACCSL_REG;
1936                 }
1937                 else if (segmentIndex < flashAccessInfo.SegmentCount)
1938                 {
1939                     xacc = *(const volatile uint8_t *)&FTFx_XACCSH_REG;
1940                     segmentIndex -= 8;
1941                 }
1942                 else
1943                 {
1944                     isInvalidSegmentIndex = true;
1945                 }
1946             }
1947             else
1948 #endif
1949             {
1950                 /* For primary flash, The eight XACC registers allow up to 64 restricted segments of equal memory size.
1951                  */
1952                 if (segmentIndex < 32)
1953                 {
1954                     xacc = *(const volatile uint32_t *)&FTFx_XACCL3_REG;
1955                 }
1956                 else if (segmentIndex < flashAccessInfo.SegmentCount)
1957                 {
1958                     xacc = *(const volatile uint32_t *)&FTFx_XACCH3_REG;
1959                     segmentIndex -= 32;
1960                 }
1961                 else
1962                 {
1963                     isInvalidSegmentIndex = true;
1964                 }
1965             }
1966 
1967             if (isInvalidSegmentIndex)
1968             {
1969                 break;
1970             }
1971 
1972             /* Determine if this address range is in a execute-only protection flash segment. */
1973             if ((~xacc) & (1u << segmentIndex))
1974             {
1975                 executeOnlySegmentCounter++;
1976             }
1977 
1978             start += flashAccessInfo.SegmentSize;
1979         }
1980 
1981         if (executeOnlySegmentCounter < 1u)
1982         {
1983             *access_state = kFLASH_AccessStateUnLimited;
1984         }
1985         else if (executeOnlySegmentCounter < maxSupportedExecuteOnlySegmentCount)
1986         {
1987             *access_state = kFLASH_AccessStateMixed;
1988         }
1989         else
1990         {
1991             *access_state = kFLASH_AccessStateExecuteOnly;
1992         }
1993     }
1994 #else
1995     *access_state = kFLASH_AccessStateUnLimited;
1996 #endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */
1997 
1998     return (returnCode);
1999 }
2000 
FLASH_GetProperty(flash_config_t * config,flash_property_tag_t whichProperty,uint32_t * value)2001 status_t FLASH_GetProperty(flash_config_t *config, flash_property_tag_t whichProperty, uint32_t *value)
2002 {
2003     if ((config == NULL) || (value == NULL))
2004     {
2005         return kStatus_FLASH_InvalidArgument;
2006     }
2007 
2008     switch (whichProperty)
2009     {
2010         case kFLASH_PropertyPflashSectorSize:
2011             *value = config->PFlashSectorSize;
2012             break;
2013 
2014         case kFLASH_PropertyPflashTotalSize:
2015             *value = config->PFlashTotalSize;
2016             break;
2017 
2018         case kFLASH_PropertyPflashBlockSize:
2019             *value = config->PFlashTotalSize / (uint32_t)config->PFlashBlockCount;
2020             break;
2021 
2022         case kFLASH_PropertyPflashBlockCount:
2023             *value = (uint32_t)config->PFlashBlockCount;
2024             break;
2025 
2026         case kFLASH_PropertyPflashBlockBaseAddr:
2027             *value = config->PFlashBlockBase;
2028             break;
2029 
2030         case kFLASH_PropertyPflashFacSupport:
2031 #if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL)
2032             *value = FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL;
2033 #else
2034             *value = 0;
2035 #endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */
2036             break;
2037 
2038         case kFLASH_PropertyPflashAccessSegmentSize:
2039             *value = config->PFlashAccessSegmentSize;
2040             break;
2041 
2042         case kFLASH_PropertyPflashAccessSegmentCount:
2043             *value = config->PFlashAccessSegmentCount;
2044             break;
2045 
2046         case kFLASH_PropertyFlexRamBlockBaseAddr:
2047             *value = config->FlexRAMBlockBase;
2048             break;
2049 
2050         case kFLASH_PropertyFlexRamTotalSize:
2051             *value = config->FlexRAMTotalSize;
2052             break;
2053 
2054 #if FLASH_SSD_IS_FLEXNVM_ENABLED
2055         case kFLASH_PropertyDflashSectorSize:
2056             *value = FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_SECTOR_SIZE;
2057             break;
2058         case kFLASH_PropertyDflashTotalSize:
2059             *value = config->DFlashTotalSize;
2060             break;
2061         case kFLASH_PropertyDflashBlockSize:
2062             *value = FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_SIZE;
2063             break;
2064         case kFLASH_PropertyDflashBlockCount:
2065             *value = FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_COUNT;
2066             break;
2067         case kFLASH_PropertyDflashBlockBaseAddr:
2068             *value = config->DFlashBlockBase;
2069             break;
2070         case kFLASH_PropertyEepromTotalSize:
2071             *value = config->EEpromTotalSize;
2072             break;
2073 #endif /* FLASH_SSD_IS_FLEXNVM_ENABLED */
2074 
2075         default: /* catch inputs that are not recognized */
2076             return kStatus_FLASH_UnknownProperty;
2077     }
2078 
2079     return kStatus_FLASH_Success;
2080 }
2081 
FLASH_SetProperty(flash_config_t * config,flash_property_tag_t whichProperty,uint32_t value)2082 status_t FLASH_SetProperty(flash_config_t *config, flash_property_tag_t whichProperty, uint32_t value)
2083 {
2084     status_t status = kStatus_FLASH_Success;
2085 
2086     if (config == NULL)
2087     {
2088         return kStatus_FLASH_InvalidArgument;
2089     }
2090 
2091     switch (whichProperty)
2092     {
2093 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED
2094         case kFLASH_PropertyFlashMemoryIndex:
2095             if ((value != (uint32_t)kFLASH_MemoryIndexPrimaryFlash) &&
2096                 (value != (uint32_t)kFLASH_MemoryIndexSecondaryFlash))
2097             {
2098                 return kStatus_FLASH_InvalidPropertyValue;
2099             }
2100             config->FlashMemoryIndex = (uint8_t)value;
2101             break;
2102 #endif /* FLASH_SSD_IS_SECONDARY_FLASH_ENABLED */
2103 
2104         case kFLASH_PropertyPflashSectorSize:
2105         case kFLASH_PropertyPflashTotalSize:
2106         case kFLASH_PropertyPflashBlockSize:
2107         case kFLASH_PropertyPflashBlockCount:
2108         case kFLASH_PropertyPflashBlockBaseAddr:
2109         case kFLASH_PropertyPflashFacSupport:
2110         case kFLASH_PropertyPflashAccessSegmentSize:
2111         case kFLASH_PropertyPflashAccessSegmentCount:
2112         case kFLASH_PropertyFlexRamBlockBaseAddr:
2113         case kFLASH_PropertyFlexRamTotalSize:
2114 #if FLASH_SSD_IS_FLEXNVM_ENABLED
2115         case kFLASH_PropertyDflashSectorSize:
2116         case kFLASH_PropertyDflashTotalSize:
2117         case kFLASH_PropertyDflashBlockSize:
2118         case kFLASH_PropertyDflashBlockCount:
2119         case kFLASH_PropertyDflashBlockBaseAddr:
2120         case kFLASH_PropertyEepromTotalSize:
2121 #endif /* FLASH_SSD_IS_FLEXNVM_ENABLED */
2122             status = kStatus_FLASH_ReadOnlyProperty;
2123             break;
2124         default: /* catch inputs that are not recognized */
2125             status = kStatus_FLASH_UnknownProperty;
2126             break;
2127     }
2128 
2129     return status;
2130 }
2131 
2132 #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD
FLASH_SetFlexramFunction(flash_config_t * config,flash_flexram_function_option_t option)2133 status_t FLASH_SetFlexramFunction(flash_config_t *config, flash_flexram_function_option_t option)
2134 {
2135     status_t status;
2136 
2137     if (config == NULL)
2138     {
2139         return kStatus_FLASH_InvalidArgument;
2140     }
2141 
2142     status = flasn_check_flexram_function_option_range(option);
2143     if (status != kStatus_FLASH_Success)
2144     {
2145         return status;
2146     }
2147 
2148     /* preparing passing parameter to verify all block command */
2149     kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_1_2(FTFx_SET_FLEXRAM_FUNCTION, option, 0xFFFFU);
2150 
2151     /* calling flash command sequence function to execute the command */
2152     return flash_command_sequence(config);
2153 }
2154 #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */
2155 
2156 #if defined(FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD) && FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD
FLASH_SwapControl(flash_config_t * config,uint32_t address,flash_swap_control_option_t option,flash_swap_state_config_t * returnInfo)2157 status_t FLASH_SwapControl(flash_config_t *config,
2158                            uint32_t address,
2159                            flash_swap_control_option_t option,
2160                            flash_swap_state_config_t *returnInfo)
2161 {
2162     status_t returnCode;
2163 
2164     if ((config == NULL) || (returnInfo == NULL))
2165     {
2166         return kStatus_FLASH_InvalidArgument;
2167     }
2168 
2169     if (address & (FSL_FEATURE_FLASH_PFLASH_SWAP_CONTROL_CMD_ADDRESS_ALIGMENT - 1))
2170     {
2171         return kStatus_FLASH_AlignmentError;
2172     }
2173 
2174     /* Make sure address provided is in the lower half of Program flash but not in the Flash Configuration Field */
2175     if ((address >= (config->PFlashTotalSize / 2)) ||
2176         ((address >= kFLASH_ConfigAreaStart) && (address <= kFLASH_ConfigAreaEnd)))
2177     {
2178         return kStatus_FLASH_SwapIndicatorAddressError;
2179     }
2180 
2181     /* Check the option. */
2182     returnCode = flash_check_swap_control_option(option);
2183     if (returnCode)
2184     {
2185         return returnCode;
2186     }
2187 
2188     kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_SWAP_CONTROL, address);
2189     kFCCOBx[1] = BYTES_JOIN_TO_WORD_1_3(option, 0xFFFFFFU);
2190 
2191     returnCode = flash_command_sequence(config);
2192 
2193     returnInfo->flashSwapState = (flash_swap_state_t)FTFx_FCCOB5_REG;
2194     returnInfo->currentSwapBlockStatus = (flash_swap_block_status_t)FTFx_FCCOB6_REG;
2195     returnInfo->nextSwapBlockStatus = (flash_swap_block_status_t)FTFx_FCCOB7_REG;
2196 
2197     return returnCode;
2198 }
2199 #endif /* FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD */
2200 
2201 #if defined(FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP) && FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP
FLASH_Swap(flash_config_t * config,uint32_t address,flash_swap_function_option_t option)2202 status_t FLASH_Swap(flash_config_t *config, uint32_t address, flash_swap_function_option_t option)
2203 {
2204     flash_swap_state_config_t returnInfo;
2205     status_t returnCode;
2206 
2207     memset(&returnInfo, 0xFFU, sizeof(returnInfo));
2208 
2209     do
2210     {
2211         returnCode = FLASH_SwapControl(config, address, kFLASH_SwapControlOptionReportStatus, &returnInfo);
2212         if (returnCode != kStatus_FLASH_Success)
2213         {
2214             return returnCode;
2215         }
2216 
2217         if (kFLASH_SwapFunctionOptionDisable == option)
2218         {
2219             if (returnInfo.flashSwapState == kFLASH_SwapStateDisabled)
2220             {
2221                 return kStatus_FLASH_Success;
2222             }
2223             else if (returnInfo.flashSwapState == kFLASH_SwapStateUninitialized)
2224             {
2225                 /* The swap system changed to the DISABLED state with Program flash block 0
2226                  * located at relative flash address 0x0_0000 */
2227                 returnCode = FLASH_SwapControl(config, address, kFLASH_SwapControlOptionDisableSystem, &returnInfo);
2228             }
2229             else
2230             {
2231                 /* Swap disable should be requested only when swap system is in the uninitialized state */
2232                 return kStatus_FLASH_SwapSystemNotInUninitialized;
2233             }
2234         }
2235         else
2236         {
2237             /* When first swap: the initial swap state is Uninitialized, flash swap inidicator address is unset,
2238              *    the swap procedure should be Uninitialized -> Update-Erased -> Complete.
2239              * After the first swap has been completed, the flash swap inidicator address cannot be modified
2240              *    unless EraseAllBlocks command is issued, the swap procedure is changed to Update -> Update-Erased ->
2241              *    Complete. */
2242             switch (returnInfo.flashSwapState)
2243             {
2244                 case kFLASH_SwapStateUninitialized:
2245                     /* If current swap mode is Uninitialized, Initialize Swap to Initialized/READY state. */
2246                     returnCode =
2247                         FLASH_SwapControl(config, address, kFLASH_SwapControlOptionIntializeSystem, &returnInfo);
2248                     break;
2249                 case kFLASH_SwapStateReady:
2250                     /* Validate whether the address provided to the swap system is matched to
2251                      * swap indicator address in the IFR */
2252                     returnCode = flash_validate_swap_indicator_address(config, address);
2253                     if (returnCode == kStatus_FLASH_Success)
2254                     {
2255                         /* If current swap mode is Initialized/Ready, Initialize Swap to UPDATE state. */
2256                         returnCode =
2257                             FLASH_SwapControl(config, address, kFLASH_SwapControlOptionSetInUpdateState, &returnInfo);
2258                     }
2259                     break;
2260                 case kFLASH_SwapStateUpdate:
2261                     /* If current swap mode is Update, Erase indicator sector in non active block
2262                      * to proceed swap system to update-erased state */
2263                     returnCode = FLASH_Erase(config, address + (config->PFlashTotalSize >> 1),
2264                                              FSL_FEATURE_FLASH_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT, kFLASH_ApiEraseKey);
2265                     break;
2266                 case kFLASH_SwapStateUpdateErased:
2267                     /* If current swap mode is Update or Update-Erased, progress Swap to COMPLETE State */
2268                     returnCode =
2269                         FLASH_SwapControl(config, address, kFLASH_SwapControlOptionSetInCompleteState, &returnInfo);
2270                     break;
2271                 case kFLASH_SwapStateComplete:
2272                     break;
2273                 case kFLASH_SwapStateDisabled:
2274                     /* When swap system is in disabled state, We need to clear swap system back to uninitialized
2275                      * by issuing EraseAllBlocks command */
2276                     returnCode = kStatus_FLASH_SwapSystemNotInUninitialized;
2277                     break;
2278                 default:
2279                     returnCode = kStatus_FLASH_InvalidArgument;
2280                     break;
2281             }
2282         }
2283         if (returnCode != kStatus_FLASH_Success)
2284         {
2285             break;
2286         }
2287     } while (!((kFLASH_SwapStateComplete == returnInfo.flashSwapState) && (kFLASH_SwapFunctionOptionEnable == option)));
2288 
2289     return returnCode;
2290 }
2291 #endif /* FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP */
2292 
2293 #if defined(FSL_FEATURE_FLASH_HAS_PROGRAM_PARTITION_CMD) && FSL_FEATURE_FLASH_HAS_PROGRAM_PARTITION_CMD
FLASH_ProgramPartition(flash_config_t * config,flash_partition_flexram_load_option_t option,uint32_t eepromDataSizeCode,uint32_t flexnvmPartitionCode)2294 status_t FLASH_ProgramPartition(flash_config_t *config,
2295                                 flash_partition_flexram_load_option_t option,
2296                                 uint32_t eepromDataSizeCode,
2297                                 uint32_t flexnvmPartitionCode)
2298 {
2299     status_t returnCode;
2300 
2301     if (config == NULL)
2302     {
2303         return kStatus_FLASH_InvalidArgument;
2304     }
2305 
2306     /* eepromDataSizeCode[7:6], flexnvmPartitionCode[7:4] should be all 1'b0
2307      *  or it will cause access error. */
2308     /* eepromDataSizeCode &= 0x3FU;  */
2309     /* flexnvmPartitionCode &= 0x0FU; */
2310 
2311     /* preparing passing parameter to program the flash block */
2312     kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_2_1(FTFx_PROGRAM_PARTITION, 0xFFFFU, option);
2313     kFCCOBx[1] = BYTES_JOIN_TO_WORD_1_1_2(eepromDataSizeCode, flexnvmPartitionCode, 0xFFFFU);
2314 
2315     flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
2316 
2317     /* calling flash command sequence function to execute the command */
2318     returnCode = flash_command_sequence(config);
2319 
2320     flash_cache_clear(config);
2321 
2322 #if FLASH_SSD_IS_FLEXNVM_ENABLED
2323     /* Data flash IFR will be updated by program partition command during reset sequence,
2324      * so we just set reserved values for partitioned FlexNVM size here */
2325     config->EEpromTotalSize = FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_RESERVED;
2326     config->DFlashTotalSize = FLEX_NVM_DFLASH_SIZE_FOR_DEPART_RESERVED;
2327 #endif
2328 
2329     return (returnCode);
2330 }
2331 #endif /* FSL_FEATURE_FLASH_HAS_PROGRAM_PARTITION_CMD */
2332 
FLASH_PflashSetProtection(flash_config_t * config,pflash_protection_status_t * protectStatus)2333 status_t FLASH_PflashSetProtection(flash_config_t *config, pflash_protection_status_t *protectStatus)
2334 {
2335     if (config == NULL)
2336     {
2337         return kStatus_FLASH_InvalidArgument;
2338     }
2339 
2340 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER
2341     if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash)
2342     {
2343         *kFPROTSL = protectStatus->valueLow32b.prots16b.protsl;
2344         if (protectStatus->valueLow32b.prots16b.protsl != *kFPROTSL)
2345         {
2346             return kStatus_FLASH_CommandFailure;
2347         }
2348 
2349         *kFPROTSH = protectStatus->valueLow32b.prots16b.protsh;
2350         if (protectStatus->valueLow32b.prots16b.protsh != *kFPROTSH)
2351         {
2352             return kStatus_FLASH_CommandFailure;
2353         }
2354     }
2355     else
2356 #endif
2357     {
2358         *kFPROTL = protectStatus->valueLow32b.protl32b;
2359         if (protectStatus->valueLow32b.protl32b != *kFPROTL)
2360         {
2361             return kStatus_FLASH_CommandFailure;
2362         }
2363 
2364 #if defined(FTFx_FPROT_HIGH_REG)
2365         *kFPROTH = protectStatus->valueHigh32b.proth32b;
2366         if (protectStatus->valueHigh32b.proth32b != *kFPROTH)
2367         {
2368             return kStatus_FLASH_CommandFailure;
2369         }
2370 #endif
2371     }
2372 
2373     return kStatus_FLASH_Success;
2374 }
2375 
FLASH_PflashGetProtection(flash_config_t * config,pflash_protection_status_t * protectStatus)2376 status_t FLASH_PflashGetProtection(flash_config_t *config, pflash_protection_status_t *protectStatus)
2377 {
2378     if ((config == NULL) || (protectStatus == NULL))
2379     {
2380         return kStatus_FLASH_InvalidArgument;
2381     }
2382 
2383 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER
2384     if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash)
2385     {
2386         protectStatus->valueLow32b.prots16b.protsl = *kFPROTSL;
2387         protectStatus->valueLow32b.prots16b.protsh = *kFPROTSH;
2388     }
2389     else
2390 #endif
2391     {
2392         protectStatus->valueLow32b.protl32b = *kFPROTL;
2393 #if defined(FTFx_FPROT_HIGH_REG)
2394         protectStatus->valueHigh32b.proth32b = *kFPROTH;
2395 #endif
2396     }
2397 
2398     return kStatus_FLASH_Success;
2399 }
2400 
2401 #if FLASH_SSD_IS_FLEXNVM_ENABLED
FLASH_DflashSetProtection(flash_config_t * config,uint8_t protectStatus)2402 status_t FLASH_DflashSetProtection(flash_config_t *config, uint8_t protectStatus)
2403 {
2404     if (config == NULL)
2405     {
2406         return kStatus_FLASH_InvalidArgument;
2407     }
2408 
2409     if ((config->DFlashTotalSize == 0) || (config->DFlashTotalSize == FLEX_NVM_DFLASH_SIZE_FOR_DEPART_RESERVED))
2410     {
2411         return kStatus_FLASH_CommandNotSupported;
2412     }
2413 
2414     FTFx->FDPROT = protectStatus;
2415 
2416     if (FTFx->FDPROT != protectStatus)
2417     {
2418         return kStatus_FLASH_CommandFailure;
2419     }
2420 
2421     return kStatus_FLASH_Success;
2422 }
2423 #endif /* FLASH_SSD_IS_FLEXNVM_ENABLED */
2424 
2425 #if FLASH_SSD_IS_FLEXNVM_ENABLED
FLASH_DflashGetProtection(flash_config_t * config,uint8_t * protectStatus)2426 status_t FLASH_DflashGetProtection(flash_config_t *config, uint8_t *protectStatus)
2427 {
2428     if ((config == NULL) || (protectStatus == NULL))
2429     {
2430         return kStatus_FLASH_InvalidArgument;
2431     }
2432 
2433     if ((config->DFlashTotalSize == 0) || (config->DFlashTotalSize == FLEX_NVM_DFLASH_SIZE_FOR_DEPART_RESERVED))
2434     {
2435         return kStatus_FLASH_CommandNotSupported;
2436     }
2437 
2438     *protectStatus = FTFx->FDPROT;
2439 
2440     return kStatus_FLASH_Success;
2441 }
2442 #endif /* FLASH_SSD_IS_FLEXNVM_ENABLED */
2443 
2444 #if FLASH_SSD_IS_FLEXNVM_ENABLED
FLASH_EepromSetProtection(flash_config_t * config,uint8_t protectStatus)2445 status_t FLASH_EepromSetProtection(flash_config_t *config, uint8_t protectStatus)
2446 {
2447     if (config == NULL)
2448     {
2449         return kStatus_FLASH_InvalidArgument;
2450     }
2451 
2452     if ((config->EEpromTotalSize == 0) || (config->EEpromTotalSize == FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_RESERVED))
2453     {
2454         return kStatus_FLASH_CommandNotSupported;
2455     }
2456 
2457     FTFx->FEPROT = protectStatus;
2458 
2459     if (FTFx->FEPROT != protectStatus)
2460     {
2461         return kStatus_FLASH_CommandFailure;
2462     }
2463 
2464     return kStatus_FLASH_Success;
2465 }
2466 #endif /* FLASH_SSD_IS_FLEXNVM_ENABLED */
2467 
2468 #if FLASH_SSD_IS_FLEXNVM_ENABLED
FLASH_EepromGetProtection(flash_config_t * config,uint8_t * protectStatus)2469 status_t FLASH_EepromGetProtection(flash_config_t *config, uint8_t *protectStatus)
2470 {
2471     if ((config == NULL) || (protectStatus == NULL))
2472     {
2473         return kStatus_FLASH_InvalidArgument;
2474     }
2475 
2476     if ((config->EEpromTotalSize == 0) || (config->EEpromTotalSize == FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_RESERVED))
2477     {
2478         return kStatus_FLASH_CommandNotSupported;
2479     }
2480 
2481     *protectStatus = FTFx->FEPROT;
2482 
2483     return kStatus_FLASH_Success;
2484 }
2485 #endif /* FLASH_SSD_IS_FLEXNVM_ENABLED */
2486 
FLASH_PflashSetPrefetchSpeculation(flash_prefetch_speculation_status_t * speculationStatus)2487 status_t FLASH_PflashSetPrefetchSpeculation(flash_prefetch_speculation_status_t *speculationStatus)
2488 {
2489 #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM
2490     {
2491         FTFx_REG32_ACCESS_TYPE regBase;
2492 #if defined(MCM)
2493         regBase = (FTFx_REG32_ACCESS_TYPE)&MCM->PLACR;
2494 #elif defined(MCM0)
2495         regBase = (FTFx_REG32_ACCESS_TYPE)&MCM0->PLACR;
2496 #endif
2497         if (speculationStatus->instructionOption == kFLASH_prefetchSpeculationOptionDisable)
2498         {
2499             if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable)
2500             {
2501                 return kStatus_FLASH_InvalidSpeculationOption;
2502             }
2503             else
2504             {
2505                 *regBase |= MCM_PLACR_DFCS_MASK;
2506             }
2507         }
2508         else
2509         {
2510             *regBase &= ~MCM_PLACR_DFCS_MASK;
2511             if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable)
2512             {
2513                 *regBase |= MCM_PLACR_EFDS_MASK;
2514             }
2515             else
2516             {
2517                 *regBase &= ~MCM_PLACR_EFDS_MASK;
2518             }
2519         }
2520     }
2521 #elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC
2522     {
2523         FTFx_REG32_ACCESS_TYPE regBase;
2524         uint32_t b0dpeMask, b0ipeMask;
2525 #if defined(FMC_PFB01CR_B0DPE_MASK)
2526         regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB01CR;
2527         b0dpeMask = FMC_PFB01CR_B0DPE_MASK;
2528         b0ipeMask = FMC_PFB01CR_B0IPE_MASK;
2529 #elif defined(FMC_PFB0CR_B0DPE_MASK)
2530         regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB0CR;
2531         b0dpeMask = FMC_PFB0CR_B0DPE_MASK;
2532         b0ipeMask = FMC_PFB0CR_B0IPE_MASK;
2533 #endif
2534         if (speculationStatus->instructionOption == kFLASH_prefetchSpeculationOptionEnable)
2535         {
2536             *regBase |= b0ipeMask;
2537         }
2538         else
2539         {
2540             *regBase &= ~b0ipeMask;
2541         }
2542         if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable)
2543         {
2544             *regBase |= b0dpeMask;
2545         }
2546         else
2547         {
2548             *regBase &= ~b0dpeMask;
2549         }
2550 
2551 /* Invalidate Prefetch Speculation Buffer */
2552 #if defined(FMC_PFB01CR_S_INV_MASK)
2553         FMC->PFB01CR |= FMC_PFB01CR_S_INV_MASK;
2554 #elif defined(FMC_PFB01CR_S_B_INV_MASK)
2555         FMC->PFB01CR |= FMC_PFB01CR_S_B_INV_MASK;
2556 #elif defined(FMC_PFB0CR_S_INV_MASK)
2557         FMC->PFB0CR |= FMC_PFB0CR_S_INV_MASK;
2558 #elif defined(FMC_PFB0CR_S_B_INV_MASK)
2559         FMC->PFB0CR |= FMC_PFB0CR_S_B_INV_MASK;
2560 #endif
2561     }
2562 #elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM
2563     {
2564         FTFx_REG32_ACCESS_TYPE regBase;
2565         uint32_t flashSpeculationMask, dataPrefetchMask;
2566         regBase = (FTFx_REG32_ACCESS_TYPE)&MSCM_OCMDR0_REG;
2567         flashSpeculationMask = MSCM_OCMDR_OCMC1_DFCS_MASK;
2568         dataPrefetchMask = MSCM_OCMDR_OCMC1_DFDS_MASK;
2569 
2570         if (speculationStatus->instructionOption == kFLASH_prefetchSpeculationOptionDisable)
2571         {
2572             if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable)
2573             {
2574                 return kStatus_FLASH_InvalidSpeculationOption;
2575             }
2576             else
2577             {
2578                 *regBase |= flashSpeculationMask;
2579             }
2580         }
2581         else
2582         {
2583             *regBase &= ~flashSpeculationMask;
2584             if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable)
2585             {
2586                 *regBase &= ~dataPrefetchMask;
2587             }
2588             else
2589             {
2590                 *regBase |= dataPrefetchMask;
2591             }
2592         }
2593     }
2594 #endif /* FSL_FEATURE_FTFx_MCM_FLASH_CACHE_CONTROLS */
2595 
2596     return kStatus_FLASH_Success;
2597 }
2598 
FLASH_PflashGetPrefetchSpeculation(flash_prefetch_speculation_status_t * speculationStatus)2599 status_t FLASH_PflashGetPrefetchSpeculation(flash_prefetch_speculation_status_t *speculationStatus)
2600 {
2601     memset(speculationStatus, 0, sizeof(flash_prefetch_speculation_status_t));
2602 
2603     /* Assuming that all speculation options are enabled. */
2604     speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionEnable;
2605     speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionEnable;
2606 
2607 #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM
2608     {
2609         uint32_t value;
2610 #if defined(MCM)
2611         value = MCM->PLACR;
2612 #elif defined(MCM0)
2613         value = MCM0->PLACR;
2614 #endif
2615         if (value & MCM_PLACR_DFCS_MASK)
2616         {
2617             /* Speculation buffer is off. */
2618             speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionDisable;
2619             speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable;
2620         }
2621         else
2622         {
2623             /* Speculation buffer is on for instruction. */
2624             if (!(value & MCM_PLACR_EFDS_MASK))
2625             {
2626                 /* Speculation buffer is off for data. */
2627                 speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable;
2628             }
2629         }
2630     }
2631 #elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC
2632     {
2633         uint32_t value;
2634         uint32_t b0dpeMask, b0ipeMask;
2635 #if defined(FMC_PFB01CR_B0DPE_MASK)
2636         value = FMC->PFB01CR;
2637         b0dpeMask = FMC_PFB01CR_B0DPE_MASK;
2638         b0ipeMask = FMC_PFB01CR_B0IPE_MASK;
2639 #elif defined(FMC_PFB0CR_B0DPE_MASK)
2640         value = FMC->PFB0CR;
2641         b0dpeMask = FMC_PFB0CR_B0DPE_MASK;
2642         b0ipeMask = FMC_PFB0CR_B0IPE_MASK;
2643 #endif
2644         if (!(value & b0dpeMask))
2645         {
2646             /* Do not prefetch in response to data references. */
2647             speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable;
2648         }
2649         if (!(value & b0ipeMask))
2650         {
2651             /* Do not prefetch in response to instruction fetches. */
2652             speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionDisable;
2653         }
2654     }
2655 #elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM
2656     {
2657         uint32_t value;
2658         uint32_t flashSpeculationMask, dataPrefetchMask;
2659         value = MSCM_OCMDR0_REG;
2660         flashSpeculationMask = MSCM_OCMDR_OCMC1_DFCS_MASK;
2661         dataPrefetchMask = MSCM_OCMDR_OCMC1_DFDS_MASK;
2662 
2663         if (value & flashSpeculationMask)
2664         {
2665             /* Speculation buffer is off. */
2666             speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionDisable;
2667             speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable;
2668         }
2669         else
2670         {
2671             /* Speculation buffer is on for instruction. */
2672             if (value & dataPrefetchMask)
2673             {
2674                 /* Speculation buffer is off for data. */
2675                 speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable;
2676             }
2677         }
2678     }
2679 #endif
2680 
2681     return kStatus_FLASH_Success;
2682 }
2683 
2684 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2685 /*!
2686  * @brief Copy PIC of flash_run_command() to RAM
2687  */
copy_flash_run_command(uint32_t * flashRunCommand)2688 static void copy_flash_run_command(uint32_t *flashRunCommand)
2689 {
2690     assert(sizeof(s_flashRunCommandFunctionCode) <= (kFLASH_ExecuteInRamFunctionMaxSizeInWords * 4));
2691 
2692     /* Since the value of ARM function pointer is always odd, but the real start address
2693      * of function memory should be even, that's why +1 operation exist. */
2694     memcpy((void *)flashRunCommand, (void *)s_flashRunCommandFunctionCode, sizeof(s_flashRunCommandFunctionCode));
2695     callFlashRunCommand = (void (*)(FTFx_REG8_ACCESS_TYPE ftfx_fstat))((uint32_t)flashRunCommand + 1);
2696 }
2697 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
2698 
2699 /*!
2700  * @brief Flash Command Sequence
2701  *
2702  * This function is used to perform the command write sequence to the flash.
2703  *
2704  * @param driver Pointer to storage for the driver runtime state.
2705  * @return An error code or kStatus_FLASH_Success
2706  */
flash_command_sequence(flash_config_t * config)2707 static status_t flash_command_sequence(flash_config_t *config)
2708 {
2709     uint8_t registerValue;
2710 
2711 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2712     /* clear RDCOLERR & ACCERR & FPVIOL flag in flash status register */
2713     FTFx->FSTAT = FTFx_FSTAT_RDCOLERR_MASK | FTFx_FSTAT_ACCERR_MASK | FTFx_FSTAT_FPVIOL_MASK;
2714 
2715     status_t returnCode = flash_check_execute_in_ram_function_info(config);
2716     if (kStatus_FLASH_Success != returnCode)
2717     {
2718         return returnCode;
2719     }
2720 
2721     /* We pass the ftfx_fstat address as a parameter to flash_run_comamnd() instead of using
2722      * pre-processed MICRO sentences or operating global variable in flash_run_comamnd()
2723      * to make sure that flash_run_command() will be compiled into position-independent code (PIC). */
2724     callFlashRunCommand((FTFx_REG8_ACCESS_TYPE)(&FTFx->FSTAT));
2725 #else
2726     /* clear RDCOLERR & ACCERR & FPVIOL flag in flash status register */
2727     FTFx->FSTAT = FTFx_FSTAT_RDCOLERR_MASK | FTFx_FSTAT_ACCERR_MASK | FTFx_FSTAT_FPVIOL_MASK;
2728 
2729     /* clear CCIF bit */
2730     FTFx->FSTAT = FTFx_FSTAT_CCIF_MASK;
2731 
2732     /* Check CCIF bit of the flash status register, wait till it is set.
2733      * IP team indicates that this loop will always complete. */
2734     while (!(FTFx->FSTAT & FTFx_FSTAT_CCIF_MASK))
2735     {
2736     }
2737 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
2738 
2739     /* Check error bits */
2740     /* Get flash status register value */
2741     registerValue = FTFx->FSTAT;
2742 
2743     /* checking access error */
2744     if (registerValue & FTFx_FSTAT_ACCERR_MASK)
2745     {
2746         return kStatus_FLASH_AccessError;
2747     }
2748     /* checking protection error */
2749     else if (registerValue & FTFx_FSTAT_FPVIOL_MASK)
2750     {
2751         return kStatus_FLASH_ProtectionViolation;
2752     }
2753     /* checking MGSTAT0 non-correctable error */
2754     else if (registerValue & FTFx_FSTAT_MGSTAT0_MASK)
2755     {
2756         return kStatus_FLASH_CommandFailure;
2757     }
2758     else
2759     {
2760         return kStatus_FLASH_Success;
2761     }
2762 }
2763 
2764 #if FLASH_DRIVER_IS_FLASH_RESIDENT && FLASH_IS_CACHE_INVALIDATION_AVAILABLE
2765 /*!
2766  * @brief Copy PIC of flash_common_bit_operation() to RAM
2767  *
2768  */
copy_flash_common_bit_operation(uint32_t * flashCommonBitOperation)2769 static void copy_flash_common_bit_operation(uint32_t *flashCommonBitOperation)
2770 {
2771     assert(sizeof(s_flashCommonBitOperationFunctionCode) <= (kFLASH_ExecuteInRamFunctionMaxSizeInWords * 4));
2772 
2773     /* Since the value of ARM function pointer is always odd, but the real start address
2774      * of function memory should be even, that's why +1 operation exist. */
2775     memcpy((void *)flashCommonBitOperation, (void *)s_flashCommonBitOperationFunctionCode,
2776            sizeof(s_flashCommonBitOperationFunctionCode));
2777     callFlashCommonBitOperation = (void (*)(FTFx_REG32_ACCESS_TYPE base, uint32_t bitMask, uint32_t bitShift,
2778                                             uint32_t bitValue))((uint32_t)flashCommonBitOperation + 1);
2779 }
2780 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT && FLASH_IS_CACHE_INVALIDATION_AVAILABLE */
2781 
2782 #if FLASH_CACHE_IS_CONTROLLED_BY_MCM
2783 /*! @brief Performs the cache clear to the flash by MCM.*/
mcm_flash_cache_clear(void)2784 void mcm_flash_cache_clear(void)
2785 {
2786     FTFx_REG32_ACCESS_TYPE regBase;
2787 
2788 #if defined(BL_TARGET_ROM) && defined(MCM0_CACHE_REG) && defined(MCM1_CACHE_REG) && \
2789     defined(FSL_FEATURE_FLASH_CURRENT_CORE_ID)
2790     {
2791         uint16_t armPartNumber = (uint16_t)((SCB->CPUID & SCB_CPUID_PARTNO_Msk) >> SCB_CPUID_PARTNO_Pos);
2792         uint32_t cortexVersion = __CORTEX_M;
2793         uint32_t coreId = FSL_FEATURE_FLASH_CURRENT_CORE_ID;
2794 #if (__CORTEX_M <= 7)
2795         /* Note: Below code only apply to dual core device */
2796         if (s_armCorePartNumberArray[cortexVersion] != armPartNumber)
2797         {
2798             coreId ^= 0x1;
2799         }
2800         regBase = s_mcmModuleAccessTypeArray[coreId];
2801 #else
2802         #error "Inapplicable ARM Cortext Version!"
2803 #endif
2804     }
2805 #elif defined(MCM0_CACHE_REG)
2806     regBase = (FTFx_REG32_ACCESS_TYPE)&MCM0_CACHE_REG;
2807 #elif defined(MCM1_CACHE_REG)
2808     regBase = (FTFx_REG32_ACCESS_TYPE)&MCM1_CACHE_REG;
2809 #endif
2810 
2811 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2812     callFlashCommonBitOperation(regBase, MCM_CACHE_CLEAR_MASK, MCM_CACHE_CLEAR_SHIFT, 1U);
2813 #else  /* !FLASH_DRIVER_IS_FLASH_RESIDENT */
2814     *regBase |= MCM_CACHE_CLEAR_MASK;
2815 
2816     /* Memory barriers for good measure.
2817      * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */
2818     __ISB();
2819     __DSB();
2820 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
2821 }
2822 #endif /* FLASH_CACHE_IS_CONTROLLED_BY_MCM */
2823 
2824 #if FLASH_CACHE_IS_CONTROLLED_BY_FMC
2825 /*! @brief Performs the cache clear to the flash by FMC.*/
fmc_flash_cache_clear(void)2826 void fmc_flash_cache_clear(void)
2827 {
2828 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2829     FTFx_REG32_ACCESS_TYPE regBase = (FTFx_REG32_ACCESS_TYPE)0;
2830 #if defined(FMC_PFB01CR_CINV_WAY_MASK)
2831     regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB01CR;
2832     callFlashCommonBitOperation(regBase, FMC_PFB01CR_CINV_WAY_MASK, FMC_PFB01CR_CINV_WAY_SHIFT, 0xFU);
2833 #else
2834     regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB0CR;
2835     callFlashCommonBitOperation(regBase, FMC_PFB0CR_CINV_WAY_MASK, FMC_PFB0CR_CINV_WAY_SHIFT, 0xFU);
2836 #endif
2837 #else /* !FLASH_DRIVER_IS_FLASH_RESIDENT */
2838 #if defined(FMC_PFB01CR_CINV_WAY_MASK)
2839     FMC->PFB01CR = (FMC->PFB01CR & ~FMC_PFB01CR_CINV_WAY_MASK) | FMC_PFB01CR_CINV_WAY(~0);
2840 #else
2841     FMC->PFB0CR = (FMC->PFB0CR & ~FMC_PFB0CR_CINV_WAY_MASK) | FMC_PFB0CR_CINV_WAY(~0);
2842 #endif
2843     /* Memory barriers for good measure.
2844      * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */
2845     __ISB();
2846     __DSB();
2847 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
2848 }
2849 #endif /* FLASH_CACHE_IS_CONTROLLED_BY_FMC */
2850 
2851 #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM
2852 /*! @brief Performs the prefetch speculation buffer clear to the flash by MSCM.*/
mscm_flash_prefetch_speculation_enable(uint32_t flashIndex,bool enable)2853 void mscm_flash_prefetch_speculation_enable(uint32_t flashIndex, bool enable)
2854 {
2855     uint8_t setValue;
2856     if (enable)
2857     {
2858         setValue = 0x0U;
2859     }
2860     else
2861     {
2862         setValue = 0x3U;
2863     }
2864 
2865 /* The OCMDR[0] is always used to prefetch main Pflash*/
2866 /* For device with FlexNVM support, the OCMDR[1] is used to prefetch Dflash.
2867  * For device with secondary flash support, the OCMDR[1] is used to prefetch secondary Pflash. */
2868 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2869     switch (flashIndex)
2870     {
2871 #if FLASH_SSD_IS_FLEXNVM_ENABLED || FLASH_SSD_IS_SECONDARY_FLASH_ENABLED
2872         case kFLASH_MemoryIndexSecondaryFlash:
2873             callFlashCommonBitOperation((FTFx_REG32_ACCESS_TYPE)&MSCM_OCMDR1_REG, MSCM_SPECULATION_DISABLE_MASK,
2874                                         MSCM_SPECULATION_DISABLE_SHIFT, setValue);
2875             break;
2876 #endif
2877         case kFLASH_MemoryIndexPrimaryFlash:
2878         default:
2879             callFlashCommonBitOperation((FTFx_REG32_ACCESS_TYPE)&MSCM_OCMDR0_REG, MSCM_SPECULATION_DISABLE_MASK,
2880                                         MSCM_SPECULATION_DISABLE_SHIFT, setValue);
2881             break;
2882     }
2883 #else /* !FLASH_DRIVER_IS_FLASH_RESIDENT */
2884     switch (flashIndex)
2885     {
2886 #if FLASH_SSD_IS_FLEXNVM_ENABLED || FLASH_SSD_IS_SECONDARY_FLASH_ENABLED
2887         case kFLASH_MemoryIndexSecondaryFlash:
2888             MSCM_OCMDR1_REG = (MSCM_OCMDR1_REG & (~MSCM_SPECULATION_DISABLE_MASK)) | MSCM_SPECULATION_DISABLE(setValue);
2889             /* Each cahce clear instaruction should be followed by below code*/
2890             __ISB();
2891             __DSB();
2892             break;
2893 #endif
2894         case kFLASH_MemoryIndexPrimaryFlash:
2895         default:
2896             MSCM_OCMDR0_REG = (MSCM_OCMDR0_REG & (~MSCM_SPECULATION_DISABLE_MASK)) | MSCM_SPECULATION_DISABLE(setValue);
2897             /* Memory barriers for good measure.
2898              * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */
2899             __ISB();
2900             __DSB();
2901             break;
2902     }
2903 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
2904 }
2905 #endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM */
2906 
2907 #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC
2908 /*! @brief Performs the prefetch speculation buffer clear to the flash by FMC.*/
fmc_flash_prefetch_speculation_clear(void)2909 void fmc_flash_prefetch_speculation_clear(void)
2910 {
2911 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2912     FTFx_REG32_ACCESS_TYPE regBase = (FTFx_REG32_ACCESS_TYPE)0;
2913 #if defined(FMC_PFB01CR_S_INV_MASK)
2914     regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB01CR;
2915     callFlashCommonBitOperation(regBase, FMC_PFB01CR_S_INV_MASK, FMC_PFB01CR_S_INV_SHIFT, 1U);
2916 #elif defined(FMC_PFB01CR_S_B_INV_MASK)
2917     regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB01CR;
2918     callFlashCommonBitOperation(regBase, FMC_PFB01CR_S_B_INV_MASK, FMC_PFB01CR_S_B_INV_SHIFT, 1U);
2919 #elif defined(FMC_PFB0CR_S_INV_MASK)
2920     regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB0CR;
2921     callFlashCommonBitOperation(regBase, FMC_PFB0CR_S_INV_MASK, FMC_PFB0CR_S_INV_SHIFT, 1U);
2922 #elif defined(FMC_PFB0CR_S_B_INV_MASK)
2923     regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB0CR;
2924     callFlashCommonBitOperation(regBase, FMC_PFB0CR_S_B_INV_MASK, FMC_PFB0CR_S_B_INV_SHIFT, 1U);
2925 #endif
2926 #else /* !FLASH_DRIVER_IS_FLASH_RESIDENT */
2927 #if defined(FMC_PFB01CR_S_INV_MASK)
2928     FMC->PFB01CR |= FMC_PFB01CR_S_INV_MASK;
2929 #elif defined(FMC_PFB01CR_S_B_INV_MASK)
2930     FMC->PFB01CR |= FMC_PFB01CR_S_B_INV_MASK;
2931 #elif defined(FMC_PFB0CR_S_INV_MASK)
2932     FMC->PFB0CR |= FMC_PFB0CR_S_INV_MASK;
2933 #elif defined(FMC_PFB0CR_S_B_INV_MASK)
2934     FMC->PFB0CR |= FMC_PFB0CR_S_B_INV_MASK;
2935 #endif
2936     /* Memory barriers for good measure.
2937      * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */
2938     __ISB();
2939     __DSB();
2940 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
2941 }
2942 #endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC */
2943 
2944 /*!
2945  * @brief Flash Cache Clear
2946  *
2947  * This function is used to perform the cache and prefetch speculation clear to the flash.
2948  */
flash_cache_clear(flash_config_t * config)2949 void flash_cache_clear(flash_config_t *config)
2950 {
2951     flash_cache_clear_process(config, kFLASH_CacheClearProcessPost);
2952 }
2953 
2954 /*!
2955  * @brief Flash Cache Clear Process
2956  *
2957  * This function is used to perform the cache and prefetch speculation clear process to the flash.
2958  */
flash_cache_clear_process(flash_config_t * config,flash_cache_clear_process_t process)2959 static void flash_cache_clear_process(flash_config_t *config, flash_cache_clear_process_t process)
2960 {
2961 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2962     status_t returnCode = flash_check_execute_in_ram_function_info(config);
2963     if (kStatus_FLASH_Success != returnCode)
2964     {
2965         return;
2966     }
2967 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
2968 
2969     /* We pass the ftfx register address as a parameter to flash_common_bit_operation() instead of using
2970      * pre-processed MACROs or a global variable in flash_common_bit_operation()
2971      * to make sure that flash_common_bit_operation() will be compiled into position-independent code (PIC). */
2972     if (process == kFLASH_CacheClearProcessPost)
2973     {
2974 #if FLASH_CACHE_IS_CONTROLLED_BY_MCM
2975         mcm_flash_cache_clear();
2976 #endif
2977 #if FLASH_CACHE_IS_CONTROLLED_BY_FMC
2978         fmc_flash_cache_clear();
2979 #endif
2980 #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM
2981         mscm_flash_prefetch_speculation_enable(config->FlashMemoryIndex, true);
2982 #endif
2983 #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC
2984         fmc_flash_prefetch_speculation_clear();
2985 #endif
2986     }
2987     if (process == kFLASH_CacheClearProcessPre)
2988     {
2989 #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM
2990         mscm_flash_prefetch_speculation_enable(config->FlashMemoryIndex, false);
2991 #endif
2992     }
2993 }
2994 
2995 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2996 /*! @brief Check whether flash execute-in-ram functions are ready  */
flash_check_execute_in_ram_function_info(flash_config_t * config)2997 static status_t flash_check_execute_in_ram_function_info(flash_config_t *config)
2998 {
2999     flash_execute_in_ram_function_config_t *flashExecuteInRamFunctionInfo;
3000 
3001     if (config == NULL)
3002     {
3003         return kStatus_FLASH_InvalidArgument;
3004     }
3005 
3006     flashExecuteInRamFunctionInfo = (flash_execute_in_ram_function_config_t *)config->flashExecuteInRamFunctionInfo;
3007 
3008     if ((config->flashExecuteInRamFunctionInfo) &&
3009         (kFLASH_ExecuteInRamFunctionTotalNum == flashExecuteInRamFunctionInfo->activeFunctionCount))
3010     {
3011         return kStatus_FLASH_Success;
3012     }
3013 
3014     return kStatus_FLASH_ExecuteInRamFunctionNotReady;
3015 }
3016 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
3017 
3018 /*! @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)3019 static status_t flash_check_range(flash_config_t *config,
3020                                   uint32_t startAddress,
3021                                   uint32_t lengthInBytes,
3022                                   uint32_t alignmentBaseline)
3023 {
3024     if (config == NULL)
3025     {
3026         return kStatus_FLASH_InvalidArgument;
3027     }
3028 
3029     /* Verify the start and length are alignmentBaseline aligned. */
3030     if ((startAddress & (alignmentBaseline - 1)) || (lengthInBytes & (alignmentBaseline - 1)))
3031     {
3032         return kStatus_FLASH_AlignmentError;
3033     }
3034 
3035     /* check for valid range of the target addresses */
3036     if (
3037 #if FLASH_SSD_IS_FLEXNVM_ENABLED
3038         ((startAddress >= config->DFlashBlockBase) &&
3039          ((startAddress + lengthInBytes) <= (config->DFlashBlockBase + config->DFlashTotalSize))) ||
3040 #endif
3041         ((startAddress >= config->PFlashBlockBase) &&
3042          ((startAddress + lengthInBytes) <= (config->PFlashBlockBase + config->PFlashTotalSize))))
3043     {
3044         return kStatus_FLASH_Success;
3045     }
3046 
3047     return kStatus_FLASH_AddressError;
3048 }
3049 
3050 /*! @brief Gets the right address, sector and block size of current flash type which is indicated by address.*/
flash_get_matched_operation_info(flash_config_t * config,uint32_t address,flash_operation_config_t * info)3051 static status_t flash_get_matched_operation_info(flash_config_t *config,
3052                                                  uint32_t address,
3053                                                  flash_operation_config_t *info)
3054 {
3055     if ((config == NULL) || (info == NULL))
3056     {
3057         return kStatus_FLASH_InvalidArgument;
3058     }
3059 
3060     /* Clean up info Structure*/
3061     memset(info, 0, sizeof(flash_operation_config_t));
3062 
3063 #if FLASH_SSD_IS_FLEXNVM_ENABLED
3064     if ((address >= config->DFlashBlockBase) && (address <= (config->DFlashBlockBase + config->DFlashTotalSize)))
3065     {
3066         /* When required by the command, address bit 23 selects between program flash memory
3067          * (=0) and data flash memory (=1).*/
3068         info->convertedAddress = address - config->DFlashBlockBase + 0x800000U;
3069         info->activeSectorSize = FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_SECTOR_SIZE;
3070         info->activeBlockSize = config->DFlashTotalSize / FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_COUNT;
3071 
3072         info->blockWriteUnitSize = FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_WRITE_UNIT_SIZE;
3073         info->sectorCmdAddressAligment = FSL_FEATURE_FLASH_FLEX_NVM_SECTOR_CMD_ADDRESS_ALIGMENT;
3074         info->sectionCmdAddressAligment = FSL_FEATURE_FLASH_FLEX_NVM_SECTION_CMD_ADDRESS_ALIGMENT;
3075         info->resourceCmdAddressAligment = FSL_FEATURE_FLASH_FLEX_NVM_RESOURCE_CMD_ADDRESS_ALIGMENT;
3076         info->checkCmdAddressAligment = FSL_FEATURE_FLASH_FLEX_NVM_CHECK_CMD_ADDRESS_ALIGMENT;
3077     }
3078     else
3079 #endif /* FLASH_SSD_IS_FLEXNVM_ENABLED */
3080     {
3081         info->convertedAddress = address - config->PFlashBlockBase;
3082         info->activeSectorSize = config->PFlashSectorSize;
3083         info->activeBlockSize = config->PFlashTotalSize / config->PFlashBlockCount;
3084 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED
3085         if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash)
3086         {
3087 #if FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER || FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER
3088             /* When required by the command, address bit 23 selects between main flash memory
3089              * (=0) and secondary flash memory (=1).*/
3090             info->convertedAddress += 0x800000U;
3091 #endif
3092             info->blockWriteUnitSize = SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE;
3093             info->sectorCmdAddressAligment = SECONDARY_FLASH_FEATURE_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT;
3094             info->sectionCmdAddressAligment = SECONDARY_FLASH_FEATURE_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT;
3095         }
3096         else
3097 #endif /* FLASH_SSD_IS_SECONDARY_FLASH_ENABLED */
3098         {
3099             info->blockWriteUnitSize = MAIN_FLASH_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE;
3100             info->sectorCmdAddressAligment = MAIN_FLASH_FEATURE_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT;
3101             info->sectionCmdAddressAligment = MAIN_FLASH_FEATURE_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT;
3102         }
3103 
3104         info->resourceCmdAddressAligment = FSL_FEATURE_FLASH_PFLASH_RESOURCE_CMD_ADDRESS_ALIGMENT;
3105         info->checkCmdAddressAligment = FSL_FEATURE_FLASH_PFLASH_CHECK_CMD_ADDRESS_ALIGMENT;
3106     }
3107 
3108     return kStatus_FLASH_Success;
3109 }
3110 
3111 /*! @brief Validates the given user key for flash erase APIs.*/
flash_check_user_key(uint32_t key)3112 static status_t flash_check_user_key(uint32_t key)
3113 {
3114     /* Validate the user key */
3115     if (key != kFLASH_ApiEraseKey)
3116     {
3117         return kStatus_FLASH_EraseKeyError;
3118     }
3119 
3120     return kStatus_FLASH_Success;
3121 }
3122 
3123 #if FLASH_SSD_IS_FLEXNVM_ENABLED
3124 /*! @brief Updates FlexNVM memory partition status according to data flash 0 IFR.*/
flash_update_flexnvm_memory_partition_status(flash_config_t * config)3125 static status_t flash_update_flexnvm_memory_partition_status(flash_config_t *config)
3126 {
3127     struct
3128     {
3129         uint32_t reserved0;
3130         uint8_t FlexNVMPartitionCode;
3131         uint8_t EEPROMDataSetSize;
3132         uint16_t reserved1;
3133     } dataIFRReadOut;
3134     status_t returnCode;
3135 
3136     if (config == NULL)
3137     {
3138         return kStatus_FLASH_InvalidArgument;
3139     }
3140 
3141 #if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD
3142     /* Get FlexNVM memory partition info from data flash IFR */
3143     returnCode = FLASH_ReadResource(config, DFLASH_IFR_READRESOURCE_START_ADDRESS, (uint32_t *)&dataIFRReadOut,
3144                                     sizeof(dataIFRReadOut), kFLASH_ResourceOptionFlashIfr);
3145     if (returnCode != kStatus_FLASH_Success)
3146     {
3147         return kStatus_FLASH_PartitionStatusUpdateFailure;
3148     }
3149 #else
3150 #error "Cannot get FlexNVM memory partition info"
3151 #endif
3152 
3153     /* Fill out partitioned EEPROM size */
3154     dataIFRReadOut.EEPROMDataSetSize &= 0x0FU;
3155     switch (dataIFRReadOut.EEPROMDataSetSize)
3156     {
3157         case 0x00U:
3158             config->EEpromTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0000;
3159             break;
3160         case 0x01U:
3161             config->EEpromTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0001;
3162             break;
3163         case 0x02U:
3164             config->EEpromTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0010;
3165             break;
3166         case 0x03U:
3167             config->EEpromTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0011;
3168             break;
3169         case 0x04U:
3170             config->EEpromTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0100;
3171             break;
3172         case 0x05U:
3173             config->EEpromTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0101;
3174             break;
3175         case 0x06U:
3176             config->EEpromTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0110;
3177             break;
3178         case 0x07U:
3179             config->EEpromTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0111;
3180             break;
3181         case 0x08U:
3182             config->EEpromTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1000;
3183             break;
3184         case 0x09U:
3185             config->EEpromTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1001;
3186             break;
3187         case 0x0AU:
3188             config->EEpromTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1010;
3189             break;
3190         case 0x0BU:
3191             config->EEpromTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1011;
3192             break;
3193         case 0x0CU:
3194             config->EEpromTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1100;
3195             break;
3196         case 0x0DU:
3197             config->EEpromTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1101;
3198             break;
3199         case 0x0EU:
3200             config->EEpromTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1110;
3201             break;
3202         case 0x0FU:
3203             config->EEpromTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1111;
3204             break;
3205         default:
3206             config->EEpromTotalSize = FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_RESERVED;
3207             break;
3208     }
3209 
3210     /* Fill out partitioned DFlash size */
3211     dataIFRReadOut.FlexNVMPartitionCode &= 0x0FU;
3212     switch (dataIFRReadOut.FlexNVMPartitionCode)
3213     {
3214         case 0x00U:
3215 #if (FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0000 != 0xFFFFFFFF)
3216             config->DFlashTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0000;
3217 #else
3218             config->DFlashTotalSize = FLEX_NVM_DFLASH_SIZE_FOR_DEPART_RESERVED;
3219 #endif /* FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0000 */
3220             break;
3221         case 0x01U:
3222 #if (FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0001 != 0xFFFFFFFF)
3223             config->DFlashTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0001;
3224 #else
3225             config->DFlashTotalSize = FLEX_NVM_DFLASH_SIZE_FOR_DEPART_RESERVED;
3226 #endif /* FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0001 */
3227             break;
3228         case 0x02U:
3229 #if (FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0010 != 0xFFFFFFFF)
3230             config->DFlashTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0010;
3231 #else
3232             config->DFlashTotalSize = FLEX_NVM_DFLASH_SIZE_FOR_DEPART_RESERVED;
3233 #endif /* FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0010 */
3234             break;
3235         case 0x03U:
3236 #if (FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0011 != 0xFFFFFFFF)
3237             config->DFlashTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0011;
3238 #else
3239             config->DFlashTotalSize = FLEX_NVM_DFLASH_SIZE_FOR_DEPART_RESERVED;
3240 #endif /* FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0011 */
3241             break;
3242         case 0x04U:
3243 #if (FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0100 != 0xFFFFFFFF)
3244             config->DFlashTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0100;
3245 #else
3246             config->DFlashTotalSize = FLEX_NVM_DFLASH_SIZE_FOR_DEPART_RESERVED;
3247 #endif /* FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0100 */
3248             break;
3249         case 0x05U:
3250 #if (FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0101 != 0xFFFFFFFF)
3251             config->DFlashTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0101;
3252 #else
3253             config->DFlashTotalSize = FLEX_NVM_DFLASH_SIZE_FOR_DEPART_RESERVED;
3254 #endif /* FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0101 */
3255             break;
3256         case 0x06U:
3257 #if (FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0110 != 0xFFFFFFFF)
3258             config->DFlashTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0110;
3259 #else
3260             config->DFlashTotalSize = FLEX_NVM_DFLASH_SIZE_FOR_DEPART_RESERVED;
3261 #endif /* FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0110 */
3262             break;
3263         case 0x07U:
3264 #if (FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0111 != 0xFFFFFFFF)
3265             config->DFlashTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0111;
3266 #else
3267             config->DFlashTotalSize = FLEX_NVM_DFLASH_SIZE_FOR_DEPART_RESERVED;
3268 #endif /* FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0111 */
3269             break;
3270         case 0x08U:
3271 #if (FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1000 != 0xFFFFFFFF)
3272             config->DFlashTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1000;
3273 #else
3274             config->DFlashTotalSize = FLEX_NVM_DFLASH_SIZE_FOR_DEPART_RESERVED;
3275 #endif /* FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1000 */
3276             break;
3277         case 0x09U:
3278 #if (FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1001 != 0xFFFFFFFF)
3279             config->DFlashTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1001;
3280 #else
3281             config->DFlashTotalSize = FLEX_NVM_DFLASH_SIZE_FOR_DEPART_RESERVED;
3282 #endif /* FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1001 */
3283             break;
3284         case 0x0AU:
3285 #if (FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1010 != 0xFFFFFFFF)
3286             config->DFlashTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1010;
3287 #else
3288             config->DFlashTotalSize = FLEX_NVM_DFLASH_SIZE_FOR_DEPART_RESERVED;
3289 #endif /* FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1010 */
3290             break;
3291         case 0x0BU:
3292 #if (FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1011 != 0xFFFFFFFF)
3293             config->DFlashTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1011;
3294 #else
3295             config->DFlashTotalSize = FLEX_NVM_DFLASH_SIZE_FOR_DEPART_RESERVED;
3296 #endif /* FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1011 */
3297             break;
3298         case 0x0CU:
3299 #if (FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1100 != 0xFFFFFFFF)
3300             config->DFlashTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1100;
3301 #else
3302             config->DFlashTotalSize = FLEX_NVM_DFLASH_SIZE_FOR_DEPART_RESERVED;
3303 #endif /* FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1100 */
3304             break;
3305         case 0x0DU:
3306 #if (FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1101 != 0xFFFFFFFF)
3307             config->DFlashTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1101;
3308 #else
3309             config->DFlashTotalSize = FLEX_NVM_DFLASH_SIZE_FOR_DEPART_RESERVED;
3310 #endif /* FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1101 */
3311             break;
3312         case 0x0EU:
3313 #if (FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1110 != 0xFFFFFFFF)
3314             config->DFlashTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1110;
3315 #else
3316             config->DFlashTotalSize = FLEX_NVM_DFLASH_SIZE_FOR_DEPART_RESERVED;
3317 #endif /* FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1110 */
3318             break;
3319         case 0x0FU:
3320 #if (FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1111 != 0xFFFFFFFF)
3321             config->DFlashTotalSize = FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1111;
3322 #else
3323             config->DFlashTotalSize = FLEX_NVM_DFLASH_SIZE_FOR_DEPART_RESERVED;
3324 #endif /* FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1111 */
3325             break;
3326         default:
3327             config->DFlashTotalSize = FLEX_NVM_DFLASH_SIZE_FOR_DEPART_RESERVED;
3328             break;
3329     }
3330 
3331     return kStatus_FLASH_Success;
3332 }
3333 #endif /* FLASH_SSD_IS_FLEXNVM_ENABLED */
3334 
3335 #if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD
3336 /*! @brief Validates the range of the given resource address.*/
flash_check_resource_range(uint32_t start,uint32_t lengthInBytes,uint32_t alignmentBaseline,flash_read_resource_option_t option)3337 static status_t flash_check_resource_range(uint32_t start,
3338                                            uint32_t lengthInBytes,
3339                                            uint32_t alignmentBaseline,
3340                                            flash_read_resource_option_t option)
3341 {
3342     status_t status;
3343     uint32_t maxReadbleAddress;
3344 
3345     if ((start & (alignmentBaseline - 1)) || (lengthInBytes & (alignmentBaseline - 1)))
3346     {
3347         return kStatus_FLASH_AlignmentError;
3348     }
3349 
3350     status = kStatus_FLASH_Success;
3351 
3352     maxReadbleAddress = start + lengthInBytes - 1;
3353     if (option == kFLASH_ResourceOptionVersionId)
3354     {
3355         if ((start != kFLASH_ResourceRangeVersionIdStart) ||
3356             ((start + lengthInBytes - 1) != kFLASH_ResourceRangeVersionIdEnd))
3357         {
3358             status = kStatus_FLASH_InvalidArgument;
3359         }
3360     }
3361     else if (option == kFLASH_ResourceOptionFlashIfr)
3362     {
3363         if (maxReadbleAddress < kFLASH_ResourceRangePflashIfrSizeInBytes)
3364         {
3365         }
3366 #if defined(FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP) && FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP
3367         else if ((start >= kFLASH_ResourceRangePflashSwapIfrStart) &&
3368                  (maxReadbleAddress <= kFLASH_ResourceRangePflashSwapIfrEnd))
3369         {
3370         }
3371 #endif /* FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP */
3372         else if ((start >= kFLASH_ResourceRangeDflashIfrStart) &&
3373                  (maxReadbleAddress <= kFLASH_ResourceRangeDflashIfrEnd))
3374         {
3375         }
3376         else
3377         {
3378             status = kStatus_FLASH_InvalidArgument;
3379         }
3380     }
3381     else
3382     {
3383         status = kStatus_FLASH_InvalidArgument;
3384     }
3385 
3386     return status;
3387 }
3388 #endif /* FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD */
3389 
3390 #if defined(FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD) && FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD
3391 /*! @brief Validates the gived swap control option.*/
flash_check_swap_control_option(flash_swap_control_option_t option)3392 static status_t flash_check_swap_control_option(flash_swap_control_option_t option)
3393 {
3394     if ((option == kFLASH_SwapControlOptionIntializeSystem) || (option == kFLASH_SwapControlOptionSetInUpdateState) ||
3395         (option == kFLASH_SwapControlOptionSetInCompleteState) || (option == kFLASH_SwapControlOptionReportStatus) ||
3396         (option == kFLASH_SwapControlOptionDisableSystem))
3397     {
3398         return kStatus_FLASH_Success;
3399     }
3400 
3401     return kStatus_FLASH_InvalidArgument;
3402 }
3403 #endif /* FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD */
3404 
3405 #if defined(FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP) && FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP
3406 /*! @brief Validates the gived address to see if it is equal to swap indicator address in pflash swap IFR.*/
flash_validate_swap_indicator_address(flash_config_t * config,uint32_t address)3407 static status_t flash_validate_swap_indicator_address(flash_config_t *config, uint32_t address)
3408 {
3409     flash_swap_ifr_field_data_t flashSwapIfrFieldData;
3410     uint32_t swapIndicatorAddress;
3411 
3412     status_t returnCode;
3413 #if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD
3414     returnCode =
3415         FLASH_ReadResource(config, kFLASH_ResourceRangePflashSwapIfrStart, flashSwapIfrFieldData.flashSwapIfrData,
3416                            sizeof(flashSwapIfrFieldData.flashSwapIfrData), kFLASH_ResourceOptionFlashIfr);
3417 
3418     if (returnCode != kStatus_FLASH_Success)
3419     {
3420         return returnCode;
3421     }
3422 #else
3423     {
3424         /* From RM, the actual info are stored in FCCOB6,7 */
3425         uint32_t returnValue[2];
3426         returnCode = FLASH_ReadOnce(config, kFLASH_RecordIndexSwapAddr, returnValue, 4);
3427         if (returnCode != kStatus_FLASH_Success)
3428         {
3429             return returnCode;
3430         }
3431         flashSwapIfrFieldData.flashSwapIfrField.swapIndicatorAddress = (uint16_t)returnValue[0];
3432         returnCode = FLASH_ReadOnce(config, kFLASH_RecordIndexSwapEnable, returnValue, 4);
3433         if (returnCode != kStatus_FLASH_Success)
3434         {
3435             return returnCode;
3436         }
3437         flashSwapIfrFieldData.flashSwapIfrField.swapEnableWord = (uint16_t)returnValue[0];
3438         returnCode = FLASH_ReadOnce(config, kFLASH_RecordIndexSwapDisable, returnValue, 4);
3439         if (returnCode != kStatus_FLASH_Success)
3440         {
3441             return returnCode;
3442         }
3443         flashSwapIfrFieldData.flashSwapIfrField.swapDisableWord = (uint16_t)returnValue[0];
3444     }
3445 #endif
3446 
3447     /* The high bits value of Swap Indicator Address is stored in Program Flash Swap IFR Field,
3448      * the low severval bit value of Swap Indicator Address is always 1'b0 */
3449     swapIndicatorAddress = (uint32_t)flashSwapIfrFieldData.flashSwapIfrField.swapIndicatorAddress *
3450                            FSL_FEATURE_FLASH_PFLASH_SWAP_CONTROL_CMD_ADDRESS_ALIGMENT;
3451     if (address != swapIndicatorAddress)
3452     {
3453         return kStatus_FLASH_SwapIndicatorAddressError;
3454     }
3455 
3456     return returnCode;
3457 }
3458 #endif /* FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP */
3459 
3460 #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD
3461 /*! @brief Validates the gived flexram function option.*/
flasn_check_flexram_function_option_range(flash_flexram_function_option_t option)3462 static inline status_t flasn_check_flexram_function_option_range(flash_flexram_function_option_t option)
3463 {
3464     if ((option != kFLASH_FlexramFunctionOptionAvailableAsRam) &&
3465         (option != kFLASH_FlexramFunctionOptionAvailableForEeprom))
3466     {
3467         return kStatus_FLASH_InvalidArgument;
3468     }
3469 
3470     return kStatus_FLASH_Success;
3471 }
3472 #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */
3473 
3474 /*! @brief Gets the flash protection information (region size, region count).*/
flash_get_protection_info(flash_config_t * config,flash_protection_config_t * info)3475 static status_t flash_get_protection_info(flash_config_t *config, flash_protection_config_t *info)
3476 {
3477     uint32_t pflashTotalSize;
3478 
3479     if ((config == NULL) || (info == NULL))
3480     {
3481         return kStatus_FLASH_InvalidArgument;
3482     }
3483 
3484     /* Clean up info Structure*/
3485     memset(info, 0, sizeof(flash_protection_config_t));
3486 
3487 /* Note: KW40 has a secondary flash, but it doesn't have independent protection register*/
3488 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && (!FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER)
3489     pflashTotalSize = MAIN_FLASH_FEATURE_PFLASH_BLOCK_COUNT * MAIN_FLASH_FEATURE_PFLASH_BLOCK_SIZE +
3490                       FSL_FEATURE_FLASH_PFLASH_1_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SIZE;
3491     info->regionBase = MAIN_FLASH_FEATURE_PFLASH_START_ADDRESS;
3492 #else
3493     pflashTotalSize = config->PFlashTotalSize;
3494     info->regionBase = config->PFlashBlockBase;
3495 #endif
3496 
3497 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER
3498     if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash)
3499     {
3500         info->regionCount = SECONDARY_FLASH_FEATURE_PFLASH_PROTECTION_REGION_COUNT;
3501     }
3502     else
3503 #endif
3504     {
3505         info->regionCount = MAIN_FLASH_FEATURE_PFLASH_PROTECTION_REGION_COUNT;
3506     }
3507 
3508     /* Calculate the size of the flash protection region
3509      * If the flash density is > 32KB, then protection region is 1/32 of total flash density
3510      * Else if flash density is < 32KB, then flash protection region is set to 1KB */
3511     if (pflashTotalSize > info->regionCount * 1024)
3512     {
3513         info->regionSize = (pflashTotalSize) / info->regionCount;
3514     }
3515     else
3516     {
3517         info->regionSize = 1024;
3518     }
3519 
3520     return kStatus_FLASH_Success;
3521 }
3522 
3523 #if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL
3524 /*! @brief Gets the flash Execute-Only access information (Segment size, Segment count).*/
flash_get_access_info(flash_config_t * config,flash_access_config_t * info)3525 static status_t flash_get_access_info(flash_config_t *config, flash_access_config_t *info)
3526 {
3527     if ((config == NULL) || (info == NULL))
3528     {
3529         return kStatus_FLASH_InvalidArgument;
3530     }
3531 
3532     /* Clean up info Structure*/
3533     memset(info, 0, sizeof(flash_access_config_t));
3534 
3535 /* Note: KW40 has a secondary flash, but it doesn't have independent access register*/
3536 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && (!FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER)
3537     info->SegmentBase = MAIN_FLASH_FEATURE_PFLASH_START_ADDRESS;
3538 #else
3539     info->SegmentBase = config->PFlashBlockBase;
3540 #endif
3541     info->SegmentSize = config->PFlashAccessSegmentSize;
3542     info->SegmentCount = config->PFlashAccessSegmentCount;
3543 
3544     return kStatus_FLASH_Success;
3545 }
3546 #endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */
3547