]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo_bsp/ps7_cortexa9_0/libsrc/standalone_v6_6/src/xil_cache.c
Update Zynq, MPSoc Cortex-A53 and MPSoc Cortex-R5 demo projects to build with the...
[freertos] / FreeRTOS / Demo / CORTEX_A9_Zynq_ZC702 / RTOSDemo_bsp / ps7_cortexa9_0 / libsrc / standalone_v6_6 / src / xil_cache.c
1 /******************************************************************************
2 *
3 * Copyright (C) 2010 - 2015 Xilinx, Inc.  All rights reserved.
4 *
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:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
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.
18 *
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
25 * SOFTWARE.
26 *
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.
30 *
31 ******************************************************************************/
32 /*****************************************************************************/
33 /**
34 *
35 * @file xil_cache.c
36 *
37 * Contains required functions for the ARM cache functionality.
38 *
39 * <pre>
40 * MODIFICATION HISTORY:
41 *
42 * Ver    Who Date     Changes
43 * ----- ---- -------- -----------------------------------------------
44 * 1.00a  ecm 01/29/10 First release
45 * 1.00a  ecm 06/24/10 Moved the L1 and L2 specific function prototypes
46 *                                 to xil_cache_mach.h to give access to sophisticated users
47 * 3.02a  sdm 04/07/11 Updated Flush/InvalidateRange APIs to flush/invalidate
48 *                                 L1 and L2 caches in a single loop and used dsb, L2 sync
49 *                                 at the end of the loop.
50 * 3.04a  sdm 01/02/12 Remove redundant dsb/dmb instructions in cache maintenance
51 *                                 APIs.
52 * 3.07a  asa 07/16/12 Corrected the L1 and L2 cache invalidation order.
53 * 3.07a  sgd 09/18/12 Corrected the L2 cache enable and disable sequence.
54 * 3.10a  srt 04/18/13 Implemented ARM Erratas. Please refer to file
55 *                                 'xil_errata.h' for errata description
56 * 3.10a  asa 05/13/13 Modified cache disable APIs. The L2 cache disable
57 *                                         operation was being done with L1 Data cache disabled. This is
58 *                                         fixed so that L2 cache disable operation happens independent of
59 *                                         L1 cache disable operation. This fixes CR #706464.
60 *                                         Changes are done to do a L2 cache sync (poll reg7_?cache_?sync).
61 *                                         This is done to fix the CR #700542.
62 * 3.11a  asa 09/23/13 Modified the Xil_DCacheFlushRange and
63 *                                         Xil_DCacheInvalidateRange to fix potential issues. Fixed other
64 *                                         relevant cache APIs to disable and enable back the interrupts.
65 *                                         This fixes CR #663885.
66 * 3.11a  asa 09/28/13 Made changes for L2 cache sync operation. It is found
67 *                                         out that for L2 cache flush/clean/invalidation by cache lines
68 *                                         does not need a cache sync as these are atomic nature. Similarly
69 *                                         figured out that for complete L2 cache flush/invalidation by way
70 *                                         we need to wait for some more time in a loop till the status
71 *                                         shows that the cache operation is completed.
72 * 4.00   pkp 24/01/14 Modified Xil_DCacheInvalidateRange to fix the bug. Few
73 *                                         cache lines were missed to invalidate when unaligned address
74 *                                         invalidation was accommodated. That fixes CR #766768.
75 *                                         Also in Xil_L1DCacheInvalidate, while invalidating all L1D cache
76 *                                         stack memory which contains return address was invalidated. So
77 *                                         stack memory was flushed first and then L1D cache is invalidated.
78 *                                         This is done to fix CR #763829
79 * 4.01   asa 05/09/14 Made changes in cortexa9/xil_cache.c to fix CR# 798230.
80 * 4.02   pkp 06/27/14 Added notes to Xil_L1DCacheInvalidateRange function for
81 *                                         explanation of CR#785243
82 * 5.00   kvn 12/15/14 Xil_L2CacheInvalidate was modified to fix CR# 838835. L2 Cache
83 *                                         has stack memory which has return address. Before invalidating
84 *                                         cache, stack memory was flushed first and L2 Cache is invalidated.
85 * 5.01   pkp 05/12/15 Xil_DCacheInvalidateRange and Xil_DCacheFlushRange is modified
86 *                                         to remove unnecessary dsb in the APIs. Instead of using dsb
87 *                                         for L2 Cache, L2CacheSync has been used for each L2 cache line
88 *                                         and single dsb has been used for L1 cache. Also L2CacheSync is
89 *                                         added into Xil_L2CacheInvalidateRange API. Xil_L1DCacheInvalidate
90 *                                         and Xil_L2CacheInvalidate APIs are modified to flush the complete
91 *                                         stack instead of just System Stack
92 * 5.03   pkp 10/07/15 L2 Cache functionalities are avoided for the OpenAMP slave
93 *                                         application(when USE_AMP flag is defined for BSP) as master CPU
94 *                                         would be utilizing L2 cache for its operation
95 * 6.6    mus 12/07/17 Errata 753970 is not applicable for the PL130 cache controller
96 *                     version r0p2, which is present in zynq. So,removed the handling
97 *                     related to same.It fixes CR#989132.
98 * 6.6    asa 16/01/18 Changes made in Xil_L1DCacheInvalidate and Xil_L2CacheInvalidate
99 *                                         routines to ensure the stack data flushed only when the respective
100 *                                         caches are enabled. This fixes CR-992023.
101 *
102 * </pre>
103 *
104 ******************************************************************************/
105
106 /***************************** Include Files *********************************/
107
108 #include "xil_cache.h"
109 #include "xil_cache_l.h"
110 #include "xil_io.h"
111 #include "xpseudo_asm.h"
112 #include "xparameters.h"
113 #include "xreg_cortexa9.h"
114 #include "xl2cc.h"
115 #include "xil_errata.h"
116 #include "xil_exception.h"
117
118 /************************** Function Prototypes ******************************/
119
120 /************************** Variable Definitions *****************************/
121
122 #define IRQ_FIQ_MASK 0xC0U      /* Mask IRQ and FIQ interrupts in cpsr */
123
124 #ifdef __GNUC__
125         extern s32  _stack_end;
126         extern s32  __undef_stack;
127 #endif
128
129 #ifndef USE_AMP
130 /****************************************************************************
131 *
132 * Access L2 Debug Control Register.
133 *
134 * @param        Value, value to be written to Debug Control Register.
135 *
136 * @return       None.
137 *
138 * @note         None.
139 *
140 ****************************************************************************/
141 #ifdef __GNUC__
142 static inline void Xil_L2WriteDebugCtrl(u32 Value)
143 #else
144 static void Xil_L2WriteDebugCtrl(u32 Value)
145 #endif
146 {
147 #if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915)
148         Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_DEBUG_CTRL_OFFSET, Value);
149 #else
150         (void)(Value);
151 #endif
152 }
153
154 /****************************************************************************
155 *
156 * Perform L2 Cache Sync Operation.
157 *
158 * @param        None.
159 *
160 * @return       None.
161 *
162 * @note         None.
163 *
164 ****************************************************************************/
165 #ifdef __GNUC__
166 static inline void Xil_L2CacheSync(void)
167 #else
168 static void Xil_L2CacheSync(void)
169 #endif
170 {
171         Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_SYNC_OFFSET, 0x0U);
172 }
173 #endif
174 /****************************************************************************/
175 /**
176 * @brief        Enable the Data cache.
177 *
178 * @param        None.
179 *
180 * @return       None.
181 *
182 * @note         None.
183 *
184 ****************************************************************************/
185 void Xil_DCacheEnable(void)
186 {
187         Xil_L1DCacheEnable();
188 #ifndef USE_AMP
189         Xil_L2CacheEnable();
190 #endif
191 }
192
193 /****************************************************************************/
194 /**
195 * @brief        Disable the Data cache.
196 *
197 * @param        None.
198 *
199 * @return       None.
200 *
201 * @note         None.
202 *
203 ****************************************************************************/
204 void Xil_DCacheDisable(void)
205 {
206 #ifndef USE_AMP
207         Xil_L2CacheDisable();
208 #endif
209         Xil_L1DCacheDisable();
210 }
211
212 /****************************************************************************/
213 /**
214 * @brief        Invalidate the entire Data cache.
215 *
216 * @param        None.
217 *
218 * @return       None.
219 *
220 * @note         None.
221 *
222 ****************************************************************************/
223 void Xil_DCacheInvalidate(void)
224 {
225         u32 currmask;
226
227         currmask = mfcpsr();
228         mtcpsr(currmask | IRQ_FIQ_MASK);
229 #ifndef USE_AMP
230         Xil_L2CacheInvalidate();
231 #endif
232         Xil_L1DCacheInvalidate();
233
234         mtcpsr(currmask);
235 }
236
237 /*****************************************************************************/
238 /**
239 * @brief        Invalidate a Data cache line. If the byte specified by the address
240 *                       (adr) is cached by the Data cache, the cacheline containing that
241 *                       byte is invalidated. If the cacheline is modified (dirty), the
242 *                       modified contents are lost and are NOT written to the system memory
243 *                       before the line is invalidated.
244 *
245 * @param        adr: 32bit address of the data to be flushed.
246 *
247 * @return       None.
248 *
249 * @note         The bottom 4 bits are set to 0, forced by architecture.
250 *
251 ****************************************************************************/
252 void Xil_DCacheInvalidateLine(u32 adr)
253 {
254         u32 currmask;
255
256         currmask = mfcpsr();
257         mtcpsr(currmask | IRQ_FIQ_MASK);
258 #ifndef USE_AMP
259         Xil_L2CacheInvalidateLine(adr);
260 #endif
261         Xil_L1DCacheInvalidateLine(adr);
262
263         mtcpsr(currmask);
264 }
265
266
267 /*****************************************************************************/
268 /**
269 * @brief        Invalidate the Data cache for the given address range.
270 *                       If the bytes specified by the address range are cached by the Data
271 *                       cache, the cachelines containing those bytes are invalidated. If
272 *                       the cachelines are modified (dirty), the modified contents are lost
273 *                       and NOT written to the system memory before the lines are
274 *                       invalidated.
275 *
276 *                       In this function, if start address or end address is not aligned to
277 *                       cache-line, particular cache-line containing unaligned start or end
278 *                       address is flush first and then invalidated the others as
279 *                       invalidating the same unaligned cache line may result into loss of
280 *                       data. This issue raises few possibilities.
281 *
282 *                       If the address to be invalidated is not cache-line aligned, the
283 *                       following choices are available:
284 *                       1. Invalidate the cache line when required and do not bother much
285 *                       for the side effects. Though it sounds good, it can result in
286 *                       hard-to-debug issues. The problem is, if some other variable are
287 *                       allocated in the same cache line and had been recently updated
288 *                       (in cache), the invalidation would result in loss of data.
289 *                       2. Flush the cache line first. This will ensure that if any other
290 *                       variable present in the same cache line and updated recently are
291 *                       flushed out to memory. Then it can safely be invalidated. Again it
292 *                       sounds good, but this can result in issues. For example, when the
293 *                       invalidation happens in a typical ISR (after a DMA transfer has
294 *                       updated the memory), then flushing the cache line means, loosing
295 *                       data that were updated recently before the ISR got invoked.
296 *
297 *                       Linux prefers the second one. To have uniform implementation
298 *                       (across standalone and Linux), the second option is implemented.
299 *                       This being the case, follwoing needs to be taken care of:
300 *                       1. Whenever possible, the addresses must be cache line aligned.
301 *                       Please nore that, not just start address, even the end address must
302 *                       be cache line aligned. If that is taken care of, this will always
303 *                       work.
304 *                       2. Avoid situations where invalidation has to be done after the
305 *                       data is updated by peripheral/DMA directly into the memory. It is
306 *                       not tough to achieve (may be a bit risky). The common use case to
307 *                       do invalidation is when a DMA happens. Generally for such use
308 *                       cases, buffers can be allocated first and then start the DMA. The
309 *                       practice that needs to be followed here is, immediately after
310 *                       buffer allocation and before starting the DMA, do the invalidation.
311 *                       With this approach, invalidation need not to be done after the DMA
312 *                       transfer is over.
313 *
314 *                       This is going to always work if done carefully.
315 *                       However, the concern is, there is no guarantee that invalidate has
316 *                       not needed to be done after DMA is complete. For example, because
317 *                       of some reasons if the first cache line or last cache line
318 *                       (assuming the buffer in question comprises of multiple cache lines)
319 *                       are brought into cache (between the time it is invalidated and DMA
320 *                       completes) because of some speculative prefetching or reading data
321 *                       for a variable present in the same cache line, then we will have to
322 *                       invalidate the cache after DMA is complete.
323 *
324 *
325 * @param        adr: 32bit start address of the range to be invalidated.
326 * @param        len: Length of the range to be invalidated in bytes.
327 *
328 * @return       None.
329 *
330 * @note         None.
331 *
332 ****************************************************************************/
333 void Xil_DCacheInvalidateRange(INTPTR adr, u32 len)
334 {
335         const u32 cacheline = 32U;
336         u32 end;
337         u32 tempadr = adr;
338         u32 tempend;
339         u32 currmask;
340         volatile u32 *L2CCOffset = (volatile u32 *)(XPS_L2CC_BASEADDR +
341                                     XPS_L2CC_CACHE_INVLD_PA_OFFSET);
342
343         currmask = mfcpsr();
344         mtcpsr(currmask | IRQ_FIQ_MASK);
345
346         if (len != 0U) {
347                 end = tempadr + len;
348                 tempend = end;
349                 /* Select L1 Data cache in CSSR */
350                 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U);
351
352                 if ((tempadr & (cacheline-1U)) != 0U) {
353                         tempadr &= (~(cacheline - 1U));
354
355                         Xil_L1DCacheFlushLine(tempadr);
356 #ifndef USE_AMP
357                         /* Disable Write-back and line fills */
358                         Xil_L2WriteDebugCtrl(0x3U);
359                         Xil_L2CacheFlushLine(tempadr);
360                         /* Enable Write-back and line fills */
361                         Xil_L2WriteDebugCtrl(0x0U);
362                         Xil_L2CacheSync();
363 #endif
364                         tempadr += cacheline;
365                 }
366                 if ((tempend & (cacheline-1U)) != 0U) {
367                         tempend &= (~(cacheline - 1U));
368
369                         Xil_L1DCacheFlushLine(tempend);
370 #ifndef USE_AMP
371                         /* Disable Write-back and line fills */
372                         Xil_L2WriteDebugCtrl(0x3U);
373                         Xil_L2CacheFlushLine(tempend);
374                         /* Enable Write-back and line fills */
375                         Xil_L2WriteDebugCtrl(0x0U);
376                         Xil_L2CacheSync();
377 #endif
378                 }
379
380                 while (tempadr < tempend) {
381 #ifndef USE_AMP
382                         /* Invalidate L2 cache line */
383                         *L2CCOffset = tempadr;
384                         Xil_L2CacheSync();
385 #endif
386
387         /* Invalidate L1 Data cache line */
388 #if defined (__GNUC__) || defined (__ICCARM__)
389                         asm_cp15_inval_dc_line_mva_poc(tempadr);
390 #else
391                         { volatile register u32 Reg
392                                 __asm(XREG_CP15_INVAL_DC_LINE_MVA_POC);
393                           Reg = tempadr; }
394 #endif
395                         tempadr += cacheline;
396                 }
397         }
398
399         dsb();
400         mtcpsr(currmask);
401 }
402
403 /****************************************************************************/
404 /**
405 * @brief        Flush the entire Data cache.
406 *
407 * @param        None.
408 *
409 * @return       None.
410 *
411 * @note         None.
412 *
413 ****************************************************************************/
414 void Xil_DCacheFlush(void)
415 {
416         u32 currmask;
417
418         currmask = mfcpsr();
419         mtcpsr(currmask | IRQ_FIQ_MASK);
420         Xil_L1DCacheFlush();
421 #ifndef USE_AMP
422         Xil_L2CacheFlush();
423 #endif
424         mtcpsr(currmask);
425 }
426
427
428 /****************************************************************************/
429 /**
430 * @brief        Flush a Data cache line. If the byte specified by the address (adr)
431 *                       is cached by the Data cache, the cacheline containing that byte is
432 *                       invalidated. If the cacheline is modified (dirty), the entire
433 *                       contents of the cacheline are written to system memory before the
434 *                       line is invalidated.
435 *
436 * @param        adr: 32bit address of the data to be flushed.
437 *
438 * @return       None.
439 *
440 * @note         The bottom 4 bits are set to 0, forced by architecture.
441 *
442 ****************************************************************************/
443 void Xil_DCacheFlushLine(u32 adr)
444 {
445         u32 currmask;
446
447         currmask = mfcpsr();
448         mtcpsr(currmask | IRQ_FIQ_MASK);
449         Xil_L1DCacheFlushLine(adr);
450 #ifndef USE_AMP
451         /* Disable Write-back and line fills */
452         Xil_L2WriteDebugCtrl(0x3U);
453
454         Xil_L2CacheFlushLine(adr);
455
456         /* Enable Write-back and line fills */
457         Xil_L2WriteDebugCtrl(0x0U);
458         Xil_L2CacheSync();
459 #endif
460         mtcpsr(currmask);
461 }
462
463 /****************************************************************************/
464 /**
465 * @brief        Flush the Data cache for the given address range.
466 *                       If the bytes specified by the address range are cached by the
467 *                       data cache, the cachelines containing those bytes are invalidated.
468 *                       If the cachelines are modified (dirty), they are written to the
469 *                       system memory before the lines are invalidated.
470 *
471 * @param        adr: 32bit start address of the range to be flushed.
472 * @param        len: Length of the range to be flushed in bytes.
473 *
474 * @return       None.
475 *
476 * @note         None.
477 *
478 ****************************************************************************/
479 void Xil_DCacheFlushRange(INTPTR adr, u32 len)
480 {
481         u32 LocalAddr = adr;
482         const u32 cacheline = 32U;
483         u32 end;
484         u32 currmask;
485         volatile u32 *L2CCOffset = (volatile u32 *)(XPS_L2CC_BASEADDR +
486                                     XPS_L2CC_CACHE_INV_CLN_PA_OFFSET);
487
488         currmask = mfcpsr();
489         mtcpsr(currmask | IRQ_FIQ_MASK);
490
491         if (len != 0U) {
492                 /* Back the starting address up to the start of a cache line
493                  * perform cache operations until adr+len
494                  */
495                 end = LocalAddr + len;
496                 LocalAddr &= ~(cacheline - 1U);
497
498                 while (LocalAddr < end) {
499
500         /* Flush L1 Data cache line */
501 #if defined (__GNUC__) || defined (__ICCARM__)
502                         asm_cp15_clean_inval_dc_line_mva_poc(LocalAddr);
503 #else
504                         { volatile register u32 Reg
505                                 __asm(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC);
506                           Reg = LocalAddr; }
507 #endif
508 #ifndef USE_AMP
509                         /* Flush L2 cache line */
510                         *L2CCOffset = LocalAddr;
511                         Xil_L2CacheSync();
512 #endif
513                         LocalAddr += cacheline;
514                 }
515         }
516         dsb();
517         mtcpsr(currmask);
518 }
519 /****************************************************************************/
520 /**
521 * @brief        Store a Data cache line. If the byte specified by the address (adr)
522 *                       is cached by the Data cache and the cacheline is modified (dirty),
523 *                       the entire contents of the cacheline are written to system memory.
524 *                       After the store completes, the cacheline is marked as unmodified
525 *                       (not dirty).
526 *
527 * @param        adr: 32bit address of the data to be stored.
528 *
529 * @return       None.
530 *
531 * @note         The bottom 4 bits are set to 0, forced by architecture.
532 *
533 ****************************************************************************/
534 void Xil_DCacheStoreLine(u32 adr)
535 {
536         u32 currmask;
537
538         currmask = mfcpsr();
539         mtcpsr(currmask | IRQ_FIQ_MASK);
540
541         Xil_L1DCacheStoreLine(adr);
542 #ifndef USE_AMP
543         Xil_L2CacheStoreLine(adr);
544 #endif
545         mtcpsr(currmask);
546 }
547
548 /***************************************************************************/
549 /**
550 * @brief        Enable the instruction cache.
551 *
552 * @param        None.
553 *
554 * @return       None.
555 *
556 * @note         None.
557 *
558 ****************************************************************************/
559 void Xil_ICacheEnable(void)
560 {
561         Xil_L1ICacheEnable();
562 #ifndef USE_AMP
563         Xil_L2CacheEnable();
564 #endif
565 }
566
567 /***************************************************************************/
568 /**
569 * @brief        Disable the instruction cache.
570 *
571 * @param        None.
572 *
573 * @return       None.
574 *
575 * @note         None.
576 *
577 ****************************************************************************/
578 void Xil_ICacheDisable(void)
579 {
580 #ifndef USE_AMP
581         Xil_L2CacheDisable();
582 #endif
583         Xil_L1ICacheDisable();
584 }
585
586
587 /****************************************************************************/
588 /**
589 * @brief        Invalidate the entire instruction cache.
590 *
591 * @param        None.
592 *
593 * @return       None.
594 *
595 * @note         None.
596 *
597 ****************************************************************************/
598 void Xil_ICacheInvalidate(void)
599 {
600         u32 currmask;
601
602         currmask = mfcpsr();
603         mtcpsr(currmask | IRQ_FIQ_MASK);
604 #ifndef USE_AMP
605         Xil_L2CacheInvalidate();
606 #endif
607         Xil_L1ICacheInvalidate();
608
609         mtcpsr(currmask);
610 }
611
612 /****************************************************************************/
613 /**
614 * @brief        Invalidate an instruction cache line. If the instruction specified
615 *                       by the address is cached by the instruction cache, the cacheline
616 *                       containing that instruction is invalidated.
617 *
618 * @param        adr: 32bit address of the instruction to be invalidated.
619 *
620 * @return       None.
621 *
622 * @note         The bottom 4 bits are set to 0, forced by architecture.
623 *
624 ****************************************************************************/
625 void Xil_ICacheInvalidateLine(u32 adr)
626 {
627         u32 currmask;
628
629         currmask = mfcpsr();
630         mtcpsr(currmask | IRQ_FIQ_MASK);
631 #ifndef USE_AMP
632         Xil_L2CacheInvalidateLine(adr);
633 #endif
634         Xil_L1ICacheInvalidateLine(adr);
635         mtcpsr(currmask);
636 }
637
638 /****************************************************************************/
639 /**
640 * @brief        Invalidate the instruction cache for the given address range.
641 *                       If the instructions specified by the address range are cached by
642 *                       the instrunction cache, the cachelines containing those
643 *                       instructions are invalidated.
644 *
645 * @param        adr: 32bit start address of the range to be invalidated.
646 * @param        len: Length of the range to be invalidated in bytes.
647 *
648 * @return       None.
649 *
650 * @note         None.
651 *
652 ****************************************************************************/
653 void Xil_ICacheInvalidateRange(INTPTR adr, u32 len)
654 {
655         u32 LocalAddr = adr;
656         const u32 cacheline = 32U;
657         u32 end;
658         volatile u32 *L2CCOffset = (volatile u32 *)(XPS_L2CC_BASEADDR +
659                                     XPS_L2CC_CACHE_INVLD_PA_OFFSET);
660
661         u32 currmask;
662
663         currmask = mfcpsr();
664         mtcpsr(currmask | IRQ_FIQ_MASK);
665         if (len != 0U) {
666                 /* Back the starting address up to the start of a cache line
667                  * perform cache operations until adr+len
668                  */
669                 end = LocalAddr + len;
670                 LocalAddr = LocalAddr & ~(cacheline - 1U);
671
672                 /* Select cache L0 I-cache in CSSR */
673                 mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U);
674
675                 while (LocalAddr < end) {
676 #ifndef USE_AMP
677                 /* Invalidate L2 cache line */
678                 *L2CCOffset = LocalAddr;
679                 dsb();
680 #endif
681
682                 /* Invalidate L1 I-cache line */
683 #if defined (__GNUC__) || defined (__ICCARM__)
684                         asm_cp15_inval_ic_line_mva_pou(LocalAddr);
685 #else
686                         { volatile register u32 Reg
687                                 __asm(XREG_CP15_INVAL_IC_LINE_MVA_POU);
688                           Reg = LocalAddr; }
689 #endif
690
691                         LocalAddr += cacheline;
692                 }
693         }
694
695         /* Wait for L1 and L2 invalidate to complete */
696         dsb();
697         mtcpsr(currmask);
698 }
699
700 /****************************************************************************/
701 /**
702 * @brief        Enable the level 1 Data cache.
703 *
704 * @param        None.
705 *
706 * @return       None.
707 *
708 * @note         None.
709 *
710 ****************************************************************************/
711 void Xil_L1DCacheEnable(void)
712 {
713         register u32 CtrlReg;
714
715         /* enable caches only if they are disabled */
716 #ifdef __GNUC__
717         CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
718 #elif defined (__ICCARM__)
719         mfcp(XREG_CP15_SYS_CONTROL, CtrlReg);
720 #else
721         { volatile register u32 Reg __asm(XREG_CP15_SYS_CONTROL);
722           CtrlReg = Reg; }
723 #endif
724         if ((CtrlReg & (XREG_CP15_CONTROL_C_BIT)) != 0U) {
725                 return;
726         }
727
728         /* clean and invalidate the Data cache */
729         Xil_L1DCacheInvalidate();
730
731         /* enable the Data cache */
732         CtrlReg |= (XREG_CP15_CONTROL_C_BIT);
733
734         mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
735 }
736
737 /***************************************************************************/
738 /**
739 * @brief        Disable the level 1 Data cache.
740 *
741 * @param        None.
742 *
743 * @return       None.
744 *
745 * @note         None.
746 *
747 ****************************************************************************/
748 void Xil_L1DCacheDisable(void)
749 {
750         register u32 CtrlReg;
751
752         /* clean and invalidate the Data cache */
753         Xil_L1DCacheFlush();
754
755 #ifdef __GNUC__
756         /* disable the Data cache */
757         CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
758 #elif defined (__ICCARM__)
759         mfcp(XREG_CP15_SYS_CONTROL, CtrlReg);
760 #else
761         { volatile register u32 Reg __asm(XREG_CP15_SYS_CONTROL);
762           CtrlReg = Reg; }
763 #endif
764
765         CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT);
766
767         mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
768 }
769
770 /****************************************************************************/
771 /**
772 * @brief        Invalidate the level 1 Data cache.
773 *
774 * @param        None.
775 *
776 * @return       None.
777 *
778 * @note         In Cortex A9, there is no cp instruction for invalidating
779 *                       the whole D-cache. This function invalidates each line by
780 *                       set/way.
781 *
782 ****************************************************************************/
783 void Xil_L1DCacheInvalidate(void)
784 {
785         register u32 CsidReg, C7Reg;
786         u32 CacheSize, LineSize, NumWays;
787         u32 Way, WayIndex, Set, SetIndex, NumSet;
788         u32 currmask;
789
790 #ifdef __GNUC__
791         u32 stack_start,stack_end,stack_size;
792         register u32 CtrlReg;
793 #endif
794
795         currmask = mfcpsr();
796         mtcpsr(currmask | IRQ_FIQ_MASK);
797
798 #ifdef __GNUC__
799         stack_end = (u32)&_stack_end;
800         stack_start = (u32)&__undef_stack;
801         stack_size=stack_start-stack_end;
802
803         /* Check for the cache status. If cache is enabled, then only
804          * flush stack memory to save return address. If cache is disabled,
805          * dont flush anything as it might result in flushing stale date into
806          * memory which is undesirable.
807          * */
808         CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
809         if ((CtrlReg & (XREG_CP15_CONTROL_C_BIT)) != 0U) {
810                 Xil_DCacheFlushRange(stack_end, stack_size);
811         }
812 #endif
813
814         /* Select cache level 0 and D cache in CSSR */
815         mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U);
816
817 #ifdef __GNUC__
818         CsidReg = mfcp(XREG_CP15_CACHE_SIZE_ID);
819 #elif defined (__ICCARM__)
820         mfcp(XREG_CP15_CACHE_SIZE_ID, CsidReg);
821 #else
822         { volatile register u32 Reg __asm(XREG_CP15_CACHE_SIZE_ID);
823           CsidReg = Reg; }
824 #endif
825         /* Determine Cache Size */
826         CacheSize = (CsidReg >> 13U) & 0x1FFU;
827         CacheSize +=1U;
828         CacheSize *=128U;    /* to get number of bytes */
829
830         /* Number of Ways */
831         NumWays = (CsidReg & 0x3ffU) >> 3U;
832         NumWays += 1U;
833
834         /* Get the cacheline size, way size, index size from csidr */
835         LineSize = (CsidReg & 0x07U) + 4U;
836
837         NumSet = CacheSize/NumWays;
838         NumSet /= (0x00000001U << LineSize);
839
840         Way = 0U;
841         Set = 0U;
842
843         /* Invalidate all the cachelines */
844         for (WayIndex =0U; WayIndex < NumWays; WayIndex++) {
845                 for (SetIndex =0U; SetIndex < NumSet; SetIndex++) {
846                         C7Reg = Way | Set;
847
848                 /* Invalidate by Set/Way */
849 #if defined (__GNUC__) || defined (__ICCARM__)
850                         asm_cp15_inval_dc_line_sw(C7Reg);
851 #else
852                         /*mtcp(XREG_CP15_INVAL_DC_LINE_SW, C7Reg), */
853                         { volatile register u32 Reg
854                                 __asm(XREG_CP15_INVAL_DC_LINE_SW);
855                           Reg = C7Reg; }
856 #endif
857                         Set += (0x00000001U << LineSize);
858                 }
859                 Set=0U;
860                 Way += 0x40000000U;
861         }
862
863         /* Wait for L1 invalidate to complete */
864         dsb();
865         mtcpsr(currmask);
866 }
867
868 /****************************************************************************/
869 /**
870 * @brief        Invalidate a level 1 Data cache line. If the byte specified by the
871 *                       address (Addr) is cached by the Data cache, the cacheline
872 *                       containing that byte is invalidated. If the cacheline is modified
873 *                       (dirty), the modified contents are lost and are NOT written to
874 *                       system memory before the line is invalidated.
875 *
876 * @param        adr: 32bit address of the data to be invalidated.
877 *
878 * @return       None.
879 *
880 * @note         The bottom 5 bits are set to 0, forced by architecture.
881 *
882 ****************************************************************************/
883 void Xil_L1DCacheInvalidateLine(u32 adr)
884 {
885         mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U);
886         mtcp(XREG_CP15_INVAL_DC_LINE_MVA_POC, (adr & (~0x1FU)));
887
888         /* Wait for L1 invalidate to complete */
889         dsb();
890 }
891
892 /****************************************************************************/
893 /**
894 * @brief        Invalidate the level 1 Data cache for the given address range.
895 *                       If the bytes specified by the address range are cached by the Data
896 *                       cache, the cachelines containing those bytes are invalidated. If the
897 *                       cachelines are modified (dirty), the modified contents are lost and
898 *                       NOT written to the system memory before the lines are invalidated.
899 *
900 * @param        adr: 32bit start address of the range to be invalidated.
901 * @param        len: Length of the range to be invalidated in bytes.
902 *
903 * @return       None.
904 *
905 * @note         None.
906 *
907 ****************************************************************************/
908 void Xil_L1DCacheInvalidateRange(u32 adr, u32 len)
909 {
910         u32 LocalAddr = adr;
911         const u32 cacheline = 32U;
912         u32 end;
913         u32 currmask;
914
915         currmask = mfcpsr();
916         mtcpsr(currmask | IRQ_FIQ_MASK);
917
918         if (len != 0U) {
919                 /* Back the starting address up to the start of a cache line
920                  * perform cache operations until adr+len
921                  */
922                 end = LocalAddr + len;
923                 LocalAddr = LocalAddr & ~(cacheline - 1U);
924
925                 /* Select cache L0 D-cache in CSSR */
926                 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
927
928                 while (LocalAddr < end) {
929
930 #if defined (__GNUC__) || defined (__ICCARM__)
931                         asm_cp15_inval_dc_line_mva_poc(LocalAddr);
932 #else
933                         { volatile register u32 Reg
934                                 __asm(XREG_CP15_INVAL_DC_LINE_MVA_POC);
935                           Reg = LocalAddr; }
936 #endif
937                         LocalAddr += cacheline;
938                 }
939         }
940
941         /* Wait for L1 invalidate to complete */
942         dsb();
943         mtcpsr(currmask);
944 }
945
946 /****************************************************************************/
947 /**
948 * @brief        Flush the level 1 Data cache.
949 *
950 * @param        None.
951 *
952 * @return       None.
953 *
954 * @note         In Cortex A9, there is no cp instruction for flushing
955 *                       the whole D-cache. Need to flush each line.
956 *
957 ****************************************************************************/
958 void Xil_L1DCacheFlush(void)
959 {
960         register u32 CsidReg, C7Reg;
961         u32 CacheSize, LineSize, NumWays;
962         u32 Way;
963         u32 WayIndex, Set, SetIndex, NumSet;
964         u32 currmask;
965
966         currmask = mfcpsr();
967         mtcpsr(currmask | IRQ_FIQ_MASK);
968
969         /* Select cache level 0 and D cache in CSSR */
970         mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
971
972 #ifdef __GNUC__
973         CsidReg = mfcp(XREG_CP15_CACHE_SIZE_ID);
974 #elif defined (__ICCARM__)
975         mfcp(XREG_CP15_CACHE_SIZE_ID, CsidReg);
976 #else
977         { volatile register u32 Reg __asm(XREG_CP15_CACHE_SIZE_ID);
978           CsidReg = Reg; }
979 #endif
980
981         /* Determine Cache Size */
982
983         CacheSize = (CsidReg >> 13U) & 0x1FFU;
984         CacheSize +=1U;
985         CacheSize *=128U;    /* to get number of bytes */
986
987         /* Number of Ways */
988         NumWays = (CsidReg & 0x3ffU) >> 3U;
989         NumWays += 1U;
990
991         /* Get the cacheline size, way size, index size from csidr */
992         LineSize = (CsidReg & 0x07U) + 4U;
993
994         NumSet = CacheSize/NumWays;
995         NumSet /= (0x00000001U << LineSize);
996
997         Way = 0U;
998         Set = 0U;
999
1000         /* Invalidate all the cachelines */
1001         for (WayIndex =0U; WayIndex < NumWays; WayIndex++) {
1002                 for (SetIndex =0U; SetIndex < NumSet; SetIndex++) {
1003                         C7Reg = Way | Set;
1004                         /* Flush by Set/Way */
1005
1006 #if defined (__GNUC__) || defined (__ICCARM__)
1007                         asm_cp15_clean_inval_dc_line_sw(C7Reg);
1008 #else
1009                         { volatile register u32 Reg
1010                                 __asm(XREG_CP15_CLEAN_INVAL_DC_LINE_SW);
1011                           Reg = C7Reg; }
1012 #endif
1013                         Set += (0x00000001U << LineSize);
1014                 }
1015                 Set = 0U;
1016                 Way += 0x40000000U;
1017         }
1018
1019         /* Wait for L1 flush to complete */
1020         dsb();
1021         mtcpsr(currmask);
1022 }
1023
1024 /****************************************************************************/
1025 /**
1026 * @brief        Flush a level 1 Data cache line. If the byte specified by the
1027 *                       address (adr) is cached by the Data cache, the cacheline containing
1028 *                       that byte is invalidated. If the cacheline is modified (dirty), the
1029 *                       entire contents of the cacheline are written to system memory
1030 *                       before the line is invalidated.
1031 *
1032 * @param        adr: 32bit address of the data to be flushed.
1033 *
1034 * @return       None.
1035 *
1036 * @note         The bottom 5 bits are set to 0, forced by architecture.
1037 *
1038 ****************************************************************************/
1039 void Xil_L1DCacheFlushLine(u32 adr)
1040 {
1041         mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U);
1042         mtcp(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC, (adr & (~0x1FU)));
1043
1044         /* Wait for L1 flush to complete */
1045         dsb();
1046 }
1047
1048 /****************************************************************************/
1049 /**
1050 * @brief        Flush the level 1  Data cache for the given address range.
1051 *                       If the bytes specified by the address range are cached by the Data
1052 *                       cache, the cacheline containing those bytes are invalidated. If the
1053 *                       cachelines are modified (dirty), they are written to system memory
1054 *                       before the lines are invalidated.
1055 *
1056 * @param        adr: 32bit start address of the range to be flushed.
1057 * @param        len: Length of the range to be flushed in bytes.
1058 *
1059 * @return       None.
1060 *
1061 * @note         None.
1062 *
1063 ****************************************************************************/
1064 void Xil_L1DCacheFlushRange(u32 adr, u32 len)
1065 {
1066         u32 LocalAddr = adr;
1067         const u32 cacheline = 32U;
1068         u32 end;
1069         u32 currmask;
1070
1071         currmask = mfcpsr();
1072         mtcpsr(currmask | IRQ_FIQ_MASK);
1073
1074         if (len != 0U) {
1075                 /* Back the starting address up to the start of a cache line
1076                  * perform cache operations until adr+len
1077                  */
1078                 end = LocalAddr + len;
1079                 LocalAddr = LocalAddr & ~(cacheline - 1U);
1080
1081                 /* Select cache L0 D-cache in CSSR */
1082                 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U);
1083
1084                 while (LocalAddr < end) {
1085
1086 #if defined (__GNUC__) || defined (__ICCARM__)
1087                         asm_cp15_clean_inval_dc_line_mva_poc(LocalAddr);
1088 #else
1089                         { volatile register u32 Reg
1090                                 __asm(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC);
1091                           Reg = LocalAddr; }
1092 #endif
1093                         LocalAddr += cacheline;
1094                 }
1095         }
1096
1097         /* Wait for L1 flush to complete */
1098         dsb();
1099         mtcpsr(currmask);
1100 }
1101
1102 /****************************************************************************/
1103 /**
1104 * @brief        Store a level 1  Data cache line. If the byte specified by the
1105 *                       address (adr) is cached by the Data cache and the cacheline is
1106 *                       modified (dirty), the entire contents of the cacheline are written
1107 *                       to system memory. After the store completes, the cacheline is
1108 *                       marked as unmodified (not dirty).
1109 *
1110 * @param        Address to be stored.
1111 *
1112 * @return       None.
1113 *
1114 * @note         The bottom 5 bits are set to 0, forced by architecture.
1115 *
1116 ****************************************************************************/
1117 void Xil_L1DCacheStoreLine(u32 adr)
1118 {
1119         mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U);
1120         mtcp(XREG_CP15_CLEAN_DC_LINE_MVA_POC, (adr & (~0x1FU)));
1121
1122         /* Wait for L1 store to complete */
1123         dsb();
1124 }
1125
1126
1127 /****************************************************************************/
1128 /**
1129 * @brief        Enable the level 1 instruction cache.
1130 *
1131 * @param        None.
1132 *
1133 * @return       None.
1134 *
1135 * @note         None.
1136 *
1137 ****************************************************************************/
1138 void Xil_L1ICacheEnable(void)
1139 {
1140         register u32 CtrlReg;
1141
1142         /* enable caches only if they are disabled */
1143 #ifdef __GNUC__
1144         CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
1145 #elif defined (__ICCARM__)
1146         mfcp(XREG_CP15_SYS_CONTROL, CtrlReg);
1147 #else
1148         { volatile register u32 Reg __asm(XREG_CP15_SYS_CONTROL);
1149           CtrlReg = Reg; }
1150 #endif
1151         if ((CtrlReg & (XREG_CP15_CONTROL_I_BIT)) != 0U) {
1152                 return;
1153         }
1154
1155         /* invalidate the instruction cache */
1156         mtcp(XREG_CP15_INVAL_IC_POU, 0U);
1157
1158         /* enable the instruction cache */
1159         CtrlReg |= (XREG_CP15_CONTROL_I_BIT);
1160
1161         mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
1162 }
1163
1164 /****************************************************************************/
1165 /**
1166 * @brief        Disable level 1 the instruction cache.
1167 *
1168 * @param        None.
1169 *
1170 * @return       None.
1171 *
1172 * @note         None.
1173 *
1174 ****************************************************************************/
1175 void Xil_L1ICacheDisable(void)
1176 {
1177         register u32 CtrlReg;
1178
1179         dsb();
1180
1181         /* invalidate the instruction cache */
1182         mtcp(XREG_CP15_INVAL_IC_POU, 0U);
1183
1184         /* disable the instruction cache */
1185 #ifdef __GNUC__
1186         CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
1187 #elif defined (__ICCARM__)
1188         mfcp(XREG_CP15_SYS_CONTROL, CtrlReg);
1189 #else
1190         { volatile register u32 Reg __asm(XREG_CP15_SYS_CONTROL);
1191           CtrlReg = Reg; }
1192 #endif
1193         CtrlReg &= ~(XREG_CP15_CONTROL_I_BIT);
1194
1195         mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
1196 }
1197
1198 /****************************************************************************/
1199 /**
1200 * @brief        Invalidate the entire level 1 instruction cache.
1201 *
1202 * @param        None.
1203 *
1204 * @return       None.
1205 *
1206 * @note         None.
1207 *
1208 ****************************************************************************/
1209 void Xil_L1ICacheInvalidate(void)
1210 {
1211         mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U);
1212         /* invalidate the instruction cache */
1213         mtcp(XREG_CP15_INVAL_IC_POU, 0U);
1214
1215         /* Wait for L1 invalidate to complete */
1216         dsb();
1217 }
1218
1219 /****************************************************************************/
1220 /**
1221 * @brief        Invalidate a level 1  instruction cache line. If the instruction
1222 *                       specified by the address is cached by the instruction cache, the
1223 *                       cacheline containing that instruction is invalidated.
1224 *
1225 * @param        adr: 32bit address of the instruction to be invalidated.
1226 *
1227 * @return       None.
1228 *
1229 * @note         The bottom 5 bits are set to 0, forced by architecture.
1230 *
1231 ****************************************************************************/
1232 void Xil_L1ICacheInvalidateLine(u32 adr)
1233 {
1234         mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U);
1235         mtcp(XREG_CP15_INVAL_IC_LINE_MVA_POU, (adr & (~0x1FU)));
1236
1237         /* Wait for L1 invalidate to complete */
1238         dsb();
1239 }
1240
1241 /****************************************************************************/
1242 /**
1243 * @brief        Invalidate the level 1 instruction cache for the given address
1244 *                       range. If the instrucions specified by the address range are cached
1245 *                       by the instruction cache, the cacheline containing those bytes are
1246 *                       invalidated.
1247 *
1248 * @param        adr: 32bit start address of the range to be invalidated.
1249 * @param        len: Length of the range to be invalidated in bytes.
1250 *
1251 * @return       None.
1252 *
1253 * @note         None.
1254 *
1255 ****************************************************************************/
1256 void Xil_L1ICacheInvalidateRange(u32 adr, u32 len)
1257 {
1258         u32 LocalAddr = adr;
1259         const u32 cacheline = 32U;
1260         u32 end;
1261         u32 currmask;
1262
1263         currmask = mfcpsr();
1264         mtcpsr(currmask | IRQ_FIQ_MASK);
1265
1266         if (len != 0U) {
1267                 /* Back the starting address up to the start of a cache line
1268                  * perform cache operations until adr+len
1269                  */
1270                 end = LocalAddr + len;
1271                 LocalAddr = LocalAddr & ~(cacheline - 1U);
1272
1273                 /* Select cache L0 I-cache in CSSR */
1274                 mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U);
1275
1276                 while (LocalAddr < end) {
1277
1278 #if defined (__GNUC__) || defined (__ICCARM__)
1279                         asm_cp15_inval_ic_line_mva_pou(LocalAddr);
1280 #else
1281                         { volatile register u32 Reg
1282                                 __asm(XREG_CP15_INVAL_IC_LINE_MVA_POU);
1283                           Reg = LocalAddr; }
1284 #endif
1285                         LocalAddr += cacheline;
1286                 }
1287         }
1288
1289         /* Wait for L1 invalidate to complete */
1290         dsb();
1291         mtcpsr(currmask);
1292 }
1293
1294 #ifndef USE_AMP
1295 /****************************************************************************/
1296 /**
1297 * @brief        Enable the L2 cache.
1298 *
1299 * @param        None.
1300 *
1301 * @return       None.
1302 *
1303 * @note         None.
1304 *
1305 ****************************************************************************/
1306 void Xil_L2CacheEnable(void)
1307 {
1308         register u32 L2CCReg;
1309
1310         L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET);
1311
1312         /* only enable if L2CC is currently disabled */
1313         if ((L2CCReg & 0x01U) == 0U) {
1314                 /* set up the way size and latencies */
1315                 L2CCReg = Xil_In32(XPS_L2CC_BASEADDR +
1316                                    XPS_L2CC_AUX_CNTRL_OFFSET);
1317                 L2CCReg &= XPS_L2CC_AUX_REG_ZERO_MASK;
1318                 L2CCReg |= XPS_L2CC_AUX_REG_DEFAULT_MASK;
1319                 Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_AUX_CNTRL_OFFSET,
1320                           L2CCReg);
1321                 Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_TAG_RAM_CNTRL_OFFSET,
1322                           XPS_L2CC_TAG_RAM_DEFAULT_MASK);
1323                 Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_DATA_RAM_CNTRL_OFFSET,
1324                           XPS_L2CC_DATA_RAM_DEFAULT_MASK);
1325
1326                 /* Clear the pending interrupts */
1327                 L2CCReg = Xil_In32(XPS_L2CC_BASEADDR +
1328                                    XPS_L2CC_ISR_OFFSET);
1329                 Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_IAR_OFFSET, L2CCReg);
1330
1331                 Xil_L2CacheInvalidate();
1332                 /* Enable the L2CC */
1333                 L2CCReg = Xil_In32(XPS_L2CC_BASEADDR +
1334                                    XPS_L2CC_CNTRL_OFFSET);
1335                 Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET,
1336                           (L2CCReg | (0x01U)));
1337
1338         Xil_L2CacheSync();
1339         /* synchronize the processor */
1340             dsb();
1341
1342     }
1343 }
1344
1345 /****************************************************************************/
1346 /**
1347 * @brief        Disable the L2 cache.
1348 *
1349 * @param        None.
1350 *
1351 * @return       None.
1352 *
1353 * @note         None.
1354 *
1355 ****************************************************************************/
1356 void Xil_L2CacheDisable(void)
1357 {
1358     register u32 L2CCReg;
1359
1360         L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET);
1361
1362     if((L2CCReg & 0x1U) != 0U) {
1363
1364         /* Clean and Invalidate L2 Cache */
1365         Xil_L2CacheFlush();
1366
1367             /* Disable the L2CC */
1368         L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET);
1369             Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET,
1370                       (L2CCReg & (~0x01U)));
1371                 /* Wait for the cache operations to complete */
1372
1373                 dsb();
1374     }
1375 }
1376
1377 /*****************************************************************************/
1378 /**
1379 * @brief        Invalidate the entire level 2 cache.
1380 *
1381 * @param        None.
1382 *
1383 * @return       None.
1384 *
1385 * @note         None.
1386 *
1387 ****************************************************************************/
1388 void Xil_L2CacheInvalidate(void)
1389 {
1390         #ifdef __GNUC__
1391         u32 stack_start,stack_end,stack_size;
1392         register u32 L2CCReg;
1393         stack_end = (u32)&_stack_end;
1394         stack_start = (u32)&__undef_stack;
1395         stack_size=stack_start-stack_end;
1396
1397         /* Check for the cache status. If cache is enabled, then only
1398          * flush stack memory to save return address. If cache is disabled,
1399      * dont flush anything as it might result in flushing stale date into
1400          * memory which is undesirable.
1401          */
1402         L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET);
1403         if ((L2CCReg & 0x01U) != 0U) {
1404         /*Flush stack memory to save return address*/
1405                 Xil_DCacheFlushRange(stack_end, stack_size);
1406         }
1407
1408         #endif
1409         u32 ResultDCache;
1410         /* Invalidate the caches */
1411         Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_WAY_OFFSET,
1412                   0x0000FFFFU);
1413         ResultDCache = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_WAY_OFFSET)
1414                                                         & 0x0000FFFFU;
1415         while(ResultDCache != (u32)0U) {
1416                 ResultDCache = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_WAY_OFFSET)
1417                                                         & 0x0000FFFFU;
1418         }
1419
1420         /* Wait for the invalidate to complete */
1421         Xil_L2CacheSync();
1422
1423         /* synchronize the processor */
1424         dsb();
1425 }
1426
1427 /*****************************************************************************/
1428 /**
1429 * @brief        Invalidate a level 2 cache line. If the byte specified by the
1430 *                       address (adr) is cached by the Data cache, the cacheline containing
1431 *                       that byte is invalidated. If the cacheline is modified (dirty),
1432 *                       the modified contents are lost and are NOT written to system memory
1433 *                       before the line is invalidated.
1434 *
1435 * @param        adr: 32bit address of the data/instruction to be invalidated.
1436 *
1437 * @return       None.
1438 *
1439 * @note         The bottom 4 bits are set to 0, forced by architecture.
1440 *
1441 ****************************************************************************/
1442 void Xil_L2CacheInvalidateLine(u32 adr)
1443 {
1444         Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_PA_OFFSET, (u32)adr);
1445         /* synchronize the processor */
1446         dsb();
1447 }
1448
1449 /****************************************************************************/
1450 /**
1451 * @brief        Invalidate the level 2 cache for the given address range.
1452 *                       If the bytes specified by the address range are cached by the L2
1453 *                       cache, the cacheline containing those bytes are invalidated. If the
1454 *                       cachelines are modified (dirty), the modified contents are lost and
1455 *                       are NOT written to system memory before the lines are invalidated.
1456 *
1457 * @param        adr: 32bit start address of the range to be invalidated.
1458 * @param        len: Length of the range to be invalidated in bytes.
1459 *
1460 * @return       None.
1461 *
1462 * @note         None.
1463 *
1464 ****************************************************************************/
1465 void Xil_L2CacheInvalidateRange(u32 adr, u32 len)
1466 {
1467         u32 LocalAddr = adr;
1468         const u32 cacheline = 32U;
1469         u32 end;
1470         volatile u32 *L2CCOffset = (volatile u32 *)(XPS_L2CC_BASEADDR +
1471                                     XPS_L2CC_CACHE_INVLD_PA_OFFSET);
1472
1473         u32 currmask;
1474
1475         currmask = mfcpsr();
1476         mtcpsr(currmask | IRQ_FIQ_MASK);
1477
1478         if (len != 0U) {
1479                 /* Back the starting address up to the start of a cache line
1480                  * perform cache operations until adr+len
1481                  */
1482                 end = LocalAddr + len;
1483                 LocalAddr = LocalAddr & ~(cacheline - 1U);
1484
1485                 /* Disable Write-back and line fills */
1486                 Xil_L2WriteDebugCtrl(0x3U);
1487
1488                 while (LocalAddr < end) {
1489                         *L2CCOffset = LocalAddr;
1490                         Xil_L2CacheSync();
1491                         LocalAddr += cacheline;
1492                 }
1493
1494                 /* Enable Write-back and line fills */
1495                 Xil_L2WriteDebugCtrl(0x0U);
1496         }
1497
1498         /* synchronize the processor */
1499         dsb();
1500         mtcpsr(currmask);
1501 }
1502
1503 /****************************************************************************/
1504 /**
1505 * @brief        Flush the entire level 2 cache.
1506 *
1507 * @param        None.
1508 *
1509 * @return       None.
1510 *
1511 * @note         None.
1512 *
1513 ****************************************************************************/
1514 void Xil_L2CacheFlush(void)
1515 {
1516         u32 ResultL2Cache;
1517
1518         /* Flush the caches */
1519
1520         /* Disable Write-back and line fills */
1521         Xil_L2WriteDebugCtrl(0x3U);
1522
1523         Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INV_CLN_WAY_OFFSET,
1524                   0x0000FFFFU);
1525         ResultL2Cache = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INV_CLN_WAY_OFFSET)
1526                                                         & 0x0000FFFFU;
1527
1528         while(ResultL2Cache != (u32)0U) {
1529                 ResultL2Cache = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INV_CLN_WAY_OFFSET)
1530                                                                         & 0x0000FFFFU;
1531         }
1532
1533         Xil_L2CacheSync();
1534         /* Enable Write-back and line fills */
1535         Xil_L2WriteDebugCtrl(0x0U);
1536
1537         /* synchronize the processor */
1538         dsb();
1539 }
1540
1541 /****************************************************************************/
1542 /**
1543 * @brief        Flush a level 2 cache line. If the byte specified by the address
1544 *                       (adr) is cached by the L2 cache, the cacheline containing that
1545 *                       byte is invalidated. If the cacheline is modified (dirty), the
1546 *                       entire contents of the cacheline are written to system memory
1547 *                       before the line is invalidated.
1548 *
1549 * @param        adr: 32bit address of the data/instruction to be flushed.
1550 *
1551 * @return       None.
1552 *
1553 * @note         The bottom 4 bits are set to 0, forced by architecture.
1554 *
1555 ****************************************************************************/
1556 void Xil_L2CacheFlushLine(u32 adr)
1557 {
1558 #ifdef CONFIG_PL310_ERRATA_588369
1559         Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_CLEAN_PA_OFFSET, adr);
1560         Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_PA_OFFSET, adr);
1561 #else
1562         Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INV_CLN_PA_OFFSET, adr);
1563 #endif
1564         /* synchronize the processor */
1565         dsb();
1566 }
1567
1568 /****************************************************************************/
1569 /**
1570 * @brief        Flush the level 2 cache for the given address range.
1571 *                       If the bytes specified by the address range are cached by the L2
1572 *                       cache, the cacheline containing those bytes are invalidated. If the
1573 *                       cachelines are modified (dirty), they are written to the system
1574 *                       memory before the lines are invalidated.
1575 *
1576 * @param        adr: 32bit start address of the range to be flushed.
1577 * @param        len: Length of the range to be flushed in bytes.
1578 *
1579 * @return       None.
1580 *
1581 * @note         None.
1582 *
1583 ****************************************************************************/
1584 void Xil_L2CacheFlushRange(u32 adr, u32 len)
1585 {
1586         u32 LocalAddr = adr;
1587         const u32 cacheline = 32U;
1588         u32 end;
1589         volatile u32 *L2CCOffset = (volatile u32 *)(XPS_L2CC_BASEADDR +
1590                                     XPS_L2CC_CACHE_INV_CLN_PA_OFFSET);
1591
1592         u32 currmask;
1593
1594         currmask = mfcpsr();
1595         mtcpsr(currmask | IRQ_FIQ_MASK);
1596         if (len != 0U) {
1597                 /* Back the starting address up to the start of a cache line
1598                  * perform cache operations until adr+len
1599                  */
1600                 end = LocalAddr + len;
1601                 LocalAddr = LocalAddr & ~(cacheline - 1U);
1602
1603                 /* Disable Write-back and line fills */
1604                 Xil_L2WriteDebugCtrl(0x3U);
1605
1606                 while (LocalAddr < end) {
1607                         *L2CCOffset = LocalAddr;
1608                         Xil_L2CacheSync();
1609                         LocalAddr += cacheline;
1610                 }
1611
1612                 /* Enable Write-back and line fills */
1613                 Xil_L2WriteDebugCtrl(0x0U);
1614         }
1615         /* synchronize the processor */
1616         dsb();
1617         mtcpsr(currmask);
1618 }
1619
1620 /****************************************************************************/
1621 /**
1622 * @brief        Store a level 2 cache line. If the byte specified by the address
1623 *                       (adr) is cached by the L2 cache and the cacheline is modified
1624 *                       (dirty), the entire contents of the cacheline are written to
1625 *                       system memory. After the store completes, the cacheline is marked
1626 *                       as unmodified (not dirty).
1627 *
1628 * @param        adr: 32bit address of the data/instruction to be stored.
1629 *
1630 * @return       None.
1631 *
1632 * @note         The bottom 4 bits are set to 0, forced by architecture.
1633 *
1634 ****************************************************************************/
1635 void Xil_L2CacheStoreLine(u32 adr)
1636 {
1637         Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_CLEAN_PA_OFFSET, adr);
1638         /* synchronize the processor */
1639         dsb();
1640 }
1641 #endif