mcu_hi3321_watch/kernel/freertos/FreeRTOS/Arch/RISC-V/cache.c
2025-05-26 20:15:20 +08:00

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 */