Skip to content

Commit

Permalink
powerpc/cache: add cache flush operation for various e500
Browse files Browse the repository at this point in the history
Various e500 core have different cache architecture, so they
need different cache flush operations. Therefore, add a callback
function cpu_flush_caches to the struct cpu_spec. The cache flush
operation for the specific kind of e500 is selected at init time.
The callback function will flush all caches inside the current cpu.

Signed-off-by: Chenhui Zhao <chenhui.zhao@freescale.com>
Signed-off-by: Tang Yuantian <Yuantian.Tang@feescale.com>
Signed-off-by: Scott Wood <oss@buserror.net>
  • Loading branch information
chenhui zhao authored and Scott Wood committed Mar 5, 2016
1 parent ebb9d30 commit e7affb1
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 78 deletions.
2 changes: 0 additions & 2 deletions arch/powerpc/include/asm/cacheflush.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ extern void flush_dcache_page(struct page *page);
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)

extern void __flush_disable_L1(void);

extern void flush_icache_range(unsigned long, unsigned long);
extern void flush_icache_user_range(struct vm_area_struct *vma,
struct page *page, unsigned long addr,
Expand Down
8 changes: 8 additions & 0 deletions arch/powerpc/include/asm/cputable.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ extern int machine_check_e500(struct pt_regs *regs);
extern int machine_check_e200(struct pt_regs *regs);
extern int machine_check_47x(struct pt_regs *regs);

extern void cpu_down_flush_e500v2(void);
extern void cpu_down_flush_e500mc(void);
extern void cpu_down_flush_e5500(void);
extern void cpu_down_flush_e6500(void);

/* NOTE WELL: Update identify_cpu() if fields are added or removed! */
struct cpu_spec {
/* CPU is matched via (PVR & pvr_mask) == pvr_value */
Expand All @@ -59,6 +64,9 @@ struct cpu_spec {
unsigned int icache_bsize;
unsigned int dcache_bsize;

/* flush caches inside the current cpu */
void (*cpu_down_flush)(void);

/* number of performance monitor counters */
unsigned int num_pmcs;
enum powerpc_pmc_type pmc_type;
Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ int main(void)
DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features));
DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
DEFINE(CPU_SPEC_RESTORE, offsetof(struct cpu_spec, cpu_restore));
DEFINE(CPU_DOWN_FLUSH, offsetof(struct cpu_spec, cpu_down_flush));

DEFINE(pbe_address, offsetof(struct pbe, address));
DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
Expand Down
112 changes: 112 additions & 0 deletions arch/powerpc/kernel/cpu_setup_fsl_booke.S
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@
*
*/

#include <asm/page.h>
#include <asm/processor.h>
#include <asm/cputable.h>
#include <asm/ppc_asm.h>
#include <asm/mmu-book3e.h>
#include <asm/asm-offsets.h>
#include <asm/mpc85xx.h>

_GLOBAL(__e500_icache_setup)
mfspr r0, SPRN_L1CSR1
Expand Down Expand Up @@ -233,3 +235,113 @@ _GLOBAL(__setup_cpu_e5500)
mtlr r5
blr
#endif

/* flush L1 date cache, it can apply to e500v2, e500mc and e5500 */
_GLOBAL(flush_dcache_L1)
mfmsr r10
wrteei 0

mfspr r3,SPRN_L1CFG0
rlwinm r5,r3,9,3 /* Extract cache block size */
twlgti r5,1 /* Only 32 and 64 byte cache blocks
* are currently defined.
*/
li r4,32
subfic r6,r5,2 /* r6 = log2(1KiB / cache block size) -
* log2(number of ways)
*/
slw r5,r4,r5 /* r5 = cache block size */

rlwinm r7,r3,0,0xff /* Extract number of KiB in the cache */
mulli r7,r7,13 /* An 8-way cache will require 13
* loads per set.
*/
slw r7,r7,r6

/* save off HID0 and set DCFA */
mfspr r8,SPRN_HID0
ori r9,r8,HID0_DCFA@l
mtspr SPRN_HID0,r9
isync

LOAD_REG_IMMEDIATE(r6, KERNELBASE)
mr r4, r6
mtctr r7

1: lwz r3,0(r4) /* Load... */
add r4,r4,r5
bdnz 1b

msync
mr r4, r6
mtctr r7

1: dcbf 0,r4 /* ...and flush. */
add r4,r4,r5
bdnz 1b

/* restore HID0 */
mtspr SPRN_HID0,r8
isync

wrtee r10

blr

has_L2_cache:
/* skip L2 cache on P2040/P2040E as they have no L2 cache */
mfspr r3, SPRN_SVR
/* shift right by 8 bits and clear E bit of SVR */
rlwinm r4, r3, 24, ~0x800

lis r3, SVR_P2040@h
ori r3, r3, SVR_P2040@l
cmpw r4, r3
beq 1f

li r3, 1
blr
1:
li r3, 0
blr

/* flush backside L2 cache */
flush_backside_L2_cache:
mflr r10
bl has_L2_cache
mtlr r10
cmpwi r3, 0
beq 2f

/* Flush the L2 cache */
mfspr r3, SPRN_L2CSR0
ori r3, r3, L2CSR0_L2FL@l
msync
isync
mtspr SPRN_L2CSR0,r3
isync

/* check if it is complete */
1: mfspr r3,SPRN_L2CSR0
andi. r3, r3, L2CSR0_L2FL@l
bne 1b
2:
blr

_GLOBAL(cpu_down_flush_e500v2)
mflr r0
bl flush_dcache_L1
mtlr r0
blr

_GLOBAL(cpu_down_flush_e500mc)
_GLOBAL(cpu_down_flush_e5500)
mflr r0
bl flush_dcache_L1
bl flush_backside_L2_cache
mtlr r0
blr

/* L1 Data Cache of e6500 contains no modified data, no flush is required */
_GLOBAL(cpu_down_flush_e6500)
blr
4 changes: 4 additions & 0 deletions arch/powerpc/kernel/cputable.c
Original file line number Diff line number Diff line change
Expand Up @@ -2050,6 +2050,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.cpu_setup = __setup_cpu_e500v2,
.machine_check = machine_check_e500,
.platform = "ppc8548",
.cpu_down_flush = cpu_down_flush_e500v2,
},
#else
{ /* e500mc */
Expand All @@ -2069,6 +2070,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.cpu_setup = __setup_cpu_e500mc,
.machine_check = machine_check_e500mc,
.platform = "ppce500mc",
.cpu_down_flush = cpu_down_flush_e500mc,
},
#endif /* CONFIG_PPC_E500MC */
#endif /* CONFIG_PPC32 */
Expand All @@ -2093,6 +2095,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
#endif
.machine_check = machine_check_e500mc,
.platform = "ppce5500",
.cpu_down_flush = cpu_down_flush_e5500,
},
{ /* e6500 */
.pvr_mask = 0xffff0000,
Expand All @@ -2115,6 +2118,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
#endif
.machine_check = machine_check_e500mc,
.platform = "ppce6500",
.cpu_down_flush = cpu_down_flush_e6500,
},
#endif /* CONFIG_PPC_E500MC */
#ifdef CONFIG_PPC32
Expand Down
74 changes: 0 additions & 74 deletions arch/powerpc/kernel/head_fsl_booke.S
Original file line number Diff line number Diff line change
Expand Up @@ -1037,80 +1037,6 @@ _GLOBAL(set_context)
isync /* Force context change */
blr

