1 /*
2 * Copyright 2020 NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8 /*!*********************************************************************************
9 *************************************************************************************
10 * Include
11 *************************************************************************************
12 ********************************************************************************** */
13 #include "fsl_flash.h"
14 #include "fsl_k4_flash.h"
15 #include "fsl_adapter_flash.h"
16 /*****************************************************************************
17 *****************************************************************************
18 * Private macros
19 *****************************************************************************
20 *****************************************************************************/
21 #define PGM_SIZE_BYTE FSL_FEATURE_FLASH_PFLASH_PHRASE_SIZE
22
23 #if defined(__IAR_SYSTEMS_ICC__)
24 #define __RAMFUNC __ramfunc
25 #elif defined(__GNUC__)
26 #define __RAMFUNC __attribute__((section(".ramfunc"))) __attribute__((__noinline__))
27 #endif
28
29 /* ECC_SIM_OM option is to be used only when simulating ECC faults for test purposes.
30 * The controller raises an ECC fault at the first read access to the flash whatever the master.
31 * Any intruction fetch from flash would cause the simulated ECC fault to raise, so need to place
32 * such code in RAM. Likewise the flash cache must be disabled.
33 * These reasons justify the __ECC_FCT_PLACEMENT attribute used for the ECC related functions.
34 */
35 #ifdef ECC_SIM_ON
36 #define __ECC_FCT_PLACEMENT __RAMFUNC
37 __ECC_FCT_PLACEMENT static void flash_cache_disable1(void);
38 #define FLASH_CACHE_DISABLE() flash_cache_disable1()
39 #else
40 #define __ECC_FCT_PLACEMENT
41 #define FLASH_CACHE_DISABLE() flash_cache_disable()
42 #endif
43
44 #define OCMDR0_CF0_DNCBEI_SHIFT (2u + SMSCM_OCMDR0_OCMCF0_SHIFT)
45 #define OCMDR0_CF0_DNCBED_SHIFT (3u + SMSCM_OCMDR0_OCMCF0_SHIFT)
46 #define OCMDR0_CF0_DNCBEI_MASK (1u << OCMDR0_CF0_DNCBEI_SHIFT)
47 #define OCMDR0_CF0_DNCBED_MASK (1u << OCMDR0_CF0_DNCBED_SHIFT)
48
49 /*!*********************************************************************************
50 *************************************************************************************
51 * Private type definitions
52 *************************************************************************************
53 ********************************************************************************** */
54 static flash_config_t s_flashConfig;
55 /*!*********************************************************************************
56 *************************************************************************************
57 * Private prototypes
58 *************************************************************************************
59 ********************************************************************************** */
60 static hal_flash_status_t HAL_FlashProgramAdaptation(uint32_t dest, uint32_t size, uint8_t *pData);
61 /*!*********************************************************************************
62 *************************************************************************************
63 * Public memory declarations
64 *************************************************************************************
65 ********************************************************************************** */
66
67 /*****************************************************************************
68 *****************************************************************************
69 * Private functions
70 *****************************************************************************
71 *****************************************************************************/
HAL_FlashGetStatus(status_t status)72 static hal_flash_status_t HAL_FlashGetStatus(status_t status)
73 {
74 #if (defined(HAL_FLASH_TRANSFER_MODE) && (HAL_FLASH_TRANSFER_MODE > 0U))
75 hal_flash_status_t flashStatus = kStatus_HAL_Flash_Error;
76 switch (status)
77 {
78 case (status_t)kStatus_Success:
79 flashStatus = kStatus_HAL_Flash_Success;
80 break;
81 case (status_t)kStatus_FLASH_InvalidArgument:
82 flashStatus = kStatus_HAL_Flash_InvalidArgument;
83 break;
84 case (status_t)kStatus_FLASH_AlignmentError:
85 flashStatus = kStatus_HAL_Flash_AlignmentError;
86 break;
87 default:
88 /*MISRA rule 16.4*/
89 break;
90 }
91 return flashStatus;
92 #else
93 return (hal_flash_status_t)status;
94 #endif
95 }
96
HAL_FlashGetPropertyTag(hal_flash_property_tag_t tag)97 static flash_property_tag_t HAL_FlashGetPropertyTag(hal_flash_property_tag_t tag)
98 {
99 flash_property_tag_t ret;
100 switch (tag)
101 {
102 case kHAL_Flash_PropertyPflashSectorSize:
103 ret = kFLASH_PropertyPflash0SectorSize;
104 break;
105 case kHAL_Flash_PropertyPflashTotalSize:
106 ret = kFLASH_PropertyPflash0TotalSize;
107 break;
108 case kHAL_Flash_PropertyPflashBlockCount:
109 ret = kFLASH_PropertyPflash0BlockCount;
110 break;
111 case kHAL_Flash_PropertyPflashBlockBaseAddr:
112 ret = kFLASH_PropertyPflash0BlockBaseAddr;
113 break;
114 case kHAL_Flash_PropertyPflashBlockSize:
115 ret = kFLASH_PropertyPflash0BlockSize;
116 break;
117 default:
118 /*MISRA rule 16.4*/
119 ret = (flash_property_tag_t)-1;
120 break;
121 }
122 return ret;
123 }
124
HAL_FlashProgramAdaptation(uint32_t dest,uint32_t size,uint8_t * pData)125 static hal_flash_status_t HAL_FlashProgramAdaptation(uint32_t dest, uint32_t size, uint8_t *pData)
126 {
127 int32_t status;
128
129 uint32_t regPrimask = DisableGlobalIRQ();
130
131 status = FLASH_Program(&s_flashConfig, FLASH, dest, (uint8_t *)pData, size);
132
133 EnableGlobalIRQ(regPrimask);
134
135 return HAL_FlashGetStatus(status);
136 }
137
138 /*!*********************************************************************************
139 *************************************************************************************
140 * Public functions
141 *************************************************************************************
142 ********************************************************************************** */
143
144 /*!
145 * @brief Initializes the global flash properties structure members.
146 *
147 * This function initializes the Flash module for the other Flash APIs.
148 *
149 *
150 * @retval #kStatus_HAL_Flash_Success API was executed successfully.
151 * @retval #kStatus_HAL_Flash_InvalidArgument An invalid argument is provided.
152 * @retval #kStatus_HAL_Flash_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available.
153 * @retval #kStatus_HAL_Flash_PartitionStatusUpdateFailure Failed to update the partition status.
154 */
HAL_FlashInit()155 hal_flash_status_t HAL_FlashInit()
156 {
157 static uint32_t flashInit = 0;
158 status_t status = (status_t)kStatus_HAL_Flash_Success;
159
160 uint32_t regPrimask = DisableGlobalIRQ();
161 /* Disable cache/Prefetch */
162 flash_cache_disable();
163 EnableGlobalIRQ(regPrimask);
164 if (0U == flashInit)
165 {
166 /* Init Flash */
167 status = FLASH_Init(&s_flashConfig);
168 flashInit = 1U;
169 }
170 return HAL_FlashGetStatus(status);
171 }
172
173 /*!
174 * \brief Verify erase data in Flash
175 *
176 * @param start The address of the Flash location
177 * @param lengthInBytes The number of bytes to be checked
178 * @param margin Flash margin value
179 * @retval #kStatus_HAL_Flash_Success API was executed successfully.
180 */
HAL_FlashVerifyErase(uint32_t start,uint32_t lengthInBytes,hal_flash_margin_value_t margin)181 hal_flash_status_t HAL_FlashVerifyErase(uint32_t start, uint32_t lengthInBytes, hal_flash_margin_value_t margin)
182 {
183 int32_t status;
184 uint32_t regPrimask = DisableGlobalIRQ();
185
186 (void)margin;
187 if (start >= s_flashConfig.msf1Config[0].ifrDesc.pflashIfr0Start)
188 {
189 status = FLASH_VerifyEraseIFRPhrase(&s_flashConfig, FLASH, start, lengthInBytes);
190 }
191 else
192 {
193 status = FLASH_VerifyErasePhrase(&s_flashConfig, FLASH, start, lengthInBytes);
194 }
195 EnableGlobalIRQ(regPrimask);
196 return HAL_FlashGetStatus(status);
197 }
198
199 /*!
200 * \brief Write aligned data to FLASH
201 *
202 * @param halFlashHandle Hal flash adapter handle
203 * @param dest The address of the Flash location
204 * @param size The number of bytes to be programed
205 * @param pData Pointer to the data to be programmed to Flash
206 *
207 * @retval #kStatus_HAL_Flash_Success API was executed successfully.
208 *
209 */
HAL_FlashProgram(uint32_t dest,uint32_t size,uint8_t * pData)210 hal_flash_status_t HAL_FlashProgram(uint32_t dest, uint32_t size, uint8_t *pData)
211 {
212 return HAL_FlashProgramAdaptation(dest, size, pData);
213 }
214
215 /*!
216 * \brief Write data to FLASH
217 *
218 * @param dest The address of the Flash location
219 * @param size The number of bytes to be programed
220 * @param pData Pointer to the data to be programmed to Flash
221 *
222 * @retval #kStatus_HAL_Flash_Success API was executed successfully.
223 *
224 */
HAL_FlashProgramUnaligned(uint32_t dest,uint32_t size,uint8_t * pData)225 hal_flash_status_t HAL_FlashProgramUnaligned(uint32_t dest, uint32_t size, uint8_t *pData)
226 {
227 uint8_t buffer[PGM_SIZE_BYTE];
228 uint32_t bytes = dest & ((uint32_t)PGM_SIZE_BYTE - 1U);
229 hal_flash_status_t status = kStatus_HAL_Flash_Success;
230
231 if (bytes != 0U)
232 {
233 uint32_t unalignedBytes = (uint32_t)PGM_SIZE_BYTE - bytes;
234
235 if (unalignedBytes > size)
236 {
237 unalignedBytes = size;
238 }
239
240 memcpy(buffer, (uint8_t *)(dest - bytes), PGM_SIZE_BYTE);
241 memcpy(&buffer[bytes], pData, unalignedBytes);
242
243 status = HAL_FlashProgramAdaptation(dest - bytes, PGM_SIZE_BYTE, buffer);
244 if (kStatus_HAL_Flash_Success == status)
245 {
246 dest += (uint32_t)PGM_SIZE_BYTE - bytes;
247 pData += unalignedBytes;
248 size -= unalignedBytes;
249 }
250 }
251
252 if (kStatus_HAL_Flash_Success == status)
253 {
254 bytes = size & ~((uint32_t)PGM_SIZE_BYTE - 1U);
255
256 if (bytes != 0U)
257 {
258 status = HAL_FlashProgramAdaptation(dest, bytes, pData);
259 if (kStatus_HAL_Flash_Success == status)
260 {
261 dest += bytes;
262 pData += bytes;
263 size -= bytes;
264 }
265 }
266
267 if (kStatus_HAL_Flash_Success == status)
268 {
269 if (size != 0U)
270 {
271 memcpy(buffer, (uint8_t *)dest, PGM_SIZE_BYTE);
272 memcpy(buffer, pData, size);
273 status = HAL_FlashProgramAdaptation(dest, PGM_SIZE_BYTE, buffer);
274 }
275 }
276 }
277 return status;
278 }
279
280 /*!
281 * \brief Erase to 0xFF one or more FLASH sectors.
282 *
283 * @param dest The start address of the first sector to be erased
284 * @param size The amount of flash to be erased (multiple of sector size)
285 *
286 * @retval #kStatus_HAL_Flash_Success API was executed successfully.
287 *
288 */
HAL_FlashEraseSector(uint32_t dest,uint32_t size)289 hal_flash_status_t HAL_FlashEraseSector(uint32_t dest, uint32_t size)
290 {
291 int32_t status;
292
293 uint32_t regPrimask = DisableGlobalIRQ();
294
295 status = FLASH_Erase(&s_flashConfig, FLASH, dest, size, (uint32_t)kFLASH_ApiEraseKey);
296
297 EnableGlobalIRQ(regPrimask);
298
299 return HAL_FlashGetStatus(status);
300 }
301
302 /*!
303 * \brief Read data from FLASH
304 *
305
306 * @param scr The address of the Flash location to be read
307 * @param size The number of bytes to be read
308 * @param pData Pointer to the data to be read from Flash
309 *
310 * @retval #kStatus_HAL_Flash_Success API was executed successfully.
311 *
312 */
HAL_FlashRead(uint32_t src,uint32_t size,uint8_t * pData)313 hal_flash_status_t HAL_FlashRead(uint32_t src, uint32_t size, uint8_t *pData)
314 {
315 (void)memcpy(pData, (uint8_t *)src, size);
316 return kStatus_HAL_Flash_Success;
317 }
318
319 #ifdef ECC_SIM_ON
flash_cache_disable1(void)320 __ECC_FCT_PLACEMENT static void flash_cache_disable1(void)
321 {
322 SMSCM->OCMDR0 = (SMSCM->OCMDR0 & (~SMSCM_FLASH_CACHE_CTRL_MASK)) | SMSCM_FLASH_CACHE_CTRL(0x1);
323 SMSCM->OCMDR0 = (SMSCM->OCMDR0 & (~SMSCM_FLASH_CACHE_CTRL_MASK)) | SMSCM_FLASH_CACHE_CTRL(0x8);
324 SMSCM->OCMDR0 = (SMSCM->OCMDR0 & (~SMSCM_FLASH_SPECULATION_CTRL_MASK)) | SMSCM_FLASH_SPECULATION_CTRL(0x3);
325 __ISB();
326 __DSB();
327 }
328 #endif
flash_bus_fault_ecc_non_correctable_err_on_data_fetch(bool enableNdisable)329 __ECC_FCT_PLACEMENT static int flash_bus_fault_ecc_non_correctable_err_on_data_fetch(bool enableNdisable)
330 {
331 int st = -1;
332 uint32_t reg_val;
333 reg_val = SMSCM->OCMDR0;
334 if ((reg_val & SMSCM_OCMDR0_RO_MASK) != SMSCM_OCMDR0_RO_MASK)
335 {
336 FLASH_CACHE_DISABLE();
337 // flash_cache_speculation_control(true, FLASH);
338 reg_val &= ~SMSCM_OCMDR0_OCMCF0_MASK;
339 if (!enableNdisable)
340 {
341 /* disable bus fault on data read in case of ECC non recoverable error */
342 reg_val |= OCMDR0_CF0_DNCBED_MASK;
343 }
344 SMSCM->OCMDR0 = reg_val;
345 st = 0;
346 }
347 return st;
348 }
349
350 /*!
351 * \brief Activate or deactivate ECC fault detection without bus faulting
352 *
353 * Note a RAM version of this function is required when ECC fault simulation is used.
354 *
355 * @param sav_cfg pointer of 32 bit location to remember flash cache and
356 * ECC configuration to be restored
357 *
358 * @retval 0 if OK might be -1 if configuration is readonly.
359 *
360 */
FLASH_ActivateEccFaultDetection(FMU_Type * base,uint32_t * sav_cfg)361 __ECC_FCT_PLACEMENT int FLASH_ActivateEccFaultDetection(FMU_Type *base, uint32_t *sav_cfg)
362 {
363 int st;
364 uint32_t fcncf_val;
365 *sav_cfg = SMSCM->OCMDR0;
366 st = flash_bus_fault_ecc_non_correctable_err_on_data_fetch(false);
367 if (0 == st)
368 {
369 fcncf_val = base->FCNFG;
370 fcncf_val |= FMU_FCNFG_DFDIE_MASK;
371 /* Command Complete CCIE must remain unset */
372 // fcncf_val &= ~FMU_FCNFG_CCIE_MASK;
373 base->FCNFG = fcncf_val;
374 __ISB();
375 __DSB();
376 }
377 return st;
378 }
379
FLASH_DeactivateEccFaultDetection(FMU_Type * base,uint32_t restore_cfg)380 __ECC_FCT_PLACEMENT int FLASH_DeactivateEccFaultDetection(FMU_Type *base, uint32_t restore_cfg)
381 {
382 int st;
383 uint32_t fcncf_val;
384 st = flash_bus_fault_ecc_non_correctable_err_on_data_fetch(true);
385
386 /* Reenable flash cache and reenable bus fault on ECC non correctable fault detection */
387 SMSCM->OCMDR0 = restore_cfg;
388 fcncf_val = base->FCNFG;
389 base->FCNFG = fcncf_val;
390 __ISB();
391 __DSB();
392 return st;
393 }
394
HAL_FlashEccStatusRaised(void)395 bool HAL_FlashEccStatusRaised(void)
396 {
397 return (FMU0->FSTAT & FLASH_FSTAT_DFDIF_MASK) ? true : false;
398 }
399
400 /*!
401 * \brief Read data from FLASH checking for ECC errors
402 *
403 * Note a RAM version of this function is required when ECC fault simulation is used.
404 *
405 * @param scr The address of the Flash location to be read
406 * @param size The number of bytes to be read
407 * @param pData Pointer to the data to be read from Flash
408 *
409 * @retval #kStatus_HAL_Flash_Success API was executed successfully.
410 * #kStatus_HAL_Flash_EccError if ECC Fault error got raised.
411 *
412 */
HAL_FlashReadCheckEccFaults(uint32_t src,uint32_t size,uint8_t * pData)413 hal_flash_status_t HAL_FlashReadCheckEccFaults(uint32_t src, uint32_t size, uint8_t *pData)
414 {
415 hal_flash_status_t st = kStatus_HAL_Flash_Success;
416
417 uint32_t sav_cfg;
418 uint8_t *addr = (uint8_t *)src;
419 uint8_t *end_addr = addr + size;
420 uint32_t regPrimask = DisableGlobalIRQ();
421 FMU0->FSTAT = FLASH_FSTAT_DFDIF_MASK;
422 if (FLASH_ActivateEccFaultDetection(FMU0, &sav_cfg) == 0)
423 {
424 while (addr < end_addr)
425 {
426 *pData = *addr;
427 if ((FMU0->FSTAT & FLASH_FSTAT_DFDIF_MASK) == FLASH_FSTAT_DFDIF_MASK)
428 {
429 /* Acknowledge Double ECC Fault event */
430 FMU0->FSTAT = FLASH_FSTAT_DFDIF_MASK;
431 st = kStatus_HAL_Flash_EccError;
432 break;
433 }
434 addr++;
435 pData++;
436 }
437 (void)FLASH_DeactivateEccFaultDetection(FMU0, sav_cfg);
438 }
439 EnableGlobalIRQ(regPrimask);
440 return st;
441 }
442
443 /*!
444 * @brief Returns the desired hal flash property.
445 *
446 * @param Property The desired property from the list of properties in
447 * enum hal_flash_property_tag_t
448 * @param value A pointer to the value returned for the desired flash property.
449 *
450 * @retval #kStatus_HAL_Flash_Success API was executed successfully.
451 * @retval #kStatus_HAL_Flash_InvalidArgument An invalid argument is provided.
452 * @retval #kStatus_HAL_Flash_NotSupport Flash currently not support.
453 */
HAL_FlashGetProperty(hal_flash_property_tag_t property,uint32_t * value)454 hal_flash_status_t HAL_FlashGetProperty(hal_flash_property_tag_t property, uint32_t *value)
455 {
456 flash_property_tag_t ret;
457 if (value == NULL)
458 {
459 return kStatus_HAL_Flash_InvalidArgument;
460 }
461 ret = HAL_FlashGetPropertyTag(property);
462 if (((flash_property_tag_t)-1) == ret)
463 {
464 return kStatus_HAL_Flash_NotSupport;
465 }
466 else
467 {
468 return HAL_FlashGetStatus(FLASH_GetProperty(&s_flashConfig, ret, value));
469 }
470 }
471
472 /*!
473 * @brief Set the desired hal flash property.
474 *
475 * @param Property The desired property from the list of properties in
476 * enum hal_flash_property_tag_t
477 * @param value The value would be set to the desired flash property.
478 *
479 * @retval #kStatus_HAL_Flash_Success API was executed successfully.
480 * @retval #kStatus_HAL_Flash_InvalidArgument An invalid argument is provided.
481 * @retval #kStatus_HAL_Flash_NotSupport Flash currently not support.
482 */
HAL_FlashSetProperty(hal_flash_property_tag_t property,uint32_t value)483 hal_flash_status_t HAL_FlashSetProperty(hal_flash_property_tag_t property, uint32_t value)
484 {
485 return kStatus_HAL_Flash_NotSupport;
486 }
487
488 /*!
489 * @brief Returns the security state via the pointer passed into the function.
490 *
491 * This function retrieves the current flash security status, including the
492 * security enabling state and the backdoor key enabling state.
493 *
494 * @param state A pointer to the value returned for the current security status
495 *
496 * @retval #kStatus_HAL_Flash_Success API was executed successfully.
497 * @retval #kStatus_HAL_Flash_InvalidArgument An invalid argument is provided.
498 * @retval #kStatus_HAL_Flash_NotSupport Flash currently not support.
499 */
HAL_FlashGetSecurityState(hal_flash_security_state_t * state)500 hal_flash_status_t HAL_FlashGetSecurityState(hal_flash_security_state_t *state)
501 {
502 #if 0
503 return HAL_FlashGetStatus(FLASH_GetSecurityState(s_flashConfig, (ftfx_security_state_t *)state));
504 #else
505 return kStatus_HAL_Flash_NotSupport;
506 #endif
507 }