]> git.sur5r.net Git - u-boot/commitdiff
powerpc/85xx: clear out TLB on boot
authorScott Wood <scottwood@freescale.com>
Mon, 20 Aug 2012 13:10:08 +0000 (13:10 +0000)
committerAndy Fleming <afleming@freescale.com>
Thu, 23 Aug 2012 17:16:57 +0000 (12:16 -0500)
Instead of just shooting down the entry that covers CCSR, clear out
every TLB entry that isn't the one that we're executing out of.

Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
arch/powerpc/cpu/mpc85xx/start.S
arch/powerpc/include/asm/mmu.h
arch/powerpc/include/asm/processor.h

index 66e8eb8f931dbbf6319dfb6a10a94e9695a24b39..9e04257d2ca00af07b923e4f8be4b64e11e423fe 100644 (file)
@@ -435,12 +435,11 @@ l2_disabled:
  * Search for the TLB that covers the code we're executing, and shrink it
  * so that it covers only this 4K page.  That will ensure that any other
  * TLB we create won't interfere with it.  We assume that the TLB exists,
- * which is why we don't check the Valid bit of MAS1.
+ * which is why we don't check the Valid bit of MAS1.  We also assume
+ * it is in TLB1.
  *
  * This is necessary, for example, when booting from the on-chip ROM,
  * which (oddly) creates a single 4GB TLB that covers CCSR and DDR.
- * If we don't shrink this TLB now, then we'll accidentally delete it
- * in "purge_old_ccsr_tlb" below.
  */
        bl      nexti           /* Find our address */
 nexti: mflr    r1              /* R1 = our PC */
@@ -450,11 +449,15 @@ nexti:    mflr    r1              /* R1 = our PC */
        msync
        tlbsx   0, r1           /* This must succeed */
 
+       mfspr   r14, MAS0       /* Save ESEL for later */
+       rlwinm  r14, r14, 16, 0xfff
+
        /* Set the size of the TLB to 4KB */
        mfspr   r3, MAS1
        li      r2, 0xF00
        andc    r3, r3, r2      /* Clear the TSIZE bits */
        ori     r3, r3, MAS1_TSIZE(BOOKE_PAGESZ_4K)@l
+       oris    r3, r3, MAS1_IPROT@h
        mtspr   MAS1, r3
 
        /*
@@ -488,6 +491,39 @@ nexti:     mflr    r1              /* R1 = our PC */
        msync
        tlbwe
 
+/*
+ * Clear out any other TLB entries that may exist, to avoid conflicts.
+ * Our TLB entry is in r14.
+ */
+       li      r0, TLBIVAX_ALL | TLBIVAX_TLB0
+       tlbivax 0, r0
+       tlbsync
+
+       mfspr   r4, SPRN_TLB1CFG
+       rlwinm  r4, r4, 0, TLBnCFG_NENTRY_MASK
+
+       li      r3, 0
+       mtspr   MAS1, r3
+1:     cmpw    r3, r14
+#if defined(CONFIG_SYS_PPC_E500_DEBUG_TLB) && !defined(CONFIG_NAND_SPL)
+       cmpwi   cr1, r3, CONFIG_SYS_PPC_E500_DEBUG_TLB
+       cror    cr0*4+eq, cr0*4+eq, cr1*4+eq
+#endif
+       rlwinm  r5, r3, 16, MAS0_ESEL_MSK
+       addi    r3, r3, 1
+       beq     2f              /* skip the entry we're executing from */
+
+       oris    r5, r5, MAS0_TLBSEL(1)@h
+       mtspr   MAS0, r5
+
+       isync
+       tlbwe
+       isync
+       msync
+
+2:     cmpw    r3, r4
+       blt     1b
+
 /*
  * Relocate CCSR, if necessary.  We relocate CCSR if (obviously) the default
  * location is not where we want it.  This typically happens on a 36-bit
@@ -506,41 +542,15 @@ nexti:    mflr    r1              /* R1 = our PC */
 #error "CONFIG_SYS_CCSRBAR_PHYS_HIGH and CONFIG_SYS_CCSRBAR_PHYS_LOW) must be defined."
 #endif
 
-purge_old_ccsr_tlb:
-       lis     r8, CONFIG_SYS_CCSRBAR@h
-       ori     r8, r8, CONFIG_SYS_CCSRBAR@l
-       lis     r9, (CONFIG_SYS_CCSRBAR + 0x1000)@h
-       ori     r9, r9, (CONFIG_SYS_CCSRBAR + 0x1000)@l
-
-       /*
-        * In a multi-stage boot (e.g. NAND boot), a previous stage may have
-        * created a TLB for CCSR, which will interfere with our relocation
-        * code.  Since we're going to create a new TLB for CCSR anyway,
-        * it should be safe to delete this old TLB here.  We have to search
-        * for it, though.
-        */
-
-       li      r1, 0
-       mtspr   MAS6, r1        /* Search the current address space and PID */
-       isync
-       msync
-       tlbsx   0, r8
-       mfspr   r1, MAS1
-       andis.  r2, r1, MAS1_VALID@h    /* Check for the Valid bit */
-       beq     1f                      /* Skip if no TLB found */
-
-       rlwinm  r1, r1, 0, 1, 31        /* Clear Valid bit */
-       mtspr   MAS1, r1
-       isync
-       msync
-       tlbwe
-1:
-
 create_ccsr_new_tlb:
        /*
         * Create a TLB for the new location of CCSR.  Register R8 is reserved
         * for the virtual address of this TLB (CONFIG_SYS_CCSRBAR).
         */
+       lis     r8, CONFIG_SYS_CCSRBAR@h
+       ori     r8, r8, CONFIG_SYS_CCSRBAR@l
+       lis     r9, (CONFIG_SYS_CCSRBAR + 0x1000)@h
+       ori     r9, r9, (CONFIG_SYS_CCSRBAR + 0x1000)@l
        lis     r0, FSL_BOOKE_MAS0(0, 0, 0)@h
        ori     r0, r0, FSL_BOOKE_MAS0(0, 0, 0)@l
        lis     r1, FSL_BOOKE_MAS1(1, 0, 0, 0, BOOKE_PAGESZ_4K)@h
index 209103e3ce10ae216ae1615c8ceb1f546b1e7e23..2e0e292da05df9e8ad8c14015478c1941b55c69d 100644 (file)
@@ -475,6 +475,10 @@ extern void print_bats(void);
 #define BOOKE_PAGESZ_256GB     14
 #define BOOKE_PAGESZ_1TB       15
 
+#define TLBIVAX_ALL            4
+#define TLBIVAX_TLB0           0
+#define TLBIVAX_TLB1           8
+
 #ifdef CONFIG_E500
 #ifndef __ASSEMBLY__
 extern void set_tlb(u8 tlb, u32 epn, u64 rpn,
index f3acd17dd5ffe0fb12b055285c898cc0d1bbcc6f..36695e2fb6d6b487d098c2b22ba506191d0bd201 100644 (file)
 
 #define SPRN_TLB0CFG   0x2B0   /* TLB 0 Config Register */
 #define SPRN_TLB1CFG   0x2B1   /* TLB 1 Config Register */
+#define   TLBnCFG_NENTRY_MASK  0x00000fff
 #define SPRN_TLB0PS    0x158   /* TLB 0 Page Size Register */
 #define SPRN_TLB1PS    0x159   /* TLB 1 Page Size Register */
 #define SPRN_MMUCSR0   0x3f4   /* MMU control and status register 0 */