Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  *  linux/arch/arm/mm/arm946.S: utility functions for ARM946E-S
0004  *
0005  *  Copyright (C) 2004-2006 Hyok S. Choi (hyok.choi@samsung.com)
0006  *
0007  *  (Many of cache codes are from proc-arm926.S)
0008  */
0009 #include <linux/linkage.h>
0010 #include <linux/init.h>
0011 #include <linux/pgtable.h>
0012 #include <asm/assembler.h>
0013 #include <asm/hwcap.h>
0014 #include <asm/pgtable-hwdef.h>
0015 #include <asm/ptrace.h>
0016 #include "proc-macros.S"
0017 
0018 /*
0019  * ARM946E-S is synthesizable to have 0KB to 1MB sized D-Cache,
0020  * comprising 256 lines of 32 bytes (8 words).
0021  */
0022 #define CACHE_DSIZE (CONFIG_CPU_DCACHE_SIZE) /* typically 8KB. */
0023 #define CACHE_DLINESIZE 32          /* fixed */
0024 #define CACHE_DSEGMENTS 4           /* fixed */
0025 #define CACHE_DENTRIES  (CACHE_DSIZE / CACHE_DSEGMENTS / CACHE_DLINESIZE)
0026 #define CACHE_DLIMIT    (CACHE_DSIZE * 4)   /* benchmark needed */
0027 
0028     .text
0029 /*
0030  * cpu_arm946_proc_init()
0031  * cpu_arm946_switch_mm()
0032  *
0033  * These are not required.
0034  */
0035 ENTRY(cpu_arm946_proc_init)
0036 ENTRY(cpu_arm946_switch_mm)
0037     ret lr
0038 
0039 /*
0040  * cpu_arm946_proc_fin()
0041  */
0042 ENTRY(cpu_arm946_proc_fin)
0043     mrc p15, 0, r0, c1, c0, 0       @ ctrl register
0044     bic r0, r0, #0x00001000     @ i-cache
0045     bic r0, r0, #0x00000004     @ d-cache
0046     mcr p15, 0, r0, c1, c0, 0       @ disable caches
0047     ret lr
0048 
0049 /*
0050  * cpu_arm946_reset(loc)
0051  * Params  : r0 = address to jump to
0052  * Notes   : This sets up everything for a reset
0053  */
0054     .pushsection    .idmap.text, "ax"
0055 ENTRY(cpu_arm946_reset)
0056     mov ip, #0
0057     mcr p15, 0, ip, c7, c5, 0       @ flush I cache
0058     mcr p15, 0, ip, c7, c6, 0       @ flush D cache
0059     mcr p15, 0, ip, c7, c10, 4      @ drain WB
0060     mrc p15, 0, ip, c1, c0, 0       @ ctrl register
0061     bic ip, ip, #0x00000005     @ .............c.p
0062     bic ip, ip, #0x00001000     @ i-cache
0063     mcr p15, 0, ip, c1, c0, 0       @ ctrl register
0064     ret r0
0065 ENDPROC(cpu_arm946_reset)
0066     .popsection
0067 
0068 /*
0069  * cpu_arm946_do_idle()
0070  */
0071     .align  5
0072 ENTRY(cpu_arm946_do_idle)
0073     mcr p15, 0, r0, c7, c0, 4       @ Wait for interrupt
0074     ret lr
0075 
0076 /*
0077  *  flush_icache_all()
0078  *
0079  *  Unconditionally clean and invalidate the entire icache.
0080  */
0081 ENTRY(arm946_flush_icache_all)
0082     mov r0, #0
0083     mcr p15, 0, r0, c7, c5, 0       @ invalidate I cache
0084     ret lr
0085 ENDPROC(arm946_flush_icache_all)
0086 
0087 /*
0088  *  flush_user_cache_all()
0089  */
0090 ENTRY(arm946_flush_user_cache_all)
0091     /* FALLTHROUGH */
0092 
0093 /*
0094  *  flush_kern_cache_all()
0095  *
0096  *  Clean and invalidate the entire cache.
0097  */
0098 ENTRY(arm946_flush_kern_cache_all)
0099     mov r2, #VM_EXEC
0100     mov ip, #0
0101 __flush_whole_cache:
0102 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
0103     mcr p15, 0, ip, c7, c6, 0       @ flush D cache
0104 #else
0105     mov r1, #(CACHE_DSEGMENTS - 1) << 29 @ 4 segments
0106 1:  orr r3, r1, #(CACHE_DENTRIES - 1) << 4 @ n entries
0107 2:  mcr p15, 0, r3, c7, c14, 2      @ clean/flush D index
0108     subs    r3, r3, #1 << 4
0109     bcs 2b              @ entries n to 0
0110     subs    r1, r1, #1 << 29
0111     bcs 1b              @ segments 3 to 0
0112 #endif
0113     tst r2, #VM_EXEC
0114     mcrne   p15, 0, ip, c7, c5, 0       @ flush I cache
0115     mcrne   p15, 0, ip, c7, c10, 4      @ drain WB
0116     ret lr
0117 
0118 /*
0119  *  flush_user_cache_range(start, end, flags)
0120  *
0121  *  Clean and invalidate a range of cache entries in the
0122  *  specified address range.
0123  *
0124  *  - start - start address (inclusive)
0125  *  - end   - end address (exclusive)
0126  *  - flags - vm_flags describing address space
0127  * (same as arm926)
0128  */
0129 ENTRY(arm946_flush_user_cache_range)
0130     mov ip, #0
0131     sub r3, r1, r0          @ calculate total size
0132     cmp r3, #CACHE_DLIMIT
0133     bhs __flush_whole_cache
0134 
0135 1:  tst r2, #VM_EXEC
0136 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
0137     mcr p15, 0, r0, c7, c6, 1       @ invalidate D entry
0138     mcrne   p15, 0, r0, c7, c5, 1       @ invalidate I entry
0139     add r0, r0, #CACHE_DLINESIZE
0140     mcr p15, 0, r0, c7, c6, 1       @ invalidate D entry
0141     mcrne   p15, 0, r0, c7, c5, 1       @ invalidate I entry
0142     add r0, r0, #CACHE_DLINESIZE
0143 #else
0144     mcr p15, 0, r0, c7, c14, 1      @ clean and invalidate D entry
0145     mcrne   p15, 0, r0, c7, c5, 1       @ invalidate I entry
0146     add r0, r0, #CACHE_DLINESIZE
0147     mcr p15, 0, r0, c7, c14, 1      @ clean and invalidate D entry
0148     mcrne   p15, 0, r0, c7, c5, 1       @ invalidate I entry
0149     add r0, r0, #CACHE_DLINESIZE
0150 #endif
0151     cmp r0, r1
0152     blo 1b
0153     tst r2, #VM_EXEC
0154     mcrne   p15, 0, ip, c7, c10, 4      @ drain WB
0155     ret lr
0156 
0157 /*
0158  *  coherent_kern_range(start, end)
0159  *
0160  *  Ensure coherency between the Icache and the Dcache in the
0161  *  region described by start, end.  If you have non-snooping
0162  *  Harvard caches, you need to implement this function.
0163  *
0164  *  - start - virtual start address
0165  *  - end   - virtual end address
0166  */
0167 ENTRY(arm946_coherent_kern_range)
0168     /* FALLTHROUGH */
0169 
0170 /*
0171  *  coherent_user_range(start, end)
0172  *
0173  *  Ensure coherency between the Icache and the Dcache in the
0174  *  region described by start, end.  If you have non-snooping
0175  *  Harvard caches, you need to implement this function.
0176  *
0177  *  - start - virtual start address
0178  *  - end   - virtual end address
0179  * (same as arm926)
0180  */
0181 ENTRY(arm946_coherent_user_range)
0182     bic r0, r0, #CACHE_DLINESIZE - 1
0183 1:  mcr p15, 0, r0, c7, c10, 1      @ clean D entry
0184     mcr p15, 0, r0, c7, c5, 1       @ invalidate I entry
0185     add r0, r0, #CACHE_DLINESIZE
0186     cmp r0, r1
0187     blo 1b
0188     mcr p15, 0, r0, c7, c10, 4      @ drain WB
0189     mov r0, #0
0190     ret lr
0191 
0192 /*
0193  *  flush_kern_dcache_area(void *addr, size_t size)
0194  *
0195  *  Ensure no D cache aliasing occurs, either with itself or
0196  *  the I cache
0197  *
0198  *  - addr  - kernel address
0199  *  - size  - region size
0200  * (same as arm926)
0201  */
0202 ENTRY(arm946_flush_kern_dcache_area)
0203     add r1, r0, r1
0204 1:  mcr p15, 0, r0, c7, c14, 1      @ clean+invalidate D entry
0205     add r0, r0, #CACHE_DLINESIZE
0206     cmp r0, r1
0207     blo 1b
0208     mov r0, #0
0209     mcr p15, 0, r0, c7, c5, 0       @ invalidate I cache
0210     mcr p15, 0, r0, c7, c10, 4      @ drain WB
0211     ret lr
0212 
0213 /*
0214  *  dma_inv_range(start, end)
0215  *
0216  *  Invalidate (discard) the specified virtual address range.
0217  *  May not write back any entries.  If 'start' or 'end'
0218  *  are not cache line aligned, those lines must be written
0219  *  back.
0220  *
0221  *  - start - virtual start address
0222  *  - end   - virtual end address
0223  * (same as arm926)
0224  */
0225 arm946_dma_inv_range:
0226 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
0227     tst r0, #CACHE_DLINESIZE - 1
0228     mcrne   p15, 0, r0, c7, c10, 1      @ clean D entry
0229     tst r1, #CACHE_DLINESIZE - 1
0230     mcrne   p15, 0, r1, c7, c10, 1      @ clean D entry
0231 #endif
0232     bic r0, r0, #CACHE_DLINESIZE - 1
0233 1:  mcr p15, 0, r0, c7, c6, 1       @ invalidate D entry
0234     add r0, r0, #CACHE_DLINESIZE
0235     cmp r0, r1
0236     blo 1b
0237     mcr p15, 0, r0, c7, c10, 4      @ drain WB
0238     ret lr
0239 
0240 /*
0241  *  dma_clean_range(start, end)
0242  *
0243  *  Clean the specified virtual address range.
0244  *
0245  *  - start - virtual start address
0246  *  - end   - virtual end address
0247  *
0248  * (same as arm926)
0249  */
0250 arm946_dma_clean_range:
0251 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
0252     bic r0, r0, #CACHE_DLINESIZE - 1
0253 1:  mcr p15, 0, r0, c7, c10, 1      @ clean D entry
0254     add r0, r0, #CACHE_DLINESIZE
0255     cmp r0, r1
0256     blo 1b
0257 #endif
0258     mcr p15, 0, r0, c7, c10, 4      @ drain WB
0259     ret lr
0260 
0261 /*
0262  *  dma_flush_range(start, end)
0263  *
0264  *  Clean and invalidate the specified virtual address range.
0265  *
0266  *  - start - virtual start address
0267  *  - end   - virtual end address
0268  *
0269  * (same as arm926)
0270  */
0271 ENTRY(arm946_dma_flush_range)
0272     bic r0, r0, #CACHE_DLINESIZE - 1
0273 1:
0274 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
0275     mcr p15, 0, r0, c7, c14, 1      @ clean+invalidate D entry
0276 #else
0277     mcr p15, 0, r0, c7, c6, 1       @ invalidate D entry
0278 #endif
0279     add r0, r0, #CACHE_DLINESIZE
0280     cmp r0, r1
0281     blo 1b
0282     mcr p15, 0, r0, c7, c10, 4      @ drain WB
0283     ret lr
0284 
0285 /*
0286  *  dma_map_area(start, size, dir)
0287  *  - start - kernel virtual start address
0288  *  - size  - size of region
0289  *  - dir   - DMA direction
0290  */
0291 ENTRY(arm946_dma_map_area)
0292     add r1, r1, r0
0293     cmp r2, #DMA_TO_DEVICE
0294     beq arm946_dma_clean_range
0295     bcs arm946_dma_inv_range
0296     b   arm946_dma_flush_range
0297 ENDPROC(arm946_dma_map_area)
0298 
0299 /*
0300  *  dma_unmap_area(start, size, dir)
0301  *  - start - kernel virtual start address
0302  *  - size  - size of region
0303  *  - dir   - DMA direction
0304  */
0305 ENTRY(arm946_dma_unmap_area)
0306     ret lr
0307 ENDPROC(arm946_dma_unmap_area)
0308 
0309     .globl  arm946_flush_kern_cache_louis
0310     .equ    arm946_flush_kern_cache_louis, arm946_flush_kern_cache_all
0311 
0312     @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
0313     define_cache_functions arm946
0314 
0315 ENTRY(cpu_arm946_dcache_clean_area)
0316 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
0317 1:  mcr p15, 0, r0, c7, c10, 1      @ clean D entry
0318     add r0, r0, #CACHE_DLINESIZE
0319     subs    r1, r1, #CACHE_DLINESIZE
0320     bhi 1b
0321 #endif
0322     mcr p15, 0, r0, c7, c10, 4      @ drain WB
0323     ret lr
0324 
0325     .type   __arm946_setup, #function
0326 __arm946_setup:
0327     mov r0, #0
0328     mcr p15, 0, r0, c7, c5, 0       @ invalidate I cache
0329     mcr p15, 0, r0, c7, c6, 0       @ invalidate D cache
0330     mcr p15, 0, r0, c7, c10, 4      @ drain WB
0331 
0332     mcr p15, 0, r0, c6, c3, 0       @ disable memory region 3~7
0333     mcr p15, 0, r0, c6, c4, 0
0334     mcr p15, 0, r0, c6, c5, 0
0335     mcr p15, 0, r0, c6, c6, 0
0336     mcr p15, 0, r0, c6, c7, 0
0337 
0338     mov r0, #0x0000003F         @ base = 0, size = 4GB
0339     mcr p15, 0, r0, c6, c0, 0       @ set region 0, default
0340 
0341     ldr r0, =(CONFIG_DRAM_BASE & 0xFFFFF000) @ base[31:12] of RAM
0342     ldr r7, =CONFIG_DRAM_SIZE       @ size of RAM (must be >= 4KB)
0343     pr_val  r3, r0, r7, #1
0344     mcr p15, 0, r3, c6, c1, 0
0345 
0346     ldr r0, =(CONFIG_FLASH_MEM_BASE & 0xFFFFF000) @ base[31:12] of FLASH
0347     ldr r7, =CONFIG_FLASH_SIZE      @ size of FLASH (must be >= 4KB)
0348     pr_val  r3, r0, r7, #1
0349     mcr p15, 0, r3, c6, c2, 0
0350 
0351     mov r0, #0x06
0352     mcr p15, 0, r0, c2, c0, 0       @ region 1,2 d-cacheable
0353     mcr p15, 0, r0, c2, c0, 1       @ region 1,2 i-cacheable
0354 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
0355     mov r0, #0x00           @ disable whole write buffer
0356 #else
0357     mov r0, #0x02           @ region 1 write bufferred
0358 #endif
0359     mcr p15, 0, r0, c3, c0, 0
0360 
0361 /*
0362  *  Access Permission Settings for future permission control by PU.
0363  *
0364  *              priv.   user
0365  *  region 0 (whole)    rw  --  : b0001
0366  *  region 1 (RAM)      rw  rw  : b0011
0367  *  region 2 (FLASH)    rw  r-  : b0010
0368  *  region 3~7 (none)   --  --  : b0000
0369  */
0370     mov r0, #0x00000031
0371     orr r0, r0, #0x00000200
0372     mcr p15, 0, r0, c5, c0, 2       @ set data access permission
0373     mcr p15, 0, r0, c5, c0, 3       @ set inst. access permission
0374 
0375     mrc p15, 0, r0, c1, c0      @ get control register
0376     orr r0, r0, #0x00001000     @ I-cache
0377     orr r0, r0, #0x00000005     @ MPU/D-cache
0378 #ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
0379     orr r0, r0, #0x00004000     @ .1.. .... .... ....
0380 #endif
0381     ret lr
0382 
0383     .size   __arm946_setup, . - __arm946_setup
0384 
0385     __INITDATA
0386 
0387     @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
0388     define_processor_functions arm946, dabort=nommu_early_abort, pabort=legacy_pabort, nommu=1
0389 
0390     .section ".rodata"
0391 
0392     string  cpu_arch_name, "armv5te"
0393     string  cpu_elf_name, "v5t"
0394     string  cpu_arm946_name, "ARM946E-S"
0395 
0396     .align
0397 
0398     .section ".proc.info.init", "a"
0399     .type   __arm946_proc_info,#object
0400 __arm946_proc_info:
0401     .long   0x41009460
0402     .long   0xff00fff0
0403     .long   0
0404     .long   0
0405     initfn  __arm946_setup, __arm946_proc_info
0406     .long   cpu_arch_name
0407     .long   cpu_elf_name
0408     .long   HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
0409     .long   cpu_arm946_name
0410     .long   arm946_processor_functions
0411     .long   0
0412     .long   0
0413     .long   arm946_cache_fns
0414     .size   __arm946_proc_info, . - __arm946_proc_info
0415