2019-03-11 13:10:36 +08:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2016, Freescale Semiconductor, Inc.
|
|
|
|
* Copyright 2016-2017 NXP
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
2019-06-12 15:01:12 +08:00
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
2019-03-11 13:10:36 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "fsl_cache.h"
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* Definitions
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
/* Component ID definition, used by tools. */
|
|
|
|
#ifndef FSL_COMPONENT_ID
|
|
|
|
#define FSL_COMPONENT_ID "platform.drivers.cache_armv7_m7"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(FSL_FEATURE_SOC_L2CACHEC_COUNT) && FSL_FEATURE_SOC_L2CACHEC_COUNT
|
|
|
|
#define L2CACHE_OPERATION_TIMEOUT 0xFFFFFU
|
|
|
|
#define L2CACHE_8WAYS_MASK 0xFFU
|
|
|
|
#define L2CACHE_16WAYS_MASK 0xFFFFU
|
|
|
|
#define L2CACHE_SMALLWAYS_NUM 8U
|
|
|
|
#define L2CACHE_1KBCOVERTOB 1024U
|
|
|
|
#define L2CACHE_SAMLLWAYS_SIZE 16U
|
2019-06-12 15:01:12 +08:00
|
|
|
#define L2CACHE_LOCKDOWN_REGNUM 8 /*!< Lock down register numbers.*/
|
|
|
|
/*******************************************************************************
|
|
|
|
* Prototypes
|
|
|
|
******************************************************************************/
|
2019-03-11 13:10:36 +08:00
|
|
|
/*!
|
|
|
|
* @brief Set for all ways and waiting for the operation finished.
|
|
|
|
* This is provided for all the background operations.
|
|
|
|
*
|
|
|
|
* @param auxCtlReg The auxiliary control register.
|
|
|
|
* @param regAddr The register address to be operated.
|
|
|
|
*/
|
|
|
|
static void L2CACHE_SetAndWaitBackGroundOperate(uint32_t auxCtlReg, uint32_t regAddr);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Invalidates the Level 2 cache line by physical address.
|
|
|
|
* This function invalidates a cache line by physcial address.
|
|
|
|
*
|
|
|
|
* @param address The physical addderss of the cache.
|
|
|
|
* The format of the address shall be :
|
|
|
|
* bit 31 ~ bit n+1 | bitn ~ bit5 | bit4 ~ bit0
|
|
|
|
* Tag | index | 0
|
|
|
|
* Note: the physical address shall be aligned to the line size - 32B (256 bit).
|
|
|
|
* so keep the last 5 bits (bit 4 ~ bit 0) of the physical address always be zero.
|
|
|
|
* If the input address is not aligned, it will be changed to 32-byte aligned address.
|
|
|
|
* The n is varies according to the index width.
|
|
|
|
* @return The actual 32-byte aligned physical address be operated.
|
|
|
|
*/
|
|
|
|
static uint32_t L2CACHE_InvalidateLineByAddr(uint32_t address);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Cleans the Level 2 cache line based on the physical address.
|
|
|
|
* This function cleans a cache line based on a physcial address.
|
|
|
|
*
|
|
|
|
* @param address The physical addderss of the cache.
|
|
|
|
* The format of the address shall be :
|
|
|
|
* bit 31 ~ bit n+1 | bitn ~ bit5 | bit4 ~ bit0
|
|
|
|
* Tag | index | 0
|
|
|
|
* Note: the physical address shall be aligned to the line size - 32B (256 bit).
|
|
|
|
* so keep the last 5 bits (bit 4 ~ bit 0) of the physical address always be zero.
|
|
|
|
* If the input address is not aligned, it will be changed to 32-byte aligned address.
|
|
|
|
* The n is varies according to the index width.
|
|
|
|
* @return The actual 32-byte aligned physical address be operated.
|
|
|
|
*/
|
|
|
|
static uint32_t L2CACHE_CleanLineByAddr(uint32_t address);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Cleans and invalidates the Level 2 cache line based on the physical address.
|
|
|
|
* This function cleans and invalidates a cache line based on a physcial address.
|
|
|
|
*
|
|
|
|
* @param address The physical addderss of the cache.
|
|
|
|
* The format of the address shall be :
|
|
|
|
* bit 31 ~ bit n+1 | bitn ~ bit5 | bit4 ~ bit0
|
|
|
|
* Tag | index | 0
|
|
|
|
* Note: the physical address shall be aligned to the line size - 32B (256 bit).
|
|
|
|
* so keep the last 5 bits (bit 4 ~ bit 0) of the physical address always be zero.
|
|
|
|
* If the input address is not aligned, it will be changed to 32-byte aligned address.
|
|
|
|
* The n is varies according to the index width.
|
|
|
|
* @return The actual 32-byte aligned physical address be operated.
|
|
|
|
*/
|
|
|
|
static uint32_t L2CACHE_CleanInvalidateLineByAddr(uint32_t address);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Gets the number of the Level 2 cache and the way size.
|
|
|
|
* This function cleans and invalidates a cache line based on a physcial address.
|
|
|
|
*
|
|
|
|
* @param num_ways The number of the cache way.
|
|
|
|
* @param size_way The way size.
|
|
|
|
*/
|
|
|
|
static void L2CACHE_GetWayNumSize(uint32_t *num_ways, uint32_t *size_way);
|
|
|
|
/*******************************************************************************
|
|
|
|
* Code
|
|
|
|
******************************************************************************/
|
|
|
|
static void L2CACHE_SetAndWaitBackGroundOperate(uint32_t auxCtlReg, uint32_t regAddr)
|
|
|
|
{
|
|
|
|
uint16_t mask = L2CACHE_8WAYS_MASK;
|
|
|
|
uint32_t timeout = L2CACHE_OPERATION_TIMEOUT;
|
|
|
|
|
|
|
|
/* Check the ways used at first. */
|
|
|
|
if (auxCtlReg & L2CACHEC_REG1_AUX_CONTROL_ASSOCIATIVITY_MASK)
|
|
|
|
{
|
|
|
|
mask = L2CACHE_16WAYS_MASK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the opeartion for all ways/entries of the cache. */
|
|
|
|
*(uint32_t *)regAddr = mask;
|
|
|
|
/* Waiting for until the operation is complete. */
|
|
|
|
while ((*(volatile uint32_t *)regAddr & mask) && timeout)
|
|
|
|
{
|
|
|
|
__ASM("nop");
|
|
|
|
timeout--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint32_t L2CACHE_InvalidateLineByAddr(uint32_t address)
|
|
|
|
{
|
|
|
|
/* Align the address first. */
|
|
|
|
address &= ~(uint32_t)(FSL_FEATURE_L2CACHE_LINESIZE_BYTE - 1);
|
|
|
|
/* Invalidate the cache line by physical address. */
|
|
|
|
L2CACHEC->REG7_INV_PA = address;
|
|
|
|
|
|
|
|
return address;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint32_t L2CACHE_CleanLineByAddr(uint32_t address)
|
|
|
|
{
|
|
|
|
/* Align the address first. */
|
|
|
|
address &= ~(uint32_t)(FSL_FEATURE_L2CACHE_LINESIZE_BYTE - 1);
|
|
|
|
/* Invalidate the cache line by physical address. */
|
|
|
|
L2CACHEC->REG7_CLEAN_PA = address;
|
|
|
|
|
|
|
|
return address;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint32_t L2CACHE_CleanInvalidateLineByAddr(uint32_t address)
|
|
|
|
{
|
|
|
|
/* Align the address first. */
|
|
|
|
address &= ~(uint32_t)(FSL_FEATURE_L2CACHE_LINESIZE_BYTE - 1);
|
|
|
|
/* Clean and invalidate the cache line by physical address. */
|
|
|
|
L2CACHEC->REG7_CLEAN_INV_PA = address;
|
|
|
|
|
|
|
|
return address;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void L2CACHE_GetWayNumSize(uint32_t *num_ways, uint32_t *size_way)
|
|
|
|
{
|
|
|
|
assert(num_ways);
|
|
|
|
assert(size_way);
|
|
|
|
|
|
|
|
uint32_t number = (L2CACHEC->REG1_AUX_CONTROL & L2CACHEC_REG1_AUX_CONTROL_ASSOCIATIVITY_MASK) >>
|
|
|
|
L2CACHEC_REG1_AUX_CONTROL_ASSOCIATIVITY_SHIFT;
|
|
|
|
uint32_t size = (L2CACHEC->REG1_AUX_CONTROL & L2CACHEC_REG1_AUX_CONTROL_WAYSIZE_MASK) >>
|
|
|
|
L2CACHEC_REG1_AUX_CONTROL_WAYSIZE_SHIFT;
|
|
|
|
|
|
|
|
*num_ways = (number + 1) * L2CACHE_SMALLWAYS_NUM;
|
|
|
|
if (!size)
|
|
|
|
{
|
|
|
|
/* 0 internally mapped to the same size as 1 - 16KB.*/
|
|
|
|
size += 1;
|
|
|
|
}
|
|
|
|
*size_way = (1 << (size - 1)) * L2CACHE_SAMLLWAYS_SIZE * L2CACHE_1KBCOVERTOB;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Initializes the level 2 cache controller module.
|
|
|
|
*
|
|
|
|
* param config Pointer to configuration structure. See "l2cache_config_t".
|
|
|
|
*/
|
2019-03-11 13:10:36 +08:00
|
|
|
void L2CACHE_Init(l2cache_config_t *config)
|
|
|
|
{
|
2019-06-12 15:01:12 +08:00
|
|
|
assert(config);
|
|
|
|
|
2019-03-11 13:10:36 +08:00
|
|
|
uint16_t waysNum = 0xFFU; /* Default use the 8-way mask. */
|
|
|
|
uint8_t count;
|
|
|
|
uint32_t auxReg = 0;
|
|
|
|
|
|
|
|
/*The aux register must be configured when the cachec is disabled
|
|
|
|
* So disable first if the cache controller is enabled.
|
|
|
|
*/
|
|
|
|
if (L2CACHEC->REG1_CONTROL & L2CACHEC_REG1_CONTROL_CE_MASK)
|
|
|
|
{
|
|
|
|
L2CACHE_Disable();
|
2019-06-12 15:01:12 +08:00
|
|
|
}
|
2019-03-11 13:10:36 +08:00
|
|
|
|
|
|
|
/* Unlock all entries. */
|
|
|
|
if (L2CACHEC->REG1_AUX_CONTROL & L2CACHEC_REG1_AUX_CONTROL_ASSOCIATIVITY_MASK)
|
|
|
|
{
|
|
|
|
waysNum = 0xFFFFU;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
for (count = 0; count < L2CACHE_LOCKDOWN_REGNUM; count++)
|
2019-03-11 13:10:36 +08:00
|
|
|
{
|
2019-06-12 15:01:12 +08:00
|
|
|
L2CACHE_LockdownByWayEnable(count, waysNum, false);
|
2019-03-11 13:10:36 +08:00
|
|
|
}
|
2019-06-12 15:01:12 +08:00
|
|
|
|
2019-03-11 13:10:36 +08:00
|
|
|
/* Set the ways and way-size etc. */
|
|
|
|
auxReg = L2CACHEC_REG1_AUX_CONTROL_ASSOCIATIVITY(config->wayNum) |
|
2019-06-12 15:01:12 +08:00
|
|
|
L2CACHEC_REG1_AUX_CONTROL_WAYSIZE(config->waySize) | L2CACHEC_REG1_AUX_CONTROL_CRP(config->repacePolicy) |
|
|
|
|
L2CACHEC_REG1_AUX_CONTROL_IPE(config->istrPrefetchEnable) |
|
|
|
|
L2CACHEC_REG1_AUX_CONTROL_DPE(config->dataPrefetchEnable) |
|
|
|
|
L2CACHEC_REG1_AUX_CONTROL_NLE(config->nsLockdownEnable) |
|
|
|
|
L2CACHEC_REG1_AUX_CONTROL_FWA(config->writeAlloc) | L2CACHEC_REG1_AUX_CONTROL_HPSDRE(config->writeAlloc);
|
2019-03-11 13:10:36 +08:00
|
|
|
L2CACHEC->REG1_AUX_CONTROL = auxReg;
|
|
|
|
|
|
|
|
/* Set the tag/data ram latency. */
|
|
|
|
if (config->lateConfig)
|
|
|
|
{
|
|
|
|
uint32_t data = 0;
|
|
|
|
/* Tag latency. */
|
2019-06-12 15:01:12 +08:00
|
|
|
data = L2CACHEC_REG1_TAG_RAM_CONTROL_SL(config->lateConfig->tagSetupLate) |
|
|
|
|
L2CACHEC_REG1_TAG_RAM_CONTROL_SL(config->lateConfig->tagSetupLate) |
|
|
|
|
L2CACHEC_REG1_TAG_RAM_CONTROL_RAL(config->lateConfig->tagReadLate) |
|
|
|
|
L2CACHEC_REG1_TAG_RAM_CONTROL_WAL(config->lateConfig->dataWriteLate);
|
2019-03-11 13:10:36 +08:00
|
|
|
L2CACHEC->REG1_TAG_RAM_CONTROL = data;
|
|
|
|
/* Data latency. */
|
2019-06-12 15:01:12 +08:00
|
|
|
data = L2CACHEC_REG1_DATA_RAM_CONTROL_SL(config->lateConfig->dataSetupLate) |
|
|
|
|
L2CACHEC_REG1_DATA_RAM_CONTROL_SL(config->lateConfig->dataSetupLate) |
|
|
|
|
L2CACHEC_REG1_DATA_RAM_CONTROL_RAL(config->lateConfig->dataReadLate) |
|
|
|
|
L2CACHEC_REG1_DATA_RAM_CONTROL_WAL(config->lateConfig->dataWriteLate);
|
2019-03-11 13:10:36 +08:00
|
|
|
L2CACHEC->REG1_DATA_RAM_CONTROL = data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Gets an available default settings for the cache controller.
|
|
|
|
*
|
|
|
|
* This function initializes the cache controller configuration structure with default settings.
|
|
|
|
* The default values are:
|
|
|
|
* code
|
|
|
|
* config->waysNum = kL2CACHE_8ways;
|
|
|
|
* config->waySize = kL2CACHE_32KbSize;
|
|
|
|
* config->repacePolicy = kL2CACHE_Roundrobin;
|
|
|
|
* config->lateConfig = NULL;
|
|
|
|
* config->istrPrefetchEnable = false;
|
|
|
|
* config->dataPrefetchEnable = false;
|
|
|
|
* config->nsLockdownEnable = false;
|
|
|
|
* config->writeAlloc = kL2CACHE_UseAwcache;
|
|
|
|
* endcode
|
|
|
|
* param config Pointer to the configuration structure.
|
|
|
|
*/
|
2019-03-11 13:10:36 +08:00
|
|
|
void L2CACHE_GetDefaultConfig(l2cache_config_t *config)
|
|
|
|
{
|
|
|
|
assert(config);
|
2019-06-12 15:01:12 +08:00
|
|
|
|
|
|
|
/* Initializes the configure structure to zero. */
|
|
|
|
memset(config, 0, sizeof(*config));
|
|
|
|
|
2019-03-11 13:10:36 +08:00
|
|
|
uint32_t number = (L2CACHEC->REG1_AUX_CONTROL & L2CACHEC_REG1_AUX_CONTROL_ASSOCIATIVITY_MASK) >>
|
|
|
|
L2CACHEC_REG1_AUX_CONTROL_ASSOCIATIVITY_SHIFT;
|
|
|
|
uint32_t size = (L2CACHEC->REG1_AUX_CONTROL & L2CACHEC_REG1_AUX_CONTROL_WAYSIZE_MASK) >>
|
|
|
|
L2CACHEC_REG1_AUX_CONTROL_WAYSIZE_SHIFT;
|
|
|
|
|
|
|
|
/* Get the default value */
|
|
|
|
config->wayNum = (l2cache_way_num_t)number;
|
|
|
|
config->waySize = (l2cache_way_size)size;
|
|
|
|
config->repacePolicy = kL2CACHE_Roundrobin;
|
|
|
|
config->lateConfig = NULL;
|
|
|
|
config->istrPrefetchEnable = false;
|
|
|
|
config->dataPrefetchEnable = false;
|
|
|
|
config->nsLockdownEnable = false;
|
2019-06-12 15:01:12 +08:00
|
|
|
config->writeAlloc = kL2CACHE_UseAwcache;
|
2019-03-11 13:10:36 +08:00
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Enables the level 2 cache controller.
|
|
|
|
* This function enables the cache controller. Must be written using a secure access.
|
|
|
|
* If write with a Non-secure access will cause a DECERR response.
|
|
|
|
*
|
|
|
|
*/
|
2019-03-11 13:10:36 +08:00
|
|
|
void L2CACHE_Enable(void)
|
|
|
|
{
|
|
|
|
/* Invalidate first. */
|
|
|
|
L2CACHE_Invalidate();
|
|
|
|
/* Enable the level 2 cache controller. */
|
|
|
|
L2CACHEC->REG1_CONTROL = L2CACHEC_REG1_CONTROL_CE_MASK;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Disables the level 2 cache controller.
|
|
|
|
* This function disables the cache controller. Must be written using a secure access.
|
|
|
|
* If write with a Non-secure access will cause a DECERR response.
|
|
|
|
*
|
|
|
|
*/
|
2019-03-11 13:10:36 +08:00
|
|
|
void L2CACHE_Disable(void)
|
|
|
|
{
|
|
|
|
/* First CleanInvalidate all enties in the cache. */
|
|
|
|
L2CACHE_CleanInvalidate();
|
|
|
|
/* Disable the level 2 cache controller. */
|
|
|
|
L2CACHEC->REG1_CONTROL &= ~L2CACHEC_REG1_CONTROL_CE_MASK;
|
|
|
|
/* DSB - data sync barrier.*/
|
|
|
|
__DSB();
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Invalidates the Level 2 cache.
|
|
|
|
* This function invalidates all entries in cache.
|
|
|
|
*
|
|
|
|
*/
|
2019-03-11 13:10:36 +08:00
|
|
|
void L2CACHE_Invalidate(void)
|
|
|
|
{
|
|
|
|
/* Invalidate all entries in cache. */
|
|
|
|
L2CACHE_SetAndWaitBackGroundOperate(L2CACHEC->REG1_AUX_CONTROL, (uint32_t)&L2CACHEC->REG7_INV_WAY);
|
|
|
|
/* Cache sync. */
|
|
|
|
L2CACHEC->REG7_CACHE_SYNC = 0;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Cleans the level 2 cache controller.
|
|
|
|
* This function cleans all entries in the level 2 cache controller.
|
|
|
|
*
|
|
|
|
*/
|
2019-03-11 13:10:36 +08:00
|
|
|
void L2CACHE_Clean(void)
|
|
|
|
{
|
|
|
|
/* Clean all entries of the cache. */
|
|
|
|
L2CACHE_SetAndWaitBackGroundOperate(L2CACHEC->REG1_AUX_CONTROL, (uint32_t)&L2CACHEC->REG7_CLEAN_WAY);
|
|
|
|
/* Cache sync. */
|
|
|
|
L2CACHEC->REG7_CACHE_SYNC = 0;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Cleans and invalidates the level 2 cache controller.
|
|
|
|
* This function cleans and invalidates all entries in the level 2 cache controller.
|
|
|
|
*
|
|
|
|
*/
|
2019-03-11 13:10:36 +08:00
|
|
|
void L2CACHE_CleanInvalidate(void)
|
|
|
|
{
|
|
|
|
/* Clean all entries of the cache. */
|
|
|
|
L2CACHE_SetAndWaitBackGroundOperate(L2CACHEC->REG1_AUX_CONTROL, (uint32_t)&L2CACHEC->REG7_CLEAN_INV_WAY);
|
|
|
|
/* Cache sync. */
|
|
|
|
L2CACHEC->REG7_CACHE_SYNC = 0;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Invalidates the Level 2 cache lines in the range of two physical addresses.
|
|
|
|
* This function invalidates all cache lines between two physical addresses.
|
|
|
|
*
|
|
|
|
* param address The start address of the memory to be invalidated.
|
|
|
|
* param size_byte The memory size.
|
|
|
|
* note The start address and size_byte should be 32-byte(FSL_FEATURE_L2CACHE_LINESIZE_BYTE) aligned.
|
|
|
|
* The startAddr here will be forced to align to L2 line size if startAddr
|
|
|
|
* is not aligned. For the size_byte, application should make sure the
|
|
|
|
* alignment or make sure the right operation order if the size_byte is not aligned.
|
|
|
|
*/
|
2019-03-11 13:10:36 +08:00
|
|
|
void L2CACHE_InvalidateByRange(uint32_t address, uint32_t size_byte)
|
|
|
|
{
|
|
|
|
uint32_t endAddr = address + size_byte;
|
|
|
|
|
|
|
|
/* Invalidate addresses in the range. */
|
|
|
|
while (address < endAddr)
|
|
|
|
{
|
|
|
|
address = L2CACHE_InvalidateLineByAddr(address);
|
|
|
|
/* Update the size. */
|
|
|
|
address += FSL_FEATURE_L2CACHE_LINESIZE_BYTE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Cache sync. */
|
|
|
|
L2CACHEC->REG7_CACHE_SYNC = 0;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Cleans the Level 2 cache lines in the range of two physical addresses.
|
|
|
|
* This function cleans all cache lines between two physical addresses.
|
|
|
|
*
|
|
|
|
* param address The start address of the memory to be cleaned.
|
|
|
|
* param size_byte The memory size.
|
|
|
|
* note The start address and size_byte should be 32-byte(FSL_FEATURE_L2CACHE_LINESIZE_BYTE) aligned.
|
|
|
|
* The startAddr here will be forced to align to L2 line size if startAddr
|
|
|
|
* is not aligned. For the size_byte, application should make sure the
|
|
|
|
* alignment or make sure the right operation order if the size_byte is not aligned.
|
|
|
|
*/
|
2019-03-11 13:10:36 +08:00
|
|
|
void L2CACHE_CleanByRange(uint32_t address, uint32_t size_byte)
|
|
|
|
{
|
|
|
|
uint32_t num_ways = 0;
|
|
|
|
uint32_t size_way = 0;
|
|
|
|
uint32_t endAddr = address + size_byte;
|
|
|
|
|
|
|
|
/* Get the number and size of the cache way. */
|
|
|
|
L2CACHE_GetWayNumSize(&num_ways, &size_way);
|
|
|
|
|
|
|
|
/* Check if the clean size is over the cache size. */
|
|
|
|
if ((endAddr - address) > num_ways * size_way)
|
|
|
|
{
|
|
|
|
L2CACHE_Clean();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Clean addresses in the range. */
|
|
|
|
while ((address & ~(uint32_t)(FSL_FEATURE_L2CACHE_LINESIZE_BYTE - 1)) < endAddr)
|
|
|
|
{
|
|
|
|
/* Clean the address in the range. */
|
|
|
|
address = L2CACHE_CleanLineByAddr(address);
|
|
|
|
address += FSL_FEATURE_L2CACHE_LINESIZE_BYTE;
|
|
|
|
}
|
|
|
|
|
|
|
|
L2CACHEC->REG7_CACHE_SYNC = 0;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Cleans and invalidates the Level 2 cache lines in the range of two physical addresses.
|
|
|
|
* This function cleans and invalidates all cache lines between two physical addresses.
|
|
|
|
*
|
|
|
|
* param address The start address of the memory to be cleaned and invalidated.
|
|
|
|
* param size_byte The memory size.
|
|
|
|
* note The start address and size_byte should be 32-byte(FSL_FEATURE_L2CACHE_LINESIZE_BYTE) aligned.
|
|
|
|
* The startAddr here will be forced to align to L2 line size if startAddr
|
|
|
|
* is not aligned. For the size_byte, application should make sure the
|
|
|
|
* alignment or make sure the right operation order if the size_byte is not aligned.
|
|
|
|
*/
|
2019-03-11 13:10:36 +08:00
|
|
|
void L2CACHE_CleanInvalidateByRange(uint32_t address, uint32_t size_byte)
|
|
|
|
{
|
|
|
|
uint32_t num_ways = 0;
|
|
|
|
uint32_t size_way = 0;
|
|
|
|
uint32_t endAddr = address + size_byte;
|
|
|
|
|
|
|
|
/* Get the number and size of the cache way. */
|
|
|
|
L2CACHE_GetWayNumSize(&num_ways, &size_way);
|
|
|
|
|
|
|
|
/* Check if the clean size is over the cache size. */
|
|
|
|
if ((endAddr - address) > num_ways * size_way)
|
|
|
|
{
|
|
|
|
L2CACHE_CleanInvalidate();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Clean addresses in the range. */
|
|
|
|
while ((address & ~(uint32_t)(FSL_FEATURE_L2CACHE_LINESIZE_BYTE - 1)) < endAddr)
|
|
|
|
{
|
|
|
|
/* Clean the address in the range. */
|
|
|
|
address = L2CACHE_CleanInvalidateLineByAddr(address);
|
|
|
|
address += FSL_FEATURE_L2CACHE_LINESIZE_BYTE;
|
|
|
|
}
|
|
|
|
|
|
|
|
L2CACHEC->REG7_CACHE_SYNC = 0;
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Enables or disables to lock down the data and instruction by way.
|
|
|
|
* This function locks down the cached instruction/data by way and prevent the adresses from
|
|
|
|
* being allocated and prevent dara from being evicted out of the level 2 cache.
|
|
|
|
* But the normal cache maintenance operations that invalidate, clean or clean
|
|
|
|
* and validate cache contents affect the locked-down cache lines as normal.
|
|
|
|
*
|
|
|
|
* param masterId The master id, range from 0 ~ 7.
|
|
|
|
* param mask The ways to be enabled or disabled to lockdown.
|
|
|
|
* each bit in value is related to each way of the cache. for example:
|
|
|
|
* value: bit 0 ------ way 0.
|
|
|
|
* value: bit 1 ------ way 1.
|
|
|
|
* --------------------------
|
|
|
|
* value: bit 15 ------ way 15.
|
|
|
|
* Note: please make sure the value setting is align with your supported ways.
|
|
|
|
* param enable True enable the lockdown, false to disable the lockdown.
|
|
|
|
*/
|
2019-03-11 13:10:36 +08:00
|
|
|
void L2CACHE_LockdownByWayEnable(uint32_t masterId, uint32_t mask, bool enable)
|
|
|
|
{
|
|
|
|
uint8_t num_ways = (L2CACHEC->REG1_AUX_CONTROL & L2CACHEC_REG1_AUX_CONTROL_ASSOCIATIVITY_MASK) >>
|
|
|
|
L2CACHEC_REG1_AUX_CONTROL_ASSOCIATIVITY_SHIFT;
|
|
|
|
num_ways = (num_ways + 1) * L2CACHE_SMALLWAYS_NUM;
|
|
|
|
|
|
|
|
assert(mask < (1U << num_ways));
|
|
|
|
assert(masterId < L2CACHE_LOCKDOWN_REGNUM);
|
|
|
|
|
|
|
|
uint32_t dataReg = L2CACHEC->LOCKDOWN[masterId].REG9_D_LOCKDOWN;
|
|
|
|
uint32_t istrReg = L2CACHEC->LOCKDOWN[masterId].REG9_I_LOCKDOWN;
|
|
|
|
|
|
|
|
if (enable)
|
|
|
|
{
|
|
|
|
/* Data lockdown. */
|
|
|
|
L2CACHEC->LOCKDOWN[masterId].REG9_D_LOCKDOWN = dataReg | mask;
|
|
|
|
/* Instruction lockdown. */
|
|
|
|
L2CACHEC->LOCKDOWN[masterId].REG9_I_LOCKDOWN = istrReg | mask;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Data lockdown. */
|
|
|
|
L2CACHEC->LOCKDOWN[masterId].REG9_D_LOCKDOWN = dataReg & ~mask;
|
|
|
|
/* Instruction lockdown. */
|
|
|
|
L2CACHEC->LOCKDOWN[masterId].REG9_I_LOCKDOWN = istrReg & ~mask;
|
|
|
|
}
|
|
|
|
}
|
2019-06-12 15:01:12 +08:00
|
|
|
#endif /* FSL_FEATURE_SOC_L2CACHEC_COUNT */
|
2019-03-11 13:10:36 +08:00
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Invalidate cortex-m7 L1 instruction cache by range.
|
|
|
|
*
|
|
|
|
* param address The start address of the memory to be invalidated.
|
|
|
|
* param size_byte The memory size.
|
|
|
|
* note The start address and size_byte should be 32-byte(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE) aligned.
|
|
|
|
* The startAddr here will be forced to align to L1 I-cache line size if
|
|
|
|
* startAddr is not aligned. For the size_byte, application should make sure the
|
|
|
|
* alignment or make sure the right operation order if the size_byte is not aligned.
|
|
|
|
*/
|
2019-03-11 13:10:36 +08:00
|
|
|
void L1CACHE_InvalidateICacheByRange(uint32_t address, uint32_t size_byte)
|
|
|
|
{
|
|
|
|
#if (__DCACHE_PRESENT == 1U)
|
2019-06-12 15:01:12 +08:00
|
|
|
uint32_t addr = address & (uint32_t) ~(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE - 1);
|
2019-03-11 13:10:36 +08:00
|
|
|
int32_t size = size_byte + address - addr;
|
|
|
|
uint32_t linesize = 32U;
|
|
|
|
|
|
|
|
__DSB();
|
|
|
|
while (size > 0)
|
|
|
|
{
|
|
|
|
SCB->ICIMVAU = addr;
|
|
|
|
addr += linesize;
|
|
|
|
size -= linesize;
|
|
|
|
}
|
|
|
|
__DSB();
|
|
|
|
__ISB();
|
2019-06-12 15:01:12 +08:00
|
|
|
#endif
|
2019-03-11 13:10:36 +08:00
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Invalidates all instruction caches by range.
|
|
|
|
*
|
|
|
|
* Both cortex-m7 L1 cache line and L2 PL310 cache line length is 32-byte.
|
|
|
|
*
|
|
|
|
* param address The physical address.
|
|
|
|
* param size_byte size of the memory to be invalidated.
|
|
|
|
* note address and size should be aligned to cache line size
|
|
|
|
* 32-Byte due to the cache operation unit is one cache line. The startAddr here will be forced
|
|
|
|
* to align to the cache line size if startAddr is not aligned. For the size_byte, application should
|
|
|
|
* make sure the alignment or make sure the right operation order if the size_byte is not aligned.
|
|
|
|
*/
|
2019-03-11 13:10:36 +08:00
|
|
|
void ICACHE_InvalidateByRange(uint32_t address, uint32_t size_byte)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SOC_L2CACHEC_COUNT) && FSL_FEATURE_SOC_L2CACHEC_COUNT
|
|
|
|
#if defined(FSL_SDK_DISBLE_L2CACHE_PRESENT) && !FSL_SDK_DISBLE_L2CACHE_PRESENT
|
|
|
|
L2CACHE_InvalidateByRange(address, size_byte);
|
|
|
|
#endif /* !FSL_SDK_DISBLE_L2CACHE_PRESENT */
|
|
|
|
#endif /* FSL_FEATURE_SOC_L2CACHEC_COUNT */
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
L1CACHE_InvalidateICacheByRange(address, size_byte);
|
2019-03-11 13:10:36 +08:00
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Invalidates all data caches by range.
|
|
|
|
*
|
|
|
|
* Both cortex-m7 L1 cache line and L2 PL310 cache line length is 32-byte.
|
|
|
|
*
|
|
|
|
* param address The physical address.
|
|
|
|
* param size_byte size of the memory to be invalidated.
|
|
|
|
* note address and size should be aligned to cache line size
|
|
|
|
* 32-Byte due to the cache operation unit is one cache line. The startAddr here will be forced
|
|
|
|
* to align to the cache line size if startAddr is not aligned. For the size_byte, application should
|
|
|
|
* make sure the alignment or make sure the right operation order if the size_byte is not aligned.
|
|
|
|
*/
|
2019-03-11 13:10:36 +08:00
|
|
|
void DCACHE_InvalidateByRange(uint32_t address, uint32_t size_byte)
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_SOC_L2CACHEC_COUNT) && FSL_FEATURE_SOC_L2CACHEC_COUNT
|
|
|
|
#if defined(FSL_SDK_DISBLE_L2CACHE_PRESENT) && !FSL_SDK_DISBLE_L2CACHE_PRESENT
|
|
|
|
L2CACHE_InvalidateByRange(address, size_byte);
|
|
|
|
#endif /* !FSL_SDK_DISBLE_L2CACHE_PRESENT */
|
|
|
|
#endif /* FSL_FEATURE_SOC_L2CACHEC_COUNT */
|
|
|
|
L1CACHE_InvalidateDCacheByRange(address, size_byte);
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Cleans all data caches by range.
|
|
|
|
*
|
|
|
|
* Both cortex-m7 L1 cache line and L2 PL310 cache line length is 32-byte.
|
|
|
|
*
|
|
|
|
* param address The physical address.
|
|
|
|
* param size_byte size of the memory to be cleaned.
|
|
|
|
* note address and size should be aligned to cache line size
|
|
|
|
* 32-Byte due to the cache operation unit is one cache line. The startAddr here will be forced
|
|
|
|
* to align to the cache line size if startAddr is not aligned. For the size_byte, application should
|
|
|
|
* make sure the alignment or make sure the right operation order if the size_byte is not aligned.
|
|
|
|
*/
|
2019-03-11 13:10:36 +08:00
|
|
|
void DCACHE_CleanByRange(uint32_t address, uint32_t size_byte)
|
|
|
|
{
|
|
|
|
L1CACHE_CleanDCacheByRange(address, size_byte);
|
|
|
|
#if defined(FSL_FEATURE_SOC_L2CACHEC_COUNT) && FSL_FEATURE_SOC_L2CACHEC_COUNT
|
|
|
|
#if defined(FSL_SDK_DISBLE_L2CACHE_PRESENT) && !FSL_SDK_DISBLE_L2CACHE_PRESENT
|
|
|
|
L2CACHE_CleanByRange(address, size_byte);
|
|
|
|
#endif /* !FSL_SDK_DISBLE_L2CACHE_PRESENT */
|
|
|
|
#endif /* FSL_FEATURE_SOC_L2CACHEC_COUNT */
|
|
|
|
}
|
|
|
|
|
2019-06-12 15:01:12 +08:00
|
|
|
/*!
|
|
|
|
* brief Cleans and Invalidates all data caches by range.
|
|
|
|
*
|
|
|
|
* Both cortex-m7 L1 cache line and L2 PL310 cache line length is 32-byte.
|
|
|
|
*
|
|
|
|
* param address The physical address.
|
|
|
|
* param size_byte size of the memory to be cleaned and invalidated.
|
|
|
|
* note address and size should be aligned to cache line size
|
|
|
|
* 32-Byte due to the cache operation unit is one cache line. The startAddr here will be forced
|
|
|
|
* to align to the cache line size if startAddr is not aligned. For the size_byte, application should
|
|
|
|
* make sure the alignment or make sure the right operation order if the size_byte is not aligned.
|
|
|
|
*/
|
2019-03-11 13:10:36 +08:00
|
|
|
void DCACHE_CleanInvalidateByRange(uint32_t address, uint32_t size_byte)
|
|
|
|
{
|
|
|
|
L1CACHE_CleanInvalidateDCacheByRange(address, size_byte);
|
|
|
|
#if defined(FSL_FEATURE_SOC_L2CACHEC_COUNT) && FSL_FEATURE_SOC_L2CACHEC_COUNT
|
|
|
|
#if defined(FSL_SDK_DISBLE_L2CACHE_PRESENT) && !FSL_SDK_DISBLE_L2CACHE_PRESENT
|
|
|
|
L2CACHE_CleanInvalidateByRange(address, size_byte);
|
|
|
|
#endif /* !FSL_SDK_DISBLE_L2CACHE_PRESENT */
|
|
|
|
#endif /* FSL_FEATURE_SOC_L2CACHEC_COUNT */
|
|
|
|
}
|