1 /* 2 * sc-rm7k.c: RM7000 cache management functions. 3 * 4 * Copyright (C) 1997, 2001, 2003, 2004 Ralf Baechle (ralf@linux-mips.org) 5 */ 6 7 #undef DEBUG 8 9 #include <linux/init.h> 10 #include <linux/kernel.h> 11 #include <linux/mm.h> 12 #include <linux/bitops.h> 13 14 #include <asm/addrspace.h> 15 #include <asm/bcache.h> 16 #include <asm/cacheops.h> 17 #include <asm/mipsregs.h> 18 #include <asm/processor.h> 19 #include <asm/cacheflush.h> /* for run_uncached() */ 20 21 /* Primary cache parameters. */ 22 #define sc_lsize 32 23 #define tc_pagesize (32*128) 24 25 /* Secondary cache parameters. */ 26 #define scache_size (256*1024) /* Fixed to 256KiB on RM7000 */ 27 28 extern unsigned long icache_way_size, dcache_way_size; 29 30 #include <asm/r4kcache.h> 31 32 int rm7k_tcache_enabled; 33 34 /* 35 * Writeback and invalidate the primary cache dcache before DMA. 36 * (XXX These need to be fixed ...) 37 */ 38 static void rm7k_sc_wback_inv(unsigned long addr, unsigned long size) 39 { 40 unsigned long end, a; 41 42 pr_debug("rm7k_sc_wback_inv[%08lx,%08lx]", addr, size); 43 44 /* Catch bad driver code */ 45 BUG_ON(size == 0); 46 47 blast_scache_range(addr, addr + size); 48 49 if (!rm7k_tcache_enabled) 50 return; 51 52 a = addr & ~(tc_pagesize - 1); 53 end = (addr + size - 1) & ~(tc_pagesize - 1); 54 while(1) { 55 invalidate_tcache_page(a); /* Page_Invalidate_T */ 56 if (a == end) 57 break; 58 a += tc_pagesize; 59 } 60 } 61 62 static void rm7k_sc_inv(unsigned long addr, unsigned long size) 63 { 64 unsigned long end, a; 65 66 pr_debug("rm7k_sc_inv[%08lx,%08lx]", addr, size); 67 68 /* Catch bad driver code */ 69 BUG_ON(size == 0); 70 71 blast_inv_scache_range(addr, addr + size); 72 73 if (!rm7k_tcache_enabled) 74 return; 75 76 a = addr & ~(tc_pagesize - 1); 77 end = (addr + size - 1) & ~(tc_pagesize - 1); 78 while(1) { 79 invalidate_tcache_page(a); /* Page_Invalidate_T */ 80 if (a == end) 81 break; 82 a += tc_pagesize; 83 } 84 } 85 86 /* 87 * This function is executed in uncached address space. 88 */ 89 static __cpuinit void __rm7k_sc_enable(void) 90 { 91 int i; 92 93 set_c0_config(RM7K_CONF_SE); 94 95 write_c0_taglo(0); 96 write_c0_taghi(0); 97 98 for (i = 0; i < scache_size; i += sc_lsize) { 99 __asm__ __volatile__ ( 100 ".set noreorder\n\t" 101 ".set mips3\n\t" 102 "cache %1, (%0)\n\t" 103 ".set mips0\n\t" 104 ".set reorder" 105 : 106 : "r" (CKSEG0ADDR(i)), "i" (Index_Store_Tag_SD)); 107 } 108 } 109 110 static __cpuinit void rm7k_sc_enable(void) 111 { 112 if (read_c0_config() & RM7K_CONF_SE) 113 return; 114 115 printk(KERN_INFO "Enabling secondary cache...\n"); 116 run_uncached(__rm7k_sc_enable); 117 } 118 119 static void rm7k_sc_disable(void) 120 { 121 clear_c0_config(RM7K_CONF_SE); 122 } 123 124 struct bcache_ops rm7k_sc_ops = { 125 .bc_enable = rm7k_sc_enable, 126 .bc_disable = rm7k_sc_disable, 127 .bc_wback_inv = rm7k_sc_wback_inv, 128 .bc_inv = rm7k_sc_inv 129 }; 130 131 void __cpuinit rm7k_sc_init(void) 132 { 133 struct cpuinfo_mips *c = ¤t_cpu_data; 134 unsigned int config = read_c0_config(); 135 136 if ((config & RM7K_CONF_SC)) 137 return; 138 139 c->scache.linesz = sc_lsize; 140 c->scache.ways = 4; 141 c->scache.waybit= __ffs(scache_size / c->scache.ways); 142 c->scache.waysize = scache_size / c->scache.ways; 143 c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways); 144 printk(KERN_INFO "Secondary cache size %dK, linesize %d bytes.\n", 145 (scache_size >> 10), sc_lsize); 146 147 if (!(config & RM7K_CONF_SE)) 148 rm7k_sc_enable(); 149 150 /* 151 * While we're at it let's deal with the tertiary cache. 152 */ 153 if (!(config & RM7K_CONF_TC)) { 154 155 /* 156 * We can't enable the L3 cache yet. There may be board-specific 157 * magic necessary to turn it on, and blindly asking the CPU to 158 * start using it would may give cache errors. 159 * 160 * Also, board-specific knowledge may allow us to use the 161 * CACHE Flash_Invalidate_T instruction if the tag RAM supports 162 * it, and may specify the size of the L3 cache so we don't have 163 * to probe it. 164 */ 165 printk(KERN_INFO "Tertiary cache present, %s enabled\n", 166 (config & RM7K_CONF_TE) ? "already" : "not (yet)"); 167 168 if ((config & RM7K_CONF_TE)) 169 rm7k_tcache_enabled = 1; 170 } 171 172 bcops = &rm7k_sc_ops; 173 } 174