1 /* 2 * Copyright (C) 2006 Chris Dearman (chris@mips.com), 3 */ 4 #include <linux/init.h> 5 #include <linux/kernel.h> 6 #include <linux/sched.h> 7 #include <linux/mm.h> 8 9 #include <asm/cpu-type.h> 10 #include <asm/mipsregs.h> 11 #include <asm/bcache.h> 12 #include <asm/cacheops.h> 13 #include <asm/page.h> 14 #include <asm/pgtable.h> 15 #include <asm/mmu_context.h> 16 #include <asm/r4kcache.h> 17 #include <asm/mips-cm.h> 18 19 /* 20 * MIPS32/MIPS64 L2 cache handling 21 */ 22 23 /* 24 * Writeback and invalidate the secondary cache before DMA. 25 */ 26 static void mips_sc_wback_inv(unsigned long addr, unsigned long size) 27 { 28 blast_scache_range(addr, addr + size); 29 } 30 31 /* 32 * Invalidate the secondary cache before DMA. 33 */ 34 static void mips_sc_inv(unsigned long addr, unsigned long size) 35 { 36 unsigned long lsize = cpu_scache_line_size(); 37 unsigned long almask = ~(lsize - 1); 38 39 cache_op(Hit_Writeback_Inv_SD, addr & almask); 40 cache_op(Hit_Writeback_Inv_SD, (addr + size - 1) & almask); 41 blast_inv_scache_range(addr, addr + size); 42 } 43 44 static void mips_sc_enable(void) 45 { 46 /* L2 cache is permanently enabled */ 47 } 48 49 static void mips_sc_disable(void) 50 { 51 /* L2 cache is permanently enabled */ 52 } 53 54 static void mips_sc_prefetch_enable(void) 55 { 56 unsigned long pftctl; 57 58 if (mips_cm_revision() < CM_REV_CM2_5) 59 return; 60 61 /* 62 * If there is one or more L2 prefetch unit present then enable 63 * prefetching for both code & data, for all ports. 64 */ 65 pftctl = read_gcr_l2_pft_control(); 66 if (pftctl & CM_GCR_L2_PFT_CONTROL_NPFT_MSK) { 67 pftctl &= ~CM_GCR_L2_PFT_CONTROL_PAGEMASK_MSK; 68 pftctl |= PAGE_MASK & CM_GCR_L2_PFT_CONTROL_PAGEMASK_MSK; 69 pftctl |= CM_GCR_L2_PFT_CONTROL_PFTEN_MSK; 70 write_gcr_l2_pft_control(pftctl); 71 72 pftctl = read_gcr_l2_pft_control_b(); 73 pftctl |= CM_GCR_L2_PFT_CONTROL_B_PORTID_MSK; 74 pftctl |= CM_GCR_L2_PFT_CONTROL_B_CEN_MSK; 75 write_gcr_l2_pft_control_b(pftctl); 76 } 77 } 78 79 static void mips_sc_prefetch_disable(void) 80 { 81 unsigned long pftctl; 82 83 if (mips_cm_revision() < CM_REV_CM2_5) 84 return; 85 86 pftctl = read_gcr_l2_pft_control(); 87 pftctl &= ~CM_GCR_L2_PFT_CONTROL_PFTEN_MSK; 88 write_gcr_l2_pft_control(pftctl); 89 90 pftctl = read_gcr_l2_pft_control_b(); 91 pftctl &= ~CM_GCR_L2_PFT_CONTROL_B_PORTID_MSK; 92 pftctl &= ~CM_GCR_L2_PFT_CONTROL_B_CEN_MSK; 93 write_gcr_l2_pft_control_b(pftctl); 94 } 95 96 static bool mips_sc_prefetch_is_enabled(void) 97 { 98 unsigned long pftctl; 99 100 if (mips_cm_revision() < CM_REV_CM2_5) 101 return false; 102 103 pftctl = read_gcr_l2_pft_control(); 104 if (!(pftctl & CM_GCR_L2_PFT_CONTROL_NPFT_MSK)) 105 return false; 106 return !!(pftctl & CM_GCR_L2_PFT_CONTROL_PFTEN_MSK); 107 } 108 109 static struct bcache_ops mips_sc_ops = { 110 .bc_enable = mips_sc_enable, 111 .bc_disable = mips_sc_disable, 112 .bc_wback_inv = mips_sc_wback_inv, 113 .bc_inv = mips_sc_inv, 114 .bc_prefetch_enable = mips_sc_prefetch_enable, 115 .bc_prefetch_disable = mips_sc_prefetch_disable, 116 .bc_prefetch_is_enabled = mips_sc_prefetch_is_enabled, 117 }; 118 119 /* 120 * Check if the L2 cache controller is activated on a particular platform. 121 * MTI's L2 controller and the L2 cache controller of Broadcom's BMIPS 122 * cores both use c0_config2's bit 12 as "L2 Bypass" bit, that is the 123 * cache being disabled. However there is no guarantee for this to be 124 * true on all platforms. In an act of stupidity the spec defined bits 125 * 12..15 as implementation defined so below function will eventually have 126 * to be replaced by a platform specific probe. 127 */ 128 static inline int mips_sc_is_activated(struct cpuinfo_mips *c) 129 { 130 unsigned int config2 = read_c0_config2(); 131 unsigned int tmp; 132 133 /* Check the bypass bit (L2B) */ 134 switch (current_cpu_type()) { 135 case CPU_34K: 136 case CPU_74K: 137 case CPU_1004K: 138 case CPU_1074K: 139 case CPU_INTERAPTIV: 140 case CPU_PROAPTIV: 141 case CPU_P5600: 142 case CPU_BMIPS5000: 143 case CPU_QEMU_GENERIC: 144 case CPU_P6600: 145 if (config2 & (1 << 12)) 146 return 0; 147 } 148 149 tmp = (config2 >> 4) & 0x0f; 150 if (0 < tmp && tmp <= 7) 151 c->scache.linesz = 2 << tmp; 152 else 153 return 0; 154 return 1; 155 } 156 157 static int __init mips_sc_probe_cm3(void) 158 { 159 struct cpuinfo_mips *c = ¤t_cpu_data; 160 unsigned long cfg = read_gcr_l2_config(); 161 unsigned long sets, line_sz, assoc; 162 163 if (cfg & CM_GCR_L2_CONFIG_BYPASS_MSK) 164 return 0; 165 166 sets = cfg & CM_GCR_L2_CONFIG_SET_SIZE_MSK; 167 sets >>= CM_GCR_L2_CONFIG_SET_SIZE_SHF; 168 if (sets) 169 c->scache.sets = 64 << sets; 170 171 line_sz = cfg & CM_GCR_L2_CONFIG_LINE_SIZE_MSK; 172 line_sz >>= CM_GCR_L2_CONFIG_LINE_SIZE_SHF; 173 if (line_sz) 174 c->scache.linesz = 2 << line_sz; 175 176 assoc = cfg & CM_GCR_L2_CONFIG_ASSOC_MSK; 177 assoc >>= CM_GCR_L2_CONFIG_ASSOC_SHF; 178 c->scache.ways = assoc + 1; 179 c->scache.waysize = c->scache.sets * c->scache.linesz; 180 c->scache.waybit = __ffs(c->scache.waysize); 181 182 if (c->scache.linesz) { 183 c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT; 184 return 1; 185 } 186 187 return 0; 188 } 189 190 static inline int __init mips_sc_probe(void) 191 { 192 struct cpuinfo_mips *c = ¤t_cpu_data; 193 unsigned int config1, config2; 194 unsigned int tmp; 195 196 /* Mark as not present until probe completed */ 197 c->scache.flags |= MIPS_CACHE_NOT_PRESENT; 198 199 if (mips_cm_revision() >= CM_REV_CM3) 200 return mips_sc_probe_cm3(); 201 202 /* Ignore anything but MIPSxx processors */ 203 if (!(c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 | 204 MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R1 | 205 MIPS_CPU_ISA_M64R2 | MIPS_CPU_ISA_M64R6))) 206 return 0; 207 208 /* Does this MIPS32/MIPS64 CPU have a config2 register? */ 209 config1 = read_c0_config1(); 210 if (!(config1 & MIPS_CONF_M)) 211 return 0; 212 213 config2 = read_c0_config2(); 214 215 if (!mips_sc_is_activated(c)) 216 return 0; 217 218 tmp = (config2 >> 8) & 0x0f; 219 if (tmp <= 7) 220 c->scache.sets = 64 << tmp; 221 else 222 return 0; 223 224 tmp = (config2 >> 0) & 0x0f; 225 if (tmp <= 7) 226 c->scache.ways = tmp + 1; 227 else 228 return 0; 229 230 c->scache.waysize = c->scache.sets * c->scache.linesz; 231 c->scache.waybit = __ffs(c->scache.waysize); 232 233 c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT; 234 235 return 1; 236 } 237 238 int mips_sc_init(void) 239 { 240 int found = mips_sc_probe(); 241 if (found) { 242 mips_sc_enable(); 243 mips_sc_prefetch_enable(); 244 bcops = &mips_sc_ops; 245 } 246 return found; 247 } 248