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