]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
mips32: detect L1 cache sizes if they're not defined
authorPaul Burton <paul.burton@imgtec.com>
Fri, 8 Nov 2013 11:18:42 +0000 (11:18 +0000)
committerDaniel Schwierzeck <daniel.schwierzeck@gmail.com>
Sat, 9 Nov 2013 16:21:01 +0000 (17:21 +0100)
For boards such as the MIPS Malta with an FPGA core card it is desirable
to be able to detect the L1 cache sizes at runtime, since they are not
dependant upon the board but on the FPGA bitstream in use. This patch
performs that detection when the CONFIG_SYS_[DI]CACHE_SIZE macros are
not defined by the board configuration. In cases where the sizes are
detected this patch also removes the restriction that the I-cache &
D-cache line sizes must be the same, as this is not necessarily true.

If the cache sizes are defined by a configuration then they will be
hardcoded as before, so this patch will not add overhead to such
boards.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
arch/mips/cpu/mips32/cache.S
arch/mips/cpu/mips32/cpu.c
arch/mips/include/asm/mipsregs.h

index 12f656cad0a7746f1cbcb2c56a3238f04c67c198..22bd844eae750610e2b1367e6bb581db9e17902a 100644 (file)
 
 #define RA             t9
 
-/*
- * 16kB is the maximum size of instruction and data caches on MIPS 4K,
- * 64kB is on 4KE, 24K, 5K, etc. Set bigger size for convenience.
- *
- * Note that the above size is the maximum size of primary cache. U-Boot
- * doesn't have L2 cache support for now.
- */
-#define MIPS_MAX_CACHE_SIZE    0x10000
-
 #define INDEX_BASE     CKSEG0
 
        .macro  cache_op op addr
@@ -126,12 +117,85 @@ LEAF(mips_init_dcache)
  */
 NESTED(mips_cache_reset, 0, ra)
        move    RA, ra
-       li      t2, CONFIG_SYS_ICACHE_SIZE
-       li      t3, CONFIG_SYS_DCACHE_SIZE
+
+#if !defined(CONFIG_SYS_ICACHE_SIZE) || !defined(CONFIG_SYS_DCACHE_SIZE) || \
+    !defined(CONFIG_SYS_CACHELINE_SIZE)
+       /* read Config1 for use below */
+       mfc0    t5, CP0_CONFIG, 1
+#endif
+
+#ifdef CONFIG_SYS_CACHELINE_SIZE
+       li      t7, CONFIG_SYS_CACHELINE_SIZE
        li      t8, CONFIG_SYS_CACHELINE_SIZE
+#else
+       /* Detect I-cache line size. */
+       srl     t8, t5, MIPS_CONF1_IL_SHIFT
+       andi    t8, t8, (MIPS_CONF1_IL >> MIPS_CONF1_IL_SHIFT)
+       beqz    t8, 1f
+       li      t6, 2
+       sllv    t8, t6, t8
 
-       li      v0, MIPS_MAX_CACHE_SIZE
+1:     /* Detect D-cache line size. */
+       srl     t7, t5, MIPS_CONF1_DL_SHIFT
+       andi    t7, t7, (MIPS_CONF1_DL >> MIPS_CONF1_DL_SHIFT)
+       beqz    t7, 1f
+       li      t6, 2
+       sllv    t7, t6, t7
+1:
+#endif
 
+#ifdef CONFIG_SYS_ICACHE_SIZE
+       li      t2, CONFIG_SYS_ICACHE_SIZE
+#else
+       /* Detect I-cache size. */
+       srl     t6, t5, MIPS_CONF1_IS_SHIFT
+       andi    t6, t6, (MIPS_CONF1_IS >> MIPS_CONF1_IS_SHIFT)
+       li      t4, 32
+       xori    t2, t6, 0x7
+       beqz    t2, 1f
+       addi    t6, t6, 1
+       sllv    t4, t4, t6
+1:     /* At this point t4 == I-cache sets. */
+       mul     t2, t4, t8
+       srl     t6, t5, MIPS_CONF1_IA_SHIFT
+       andi    t6, t6, (MIPS_CONF1_IA >> MIPS_CONF1_IA_SHIFT)
+       addi    t6, t6, 1
+       /* At this point t6 == I-cache ways. */
+       mul     t2, t2, t6
+#endif
+
+#ifdef CONFIG_SYS_DCACHE_SIZE
+       li      t3, CONFIG_SYS_DCACHE_SIZE
+#else
+       /* Detect D-cache size. */
+       srl     t6, t5, MIPS_CONF1_DS_SHIFT
+       andi    t6, t6, (MIPS_CONF1_DS >> MIPS_CONF1_DS_SHIFT)
+       li      t4, 32
+       xori    t3, t6, 0x7
+       beqz    t3, 1f
+       addi    t6, t6, 1
+       sllv    t4, t4, t6
+1:     /* At this point t4 == I-cache sets. */
+       mul     t3, t4, t7
+       srl     t6, t5, MIPS_CONF1_DA_SHIFT
+       andi    t6, t6, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHIFT)
+       addi    t6, t6, 1
+       /* At this point t6 == I-cache ways. */
+       mul     t3, t3, t6
+#endif
+
+       /* Determine the largest L1 cache size */
+#if defined(CONFIG_SYS_ICACHE_SIZE) && defined(CONFIG_SYS_DCACHE_SIZE)
+#if CONFIG_SYS_ICACHE_SIZE > CONFIG_SYS_DCACHE_SIZE
+       li      v0, CONFIG_SYS_ICACHE_SIZE
+#else
+       li      v0, CONFIG_SYS_DCACHE_SIZE
+#endif
+#else
+       move    v0, t2
+       sltu    t1, t2, t3
+       movn    v0, t3, t1
+#endif
        /*
         * Now clear that much memory starting from zero.
         */
