]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo_bsp/ps7_cortexa9_0/libsrc/standalone_v4_1/src/xil_cache.c
Add back Zynq demo - this time using SDK V14.2.
[freertos] / FreeRTOS / Demo / CORTEX_A9_Zynq_ZC702 / RTOSDemo_bsp / ps7_cortexa9_0 / libsrc / standalone_v4_1 / src / xil_cache.c
1 /******************************************************************************
2 *
3 * (c) Copyright 2010-14  Xilinx, Inc. All rights reserved.
4 *
5 * This file contains confidential and proprietary information of Xilinx, Inc.
6 * and is protected under U.S. and international copyright and other
7 * intellectual property laws.
8 *
9 * DISCLAIMER
10 * This disclaimer is not a license and does not grant any rights to the
11 * materials distributed herewith. Except as otherwise provided in a valid
12 * license issued to you by Xilinx, and to the maximum extent permitted by
13 * applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL
14 * FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS,
15 * IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
16 * MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE;
17 * and (2) Xilinx shall not be liable (whether in contract or tort, including
18 * negligence, or under any other theory of liability) for any loss or damage
19 * of any kind or nature related to, arising under or in connection with these
20 * materials, including for any direct, or any indirect, special, incidental,
21 * or consequential loss or damage (including loss of data, profits, goodwill,
22 * or any type of loss or damage suffered as a result of any action brought by
23 * a third party) even if such damage or loss was reasonably foreseeable or
24 * Xilinx had been advised of the possibility of the same.
25 *
26 * CRITICAL APPLICATIONS
27 * Xilinx products are not designed or intended to be fail-safe, or for use in
28 * any application requiring fail-safe performance, such as life-support or
29 * safety devices or systems, Class III medical devices, nuclear facilities,
30 * applications related to the deployment of airbags, or any other applications
31 * that could lead to death, personal injury, or severe property or
32 * environmental damage (individually and collectively, "Critical
33 * Applications"). Customer assumes the sole risk and liability of any use of
34 * Xilinx products in Critical Applications, subject only to applicable laws
35 * and regulations governing limitations on product liability.
36 *
37 * THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE
38 * AT ALL TIMES.
39 *
40 ******************************************************************************/
41 /*****************************************************************************/
42 /**
43 *
44 * @file xil_cache.c
45 *
46 * Contains required functions for the ARM cache functionality.
47 *
48 * <pre>
49 * MODIFICATION HISTORY:
50 *
51 * Ver    Who Date     Changes
52 * ----- ---- -------- -----------------------------------------------
53 * 1.00a  ecm 01/29/10 First release
54 * 1.00a  ecm 06/24/10 Moved the L1 and L2 specific function prototypes
55 *                     to xil_cache_mach.h to give access to sophisticated users
56 * 3.02a  sdm 04/07/11 Updated Flush/InvalidateRange APIs to flush/invalidate
57 *                     L1 and L2 caches in a single loop and used dsb, L2 sync
58 *                     at the end of the loop.
59 * 3.04a  sdm 01/02/12 Remove redundant dsb/dmb instructions in cache maintenance
60 *                     APIs.
61 * 3.07a  asa 07/16/12 Corrected the L1 and L2 cache invalidation order.
62 * 3.07a  sgd 09/18/12 Corrected the L2 cache enable and disable sequence.
63 * 3.10a  srt 04/18/13 Implemented ARM Erratas. Please refer to file
64 *                     'xil_errata.h' for errata description
65 * 3.10a  asa 05/13/13 Modified cache disable APIs. The L2 cache disable
66 *                         operation was being done with L1 Data cache disabled. This is
67 *                         fixed so that L2 cache disable operation happens independent of
68 *                         L1 cache disable operation. This fixes CR #706464.
69 *                         Changes are done to do a L2 cache sync (poll reg7_?cache_?sync).
70 *                         This is done to fix the CR #700542.
71 * 3.11a  asa 09/23/13 Modified the Xil_DCacheFlushRange and
72 *                        Xil_DCacheInvalidateRange to fix potential issues. Fixed other
73 *                        relevant cache APIs to disable and enable back the interrupts.
74 *                        This fixes CR #663885.
75 * 3.11a  asa 09/28/13 Made changes for L2 cache sync operation. It is found
76 *                        out that for L2 cache flush/clean/invalidation by cache lines
77 *                        does not need a cache sync as these are atomic nature. Similarly
78 *                        figured out that for complete L2 cache flush/invalidation by way
79 *                        we need to wait for some more time in a loop till the status
80 *                        shows that the cache operation is completed.
81 * 4.00   pkp 24/01/14 Modified Xil_DCacheInvalidateRange to fix the bug. Few
82 *                        cache lines were missed to invalidate when unaligned address
83 *                        invalidation was accommodated. That fixes CR #766768. 
84 *                        Also in Xil_L1DCacheInvalidate, while invalidating all L1D cache
85 *                        stack memory which contains return address was invalidated. So
86 *                        stack memory was flushed first and then L1D cache is invalidated.
87 *                        This is done to fix CR #763829
88 * 4.01   asa 05/09/14 Made changes in cortexa9/xil_cache.c to fix CR# 798230.
89 * </pre>
90 *
91 ******************************************************************************/
92
93 /***************************** Include Files *********************************/
94
95 #include "xil_cache.h"
96 #include "xil_cache_l.h"
97 #include "xil_io.h"
98 #include "xpseudo_asm.h"
99 #include "xparameters.h"
100 #include "xreg_cortexa9.h"
101 #include "xl2cc.h"
102 #include "xil_errata.h"
103 #include "xil_exception.h"
104
105 /************************** Function Prototypes ******************************/
106
107 /************************** Variable Definitions *****************************/
108
109 #define IRQ_FIQ_MASK 0xC0       /* Mask IRQ and FIQ interrupts in cpsr */
110
111 #ifdef __GNUC__
112         extern int  _stack_end;
113         extern int  _stack;
114 #endif
115
116 /****************************************************************************
117 *
118 * Access L2 Debug Control Register.
119 *
120 * @param        Value, value to be written to Debug Control Register.
121 *
122 * @return       None.
123 *
124 * @note         None.
125 *
126 ****************************************************************************/
127 #ifdef __GNUC__
128 static inline void Xil_L2WriteDebugCtrl(u32 Value)
129 #else
130 static void Xil_L2WriteDebugCtrl(u32 Value)
131 #endif
132 {
133 #if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915)
134         Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_DEBUG_CTRL_OFFSET, Value);
135 #else
136         (void)(Value);
137 #endif
138 }
139
140 /****************************************************************************
141 *
142 * Perform L2 Cache Sync Operation.
143 *
144 * @param        None.
145 *
146 * @return       None.
147 *
148 * @note         None.
149 *
150 ****************************************************************************/
151 #ifdef __GNUC__
152 static inline void Xil_L2CacheSync(void)
153 #else
154 static void Xil_L2CacheSync(void)
155 #endif
156 {
157 #ifdef CONFIG_PL310_ERRATA_753970
158         Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_DUMMY_CACHE_SYNC_OFFSET, 0x0);
159 #else
160         Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_SYNC_OFFSET, 0x0);
161 #endif
162 }
163
164 /****************************************************************************
165 *
166 * Enable the Data cache.
167 *
168 * @param        None.
169 *
170 * @return       None.
171 *
172 * @note         None.
173 *
174 ****************************************************************************/
175 void Xil_DCacheEnable(void)
176 {
177         Xil_L1DCacheEnable();
178         Xil_L2CacheEnable();
179 }
180
181 /****************************************************************************
182 *
183 * Disable the Data cache.
184 *
185 * @param        None.
186 *
187 * @return       None.
188 *
189 * @note         None.
190 *
191 ****************************************************************************/
192 void Xil_DCacheDisable(void)
193 {
194         Xil_L2CacheDisable();
195         Xil_L1DCacheDisable();
196 }
197
198 /****************************************************************************
199 *
200 * Invalidate the entire Data cache.
201 *
202 * @param        None.
203 *
204 * @return       None.
205 *
206 * @note         None.
207 *
208 ****************************************************************************/
209 void Xil_DCacheInvalidate(void)
210 {
211         unsigned int currmask;
212
213         currmask = mfcpsr();
214         mtcpsr(currmask | IRQ_FIQ_MASK);
215
216         Xil_L2CacheInvalidate();
217         Xil_L1DCacheInvalidate();
218
219         mtcpsr(currmask);
220 }
221
222 /****************************************************************************
223 *
224 * Invalidate a Data cache line. If the byte specified by the address (adr)
225 * is cached by the Data cache, the cacheline containing that byte is
226 * invalidated.  If the cacheline is modified (dirty), the modified contents
227 * are lost and are NOT written to system memory before the line is
228 * invalidated.
229 *
230 * @param        Address to be flushed.
231 *
232 * @return       None.
233 *
234 * @note         The bottom 4 bits are set to 0, forced by architecture.
235 *
236 ****************************************************************************/
237 void Xil_DCacheInvalidateLine(unsigned int adr)
238 {
239         unsigned int currmask;
240
241         currmask = mfcpsr();
242         mtcpsr(currmask | IRQ_FIQ_MASK);
243
244         Xil_L2CacheInvalidateLine(adr);
245         Xil_L1DCacheInvalidateLine(adr);
246
247         mtcpsr(currmask);
248 }
249
250 /****************************************************************************
251 *
252 * Invalidate the Data cache for the given address range.
253 * If the bytes specified by the address (adr) are cached by the Data cache,
254 * the cacheline containing that byte is invalidated.    If the cacheline
255 * is modified (dirty), the modified contents are lost and are NOT
256 * written to system memory before the line is invalidated.
257 *
258 * @param        Start address of range to be invalidated.
259 * @param        Length of range to be invalidated in bytes.
260 *
261 * @return       None.
262 *
263 * @note         None.
264 *
265 ****************************************************************************/
266 void Xil_DCacheInvalidateRange(unsigned int adr, unsigned len)
267 {
268         const unsigned cacheline = 32;
269         unsigned int end;
270         unsigned int tempadr = adr;
271         unsigned int tempend;
272         unsigned int currmask;
273         volatile u32 *L2CCOffset = (volatile u32 *) (XPS_L2CC_BASEADDR +
274                                     XPS_L2CC_CACHE_INVLD_PA_OFFSET);
275
276         currmask = mfcpsr();
277         mtcpsr(currmask | IRQ_FIQ_MASK);
278
279         if (len != 0) {
280                 end = tempadr + len;
281                 tempend = end;
282                 /* Select L1 Data cache in CSSR */
283                 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
284
285                 if (tempadr & (cacheline-1)) {
286                         tempadr &= ~(cacheline - 1);
287
288                         Xil_L1DCacheFlushLine(tempadr);
289                         /* Disable Write-back and line fills */
290                         Xil_L2WriteDebugCtrl(0x3);
291                         Xil_L2CacheFlushLine(tempadr);
292                         /* Enable Write-back and line fills */
293                         Xil_L2WriteDebugCtrl(0x0);
294                         Xil_L2CacheSync();
295                         tempadr += cacheline;
296                 }
297                 if (tempend & (cacheline-1)) {
298                         tempend &= ~(cacheline - 1);
299
300                         Xil_L1DCacheFlushLine(tempend);
301                         /* Disable Write-back and line fills */
302                         Xil_L2WriteDebugCtrl(0x3);
303                         Xil_L2CacheFlushLine(tempend);
304                         /* Enable Write-back and line fills */
305                         Xil_L2WriteDebugCtrl(0x0);
306                         Xil_L2CacheSync();
307                 }
308
309                 while (tempadr < tempend) {
310                         /* Invalidate L2 cache line */
311                         *L2CCOffset = tempadr;
312                         dsb();
313 #ifdef __GNUC__
314                         /* Invalidate L1 Data cache line */
315                         __asm__ __volatile__("mcr " \
316                         XREG_CP15_INVAL_DC_LINE_MVA_POC :: "r" (tempadr));
317 #else
318                         { volatile register unsigned int Reg
319                                 __asm(XREG_CP15_INVAL_DC_LINE_MVA_POC);
320                           Reg = tempadr; }
321 #endif
322                         tempadr += cacheline;
323                 }
324         }
325
326         dsb();
327         mtcpsr(currmask);
328 }
329
330 /****************************************************************************
331 *
332 * Flush the entire Data cache.
333 *
334 * @param        None.
335 *
336 * @return       None.
337 *
338 * @note         None.
339 *
340 ****************************************************************************/
341 void Xil_DCacheFlush(void)
342 {
343         unsigned int currmask;
344
345         currmask = mfcpsr();
346         mtcpsr(currmask | IRQ_FIQ_MASK);
347         Xil_L1DCacheFlush();
348         Xil_L2CacheFlush();
349
350         mtcpsr(currmask);
351 }
352
353 /****************************************************************************
354 *
355 * Flush a Data cache line. If the byte specified by the address (adr)
356 * is cached by the Data cache, the cacheline containing that byte is
357 * invalidated.  If the cacheline is modified (dirty), the entire
358 * contents of the cacheline are written to system memory before the
359 * line is invalidated.
360 *
361 * @param        Address to be flushed.
362 *
363 * @return       None.
364 *
365 * @note         The bottom 4 bits are set to 0, forced by architecture.
366 *
367 ****************************************************************************/
368 void Xil_DCacheFlushLine(unsigned int adr)
369 {
370         unsigned int currmask;
371
372         currmask = mfcpsr();
373         mtcpsr(currmask | IRQ_FIQ_MASK);
374         Xil_L1DCacheFlushLine(adr);
375
376         /* Disable Write-back and line fills */
377         Xil_L2WriteDebugCtrl(0x3);
378
379         Xil_L2CacheFlushLine(adr);
380
381         /* Enable Write-back and line fills */
382         Xil_L2WriteDebugCtrl(0x0);
383         Xil_L2CacheSync();
384         mtcpsr(currmask);
385 }
386
387 /****************************************************************************
388 * Flush the Data cache for the given address range.
389 * If the bytes specified by the address (adr) are cached by the Data cache,
390 * the cacheline containing that byte is invalidated.    If the cacheline
391 * is modified (dirty), the written to system memory first before the
392 * before the line is invalidated.
393 *
394 * @param        Start address of range to be flushed.
395 * @param        Length of range to be flushed in bytes.
396 *
397 * @return       None.
398 *
399 * @note         None.
400 *
401 ****************************************************************************/
402 void Xil_DCacheFlushRange(unsigned int adr, unsigned len)
403 {
404         const unsigned cacheline = 32;
405         unsigned int end;
406         unsigned int currmask;
407         volatile u32 *L2CCOffset = (volatile u32 *) (XPS_L2CC_BASEADDR +
408                                     XPS_L2CC_CACHE_INV_CLN_PA_OFFSET);
409
410         currmask = mfcpsr();
411         mtcpsr(currmask | IRQ_FIQ_MASK);
412
413         if (len != 0) {
414                 /* Back the starting address up to the start of a cache line
415                  * perform cache operations until adr+len
416                  */
417                 end = adr + len;
418                 adr &= ~(cacheline - 1);
419
420                 while (adr < end) {
421 #ifdef __GNUC__
422                         /* Flush L1 Data cache line */
423                         __asm__ __volatile__("mcr " \
424                         XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC :: "r" (adr));
425 #else
426                         { volatile register unsigned int Reg
427                                 __asm(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC);
428                           Reg = adr; }
429 #endif
430                         /* Flush L2 cache line */
431                         *L2CCOffset = adr;
432                         dsb();
433                         adr += cacheline;
434                 }
435         }
436         dsb();
437         mtcpsr(currmask);
438 }
439 /****************************************************************************
440 *
441 * Store a Data cache line. If the byte specified by the address (adr)
442 * is cached by the Data cache and the cacheline is modified (dirty),
443 * the entire contents of the cacheline are written to system memory.
444 * After the store completes, the cacheline is marked as unmodified
445 * (not dirty).
446 *
447 * @param        Address to be stored.
448 *
449 * @return       None.
450 *
451 * @note         The bottom 4 bits are set to 0, forced by architecture.
452 *
453 ****************************************************************************/
454 void Xil_DCacheStoreLine(unsigned int adr)
455 {
456         unsigned int currmask;
457
458         currmask = mfcpsr();
459         mtcpsr(currmask | IRQ_FIQ_MASK);
460
461         Xil_L1DCacheStoreLine(adr);
462         Xil_L2CacheStoreLine(adr);
463         mtcpsr(currmask);
464 }
465
466 /****************************************************************************
467 *
468 * Enable the instruction cache.
469 *
470 * @param        None.
471 *
472 * @return       None.
473 *
474 * @note         None.
475 *
476 ****************************************************************************/
477 void Xil_ICacheEnable(void)
478 {
479         Xil_L1ICacheEnable();
480         Xil_L2CacheEnable();
481 }
482
483 /****************************************************************************
484 *
485 * Disable the instruction cache.
486 *
487 * @param        None.
488 *
489 * @return       None.
490 *
491 * @note         None.
492 *
493 ****************************************************************************/
494 void Xil_ICacheDisable(void)
495 {
496         Xil_L2CacheDisable();
497         Xil_L1ICacheDisable();
498 }
499
500 /****************************************************************************
501 *
502 * Invalidate the entire instruction cache.
503 *
504 * @param        None.
505 *
506 * @return       None.
507 *
508 * @note         None.
509 *
510 ****************************************************************************/
511 void Xil_ICacheInvalidate(void)
512 {
513         unsigned int currmask;
514
515         currmask = mfcpsr();
516         mtcpsr(currmask | IRQ_FIQ_MASK);
517
518         Xil_L2CacheInvalidate();
519         Xil_L1ICacheInvalidate();
520
521         mtcpsr(currmask);
522 }
523
524 /****************************************************************************
525 *
526 * Invalidate an instruction cache line. If the instruction specified by the
527 * parameter adr is cached by the instruction cache, the cacheline containing
528 * that instruction is invalidated.
529 *
530 * @param        None.
531 *
532 * @return       None.
533 *
534 * @note         The bottom 4 bits are set to 0, forced by architecture.
535 *
536 ****************************************************************************/
537 void Xil_ICacheInvalidateLine(unsigned int adr)
538 {
539         unsigned int currmask;
540
541         currmask = mfcpsr();
542         mtcpsr(currmask | IRQ_FIQ_MASK);
543         Xil_L2CacheInvalidateLine(adr);
544         Xil_L1ICacheInvalidateLine(adr);
545         mtcpsr(currmask);
546 }
547
548 /****************************************************************************
549 *
550 * Invalidate the instruction cache for the given address range.
551 * If the bytes specified by the address (adr) are cached by the Data cache,
552 * the cacheline containing that byte is invalidated. If the cacheline
553 * is modified (dirty), the modified contents are lost and are NOT
554 * written to system memory before the line is invalidated.
555 *
556 * @param        Start address of range to be invalidated.
557 * @param        Length of range to be invalidated in bytes.
558 *
559 * @return       None.
560 *
561 * @note         None.
562 *
563 ****************************************************************************/
564 void Xil_ICacheInvalidateRange(unsigned int adr, unsigned len)
565 {
566         const unsigned cacheline = 32;
567         unsigned int end;
568         volatile u32 *L2CCOffset = (volatile u32 *) (XPS_L2CC_BASEADDR +
569                                     XPS_L2CC_CACHE_INVLD_PA_OFFSET);
570
571         unsigned int currmask;
572
573         currmask = mfcpsr();
574         mtcpsr(currmask | IRQ_FIQ_MASK);
575         if (len != 0) {
576                 /* Back the starting address up to the start of a cache line
577                  * perform cache operations until adr+len
578                  */
579                 end = adr + len;
580                 adr = adr & ~(cacheline - 1);
581
582                 /* Select cache L0 I-cache in CSSR */
583                 mtcp(XREG_CP15_CACHE_SIZE_SEL, 1);
584
585                 while (adr < end) {
586                 /* Invalidate L2 cache line */
587                 *L2CCOffset = adr;
588                 dsb();
589 #ifdef __GNUC__
590                         /* Invalidate L1 I-cache line */
591                         __asm__ __volatile__("mcr " \
592                         XREG_CP15_INVAL_IC_LINE_MVA_POU :: "r" (adr));
593 #else
594                         { volatile register unsigned int Reg
595                                 __asm(XREG_CP15_INVAL_IC_LINE_MVA_POU);
596                           Reg = adr; }
597 #endif
598
599                         adr += cacheline;
600                 }
601         }
602
603         /* Wait for L1 and L2 invalidate to complete */
604         dsb();
605         mtcpsr(currmask);
606 }
607
608 /****************************************************************************
609 *
610 * Enable the level 1 Data cache.
611 *
612 * @param        None.
613 *
614 * @return       None.
615 *
616 * @note         None.
617 *
618 ****************************************************************************/
619 void Xil_L1DCacheEnable(void)
620 {
621         register unsigned int CtrlReg;
622
623         /* enable caches only if they are disabled */
624 #ifdef __GNUC__
625         CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
626 #else
627         { volatile register unsigned int Reg __asm(XREG_CP15_SYS_CONTROL);
628           CtrlReg = Reg; }
629 #endif
630         if (CtrlReg & XREG_CP15_CONTROL_C_BIT) {
631                 return;
632         }
633
634         /* clean and invalidate the Data cache */
635         Xil_L1DCacheInvalidate();
636
637         /* enable the Data cache */
638         CtrlReg |= (XREG_CP15_CONTROL_C_BIT);
639
640         mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
641 }
642
643 /****************************************************************************
644 *
645 * Disable the level 1 Data cache.
646 *
647 * @param        None.
648 *
649 * @return       None.
650 *
651 * @note         None.
652 *
653 ****************************************************************************/
654 void Xil_L1DCacheDisable(void)
655 {
656         register unsigned int CtrlReg;
657
658         /* clean and invalidate the Data cache */
659         Xil_L1DCacheFlush();
660
661 #ifdef __GNUC__
662         /* disable the Data cache */
663         CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
664 #else
665         { volatile register unsigned int Reg __asm(XREG_CP15_SYS_CONTROL);
666           CtrlReg = Reg; }
667 #endif
668
669         CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT);
670
671         mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
672 }
673
674 /****************************************************************************
675 *
676 * Invalidate the level 1 Data cache.
677 *
678 * @param        None.
679 *
680 * @return       None.
681 *
682 * @note         In Cortex A9, there is no cp instruction for invalidating
683 *               the whole D-cache. This function invalidates each line by
684 *               set/way.
685 *
686 ****************************************************************************/
687 void Xil_L1DCacheInvalidate(void)
688 {
689         register unsigned int CsidReg, C7Reg;
690         unsigned int CacheSize, LineSize, NumWays;
691         unsigned int Way, WayIndex, Set, SetIndex, NumSet;
692         unsigned int currmask;
693         
694 #ifdef __GNUC__
695         unsigned int stack_start,stack_end,stack_size;
696 #endif 
697         
698         currmask = mfcpsr();
699         mtcpsr(currmask | IRQ_FIQ_MASK);
700         
701 #ifdef __GNUC__
702         stack_end = (unsigned int )&_stack_end;
703         stack_start = (unsigned int )&_stack;
704         stack_size=stack_start-stack_end;
705
706         /*Flush stack memory to save return address*/
707         Xil_DCacheFlushRange(stack_end, stack_size);
708 #endif
709         
710         /* Select cache level 0 and D cache in CSSR */
711         mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
712
713 #ifdef __GNUC__
714         CsidReg = mfcp(XREG_CP15_CACHE_SIZE_ID);
715 #else
716         { volatile register unsigned int Reg __asm(XREG_CP15_CACHE_SIZE_ID);
717           CsidReg = Reg; }
718 #endif
719         /* Determine Cache Size */
720         CacheSize = (CsidReg >> 13) & 0x1FF;
721         CacheSize +=1;
722         CacheSize *=128;    /* to get number of bytes */
723
724         /* Number of Ways */
725         NumWays = (CsidReg & 0x3ff) >> 3;
726         NumWays += 1;
727
728         /* Get the cacheline size, way size, index size from csidr */
729         LineSize = (CsidReg & 0x07) + 4;
730
731         NumSet = CacheSize/NumWays;
732         NumSet /= (1 << LineSize);
733
734         Way = 0UL;
735         Set = 0UL;
736
737         /* Invalidate all the cachelines */
738         for (WayIndex =0; WayIndex < NumWays; WayIndex++) {
739                 for (SetIndex =0; SetIndex < NumSet; SetIndex++) {
740                         C7Reg = Way | Set;
741 #ifdef __GNUC__
742                         /* Invalidate by Set/Way */
743                         __asm__ __volatile__("mcr " \
744                         XREG_CP15_INVAL_DC_LINE_SW :: "r" (C7Reg));
745 #else
746                         //mtcp(XREG_CP15_INVAL_DC_LINE_SW, C7Reg);
747                         { volatile register unsigned int Reg
748                                 __asm(XREG_CP15_INVAL_DC_LINE_SW);
749                           Reg = C7Reg; }
750 #endif
751                         Set += (1 << LineSize);
752                 }
753                 Set=0UL;
754                 Way += 0x40000000;
755         }
756
757         /* Wait for L1 invalidate to complete */
758         dsb();
759         mtcpsr(currmask);
760 }
761
762 /****************************************************************************
763 *
764 * Invalidate a level 1 Data cache line. If the byte specified by the address
765 * (Addr) is cached by the Data cache, the cacheline containing that byte is
766 * invalidated.  If the cacheline is modified (dirty), the modified contents
767 * are lost and are NOT written to system memory before the line is
768 * invalidated.
769 *
770 * @param        Address to be flushed.
771 *
772 * @return       None.
773 *
774 * @note         The bottom 5 bits are set to 0, forced by architecture.
775 *
776 ****************************************************************************/
777 void Xil_L1DCacheInvalidateLine(unsigned int adr)
778 {
779         mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
780         mtcp(XREG_CP15_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F)));
781
782         /* Wait for L1 invalidate to complete */
783         dsb();
784 }
785
786 /****************************************************************************
787 *
788 * Invalidate the level 1 Data cache for the given address range.
789 * If the bytes specified by the address (adr) are cached by the Data cache,
790 * the cacheline containing that byte is invalidated. If the cacheline
791 * is modified (dirty), the modified contents are lost and are NOT
792 * written to system memory before the line is invalidated.
793 *
794 * @param        Start address of range to be invalidated.
795 * @param        Length of range to be invalidated in bytes.
796 *
797 * @return       None.
798 *
799 * @note         None.
800 *
801 ****************************************************************************/
802 void Xil_L1DCacheInvalidateRange(unsigned int adr, unsigned len)
803 {
804         const unsigned cacheline = 32;
805         unsigned int end;
806         unsigned int currmask;
807
808         currmask = mfcpsr();
809         mtcpsr(currmask | IRQ_FIQ_MASK);
810
811         if (len != 0) {
812                 /* Back the starting address up to the start of a cache line
813                  * perform cache operations until adr+len
814                  */
815                 end = adr + len;
816                 adr = adr & ~(cacheline - 1);
817
818                 /* Select cache L0 D-cache in CSSR */
819                 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
820
821                 while (adr < end) {
822 #ifdef __GNUC__
823                         __asm__ __volatile__("mcr " \
824                         XREG_CP15_INVAL_DC_LINE_MVA_POC :: "r" (adr));
825 #else
826                         { volatile register unsigned int Reg
827                                 __asm(XREG_CP15_INVAL_DC_LINE_MVA_POC);
828                           Reg = adr; }
829 #endif
830                         adr += cacheline;
831                 }
832         }
833
834         /* Wait for L1 invalidate to complete */
835         dsb();
836         mtcpsr(currmask);
837 }
838
839 /****************************************************************************
840 *
841 * Flush the level 1 Data cache.
842 *
843 * @param        None.
844 *
845 * @return       None.
846 *
847 * @note         In Cortex A9, there is no cp instruction for flushing
848 *               the whole D-cache. Need to flush each line.
849 *
850 ****************************************************************************/
851 void Xil_L1DCacheFlush(void)
852 {
853         register unsigned int CsidReg, C7Reg;
854         unsigned int CacheSize, LineSize, NumWays;
855         unsigned int Way, WayIndex, Set, SetIndex, NumSet;
856         unsigned int currmask;
857
858         currmask = mfcpsr();
859         mtcpsr(currmask | IRQ_FIQ_MASK);
860
861         /* Select cache level 0 and D cache in CSSR */
862         mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
863
864 #ifdef __GNUC__
865         CsidReg = mfcp(XREG_CP15_CACHE_SIZE_ID);
866 #else
867         { volatile register unsigned int Reg __asm(XREG_CP15_CACHE_SIZE_ID);
868           CsidReg = Reg; }
869 #endif
870
871         /* Determine Cache Size */
872
873         CacheSize = (CsidReg >> 13) & 0x1FF;
874         CacheSize +=1;
875         CacheSize *=128;    /* to get number of bytes */
876
877         /* Number of Ways */
878         NumWays = (CsidReg & 0x3ff) >> 3;
879         NumWays += 1;
880
881         /* Get the cacheline size, way size, index size from csidr */
882         LineSize = (CsidReg & 0x07) + 4;
883
884         NumSet = CacheSize/NumWays;
885         NumSet /= (1 << LineSize);
886
887         Way = 0UL;
888         Set = 0UL;
889
890         /* Invalidate all the cachelines */
891         for (WayIndex =0; WayIndex < NumWays; WayIndex++) {
892                 for (SetIndex =0; SetIndex < NumSet; SetIndex++) {
893                         C7Reg = Way | Set;
894                         /* Flush by Set/Way */
895 #ifdef __GNUC__
896                         __asm__ __volatile__("mcr " \
897                         XREG_CP15_CLEAN_INVAL_DC_LINE_SW :: "r" (C7Reg));
898 #else
899                         { volatile register unsigned int Reg
900                                 __asm(XREG_CP15_CLEAN_INVAL_DC_LINE_SW);
901                           Reg = C7Reg; }
902 #endif
903                         Set += (1 << LineSize);
904                 }
905                 Set = 0UL;
906                 Way += 0x40000000;
907         }
908
909         /* Wait for L1 flush to complete */
910         dsb();
911         mtcpsr(currmask);
912 }
913
914 /****************************************************************************
915 *
916 * Flush a level 1 Data cache line. If the byte specified by the address (adr)
917 * is cached by the Data cache, the cacheline containing that byte is
918 * invalidated.  If the cacheline is modified (dirty), the entire
919 * contents of the cacheline are written to system memory before the
920 * line is invalidated.
921 *
922 * @param        Address to be flushed.
923 *
924 * @return       None.
925 *
926 * @note         The bottom 5 bits are set to 0, forced by architecture.
927 *
928 ****************************************************************************/
929 void Xil_L1DCacheFlushLine(unsigned int adr)
930 {
931         mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
932         mtcp(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F)));
933
934         /* Wait for L1 flush to complete */
935         dsb();
936 }
937
938 /****************************************************************************
939 * Flush the level 1  Data cache for the given address range.
940 * If the bytes specified by the address (adr) are cached by the Data cache,
941 * the cacheline containing that byte is invalidated.    If the cacheline
942 * is modified (dirty), the written to system memory first before the
943 * before the line is invalidated.
944 *
945 * @param        Start address of range to be flushed.
946 * @param        Length of range to be flushed in bytes.
947 *
948 * @return       None.
949 *
950 * @note         None.
951 *
952 ****************************************************************************/
953 void Xil_L1DCacheFlushRange(unsigned int adr, unsigned len)
954 {
955         const unsigned cacheline = 32;
956         unsigned int end;
957         unsigned int currmask;
958
959         currmask = mfcpsr();
960         mtcpsr(currmask | IRQ_FIQ_MASK);
961
962         if (len != 0) {
963                 /* Back the starting address up to the start of a cache line
964                  * perform cache operations until adr+len
965                  */
966                 end = adr + len;
967                 adr = adr & ~(cacheline - 1);
968
969                 /* Select cache L0 D-cache in CSSR */
970                 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
971
972                 while (adr < end) {
973 #ifdef __GNUC__
974                         __asm__ __volatile__("mcr " \
975                         XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC :: "r" (adr));
976 #else
977                         { volatile register unsigned int Reg
978                                 __asm(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC);
979                           Reg = adr; }
980 #endif
981                         adr += cacheline;
982                 }
983         }
984
985         /* Wait for L1 flush to complete */
986         dsb();
987         mtcpsr(currmask);
988 }
989
990 /****************************************************************************
991 *
992 * Store a level 1  Data cache line. If the byte specified by the address (adr)
993 * is cached by the Data cache and the cacheline is modified (dirty),
994 * the entire contents of the cacheline are written to system memory.
995 * After the store completes, the cacheline is marked as unmodified
996 * (not dirty).
997 *
998 * @param        Address to be stored.
999 *
1000 * @return       None.
1001 *
1002 * @note         The bottom 5 bits are set to 0, forced by architecture.
1003 *
1004 ****************************************************************************/
1005 void Xil_L1DCacheStoreLine(unsigned int adr)
1006 {
1007         mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
1008         mtcp(XREG_CP15_CLEAN_DC_LINE_MVA_POC, (adr & (~0x1F)));
1009
1010         /* Wait for L1 store to complete */
1011         dsb();
1012 }
1013
1014 /****************************************************************************
1015 *
1016 * Enable the level 1 instruction cache.
1017 *
1018 * @param        None.
1019 *
1020 * @return       None.
1021 *
1022 * @note         None.
1023 *
1024 ****************************************************************************/
1025 void Xil_L1ICacheEnable(void)
1026 {
1027         register unsigned int CtrlReg;
1028
1029         /* enable caches only if they are disabled */
1030 #ifdef __GNUC__
1031         CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
1032 #else
1033         { volatile register unsigned int Reg __asm(XREG_CP15_SYS_CONTROL);
1034           CtrlReg = Reg; }
1035 #endif
1036         if (CtrlReg & XREG_CP15_CONTROL_I_BIT) {
1037                 return;
1038         }
1039
1040         /* invalidate the instruction cache */
1041         mtcp(XREG_CP15_INVAL_IC_POU, 0);
1042
1043         /* enable the instruction cache */
1044         CtrlReg |= (XREG_CP15_CONTROL_I_BIT);
1045
1046         mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
1047 }
1048
1049 /****************************************************************************
1050 *
1051 * Disable level 1 the instruction cache.
1052 *
1053 * @param        None.
1054 *
1055 * @return       None.
1056 *
1057 * @note         None.
1058 *
1059 ****************************************************************************/
1060 void Xil_L1ICacheDisable(void)
1061 {
1062         register unsigned int CtrlReg;
1063
1064         dsb();
1065
1066         /* invalidate the instruction cache */
1067         mtcp(XREG_CP15_INVAL_IC_POU, 0);
1068
1069         /* disable the instruction cache */
1070 #ifdef __GNUC__
1071         CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
1072 #else
1073         { volatile register unsigned int Reg __asm(XREG_CP15_SYS_CONTROL);
1074           CtrlReg = Reg; }
1075 #endif
1076         CtrlReg &= ~(XREG_CP15_CONTROL_I_BIT);
1077
1078         mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
1079 }
1080
1081 /****************************************************************************
1082 *
1083 * Invalidate the entire level 1 instruction cache.
1084 *
1085 * @param        None.
1086 *
1087 * @return       None.
1088 *
1089 * @note         None.
1090 *
1091 ****************************************************************************/
1092 void Xil_L1ICacheInvalidate(void)
1093 {
1094         mtcp(XREG_CP15_CACHE_SIZE_SEL, 1);
1095         /* invalidate the instruction cache */
1096         mtcp(XREG_CP15_INVAL_IC_POU, 0);
1097
1098         /* Wait for L1 invalidate to complete */
1099         dsb();
1100 }
1101
1102 /****************************************************************************
1103 *
1104 * Invalidate a level 1  instruction cache line. If the instruction specified by
1105 * the parameter adr is cached by the instruction cache, the cacheline containing
1106 * that instruction is invalidated.
1107 *
1108 * @param        None.
1109 *
1110 * @return       None.
1111 *
1112 * @note         The bottom 5 bits are set to 0, forced by architecture.
1113 *
1114 ****************************************************************************/
1115 void Xil_L1ICacheInvalidateLine(unsigned int adr)
1116 {
1117         mtcp(XREG_CP15_CACHE_SIZE_SEL, 1);
1118         mtcp(XREG_CP15_INVAL_IC_LINE_MVA_POU, (adr & (~0x1F)));
1119
1120         /* Wait for L1 invalidate to complete */
1121         dsb();
1122 }
1123
1124 /****************************************************************************
1125 *
1126 * Invalidate the level 1 instruction cache for the given address range.
1127 * If the bytes specified by the address (adr) are cached by the Data cache,
1128 * the cacheline containing that byte is invalidated.    If the cacheline
1129 * is modified (dirty), the modified contents are lost and are NOT
1130 * written to system memory before the line is invalidated.
1131 *
1132 * @param        Start address of range to be invalidated.
1133 * @param        Length of range to be invalidated in bytes.
1134 *
1135 * @return       None.
1136 *
1137 * @note         None.
1138 *
1139 ****************************************************************************/
1140 void Xil_L1ICacheInvalidateRange(unsigned int adr, unsigned len)
1141 {
1142         const unsigned cacheline = 32;
1143         unsigned int end;
1144         unsigned int currmask;
1145
1146         currmask = mfcpsr();
1147         mtcpsr(currmask | IRQ_FIQ_MASK);
1148
1149         if (len != 0) {
1150                 /* Back the starting address up to the start of a cache line
1151                  * perform cache operations until adr+len
1152                  */
1153                 end = adr + len;
1154                 adr = adr & ~(cacheline - 1);
1155
1156                 /* Select cache L0 I-cache in CSSR */
1157                 mtcp(XREG_CP15_CACHE_SIZE_SEL, 1);
1158
1159                 while (adr < end) {
1160 #ifdef __GNUC__
1161                         __asm__ __volatile__("mcr " \
1162                         XREG_CP15_INVAL_IC_LINE_MVA_POU :: "r" (adr));
1163 #else
1164                         { volatile register unsigned int Reg
1165                                 __asm(XREG_CP15_INVAL_IC_LINE_MVA_POU);
1166                           Reg = adr; }
1167 #endif
1168                         adr += cacheline;
1169                 }
1170         }
1171
1172         /* Wait for L1 invalidate to complete */
1173         dsb();
1174         mtcpsr(currmask);
1175 }
1176
1177 /****************************************************************************
1178 *
1179 * Enable the L2 cache.
1180 *
1181 * @param        None.
1182 *
1183 * @return       None.
1184 *
1185 * @note         None.
1186 *
1187 ****************************************************************************/
1188 void Xil_L2CacheEnable(void)
1189 {
1190         register unsigned int L2CCReg;
1191
1192         L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET);
1193
1194         /* only enable if L2CC is currently disabled */
1195         if ((L2CCReg & 0x01) == 0) {
1196                 /* set up the way size and latencies */
1197                 L2CCReg = Xil_In32(XPS_L2CC_BASEADDR +
1198                                    XPS_L2CC_AUX_CNTRL_OFFSET);
1199                 L2CCReg &= XPS_L2CC_AUX_REG_ZERO_MASK;
1200                 L2CCReg |= XPS_L2CC_AUX_REG_DEFAULT_MASK;
1201                 Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_AUX_CNTRL_OFFSET,
1202                           L2CCReg);
1203                 Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_TAG_RAM_CNTRL_OFFSET,
1204                           XPS_L2CC_TAG_RAM_DEFAULT_MASK);
1205                 Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_DATA_RAM_CNTRL_OFFSET,
1206                           XPS_L2CC_DATA_RAM_DEFAULT_MASK);
1207
1208                 /* Clear the pending interrupts */
1209                 L2CCReg = Xil_In32(XPS_L2CC_BASEADDR +
1210                                    XPS_L2CC_ISR_OFFSET);
1211                 Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_IAR_OFFSET, L2CCReg);
1212
1213                 Xil_L2CacheInvalidate();
1214                 /* Enable the L2CC */
1215                 L2CCReg = Xil_In32(XPS_L2CC_BASEADDR +
1216                                    XPS_L2CC_CNTRL_OFFSET);
1217                 Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET,
1218                           (L2CCReg | (0x01)));
1219
1220         Xil_L2CacheSync();
1221         /* synchronize the processor */
1222             dsb();
1223
1224     }
1225 }
1226
1227 /****************************************************************************
1228 *
1229 * Disable the L2 cache.
1230 *
1231 * @param        None.
1232 *
1233 * @return       None.
1234 *
1235 * @note         None.
1236 *
1237 ****************************************************************************/
1238 void Xil_L2CacheDisable(void)
1239 {
1240     register unsigned int L2CCReg;
1241
1242         L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET);
1243
1244     if(L2CCReg & 0x1) {
1245
1246         /* Clean and Invalidate L2 Cache */
1247         Xil_L2CacheFlush();
1248
1249             /* Disable the L2CC */
1250         L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET);
1251             Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET,
1252                       (L2CCReg & (~0x01)));
1253                 /* Wait for the cache operations to complete */
1254
1255                 dsb();
1256     }
1257 }
1258
1259 /****************************************************************************
1260 *
1261 * Invalidate the L2 cache. If the byte specified by the address (adr)
1262 * is cached by the Data cache, the cacheline containing that byte is
1263 * invalidated.  If the cacheline is modified (dirty), the modified contents
1264 * are lost and are NOT written to system memory before the line is
1265 * invalidated.
1266 *
1267 * @param        Address to be flushed.
1268 *
1269 * @return       None.
1270 *
1271 * @note         The bottom 4 bits are set to 0, forced by architecture.
1272 *
1273 ****************************************************************************/
1274 void Xil_L2CacheInvalidate(void)
1275 {
1276         /* Invalidate the caches */
1277         Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_WAY_OFFSET,
1278                   0x0000FFFF);
1279         while((Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_WAY_OFFSET))
1280                                                                                                                                 & 0x0000FFFF);
1281
1282         /* Wait for the invalidate to complete */
1283         Xil_L2CacheSync();
1284
1285         /* synchronize the processor */
1286         dsb();
1287 }
1288
1289 /****************************************************************************
1290 *
1291 * Invalidate a level 2 cache line. If the byte specified by the address (adr)
1292 * is cached by the Data cache, the cacheline containing that byte is
1293 * invalidated.  If the cacheline is modified (dirty), the modified contents
1294 * are lost and are NOT written to system memory before the line is
1295 * invalidated.
1296 *
1297 * @param        Address to be flushed.
1298 *
1299 * @return       None.
1300 *
1301 * @note         The bottom 4 bits are set to 0, forced by architecture.
1302 *
1303 ****************************************************************************/
1304 void Xil_L2CacheInvalidateLine(unsigned int adr)
1305 {
1306         Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_PA_OFFSET, adr);
1307         /* synchronize the processor */
1308         dsb();
1309 }
1310
1311 /****************************************************************************
1312 *
1313 * Invalidate the level 2 cache for the given address range.
1314 * If the bytes specified by the address (adr) are cached by the Data cache,
1315 * the cacheline containing that byte is invalidated.    If the cacheline
1316 * is modified (dirty), the modified contents are lost and are NOT
1317 * written to system memory before the line is invalidated.
1318 *
1319 * @param        Start address of range to be invalidated.
1320 * @param        Length of range to be invalidated in bytes.
1321 *
1322 * @return       None.
1323 *
1324 * @note         None.
1325 *
1326 ****************************************************************************/
1327 void Xil_L2CacheInvalidateRange(unsigned int adr, unsigned len)
1328 {
1329         const unsigned cacheline = 32;
1330         unsigned int end;
1331         volatile u32 *L2CCOffset = (volatile u32 *) (XPS_L2CC_BASEADDR +
1332                                     XPS_L2CC_CACHE_INVLD_PA_OFFSET);
1333
1334         unsigned int currmask;
1335
1336         currmask = mfcpsr();
1337         mtcpsr(currmask | IRQ_FIQ_MASK);
1338
1339         if (len != 0) {
1340                 /* Back the starting address up to the start of a cache line
1341                  * perform cache operations until adr+len
1342                  */
1343                 end = adr + len;
1344                 adr = adr & ~(cacheline - 1);
1345
1346                 /* Disable Write-back and line fills */
1347                 Xil_L2WriteDebugCtrl(0x3);
1348
1349                 while (adr < end) {
1350                         *L2CCOffset = adr;
1351                         adr += cacheline;
1352                 }
1353
1354                 /* Enable Write-back and line fills */
1355                 Xil_L2WriteDebugCtrl(0x0);
1356         }
1357
1358         /* synchronize the processor */
1359         dsb();
1360         mtcpsr(currmask);
1361 }
1362
1363 /****************************************************************************
1364 *
1365 * Flush the L2 cache. If the byte specified by the address (adr)
1366 * is cached by the Data cache, the cacheline containing that byte is
1367 * invalidated. If the cacheline is modified (dirty), the entire
1368 * contents of the cacheline are written to system memory before the
1369 * line is invalidated.
1370 *
1371 * @param        Address to be flushed.
1372 *
1373 * @return       None.
1374 *
1375 * @note         The bottom 4 bits are set to 0, forced by architecture.
1376 *
1377 ****************************************************************************/
1378 void Xil_L2CacheFlush(void)
1379 {
1380
1381         /* Flush the caches */
1382
1383         /* Disable Write-back and line fills */
1384         Xil_L2WriteDebugCtrl(0x3);
1385
1386         Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INV_CLN_WAY_OFFSET,
1387                   0x0000FFFF);
1388
1389         while((Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INV_CLN_WAY_OFFSET))
1390                                                                                                                         & 0x0000FFFF);
1391
1392         Xil_L2CacheSync();
1393         /* Enable Write-back and line fills */
1394         Xil_L2WriteDebugCtrl(0x0);
1395
1396         /* synchronize the processor */
1397         dsb();
1398 }
1399
1400 /****************************************************************************
1401 *
1402 * Flush a level 2 cache line. If the byte specified by the address (adr)
1403 * is cached by the Data cache, the cacheline containing that byte is
1404 * invalidated. If the cacheline is modified (dirty), the entire
1405 * contents of the cacheline are written to system memory before the
1406 * line is invalidated.
1407 *
1408 * @param        Address to be flushed.
1409 *
1410 * @return       None.
1411 *
1412 * @note         The bottom 4 bits are set to 0, forced by architecture.
1413 *
1414 ****************************************************************************/
1415 void Xil_L2CacheFlushLine(unsigned int adr)
1416 {
1417 #ifdef CONFIG_PL310_ERRATA_588369
1418         Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_CLEAN_PA_OFFSET, adr);
1419         Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_PA_OFFSET, adr);
1420 #else
1421         Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INV_CLN_PA_OFFSET, adr);
1422 #endif
1423         /* synchronize the processor */
1424         dsb();
1425 }
1426
1427 /****************************************************************************
1428 * Flush the level 2 cache for the given address range.
1429 * If the bytes specified by the address (adr) are cached by the Data cache,
1430 * the cacheline containing that byte is invalidated.    If the cacheline
1431 * is modified (dirty), the written to system memory first before the
1432 * before the line is invalidated.
1433 *
1434 * @param        Start address of range to be flushed.
1435 * @param        Length of range to be flushed in bytes.
1436 *
1437 * @return       None.
1438 *
1439 * @note         None.
1440 *
1441 ****************************************************************************/
1442 void Xil_L2CacheFlushRange(unsigned int adr, unsigned len)
1443 {
1444         const unsigned cacheline = 32;
1445         unsigned int end;
1446         volatile u32 *L2CCOffset = (volatile u32 *) (XPS_L2CC_BASEADDR +
1447                                     XPS_L2CC_CACHE_INV_CLN_PA_OFFSET);
1448
1449         unsigned int currmask;
1450
1451         currmask = mfcpsr();
1452         mtcpsr(currmask | IRQ_FIQ_MASK);
1453         if (len != 0) {
1454                 /* Back the starting address up to the start of a cache line
1455                  * perform cache operations until adr+len
1456                  */
1457                 end = adr + len;
1458                 adr = adr & ~(cacheline - 1);
1459
1460                 /* Disable Write-back and line fills */
1461                 Xil_L2WriteDebugCtrl(0x3);
1462
1463                 while (adr < end) {
1464                         *L2CCOffset = adr;
1465                         Xil_L2CacheSync();
1466                         adr += cacheline;
1467                 }
1468
1469                 /* Enable Write-back and line fills */
1470                 Xil_L2WriteDebugCtrl(0x0);
1471         }
1472         /* synchronize the processor */
1473         dsb();
1474         mtcpsr(currmask);
1475 }
1476
1477 /****************************************************************************
1478 *
1479 * Store a level 2 cache line. If the byte specified by the address (adr)
1480 * is cached by the Data cache and the cacheline is modified (dirty),
1481 * the entire contents of the cacheline are written to system memory.
1482 * After the store completes, the cacheline is marked as unmodified
1483 * (not dirty).
1484 *
1485 * @param        Address to be stored.
1486 *
1487 * @return       None.
1488 *
1489 * @note         The bottom 4 bits are set to 0, forced by architecture.
1490 *
1491 ****************************************************************************/
1492 void Xil_L2CacheStoreLine(unsigned int adr)
1493 {
1494         Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_CLEAN_PA_OFFSET, adr);
1495         /* synchronize the processor */
1496         dsb();
1497 }