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