@@ -163,7 +227,7 @@ NESTED(mips_cache_reset, 0, ra)
         * then initialize D-cache.
         */
        move    a1, t3
-       move    a2, t8
+       move    a2, t7
        PTR_LA  v1, mips_init_dcache
        jalr    v1
 
index 28d5c456832be0ecbe547efb70b7ee77c243fa12..278865b6fff54849c98b0e1bd69a7cc7b2e5ba6f 100644 (file)
@@ -34,28 +34,89 @@ int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        return 0;
 }
 
+#ifdef CONFIG_SYS_CACHELINE_SIZE
+
+static inline unsigned long icache_line_size(void)
+{
+       return CONFIG_SYS_CACHELINE_SIZE;
+}
+
+static inline unsigned long dcache_line_size(void)
+{
+       return CONFIG_SYS_CACHELINE_SIZE;
+}
+
+#else /* !CONFIG_SYS_CACHELINE_SIZE */
+
+static inline unsigned long icache_line_size(void)
+{
+       unsigned long conf1, il;
+       conf1 = read_c0_config1();
+       il = (conf1 & MIPS_CONF1_IL) >> MIPS_CONF1_IL_SHIFT;
+       if (!il)
+               return 0;
+       return 2 << il;
+}
+
+static inline unsigned long dcache_line_size(void)
+{
+       unsigned long conf1, dl;
+       conf1 = read_c0_config1();
+       dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHIFT;
+       if (!dl)
+               return 0;
+       return 2 << dl;
+}
+
+#endif /* !CONFIG_SYS_CACHELINE_SIZE */
+
 void flush_cache(ulong start_addr, ulong size)
 {
-       unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE;
-       unsigned long addr = start_addr & ~(lsize - 1);
-       unsigned long aend = (start_addr + size - 1) & ~(lsize - 1);
+       unsigned long ilsize = icache_line_size();
+       unsigned long dlsize = dcache_line_size();
+       unsigned long addr, aend;
 
        /* aend will be miscalculated when size is zero, so we return here */
        if (size == 0)
                return;
 
+       addr = start_addr & ~(dlsize - 1);
+       aend = (start_addr + size - 1) & ~(dlsize - 1);
+
+       if (ilsize == dlsize) {
+               /* flush I-cache & D-cache simultaneously */
+               while (1) {
+                       cache_op(HIT_WRITEBACK_INV_D, addr);
+                       cache_op(HIT_INVALIDATE_I, addr);
+                       if (addr == aend)
+                               break;
+                       addr += dlsize;
+               }
+               return;
+       }
+
+       /* flush D-cache */
        while (1) {
                cache_op(HIT_WRITEBACK_INV_D, addr);
+               if (addr == aend)
+                       break;
+               addr += dlsize;
+       }
+
+       /* flush I-cache */
+       addr = start_addr & ~(ilsize - 1);
+       aend = (start_addr + size - 1) & ~(ilsize - 1);
+       while (1) {
                cache_op(HIT_INVALIDATE_I, addr);
                if (addr == aend)
                        break;
-               addr += lsize;
+               addr += ilsize;
        }
 }
 
 void flush_dcache_range(ulong start_addr, ulong stop)
 {
-       unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE;
+       unsigned long lsize = dcache_line_size();
        unsigned long addr = start_addr & ~(lsize - 1);
        unsigned long aend = (stop - 1) & ~(lsize - 1);
 
@@ -69,7 +130,7 @@ void flush_dcache_range(ulong start_addr, ulong stop)
 
 void invalidate_dcache_range(ulong start_addr, ulong stop)
 {
-       unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE;
+       unsigned long lsize = dcache_line_size();
        unsigned long addr = start_addr & ~(lsize - 1);
        unsigned long aend = (stop - 1) & ~(lsize - 1);
 
index be7e5c65ec1f38e91435844192af5a9637c2b337..3571e4fdf2e2867153ed1677cd5d12c639a09047 100644 (file)
 #define MIPS_CONF1_PC          (_ULCAST_(1) <<  4)
 #define MIPS_CONF1_MD          (_ULCAST_(1) <<  5)
 #define MIPS_CONF1_C2          (_ULCAST_(1) <<  6)
+#define MIPS_CONF1_DA_SHIFT    7
 #define MIPS_CONF1_DA          (_ULCAST_(7) <<  7)
+#define MIPS_CONF1_DL_SHIFT    10
 #define MIPS_CONF1_DL          (_ULCAST_(7) << 10)
+#define MIPS_CONF1_DS_SHIFT    13
 #define MIPS_CONF1_DS          (_ULCAST_(7) << 13)
+#define MIPS_CONF1_IA_SHIFT    16
 #define MIPS_CONF1_IA          (_ULCAST_(7) << 16)
+#define MIPS_CONF1_IL_SHIFT    19
 #define MIPS_CONF1_IL          (_ULCAST_(7) << 19)
+#define MIPS_CONF1_IS_SHIFT    22
 #define MIPS_CONF1_IS          (_ULCAST_(7) << 22)
 #define MIPS_CONF1_TLBS                (_ULCAST_(63)<< 25)