1 #ifndef CYGONCE_HAL_CACHE_H
2 #define CYGONCE_HAL_CACHE_H
4 //=============================================================================
8 // HAL cache control API
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.
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.
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
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.
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.
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.
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####
47 // Contributors:hmt, jskov
48 // Travis C. Furrer <furrer@mit.edu>
50 // Purpose: Cache control API
51 // Description: The macros defined here provide the HAL APIs for handling
52 // cache control operations.
54 // #include <cyg/hal/hal_cache.h>
58 //####DESCRIPTIONEND####
60 //=============================================================================
62 #include <cyg/infra/cyg_type.h>
63 #include <cyg/hal/hal_mmu.h>
66 //-----------------------------------------------------------------------------
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))
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))
80 # define HAL_WRITE_BUFFER 64
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
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))
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))
97 # define HAL_WRITE_BUFFER 64
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
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))
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))
114 # define HAL_WRITE_BUFFER 64
116 # define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE // has instruction to clean D-cache
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))
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))
129 # define HAL_WRITE_BUFFER 32
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
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))
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))
146 # define HAL_WRITE_BUFFER 32
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
153 # error "No cache details defined"
156 // FIXME: much of the code below should make better use of
157 // the definitions from hal_mmu.h
159 //-----------------------------------------------------------------------------
160 // Global control of Instruction cache
162 #if HAL_ICACHE_SIZE != 0
164 // FIXME: disable/enable instruction streaming?
166 // Enable the instruction cache
167 #define HAL_ICACHE_ENABLE() \
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 */ \
175 "mcr p15,0,r1,c1,c0,0" \
178 : "r1" /* Clobber list */ \
182 // Disable the instruction cache (and invalidate it, required semanitcs)
183 #define HAL_ICACHE_DISABLE() \
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;" \
190 "mcr p15,0,r1,c7,c5,0;" /* flush ICache */ \
191 "nop;" /* next few instructions may be via cache */ \
199 : "r1" /* Clobber list */ \
203 // Query the state of the instruction cache
204 #define HAL_ICACHE_IS_ENABLED(_state_) \
206 register cyg_uint32 reg; \
207 asm volatile ("mrc p15,0,%0,c1,c0,0" \
211 (_state_) = (0 != (0x1000 & reg)); /* Bit 12 is ICache enable */ \
214 // Invalidate the entire cache
215 #define HAL_ICACHE_INVALIDATE_ALL() \
217 /* this macro can discard dirty cache lines (N/A for ICache) */ \
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 */ \
230 : "r1" /* Clobber list */ \
234 // Synchronize the contents of the cache with memory.
235 // (which includes flushing out pending writes)
236 #define HAL_ICACHE_SYNC() \
238 HAL_DCACHE_SYNC(); /* ensure data gets to RAM */ \
239 HAL_ICACHE_INVALIDATE_ALL(); /* forget all we know */ \
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()
252 // Set the instruction cache refill burst size
253 //#define HAL_ICACHE_BURST_SIZE(_size_)
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_)
259 // Undo a previous lock operation
260 //#define HAL_ICACHE_UNLOCK(_base_, _size_)
262 // Unlock entire cache
263 //#define HAL_ICACHE_UNLOCK_ALL()
265 //-----------------------------------------------------------------------------
266 // Instruction cache line control
268 // Invalidate cache lines in the given range without writing to memory.
269 //#define HAL_ICACHE_INVALIDATE( _base_ , _size_ )
271 //-----------------------------------------------------------------------------
272 // Global control of data cache
274 #if HAL_DCACHE_SIZE != 0
276 // Enable the data cache
277 #define HAL_DCACHE_ENABLE() \
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" \
287 : "r1" /* Clobber list */ \
291 // Disable the data cache (and invalidate it, required semanitcs)
292 #define HAL_DCACHE_DISABLE() \
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;" \
300 "mcr p15,0,r1,c7,c6,0" /* clear data cache */ \
303 : "r1" /* Clobber list */ \
307 // Query the state of the data cache
308 #define HAL_DCACHE_IS_ENABLED(_state_) \
311 asm volatile ("mrc p15,0,%0,c1,c0,0;" \
315 (_state_) = (0 != (4 & reg)); /* Bit 2 is DCache enable */ \
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. */ \
323 "mcr p15,0,r0,c7,c6,0;" /* flush d-cache */ \
324 "mcr p15,0,r0,c8,c7,0;" /* flush i+d-TLBs */ \
327 : "r0","memory" /* clobber list */); \
330 // Synchronize the contents of the cache with memory.
331 #ifdef CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE
332 #define HAL_DCACHE_SYNC() \
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;" \
341 "mcr p15,0,r0,c7,c6,0;" /* flush DCache */ \
342 "mcr p15,0,r0,c7,c10,4;" /* and drain the write buffer */ \
345 : "r0" /* Clobber list */ \
348 #elif defined(CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX)
349 #define HAL_DCACHE_SYNC() \
351 cyg_uint32 _tmp1, _tmp2; \
358 "mcr p15,0,r0,c7,c14,2;" /* clean index in DCache */ \
362 "add %0,%0,#0x04000000;" /* get to next index */ \
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 */ \
373 # error "Don't know how to sync Dcache"
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()
387 // Set the data cache refill burst size
388 //#define HAL_DCACHE_BURST_SIZE(_size_)
390 // Set the data cache write mode
391 //#define HAL_DCACHE_WRITE_MODE( _mode_ )
393 #define HAL_DCACHE_WRITETHRU_MODE 0
394 #define HAL_DCACHE_WRITEBACK_MODE 1
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; \
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_)
405 // Undo a previous lock operation
406 //#define HAL_DCACHE_UNLOCK(_base_, _size_)
408 // Unlock entire cache
409 //#define HAL_DCACHE_UNLOCK_ALL()
411 //-----------------------------------------------------------------------------
412 // Data cache line control
414 // Allocate cache lines for the given address range without reading its
415 // contents from memory.
416 //#define HAL_DCACHE_ALLOCATE( _base_ , _size_ )
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_ )
423 // HAL_DCACHE_STORE( _base_ , _size_ );
424 // HAL_DCACHE_INVALIDATE( _base_ , _size_ );
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_ )
431 // register int addr, enda;
432 // for ( addr = (~(HAL_DCACHE_LINE_SIZE - 1)) & (int)(_base_),
433 // enda = (int)(_base_) + (_size_);
435 // addr += HAL_DCACHE_LINE_SIZE )
438 // "mcr p15,0,%0,c7,c6,1;" /* flush entry away */
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_ )
450 // register int addr, enda;
451 // for ( addr = (~(HAL_DCACHE_LINE_SIZE - 1)) & (int)(_base_),
452 // enda = (int)(_base_) + (_size_);
454 // addr += HAL_DCACHE_LINE_SIZE )
456 // asm volatile ("mcr p15,0,%0,c7,c10,1;" /* push entry to RAM */
464 // Preread the given range into the cache with the intention of reading
466 //#define HAL_DCACHE_READ_HINT( _base_ , _size_ )
468 // Preread the given range into the cache with the intention of writing
470 //#define HAL_DCACHE_WRITE_HINT( _base_ , _size_ )
472 // Allocate and zero the cache lines associated with the given range.
473 //#define HAL_DCACHE_ZERO( _base_ , _size_ )
475 //-----------------------------------------------------------------------------
476 // Cache controls for safely disabling/reenabling caches around execution
477 // of relocated code.
479 #define HAL_FLASH_CACHES_OFF(_d_, _i_) \
481 HAL_ICACHE_IS_ENABLED(_i_); \
482 HAL_DCACHE_IS_ENABLED(_d_); \
483 HAL_ICACHE_INVALIDATE_ALL(); \
484 HAL_ICACHE_DISABLE(); \
486 HAL_DCACHE_INVALIDATE_ALL(); \
487 HAL_DCACHE_DISABLE(); \
490 #define HAL_FLASH_CACHES_ON(_d_, _i_) \
492 if (_d_) HAL_DCACHE_ENABLE(); \
493 if (_i_) HAL_ICACHE_ENABLE(); \
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)
503 //-----------------------------------------------------------------------------
504 #endif // ifndef CYGONCE_HAL_CACHE_H
505 // End of hal_cache.h