_GLOBAL(flush_dcache_L1)
mfspr r3,SPRN_L1CFG0

rlwinm r5,r3,9,3 /* Extract cache block size */
twlgti r5,1 /* Only 32 and 64 byte cache blocks
* are currently defined.
*/
li r4,32
subfic r6,r5,2 /* r6 = log2(1KiB / cache block size) -
* log2(number of ways)
*/
slw r5,r4,r5 /* r5 = cache block size */

rlwinm r7,r3,0,0xff /* Extract number of KiB in the cache */
mulli r7,r7,13 /* An 8-way cache will require 13
* loads per set.
*/
slw r7,r7,r6

/* save off HID0 and set DCFA */
mfspr r8,SPRN_HID0
ori r9,r8,HID0_DCFA@l
mtspr SPRN_HID0,r9
isync

lis r4,KERNELBASE@h
mtctr r7

1: lwz r3,0(r4) /* Load... */
add r4,r4,r5
bdnz 1b

msync
lis r4,KERNELBASE@h
mtctr r7

1: dcbf 0,r4 /* ...and flush. */
add r4,r4,r5
bdnz 1b

/* restore HID0 */
mtspr SPRN_HID0,r8
isync

blr

/* Flush L1 d-cache, invalidate and disable d-cache and i-cache */
_GLOBAL(__flush_disable_L1)
mflr r10
bl flush_dcache_L1 /* Flush L1 d-cache */
mtlr r10

mfspr r4, SPRN_L1CSR0 /* Invalidate and disable d-cache */
li r5, 2
rlwimi r4, r5, 0, 3

msync
isync
mtspr SPRN_L1CSR0, r4
isync

1: mfspr r4, SPRN_L1CSR0 /* Wait for the invalidate to finish */
andi. r4, r4, 2
bne 1b

mfspr r4, SPRN_L1CSR1 /* Invalidate and disable i-cache */
li r5, 2
rlwimi r4, r5, 0, 3

mtspr SPRN_L1CSR1, r4
isync

blr

#ifdef CONFIG_SMP
/* When we get here, r24 needs to hold the CPU # */
.globl __secondary_start
Expand Down
5 changes: 3 additions & 2 deletions arch/powerpc/platforms/85xx/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ static void smp_85xx_mach_cpu_die(void)

mtspr(SPRN_TCR, 0);

__flush_disable_L1();
cur_cpu_spec->cpu_down_flush();

tmp = (mfspr(SPRN_HID0) & ~(HID0_DOZE|HID0_SLEEP)) | HID0_NAP;
mtspr(SPRN_HID0, tmp);
isync();
Expand Down Expand Up @@ -359,7 +360,7 @@ void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary)
local_irq_disable();

if (secondary) {
__flush_disable_L1();
cur_cpu_spec->cpu_down_flush();
atomic_inc(&kexec_down_cpus);
/* loop forever */
while (1);
Expand Down

0 comments on commit e7affb1

Please sign in to comment.