Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  *  linux/arch/arm/mm/cache-fa.S
0004  *
0005  *  Copyright (C) 2005 Faraday Corp.
0006  *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
0007  *
0008  * Based on cache-v4wb.S:
0009  *  Copyright (C) 1997-2002 Russell king
0010  *
0011  *  Processors: FA520 FA526 FA626   
0012  */
0013 #include <linux/linkage.h>
0014 #include <linux/init.h>
0015 #include <asm/assembler.h>
0016 #include <asm/memory.h>
0017 #include <asm/page.h>
0018 
0019 #include "proc-macros.S"
0020 
0021 /*
0022  * The size of one data cache line.
0023  */
0024 #define CACHE_DLINESIZE 16
0025 
0026 /*
0027  * The total size of the data cache.
0028  */
0029 #ifdef CONFIG_ARCH_GEMINI
0030 #define CACHE_DSIZE 8192
0031 #else
0032 #define CACHE_DSIZE 16384 
0033 #endif 
0034 
0035 /* FIXME: put optimal value here. Current one is just estimation */
0036 #define CACHE_DLIMIT    (CACHE_DSIZE * 2)
0037 
0038 /*
0039  *  flush_icache_all()
0040  *
0041  *  Unconditionally clean and invalidate the entire icache.
0042  */
0043 ENTRY(fa_flush_icache_all)
0044     mov r0, #0
0045     mcr p15, 0, r0, c7, c5, 0       @ invalidate I cache
0046     ret lr
0047 ENDPROC(fa_flush_icache_all)
0048 
0049 /*
0050  *  flush_user_cache_all()
0051  *
0052  *  Clean and invalidate all cache entries in a particular address
0053  *  space.
0054  */
0055 ENTRY(fa_flush_user_cache_all)
0056     /* FALLTHROUGH */
0057 /*
0058  *  flush_kern_cache_all()
0059  *
0060  *  Clean and invalidate the entire cache.
0061  */
0062 ENTRY(fa_flush_kern_cache_all)
0063     mov ip, #0
0064     mov r2, #VM_EXEC
0065 __flush_whole_cache:
0066     mcr p15, 0, ip, c7, c14, 0      @ clean/invalidate D cache
0067     tst r2, #VM_EXEC
0068     mcrne   p15, 0, ip, c7, c5, 0       @ invalidate I cache
0069     mcrne   p15, 0, ip, c7, c5, 6       @ invalidate BTB
0070     mcrne   p15, 0, ip, c7, c10, 4      @ drain write buffer
0071     mcrne   p15, 0, ip, c7, c5, 4       @ prefetch flush
0072     ret lr
0073 
0074 /*
0075  *  flush_user_cache_range(start, end, flags)
0076  *
0077  *  Invalidate a range of cache entries in the specified
0078  *  address space.
0079  *
0080  *  - start - start address (inclusive, page aligned)
0081  *  - end   - end address (exclusive, page aligned)
0082  *  - flags - vma_area_struct flags describing address space
0083  */
0084 ENTRY(fa_flush_user_cache_range)
0085     mov ip, #0
0086     sub r3, r1, r0          @ calculate total size
0087     cmp r3, #CACHE_DLIMIT       @ total size >= limit?
0088     bhs __flush_whole_cache     @ flush whole D cache
0089 
0090 1:  tst r2, #VM_EXEC
0091     mcrne   p15, 0, r0, c7, c5, 1       @ invalidate I line
0092     mcr p15, 0, r0, c7, c14, 1      @ clean and invalidate D entry
0093     add r0, r0, #CACHE_DLINESIZE
0094     cmp r0, r1
0095     blo 1b
0096     tst r2, #VM_EXEC
0097     mcrne   p15, 0, ip, c7, c5, 6       @ invalidate BTB
0098     mcrne   p15, 0, ip, c7, c10, 4      @ data write barrier
0099     mcrne   p15, 0, ip, c7, c5, 4       @ prefetch flush
0100     ret lr
0101 
0102 /*
0103  *  coherent_kern_range(start, end)
0104  *
0105  *  Ensure coherency between the Icache and the Dcache in the
0106  *  region described by start.  If you have non-snooping
0107  *  Harvard caches, you need to implement this function.
0108  *
0109  *  - start  - virtual start address
0110  *  - end    - virtual end address
0111  */
0112 ENTRY(fa_coherent_kern_range)
0113     /* fall through */
0114 
0115 /*
0116  *  coherent_user_range(start, end)
0117  *
0118  *  Ensure coherency between the Icache and the Dcache in the
0119  *  region described by start.  If you have non-snooping
0120  *  Harvard caches, you need to implement this function.
0121  *
0122  *  - start  - virtual start address
0123  *  - end    - virtual end address
0124  */
0125 ENTRY(fa_coherent_user_range)
0126     bic r0, r0, #CACHE_DLINESIZE - 1
0127 1:  mcr p15, 0, r0, c7, c14, 1      @ clean and invalidate D entry
0128     mcr p15, 0, r0, c7, c5, 1       @ invalidate I entry
0129     add r0, r0, #CACHE_DLINESIZE
0130     cmp r0, r1
0131     blo 1b
0132     mov r0, #0
0133     mcr p15, 0, r0, c7, c5, 6       @ invalidate BTB
0134     mcr p15, 0, r0, c7, c10, 4      @ drain write buffer
0135     mcr p15, 0, r0, c7, c5, 4       @ prefetch flush
0136     ret lr
0137 
0138 /*
0139  *  flush_kern_dcache_area(void *addr, size_t size)
0140  *
0141  *  Ensure that the data held in the page kaddr is written back
0142  *  to the page in question.
0143  *
0144  *  - addr  - kernel address
0145  *  - size  - size of region
0146  */
0147 ENTRY(fa_flush_kern_dcache_area)
0148     add r1, r0, r1
0149 1:  mcr p15, 0, r0, c7, c14, 1      @ clean & invalidate D line
0150     add r0, r0, #CACHE_DLINESIZE
0151     cmp r0, r1
0152     blo 1b
0153     mov r0, #0
0154     mcr p15, 0, r0, c7, c5, 0       @ invalidate I cache
0155     mcr p15, 0, r0, c7, c10, 4      @ drain write buffer
0156     ret lr
0157 
0158 /*
0159  *  dma_inv_range(start, end)
0160  *
0161  *  Invalidate (discard) the specified virtual address range.
0162  *  May not write back any entries.  If 'start' or 'end'
0163  *  are not cache line aligned, those lines must be written
0164  *  back.
0165  *
0166  *  - start  - virtual start address
0167  *  - end    - virtual end address
0168  */
0169 fa_dma_inv_range:
0170     tst r0, #CACHE_DLINESIZE - 1
0171     bic r0, r0, #CACHE_DLINESIZE - 1
0172     mcrne   p15, 0, r0, c7, c14, 1      @ clean & invalidate D entry
0173     tst r1, #CACHE_DLINESIZE - 1
0174     bic r1, r1, #CACHE_DLINESIZE - 1
0175     mcrne   p15, 0, r1, c7, c14, 1      @ clean & invalidate D entry
0176 1:  mcr p15, 0, r0, c7, c6, 1       @ invalidate D entry
0177     add r0, r0, #CACHE_DLINESIZE
0178     cmp r0, r1
0179     blo 1b
0180     mov r0, #0
0181     mcr p15, 0, r0, c7, c10, 4      @ drain write buffer
0182     ret lr
0183 
0184 /*
0185  *  dma_clean_range(start, end)
0186  *
0187  *  Clean (write back) the specified virtual address range.
0188  *
0189  *  - start  - virtual start address
0190  *  - end    - virtual end address
0191  */
0192 fa_dma_clean_range:
0193     bic r0, r0, #CACHE_DLINESIZE - 1
0194 1:  mcr p15, 0, r0, c7, c10, 1      @ clean D entry
0195     add r0, r0, #CACHE_DLINESIZE
0196     cmp r0, r1
0197     blo 1b
0198     mov r0, #0  
0199     mcr p15, 0, r0, c7, c10, 4      @ drain write buffer
0200     ret lr
0201 
0202 /*
0203  *  dma_flush_range(start,end)
0204  *  - start   - virtual start address of region
0205  *  - end     - virtual end address of region
0206  */
0207 ENTRY(fa_dma_flush_range)
0208     bic r0, r0, #CACHE_DLINESIZE - 1
0209 1:  mcr p15, 0, r0, c7, c14, 1      @ clean & invalidate D entry
0210     add r0, r0, #CACHE_DLINESIZE
0211     cmp r0, r1
0212     blo 1b
0213     mov r0, #0  
0214     mcr p15, 0, r0, c7, c10, 4      @ drain write buffer
0215     ret lr
0216 
0217 /*
0218  *  dma_map_area(start, size, dir)
0219  *  - start - kernel virtual start address
0220  *  - size  - size of region
0221  *  - dir   - DMA direction
0222  */
0223 ENTRY(fa_dma_map_area)
0224     add r1, r1, r0
0225     cmp r2, #DMA_TO_DEVICE
0226     beq fa_dma_clean_range
0227     bcs fa_dma_inv_range
0228     b   fa_dma_flush_range
0229 ENDPROC(fa_dma_map_area)
0230 
0231 /*
0232  *  dma_unmap_area(start, size, dir)
0233  *  - start - kernel virtual start address
0234  *  - size  - size of region
0235  *  - dir   - DMA direction
0236  */
0237 ENTRY(fa_dma_unmap_area)
0238     ret lr
0239 ENDPROC(fa_dma_unmap_area)
0240 
0241     .globl  fa_flush_kern_cache_louis
0242     .equ    fa_flush_kern_cache_louis, fa_flush_kern_cache_all
0243 
0244     __INITDATA
0245 
0246     @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
0247     define_cache_functions fa