227 lines
5.3 KiB
C
227 lines
5.3 KiB
C
#include "FreeRTOS.h"
|
|
#include "encoding.h"
|
|
#include "cache.h"
|
|
#include "barrier.h"
|
|
|
|
#ifdef __cplusplus
|
|
#if __cplusplus
|
|
extern "C" {
|
|
#endif /* __cplusplus */
|
|
#endif /* __cplusplus */
|
|
|
|
#define CACHE_PREF_LINES_MAX 7
|
|
|
|
uint32_t ArchICacheEnable(CacheSize icclSize)
|
|
{
|
|
if ((icclSize != CACHE_4KB) && (icclSize != CACHE_8KB) &&
|
|
(icclSize != CACHE_16KB) && (icclSize != CACHE_32KB)) {
|
|
return pdFAIL;
|
|
}
|
|
|
|
write_custom_csr(ICCTL, (uint32_t)((uint32_t)icclSize | ICCTL_ENABLE));
|
|
return pdPASS;
|
|
}
|
|
|
|
uint32_t ArchDCacheEnable(CacheSize dcclSize)
|
|
{
|
|
if ((dcclSize != CACHE_4KB) && (dcclSize != CACHE_8KB) &&
|
|
(dcclSize != CACHE_16KB) && (dcclSize != CACHE_32KB)) {
|
|
return pdFAIL;
|
|
}
|
|
|
|
write_custom_csr(DCCTL, (uint32_t)((uint32_t)dcclSize | DCCTL_ENABLE));
|
|
return pdPASS;
|
|
}
|
|
|
|
void ArchICacheInvAll(void)
|
|
{
|
|
write_custom_csr(ICMAINT, ICIV);
|
|
}
|
|
|
|
void ArchDCacheInvAll(void)
|
|
{
|
|
write_custom_csr(DCMAINT, DCIV);
|
|
}
|
|
|
|
uint32_t ArchICachePrefetchEnable(CachePrefLines iclValue)
|
|
{
|
|
if (iclValue > CACHE_PREF_LINES_MAX) {
|
|
return pdFAIL;
|
|
}
|
|
|
|
write_custom_csr(APREFI, (uint32_t)(((uint32_t)iclValue << 1) | IAPEN)); /* 1: ICL control bits */
|
|
return pdPASS;
|
|
}
|
|
|
|
uint32_t ArchDCachePrefetchEnable(CachePrefLines iclValue, CachePrefLines sclValue)
|
|
{
|
|
uint32_t value;
|
|
|
|
if ((iclValue > CACHE_PREF_LINES_MAX) || (sclValue > CACHE_PREF_LINES_MAX)) {
|
|
return pdFAIL;
|
|
}
|
|
|
|
value = ((uint32_t)iclValue << 1) | IAPEN; /* 1: ICL control bits */
|
|
value |= ((uint32_t)sclValue << 5) | SAPEN; /* 5: SCL control bits; */
|
|
write_custom_csr(APREFD, value);
|
|
return pdPASS;
|
|
}
|
|
|
|
void ArchICacheFlush(void)
|
|
{
|
|
write_custom_csr(ICMAINT, ICACHE_BY_ALL);
|
|
mb();
|
|
}
|
|
|
|
void ArchDCacheFlush(void)
|
|
{
|
|
unsigned int irq_status = uxHwiLock();
|
|
|
|
write_custom_csr(DCMAINT, DCACHE_FLUSH_ALL);
|
|
mb();
|
|
|
|
vHwiRestore(irq_status);
|
|
}
|
|
|
|
void ArchDCacheClean(void)
|
|
{
|
|
write_custom_csr(DCMAINT, DCACHE_CLEAN_ALL);
|
|
mb();
|
|
}
|
|
|
|
void ArchDCacheInv(void)
|
|
{
|
|
write_custom_csr(DCMAINT, DCIV);
|
|
mb();
|
|
}
|
|
|
|
void ArchICacheFlushByVa(uintptr_t baseAddr, uint32_t size)
|
|
{
|
|
uint32_t flushNum, count;
|
|
uintptr_t endAddr;
|
|
|
|
endAddr = baseAddr + size;
|
|
baseAddr = baseAddr & ~(CACHE_LINE_SIZE - 1);
|
|
|
|
endAddr = ALIGN(endAddr, CACHE_LINE_SIZE);
|
|
size = endAddr - baseAddr;
|
|
|
|
flushNum = size / CACHE_LINE_SIZE;
|
|
for (count = 0; count < flushNum; count++) {
|
|
write_custom_csr(ICINCVA, baseAddr); /* write cmo's va */
|
|
write_custom_csr(ICMAINT, ICACHE_BY_VA); /* enabel cmo(clean and invalidate) by va */
|
|
baseAddr += CACHE_LINE_SIZE;
|
|
}
|
|
|
|
mb();
|
|
}
|
|
|
|
static void DCacheOperate(uintptr_t baseAddr, uint32_t size, uint32_t config)
|
|
{
|
|
uint32_t flushNum, count;
|
|
uintptr_t endAddr;
|
|
|
|
unsigned int irq_status = uxHwiLock();
|
|
|
|
endAddr = baseAddr + size;
|
|
baseAddr = baseAddr & ~(CACHE_LINE_SIZE - 1);
|
|
|
|
endAddr = ALIGN(endAddr, CACHE_LINE_SIZE);
|
|
size = endAddr - baseAddr;
|
|
|
|
flushNum = size / CACHE_LINE_SIZE;
|
|
for (count = 0; count < flushNum; count++) {
|
|
write_custom_csr(DCINCVA, baseAddr); /* write cmo's va */
|
|
write_custom_csr(DCMAINT, config);
|
|
baseAddr += CACHE_LINE_SIZE;
|
|
}
|
|
|
|
mb();
|
|
vHwiRestore(irq_status);
|
|
}
|
|
|
|
void ArchDCacheFlushByVa(uintptr_t baseAddr, uint32_t size)
|
|
{
|
|
DCacheOperate(baseAddr, size, DCACHE_FLUSH_BY_VA);
|
|
}
|
|
|
|
void ArchDCacheInvByVa(uintptr_t baseAddr, uint32_t size)
|
|
{
|
|
uintptr_t OpStartAddr = baseAddr & ~(CACHE_LINE_SIZE - 1);
|
|
uintptr_t OpEndAddr = (baseAddr + size) & ~(CACHE_LINE_SIZE - 1);;
|
|
|
|
if (OpStartAddr != baseAddr) {
|
|
DCacheOperate(OpStartAddr, CACHE_LINE_SIZE, DCACHE_CLEAN_BY_VA);
|
|
}
|
|
|
|
if (OpEndAddr != (baseAddr + size)) {
|
|
DCacheOperate(OpEndAddr, CACHE_LINE_SIZE, DCACHE_CLEAN_BY_VA);
|
|
}
|
|
DCacheOperate(baseAddr, size, DCACHE_INV_BY_VA);
|
|
}
|
|
|
|
void ArchDCacheCleanByVa(uintptr_t baseAddr, uint32_t size)
|
|
{
|
|
DCacheOperate(baseAddr, size, DCACHE_CLEAN_BY_VA);
|
|
}
|
|
|
|
void ArchICacheFlushByAddr(uintptr_t startAddr, uintptr_t endAddr)
|
|
{
|
|
uint32_t size;
|
|
|
|
startAddr = (uint32_t)startAddr & ~(CACHE_LINE_SIZE - 1);
|
|
endAddr = ALIGN(endAddr, CACHE_LINE_SIZE);
|
|
size = endAddr - startAddr;
|
|
|
|
ArchICacheFlushByVa(startAddr, size);
|
|
}
|
|
|
|
void ArchDCacheFlushByAddr(uintptr_t startAddr, uintptr_t endAddr)
|
|
{
|
|
uint32_t size;
|
|
|
|
startAddr = (uint32_t)startAddr & ~(CACHE_LINE_SIZE - 1);
|
|
endAddr = ALIGN(endAddr, CACHE_LINE_SIZE);
|
|
size = endAddr - startAddr;
|
|
|
|
ArchDCacheFlushByVa(startAddr, size);
|
|
}
|
|
|
|
void ArchDCacheCleanByAddr(uintptr_t startAddr, uintptr_t endAddr)
|
|
{
|
|
uint32_t size;
|
|
|
|
startAddr = (uint32_t)startAddr & ~(CACHE_LINE_SIZE - 1);
|
|
endAddr = ALIGN(endAddr, CACHE_LINE_SIZE);
|
|
size = endAddr - startAddr;
|
|
|
|
ArchDCacheCleanByVa(startAddr, size);
|
|
}
|
|
|
|
void ArchDCacheInvByAddr(uintptr_t startAddr, uintptr_t endAddr)
|
|
{
|
|
uint32_t size;
|
|
|
|
startAddr = (uint32_t)startAddr & ~(CACHE_LINE_SIZE - 1);
|
|
endAddr = ALIGN(endAddr, CACHE_LINE_SIZE);
|
|
size = endAddr - startAddr;
|
|
|
|
DCacheOperate(startAddr, size, DCACHE_INV_BY_VA);
|
|
}
|
|
|
|
void dma_cache_clean(uintptr_t start, uintptr_t end)
|
|
{
|
|
ArchDCacheCleanByAddr(start, end);
|
|
}
|
|
|
|
void dma_cache_inv(uintptr_t start, uintptr_t end)
|
|
{
|
|
ArchDCacheInvByAddr(start, end);
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
#if __cplusplus
|
|
}
|
|
#endif /* __cplusplus */
|
|
#endif /* __cplusplus */
|