jacking/zynq/cache_cortexa.c

177 lines
4.0 KiB
C
Raw Permalink Normal View History

2022-01-29 01:26:40 +00:00
// stolen from
// https://github.com/Xilinx/embeddedsw/blob/master/lib/bsp/standalone/src/arm/cortexa9/xil_cache.c
#define IRQ_FIQ_MASK 0xC0
// CP15_CACHE_SIZE_SEL, CP15_CACHE_SIZE_ID, CP15_INVAL_IC_POU
// asm_cp15_inval_dc_line_sw
// asm_cp15_clean_inval_dc_line_sw
#define XREG_CP15_CACHE_SIZE_SEL "p15, 2, %0, c0, c0, 0"
#define XREG_CP15_CACHE_SIZE_ID "p15, 1, %0, c0, c0, 0"
#define XREG_CP15_INVAL_IC_POU "p15, 0, %0, c7, c5, 0"
#define XREG_CP15_INVAL_DC_LINE_SW "p15, 0, %0, c7, c6, 2"
#define XREG_CP15_CLEAN_INVAL_DC_LINE_SW "p15, 0, %0, c7, c14, 2"
#define asm_cp15_inval_dc_line_sw(param) __asm__ __volatile__("mcr " \
XREG_CP15_INVAL_DC_LINE_SW :: "r" (param)); \
#define asm_cp15_clean_inval_dc_line_sw(param) __asm__ __volatile__("mcr " \
XREG_CP15_CLEAN_INVAL_DC_LINE_SW :: "r" (param)); \
#define dsb() asm volatile("dsb":::"memory")
#define isb() asm volatile("isb":::"memory")
#define mfcpsr() ({uint32_t rval = 0U; \
__asm__ __volatile__(\
"mrs %0, cpsr\n"\
: "=r" (rval)\
);\
rval;\
}) \
#define mtcpsr(v) __asm__ __volatile__(\
"msr cpsr,%0\n"\
: : "r" (v) : "cc" \
) \
/* CP15 operations */
#define mtcp(rn, v) __asm__ __volatile__(\
"mcr " rn "\n"\
: : "r" (v)\
); \
#define mfcp(rn) ({uint32_t rval = 0U; \
__asm__ __volatile__(\
"mrc " rn "\n"\
: "=r" (rval)\
);\
rval;\
}) \
__attribute__((__unused__))
static void DC_InvalidateAll(void) {
register uint32_t CsidReg, C7Reg;
uint32_t CacheSize, LineSize, NumWays;
uint32_t Way, WayIndex, Set, SetIndex, NumSet;
uint32_t currmask;
currmask = mfcpsr();
mtcpsr(currmask | IRQ_FIQ_MASK);
/* Select cache level 0 and D cache in CSSR */
mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U);
CsidReg = mfcp(XREG_CP15_CACHE_SIZE_ID);
/* Determine Cache Size */
CacheSize = (CsidReg >> 13U) & 0x1FFU;
CacheSize +=1U;
CacheSize *=128U; /* to get number of bytes */
/* Number of Ways */
NumWays = (CsidReg & 0x3ffU) >> 3U;
NumWays += 1U;
/* Get the cacheline size, way size, index size from csidr */
LineSize = (CsidReg & 0x07U) + 4U;
NumSet = CacheSize/NumWays;
NumSet /= (0x00000001U << LineSize);
Way = 0U;
Set = 0U;
/* Invalidate all the cachelines */
for (WayIndex =0U; WayIndex < NumWays; WayIndex++) {
for (SetIndex =0U; SetIndex < NumSet; SetIndex++) {
C7Reg = Way | Set;
/* Invalidate by Set/Way */
asm_cp15_inval_dc_line_sw(C7Reg);
Set += (0x00000001U << LineSize);
}
Set=0U;
Way += 0x40000000U;
}
/* Wait for L1 invalidate to complete */
dsb();
mtcpsr(currmask);
}
static void DC_FlushAll(void) {
register uint32_t CsidReg, C7Reg;
uint32_t CacheSize, LineSize, NumWays;
uint32_t Way;
uint32_t WayIndex, Set, SetIndex, NumSet;
uint32_t currmask;
currmask = mfcpsr();
mtcpsr(currmask | IRQ_FIQ_MASK);
/* Select cache level 0 and D cache in CSSR */
mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
CsidReg = mfcp(XREG_CP15_CACHE_SIZE_ID);
/* Determine Cache Size */
CacheSize = (CsidReg >> 13U) & 0x1FFU;
CacheSize +=1U;
CacheSize *=128U; /* to get number of bytes */
/* Number of Ways */
NumWays = (CsidReg & 0x3ffU) >> 3U;
NumWays += 1U;
/* Get the cacheline size, way size, index size from csidr */
LineSize = (CsidReg & 0x07U) + 4U;
NumSet = CacheSize/NumWays;
NumSet /= (0x00000001U << LineSize);
Way = 0U;
Set = 0U;
/* Invalidate all the cachelines */
for (WayIndex =0U; WayIndex < NumWays; WayIndex++) {
for (SetIndex =0U; SetIndex < NumSet; SetIndex++) {
C7Reg = Way | Set;
/* Flush by Set/Way */
asm_cp15_clean_inval_dc_line_sw(C7Reg);
Set += (0x00000001U << LineSize);
}
Set = 0U;
Way += 0x40000000U;
}
/* Wait for L1 flush to complete */
dsb();
mtcpsr(currmask);
}
static void IC_InvalidateAll(void) {
mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U);
/* invalidate the instruction cache */
mtcp(XREG_CP15_INVAL_IC_POU, 0U);
/* Wait for L1 invalidate to complete */
dsb();
isb();
}
#undef dsb
#undef mfcpsr
#undef mtcpsr
#undef mtcp
#undef mfcp
#undef asm_cp15_inval_dc_line_sw
#undef asm_cp15_clean_inval_dc_line_sw
#undef IRQ_FIQ_MASK