| /* |
| * Copyright 2013-2016 Freescale Semiconductor, Inc. |
| * Copyright 2016-2018 NXP |
| * All rights reserved. |
| * |
| * SPDX-License-Identifier: BSD-3-Clause |
| * |
| */ |
| |
| #include "fsl_ftfx_cache.h" |
| |
| /******************************************************************************* |
| * Definitions |
| ******************************************************************************/ |
| |
| /*! |
| * @name Flash cache and speculation control defines |
| * @{ |
| */ |
| #if defined(MCM_PLACR_CFCC_MASK) |
| #define FLASH_CACHE_IS_CONTROLLED_BY_MCM (1) |
| #else |
| #define FLASH_CACHE_IS_CONTROLLED_BY_MCM (0) |
| #endif |
| |
| #define FLASH_CACHE_IS_CONTROLLED_BY_MSCM (0) |
| |
| #if defined(FMC_PFB0CR_CINV_WAY_MASK) || defined(FMC_PFB01CR_CINV_WAY_MASK) |
| #define FLASH_CACHE_IS_CONTROLLED_BY_FMC (1) |
| #else |
| #define FLASH_CACHE_IS_CONTROLLED_BY_FMC (0) |
| #endif |
| |
| #if defined(MCM_PLACR_DFCS_MASK) |
| #define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM (1) |
| #else |
| #define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM (0) |
| #endif |
| |
| #if defined(MSCM_OCMDR_OCMC1_MASK) || defined(MSCM_OCMDR_OCM1_MASK) || defined(MSCM_OCMDR0_OCM1_MASK) || \ |
| defined(MSCM_OCMDR1_OCM1_MASK) |
| #define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM (1) |
| #else |
| #define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM (0) |
| #endif |
| |
| #if defined(FMC_PFB0CR_S_INV_MASK) || defined(FMC_PFB0CR_S_B_INV_MASK) || defined(FMC_PFB01CR_S_INV_MASK) || \ |
| defined(FMC_PFB01CR_S_B_INV_MASK) |
| #define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC (1) |
| #else |
| #define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC (0) |
| #endif |
| |
| #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM || FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC || \ |
| FLASH_CACHE_IS_CONTROLLED_BY_MCM || FLASH_CACHE_IS_CONTROLLED_BY_FMC || FLASH_CACHE_IS_CONTROLLED_BY_MSCM |
| #define FLASH_IS_CACHE_INVALIDATION_AVAILABLE (1) |
| #else |
| #define FLASH_IS_CACHE_INVALIDATION_AVAILABLE (0) |
| #endif |
| /*@}*/ |
| |
| /*! @brief A function pointer used to point to relocated ftfx_common_bit_operation() */ |
| typedef void (*callftfxCommonBitOperation_t)(FTFx_REG32_ACCESS_TYPE base, |
| uint32_t bitMask, |
| uint32_t bitShift, |
| uint32_t bitValue); |
| |
| /******************************************************************************* |
| * Prototypes |
| ******************************************************************************/ |
| |
| #if FLASH_CACHE_IS_CONTROLLED_BY_MCM |
| /*! @brief Performs the cache clear to the flash by MCM.*/ |
| void mcm_flash_cache_clear(ftfx_cache_config_t *config); |
| #endif /* FLASH_CACHE_IS_CONTROLLED_BY_MCM */ |
| |
| #if FLASH_CACHE_IS_CONTROLLED_BY_MSCM |
| /*! @brief Performs the cache clear to the flash by MSCM.*/ |
| void mscm_flash_cache_clear(ftfx_cache_config_t *config); |
| #endif /* FLASH_CACHE_IS_CONTROLLED_BY_MSCM */ |
| |
| #if FLASH_CACHE_IS_CONTROLLED_BY_FMC |
| /*! @brief Performs the cache clear to the flash by FMC.*/ |
| void fmc_flash_cache_clear(ftfx_cache_config_t *config); |
| #endif /* FLASH_CACHE_IS_CONTROLLED_BY_FMC */ |
| |
| #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM |
| /*! @brief Sets the prefetch speculation buffer to the flash by MSCM.*/ |
| void mscm_flash_prefetch_speculation_enable(ftfx_cache_config_t *config, bool enable); |
| #endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM */ |
| |
| #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC |
| /*! @brief Performs the prefetch speculation buffer clear to the flash by FMC.*/ |
| void fmc_flash_prefetch_speculation_clear(ftfx_cache_config_t *config); |
| #endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC */ |
| |
| #if FTFx_DRIVER_IS_FLASH_RESIDENT && FLASH_IS_CACHE_INVALIDATION_AVAILABLE |
| /*! @brief Copy flash_cache_clear_command() to RAM*/ |
| static void ftfx_copy_common_bit_operation_to_ram(uint32_t *ftfxCommonBitOperation); |
| #endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */ |
| |
| /******************************************************************************* |
| * Variables |
| ******************************************************************************/ |
| |
| #if FTFx_DRIVER_IS_FLASH_RESIDENT && FLASH_IS_CACHE_INVALIDATION_AVAILABLE |
| /*! |
| * @brief Position independent code of ftfx_common_bit_operation() |
| * |
| * Note1: The prototype of C function is shown as below: |
| * @code |
| * void ftfx_common_bit_operation(FTFx_REG32_ACCESS_TYPE base, uint32_t bitMask, uint32_t bitShift, uint32_t |
| * bitValue) |
| * { |
| * if (bitMask) |
| * { |
| * uint32_t value = (((uint32_t)(((uint32_t)(bitValue)) << bitShift)) & bitMask); |
| * *base = (*base & (~bitMask)) | value; |
| * } |
| * |
| * __ISB(); |
| * __DSB(); |
| * } |
| * @endcode |
| * Note2: The binary code is generated by IAR 7.70.1 |
| */ |
| static const uint16_t s_ftfxCommonBitOperationFunctionCode[] = { |
| 0xb510, /* PUSH {R4, LR} */ |
| 0x2900, /* CMP R1, #0 */ |
| 0xd005, /* BEQ.N @12 */ |
| 0x6804, /* LDR R4, [R0] */ |
| 0x438c, /* BICS R4, R4, R1 */ |
| 0x4093, /* LSLS R3, R3, R2 */ |
| 0x4019, /* ANDS R1, R1, R3 */ |
| 0x4321, /* ORRS R1, R1, R4 */ |
| 0x6001, /* STR R1, [R0] */ |
| /* @12: */ |
| 0xf3bf, 0x8f6f, /* ISB */ |
| 0xf3bf, 0x8f4f, /* DSB */ |
| 0xbd10 /* POP {R4, PC} */ |
| }; |
| |
| #if (!FTFx_DRIVER_IS_EXPORTED) |
| /*! @brief A static buffer used to hold ftfx_common_bit_operation() */ |
| static uint32_t s_ftfxCommonBitOperation[kFTFx_CACHE_RamFuncMaxSizeInWords]; |
| #endif /* (!FTFx_DRIVER_IS_EXPORTED) */ |
| #endif /* FLASH_IS_CACHE_INVALIDATION_AVAILABLE && FTFx_DRIVER_IS_FLASH_RESIDENT */ |
| |
| /******************************************************************************* |
| * Code |
| ******************************************************************************/ |
| |
| status_t FTFx_CACHE_Init(ftfx_cache_config_t *config) |
| { |
| if (config == NULL) |
| { |
| return kStatus_FTFx_InvalidArgument; |
| } |
| |
| /* copy required flash commands to RAM */ |
| #if FTFx_DRIVER_IS_FLASH_RESIDENT && FLASH_IS_CACHE_INVALIDATION_AVAILABLE |
| if (NULL == config->comBitOperFuncAddr) |
| { |
| #if FTFx_DRIVER_IS_EXPORTED |
| return kStatus_FTFx_ExecuteInRamFunctionNotReady; |
| #else |
| config->comBitOperFuncAddr = s_ftfxCommonBitOperation; |
| #endif /* FTFx_DRIVER_IS_EXPORTED */ |
| } |
| ftfx_copy_common_bit_operation_to_ram(config->comBitOperFuncAddr); |
| #endif /* FLASH_IS_CACHE_INVALIDATION_AVAILABLE && FTFx_DRIVER_IS_FLASH_RESIDENT */ |
| |
| return kStatus_FTFx_Success; |
| } |
| |
| /*! |
| * @brief Flash Cache/Prefetch/Speculation Clear Process |
| * |
| * This function is used to perform the cache and prefetch speculation clear process to the flash. |
| */ |
| status_t FTFx_CACHE_ClearCachePrefetchSpeculation(ftfx_cache_config_t *config, bool isPreProcess) |
| { |
| /* We pass the ftfx register address as a parameter to ftfx_common_bit_operation() instead of using |
| * pre-processed MACROs or a global variable in ftfx_common_bit_operation() |
| * to make sure that ftfx_common_bit_operation() will be compiled into position-independent code (PIC). */ |
| if (!isPreProcess) |
| { |
| #if FLASH_CACHE_IS_CONTROLLED_BY_MCM |
| mcm_flash_cache_clear(config); |
| #endif |
| #if FLASH_CACHE_IS_CONTROLLED_BY_MSCM |
| mscm_flash_cache_clear(config); |
| #endif |
| #if FLASH_CACHE_IS_CONTROLLED_BY_FMC |
| fmc_flash_cache_clear(config); |
| #endif |
| #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM |
| mscm_flash_prefetch_speculation_enable(config, true); |
| #endif |
| #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC |
| fmc_flash_prefetch_speculation_clear(config); |
| #endif |
| } |
| if (isPreProcess) |
| { |
| #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM |
| mscm_flash_prefetch_speculation_enable(config, false); |
| #endif |
| } |
| |
| return kStatus_FTFx_Success; |
| } |
| |
| status_t FTFx_CACHE_PflashSetPrefetchSpeculation(ftfx_prefetch_speculation_status_t *speculationStatus) |
| { |
| #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM |
| { |
| if (speculationStatus->instructionOff) |
| { |
| if (!speculationStatus->dataOff) |
| { |
| return kStatus_FTFx_InvalidSpeculationOption; |
| } |
| else |
| { |
| MCM0_CACHE_REG |= MCM_PLACR_DFCS_MASK; |
| } |
| } |
| else |
| { |
| MCM0_CACHE_REG &= ~MCM_PLACR_DFCS_MASK; |
| if (!speculationStatus->dataOff) |
| { |
| MCM0_CACHE_REG |= MCM_PLACR_EFDS_MASK; |
| } |
| else |
| { |
| MCM0_CACHE_REG &= ~MCM_PLACR_EFDS_MASK; |
| } |
| } |
| } |
| #elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC |
| { |
| if (!speculationStatus->instructionOff) |
| { |
| FMC_CACHE_REG |= FMC_CACHE_B0IPE_MASK; |
| } |
| else |
| { |
| FMC_CACHE_REG &= ~FMC_CACHE_B0IPE_MASK; |
| } |
| if (!speculationStatus->dataOff) |
| { |
| FMC_CACHE_REG |= FMC_CACHE_B0DPE_MASK; |
| } |
| else |
| { |
| FMC_CACHE_REG &= ~FMC_CACHE_B0DPE_MASK; |
| } |
| |
| /* Invalidate Prefetch Speculation Buffer */ |
| FMC_SPECULATION_INVALIDATE_REG |= FMC_SPECULATION_INVALIDATE_MASK; |
| } |
| #elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM |
| { |
| if (speculationStatus->instructionOff) |
| { |
| if (!speculationStatus->dataOff) |
| { |
| return kStatus_FTFx_InvalidSpeculationOption; |
| } |
| else |
| { |
| MSCM_OCMDR0_REG |= MSCM_OCMDR_OCMC1_DFCS_MASK; |
| } |
| } |
| else |
| { |
| MSCM_OCMDR0_REG &= ~MSCM_OCMDR_OCMC1_DFCS_MASK; |
| if (!speculationStatus->dataOff) |
| { |
| MSCM_OCMDR0_REG &= ~MSCM_OCMDR_OCMC1_DFDS_MASK; |
| } |
| else |
| { |
| MSCM_OCMDR0_REG |= MSCM_OCMDR_OCMC1_DFDS_MASK; |
| } |
| } |
| } |
| #endif /* FSL_FEATURE_FTFx_MCM_FLASH_CACHE_CONTROLS */ |
| |
| return kStatus_FTFx_Success; |
| } |
| |
| status_t FTFx_CACHE_PflashGetPrefetchSpeculation(ftfx_prefetch_speculation_status_t *speculationStatus) |
| { |
| memset(speculationStatus, 0, sizeof(ftfx_prefetch_speculation_status_t)); |
| |
| /* Assuming that all speculation options are enabled. */ |
| speculationStatus->instructionOff = false; |
| speculationStatus->dataOff = false; |
| |
| #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM |
| { |
| uint32_t value = MCM0_CACHE_REG; |
| if (value & MCM_PLACR_DFCS_MASK) |
| { |
| /* Speculation buffer is off. */ |
| speculationStatus->instructionOff = true; |
| speculationStatus->dataOff = true; |
| } |
| else |
| { |
| /* Speculation buffer is on for instruction. */ |
| if (!(value & MCM_PLACR_EFDS_MASK)) |
| { |
| /* Speculation buffer is off for data. */ |
| speculationStatus->dataOff = true; |
| } |
| } |
| } |
| #elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC |
| { |
| uint32_t value = FMC_CACHE_REG; |
| if (!(value & FMC_CACHE_B0DPE_MASK)) |
| { |
| /* Do not prefetch in response to data references. */ |
| speculationStatus->dataOff = true; |
| } |
| if (!(value & FMC_CACHE_B0IPE_MASK)) |
| { |
| /* Do not prefetch in response to instruction fetches. */ |
| speculationStatus->instructionOff = true; |
| } |
| } |
| #elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM |
| { |
| uint32_t value = MSCM_OCMDR0_REG; |
| if (value & MSCM_OCMDR_OCMC1_DFCS_MASK) |
| { |
| /* Speculation buffer is off. */ |
| speculationStatus->instructionOff = true; |
| speculationStatus->dataOff = true; |
| } |
| else |
| { |
| /* Speculation buffer is on for instruction. */ |
| if (value & MSCM_OCMDR_OCMC1_DFDS_MASK) |
| { |
| /* Speculation buffer is off for data. */ |
| speculationStatus->dataOff = true; |
| } |
| } |
| } |
| #endif |
| |
| return kStatus_FTFx_Success; |
| } |
| |
| #if FTFx_DRIVER_IS_FLASH_RESIDENT && FLASH_IS_CACHE_INVALIDATION_AVAILABLE |
| /*! @brief Copy PIC of ftfx_common_bit_operation() to RAM */ |
| static void ftfx_copy_common_bit_operation_to_ram(uint32_t *ftfxCommonBitOperation) |
| { |
| assert(sizeof(s_ftfxCommonBitOperationFunctionCode) <= (kFTFx_CACHE_RamFuncMaxSizeInWords * 4)); |
| |
| memcpy(ftfxCommonBitOperation, s_ftfxCommonBitOperationFunctionCode, |
| sizeof(s_ftfxCommonBitOperationFunctionCode)); |
| } |
| #endif /* FTFx_DRIVER_IS_FLASH_RESIDENT && FLASH_IS_CACHE_INVALIDATION_AVAILABLE */ |
| |
| #if FLASH_CACHE_IS_CONTROLLED_BY_MCM |
| /*! @brief Performs the cache clear to the flash by MCM.*/ |
| void mcm_flash_cache_clear(ftfx_cache_config_t *config) |
| { |
| FTFx_REG32_ACCESS_TYPE regBase; |
| |
| #if defined(MCM0_CACHE_REG) |
| regBase = (FTFx_REG32_ACCESS_TYPE)&MCM0_CACHE_REG; |
| #elif defined(MCM1_CACHE_REG) |
| regBase = (FTFx_REG32_ACCESS_TYPE)&MCM1_CACHE_REG; |
| #endif |
| |
| #if FTFx_DRIVER_IS_FLASH_RESIDENT |
| /* Since the value of ARM function pointer is always odd, but the real start address |
| * of function memory should be even, that's why +1 operation exist. */ |
| callftfxCommonBitOperation_t callftfxCommonBitOperation = (callftfxCommonBitOperation_t)((uint32_t)config->comBitOperFuncAddr + 1); |
| callftfxCommonBitOperation(regBase, MCM_CACHE_CLEAR_MASK, MCM_CACHE_CLEAR_SHIFT, 1U); |
| #else /* !FTFx_DRIVER_IS_FLASH_RESIDENT */ |
| *regBase |= MCM_CACHE_CLEAR_MASK; |
| |
| /* Memory barriers for good measure. |
| * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ |
| __ISB(); |
| __DSB(); |
| #endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */ |
| } |
| #endif /* FLASH_CACHE_IS_CONTROLLED_BY_MCM */ |
| |
| #if FLASH_CACHE_IS_CONTROLLED_BY_MSCM |
| /*! @brief Performs the cache clear to the flash by MSCM.*/ |
| void mscm_flash_cache_clear(ftfx_cache_config_t *config) |
| { |
| uint8_t setValue = 0x1U; |
| |
| /* The OCMDR[0] is always used to cache main Pflash*/ |
| /* For device with FlexNVM support, the OCMDR[1] is used to cache Dflash. |
| * For device with secondary flash support, the OCMDR[1] is used to cache secondary Pflash. */ |
| #if FTFx_DRIVER_IS_FLASH_RESIDENT |
| /* Since the value of ARM function pointer is always odd, but the real start address |
| * of function memory should be even, that's why +1 operation exist. */ |
| callftfxCommonBitOperation_t callftfxCommonBitOperation = (callftfxCommonBitOperation_t)((uint32_t)config->comBitOperFuncAddr + 1); |
| switch (config->flashMemoryIndex) |
| { |
| case kFLASH_MemoryIndexSecondaryFlash: |
| callftfxCommonBitOperation((FTFx_REG32_ACCESS_TYPE)&MSCM_OCMDR1_REG, MSCM_CACHE_CLEAR_MASK, |
| MSCM_CACHE_CLEAR_SHIFT, setValue); |
| break; |
| case kFLASH_MemoryIndexPrimaryFlash: |
| default: |
| callftfxCommonBitOperation((FTFx_REG32_ACCESS_TYPE)&MSCM_OCMDR0_REG, MSCM_CACHE_CLEAR_MASK, |
| MSCM_CACHE_CLEAR_SHIFT, setValue); |
| break; |
| } |
| #else /* !FTFx_DRIVER_IS_FLASH_RESIDENT */ |
| switch (config->flashMemoryIndex) |
| { |
| case kFLASH_MemoryIndexSecondaryFlash: |
| MSCM_OCMDR1_REG = (MSCM_OCMDR1_REG & (~MSCM_CACHE_CLEAR_MASK)) | MSCM_CACHE_CLEAR(setValue); |
| /* Each cache clear instruction should be followed by below code*/ |
| __ISB(); |
| __DSB(); |
| break; |
| case kFLASH_MemoryIndexPrimaryFlash: |
| default: |
| MSCM_OCMDR0_REG = (MSCM_OCMDR0_REG & (~MSCM_CACHE_CLEAR_MASK)) | MSCM_CACHE_CLEAR(setValue); |
| /* Memory barriers for good measure. |
| * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ |
| __ISB(); |
| __DSB(); |
| break; |
| } |
| #endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */ |
| } |
| #endif /* FLASH_CACHE_IS_CONTROLLED_BY_MSCM */ |
| |
| #if FLASH_CACHE_IS_CONTROLLED_BY_FMC |
| /*! @brief Performs the cache clear to the flash by FMC.*/ |
| void fmc_flash_cache_clear(ftfx_cache_config_t *config) |
| { |
| #if FTFx_DRIVER_IS_FLASH_RESIDENT |
| /* Since the value of ARM function pointer is always odd, but the real start address |
| * of function memory should be even, that's why +1 operation exist. */ |
| callftfxCommonBitOperation_t callftfxCommonBitOperation = (callftfxCommonBitOperation_t)((uint32_t)config->comBitOperFuncAddr + 1); |
| callftfxCommonBitOperation((FTFx_REG32_ACCESS_TYPE)&FMC_CACHE_REG, FMC_CACHE_CLEAR_MASK, FMC_CACHE_CLEAR_SHIFT, 0xFU); |
| #else /* !FTFx_DRIVER_IS_FLASH_RESIDENT */ |
| FMC_CACHE_REG = (FMC_CACHE_REG & (~FMC_CACHE_CLEAR_MASK)) | FMC_CACHE_CLEAR(~0); |
| /* Memory barriers for good measure. |
| * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ |
| __ISB(); |
| __DSB(); |
| #endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */ |
| } |
| #endif /* FLASH_CACHE_IS_CONTROLLED_BY_FMC */ |
| |
| #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM |
| /*! @brief Performs the prefetch speculation buffer clear to the flash by MSCM.*/ |
| void mscm_flash_prefetch_speculation_enable(ftfx_cache_config_t *config, bool enable) |
| { |
| uint8_t setValue; |
| if (enable) |
| { |
| setValue = 0x0U; |
| } |
| else |
| { |
| setValue = 0x3U; |
| } |
| |
| /* The OCMDR[0] is always used to prefetch main Pflash*/ |
| /* For device with FlexNVM support, the OCMDR[1] is used to prefetch Dflash. |
| * For device with secondary flash support, the OCMDR[1] is used to prefetch secondary Pflash. */ |
| #if FTFx_DRIVER_IS_FLASH_RESIDENT |
| /* Since the value of ARM function pointer is always odd, but the real start address |
| * of function memory should be even, that's why +1 operation exist. */ |
| callftfxCommonBitOperation_t callftfxCommonBitOperation = (callftfxCommonBitOperation_t)((uint32_t)config->comBitOperFuncAddr + 1); |
| switch (config->flashMemoryIndex) |
| { |
| case 1: |
| callftfxCommonBitOperation((FTFx_REG32_ACCESS_TYPE)&MSCM_OCMDR1_REG, MSCM_SPECULATION_SET_MASK, |
| MSCM_SPECULATION_SET_SHIFT, setValue); |
| break; |
| case 0: |
| default: |
| callftfxCommonBitOperation((FTFx_REG32_ACCESS_TYPE)&MSCM_OCMDR0_REG, MSCM_SPECULATION_SET_MASK, |
| MSCM_SPECULATION_SET_SHIFT, setValue); |
| break; |
| } |
| #else /* !FTFx_DRIVER_IS_FLASH_RESIDENT */ |
| switch (config->flashMemoryIndex) |
| { |
| case kFLASH_MemoryIndexSecondaryFlash: |
| MSCM_OCMDR1_REG = (MSCM_OCMDR1_REG & (~MSCM_SPECULATION_SET_MASK)) | MSCM_SPECULATION_SET(setValue); |
| /* Each cache clear instruction should be followed by below code*/ |
| __ISB(); |
| __DSB(); |
| break; |
| case kFLASH_MemoryIndexPrimaryFlash: |
| default: |
| MSCM_OCMDR0_REG = (MSCM_OCMDR0_REG & (~MSCM_SPECULATION_SET_MASK)) | MSCM_SPECULATION_SET(setValue); |
| /* Memory barriers for good measure. |
| * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ |
| __ISB(); |
| __DSB(); |
| break; |
| } |
| #endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */ |
| } |
| #endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM */ |
| |
| #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC |
| /*! @brief Performs the prefetch speculation buffer clear to the flash by FMC.*/ |
| void fmc_flash_prefetch_speculation_clear(ftfx_cache_config_t *config) |
| { |
| #if FTFx_DRIVER_IS_FLASH_RESIDENT |
| /* Since the value of ARM function pointer is always odd, but the real start address |
| * of function memory should be even, that's why +1 operation exist. */ |
| callftfxCommonBitOperation_t callftfxCommonBitOperation = (callftfxCommonBitOperation_t)((uint32_t)config->comBitOperFuncAddr + 1); |
| callftfxCommonBitOperation((FTFx_REG32_ACCESS_TYPE)&FMC_SPECULATION_INVALIDATE_REG, FMC_SPECULATION_INVALIDATE_MASK, FMC_SPECULATION_INVALIDATE_SHIFT, 1U); |
| #else /* !FTFx_DRIVER_IS_FLASH_RESIDENT */ |
| FMC_SPECULATION_INVALIDATE_REG |= FMC_SPECULATION_INVALIDATE_MASK; |
| /* Memory barriers for good measure. |
| * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ |
| __ISB(); |
| __DSB(); |
| #endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */ |
| } |
| #endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC */ |
| |
| |