1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - OS
3 File: os_cache.c
4
5 Copyright 2003-2008 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2008-09-18#$
14 $Rev: 8573 $
15 $Author: okubata_ryoma $
16
17 *---------------------------------------------------------------------------*/
18 #include <nitro/os.h>
19 #include <nitro/code32.h>
20
21
22 /* ON when temporarily avoiding the Flush command */
23 #define SDK_AVOID_FLUSH
24
25
26 //===========================================================================
27 // DATA CACHE CONTROL
28 //===========================================================================
29 /*---------------------------------------------------------------------------*
30 Name: DC_Enable
31
32 Description: enable data cache
33
34 Arguments: None.
35
36 Returns: previous state
37 *---------------------------------------------------------------------------*/
DC_Enable()38 asm BOOL DC_Enable()
39 {
40 mrc p15, 0, r1, c1, c0, 0
41 and r0, r1, #HW_C1_DCACHE_ENABLE
42 mov r0, r0, LSR #HW_C1_DCACHE_ENABLE_SHIFT
43 orr r1, r1, #HW_C1_DCACHE_ENABLE
44 mcr p15, 0, r1, c1, c0, 0
45 bx lr
46 }
47
48 /*---------------------------------------------------------------------------*
49 Name: DC_Disable
50
51 Description: disable data cache
52
53 Arguments: None.
54
55 Returns: previous stats
56 *---------------------------------------------------------------------------*/
DC_Disable()57 asm BOOL DC_Disable()
58 {
59 mrc p15, 0, r1, c1, c0, 0
60 and r0, r1, #HW_C1_DCACHE_ENABLE
61 mov r0, r0, LSR #HW_C1_DCACHE_ENABLE_SHIFT
62 bic r1, r1, #HW_C1_DCACHE_ENABLE
63 mcr p15, 0, r1, c1, c0, 0
64 bx lr
65 }
66
67 /*---------------------------------------------------------------------------*
68 Name: DC_Restore
69
70 Description: set state of data cache
71
72 Arguments: data cache state to be set
73
74 Returns: previous state
75 *---------------------------------------------------------------------------*/
DC_Restore(register BOOL enable)76 asm BOOL DC_Restore( register BOOL enable )
77 {
78 //---- Argument process
79 cmp r0, #0
80 moveq r2, #0
81 movne r2, #HW_C1_DCACHE_ENABLE
82
83 mrc p15, 0, r1, c1, c0, 0
84 and r0, r1, #HW_C1_DCACHE_ENABLE
85 mov r0, r0, LSR #HW_C1_DCACHE_ENABLE_SHIFT
86 bic r1, r1, #HW_C1_DCACHE_ENABLE
87 orr r1, r1, r2
88 mcr p15, 0, r1, c1, c0, 0
89 bx lr
90 }
91
92 //===========================================================================
93 // DATA CACHE (for all range)
94 //===========================================================================
95 /*---------------------------------------------------------------------------*
96 Name: DC_InvalidateAll
97
98 Description: invalidate all data cache
99
100 Arguments: None.
101
102 Returns: None.
103 *---------------------------------------------------------------------------*/
DC_InvalidateAll(void)104 asm void DC_InvalidateAll( void )
105 {
106 mov r0, #0
107 mcr p15, 0, r0, c7, c6, 0
108 bx lr
109 }
110
111 /*---------------------------------------------------------------------------*
112 Name: DC_StoreAll
113
114 Description: clean all data cache
115 (write cache data to memory)
116
117 Arguments: None.
118
119 Returns: None.
120 *---------------------------------------------------------------------------*/
DC_StoreAll(void)121 asm void DC_StoreAll( void )
122 {
123 mov r1, #0
124 @1:
125 mov r0, #0
126 @2:
127 orr r2, r1, r0
128 mcr p15, 0, r2, c7, c10, 2
129 add r0, r0, #HW_CACHE_LINE_SIZE
130 cmp r0, #HW_DCACHE_SIZE/4
131 blt @2
132
133 add r1, r1, #1<<HW_C7_CACHE_SET_NO_SHIFT
134 cmp r1, #0
135 bne @1
136
137 bx lr
138 }
139
140 /*---------------------------------------------------------------------------*
141 Name: DC_FlushAll
142
143 Description: clean and invalidate all data cache
144 (write cache data to memory, and invalidate cache)
145
146 Arguments: None.
147
148 Returns: None.
149 *---------------------------------------------------------------------------*/
DC_FlushAll(void)150 asm void DC_FlushAll( void )
151 {
152 mov r12, #0
153 mov r1, #0 // r1: Set No counter (0-3)
154
155 @1:
156 mov r0, #0 // r0: Line counter (0-DCACHE_SIZE/4)
157
158 @2:
159 orr r2, r1, r0
160 mcr p15, 0, r12, c7, c10, 4 /* wait write buffer empty */
161 mcr p15, 0, r2, c7, c14, 2 /* flush */
162 add r0, r0, #HW_CACHE_LINE_SIZE
163 cmp r0, #HW_DCACHE_SIZE/4
164 blt @2
165
166 add r1, r1, #1<<HW_C7_CACHE_SET_NO_SHIFT
167 cmp r1, #0
168 bne @1
169
170 bx lr
171 }
172
173 //===========================================================================
174 // DATA CACHE (for specified range)
175 //===========================================================================
176 /*---------------------------------------------------------------------------*
177 Name: DC_InvalidateRange
178
179 Description: invalidate data cache in specified range
180
181 Arguments: startAddr start address
182 nBytes size (in byte)
183
184 Returns: None.
185 *---------------------------------------------------------------------------*/
DC_InvalidateRange(register void * startAddr,register u32 nBytes)186 asm void DC_InvalidateRange( register void* startAddr, register u32 nBytes )
187 {
188 add r1, r1, r0
189 bic r0, r0, #HW_CACHE_LINE_SIZE - 1
190
191 @1:
192 mcr p15, 0, r0, c7, c6, 1
193 add r0, r0, #HW_CACHE_LINE_SIZE
194 cmp r0, r1
195 blt @1
196 bx lr
197 }
198
199 /*---------------------------------------------------------------------------*
200 Name: DC_StoreRange
201
202 Description: clean data cache in specified range
203 (write cache data to memory)
204
205 Arguments: startAddr start address
206 nBytes size (in byte)
207
208 Returns: None.
209 *---------------------------------------------------------------------------*/
DC_StoreRange(register const void * startAddr,register u32 nBytes)210 asm void DC_StoreRange( register const void* startAddr, register u32 nBytes )
211 {
212 add r1, r1, r0
213 bic r0, r0, #HW_CACHE_LINE_SIZE - 1
214
215 @1:
216 mcr p15, 0, r0, c7, c10, 1
217 add r0, r0, #HW_CACHE_LINE_SIZE
218 cmp r0, r1
219 blt @1
220 bx lr
221 }
222
223 /*---------------------------------------------------------------------------*
224 Name: DC_FlushRange
225
226 Description: clean and invalidate data cache in specified range
227 (write cache data to memory, and invalidate cache)
228
229 Arguments: startAddr start address
230 nBytes size (in byte)
231
232 Returns: None.
233 *---------------------------------------------------------------------------*/
DC_FlushRange(register const void * startAddr,register u32 nBytes)234 asm void DC_FlushRange( register const void* startAddr, register u32 nBytes )
235 {
236 mov r12, #0
237 add r1, r1, r0
238 bic r0, r0, #HW_CACHE_LINE_SIZE - 1
239 @1:
240 mcr p15, 0, r12, c7, c10, 4 /* wait write buffer empty */
241 mcr p15, 0, r0, c7, c14, 1 /* flush */
242 add r0, r0, #HW_CACHE_LINE_SIZE
243 cmp r0, r1
244 blt @1
245
246 bx lr
247 }
248
249 //===========================================================================
250 // DATA CACHE (for specified range)
251 //===========================================================================
252 /*---------------------------------------------------------------------------*
253 Name: DC_TouchRange
254
255 Description: include specified area to data cache in advance
256
257 Arguments: startAddr start address
258 nBytes size (in byte)
259
260 Returns: None.
261 *---------------------------------------------------------------------------*/
DC_TouchRange(register const void * startAddr,register u32 nBytes)262 asm void DC_TouchRange( register const void* startAddr, register u32 nBytes )
263 {
264 add r1, r1, r0
265 bic r0, r0, #HW_CACHE_LINE_SIZE - 1
266
267 @1:
268 pld [r0]
269 add r0, r0, #HW_CACHE_LINE_SIZE
270 cmp r0, r1
271 blt @1
272 bx lr
273 }
274
275 /*---------------------------------------------------------------------------*
276 Name: DC_LockdownRange
277
278 Description: lock specified area to prevent not to release data cache
279
280 Arguments: startAddr start address
281 nBytes size (in byte)
282
283 Returns: None.
284 *---------------------------------------------------------------------------*/
DC_LockdownRange(register const void * startAddr,register u32 nBytes)285 asm void DC_LockdownRange( register const void* startAddr, register u32 nBytes )
286 {
287 add r1, r1, r0 // r1: End address
288 bic r0, r0, #HW_CACHE_LINE_SIZE - 1
289 mrc p15, 0, r3, c9, c0, 0
290 and r3, r3, #HW_C9_LOCKDOWN_SET_NO_MASK // r3: Current set number
291 cmp r3, #3 // Error if 3 sets are locked down
292 mvneq r0, #0
293 bxeq lr
294
295 stmfd sp!, { lr, r0, r1 }
296 ldr r0, =OS_DisableInterrupts
297 blx r0
298 mov r2, r0
299 ldmfd sp!, { lr, r0, r1 }
300
301 orr r3, r3, #HW_C9_LOCKDOWN_LOAD_MODE // Cache lockdown-Load Mode
302 mcr p15, 0, r3, c9, c0, 0
303
304 @111:
305 mcr p15, 0, r0, c7, c14, 1 // Clean/disable data in cache once
306 ldr r12, [r0] // Read data and place in cache
307 add r0, r0, #HW_CACHE_LINE_SIZE
308 cmp r0, r1
309 blt @111
310 add r3, r3, #1 // Cache normal mode & set number increment
311 bic r0, r3, #HW_C9_LOCKDOWN_LOAD_MODE
312 mcr p15, 0, r3, c9, c0, 0
313
314 stmfd sp!, { lr }
315 mov r0, r2
316 ldr r1, =OS_RestoreInterrupts
317 blx r1
318 ldmfd sp!, { lr }
319
320 bx lr
321 }
322
323
324 /*---------------------------------------------------------------------------*
325 Name: DC_UnlockdownAll
326
327 Description: unlock all data cache to enable to release
328
329 Arguments: None.
330
331 Returns: None.
332 *---------------------------------------------------------------------------*/
DC_UnlockdownAll(void)333 asm void DC_UnlockdownAll( void )
334 {
335 mov r3, #0
336 mcr p15, 0, r3, c9, c0, 0
337 bx lr
338 }
339
340 /*---------------------------------------------------------------------------*
341 Name: DC_Unlockdown
342
343 Description: unlock any data cache to enable to release
344
345 Arguments: num - specify number of datablock to unlock.
346
347 Returns: None.
348 *---------------------------------------------------------------------------*/
DC_Unlockdown(register u32 num)349 asm void DC_Unlockdown( register u32 num )
350 {
351 mrc p15, 0, r3, c9, c0, 0
352 and r3, r3, #HW_C9_LOCKDOWN_SET_NO_MASK
353 subs r3, r3, r0
354 movmi r3, #0
355 mcr p15, 0, r3, c9, c0, 0
356 bx lr
357 }
358
359
360 /*---------------------------------------------------------------------------*
361 Name: DC_WaitWriteBufferEmpty
362
363 Description: wait till write buffer becomes to be empty
364
365 Arguments: None.
366
367 Returns: None.
368 *---------------------------------------------------------------------------*/
DC_WaitWriteBufferEmpty()369 asm void DC_WaitWriteBufferEmpty()
370 {
371 mov r0, #0
372 mcr p15, 0, r0, c7, c10, 4
373 bx lr
374 }
375
376
377 //===========================================================================
378 // INSTRUCTION CACHE CONTROL
379 //===========================================================================
380 /*---------------------------------------------------------------------------*
381 Name: IC_Enable
382
383 Description: enable instruction cache
384
385 Arguments: None.
386
387 Returns: previous state
388 *---------------------------------------------------------------------------*/
IC_Enable()389 asm BOOL IC_Enable()
390 {
391 mrc p15, 0, r1, c1, c0, 0
392 and r0, r1, #HW_C1_ICACHE_ENABLE
393 mov r0, r0, LSR #HW_C1_ICACHE_ENABLE_SHIFT
394 orr r1, r1, #HW_C1_ICACHE_ENABLE
395 mcr p15, 0, r1, c1, c0, 0
396 bx lr
397 }
398
399 /*---------------------------------------------------------------------------*
400 Name: IC_Disable
401
402 Description: disable instruction cache
403
404 Arguments: None.
405
406 Returns: previous stats
407 *---------------------------------------------------------------------------*/
IC_Disable()408 asm BOOL IC_Disable()
409 {
410 mrc p15, 0, r1, c1, c0, 0
411 and r0, r1, #HW_C1_ICACHE_ENABLE
412 mov r0, r0, LSR #HW_C1_ICACHE_ENABLE_SHIFT
413 bic r1, r1, #HW_C1_ICACHE_ENABLE
414 mcr p15, 0, r1, c1, c0, 0
415 bx lr
416 }
417
418 /*---------------------------------------------------------------------------*
419 Name: IC_Restore
420
421 Description: set state of instruction cache
422
423 Arguments: instruction cache state to be set
424
425 Returns: previous stats
426 *---------------------------------------------------------------------------*/
IC_Restore(register BOOL enable)427 asm BOOL IC_Restore( register BOOL enable )
428 {
429 //---- Argument process
430 cmp r0, #0
431 moveq r2, #0
432 movne r2, #HW_C1_ICACHE_ENABLE
433
434 mrc p15, 0, r1, c1, c0, 0
435 and r0, r1, #HW_C1_ICACHE_ENABLE
436 mov r0, r0, LSR #HW_C1_ICACHE_ENABLE_SHIFT
437 bic r1, r1, #HW_C1_ICACHE_ENABLE
438 orr r1, r1, r2
439 mcr p15, 0, r1, c1, c0, 0
440 bx lr
441 }
442
443 //===========================================================================
444 // INSTRUCTION CACHE
445 //===========================================================================
446 /*---------------------------------------------------------------------------*
447 Name: IC_InvalidateAll
448
449 Description: invalidate all instruction cache
450
451 Arguments: None.
452
453 Returns: None.
454 *---------------------------------------------------------------------------*/
IC_InvalidateAll(void)455 asm void IC_InvalidateAll( void )
456 {
457 mov r0, #0
458 mcr p15, 0, r0, c7, c5, 0
459 bx lr
460 }
461
462 /*---------------------------------------------------------------------------*
463 Name: IC_InvalidateRange
464
465 Description: invalidate instruction cache in specified range
466
467 Arguments: startAddr start address
468 nBytes size (in byte)
469
470 Returns: None.
471 *---------------------------------------------------------------------------*/
IC_InvalidateRange(register void * startAddr,register u32 nBytes)472 asm void IC_InvalidateRange( register void* startAddr, register u32 nBytes )
473 {
474 add r1, r1, r0
475 bic r0, r0, #HW_CACHE_LINE_SIZE - 1
476
477 @1:
478 mcr p15, 0, r0, c7, c5, 1
479 add r0, r0, #HW_CACHE_LINE_SIZE
480 cmp r0, r1
481 blt @1
482 bx lr
483 }
484
485 /*---------------------------------------------------------------------------*
486 Name: IC_PrefetchRange
487
488 Description: include specified area to instruction cache in advance
489
490 Arguments: startAddr start address
491 nBytes size (in byte)
492
493 Returns: None.
494 *---------------------------------------------------------------------------*/
IC_PrefetchRange(register const void * startAddr,register u32 nBytes)495 asm void IC_PrefetchRange( register const void* startAddr, register u32 nBytes )
496 {
497 add r1, r1, r0
498 bic r0, r0, #HW_CACHE_LINE_SIZE - 1
499
500 @1:
501 mcr p15, 0, r0, c7, c13, 1
502 add r0, r0, #HW_CACHE_LINE_SIZE
503 cmp r0, r1
504 blt @1
505 bx lr
506 }
507
508
509 #include <nitro/itcm_begin.h>
510
511 /*---------------------------------------------------------------------------*
512 Name: IC_LockdownRange
513
514 Description: lock specified area to prevent not to release instruction cache
515
516 Arguments: startAddr start address
517 nBytes size (in byte)
518
519 Returns: None.
520 *---------------------------------------------------------------------------*/
IC_LockdownRange(register const void * startAddr,register u32 nBytes)521 asm void IC_LockdownRange( register const void* startAddr, register u32 nBytes )
522 {
523 add r1, r1, r0 // r1: End address
524 bic r0, r0, #HW_CACHE_LINE_SIZE - 1
525 mrc p15, 0, r3, c9, c0, 1
526 and r3, r3, #HW_C9_LOCKDOWN_SET_NO_MASK // r3: Current set number
527 cmp r3, #3 // Error if 3 sets are locked down
528 mvneq r0, #0
529 bxeq lr
530
531 stmfd sp!, { lr, r0, r1 }
532 ldr r0, =OS_DisableInterrupts
533 blx r0
534 mov r2, r0
535 ldmfd sp!, { lr, r0, r1 }
536
537 orr r3, r3, #HW_C9_LOCKDOWN_LOAD_MODE // Cache lockdown-Load Mode
538 mcr p15, 0, r3, c9, c0, 1
539
540 @1:
541 mcr p15, 0, r0, c7, c5, 1 // Disable from cache once
542 mcr p15, 0, r0, c7, c13, 1 // Prefetch
543 add r0, r0, #HW_CACHE_LINE_SIZE
544 cmp r0, r1
545 blt @1
546 add r3, r3, #1 // Cache normal mode & set number increment
547 bic r0, r3, #HW_C9_LOCKDOWN_LOAD_MODE
548 mcr p15, 0, r3, c9, c0, 1
549
550 stmfd sp!, { lr }
551 mov r0, r2
552 ldr r1, =OS_RestoreInterrupts
553 blx r1
554 ldmfd sp!, { lr }
555
556 bx lr
557 }
558
559 #include <nitro/itcm_end.h>
560
561
562 /*---------------------------------------------------------------------------*
563 Name: IC_UnlockdownAll
564
565 Description: unlock all instruction cache to enable to release
566
567 Arguments: None.
568
569 Returns: None.
570 *---------------------------------------------------------------------------*/
IC_UnlockdownAll(void)571 asm void IC_UnlockdownAll( void )
572 {
573 mov r3, #0
574 mcr p15, 0, r3, c9, c0, 1
575 bx lr
576 }
577
578
579 /*---------------------------------------------------------------------------*
580 Name: IC_Unlockdown
581
582 Description: unlock any instruction cache to enable to release
583
584 Arguments: num - specify number of datablock to unlock.
585
586 Returns: None.
587 *---------------------------------------------------------------------------*/
IC_Unlockdown(register u32 num)588 asm void IC_Unlockdown( register u32 num )
589 {
590 mrc p15, 0, r3, c9, c0, 1
591 and r3, r3, #HW_C9_LOCKDOWN_SET_NO_MASK
592 subs r3, r3, r0
593 movmi r3, #0
594 mcr p15, 0, r3, c9, c0, 1
595 bx lr
596 }
597
598
599 #include <nitro/codereset.h>
600