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
45 * 6.2 mus 01/27/17 Updated to support IAR compiler
48 ******************************************************************************/
50 /***************************** Include Files *********************************/
52 #include "xil_cache.h"
54 #include "xpseudo_asm.h"
55 #include "xparameters.h"
56 #include "xreg_cortexr5.h"
57 #include "xil_exception.h"
60 /************************** Variable Definitions *****************************/
62 #define IRQ_FIQ_MASK 0xC0 /* Mask IRQ and FIQ interrupts in cpsr */
64 #if defined (__GNUC__)
65 extern s32 _stack_end;
66 extern s32 __undef_stack;
68 /****************************************************************************/
69 /************************** Function Prototypes ******************************/
71 /****************************************************************************/
73 * @brief Enable the Data cache.
81 ****************************************************************************/
82 void Xil_DCacheEnable(void)
86 /* enable caches only if they are disabled */
87 #if defined (__GNUC__)
88 CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
89 #elif defined (__ICCARM__)
90 mfcp(XREG_CP15_SYS_CONTROL,CtrlReg);
92 if ((CtrlReg & XREG_CP15_CONTROL_C_BIT)==0x00000000U) {
93 /* invalidate the Data cache */
94 Xil_DCacheInvalidate();
96 /* enable the Data cache */
97 CtrlReg |= (XREG_CP15_CONTROL_C_BIT);
99 mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
103 /****************************************************************************/
105 * @brief Disable the Data cache.
113 ****************************************************************************/
114 void Xil_DCacheDisable(void)
116 register u32 CtrlReg;
118 /* clean and invalidate the Data cache */
121 /* disable the Data cache */
122 #if defined (__GNUC__)
123 CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
124 #elif defined (__ICCARM__)
125 mfcp(XREG_CP15_SYS_CONTROL,CtrlReg);
128 CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT);
130 mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
133 /****************************************************************************/
135 * @brief Invalidate the entire Data cache.
141 ****************************************************************************/
142 void Xil_DCacheInvalidate(void)
145 u32 stack_start,stack_end,stack_size;
148 mtcpsr(currmask | IRQ_FIQ_MASK);
150 #if defined (__GNUC__)
151 stack_end = (u32 )&_stack_end;
152 stack_start = (u32 )&__undef_stack;
153 stack_size = stack_start-stack_end;
155 /* Flush stack memory to save return address */
156 Xil_DCacheFlushRange(stack_end, stack_size);
158 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
160 /*invalidate all D cache*/
161 mtcp(XREG_CP15_INVAL_DC_ALL, 0);
166 /****************************************************************************/
168 * @brief Invalidate a Data cache line. If the byte specified by the
169 * address (adr) is cached by the data cache, the cacheline
170 * containing that byte is invalidated.If the cacheline is modified
171 * (dirty), the modified contents are lost and are NOT written
172 * to system memory before the line is invalidated.
175 * @param adr: 32bit address of the data to be flushed.
179 * @note The bottom 4 bits are set to 0, forced by architecture.
181 ****************************************************************************/
182 void Xil_DCacheInvalidateLine(INTPTR adr)
187 mtcpsr(currmask | IRQ_FIQ_MASK);
189 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
190 mtcp(XREG_CP15_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F)));
192 /* Wait for invalidate to complete */
198 /****************************************************************************/
200 * @brief Invalidate the Data cache for the given address range.
201 * If the bytes specified by the address (adr) are cached by the
202 * Data cache,the cacheline containing that byte is invalidated.
203 * If the cacheline is modified (dirty), the modified contents are
204 * lost and are NOT written to system memory before the line is
207 * @param adr: 32bit start address of the range to be invalidated.
208 * @param len: Length of range to be invalidated in bytes.
212 ****************************************************************************/
213 void Xil_DCacheInvalidateRange(INTPTR adr, u32 len)
215 const u32 cacheline = 32U;
222 mtcpsr(currmask | IRQ_FIQ_MASK);
227 /* Select L1 Data cache in CSSR */
228 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U);
230 if ((tempadr & (cacheline-1U)) != 0U) {
231 tempadr &= (~(cacheline - 1U));
233 Xil_DCacheFlushLine(tempadr);
235 if ((tempend & (cacheline-1U)) != 0U) {
236 tempend &= (~(cacheline - 1U));
238 Xil_DCacheFlushLine(tempend);
241 while (tempadr < tempend) {
243 /* Invalidate Data cache line */
244 asm_inval_dc_line_mva_poc(tempadr);
246 tempadr += cacheline;
254 /****************************************************************************/
256 * @brief Flush the entire Data cache.
262 ****************************************************************************/
263 void Xil_DCacheFlush(void)
265 register u32 CsidReg, C7Reg;
266 u32 CacheSize, LineSize, NumWays;
267 u32 Way, WayIndex, Set, SetIndex, NumSet;
271 mtcpsr(currmask | IRQ_FIQ_MASK);
273 /* Select cache level 0 and D cache in CSSR */
274 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
276 #if defined (__GNUC__)
277 CsidReg = mfcp(XREG_CP15_CACHE_SIZE_ID);
278 #elif defined (__ICCARM__)
279 mfcp(XREG_CP15_CACHE_SIZE_ID,CsidReg);
281 /* Determine Cache Size */
283 CacheSize = (CsidReg >> 13U) & 0x000001FFU;
284 CacheSize += 0x00000001U;
285 CacheSize *= (u32)128; /* to get number of bytes */
288 NumWays = (CsidReg & 0x000003ffU) >> 3U;
289 NumWays += 0x00000001U;
291 /* Get the cacheline size, way size, index size from csidr */
292 LineSize = (CsidReg & 0x00000007U) + 0x00000004U;
294 NumSet = CacheSize/NumWays;
295 NumSet /= (0x00000001U << LineSize);
300 /* Invalidate all the cachelines */
301 for (WayIndex = 0U; WayIndex < NumWays; WayIndex++) {
302 for (SetIndex = 0U; SetIndex < NumSet; SetIndex++) {
304 /* Flush by Set/Way */
305 asm_clean_inval_dc_line_sw(C7Reg);
307 Set += (0x00000001U << LineSize);
313 /* Wait for flush to complete */
320 /****************************************************************************/
322 * @brief Flush a Data cache line. If the byte specified by the address (adr)
323 * is cached by the Data cache, the cacheline containing that byte is
324 * invalidated. If the cacheline is modified (dirty), the entire
325 * contents of the cacheline are written to system memory before the
326 * line is invalidated.
328 * @param adr: 32bit address of the data to be flushed.
332 * @note The bottom 4 bits are set to 0, forced by architecture.
334 ****************************************************************************/
335 void Xil_DCacheFlushLine(INTPTR adr)
340 mtcpsr(currmask | IRQ_FIQ_MASK);
342 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
344 mtcp(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F)));
346 /* Wait for flush to complete */
351 /****************************************************************************/
353 * @brief Flush the Data cache for the given address range.
354 * If the bytes specified by the address (adr) are cached by the
355 * Data cache, the cacheline containing those bytes is invalidated.If
356 * the cacheline is modified (dirty), the written to system memory
357 * before the lines are invalidated.
359 * @param adr: 32bit start address of the range to be flushed.
360 * @param len: Length of the range to be flushed in bytes
364 ****************************************************************************/
365 void Xil_DCacheFlushRange(INTPTR adr, u32 len)
368 const u32 cacheline = 32U;
373 mtcpsr(currmask | IRQ_FIQ_MASK);
375 if (len != 0x00000000U) {
376 /* Back the starting address up to the start of a cache line
377 * perform cache operations until adr+len
379 end = LocalAddr + len;
380 LocalAddr &= ~(cacheline - 1U);
382 while (LocalAddr < end) {
383 /* Flush Data cache line */
384 asm_clean_inval_dc_line_mva_poc(LocalAddr);
386 LocalAddr += cacheline;
392 /****************************************************************************/
394 * @brief Store a Data cache line. If the byte specified by the address
395 * (adr) is cached by the Data cache and the cacheline is modified
396 * (dirty), the entire contents of the cacheline are written to
397 * system memory.After the store completes, the cacheline is marked
398 * as unmodified (not dirty).
400 * @param adr: 32bit address of the data to be stored
404 * @note The bottom 4 bits are set to 0, forced by architecture.
406 ****************************************************************************/
407 void Xil_DCacheStoreLine(INTPTR adr)
412 mtcpsr(currmask | IRQ_FIQ_MASK);
414 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
415 mtcp(XREG_CP15_CLEAN_DC_LINE_MVA_POC, (adr & (~0x1F)));
417 /* Wait for store to complete */
424 /****************************************************************************/
426 * @brief Enable the instruction cache.
432 ****************************************************************************/
433 void Xil_ICacheEnable(void)
435 register u32 CtrlReg;
437 /* enable caches only if they are disabled */
438 #if defined (__GNUC__)
439 CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
440 #elif defined (__ICCARM__)
441 mfcp(XREG_CP15_SYS_CONTROL, CtrlReg);
443 if ((CtrlReg & XREG_CP15_CONTROL_I_BIT)==0x00000000U) {
444 /* invalidate the instruction cache */
445 mtcp(XREG_CP15_INVAL_IC_POU, 0);
447 /* enable the instruction cache */
448 CtrlReg |= (XREG_CP15_CONTROL_I_BIT);
450 mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
454 /****************************************************************************/
456 * @brief Disable the instruction cache.
462 ****************************************************************************/
463 void Xil_ICacheDisable(void)
465 register u32 CtrlReg;
469 /* invalidate the instruction cache */
470 mtcp(XREG_CP15_INVAL_IC_POU, 0);
472 /* disable the instruction cache */
473 #if defined (__GNUC__)
474 CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
475 #elif defined (__ICCARM__)
476 mfcp(XREG_CP15_SYS_CONTROL,CtrlReg);
479 CtrlReg &= ~(XREG_CP15_CONTROL_I_BIT);
481 mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
484 /****************************************************************************/
486 * @brief Invalidate the entire instruction cache.
492 ****************************************************************************/
493 void Xil_ICacheInvalidate(void)
498 mtcpsr(currmask | IRQ_FIQ_MASK);
500 mtcp(XREG_CP15_CACHE_SIZE_SEL, 1);
502 /* invalidate the instruction cache */
503 mtcp(XREG_CP15_INVAL_IC_POU, 0);
505 /* Wait for invalidate to complete */
510 /****************************************************************************/
512 * @brief Invalidate an instruction cache line.If the instruction specified
513 * by the address is cached by the instruction cache, the
514 * cacheline containing that instruction is invalidated.
516 * @param adr: 32bit address of the instruction to be invalidated.
520 * @note The bottom 4 bits are set to 0, forced by architecture.
522 ****************************************************************************/
523 void Xil_ICacheInvalidateLine(INTPTR adr)
528 mtcpsr(currmask | IRQ_FIQ_MASK);
530 mtcp(XREG_CP15_CACHE_SIZE_SEL, 1);
531 mtcp(XREG_CP15_INVAL_IC_LINE_MVA_POU, (adr & (~0x1F)));
533 /* Wait for invalidate to complete */
538 /****************************************************************************/
540 * @brief Invalidate the instruction cache for the given address range.
541 * If the bytes specified by the address (adr) are cached by the
542 * Data cache, the cacheline containing that byte is invalidated.
543 * If the cachelineis modified (dirty), the modified contents are
544 * lost and are NOT written to system memory before the line is
547 * @param adr: 32bit start address of the range to be invalidated.
548 * @param len: Length of the range to be invalidated in bytes.
552 ****************************************************************************/
553 void Xil_ICacheInvalidateRange(INTPTR adr, u32 len)
556 const u32 cacheline = 32U;
561 mtcpsr(currmask | IRQ_FIQ_MASK);
562 if (len != 0x00000000U) {
563 /* Back the starting address up to the start of a cache line
564 * perform cache operations until adr+len
566 end = LocalAddr + len;
567 LocalAddr = LocalAddr & ~(cacheline - 1U);
569 /* Select cache L0 I-cache in CSSR */
570 mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U);
572 while (LocalAddr < end) {
574 /* Invalidate L1 I-cache line */
575 asm_inval_ic_line_mva_pou(LocalAddr);
577 LocalAddr += cacheline;
581 /* Wait for invalidate to complete */