summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorChenhui Zhao <chenhui.zhao@freescale.com>2014-02-17 08:23:16 (GMT)
committerJose Rivera <German.Rivera@freescale.com>2014-04-04 19:33:04 (GMT)
commit67d36dfe1a4095561287da8ce2bafd0a62a4dddc (patch)
tree19a4cde2fcf174d50fb6717a42a0b732b15f14ba /arch
parentc23407ac96fec2ad2190208da74842308057d8eb (diff)
downloadlinux-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>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/include/asm/cputable.h11
-rw-r--r--arch/powerpc/kernel/asm-offsets.c3
-rw-r--r--arch/powerpc/kernel/cputable.c4
-rw-r--r--arch/powerpc/kernel/fsl_booke_cache.S18
-rw-r--r--arch/powerpc/platforms/85xx/smp.c11
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();