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 */ 26static 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 */ 34static 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 44static void mips_sc_enable(void) 45{ 46 /* L2 cache is permanently enabled */ 47} 48 49static void mips_sc_disable(void) 50{ 51 /* L2 cache is permanently enabled */ 52} 53 54static 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 79static 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 96static 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 109static 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 */ 128static 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 if (config2 & (1 << 12)) 145 return 0; 146 } 147 148 tmp = (config2 >> 4) & 0x0f; 149 if (0 < tmp && tmp <= 7) 150 c->scache.linesz = 2 << tmp; 151 else 152 return 0; 153 return 1; 154} 155 156static int __init mips_sc_probe_cm3(void) 157{ 158 struct cpuinfo_mips *c = ¤t_cpu_data; 159 unsigned long cfg = read_gcr_l2_config(); 160 unsigned long sets, line_sz, assoc; 161 162 if (cfg & CM_GCR_L2_CONFIG_BYPASS_MSK) 163 return 0; 164 165 sets = cfg & CM_GCR_L2_CONFIG_SET_SIZE_MSK; 166 sets >>= CM_GCR_L2_CONFIG_SET_SIZE_SHF; 167 if (sets) 168 c->scache.sets = 64 << sets; 169 170 line_sz = cfg & CM_GCR_L2_CONFIG_LINE_SIZE_MSK; 171 line_sz >>= CM_GCR_L2_CONFIG_LINE_SIZE_SHF; 172 if (line_sz) 173 c->scache.linesz = 2 << line_sz; 174 175 assoc = cfg & CM_GCR_L2_CONFIG_ASSOC_MSK; 176 assoc >>= CM_GCR_L2_CONFIG_ASSOC_SHF; 177 c->scache.ways = assoc + 1; 178 c->scache.waysize = c->scache.sets * c->scache.linesz; 179 c->scache.waybit = __ffs(c->scache.waysize); 180 181 if (c->scache.linesz) { 182 c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT; 183 return 1; 184 } 185 186 return 0; 187} 188 189void __weak platform_early_l2_init(void) 190{ 191} 192 193static inline int __init mips_sc_probe(void) 194{ 195 struct cpuinfo_mips *c = ¤t_cpu_data; 196 unsigned int config1, config2; 197 unsigned int tmp; 198 199 /* Mark as not present until probe completed */ 200 c->scache.flags |= MIPS_CACHE_NOT_PRESENT; 201 202 /* 203 * Do we need some platform specific probing before 204 * we configure L2? 205 */ 206 platform_early_l2_init(); 207 208 if (mips_cm_revision() >= CM_REV_CM3) 209 return mips_sc_probe_cm3(); 210 211 /* Ignore anything but MIPSxx processors */ 212 if (!(c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 | 213 MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R1 | 214 MIPS_CPU_ISA_M64R2 | MIPS_CPU_ISA_M64R6))) 215 return 0; 216 217 /* Does this MIPS32/MIPS64 CPU have a config2 register? */ 218 config1 = read_c0_config1(); 219 if (!(config1 & MIPS_CONF_M)) 220 return 0; 221 222 config2 = read_c0_config2(); 223 224 if (!mips_sc_is_activated(c)) 225 return 0; 226 227 tmp = (config2 >> 8) & 0x0f; 228 if (tmp <= 7) 229 c->scache.sets = 64 << tmp; 230 else 231 return 0; 232 233 tmp = (config2 >> 0) & 0x0f; 234 if (tmp <= 7) 235 c->scache.ways = tmp + 1; 236 else 237 return 0; 238 239 c->scache.waysize = c->scache.sets * c->scache.linesz; 240 c->scache.waybit = __ffs(c->scache.waysize); 241 242 c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT; 243 244 return 1; 245} 246 247int mips_sc_init(void) 248{ 249 int found = mips_sc_probe(); 250 if (found) { 251 mips_sc_enable(); 252 mips_sc_prefetch_enable(); 253 bcops = &mips_sc_ops; 254 } 255 return found; 256} 257