]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_R5_UltraScale_MPSoC/RTOSDemo_R5_bsp/psu_cortexr5_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_R5_UltraScale_MPSoC / RTOSDemo_R5_bsp / psu_cortexr5_0 / libsrc / standalone_v6_6 / src / xil_cache.c
1 /******************************************************************************
2 *
3 * Copyright (C) 2014 - 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 * 5.00  pkp  02/20/14 First release
45 * 6.2   mus  01/27/17 Updated to support IAR compiler
46 * </pre>
47 *
48 ******************************************************************************/
49
50 /***************************** Include Files *********************************/
51
52 #include "xil_cache.h"
53 #include "xil_io.h"
54 #include "xpseudo_asm.h"
55 #include "xparameters.h"
56 #include "xreg_cortexr5.h"
57 #include "xil_exception.h"
58
59
60 /************************** Variable Definitions *****************************/
61
62 #define IRQ_FIQ_MASK 0xC0       /* Mask IRQ and FIQ interrupts in cpsr */
63
64 #if defined (__GNUC__)
65 extern s32  _stack_end;
66 extern s32  __undef_stack;
67 #endif
68 /****************************************************************************/
69 /************************** Function Prototypes ******************************/
70
71 /****************************************************************************/
72 /**
73 * @brief    Enable the Data cache.
74 *
75 * @param        None.
76 *
77 * @return       None.
78 *
79 * @note         None.
80 *
81 ****************************************************************************/
82 void Xil_DCacheEnable(void)
83 {
84         register u32 CtrlReg;
85
86         /* enable caches only if they are disabled */
87 #if defined (__GNUC__)
88         CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
89 #elif defined (__ICCARM__)
90          mfcp(XREG_CP15_SYS_CONTROL,CtrlReg);
91 #endif
92         if ((CtrlReg & XREG_CP15_CONTROL_C_BIT)==0x00000000U) {
93                 /* invalidate the Data cache */
94                 Xil_DCacheInvalidate();
95
96                 /* enable the Data cache */
97                 CtrlReg |= (XREG_CP15_CONTROL_C_BIT);
98
99                 mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
100         }
101 }
102
103 /****************************************************************************/
104 /**
105 * @brief    Disable the Data cache.
106 *
107 * @param        None.
108 *
109 * @return       None.
110 *
111 * @note         None.
112 *
113 ****************************************************************************/
114 void Xil_DCacheDisable(void)
115 {
116         register u32 CtrlReg;
117
118         /* clean and invalidate the Data cache */
119         Xil_DCacheFlush();
120
121         /* disable the Data cache */
122 #if defined (__GNUC__)
123         CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
124 #elif defined (__ICCARM__)
125          mfcp(XREG_CP15_SYS_CONTROL,CtrlReg);
126 #endif
127
128         CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT);
129
130         mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
131 }
132
133 /****************************************************************************/
134 /**
135 * @brief    Invalidate the entire Data cache.
136 *
137 * @param        None.
138 *
139 * @return       None.
140 *
141 ****************************************************************************/
142 void Xil_DCacheInvalidate(void)
143 {
144         u32 currmask;
145         u32 stack_start,stack_end,stack_size;
146
147         currmask = mfcpsr();
148         mtcpsr(currmask | IRQ_FIQ_MASK);
149
150 #if defined (__GNUC__)
151         stack_end = (u32 )&_stack_end;
152         stack_start = (u32 )&__undef_stack;
153         stack_size = stack_start-stack_end;
154
155         /* Flush stack memory to save return address */
156         Xil_DCacheFlushRange(stack_end, stack_size);
157 #endif
158         mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
159
160         /*invalidate all D cache*/
161         mtcp(XREG_CP15_INVAL_DC_ALL, 0);
162
163         mtcpsr(currmask);
164 }
165
166 /****************************************************************************/
167 /**
168 * @brief    Invalidate a Data cache line. If the byte specified by the
169 *           address (adr) is cached by the data cache, the cacheline
170 *           containing that byte is invalidated.If the cacheline is modified
171 *               (dirty), the modified contents are lost and are NOT written
172 *           to system memory before the line is invalidated.
173 *
174 *
175 * @param        adr: 32bit address of the data to be flushed.
176 *
177 * @return       None.
178 *
179 * @note         The bottom 4 bits are set to 0, forced by architecture.
180 *
181 ****************************************************************************/
182 void Xil_DCacheInvalidateLine(INTPTR adr)
183 {
184         u32 currmask;
185
186         currmask = mfcpsr();
187         mtcpsr(currmask | IRQ_FIQ_MASK);
188
189         mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
190         mtcp(XREG_CP15_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F)));
191
192                 /* Wait for invalidate to complete */
193         dsb();
194
195         mtcpsr(currmask);
196 }
197
198 /****************************************************************************/
199 /**
200 * @brief    Invalidate the Data cache for the given address range.
201 *           If the bytes specified by the address (adr) are cached by the
202 *           Data cache,the cacheline containing that byte is invalidated.
203 *           If the cacheline is modified (dirty), the modified contents are
204 *           lost and are NOT written to system memory before the line is
205 *           invalidated.
206 *
207 * @param        adr: 32bit start address of the range to be invalidated.
208 * @param        len: Length of range to be invalidated in bytes.
209 *
210 * @return       None.
211 *
212 ****************************************************************************/
213 void Xil_DCacheInvalidateRange(INTPTR adr, u32 len)
214 {
215         const u32 cacheline = 32U;
216         u32 end;
217         u32 tempadr = adr;
218         u32 tempend;
219         u32 currmask;
220
221         currmask = mfcpsr();
222         mtcpsr(currmask | IRQ_FIQ_MASK);
223
224         if (len != 0U) {
225                 end = tempadr + len;
226                 tempend = end;
227                 /* Select L1 Data cache in CSSR */
228                 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U);
229
230                 if ((tempadr & (cacheline-1U)) != 0U) {
231                         tempadr &= (~(cacheline - 1U));
232
233                         Xil_DCacheFlushLine(tempadr);
234                 }
235                 if ((tempend & (cacheline-1U)) != 0U) {
236                         tempend &= (~(cacheline - 1U));
237
238                         Xil_DCacheFlushLine(tempend);
239                 }
240
241                 while (tempadr < tempend) {
242
243                 /* Invalidate Data cache line */
244                 asm_inval_dc_line_mva_poc(tempadr);
245
246                 tempadr += cacheline;
247                 }
248         }
249
250         dsb();
251         mtcpsr(currmask);
252 }
253
254 /****************************************************************************/
255 /**
256 * @brief    Flush the entire Data cache.
257 *
258 * @param        None.
259 *
260 * @return       None.
261 *
262 ****************************************************************************/
263 void Xil_DCacheFlush(void)
264 {
265         register u32 CsidReg, C7Reg;
266         u32 CacheSize, LineSize, NumWays;
267         u32 Way, WayIndex, Set, SetIndex, NumSet;
268         u32 currmask;
269
270         currmask = mfcpsr();
271         mtcpsr(currmask | IRQ_FIQ_MASK);
272
273         /* Select cache level 0 and D cache in CSSR */
274         mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
275
276 #if defined (__GNUC__)
277         CsidReg = mfcp(XREG_CP15_CACHE_SIZE_ID);
278 #elif defined (__ICCARM__)
279          mfcp(XREG_CP15_CACHE_SIZE_ID,CsidReg);
280 #endif
281         /* Determine Cache Size */
282
283         CacheSize = (CsidReg >> 13U) & 0x000001FFU;
284         CacheSize += 0x00000001U;
285         CacheSize *= (u32)128;    /* to get number of bytes */
286
287         /* Number of Ways */
288         NumWays = (CsidReg & 0x000003ffU) >> 3U;
289         NumWays += 0x00000001U;
290
291         /* Get the cacheline size, way size, index size from csidr */
292         LineSize = (CsidReg & 0x00000007U) + 0x00000004U;
293
294         NumSet = CacheSize/NumWays;
295         NumSet /= (0x00000001U << LineSize);
296
297         Way = 0U;
298         Set = 0U;
299
300         /* Invalidate all the cachelines */
301         for (WayIndex = 0U; WayIndex < NumWays; WayIndex++) {
302                 for (SetIndex = 0U; SetIndex < NumSet; SetIndex++) {
303                         C7Reg = Way | Set;
304                         /* Flush by Set/Way */
305                         asm_clean_inval_dc_line_sw(C7Reg);
306
307                         Set += (0x00000001U << LineSize);
308                 }
309                 Set = 0U;
310                 Way += 0x40000000U;
311         }
312
313         /* Wait for flush to complete */
314         dsb();
315         mtcpsr(currmask);
316
317         mtcpsr(currmask);
318 }
319
320 /****************************************************************************/
321 /**
322 * @brief   Flush a Data cache line. If the byte specified by the address (adr)
323 *          is cached by the Data cache, the cacheline containing that byte is
324 *          invalidated. If the cacheline is modified (dirty), the entire
325 *          contents of the cacheline are written to system memory before the
326 *          line is invalidated.
327 *
328 * @param   adr: 32bit address of the data to be flushed.
329 *
330 * @return       None.
331 *
332 * @note         The bottom 4 bits are set to 0, forced by architecture.
333 *
334 ****************************************************************************/
335 void Xil_DCacheFlushLine(INTPTR adr)
336 {
337         u32 currmask;
338
339         currmask = mfcpsr();
340         mtcpsr(currmask | IRQ_FIQ_MASK);
341
342         mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
343
344         mtcp(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F)));
345
346                 /* Wait for flush to complete */
347         dsb();
348         mtcpsr(currmask);
349 }
350
351 /****************************************************************************/
352 /**
353 * @brief    Flush the Data cache for the given address range.
354 *           If the bytes specified by the address (adr) are cached by the
355 *           Data cache, the cacheline containing those bytes is invalidated.If
356 *           the cacheline is modified (dirty), the written to system memory
357 *           before the lines are invalidated.
358 *
359 * @param        adr: 32bit start address of the range to be flushed.
360 * @param        len: Length of the range to be flushed in bytes
361 *
362 * @return       None.
363 *
364 ****************************************************************************/
365 void Xil_DCacheFlushRange(INTPTR adr, u32 len)
366 {
367         u32 LocalAddr = adr;
368         const u32 cacheline = 32U;
369         u32 end;
370         u32 currmask;
371
372         currmask = mfcpsr();
373         mtcpsr(currmask | IRQ_FIQ_MASK);
374
375         if (len != 0x00000000U) {
376                 /* Back the starting address up to the start of a cache line
377                  * perform cache operations until adr+len
378                  */
379                 end = LocalAddr + len;
380                 LocalAddr &= ~(cacheline - 1U);
381
382                 while (LocalAddr < end) {
383                         /* Flush Data cache line */
384                         asm_clean_inval_dc_line_mva_poc(LocalAddr);
385
386                         LocalAddr += cacheline;
387                 }
388         }
389         dsb();
390         mtcpsr(currmask);
391 }
392 /****************************************************************************/
393 /**
394 * @brief    Store a Data cache line. If the byte specified by the address
395 *           (adr) is cached by the Data cache and the cacheline is modified
396 *           (dirty), the entire contents of the cacheline are written to
397 *           system memory.After the store completes, the cacheline is marked
398 *           as unmodified (not dirty).
399 *
400 * @param        adr: 32bit address of the data to be stored
401 *
402 * @return       None.
403 *
404 * @note         The bottom 4 bits are set to 0, forced by architecture.
405 *
406 ****************************************************************************/
407 void Xil_DCacheStoreLine(INTPTR adr)
408 {
409         u32 currmask;
410
411         currmask = mfcpsr();
412         mtcpsr(currmask | IRQ_FIQ_MASK);
413
414         mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
415         mtcp(XREG_CP15_CLEAN_DC_LINE_MVA_POC, (adr & (~0x1F)));
416
417         /* Wait for store to complete */
418         dsb();
419         isb();
420
421         mtcpsr(currmask);
422 }
423
424 /****************************************************************************/
425 /**
426 * @brief    Enable the instruction cache.
427 *
428 * @param        None.
429 *
430 * @return       None.
431 *
432 ****************************************************************************/
433 void Xil_ICacheEnable(void)
434 {
435         register u32 CtrlReg;
436
437         /* enable caches only if they are disabled */
438 #if defined (__GNUC__)
439         CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
440 #elif defined (__ICCARM__)
441         mfcp(XREG_CP15_SYS_CONTROL, CtrlReg);
442 #endif
443         if ((CtrlReg & XREG_CP15_CONTROL_I_BIT)==0x00000000U) {
444                 /* invalidate the instruction cache */
445                 mtcp(XREG_CP15_INVAL_IC_POU, 0);
446
447                 /* enable the instruction cache */
448                 CtrlReg |= (XREG_CP15_CONTROL_I_BIT);
449
450                 mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
451         }
452 }
453
454 /****************************************************************************/
455 /**
456 * @brief    Disable the instruction cache.
457 *
458 * @param        None.
459 *
460 * @return       None.
461 *
462 ****************************************************************************/
463 void Xil_ICacheDisable(void)
464 {
465         register u32 CtrlReg;
466
467         dsb();
468
469         /* invalidate the instruction cache */
470         mtcp(XREG_CP15_INVAL_IC_POU, 0);
471
472                 /* disable the instruction cache */
473 #if defined (__GNUC__)
474         CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
475 #elif defined (__ICCARM__)
476         mfcp(XREG_CP15_SYS_CONTROL,CtrlReg);
477 #endif
478
479         CtrlReg &= ~(XREG_CP15_CONTROL_I_BIT);
480
481         mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
482 }
483
484 /****************************************************************************/
485 /**
486 * @brief    Invalidate the entire instruction cache.
487 *
488 * @param        None.
489 *
490 * @return       None.
491 *
492 ****************************************************************************/
493 void Xil_ICacheInvalidate(void)
494 {
495         u32 currmask;
496
497         currmask = mfcpsr();
498         mtcpsr(currmask | IRQ_FIQ_MASK);
499
500         mtcp(XREG_CP15_CACHE_SIZE_SEL, 1);
501
502         /* invalidate the instruction cache */
503         mtcp(XREG_CP15_INVAL_IC_POU, 0);
504
505         /* Wait for invalidate to complete */
506         dsb();
507         mtcpsr(currmask);
508 }
509
510 /****************************************************************************/
511 /**
512 * @brief    Invalidate an instruction cache line.If the instruction specified
513 *           by the address is cached by the instruction cache, the
514 *           cacheline containing that instruction is invalidated.
515 *
516 * @param        adr: 32bit address of the instruction to be invalidated.
517 *
518 * @return       None.
519 *
520 * @note         The bottom 4 bits are set to 0, forced by architecture.
521 *
522 ****************************************************************************/
523 void Xil_ICacheInvalidateLine(INTPTR adr)
524 {
525         u32 currmask;
526
527         currmask = mfcpsr();
528         mtcpsr(currmask | IRQ_FIQ_MASK);
529
530         mtcp(XREG_CP15_CACHE_SIZE_SEL, 1);
531         mtcp(XREG_CP15_INVAL_IC_LINE_MVA_POU, (adr & (~0x1F)));
532
533                 /* Wait for invalidate to complete */
534         dsb();
535         mtcpsr(currmask);
536 }
537
538 /****************************************************************************/
539 /**
540 * @brief    Invalidate the instruction cache for the given address range.
541 *           If the bytes specified by the address (adr) are cached by the
542 *           Data cache, the cacheline containing that byte is invalidated.
543 *           If the cachelineis modified (dirty), the modified contents are
544 *           lost  and are NOT written to system memory before the line is
545 *           invalidated.
546 *
547 * @param        adr: 32bit start address of the range to be invalidated.
548 * @param        len: Length of the range to be invalidated in bytes.
549 *
550 * @return       None.
551 *
552 ****************************************************************************/
553 void Xil_ICacheInvalidateRange(INTPTR adr, u32 len)
554 {
555         u32 LocalAddr = adr;
556         const u32 cacheline = 32U;
557         u32 end;
558         u32 currmask;
559
560         currmask = mfcpsr();
561         mtcpsr(currmask | IRQ_FIQ_MASK);
562         if (len != 0x00000000U) {
563                 /* Back the starting address up to the start of a cache line
564                  * perform cache operations until adr+len
565                  */
566                 end = LocalAddr + len;
567                 LocalAddr = LocalAddr & ~(cacheline - 1U);
568
569                 /* Select cache L0 I-cache in CSSR */
570                 mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U);
571
572                 while (LocalAddr < end) {
573
574                         /* Invalidate L1 I-cache line */
575                         asm_inval_ic_line_mva_pou(LocalAddr);
576
577                         LocalAddr += cacheline;
578                 }
579         }
580
581         /* Wait for invalidate to complete */
582         dsb();
583         mtcpsr(currmask);
584 }