diff options
author | Chenhui Zhao <chenhui.zhao@freescale.com> | 2014-02-17 08:23:16 (GMT) |
---|---|---|
committer | Jose Rivera <German.Rivera@freescale.com> | 2014-04-04 19:33:04 (GMT) |
commit | 67d36dfe1a4095561287da8ce2bafd0a62a4dddc (patch) | |
tree | 19a4cde2fcf174d50fb6717a42a0b732b15f14ba | |
parent | c23407ac96fec2ad2190208da74842308057d8eb (diff) | |
download | linux-fsl-qoriq-67d36dfe1a4095561287da8ce2bafd0a62a4dddc.tar.xz |
powerpc/cache: add cache flush operation for various e500
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 in the current cpu.
Change-Id: Id6da30ac5490cac5f5669909df2152f0ee952086
Signed-off-by: Chenhui Zhao <chenhui.zhao@freescale.com>
Reviewed-on: http://git.am.freescale.net:8181/10705
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Yang Li <LeoLi@freescale.com>
Reviewed-by: Jose Rivera <German.Rivera@freescale.com>
-rw-r--r-- | arch/powerpc/include/asm/cputable.h | 11 | ||||
-rw-r--r-- | arch/powerpc/kernel/asm-offsets.c | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/cputable.c | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/fsl_booke_cache.S | 18 | ||||
-rw-r--r-- | arch/powerpc/platforms/85xx/smp.c | 11 |
5 files changed, 41 insertions, 6 deletions
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index fbf5d23..ffdaeec 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h @@ -50,6 +50,13 @@ 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); +#if defined(CONFIG_E500) || defined(CONFIG_PPC_E500MC) +extern void __flush_caches_e500v2(void); +extern void __flush_caches_e500mc(void); +extern void __flush_caches_e5500(void); +extern void __flush_caches_e6500(void); +#endif + /* NOTE WELL: Update identify_cpu() if fields are added or removed! */ struct cpu_spec { /* CPU is matched via (PVR & pvr_mask) == pvr_value */ @@ -69,6 +76,10 @@ struct cpu_spec { /* L2 cache type */ enum powerpc_l2cache_type l2cache_type; +#if defined(CONFIG_E500) || defined(CONFIG_PPC_E500MC) + /* flush caches of the cpu which is running the function */ + void (*cpu_flush_caches)(void); +#endif /* number of performance monitor counters */ unsigned int num_pmcs; enum powerpc_pmc_type pmc_type; diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index d2950df..f1e6aa3 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -364,6 +364,9 @@ 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)); +#if defined(CONFIG_E500) || defined(CONFIG_PPC_E500MC) + DEFINE(CPU_FLUSH_CACHES, offsetof(struct cpu_spec, cpu_flush_caches)); +#endif DEFINE(pbe_address, offsetof(struct pbe, address)); DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address)); diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 5ab1ed9..b0550a2 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -2054,6 +2054,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check = machine_check_e500, .platform = "ppc8548", .l2cache_type = PPC_L2_CACHE_SOC, + .cpu_flush_caches = __flush_caches_e500v2, }, { /* e500mc */ .pvr_mask = 0xffff0000, @@ -2073,6 +2074,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check = machine_check_e500mc, .platform = "ppce500mc", .l2cache_type = PPC_L2_CACHE_CORE, + .cpu_flush_caches = __flush_caches_e500mc, }, #endif /* CONFIG_PPC32 */ { /* e5500 */ @@ -2096,6 +2098,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check = machine_check_e500mc, .platform = "ppce5500", .l2cache_type = PPC_L2_CACHE_CORE, + .cpu_flush_caches = __flush_caches_e5500, }, #ifndef CONFIG_PPC32 { /* e6500 */ @@ -2118,6 +2121,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check = machine_check_e500mc, .platform = "ppce6500", .l2cache_type = PPC_L2_CACHE_CLUSTER, + .cpu_flush_caches = __flush_caches_e6500, }, #endif #ifdef CONFIG_PPC32 diff --git a/arch/powerpc/kernel/fsl_booke_cache.S b/arch/powerpc/kernel/fsl_booke_cache.S index b295b0a..767c237 100644 --- a/arch/powerpc/kernel/fsl_booke_cache.S +++ b/arch/powerpc/kernel/fsl_booke_cache.S @@ -217,3 +217,21 @@ _GLOBAL(invalidate_enable_L2) mbar blr + +_GLOBAL(__flush_caches_e500v2) + mflr r0 + bl flush_dcache_L1 + mtlr r0 + blr + +_GLOBAL(__flush_caches_e500mc) +_GLOBAL(__flush_caches_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(__flush_caches_e6500) + blr diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index 1f50419..6775982 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c @@ -217,11 +217,8 @@ static void __cpuinit smp_85xx_mach_cpu_die(void) mtspr(SPRN_TCR, 0); - if (is_core_down(cpu)) - __flush_disable_L1(); - - if (cur_cpu_spec->l2cache_type == PPC_L2_CACHE_CORE) - disable_backside_L2_cache(); + if (cur_cpu_spec && cur_cpu_spec->cpu_flush_caches) + cur_cpu_spec->cpu_flush_caches(); generic_set_cpu_dead(cpu); @@ -257,7 +254,9 @@ static void smp_85xx_mach_cpu_die(void) mtspr(SPRN_TCR, 0); - __flush_disable_L1(); + if (cur_cpu_spec && cur_cpu_spec->cpu_flush_caches) + cur_cpu_spec->cpu_flush_caches(); + tmp = (mfspr(SPRN_HID0) & ~(HID0_DOZE|HID0_SLEEP)) | HID0_NAP; mtspr(SPRN_HID0, tmp); isync(); |