]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A53_64-bit_UltraScale_MPSoC/RTOSDemo_A53_bsp/psu_cortexa53_0/libsrc/standalone_v6_1/src/xil_cache.c
Update Zynq MPSoC hardware definition and BSP files to be those shipped with the...
[freertos] / FreeRTOS / Demo / CORTEX_A53_64-bit_UltraScale_MPSoC / RTOSDemo_A53_bsp / psu_cortexa53_0 / libsrc / standalone_v6_1 / src / xil_cache.c
1 /******************************************************************************
2 *
3 * Copyright (C) 2014 - 2016 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. Cache APIs are
38 * yet to be implemented. They are left blank to avoid any compilation error
39 *
40 * <pre>
41 * MODIFICATION HISTORY:
42 *
43 * Ver    Who Date     Changes
44 * ----- ---- -------- -----------------------------------------------
45 * 5.00  pkp  05/29/14 First release
46 * 5.05  pkp      04/15/16 Updated the Xil_DCacheInvalidate,
47 *                                         Xil_DCacheInvalidateLine and Xil_DCacheInvalidateRange
48 *                                         functions description for proper explaination
49 *
50 * </pre>
51 *
52 ******************************************************************************/
53
54 /***************************** Include Files *********************************/
55
56 #include "xil_cache.h"
57 #include "xil_io.h"
58 #include "xpseudo_asm.h"
59 #include "xparameters.h"
60 #include "xreg_cortexa53.h"
61 #include "xil_exception.h"
62 #include "bspconfig.h"
63
64 /************************** Function Prototypes ******************************/
65
66 /************************** Variable Definitions *****************************/
67 #define IRQ_FIQ_MASK 0xC0U      /* Mask IRQ and FIQ interrupts in cpsr */
68
69 /****************************************************************************
70 *
71 * Enable the Data cache.
72 *
73 * @param        None.
74 *
75 * @return       None.
76 *
77 * @note         None.
78 *
79 ****************************************************************************/
80
81 void Xil_DCacheEnable(void)
82 {
83         u32 CtrlReg;
84
85         CtrlReg = mfcp(SCTLR_EL3);
86
87         /* enable caches only if they are disabled */
88         if((CtrlReg & XREG_CONTROL_DCACHE_BIT) == 0X00000000U){
89
90                 /* invalidate the Data cache */
91                 Xil_DCacheInvalidate();
92
93                 CtrlReg |= XREG_CONTROL_DCACHE_BIT;
94
95                 /* enable the Data cache for el3*/
96                 mtcp(SCTLR_EL3,CtrlReg);
97         }
98 }
99
100 /****************************************************************************
101 *
102 * Disable the Data cache.
103 *
104 * @param        None.
105 *
106 * @return       None.
107 *
108 * @note         None.
109 *
110 ****************************************************************************/
111 void Xil_DCacheDisable(void)
112 {
113         u32 CtrlReg;
114         /* clean and invalidate the Data cache */
115         Xil_DCacheFlush();
116
117         CtrlReg = mfcp(SCTLR_EL3);
118
119         CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT);
120
121         /* disable the Data cache for el3*/
122         mtcp(SCTLR_EL3,CtrlReg);
123 }
124
125 /****************************************************************************
126 *
127 * Invalidate the Data cache. The contents present in the cache are cleaned and
128 * invalidated.
129 *
130 * @param        None.
131 *
132 * @return       None.
133 *
134 * @note         In Cortex-A53, functionality to simply invalide the cachelines
135 *                       is not present. Such operations are a problem for an environment
136 *                       that supports virtualisation. It would allow one OS to invalidate
137 *                       a line belonging to another OS which could lead to that OS crashing
138 *                       because of the loss of essential data. Hence, such operations are
139 *                       promoted to clean and invalidate which avoids such corruption.
140 *
141 ****************************************************************************/
142 void Xil_DCacheInvalidate(void)
143 {
144         register u32 CsidReg, C7Reg;
145         u32 LineSize, NumWays;
146         u32 Way, WayIndex,WayAdjust, Set, SetIndex, NumSet, CacheLevel;
147         u32 currmask;
148
149         currmask = mfcpsr();
150         mtcpsr(currmask | IRQ_FIQ_MASK);
151
152
153         /* Number of level of cache*/
154
155         CacheLevel=0U;
156         /* Select cache level 0 and D cache in CSSR */
157         mtcp(CSSELR_EL1,CacheLevel);
158         isb();
159
160         CsidReg = mfcp(CCSIDR_EL1);
161
162         /* Get the cacheline size, way size, index size from csidr */
163         LineSize = (CsidReg & 0x00000007U) + 0x00000004U;
164
165         /* Number of Ways */
166         NumWays = (CsidReg & 0x00001FFFU) >> 3U;
167         NumWays += 0X00000001U;
168
169         /*Number of Set*/
170         NumSet = (CsidReg >> 13U) & 0x00007FFFU;
171         NumSet += 0X00000001U;
172
173         WayAdjust = clz(NumWays) - (u32)0x0000001FU;
174
175         Way = 0U;
176         Set = 0U;
177
178         /* Invalidate all the cachelines */
179         for (WayIndex =0U; WayIndex < NumWays; WayIndex++) {
180                 for (SetIndex =0U; SetIndex < NumSet; SetIndex++) {
181                         C7Reg = Way | Set | CacheLevel;
182                         mtcpdc(ISW,C7Reg);
183                         Set += (0x00000001U << LineSize);
184                 }
185                 Set = 0U;
186                 Way += (0x00000001U << WayAdjust);
187         }
188
189         /* Wait for invalidate to complete */
190         dsb();
191
192         /* Select cache level 1 and D cache in CSSR */
193         CacheLevel += (0x00000001U<<1U) ;
194         mtcp(CSSELR_EL1,CacheLevel);
195         isb();
196
197         CsidReg = mfcp(CCSIDR_EL1);
198
199         /* Get the cacheline size, way size, index size from csidr */
200                 LineSize = (CsidReg & 0x00000007U) + 0x00000004U;
201
202         /* Number of Ways */
203         NumWays = (CsidReg & 0x00001FFFU) >> 3U;
204         NumWays += 0x00000001U;
205
206         /* Number of Sets */
207         NumSet = (CsidReg >> 13U) & 0x00007FFFU;
208         NumSet += 0x00000001U;
209
210         WayAdjust = clz(NumWays) - (u32)0x0000001FU;
211
212         Way = 0U;
213         Set = 0U;
214
215         /* Invalidate all the cachelines */
216         for (WayIndex = 0U; WayIndex < NumWays; WayIndex++) {
217                 for (SetIndex = 0U; SetIndex < NumSet; SetIndex++) {
218                         C7Reg = Way | Set | CacheLevel;
219                         mtcpdc(ISW,C7Reg);
220                         Set += (0x00000001U << LineSize);
221                 }
222                 Set = 0U;
223                 Way += (0x00000001U << WayAdjust);
224         }
225         /* Wait for invalidate to complete */
226         dsb();
227
228         mtcpsr(currmask);
229 }
230
231 /****************************************************************************
232 *
233 * Invalidate a Data cache line. The cacheline is cleaned and invalidated
234 *
235 * @param        Address to be flushed.
236 *
237 * @return       None.
238 *
239 * @note         In Cortex-A53, functionality to simply invalide the cachelines
240 *                       is not present. Such operations are a problem for an environment
241 *                       that supports virtualisation. It would allow one OS to invalidate
242 *                       a line belonging to another OS which could lead to that OS crashing
243 *                       because of the loss of essential data. Hence, such operations are
244 *                       promoted to clean and invalidate which avoids such corruption.
245 *
246 ****************************************************************************/
247 void Xil_DCacheInvalidateLine(INTPTR adr)
248 {
249
250         u32 currmask;
251         currmask = mfcpsr();
252         mtcpsr(currmask | IRQ_FIQ_MASK);
253
254         /* Select cache level 0 and D cache in CSSR */
255         mtcp(CSSELR_EL1,0x0);
256         mtcpdc(IVAC,(adr & (~0x3F)));
257         /* Wait for invalidate to complete */
258         dsb();
259         /* Select cache level 1 and D cache in CSSR */
260         mtcp(CSSELR_EL1,0x2);
261         mtcpdc(IVAC,(adr & (~0x3F)));
262         /* Wait for invalidate to complete */
263         dsb();
264         mtcpsr(currmask);
265 }
266
267 /****************************************************************************
268 *
269 * Invalidate the Data cache for the given address range.
270 * The cachelines present in the adderss range are cleaned and invalidated
271 *
272 * @param        Start address of range to be invalidated.
273 * @param        Length of range to be invalidated in bytes.
274 *
275 * @return       None.
276 *
277 * @note         In Cortex-A53, functionality to simply invalide the cachelines
278 *                       is not present. Such operations are a problem for an environment
279 *                       that supports virtualisation. It would allow one OS to invalidate
280 *                       a line belonging to another OS which could lead to that OS crashing
281 *                       because of the loss of essential data. Hence, such operations are
282 *                       promoted to clean and invalidate which avoids such corruption.
283 *
284 ****************************************************************************/
285 void Xil_DCacheInvalidateRange(INTPTR  adr, INTPTR len)
286 {
287         const u32 cacheline = 64U;
288         INTPTR end;
289         INTPTR tempadr = adr;
290         INTPTR tempend;
291         u32 currmask;
292         currmask = mfcpsr();
293         mtcpsr(currmask | IRQ_FIQ_MASK);
294         if (len != 0U) {
295                 end = tempadr + len;
296                 tempend = end;
297
298                 if ((tempadr & (cacheline-1U)) != 0U) {
299                         tempadr &= (~(cacheline - 1U));
300                         Xil_DCacheFlushLine(tempadr);
301                         tempadr += cacheline;
302                 }
303                 if ((tempend & (cacheline-1U)) != 0U) {
304                         tempend &= (~(cacheline - 1U));
305                         Xil_DCacheFlushLine(tempend);
306                 }
307
308                 while (tempadr < tempend) {
309                         /* Select cache level 0 and D cache in CSSR */
310                         mtcp(CSSELR_EL1,0x0);
311                         /* Invalidate Data cache line */
312                         mtcpdc(IVAC,(tempadr & (~0x3F)));
313                         /* Wait for invalidate to complete */
314                         dsb();
315                         /* Select cache level 0 and D cache in CSSR */
316                         mtcp(CSSELR_EL1,0x2);
317                         /* Invalidate Data cache line */
318                         mtcpdc(IVAC,(tempadr & (~0x3F)));
319                         /* Wait for invalidate to complete */
320                         dsb();
321                         tempadr += cacheline;
322                 }
323         }
324         mtcpsr(currmask);
325 }
326
327 /****************************************************************************
328 *
329 * Flush the Data cache.
330 *
331 * @param        None.
332 *
333 * @return       None.
334 *
335 * @note         None.
336 *
337 ****************************************************************************/
338 void Xil_DCacheFlush(void)
339 {
340         register u32 CsidReg, C7Reg;
341         u32 LineSize, NumWays;
342         u32 Way, WayIndex,WayAdjust, Set, SetIndex, NumSet, CacheLevel;
343         u32 currmask;
344
345         currmask = mfcpsr();
346         mtcpsr(currmask | IRQ_FIQ_MASK);
347
348
349         /* Number of level of cache*/
350
351         CacheLevel = 0U;
352         /* Select cache level 0 and D cache in CSSR */
353         mtcp(CSSELR_EL1,CacheLevel);
354         isb();
355
356         CsidReg = mfcp(CCSIDR_EL1);
357
358         /* Get the cacheline size, way size, index size from csidr */
359         LineSize = (CsidReg & 0x00000007U) + 0x00000004U;
360
361         /* Number of Ways */
362         NumWays = (CsidReg & 0x00001FFFU) >> 3U;
363         NumWays += 0x00000001U;
364
365         /*Number of Set*/
366         NumSet = (CsidReg >> 13U) & 0x00007FFFU;
367         NumSet += 0x00000001U;
368
369         WayAdjust = clz(NumWays) - (u32)0x0000001FU;
370
371         Way = 0U;
372         Set = 0U;
373
374         /* Flush all the cachelines */
375         for (WayIndex = 0U; WayIndex < NumWays; WayIndex++) {
376                 for (SetIndex = 0U; SetIndex < NumSet; SetIndex++) {
377                         C7Reg = Way | Set | CacheLevel;
378                         mtcpdc(CISW,C7Reg);
379                         Set += (0x00000001U << LineSize);
380                 }
381                 Set = 0U;
382                 Way += (0x00000001U << WayAdjust);
383         }
384
385         /* Wait for Flush to complete */
386         dsb();
387
388         /* Select cache level 1 and D cache in CSSR */
389         CacheLevel += (0x00000001U << 1U);
390         mtcp(CSSELR_EL1,CacheLevel);
391         isb();
392
393         CsidReg = mfcp(CCSIDR_EL1);
394
395         /* Get the cacheline size, way size, index size from csidr */
396                 LineSize = (CsidReg & 0x00000007U) + 0x00000004U;
397
398         /* Number of Ways */
399         NumWays = (CsidReg & 0x00001FFFU) >> 3U;
400         NumWays += 0x00000001U;
401
402         /* Number of Sets */
403         NumSet = (CsidReg >> 13U) & 0x00007FFFU;
404         NumSet += 0x00000001U;
405
406         WayAdjust=clz(NumWays) - (u32)0x0000001FU;
407
408         Way = 0U;
409         Set = 0U;
410
411         /* Flush all the cachelines */
412         for (WayIndex =0U; WayIndex < NumWays; WayIndex++) {
413                 for (SetIndex =0U; SetIndex < NumSet; SetIndex++) {
414                         C7Reg = Way | Set | CacheLevel;
415                         mtcpdc(CISW,C7Reg);
416                         Set += (0x00000001U << LineSize);
417                 }
418                 Set=0U;
419                 Way += (0x00000001U<<WayAdjust);
420         }
421         /* Wait for Flush to complete */
422         dsb();
423
424         mtcpsr(currmask);
425 }
426
427 /****************************************************************************
428 *
429 * Flush a Data cache line. If the byte specified by the address (adr)
430 * is cached by the Data cache, the cacheline containing that byte is
431 * invalidated.  If the cacheline is modified (dirty), the entire
432 * contents of the cacheline are written to system memory before the
433 * line is invalidated.
434 *
435 * @param        Address to be flushed.
436 *
437 * @return       None.
438 *
439 * @note         The bottom 6 bits are set to 0, forced by architecture.
440 *
441 ****************************************************************************/
442 void Xil_DCacheFlushLine(INTPTR  adr)
443 {
444         u32 currmask;
445         currmask = mfcpsr();
446         mtcpsr(currmask | IRQ_FIQ_MASK);
447         /* Select cache level 0 and D cache in CSSR */
448         mtcp(CSSELR_EL1,0x0);
449         mtcpdc(CIVAC,(adr & (~0x3F)));
450         /* Wait for flush to complete */
451         dsb();
452         /* Select cache level 1 and D cache in CSSR */
453         mtcp(CSSELR_EL1,0x2);
454         mtcpdc(CIVAC,(adr & (~0x3F)));
455         /* Wait for flush to complete */
456         dsb();
457         mtcpsr(currmask);
458 }
459 /****************************************************************************
460 * Flush the Data cache for the given address range.
461 * If the bytes specified by the address (adr) are cached by the Data cache,
462 * the cacheline containing that byte is invalidated. If the cacheline
463 * is modified (dirty), the written to system memory first before the
464 * before the line is invalidated.
465 *
466 * @param        Start address of range to be flushed.
467 * @param        Length of range to be flushed in bytes.
468 *
469 * @return       None.
470 *
471 * @note         None.
472 *
473 ****************************************************************************/
474
475 void Xil_DCacheFlushRange(INTPTR  adr, INTPTR len)
476 {
477         const u32 cacheline = 64U;
478         INTPTR end;
479         INTPTR tempadr = adr;
480         INTPTR tempend;
481         u32 currmask;
482         currmask = mfcpsr();
483         mtcpsr(currmask | IRQ_FIQ_MASK);
484         if (len != 0x00000000U) {
485                 end = tempadr + len;
486                 tempend = end;
487                 if ((tempadr & (0x3F)) != 0) {
488                         tempadr &= ~(0x3F);
489                         Xil_DCacheFlushLine(tempadr);
490                         tempadr += cacheline;
491                 }
492                 if ((tempend & (0x3F)) != 0) {
493                         tempend &= ~(0x3F);
494                         Xil_DCacheFlushLine(tempend);
495                 }
496
497                 while (tempadr < tempend) {
498                         /* Select cache level 0 and D cache in CSSR */
499                         mtcp(CSSELR_EL1,0x0);
500                         /* Flush Data cache line */
501                         mtcpdc(CIVAC,(tempadr & (~0x3F)));
502                         /* Wait for flush to complete */
503                         dsb();
504                         /* Select cache level 1 and D cache in CSSR */
505                         mtcp(CSSELR_EL1,0x2);
506                         /* Flush Data cache line */
507                         mtcpdc(CIVAC,(tempadr & (~0x3F)));
508                         /* Wait for flush to complete */
509                         dsb();
510                         tempadr += cacheline;
511                 }
512         }
513
514         mtcpsr(currmask);
515 }
516
517
518 /****************************************************************************
519 *
520 * Enable the instruction cache.
521 *
522 * @param        None.
523 *
524 * @return       None.
525 *
526 * @note         None.
527 *
528 ****************************************************************************/
529
530
531 void Xil_ICacheEnable(void)
532 {
533         u32 CtrlReg;
534
535         CtrlReg = mfcp(SCTLR_EL3);
536
537         /* enable caches only if they are disabled */
538         if((CtrlReg & XREG_CONTROL_ICACHE_BIT)==0x00000000U){
539                 /* invalidate the instruction cache */
540                 Xil_ICacheInvalidate();
541
542                 CtrlReg |= XREG_CONTROL_ICACHE_BIT;
543
544                 /* enable the instruction cache for el3*/
545                 mtcp(SCTLR_EL3,CtrlReg);
546         }
547 }
548
549 /****************************************************************************
550 *
551 * Disable the instruction cache.
552 *
553 * @param        None.
554 *
555 * @return       None.
556 *
557 * @note         None.
558 *
559 ****************************************************************************/
560 void Xil_ICacheDisable(void)
561 {
562         u32 CtrlReg;
563
564         CtrlReg = mfcp(SCTLR_EL3);
565
566         /* invalidate the instruction cache */
567         Xil_ICacheInvalidate();
568         CtrlReg &= ~(XREG_CONTROL_ICACHE_BIT);
569         /* disable the instruction cache */
570         mtcp(SCTLR_EL3,CtrlReg);
571
572 }
573
574 /****************************************************************************
575 *
576 * Invalidate the entire instruction cache.
577 *
578 * @param        None.
579 *
580 * @return       None.
581 *
582 * @note         None.
583 *
584 ****************************************************************************/
585 void Xil_ICacheInvalidate(void)
586 {
587         unsigned int currmask;
588         currmask = mfcpsr();
589         mtcpsr(currmask | IRQ_FIQ_MASK);
590         mtcp(CSSELR_EL1,0x1);
591         dsb();
592         /* invalidate the instruction cache */
593         mtcpicall(IALLU);
594         /* Wait for invalidate to complete */
595         dsb();
596         mtcpsr(currmask);
597 }
598 /****************************************************************************
599 *
600 * Invalidate an instruction cache line. If the instruction specified by the
601 * parameter adr is cached by the instruction cache, the cacheline containing
602 * that instruction is invalidated.
603 *
604 * @param        None.
605 *
606 * @return       None.
607 *
608 * @note         The bottom 6 bits are set to 0, forced by architecture.
609 *
610 ****************************************************************************/
611
612 void Xil_ICacheInvalidateLine(INTPTR  adr)
613 {
614         u32 currmask;
615         currmask = mfcpsr();
616         mtcpsr(currmask | IRQ_FIQ_MASK);
617
618         mtcp(CSSELR_EL1,0x1);
619         /*Invalidate I Cache line*/
620         mtcpic(IVAU,adr & (~0x3F));
621         /* Wait for invalidate to complete */
622         dsb();
623         mtcpsr(currmask);
624 }
625
626 /****************************************************************************
627 *
628 * Invalidate the instruction cache for the given address range.
629 * If the bytes specified by the address (adr) are cached by the Data cache,
630 * the cacheline containing that byte is invalidated. If the cacheline
631 * is modified (dirty), the modified contents are lost and are NOT
632 * written to system memory before the line is invalidated.
633 *
634 * @param        Start address of range to be invalidated.
635 * @param        Length of range to be invalidated in bytes.
636 *
637 * @return       None.
638 *
639 * @note         None.
640 *
641 ****************************************************************************/
642 void Xil_ICacheInvalidateRange(INTPTR  adr, INTPTR len)
643 {
644         const u32 cacheline = 64U;
645         INTPTR end;
646         INTPTR tempadr = adr;
647         INTPTR tempend;
648         u32 currmask;
649         currmask = mfcpsr();
650         mtcpsr(currmask | IRQ_FIQ_MASK);
651
652         if (len != 0x00000000U) {
653                 end = tempadr + len;
654                 tempend = end;
655                 tempadr &= ~(cacheline - 0x00000001U);
656
657                 /* Select cache Level 0 I-cache in CSSR */
658                 mtcp(CSSELR_EL1,0x1);
659                 while (tempadr < tempend) {
660                         /*Invalidate I Cache line*/
661                         mtcpic(IVAU,adr & (~0x3F));
662
663                         tempadr += cacheline;
664                 }
665         }
666 /* Wait for invalidate to complete */
667         dsb();
668         mtcpsr(currmask);
669 }