Changeset bad1f53 in mainline for kernel/arch/arm32/src/cpu/cpu.c
- Timestamp:
- 2013-01-19T16:35:17Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 827aae5
- Parents:
- 5fcd537
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/arm32/src/cpu/cpu.c
r5fcd537 rbad1f53 34 34 */ 35 35 36 #include <arch/cache.h> 36 37 #include <arch/cpu.h> 38 #include <arch/cp15.h> 37 39 #include <cpu.h> 38 40 #include <arch.h> 39 41 #include <print.h> 42 43 static inline unsigned log2(unsigned val) 44 { 45 unsigned log = 0; 46 --val; 47 while (val) { 48 ++log; 49 val >>= 1; 50 } 51 return log; 52 } 53 54 static unsigned dcache_ways(unsigned level); 55 static unsigned dcache_sets(unsigned level); 56 static unsigned dcache_linesize_log(unsigned level); 57 40 58 41 59 /** Implementers (vendor) names */ … … 93 111 cpu->rev_num = (ident << 28) >> 28; 94 112 // TODO CPUs with arch_num == 0xf use CPUID scheme for identification 113 cpu->dcache_levels = dcache_levels(); 114 115 for (unsigned i = 0; i < cpu->dcache_levels; ++i) { 116 cpu->dcache[i].ways = dcache_ways(i); 117 cpu->dcache[i].sets = dcache_sets(i); 118 cpu->dcache[i].way_shift = 31 - log2(cpu->dcache[i].ways); 119 cpu->dcache[i].set_shift = dcache_linesize_log(i); 120 cpu->dcache[i].line_size = 1 << dcache_linesize_log(i); 121 printf("Found DCache L%u: %u-way, %u sets, %u byte lines " 122 "(shifts: w%u, s%u)\n", i + 1, cpu->dcache[i].ways, 123 cpu->dcache[i].sets, cpu->dcache[i].line_size, 124 cpu->dcache[i].way_shift, cpu->dcache[i].set_shift); 125 } 95 126 } 96 127 … … 170 201 } 171 202 203 /** See chapter B4.1.19 of ARM Architecture Reference Manual */ 204 static unsigned dcache_linesize_log(unsigned level) 205 { 206 #ifdef PROCESSOR_ARCH_armv7_a 207 CSSELR_write((level & CCSELR_LEVEL_MASK) << CCSELR_LEVEL_SHIFT); 208 const unsigned ls_log = 2 + 209 ((CCSIDR_read() >> CCSIDR_LINESIZE_SHIFT) & CCSIDR_LINESIZE_MASK); 210 return ls_log + 2; //return log2(bytes) 211 #endif 212 return 0; 213 214 } 215 216 /** See chapter B4.1.19 of ARM Architecture Reference Manual */ 217 static unsigned dcache_ways(unsigned level) 218 { 219 #ifdef PROCESSOR_ARCH_armv7_a 220 CSSELR_write((level & CCSELR_LEVEL_MASK) << CCSELR_LEVEL_SHIFT); 221 const unsigned ways = 1 + 222 ((CCSIDR_read() >> CCSIDR_ASSOC_SHIFT) & CCSIDR_ASSOC_MASK); 223 return ways; 224 #endif 225 return 0; 226 } 227 228 /** See chapter B4.1.19 of ARM Architecture Reference Manual */ 229 static unsigned dcache_sets(unsigned level) 230 { 231 #ifdef PROCESSOR_ARCH_armv7_a 232 CSSELR_write((level & CCSELR_LEVEL_MASK) << CCSELR_LEVEL_SHIFT); 233 const unsigned sets = 1 + 234 ((CCSIDR_read() >> CCSIDR_NUMSETS_SHIFT) & CCSIDR_NUMSETS_MASK); 235 return sets; 236 #endif 237 return 0; 238 } 239 240 unsigned dcache_levels(void) 241 { 242 const uint32_t val = CLIDR_read(); 243 unsigned levels = 0; 244 for (unsigned i = 1; i <= 7; ++i) { 245 const unsigned ctype = CLIDR_CACHE(i, val); 246 switch (ctype) { 247 case CLIDR_DCACHE_ONLY: 248 case CLIDR_SEP_CACHE: 249 case CLIDR_UNI_CACHE: 250 ++levels; 251 default: 252 (void)0; 253 } 254 } 255 return levels; 256 } 257 258 static void dcache_clean_manual(unsigned level, bool invalidate, 259 unsigned ways, unsigned sets, unsigned way_shift, unsigned set_shift) 260 { 261 262 for (unsigned i = 0; i < ways; ++i) { 263 for (unsigned j = 0; j < sets; ++j) { 264 const uint32_t val = 265 ((level & 0x7) << 1) | 266 (j << set_shift) | (i << way_shift); 267 if (invalidate) 268 DCCISW_write(val); 269 else 270 DCCSW_write(val); 271 } 272 } 273 } 274 275 void dcache_flush(void) 276 { 277 /* See ARM Architecture Reference Manual ch. B4.2.1 p. B4-1724 */ 278 const unsigned levels = dcache_levels(); 279 for (unsigned i = 0; i < levels; ++i) { 280 const unsigned ways = dcache_ways(i); 281 const unsigned sets = dcache_sets(i); 282 const unsigned way_shift = 31 - log2(ways); 283 const unsigned set_shift = dcache_linesize_log(i); 284 dcache_clean_manual(i, false, ways, sets, way_shift, set_shift); 285 } 286 } 287 288 void dcache_flush_invalidate(void) 289 { 290 /* See ARM Architecture Reference Manual ch. B4.2.1 p. B4-1724 */ 291 const unsigned levels = dcache_levels(); 292 for (unsigned i = 0; i < levels; ++i) { 293 const unsigned ways = dcache_ways(i); 294 const unsigned sets = dcache_sets(i); 295 const unsigned way_shift = 31 - log2(ways); 296 const unsigned set_shift = dcache_linesize_log(i); 297 dcache_clean_manual(i, true, ways, sets, way_shift, set_shift); 298 } 299 } 300 301 302 void cpu_dcache_flush(void) 303 { 304 for (unsigned i = 0; i < CPU->arch.dcache_levels; ++i) 305 dcache_clean_manual(i, false, 306 CPU->arch.dcache[i].ways, CPU->arch.dcache[i].sets, 307 CPU->arch.dcache[i].way_shift, CPU->arch.dcache[i].set_shift); 308 } 309 310 void cpu_dcache_flush_invalidate(void) 311 { 312 const unsigned levels = dcache_levels(); 313 for (unsigned i = 0; i < levels; ++i) 314 dcache_clean_manual(i, true, 315 CPU->arch.dcache[i].ways, CPU->arch.dcache[i].sets, 316 CPU->arch.dcache[i].way_shift, CPU->arch.dcache[i].set_shift); 317 } 318 319 void icache_invalidate(void) 320 { 321 ICIALLU_write(0); 322 } 323 172 324 /** @} 173 325 */
Note:
See TracChangeset
for help on using the changeset viewer.