You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
sh: Optimized cache handling for SH-4/SH-4A caches.
This reworks some of the SH-4 cache handling code to more easily accomodate newer-style caches (particularly for the > direct-mapped case), as well as optimizing some of the old code. Signed-off-by: Richard Curnow <richard.curnow@st.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
committed by
Paul Mundt
parent
fdfc74f9fc
commit
b638d0b921
@@ -4,6 +4,7 @@
|
||||
* CPU init code
|
||||
*
|
||||
* Copyright (C) 2002, 2003 Paul Mundt
|
||||
* Copyright (C) 2003 Richard Curnow
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
@@ -51,7 +52,15 @@ static void __init cache_init(void)
|
||||
ccr = ctrl_inl(CCR);
|
||||
|
||||
/*
|
||||
* If the cache is already enabled .. flush it.
|
||||
* At this point we don't know whether the cache is enabled or not - a
|
||||
* bootloader may have enabled it. There are at least 2 things that
|
||||
* could be dirty in the cache at this point:
|
||||
* 1. kernel command line set up by boot loader
|
||||
* 2. spilled registers from the prolog of this function
|
||||
* => before re-initialising the cache, we must do a purge of the whole
|
||||
* cache out to memory for safety. As long as nothing is spilled
|
||||
* during the loop to lines that have already been done, this is safe.
|
||||
* - RPC
|
||||
*/
|
||||
if (ccr & CCR_CACHE_ENABLE) {
|
||||
unsigned long ways, waysize, addrstart;
|
||||
@@ -98,6 +107,8 @@ static void __init cache_init(void)
|
||||
/* Force EMODE if possible */
|
||||
if (cpu_data->dcache.ways > 1)
|
||||
flags |= CCR_CACHE_EMODE;
|
||||
else
|
||||
flags &= ~CCR_CACHE_EMODE;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SH_WRITETHROUGH
|
||||
@@ -112,6 +123,9 @@ static void __init cache_init(void)
|
||||
/* Turn on OCRAM -- halve the OC */
|
||||
flags |= CCR_CACHE_ORA;
|
||||
cpu_data->dcache.sets >>= 1;
|
||||
|
||||
cpu_data->dcache.way_size = cpu_data->dcache.sets *
|
||||
cpu_data->dcache.linesz;
|
||||
#endif
|
||||
|
||||
ctrl_outl(flags, CCR);
|
||||
|
||||
@@ -113,6 +113,11 @@ int __init detect_cpu_and_cache_system(void)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SH_DIRECT_MAPPED
|
||||
cpu_data->icache.ways = 1;
|
||||
cpu_data->dcache.ways = 1;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* On anything that's not a direct-mapped cache, look to the CVR
|
||||
* for I/D-cache specifics.
|
||||
@@ -125,6 +130,9 @@ int __init detect_cpu_and_cache_system(void)
|
||||
(cpu_data->icache.way_incr - (1 << 5));
|
||||
}
|
||||
|
||||
cpu_data->icache.way_size = cpu_data->icache.sets *
|
||||
cpu_data->icache.linesz;
|
||||
|
||||
if (cpu_data->dcache.ways > 1) {
|
||||
size = sizes[(cvr >> 16) & 0xf];
|
||||
cpu_data->dcache.way_incr = (size >> 1);
|
||||
@@ -133,6 +141,9 @@ int __init detect_cpu_and_cache_system(void)
|
||||
(cpu_data->dcache.way_incr - (1 << 5));
|
||||
}
|
||||
|
||||
cpu_data->dcache.way_size = cpu_data->dcache.sets *
|
||||
cpu_data->dcache.linesz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+430
-87
File diff suppressed because it is too large
Load Diff
+1
-98
@@ -193,102 +193,5 @@ ENTRY(__clear_user_page)
|
||||
nop
|
||||
.L4096: .word 4096
|
||||
|
||||
ENTRY(__flush_cache_4096)
|
||||
mov.l 1f,r3
|
||||
add r6,r3
|
||||
mov r4,r0
|
||||
mov #64,r2
|
||||
shll r2
|
||||
mov #64,r6
|
||||
jmp @r3
|
||||
mov #96,r7
|
||||
.align 2
|
||||
1: .long 2f
|
||||
2:
|
||||
.rept 32
|
||||
mov.l r5,@r0
|
||||
mov.l r5,@(32,r0)
|
||||
mov.l r5,@(r0,r6)
|
||||
mov.l r5,@(r0,r7)
|
||||
add r2,r5
|
||||
add r2,r0
|
||||
.endr
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
rts
|
||||
nop
|
||||
|
||||
ENTRY(__flush_dcache_all)
|
||||
mov.l 2f,r0
|
||||
mov.l 3f,r4
|
||||
and r0,r4 ! r4 = (unsigned long)&empty_zero_page[0] & ~0xffffc000
|
||||
stc sr,r1 ! save SR
|
||||
mov.l 4f,r2
|
||||
or r1,r2
|
||||
mov #32,r3
|
||||
shll2 r3
|
||||
1:
|
||||
ldc r2,sr ! set BL bit
|
||||
movca.l r0,@r4
|
||||
ocbi @r4
|
||||
add #32,r4
|
||||
movca.l r0,@r4
|
||||
ocbi @r4
|
||||
add #32,r4
|
||||
movca.l r0,@r4
|
||||
ocbi @r4
|
||||
add #32,r4
|
||||
movca.l r0,@r4
|
||||
ocbi @r4
|
||||
ldc r1,sr ! restore SR
|
||||
dt r3
|
||||
bf/s 1b
|
||||
add #32,r4
|
||||
|
||||
rts
|
||||
nop
|
||||
.align 2
|
||||
2: .long 0xffffc000
|
||||
3: .long empty_zero_page
|
||||
4: .long 0x10000000 ! BL bit
|
||||
|
||||
/* __flush_cache_4096_all(unsigned long addr) */
|
||||
ENTRY(__flush_cache_4096_all)
|
||||
mov.l 2f,r0
|
||||
mov.l 3f,r2
|
||||
and r0,r2
|
||||
or r2,r4 ! r4 = addr | (unsigned long)&empty_zero_page[0] & ~0x3fff
|
||||
stc sr,r1 ! save SR
|
||||
mov.l 4f,r2
|
||||
or r1,r2
|
||||
mov #32,r3
|
||||
1:
|
||||
ldc r2,sr ! set BL bit
|
||||
movca.l r0,@r4
|
||||
ocbi @r4
|
||||
add #32,r4
|
||||
movca.l r0,@r4
|
||||
ocbi @r4
|
||||
add #32,r4
|
||||
movca.l r0,@r4
|
||||
ocbi @r4
|
||||
add #32,r4
|
||||
movca.l r0,@r4
|
||||
ocbi @r4
|
||||
ldc r1,sr ! restore SR
|
||||
dt r3
|
||||
bf/s 1b
|
||||
add #32,r4
|
||||
|
||||
rts
|
||||
nop
|
||||
.align 2
|
||||
2: .long 0xffffc000
|
||||
3: .long empty_zero_page
|
||||
4: .long 0x10000000 ! BL bit
|
||||
#endif
|
||||
|
||||
|
||||
+18
-4
@@ -23,15 +23,29 @@
|
||||
#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
|
||||
|
||||
struct cache_info {
|
||||
unsigned int ways;
|
||||
unsigned int sets;
|
||||
unsigned int linesz;
|
||||
unsigned int ways; /* Number of cache ways */
|
||||
unsigned int sets; /* Number of cache sets */
|
||||
unsigned int linesz; /* Cache line size (bytes) */
|
||||
|
||||
unsigned int way_size; /* sets * line size */
|
||||
|
||||
/*
|
||||
* way_incr is the address offset for accessing the next way
|
||||
* in memory mapped cache array ops.
|
||||
*/
|
||||
unsigned int way_incr;
|
||||
|
||||
unsigned int entry_shift;
|
||||
unsigned int entry_mask;
|
||||
|
||||
/*
|
||||
* Compute a mask which selects the address bits which overlap between
|
||||
* 1. those used to select the cache set during indexing
|
||||
* 2. those in the physical page number.
|
||||
*/
|
||||
unsigned int alias_mask;
|
||||
|
||||
unsigned int n_aliases; /* Number of aliases */
|
||||
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user