1 /******************************************************************************
3 * Copyright (C) 2014 - 2015 Xilinx, Inc. All rights reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
31 ******************************************************************************/
32 /*****************************************************************************/
37 * Contains required functions for the ARM cache functionality.
40 * MODIFICATION HISTORY:
42 * Ver Who Date Changes
43 * ----- ---- -------- -----------------------------------------------
44 * 5.00 pkp 02/20/14 First release
47 ******************************************************************************/
49 /***************************** Include Files *********************************/
51 #include "xil_cache.h"
53 #include "xpseudo_asm.h"
54 #include "xparameters.h"
55 #include "xreg_cortexr5.h"
56 #include "xil_exception.h"
59 /************************** Variable Definitions *****************************/
61 #define IRQ_FIQ_MASK 0xC0 /* Mask IRQ and FIQ interrupts in cpsr */
64 extern s32 _stack_end;
65 extern s32 __undef_stack;
67 /****************************************************************************/
68 /************************** Function Prototypes ******************************/
70 /****************************************************************************
72 * Enable the Data cache.
80 ****************************************************************************/
81 void Xil_DCacheEnable(void)
85 /* enable caches only if they are disabled */
86 CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
88 if ((CtrlReg & XREG_CP15_CONTROL_C_BIT)==0x00000000U) {
89 /* invalidate the Data cache */
90 Xil_DCacheInvalidate();
92 /* enable the Data cache */
93 CtrlReg |= (XREG_CP15_CONTROL_C_BIT);
95 mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
99 /****************************************************************************
101 * Disable the Data cache.
109 ****************************************************************************/
110 void Xil_DCacheDisable(void)
112 register u32 CtrlReg;
114 /* clean and invalidate the Data cache */
117 /* disable the Data cache */
118 CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
120 CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT);
122 mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
125 /****************************************************************************
127 * Invalidate the entire Data cache.
135 ****************************************************************************/
136 void Xil_DCacheInvalidate(void)
139 u32 stack_start,stack_end,stack_size;
142 mtcpsr(currmask | IRQ_FIQ_MASK);
145 stack_end = (u32 )&_stack_end;
146 stack_start = (u32 )&__undef_stack;
147 stack_size = stack_start-stack_end;
149 /* Flush stack memory to save return address */
150 Xil_DCacheFlushRange(stack_end, stack_size);
152 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
154 /*invalidate all D cache*/
155 mtcp(XREG_CP15_INVAL_DC_ALL, 0);
160 /****************************************************************************
162 * Invalidate a Data cache line. If the byte specified by the address (adr)
163 * is cached by the Data cache, the cacheline containing that byte is
164 * invalidated. If the cacheline is modified (dirty), the modified contents
165 * are lost and are NOT written to system memory before the line is
168 * @param Address to be flushed.
172 * @note The bottom 4 bits are set to 0, forced by architecture.
174 ****************************************************************************/
175 void Xil_DCacheInvalidateLine(INTPTR adr)
180 mtcpsr(currmask | IRQ_FIQ_MASK);
182 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
183 mtcp(XREG_CP15_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F)));
185 /* Wait for invalidate to complete */
191 /****************************************************************************
193 * Invalidate the Data cache for the given address range.
194 * If the bytes specified by the address (adr) are cached by the Data cache,
195 * the cacheline containing that byte is invalidated. If the cacheline
196 * is modified (dirty), the modified contents are lost and are NOT
197 * written to system memory before the line is invalidated.
199 * @param Start address of range to be invalidated.
200 * @param Length of range to be invalidated in bytes.
206 ****************************************************************************/
207 void Xil_DCacheInvalidateRange(INTPTR adr, u32 len)
209 const u32 cacheline = 32U;
216 mtcpsr(currmask | IRQ_FIQ_MASK);
221 /* Select L1 Data cache in CSSR */
222 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U);
224 if ((tempadr & (cacheline-1U)) != 0U) {
225 tempadr &= (~(cacheline - 1U));
227 Xil_DCacheFlushLine(tempadr);
229 if ((tempend & (cacheline-1U)) != 0U) {
230 tempend &= (~(cacheline - 1U));
232 Xil_DCacheFlushLine(tempend);
235 while (tempadr < tempend) {
237 /* Invalidate Data cache line */
238 asm_inval_dc_line_mva_poc(tempadr);
240 tempadr += cacheline;
248 /****************************************************************************
250 * Flush the entire Data cache.
258 ****************************************************************************/
259 void Xil_DCacheFlush(void)
261 register u32 CsidReg, C7Reg;
262 u32 CacheSize, LineSize, NumWays;
263 u32 Way, WayIndex, Set, SetIndex, NumSet;
267 mtcpsr(currmask | IRQ_FIQ_MASK);
269 /* Select cache level 0 and D cache in CSSR */
270 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
272 CsidReg = mfcp(XREG_CP15_CACHE_SIZE_ID);
274 /* Determine Cache Size */
276 CacheSize = (CsidReg >> 13U) & 0x000001FFU;
277 CacheSize += 0x00000001U;
278 CacheSize *= (u32)128; /* to get number of bytes */
281 NumWays = (CsidReg & 0x000003ffU) >> 3U;
282 NumWays += 0x00000001U;
284 /* Get the cacheline size, way size, index size from csidr */
285 LineSize = (CsidReg & 0x00000007U) + 0x00000004U;
287 NumSet = CacheSize/NumWays;
288 NumSet /= (0x00000001U << LineSize);
293 /* Invalidate all the cachelines */
294 for (WayIndex = 0U; WayIndex < NumWays; WayIndex++) {
295 for (SetIndex = 0U; SetIndex < NumSet; SetIndex++) {
297 /* Flush by Set/Way */
298 asm_clean_inval_dc_line_sw(C7Reg);
300 Set += (0x00000001U << LineSize);
306 /* Wait for flush to complete */
313 /****************************************************************************
315 * Flush a Data cache line. If the byte specified by the address (adr)
316 * is cached by the Data cache, the cacheline containing that byte is
317 * invalidated. If the cacheline is modified (dirty), the entire
318 * contents of the cacheline are written to system memory before the
319 * line is invalidated.
321 * @param Address to be flushed.
325 * @note The bottom 4 bits are set to 0, forced by architecture.
327 ****************************************************************************/
328 void Xil_DCacheFlushLine(INTPTR adr)
333 mtcpsr(currmask | IRQ_FIQ_MASK);
335 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
337 mtcp(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F)));
339 /* Wait for flush to complete */
344 /****************************************************************************
345 * Flush the Data cache for the given address range.
346 * If the bytes specified by the address (adr) are cached by the Data cache,
347 * the cacheline containing that byte is invalidated. If the cacheline
348 * is modified (dirty), the written to system memory first before the
349 * before the line is invalidated.
351 * @param Start address of range to be flushed.
352 * @param Length of range to be flushed in bytes.
358 ****************************************************************************/
359 void Xil_DCacheFlushRange(INTPTR adr, u32 len)
362 const u32 cacheline = 32U;
367 mtcpsr(currmask | IRQ_FIQ_MASK);
369 if (len != 0x00000000U) {
370 /* Back the starting address up to the start of a cache line
371 * perform cache operations until adr+len
373 end = LocalAddr + len;
374 LocalAddr &= ~(cacheline - 1U);
376 while (LocalAddr < end) {
377 /* Flush Data cache line */
378 asm_clean_inval_dc_line_mva_poc(LocalAddr);
380 LocalAddr += cacheline;
386 /****************************************************************************
388 * Store a Data cache line. If the byte specified by the address (adr)
389 * is cached by the Data cache and the cacheline is modified (dirty),
390 * the entire contents of the cacheline are written to system memory.
391 * After the store completes, the cacheline is marked as unmodified
394 * @param Address to be stored.
398 * @note The bottom 4 bits are set to 0, forced by architecture.
400 ****************************************************************************/
401 void Xil_DCacheStoreLine(INTPTR adr)
406 mtcpsr(currmask | IRQ_FIQ_MASK);
408 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
409 mtcp(XREG_CP15_CLEAN_DC_LINE_MVA_POC, (adr & (~0x1F)));
411 /* Wait for store to complete */
418 /****************************************************************************
420 * Enable the instruction cache.
428 ****************************************************************************/
429 void Xil_ICacheEnable(void)
431 register u32 CtrlReg;
433 /* enable caches only if they are disabled */
435 CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
437 if ((CtrlReg & XREG_CP15_CONTROL_I_BIT)==0x00000000U) {
438 /* invalidate the instruction cache */
439 mtcp(XREG_CP15_INVAL_IC_POU, 0);
441 /* enable the instruction cache */
442 CtrlReg |= (XREG_CP15_CONTROL_I_BIT);
444 mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
448 /****************************************************************************
450 * Disable the instruction cache.
458 ****************************************************************************/
459 void Xil_ICacheDisable(void)
461 register u32 CtrlReg;
465 /* invalidate the instruction cache */
466 mtcp(XREG_CP15_INVAL_IC_POU, 0);
468 /* disable the instruction cache */
470 CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
472 CtrlReg &= ~(XREG_CP15_CONTROL_I_BIT);
474 mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
477 /****************************************************************************
479 * Invalidate the entire instruction cache.
487 ****************************************************************************/
488 void Xil_ICacheInvalidate(void)
493 mtcpsr(currmask | IRQ_FIQ_MASK);
495 mtcp(XREG_CP15_CACHE_SIZE_SEL, 1);
497 /* invalidate the instruction cache */
498 mtcp(XREG_CP15_INVAL_IC_POU, 0);
500 /* Wait for invalidate to complete */
505 /****************************************************************************
507 * Invalidate an instruction cache line. If the instruction specified by the
508 * parameter adr is cached by the instruction cache, the cacheline containing
509 * that instruction is invalidated.
515 * @note The bottom 4 bits are set to 0, forced by architecture.
517 ****************************************************************************/
518 void Xil_ICacheInvalidateLine(INTPTR adr)
523 mtcpsr(currmask | IRQ_FIQ_MASK);
525 mtcp(XREG_CP15_CACHE_SIZE_SEL, 1);
526 mtcp(XREG_CP15_INVAL_IC_LINE_MVA_POU, (adr & (~0x1F)));
528 /* Wait for invalidate to complete */
533 /****************************************************************************
535 * Invalidate the instruction cache for the given address range.
536 * If the bytes specified by the address (adr) are cached by the Data cache,
537 * the cacheline containing that byte is invalidated. If the cacheline
538 * is modified (dirty), the modified contents are lost and are NOT
539 * written to system memory before the line is invalidated.
541 * @param Start address of range to be invalidated.
542 * @param Length of range to be invalidated in bytes.
548 ****************************************************************************/
549 void Xil_ICacheInvalidateRange(INTPTR adr, u32 len)
552 const u32 cacheline = 32U;
557 mtcpsr(currmask | IRQ_FIQ_MASK);
558 if (len != 0x00000000U) {
559 /* Back the starting address up to the start of a cache line
560 * perform cache operations until adr+len
562 end = LocalAddr + len;
563 LocalAddr = LocalAddr & ~(cacheline - 1U);
565 /* Select cache L0 I-cache in CSSR */
566 mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U);
568 while (LocalAddr < end) {
570 /* Invalidate L1 I-cache line */
571 asm_inval_ic_line_mva_pou(LocalAddr);
573 LocalAddr += cacheline;
577 /* Wait for invalidate to complete */