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