6b40fe1fb612e60c7bb9672d88954645637a2e80
[processor-sdk/open-amp.git] / obsolete / system / zynqmp_r5 / generic / xil_standalone_lib / xil_cache.c
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 THE
22 * XILINX CONSORTIUM 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 ******************************************************************************/
49 /***************************** Include Files *********************************/
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"
59 /************************** Variable Definitions *****************************/
61 #define IRQ_FIQ_MASK 0xC0 /* Mask IRQ and FIQ interrupts in cpsr */
64 extern s32 _stack_end;
65 extern s32 __undef_stack;
67 /****************************************************************************/
68 /************************** Function Prototypes ******************************/
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;
85 /* enable caches only if they are disabled */
86 CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
88 if ((CtrlReg & XREG_CP15_CONTROL_C_BIT)==0x00000000U) {
89 /* invalidate the Data cache */
90 Xil_DCacheInvalidate();
92 /* enable the Data cache */
93 CtrlReg |= (XREG_CP15_CONTROL_C_BIT);
95 mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
96 }
97 }
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;
114 /* clean and invalidate the Data cache */
115 Xil_DCacheFlush();
117 /* disable the Data cache */
118 CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
120 CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT);
122 mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
123 }
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;
141 currmask = mfcpsr();
142 mtcpsr(currmask | IRQ_FIQ_MASK);
145 stack_end = (u32 )&_stack_end;
146 stack_start = (u32 )&__undef_stack;
147 stack_size = stack_start-stack_end;
149 /* Flush stack memory to save return address */
150 Xil_DCacheFlushRange(stack_end, stack_size);
152 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
154 /*invalidate all D cache*/
155 mtcp(XREG_CP15_INVAL_DC_ALL, 0);
157 mtcpsr(currmask);
158 }
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;
179 currmask = mfcpsr();
180 mtcpsr(currmask | IRQ_FIQ_MASK);
182 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
183 mtcp(XREG_CP15_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F)));
185 /* Wait for invalidate to complete */
186 dsb();
188 mtcpsr(currmask);
189 }
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;
215 currmask = mfcpsr();
216 mtcpsr(currmask | IRQ_FIQ_MASK);
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);
224 if ((tempadr & (cacheline-1U)) != 0U) {
225 tempadr &= (~(cacheline - 1U));
227 Xil_DCacheFlushLine(tempadr);
228 }
229 if ((tempend & (cacheline-1U)) != 0U) {
230 tempend &= (~(cacheline - 1U));
232 Xil_DCacheFlushLine(tempend);
233 }
235 while (tempadr < tempend) {
237 /* Invalidate Data cache line */
238 __asm__ __volatile__("mcr " \
239 XREG_CP15_INVAL_DC_LINE_MVA_POC :: "r" (tempadr));
241 tempadr += cacheline;
242 }
243 }
245 dsb();
246 mtcpsr(currmask);
247 }
249 /****************************************************************************
250 *
251 * Flush the entire Data cache.
252 *
253 * @param None.
254 *
255 * @return None.
256 *
257 * @note None.
258 *
259 ****************************************************************************/
260 void Xil_DCacheFlush(void)
261 {
262 register u32 CsidReg, C7Reg;
263 u32 CacheSize, LineSize, NumWays;
264 u32 Way, WayIndex, Set, SetIndex, NumSet;
265 u32 currmask;
267 currmask = mfcpsr();
268 mtcpsr(currmask | IRQ_FIQ_MASK);
270 /* Select cache level 0 and D cache in CSSR */
271 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
273 CsidReg = mfcp(XREG_CP15_CACHE_SIZE_ID);
275 /* Determine Cache Size */
277 CacheSize = (CsidReg >> 13U) & 0x000001FFU;
278 CacheSize += 0x00000001U;
279 CacheSize *= (u32)128; /* to get number of bytes */
281 /* Number of Ways */
282 NumWays = (CsidReg & 0x000003ffU) >> 3U;
283 NumWays += 0x00000001U;
285 /* Get the cacheline size, way size, index size from csidr */
286 LineSize = (CsidReg & 0x00000007U) + 0x00000004U;
288 NumSet = CacheSize/NumWays;
289 NumSet /= (0x00000001U << LineSize);
291 Way = 0U;
292 Set = 0U;
294 /* Invalidate all the cachelines */
295 for (WayIndex = 0U; WayIndex < NumWays; WayIndex++) {
296 for (SetIndex = 0U; SetIndex < NumSet; SetIndex++) {
297 C7Reg = Way | Set;
298 /* Flush by Set/Way */
299 __asm__ __volatile__("mcr " \
300 XREG_CP15_CLEAN_INVAL_DC_LINE_SW :: "r" (C7Reg));
302 Set += (0x00000001U << LineSize);
303 }
304 Set = 0U;
305 Way += 0x40000000U;
306 }
308 /* Wait for flush to complete */
309 dsb();
310 mtcpsr(currmask);
312 mtcpsr(currmask);
313 }
315 /****************************************************************************
316 *
317 * Flush a Data cache line. If the byte specified by the address (adr)
318 * is cached by the Data cache, the cacheline containing that byte is
319 * invalidated. If the cacheline is modified (dirty), the entire
320 * contents of the cacheline are written to system memory before the
321 * line is invalidated.
322 *
323 * @param Address to be flushed.
324 *
325 * @return None.
326 *
327 * @note The bottom 4 bits are set to 0, forced by architecture.
328 *
329 ****************************************************************************/
330 void Xil_DCacheFlushLine(INTPTR adr)
331 {
332 u32 currmask;
334 currmask = mfcpsr();
335 mtcpsr(currmask | IRQ_FIQ_MASK);
337 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
339 mtcp(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F)));
341 /* Wait for flush to complete */
342 dsb();
343 mtcpsr(currmask);
344 }
346 /****************************************************************************
347 * Flush the Data cache for the given address range.
348 * If the bytes specified by the address (adr) are cached by the Data cache,
349 * the cacheline containing that byte is invalidated. If the cacheline
350 * is modified (dirty), the written to system memory first before the
351 * before the line is invalidated.
352 *
353 * @param Start address of range to be flushed.
354 * @param Length of range to be flushed in bytes.
355 *
356 * @return None.
357 *
358 * @note None.
359 *
360 ****************************************************************************/
361 void Xil_DCacheFlushRange(INTPTR adr, u32 len)
362 {
363 u32 LocalAddr = adr;
364 const u32 cacheline = 32U;
365 u32 end;
366 u32 currmask;
368 currmask = mfcpsr();
369 mtcpsr(currmask | IRQ_FIQ_MASK);
371 if (len != 0x00000000U) {
372 /* Back the starting address up to the start of a cache line
373 * perform cache operations until adr+len
374 */
375 end = LocalAddr + len;
376 LocalAddr &= ~(cacheline - 1U);
378 while (LocalAddr < end) {
379 /* Flush Data cache line */
380 __asm__ __volatile__("mcr " \
381 XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC :: "r" (LocalAddr));
383 LocalAddr += cacheline;
384 }
385 }
386 dsb();
387 mtcpsr(currmask);
388 }
389 /****************************************************************************
390 *
391 * Store a Data cache line. If the byte specified by the address (adr)
392 * is cached by the Data cache and the cacheline is modified (dirty),
393 * the entire contents of the cacheline are written to system memory.
394 * After the store completes, the cacheline is marked as unmodified
395 * (not dirty).
396 *
397 * @param Address to be stored.
398 *
399 * @return None.
400 *
401 * @note The bottom 4 bits are set to 0, forced by architecture.
402 *
403 ****************************************************************************/
404 void Xil_DCacheStoreLine(INTPTR adr)
405 {
406 u32 currmask;
408 currmask = mfcpsr();
409 mtcpsr(currmask | IRQ_FIQ_MASK);
411 mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
412 mtcp(XREG_CP15_CLEAN_DC_LINE_MVA_POC, (adr & (~0x1F)));
414 /* Wait for store to complete */
415 dsb();
416 isb();
418 mtcpsr(currmask);
419 }
421 /****************************************************************************
422 *
423 * Enable the instruction cache.
424 *
425 * @param None.
426 *
427 * @return None.
428 *
429 * @note None.
430 *
431 ****************************************************************************/
432 void Xil_ICacheEnable(void)
433 {
434 register u32 CtrlReg;
436 /* enable caches only if they are disabled */
438 CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
440 if ((CtrlReg & XREG_CP15_CONTROL_I_BIT)==0x00000000U) {
441 /* invalidate the instruction cache */
442 mtcp(XREG_CP15_INVAL_IC_POU, 0);
444 /* enable the instruction cache */
445 CtrlReg |= (XREG_CP15_CONTROL_I_BIT);
447 mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
448 }
449 }
451 /****************************************************************************
452 *
453 * Disable the instruction cache.
454 *
455 * @param None.
456 *
457 * @return None.
458 *
459 * @note None.
460 *
461 ****************************************************************************/
462 void Xil_ICacheDisable(void)
463 {
464 register u32 CtrlReg;
466 dsb();
468 /* invalidate the instruction cache */
469 mtcp(XREG_CP15_INVAL_IC_POU, 0);
471 /* disable the instruction cache */
473 CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
475 CtrlReg &= ~(XREG_CP15_CONTROL_I_BIT);
477 mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
478 }
480 /****************************************************************************
481 *
482 * Invalidate the entire instruction cache.
483 *
484 * @param None.
485 *
486 * @return None.
487 *
488 * @note None.
489 *
490 ****************************************************************************/
491 void Xil_ICacheInvalidate(void)
492 {
493 u32 currmask;
495 currmask = mfcpsr();
496 mtcpsr(currmask | IRQ_FIQ_MASK);
498 mtcp(XREG_CP15_CACHE_SIZE_SEL, 1);
500 /* invalidate the instruction cache */
501 mtcp(XREG_CP15_INVAL_IC_POU, 0);
503 /* Wait for invalidate to complete */
504 dsb();
505 mtcpsr(currmask);
506 }
508 /****************************************************************************
509 *
510 * Invalidate an instruction cache line. If the instruction specified by the
511 * parameter adr is cached by the instruction cache, the cacheline containing
512 * that instruction is invalidated.
513 *
514 * @param None.
515 *
516 * @return None.
517 *
518 * @note The bottom 4 bits are set to 0, forced by architecture.
519 *
520 ****************************************************************************/
521 void Xil_ICacheInvalidateLine(INTPTR adr)
522 {
523 u32 currmask;
525 currmask = mfcpsr();
526 mtcpsr(currmask | IRQ_FIQ_MASK);
528 mtcp(XREG_CP15_CACHE_SIZE_SEL, 1);
529 mtcp(XREG_CP15_INVAL_IC_LINE_MVA_POU, (adr & (~0x1F)));
531 /* Wait for invalidate to complete */
532 dsb();
533 mtcpsr(currmask);
534 }
536 /****************************************************************************
537 *
538 * Invalidate the instruction cache for the given address range.
539 * If the bytes specified by the address (adr) are cached by the Data cache,
540 * the cacheline containing that byte is invalidated. If the cacheline
541 * is modified (dirty), the modified contents are lost and are NOT
542 * written to system memory before the line is invalidated.
543 *
544 * @param Start address of range to be invalidated.
545 * @param Length of range to be invalidated in bytes.
546 *
547 * @return None.
548 *
549 * @note None.
550 *
551 ****************************************************************************/
552 void Xil_ICacheInvalidateRange(INTPTR adr, u32 len)
553 {
554 u32 LocalAddr = adr;
555 const u32 cacheline = 32U;
556 u32 end;
557 u32 currmask;
559 currmask = mfcpsr();
560 mtcpsr(currmask | IRQ_FIQ_MASK);
561 if (len != 0x00000000U) {
562 /* Back the starting address up to the start of a cache line
563 * perform cache operations until adr+len
564 */
565 end = LocalAddr + len;
566 LocalAddr = LocalAddr & ~(cacheline - 1U);
568 /* Select cache L0 I-cache in CSSR */
569 mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U);
571 while (LocalAddr < end) {
573 /* Invalidate L1 I-cache line */
574 __asm__ __volatile__("mcr " \
575 XREG_CP15_INVAL_IC_LINE_MVA_POU :: "r" (LocalAddr));
577 LocalAddr += cacheline;
578 }
579 }
581 /* Wait for invalidate to complete */
582 dsb();
583 mtcpsr(currmask);
584 }