/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * linux/arch/arm/mm/arm925.S: MMU functions for ARM925 * * Copyright (C) 1999,2000 ARM Limited * Copyright (C) 2000 Deep Blue Solutions Ltd. * Copyright (C) 2002 RidgeRun, Inc. * Copyright (C) 2002-2003 MontaVista Software, Inc. * * Update for Linux-2.6 and cache flush improvements * Copyright (C) 2004 Nokia Corporation by Tony Lindgren <tony@atomide.com> * * hacked for non-paged-MM by Hyok S. Choi, 2004. * * These are the low level assembler for performing cache and TLB * functions on the arm925. * * CONFIG_CPU_ARM925_CPU_IDLE -> nohlt * * Some additional notes based on deciphering the TI TRM on OMAP-5910: * * NOTE1: The TI925T Configuration Register bit "D-cache clean and flush * entry mode" must be 0 to flush the entries in both segments * at once. This is the default value. See TRM 2-20 and 2-24 for * more information. * * NOTE2: Default is the "D-cache clean and flush entry mode". It looks * like the "Transparent mode" must be on for partial cache flushes * to work in this mode. This mode only works with 16-bit external * memory. See TRM 2-24 for more information. * * NOTE3: Write-back cache flushing seems to be flakey with devices using * direct memory access, such as USB OHCI. The workaround is to use * write-through cache with CONFIG_CPU_DCACHE_WRITETHROUGH (this is * the default for OMAP-1510).
*/
/* * The size of one data cache line.
*/
#define CACHE_DLINESIZE 16
/* * The number of data cache segments.
*/
#define CACHE_DSEGMENTS 2
/* * The number of lines in a cache segment.
*/
#define CACHE_DENTRIES 256
/* * This is the size at which it becomes more efficient to * clean the whole cache, rather than using the individual * cache line maintenance instructions.
*/
#define CACHE_DLIMIT 8192
.text /* * cpu_arm925_proc_init()
*/
SYM_TYPED_FUNC_START(cpu_arm925_proc_init)
ret lr
SYM_FUNC_END(cpu_arm925_proc_init)
/* * cpu_arm925_reset(loc) * * Perform a soft reset of the system. Put the CPU into the * same state as it would be if it had been reset, and branch * to what would be the reset vector. * * loc: location to jump to for soft reset
*/
.align 5
.pushsection .idmap.text, "ax"
SYM_TYPED_FUNC_START(cpu_arm925_reset) /* Send software reset to MPU and DSP */
mov ip, #0xff000000
orr ip, ip, #0x00fe0000
orr ip, ip, #0x0000ce00
mov r4, #1
strh r4, [ip, #0x10]
SYM_FUNC_END(cpu_arm925_reset)
.popsection
/* * flush_icache_all() * * Unconditionally clean and invalidate the entire icache.
*/
SYM_TYPED_FUNC_START(arm925_flush_icache_all)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
ret lr
SYM_FUNC_END(arm925_flush_icache_all)
/* * flush_user_cache_all() * * Clean and invalidate all cache entries in a particular * address space.
*/
SYM_FUNC_ALIAS(arm925_flush_user_cache_all, arm925_flush_kern_cache_all)
/* * flush_kern_cache_all() * * Clean and invalidate the entire cache.
*/
SYM_TYPED_FUNC_START(arm925_flush_kern_cache_all)
mov r2, #VM_EXEC
mov ip, #0
__flush_whole_cache:
#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
#else /* Flush entries in both segments at once, see NOTE1 above */
mov r3, #(CACHE_DENTRIES - 1) << 4 @ 256 entries in segment
2: mcr p15, 0, r3, c7, c14, 2 @ clean+invalidate D index
subs r3, r3, #1 << 4
bcs 2b @ entries 255 to 0
#endif
tst r2, #VM_EXEC
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
ret lr
SYM_FUNC_END(arm925_flush_kern_cache_all)
/* * flush_user_cache_range(start, end, flags) * * Clean and invalidate a range of cache entries in the * specified address range. * * - start - start address (inclusive) * - end - end address (exclusive) * - flags - vm_flags describing address space
*/
SYM_TYPED_FUNC_START(arm925_flush_user_cache_range)
mov ip, #0 sub r3, r1, r0 @ calculate total size
cmp r3, #CACHE_DLIMIT
bgt __flush_whole_cache
1: tst r2, #VM_EXEC
#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
add r0, r0, #CACHE_DLINESIZE
mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
add r0, r0, #CACHE_DLINESIZE
#else
mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
add r0, r0, #CACHE_DLINESIZE
mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
add r0, r0, #CACHE_DLINESIZE
#endif
cmp r0, r1
blo 1b
tst r2, #VM_EXEC
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
ret lr
SYM_FUNC_END(arm925_flush_user_cache_range)
/* * coherent_kern_range(start, end) * * Ensure coherency between the Icache and the Dcache in the * region described by start, end. If you have non-snooping * Harvard caches, you need to implement this function. * * - start - virtual start address * - end - virtual end address
*/
SYM_TYPED_FUNC_START(arm925_coherent_kern_range)
#ifdef CONFIG_CFI_CLANG /* Fallthrough if !CFI */
b arm925_coherent_user_range
#endif
SYM_FUNC_END(arm925_coherent_kern_range)
/* * coherent_user_range(start, end) * * Ensure coherency between the Icache and the Dcache in the * region described by start, end. If you have non-snooping * Harvard caches, you need to implement this function. * * - start - virtual start address * - end - virtual end address
*/
SYM_TYPED_FUNC_START(arm925_coherent_user_range)
bic r0, r0, #CACHE_DLINESIZE - 1
1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
add r0, r0, #CACHE_DLINESIZE
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
mov r0, #0
ret lr
SYM_FUNC_END(arm925_coherent_user_range)
/* * flush_kern_dcache_area(void *addr, size_t size) * * Ensure no D cache aliasing occurs, either with itself or * the I cache * * - addr - kernel address * - size - region size
*/
SYM_TYPED_FUNC_START(arm925_flush_kern_dcache_area)
add r1, r0, r1
1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry
add r0, r0, #CACHE_DLINESIZE
cmp r0, r1
blo 1b
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
mcr p15, 0, r0, c7, c10, 4 @ drain WB
ret lr
SYM_FUNC_END(arm925_flush_kern_dcache_area)
/* * dma_inv_range(start, end) * * Invalidate (discard) the specified virtual address range. * May not write back any entries. If 'start' or 'end' * are not cache line aligned, those lines must be written * back. * * - start - virtual start address * - end - virtual end address * * (same as v4wb)
*/
arm925_dma_inv_range:
#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
tst r0, #CACHE_DLINESIZE - 1
mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
tst r1, #CACHE_DLINESIZE - 1
mcrne p15, 0, r1, c7, c10, 1 @ clean D entry
#endif
bic r0, r0, #CACHE_DLINESIZE - 1
1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
add r0, r0, #CACHE_DLINESIZE
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
ret lr
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.