]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/arm9/var/v2_0/include/hal_cache.h
Initial revision
[karo-tx-redboot.git] / packages / hal / arm / arm9 / var / v2_0 / include / hal_cache.h
1 #ifndef CYGONCE_HAL_CACHE_H
2 #define CYGONCE_HAL_CACHE_H
3
4 //=============================================================================
5 //
6 //      hal_cache.h
7 //
8 //      HAL cache control API
9 //
10 //=============================================================================
11 //####ECOSGPLCOPYRIGHTBEGIN####
12 // -------------------------------------------
13 // This file is part of eCos, the Embedded Configurable Operating System.
14 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
15 //
16 // eCos is free software; you can redistribute it and/or modify it under
17 // the terms of the GNU General Public License as published by the Free
18 // Software Foundation; either version 2 or (at your option) any later version.
19 //
20 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
21 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
22 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
23 // for more details.
24 //
25 // You should have received a copy of the GNU General Public License along
26 // with eCos; if not, write to the Free Software Foundation, Inc.,
27 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
28 //
29 // As a special exception, if other files instantiate templates or use macros
30 // or inline functions from this file, or you compile this file and link it
31 // with other works to produce a work based on this file, this file does not
32 // by itself cause the resulting work to be covered by the GNU General Public
33 // License. However the source code for this file must still be made available
34 // in accordance with section (3) of the GNU General Public License.
35 //
36 // This exception does not invalidate any other reasons why a work based on
37 // this file might be covered by the GNU General Public License.
38 //
39 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
40 // at http://sources.redhat.com/ecos/ecos-license/
41 // -------------------------------------------
42 //####ECOSGPLCOPYRIGHTEND####
43 //=============================================================================
44 //#####DESCRIPTIONBEGIN####
45 //
46 // Author(s):   gthomas
47 // Contributors:hmt, jskov
48 //              Travis C. Furrer <furrer@mit.edu>
49 // Date:        2000-05-08
50 // Purpose:     Cache control API
51 // Description: The macros defined here provide the HAL APIs for handling
52 //              cache control operations.
53 // Usage:
54 //              #include <cyg/hal/hal_cache.h>
55 //              ...
56 //              
57 //
58 //####DESCRIPTIONEND####
59 //
60 //=============================================================================
61
62 #include <cyg/infra/cyg_type.h>
63 #include <cyg/hal/hal_mmu.h>
64
65
66 //-----------------------------------------------------------------------------
67 // Cache dimensions
68
69 #if defined(CYGPKG_HAL_ARM_ARM9_ARM920T)
70 # define HAL_ICACHE_SIZE                 0x4000
71 # define HAL_ICACHE_LINE_SIZE            32
72 # define HAL_ICACHE_WAYS                 64
73 # define HAL_ICACHE_SETS (HAL_ICACHE_SIZE/(HAL_ICACHE_LINE_SIZE*HAL_ICACHE_WAYS))
74
75 # define HAL_DCACHE_SIZE                 0x4000
76 # define HAL_DCACHE_LINE_SIZE            32
77 # define HAL_DCACHE_WAYS                 64
78 # define HAL_DCACHE_SETS (HAL_DCACHE_SIZE/(HAL_DCACHE_LINE_SIZE*HAL_DCACHE_WAYS))
79
80 # define HAL_WRITE_BUFFER                64
81
82 # define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX
83 # define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX_STEP  0x20
84 # define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX_LIMIT 0x100
85
86 #elif defined(CYGPKG_HAL_ARM_ARM9_ARM922T)
87 # define HAL_ICACHE_SIZE                 0x2000
88 # define HAL_ICACHE_LINE_SIZE            32
89 # define HAL_ICACHE_WAYS                 64
90 # define HAL_ICACHE_SETS (HAL_ICACHE_SIZE/(HAL_ICACHE_LINE_SIZE*HAL_ICACHE_WAYS))
91
92 # define HAL_DCACHE_SIZE                 0x2000
93 # define HAL_DCACHE_LINE_SIZE            32
94 # define HAL_DCACHE_WAYS                 64
95 # define HAL_DCACHE_SETS (HAL_DCACHE_SIZE/(HAL_DCACHE_LINE_SIZE*HAL_DCACHE_WAYS))
96
97 # define HAL_WRITE_BUFFER                64
98
99 # define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX
100 # define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX_STEP  0x20
101 # define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX_LIMIT 0x80
102
103 #elif defined(CYGPKG_HAL_ARM_ARM9_ARM925T)
104 # define HAL_ICACHE_SIZE                 0x4000
105 # define HAL_ICACHE_LINE_SIZE            16
106 # define HAL_ICACHE_WAYS                 2
107 # define HAL_ICACHE_SETS (HAL_ICACHE_SIZE/(HAL_ICACHE_LINE_SIZE*HAL_ICACHE_WAYS))
108
109 # define HAL_DCACHE_SIZE                 0x2000
110 # define HAL_DCACHE_LINE_SIZE            16
111 # define HAL_DCACHE_WAYS                 2
112 # define HAL_DCACHE_SETS (HAL_DCACHE_SIZE/(HAL_DCACHE_LINE_SIZE*HAL_DCACHE_WAYS))
113
114 # define HAL_WRITE_BUFFER                64
115
116 # define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE // has instruction to clean D-cache
117
118 #elif defined(CYGPKG_HAL_ARM_ARM9_ARM940T)
119 # define HAL_ICACHE_SIZE                 0x1000
120 # define HAL_ICACHE_LINE_SIZE            16
121 # define HAL_ICACHE_WAYS                 4
122 # define HAL_ICACHE_SETS (HAL_ICACHE_SIZE/(HAL_ICACHE_LINE_SIZE*HAL_ICACHE_WAYS))
123
124 # define HAL_DCACHE_SIZE                 0x1000
125 # define HAL_DCACHE_LINE_SIZE            16
126 # define HAL_DCACHE_WAYS                 4
127 # define HAL_DCACHE_SETS (HAL_DCACHE_SIZE/(HAL_DCACHE_LINE_SIZE*HAL_DCACHE_WAYS))
128
129 # define HAL_WRITE_BUFFER                32
130
131 # define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX
132 # define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX_STEP  0x10
133 # define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX_LIMIT 0x40
134
135 #elif defined(CYGPKG_HAL_ARM_ARM9_ARM966E)
136 # define HAL_ICACHE_SIZE                 0
137 # define HAL_ICACHE_LINE_SIZE            0
138 # define HAL_ICACHE_WAYS                 0
139 # define HAL_ICACHE_SETS (HAL_ICACHE_SIZE/(HAL_ICACHE_LINE_SIZE*HAL_ICACHE_WAYS))
140
141 # define HAL_DCACHE_SIZE                 0
142 # define HAL_DCACHE_LINE_SIZE            0
143 # define HAL_DCACHE_WAYS                 0
144 # define HAL_DCACHE_SETS (HAL_DCACHE_SIZE/(HAL_DCACHE_LINE_SIZE*HAL_DCACHE_WAYS))
145
146 # define HAL_WRITE_BUFFER                32
147
148 # define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX
149 # define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX_STEP  0
150 # define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX_LIMIT 0
151
152 #else
153 # error "No cache details defined"
154 #endif
155
156 // FIXME: much of the code below should make better use of
157 // the definitions from hal_mmu.h
158
159 //-----------------------------------------------------------------------------
160 // Global control of Instruction cache
161
162 #if HAL_ICACHE_SIZE != 0
163
164 // FIXME: disable/enable instruction streaming?
165
166 // Enable the instruction cache
167 #define HAL_ICACHE_ENABLE()                                             \
168 CYG_MACRO_START                                                         \
169     asm volatile (                                                      \
170         "mrc  p15,0,r1,c1,c0,0;"                                        \
171         "orr  r1,r1,#0x1000;"                                           \
172         "orr  r1,r1,#0x0003;" /* enable ICache (also ensures   */       \
173                               /* that MMU and alignment faults */       \
174                               /* are enabled)                  */       \
175         "mcr  p15,0,r1,c1,c0,0"                                         \
176         :                                                               \
177         :                                                               \
178         : "r1" /* Clobber list */                                       \
179         );                                                              \
180 CYG_MACRO_END
181
182 // Disable the instruction cache (and invalidate it, required semanitcs)
183 #define HAL_ICACHE_DISABLE()                                            \
184 CYG_MACRO_START                                                         \
185     asm volatile (                                                      \
186         "mrc    p15,0,r1,c1,c0,0;"                                      \
187         "bic    r1,r1,#0x1000;" /* disable ICache (but not MMU, etc) */ \
188         "mcr    p15,0,r1,c1,c0,0;"                                      \
189         "mov    r1,#0;"                                                 \
190         "mcr    p15,0,r1,c7,c5,0;"  /* flush ICache */                  \
191         "nop;" /* next few instructions may be via cache    */          \
192         "nop;"                                                          \
193         "nop;"                                                          \
194         "nop;"                                                          \
195         "nop;"                                                          \
196         "nop"                                                           \
197         :                                                               \
198         :                                                               \
199         : "r1" /* Clobber list */                                       \
200         );                                                              \
201 CYG_MACRO_END
202
203 // Query the state of the instruction cache
204 #define HAL_ICACHE_IS_ENABLED(_state_)                                   \
205 CYG_MACRO_START                                                          \
206     register cyg_uint32 reg;                                             \
207     asm volatile ("mrc  p15,0,%0,c1,c0,0"                                \
208                   : "=r"(reg)                                            \
209                   :                                                      \
210         );                                                               \
211     (_state_) = (0 != (0x1000 & reg)); /* Bit 12 is ICache enable */     \
212 CYG_MACRO_END
213
214 // Invalidate the entire cache
215 #define HAL_ICACHE_INVALIDATE_ALL()                                     \
216 CYG_MACRO_START                                                         \
217     /* this macro can discard dirty cache lines (N/A for ICache) */     \
218     asm volatile (                                                      \
219         "mov    r1,#0;"                                                 \
220         "mcr    p15,0,r1,c7,c5,0;"  /* flush ICache */                  \
221         "mcr    p15,0,r1,c8,c5,0;"  /* flush ITLB only */               \
222         "nop;" /* next few instructions may be via cache    */          \
223         "nop;"                                                          \
224         "nop;"                                                          \
225         "nop;"                                                          \
226         "nop;"                                                          \
227         "nop;"                                                          \
228         :                                                               \
229         :                                                               \
230         : "r1" /* Clobber list */                                       \
231         );                                                              \
232 CYG_MACRO_END
233
234 // Synchronize the contents of the cache with memory.
235 // (which includes flushing out pending writes)
236 #define HAL_ICACHE_SYNC()                                       \
237 CYG_MACRO_START                                                 \
238     HAL_DCACHE_SYNC(); /* ensure data gets to RAM */            \
239     HAL_ICACHE_INVALIDATE_ALL(); /* forget all we know */       \
240 CYG_MACRO_END
241
242 #else
243
244 #define HAL_ICACHE_ENABLE()
245 #define HAL_ICACHE_DISABLE()
246 #define HAL_ICACHE_IS_ENABLED(_state_) ((_state_) = 0)
247 #define HAL_ICACHE_INVALIDATE_ALL()
248 #define HAL_ICACHE_SYNC()
249
250 #endif
251
252 // Set the instruction cache refill burst size
253 //#define HAL_ICACHE_BURST_SIZE(_size_)
254
255 // Load the contents of the given address range into the instruction cache
256 // and then lock the cache so that it stays there.
257 //#define HAL_ICACHE_LOCK(_base_, _size_)
258
259 // Undo a previous lock operation
260 //#define HAL_ICACHE_UNLOCK(_base_, _size_)
261
262 // Unlock entire cache
263 //#define HAL_ICACHE_UNLOCK_ALL()
264
265 //-----------------------------------------------------------------------------
266 // Instruction cache line control
267
268 // Invalidate cache lines in the given range without writing to memory.
269 //#define HAL_ICACHE_INVALIDATE( _base_ , _size_ )
270
271 //-----------------------------------------------------------------------------
272 // Global control of data cache
273
274 #if HAL_DCACHE_SIZE != 0
275
276 // Enable the data cache
277 #define HAL_DCACHE_ENABLE()                                             \
278 CYG_MACRO_START                                                         \
279     asm volatile (                                                      \
280         "mrc  p15,0,r1,c1,c0,0;"                                        \
281         "orr  r1,r1,#0x000F;" /* enable DCache (also ensures    */      \
282                               /* the MMU, alignment faults, and */      \
283                               /* write buffer are enabled)      */      \
284         "mcr  p15,0,r1,c1,c0,0"                                         \
285         :                                                               \
286         :                                                               \
287         : "r1" /* Clobber list */                                       \
288         );                                                              \
289 CYG_MACRO_END
290
291 // Disable the data cache (and invalidate it, required semanitcs)
292 #define HAL_DCACHE_DISABLE()                                            \
293 CYG_MACRO_START                                                         \
294     asm volatile (                                                      \
295         "mrc  p15,0,r1,c1,c0,0;"                                        \
296         "bic  r1,r1,#0x000C;" /* disable DCache AND write buffer  */    \
297                               /* but not MMU and alignment faults */    \
298         "mcr  p15,0,r1,c1,c0,0;"                                        \
299         "mov    r1,#0;"                                                 \
300         "mcr  p15,0,r1,c7,c6,0" /* clear data cache */                  \
301         :                                                               \
302         :                                                               \
303         : "r1" /* Clobber list */                                       \
304         );                                                              \
305 CYG_MACRO_END
306
307 // Query the state of the data cache
308 #define HAL_DCACHE_IS_ENABLED(_state_)                                   \
309 CYG_MACRO_START                                                          \
310     register int reg;                                                    \
311     asm volatile ("mrc  p15,0,%0,c1,c0,0;"                               \
312                   : "=r"(reg)                                            \
313                   :                                                      \
314         );                                                               \
315     (_state_) = (0 != (4 & reg)); /* Bit 2 is DCache enable */           \
316 CYG_MACRO_END
317
318 // Flush the entire dcache (and then both TLBs, just in case)
319 #define HAL_DCACHE_INVALIDATE_ALL()                                     \
320 CYG_MACRO_START  /* this macro can discard dirty cache lines. */        \
321     asm volatile (                                                      \
322         "mov    r0,#0;"                                                 \
323         "mcr    p15,0,r0,c7,c6,0;" /* flush d-cache */                  \
324         "mcr    p15,0,r0,c8,c7,0;" /* flush i+d-TLBs */                 \
325         :                                                               \
326         :                                                               \
327         : "r0","memory" /* clobber list */);                            \
328 CYG_MACRO_END
329
330 // Synchronize the contents of the cache with memory.
331 #ifdef CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE
332 #define HAL_DCACHE_SYNC()                                               \
333 CYG_MACRO_START                                                         \
334     asm volatile (                                                      \
335         "mov    r0, #0;"                                                \
336         "mcr    p15,0,r0,c7,c10,0;"  /* clean DCache */                 \
337         "1: mrc p15,0,r0,c15,c4,0;"  /* wait for dirty flag to clear */ \
338         "ands   r0,r0,#0x80000000;"                                     \
339         "bne    1b;"                                                    \
340         "mov    r0,#0;"                                                 \
341         "mcr    p15,0,r0,c7,c6,0;"  /* flush DCache */                  \
342         "mcr    p15,0,r0,c7,c10,4;" /* and drain the write buffer */    \
343         :                                                               \
344         :                                                               \
345         : "r0" /* Clobber list */                                       \
346         );                                                              \
347 CYG_MACRO_END
348 #elif defined(CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX)
349 #define HAL_DCACHE_SYNC()                                               \
350 CYG_MACRO_START                                                         \
351     cyg_uint32 _tmp1, _tmp2;                                            \
352     asm volatile (                                                      \
353         "mov    %0, #0;"                                                \
354         "1: "                                                           \
355         "mov    %1, #0;"                                                \
356         "2: "                                                           \
357         "orr    r0,%0,%1;"                                              \
358         "mcr    p15,0,r0,c7,c14,2;"  /* clean index in DCache */        \
359         "add    %1,%1,%2;"                                              \
360         "cmp    %1,%3;"                                                 \
361         "bne    2b;"                                                    \
362         "add    %0,%0,#0x04000000;"  /* get to next index */            \
363         "cmp    %0,#0;"                                                 \
364         "bne    1b;"                                                    \
365         "mcr    p15,0,r0,c7,c10,4;" /* drain the write buffer */        \
366         : "=r" (_tmp1), "=r" (_tmp2)                                    \
367         : "I" (CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX_STEP),            \
368           "I" (CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX_LIMIT)            \
369         : "r0" /* Clobber list */                                       \
370         );                                                              \
371 CYG_MACRO_END
372 #else
373 # error "Don't know how to sync Dcache"
374 #endif
375
376 #else
377
378 #define HAL_DCACHE_ENABLE()
379 #define HAL_DCACHE_DISABLE()
380 #define HAL_DCACHE_IS_ENABLED(_state_) ((_state_) = 0)
381 #define HAL_DCACHE_INVALIDATE_ALL()
382 #define HAL_DCACHE_SYNC()
383
384 #endif
385
386
387 // Set the data cache refill burst size
388 //#define HAL_DCACHE_BURST_SIZE(_size_)
389
390 // Set the data cache write mode
391 //#define HAL_DCACHE_WRITE_MODE( _mode_ )
392
393 #define HAL_DCACHE_WRITETHRU_MODE       0
394 #define HAL_DCACHE_WRITEBACK_MODE       1
395
396 // Get the current writeback mode - or only writeback mode if fixed
397 #define HAL_DCACHE_QUERY_WRITE_MODE( _mode_ ) CYG_MACRO_START           \
398     _mode_ = HAL_DCACHE_WRITEBACK_MODE;                                 \
399 CYG_MACRO_END
400
401 // Load the contents of the given address range into the data cache
402 // and then lock the cache so that it stays there.
403 //#define HAL_DCACHE_LOCK(_base_, _size_)
404
405 // Undo a previous lock operation
406 //#define HAL_DCACHE_UNLOCK(_base_, _size_)
407
408 // Unlock entire cache
409 //#define HAL_DCACHE_UNLOCK_ALL()
410
411 //-----------------------------------------------------------------------------
412 // Data cache line control
413
414 // Allocate cache lines for the given address range without reading its
415 // contents from memory.
416 //#define HAL_DCACHE_ALLOCATE( _base_ , _size_ )
417
418 // Write dirty cache lines to memory and invalidate the cache entries
419 // for the given address range.
420 // ---- this seems not to work despite the documentation ---
421 //#define HAL_DCACHE_FLUSH( _base_ , _size_ )
422 //CYG_MACRO_START
423 //    HAL_DCACHE_STORE( _base_ , _size_ );
424 //    HAL_DCACHE_INVALIDATE( _base_ , _size_ );
425 //CYG_MACRO_END
426
427 // Invalidate cache lines in the given range without writing to memory.
428 // ---- this seems not to work despite the documentation ---
429 //#define HAL_DCACHE_INVALIDATE( _base_ , _size_ )
430 //CYG_MACRO_START
431 //    register int addr, enda;
432 //    for ( addr = (~(HAL_DCACHE_LINE_SIZE - 1)) & (int)(_base_),
433 //              enda = (int)(_base_) + (_size_);
434 //          addr < enda ;
435 //          addr += HAL_DCACHE_LINE_SIZE )
436 //    {
437 //        asm volatile (
438 //                      "mcr  p15,0,%0,c7,c6,1;" /* flush entry away */
439 //                      :
440 //                      : "r"(addr)
441 //                      : "memory"
442 //            );
443 //    }
444 //CYG_MACRO_END
445                           
446 // Write dirty cache lines to memory for the given address range.
447 // ---- this seems not to work despite the documentation ---
448 //#define HAL_DCACHE_STORE( _base_ , _size_ )
449 //CYG_MACRO_START
450 //    register int addr, enda;
451 //    for ( addr = (~(HAL_DCACHE_LINE_SIZE - 1)) & (int)(_base_),
452 //              enda = (int)(_base_) + (_size_);
453 //          addr < enda ;
454 //          addr += HAL_DCACHE_LINE_SIZE )
455 //    {
456 //        asm volatile ("mcr  p15,0,%0,c7,c10,1;" /* push entry to RAM */
457 //                      :
458 //                      : "r"(addr)
459 //                      : "memory"
460 //            );
461 //    }
462 //CYG_MACRO_END
463
464 // Preread the given range into the cache with the intention of reading
465 // from it later.
466 //#define HAL_DCACHE_READ_HINT( _base_ , _size_ )
467
468 // Preread the given range into the cache with the intention of writing
469 // to it later.
470 //#define HAL_DCACHE_WRITE_HINT( _base_ , _size_ )
471
472 // Allocate and zero the cache lines associated with the given range.
473 //#define HAL_DCACHE_ZERO( _base_ , _size_ )
474
475 //-----------------------------------------------------------------------------
476 // Cache controls for safely disabling/reenabling caches around execution
477 // of relocated code.
478
479 #define HAL_FLASH_CACHES_OFF(_d_, _i_)          \
480     CYG_MACRO_START                             \
481     HAL_ICACHE_IS_ENABLED(_i_);                 \
482     HAL_DCACHE_IS_ENABLED(_d_);                 \
483     HAL_ICACHE_INVALIDATE_ALL();                \
484     HAL_ICACHE_DISABLE();                       \
485     HAL_DCACHE_SYNC();                          \
486     HAL_DCACHE_INVALIDATE_ALL();                \
487     HAL_DCACHE_DISABLE();                       \
488     CYG_MACRO_END
489
490 #define HAL_FLASH_CACHES_ON(_d_, _i_)           \
491     CYG_MACRO_START                             \
492     if (_d_) HAL_DCACHE_ENABLE();               \
493     if (_i_) HAL_ICACHE_ENABLE();               \
494     CYG_MACRO_END
495
496 //-----------------------------------------------------------------------------
497 // Virtual<->Physical translations
498 #ifndef HAL_VIRT_TO_PHYS_ADDRESS
499 extern cyg_uint32 hal_virt_to_phys_address(cyg_uint32 phys);
500 #define HAL_VIRT_TO_PHYS_ADDRESS(_va, _pa) \
501    _pa = hal_virt_to_phys_address(_va)
502 #endif
503 //-----------------------------------------------------------------------------
504 #endif // ifndef CYGONCE_HAL_CACHE_H
505 // End of hal_cache.h