powerpc/cache: add cache flush operation for various e500
authorchenhui zhao <chenhui.zhao@freescale.com>
Fri, 20 Nov 2015 09:13:58 +0000 (17:13 +0800)
committerScott Wood <oss@buserror.net>
Sat, 5 Mar 2016 05:44:51 +0000 (23:44 -0600)
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>
arch/powerpc/include/asm/cacheflush.h
arch/powerpc/include/asm/cputable.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/cpu_setup_fsl_booke.S
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/head_fsl_booke.S
arch/powerpc/platforms/85xx/smp.c

index 6229e6b6037b97fe7d43862945a8c7806d602128..47add2e2364ae39ef15a29a232bb709a91350bc8 100644 (file)
@@ -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,
index 94ace9b4c4e1c40839d4adbd6e51a4ea9f9b4bef..df4fb5faba436e1922ef1bd774b0d17ed814b274 100644 (file)
@@ -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 */
@@ -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;
index 10d5eab19458344d99361a998f9b899d3fdba20b..0d0183d3180a434beb5b4772bb0469e370f17940 100644 (file)
@@ -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));
index dddba3e942606e138a467c3de8bd3841d482cb30..462aed9bcf512fa38856aad905ba9003b2b6c8f5 100644 (file)
  *
  */
 
+#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
@@ -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
index be4d73053bed05891929c3e3766bf13745e1c6b7..6c662b8de90d6430a15e4c7f903ccffe74727f58 100644 (file)
@@ -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 */
@@ -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 */
@@ -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,
@@ -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
index f705171b924b9389c5b16979ce52fd90171ecffa..3bfa3150911f7b42f20b7bfb7e7715be6c10871e 100644 (file)
@@ -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
index 6b107cea1c08e0b9e2f5a9807ba64ff9cbe94d0d..4a7841616c7ff5763b6f5a5efa370ba32921cc86 100644 (file)
@@ -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();
@@ -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);