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. Cache APIs are
38 * yet to be implemented. They are left blank to avoid any compilation error
41 * MODIFICATION HISTORY:
43 * Ver Who Date Changes
44 * ----- ---- -------- -----------------------------------------------
45 * 5.00 pkp 05/29/14 First release
49 ******************************************************************************/
51 /***************************** Include Files *********************************/
53 #include "xil_cache.h"
55 #include "xpseudo_asm.h"
56 #include "xparameters.h"
57 #include "xreg_cortexa53.h"
58 #include "xil_exception.h"
60 /************************** Function Prototypes ******************************/
62 /************************** Variable Definitions *****************************/
63 #define IRQ_FIQ_MASK 0xC0U /* Mask IRQ and FIQ interrupts in cpsr */
65 /****************************************************************************
67 * Enable the Data cache.
75 ****************************************************************************/
77 void Xil_DCacheEnable(void)
80 CtrlReg = mfcp(SCTLR_EL3);
81 /* enable caches only if they are disabled */
82 if((CtrlReg & XREG_CONTROL_DCACHE_BIT) == 0X00000000U){
84 /* invalidate the Data cache */
85 Xil_DCacheInvalidate();
87 CtrlReg |= XREG_CONTROL_DCACHE_BIT;
89 /* enable the Data cache */
90 mtcp(SCTLR_EL3,CtrlReg);
94 /****************************************************************************
96 * Disable the Data cache.
104 ****************************************************************************/
105 void Xil_DCacheDisable(void)
108 /* clean and invalidate the Data cache */
110 CtrlReg = mfcp(SCTLR_EL3);
112 CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT);
113 /* disable the Data cache */
114 mtcp(SCTLR_EL3,CtrlReg);
117 /****************************************************************************
119 * invalidate the Data cache.
127 ****************************************************************************/
128 void Xil_DCacheInvalidate(void)
130 register u32 CsidReg, C7Reg;
131 u32 LineSize, NumWays;
132 u32 Way, WayIndex,WayAdjust, Set, SetIndex, NumSet, NumCacheLevel, CacheLevel,CacheLevelIndex;
136 mtcpsr(currmask | IRQ_FIQ_MASK);
139 /* Number of level of cache*/
140 NumCacheLevel = (mfcp(CLIDR_EL1)>>24U) & 0x00000007U;
143 /* Select cache level 0 and D cache in CSSR */
144 mtcp(CSSELR_EL1,CacheLevel);
147 CsidReg = mfcp(CCSIDR_EL1);
149 /* Get the cacheline size, way size, index size from csidr */
150 LineSize = (CsidReg & 0x00000007U) + 0x00000004U;
153 NumWays = (CsidReg & 0x00001FFFU) >> 3U;
154 NumWays += 0X00000001U;
157 NumSet = (CsidReg >> 13U) & 0x00007FFFU;
158 NumSet += 0X00000001U;
160 WayAdjust = clz(NumWays) - (u32)0x0000001FU;
165 /* Invalidate all the cachelines */
166 for (WayIndex =0U; WayIndex < NumWays; WayIndex++) {
167 for (SetIndex =0U; SetIndex < NumSet; SetIndex++) {
168 C7Reg = Way | Set | CacheLevel;
170 Set += (0x00000001U << LineSize);
173 Way += (0x00000001U << WayAdjust);
176 /* Wait for invalidate to complete */
179 /* Select cache level 1 and D cache in CSSR */
180 CacheLevel += (0x00000001U<<1U) ;
181 mtcp(CSSELR_EL1,CacheLevel);
184 CsidReg = mfcp(CCSIDR_EL1);
186 /* Get the cacheline size, way size, index size from csidr */
187 LineSize = (CsidReg & 0x00000007U) + 0x00000004U;
190 NumWays = (CsidReg & 0x00001FFFU) >> 3U;
191 NumWays += 0x00000001U;
194 NumSet = (CsidReg >> 13U) & 0x00007FFFU;
195 NumSet += 0x00000001U;
197 WayAdjust = clz(NumWays) - (u32)0x0000001FU;
202 /* Invalidate all the cachelines */
203 for (WayIndex = 0U; WayIndex < NumWays; WayIndex++) {
204 for (SetIndex = 0U; SetIndex < NumSet; SetIndex++) {
205 C7Reg = Way | Set | CacheLevel;
207 Set += (0x00000001U << LineSize);
210 Way += (0x00000001U << WayAdjust);
212 /* Wait for invalidate to complete */
218 /****************************************************************************
220 * Invalidate a Data cache line. If the byte specified by the address (adr)
221 * is cached by the Data cache, the cacheline containing that byte is
222 * invalidated. If the cacheline is modified (dirty), the modified contents
223 * are written to system memory before the line is invalidated.
225 * @param Address to be flushed.
229 * @note The bottom 6 bits are set to 0, forced by architecture.
231 ****************************************************************************/
232 void Xil_DCacheInvalidateLine(INTPTR adr)
237 mtcpsr(currmask | IRQ_FIQ_MASK);
239 /* Select cache level 0 and D cache in CSSR */
240 mtcp(CSSELR_EL1,0x0);
241 mtcpdc(IVAC,(adr & (~0x3F)));
242 /* Wait for invalidate to complete */
244 /* Select cache level 1 and D cache in CSSR */
245 mtcp(CSSELR_EL1,0x2);
246 mtcpdc(IVAC,(adr & (~0x3F)));
247 /* Wait for invalidate to complete */
252 /****************************************************************************
254 * Invalidate the Data cache for the given address range.
255 * If the bytes specified by the address (adr) are cached by the Data cache,
256 * the cacheline containing that byte is invalidated. If the cacheline
257 * is modified (dirty), the modified contents are written to system memory
258 * before the line is invalidated.
260 * @param Start address of range to be invalidated.
261 * @param Length of range to be invalidated in bytes.
267 ****************************************************************************/
268 void Xil_DCacheInvalidateRange(INTPTR adr, INTPTR len)
270 const u32 cacheline = 64U;
272 INTPTR tempadr = adr;
276 mtcpsr(currmask | IRQ_FIQ_MASK);
281 if ((tempadr & (cacheline-1U)) != 0U) {
282 tempadr &= (~(cacheline - 1U));
283 Xil_DCacheFlushLine(tempadr);
284 tempadr += cacheline;
286 if ((tempend & (cacheline-1U)) != 0U) {
287 tempend &= (~(cacheline - 1U));
288 Xil_DCacheFlushLine(tempend);
291 while (tempadr < tempend) {
292 /* Select cache level 0 and D cache in CSSR */
293 mtcp(CSSELR_EL1,0x0);
294 /* Invalidate Data cache line */
295 mtcpdc(IVAC,(tempadr & (~0x3F)));
296 /* Wait for invalidate to complete */
298 /* Select cache level 0 and D cache in CSSR */
299 mtcp(CSSELR_EL1,0x2);
300 /* Invalidate Data cache line */
301 mtcpdc(IVAC,(tempadr & (~0x3F)));
302 /* Wait for invalidate to complete */
304 tempadr += cacheline;
310 /****************************************************************************
312 * Flush the Data cache.
320 ****************************************************************************/
321 void Xil_DCacheFlush(void)
323 register u32 CsidReg, C7Reg;
324 u32 LineSize, NumWays;
325 u32 Way, WayIndex,WayAdjust, Set, SetIndex, NumSet, NumCacheLevel, CacheLevel,CacheLevelIndex;
329 mtcpsr(currmask | IRQ_FIQ_MASK);
332 /* Number of level of cache*/
333 NumCacheLevel = (mfcp(CLIDR_EL1)>>24U) & 0x00000007U;
336 /* Select cache level 0 and D cache in CSSR */
337 mtcp(CSSELR_EL1,CacheLevel);
340 CsidReg = mfcp(CCSIDR_EL1);
342 /* Get the cacheline size, way size, index size from csidr */
343 LineSize = (CsidReg & 0x00000007U) + 0x00000004U;
346 NumWays = (CsidReg & 0x00001FFFU) >> 3U;
347 NumWays += 0x00000001U;
350 NumSet = (CsidReg >> 13U) & 0x00007FFFU;
351 NumSet += 0x00000001U;
353 WayAdjust = clz(NumWays) - (u32)0x0000001FU;
358 /* Flush all the cachelines */
359 for (WayIndex = 0U; WayIndex < NumWays; WayIndex++) {
360 for (SetIndex = 0U; SetIndex < NumSet; SetIndex++) {
361 C7Reg = Way | Set | CacheLevel;
363 Set += (0x00000001U << LineSize);
366 Way += (0x00000001U << WayAdjust);
369 /* Wait for Flush to complete */
372 /* Select cache level 1 and D cache in CSSR */
373 CacheLevel += (0x00000001U << 1U);
374 mtcp(CSSELR_EL1,CacheLevel);
377 CsidReg = mfcp(CCSIDR_EL1);
379 /* Get the cacheline size, way size, index size from csidr */
380 LineSize = (CsidReg & 0x00000007U) + 0x00000004U;
383 NumWays = (CsidReg & 0x00001FFFU) >> 3U;
384 NumWays += 0x00000001U;
387 NumSet = (CsidReg >> 13U) & 0x00007FFFU;
388 NumSet += 0x00000001U;
390 WayAdjust=clz(NumWays) - (u32)0x0000001FU;
395 /* Flush all the cachelines */
396 for (WayIndex =0U; WayIndex < NumWays; WayIndex++) {
397 for (SetIndex =0U; SetIndex < NumSet; SetIndex++) {
398 C7Reg = Way | Set | CacheLevel;
400 Set += (0x00000001U << LineSize);
403 Way += (0x00000001U<<WayAdjust);
405 /* Wait for Flush to complete */
411 /****************************************************************************
413 * Flush a Data cache line. If the byte specified by the address (adr)
414 * is cached by the Data cache, the cacheline containing that byte is
415 * invalidated. If the cacheline is modified (dirty), the entire
416 * contents of the cacheline are written to system memory before the
417 * line is invalidated.
419 * @param Address to be flushed.
423 * @note The bottom 6 bits are set to 0, forced by architecture.
425 ****************************************************************************/
426 void Xil_DCacheFlushLine(INTPTR adr)
430 mtcpsr(currmask | IRQ_FIQ_MASK);
431 /* Select cache level 0 and D cache in CSSR */
432 mtcp(CSSELR_EL1,0x0);
433 mtcpdc(CIVAC,(adr & (~0x3F)));
434 /* Wait for flush to complete */
436 /* Select cache level 1 and D cache in CSSR */
437 mtcp(CSSELR_EL1,0x2);
438 mtcpdc(CIVAC,(adr & (~0x3F)));
439 /* Wait for flush to complete */
443 /****************************************************************************
444 * Flush the Data cache for the given address range.
445 * If the bytes specified by the address (adr) are cached by the Data cache,
446 * the cacheline containing that byte is invalidated. If the cacheline
447 * is modified (dirty), the written to system memory first before the
448 * before the line is invalidated.
450 * @param Start address of range to be flushed.
451 * @param Length of range to be flushed in bytes.
457 ****************************************************************************/
459 void Xil_DCacheFlushRange(INTPTR adr, INTPTR len)
461 const u32 cacheline = 64U;
463 INTPTR tempadr = adr;
467 mtcpsr(currmask | IRQ_FIQ_MASK);
468 if (len != 0x00000000U) {
471 if ((tempadr & (0x3F)) != 0) {
473 Xil_DCacheFlushLine(tempadr);
474 tempadr += cacheline;
476 if ((tempend & (0x3F)) != 0) {
478 Xil_DCacheFlushLine(tempend);
481 while (tempadr < tempend) {
482 /* Select cache level 0 and D cache in CSSR */
483 mtcp(CSSELR_EL1,0x0);
484 /* Flush Data cache line */
485 mtcpdc(CIVAC,(tempadr & (~0x3F)));
486 /* Wait for flush to complete */
488 /* Select cache level 1 and D cache in CSSR */
489 mtcp(CSSELR_EL1,0x2);
490 /* Flush Data cache line */
491 mtcpdc(CIVAC,(tempadr & (~0x3F)));
492 /* Wait for flush to complete */
494 tempadr += cacheline;
502 /****************************************************************************
504 * Enable the instruction cache.
512 ****************************************************************************/
515 void Xil_ICacheEnable(void)
519 CtrlReg = mfcp(SCTLR_EL3);
520 /* enable caches only if they are disabled */
521 if((CtrlReg & XREG_CONTROL_ICACHE_BIT)==0x00000000U){
522 /* invalidate the instruction cache */
523 Xil_ICacheInvalidate();
525 CtrlReg |= XREG_CONTROL_ICACHE_BIT;
526 /* enable the instruction cache */
527 mtcp(SCTLR_EL3,CtrlReg);
531 /****************************************************************************
533 * Disable the instruction cache.
541 ****************************************************************************/
542 void Xil_ICacheDisable(void)
545 CtrlReg = mfcp(SCTLR_EL3);
546 /* invalidate the instruction cache */
547 Xil_ICacheInvalidate();
548 CtrlReg &= ~(XREG_CONTROL_ICACHE_BIT);
549 /* disable the instruction cache */
550 mtcp(SCTLR_EL3,CtrlReg);
553 /****************************************************************************
555 * Invalidate the entire instruction cache.
563 ****************************************************************************/
564 void Xil_ICacheInvalidate(void)
566 unsigned int currmask;
568 mtcpsr(currmask | IRQ_FIQ_MASK);
569 mtcp(CSSELR_EL1,0x1);
571 /* invalidate the instruction cache */
573 /* Wait for invalidate to complete */
577 /****************************************************************************
579 * Invalidate an instruction cache line. If the instruction specified by the
580 * parameter adr is cached by the instruction cache, the cacheline containing
581 * that instruction is invalidated.
587 * @note The bottom 6 bits are set to 0, forced by architecture.
589 ****************************************************************************/
591 void Xil_ICacheInvalidateLine(INTPTR adr)
595 mtcpsr(currmask | IRQ_FIQ_MASK);
597 mtcp(CSSELR_EL1,0x1);
598 /*Invalidate I Cache line*/
599 mtcpic(IVAU,adr & (~0x3F));
600 /* Wait for invalidate to complete */
605 /****************************************************************************
607 * Invalidate the instruction cache for the given address range.
608 * If the bytes specified by the address (adr) are cached by the Data cache,
609 * the cacheline containing that byte is invalidated. If the cacheline
610 * is modified (dirty), the modified contents are lost and are NOT
611 * written to system memory before the line is invalidated.
613 * @param Start address of range to be invalidated.
614 * @param Length of range to be invalidated in bytes.
620 ****************************************************************************/
621 void Xil_ICacheInvalidateRange(INTPTR adr, INTPTR len)
623 const u32 cacheline = 64U;
625 INTPTR tempadr = adr;
629 mtcpsr(currmask | IRQ_FIQ_MASK);
631 if (len != 0x00000000U) {
634 tempadr &= ~(cacheline - 0x00000001U);
636 /* Select cache Level 0 I-cache in CSSR */
637 mtcp(CSSELR_EL1,0x1);
638 while (tempadr < tempend) {
639 /*Invalidate I Cache line*/
640 mtcpic(IVAU,adr & (~0x3F));
642 tempadr += cacheline;
645 /* Wait for invalidate to complete */