fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / mips / mm / sc-rm7k.c
index ec3ec9e..31ec730 100644 (file)
@@ -9,12 +9,14 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/bitops.h>
 
 #include <asm/addrspace.h>
 #include <asm/bcache.h>
 #include <asm/cacheops.h>
 #include <asm/mipsregs.h>
 #include <asm/processor.h>
+#include <asm/cacheflush.h> /* for run_uncached() */
 
 /* Primary cache parameters. */
 #define sc_lsize       32
@@ -42,14 +44,7 @@ static void rm7k_sc_wback_inv(unsigned long addr, unsigned long size)
        /* Catch bad driver code */
        BUG_ON(size == 0);
 
-       a = addr & ~(sc_lsize - 1);
-       end = (addr + size - 1) & ~(sc_lsize - 1);
-       while (1) {
-               flush_scache_line(a);   /* Hit_Writeback_Inv_SD */
-               if (a == end)
-                       break;
-               a += sc_lsize;
-       }
+       blast_scache_range(addr, addr + size);
 
        if (!rm7k_tcache_enabled)
                return;
@@ -73,14 +68,7 @@ static void rm7k_sc_inv(unsigned long addr, unsigned long size)
        /* Catch bad driver code */
        BUG_ON(size == 0);
 
-       a = addr & ~(sc_lsize - 1);
-       end = (addr + size - 1) & ~(sc_lsize - 1);
-       while (1) {
-               invalidate_scache_line(a);      /* Hit_Invalidate_SD */
-               if (a == end)
-                       break;
-               a += sc_lsize;
-       }
+       blast_inv_scache_range(addr, addr + size);
 
        if (!rm7k_tcache_enabled)
                return;
@@ -96,25 +84,13 @@ static void rm7k_sc_inv(unsigned long addr, unsigned long size)
 }
 
 /*
- * This function is executed in the uncached segment KSEG1.
- * It must not touch the stack, because the stack pointer still points
- * into KSEG0.
- *
- * Three options:
- *     - Write it in assembly and guarantee that we don't use the stack.
- *     - Disable caching for KSEG0 before calling it.
- *     - Pray that GCC doesn't randomly start using the stack.
- *
- * This being Linux, we obviously take the least sane of those options -
- * following DaveM's lead in c-r4k.c
- *
- * It seems we get our kicks from relying on unguaranteed behaviour in GCC
+ * This function is executed in uncached address space.
  */
 static __init void __rm7k_sc_enable(void)
 {
        int i;
 
-       set_c0_config(1 << 3);                          /* CONF_SE */
+       set_c0_config(RM7K_CONF_SE);
 
        write_c0_taglo(0);
        write_c0_taghi(0);
@@ -127,75 +103,71 @@ static __init void __rm7k_sc_enable(void)
                      ".set mips0\n\t"
                      ".set reorder"
                      :
-                     : "r" (KSEG0ADDR(i)), "i" (Index_Store_Tag_SD));
+                     : "r" (CKSEG0ADDR(i)), "i" (Index_Store_Tag_SD));
        }
 }
 
 static __init void rm7k_sc_enable(void)
 {
-       void (*func)(void) = (void *) KSEG1ADDR(&__rm7k_sc_enable);
-
-       if (read_c0_config() & 0x08)                    /* CONF_SE */
+       if (read_c0_config() & RM7K_CONF_SE)
                return;
 
-       printk(KERN_INFO "Enabling secondary cache...");
-       func();
+       printk(KERN_INFO "Enabling secondary cache...\n");
+       run_uncached(__rm7k_sc_enable);
 }
 
 static void rm7k_sc_disable(void)
 {
-       clear_c0_config(1<<3);                          /* CONF_SE */
+       clear_c0_config(RM7K_CONF_SE);
 }
 
-static inline int __init rm7k_sc_probe(void)
+struct bcache_ops rm7k_sc_ops = {
+       .bc_enable = rm7k_sc_enable,
+       .bc_disable = rm7k_sc_disable,
+       .bc_wback_inv = rm7k_sc_wback_inv,
+       .bc_inv = rm7k_sc_inv
+};
+
+void __init rm7k_sc_init(void)
 {
+       struct cpuinfo_mips *c = &current_cpu_data;
        unsigned int config = read_c0_config();
 
-       if ((config >> 31) & 1)
-               return 0;
+       if ((config & RM7K_CONF_SC))
+               return;
 
+       c->scache.linesz = sc_lsize;
+       c->scache.ways = 4;
+       c->scache.waybit= __ffs(scache_size / c->scache.ways);
+       c->scache.waysize = scache_size / c->scache.ways;
+       c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways);
        printk(KERN_INFO "Secondary cache size %dK, linesize %d bytes.\n",
               (scache_size >> 10), sc_lsize);
 
-       if ((config >> 3) & 1)                          /* CONF_SE */
-               return 1;
+       if (!(config & RM7K_CONF_SE))
+               rm7k_sc_enable();
 
        /*
         * While we're at it let's deal with the tertiary cache.
         */
-       if ((config >> 17) & 1)
-               return 1;
-
-       /*
-        * We can't enable the L3 cache yet. There may be board-specific
-        * magic necessary to turn it on, and blindly asking the CPU to
-        * start using it would may give cache errors.
-        *
-        * Also, board-specific knowledge may allow us to use the
-        * CACHE Flash_Invalidate_T instruction if the tag RAM supports
-        * it, and may specify the size of the L3 cache so we don't have
-        * to probe it.
-        */
-       printk(KERN_INFO "Tertiary cache present, %s enabled\n",
-              config&(1<<12) ? "already" : "not (yet)");
-
-       if ((config >> 12) & 1)
-               rm7k_tcache_enabled = 1;
-
-       return 1;
-}
-
-struct bcache_ops rm7k_sc_ops = {
-       .bc_enable = rm7k_sc_enable,
-       .bc_disable = rm7k_sc_disable,
-       .bc_wback_inv = rm7k_sc_wback_inv,
-       .bc_inv = rm7k_sc_inv
-};
-
-void __init rm7k_sc_init(void)
-{
-       if (rm7k_sc_probe()) {
-               rm7k_sc_enable();
-               bcops = &rm7k_sc_ops;
+       if (!(config & RM7K_CONF_TC)) {
+
+               /*
+                * We can't enable the L3 cache yet. There may be board-specific
+                * magic necessary to turn it on, and blindly asking the CPU to
+                * start using it would may give cache errors.
+                *
+                * Also, board-specific knowledge may allow us to use the
+                * CACHE Flash_Invalidate_T instruction if the tag RAM supports
+                * it, and may specify the size of the L3 cache so we don't have
+                * to probe it.
+                */
+               printk(KERN_INFO "Tertiary cache present, %s enabled\n",
+                      (config & RM7K_CONF_TE) ? "already" : "not (yet)");
+
+               if ((config & RM7K_CONF_TE))
+                       rm7k_tcache_enabled = 1;
        }
+
+       bcops = &rm7k_sc_ops;
 }