diff options
Diffstat (limited to 'arch/sh/mm/cache-sh4.c')
-rw-r--r-- | arch/sh/mm/cache-sh4.c | 81 |
1 files changed, 48 insertions, 33 deletions
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c index 86486326ef1d..226b190c5b9c 100644 --- a/arch/sh/mm/cache-sh4.c +++ b/arch/sh/mm/cache-sh4.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * arch/sh/mm/cache-sh4.c | 2 | * arch/sh/mm/cache-sh4.c |
3 | * | 3 | * |
4 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka | 4 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka |
5 | * Copyright (C) 2001 - 2006 Paul Mundt | 5 | * Copyright (C) 2001 - 2007 Paul Mundt |
6 | * Copyright (C) 2003 Richard Curnow | 6 | * Copyright (C) 2003 Richard Curnow |
7 | * | 7 | * |
8 | * This file is subject to the terms and conditions of the GNU General Public | 8 | * This file is subject to the terms and conditions of the GNU General Public |
@@ -44,7 +44,7 @@ static void (*__flush_dcache_segment_fn)(unsigned long, unsigned long) = | |||
44 | static void compute_alias(struct cache_info *c) | 44 | static void compute_alias(struct cache_info *c) |
45 | { | 45 | { |
46 | c->alias_mask = ((c->sets - 1) << c->entry_shift) & ~(PAGE_SIZE - 1); | 46 | c->alias_mask = ((c->sets - 1) << c->entry_shift) & ~(PAGE_SIZE - 1); |
47 | c->n_aliases = (c->alias_mask >> PAGE_SHIFT) + 1; | 47 | c->n_aliases = c->alias_mask ? (c->alias_mask >> PAGE_SHIFT) + 1 : 0; |
48 | } | 48 | } |
49 | 49 | ||
50 | static void __init emit_cache_params(void) | 50 | static void __init emit_cache_params(void) |
@@ -54,21 +54,35 @@ static void __init emit_cache_params(void) | |||
54 | ctrl_inl(CCN_CVR), | 54 | ctrl_inl(CCN_CVR), |
55 | ctrl_inl(CCN_PRR)); | 55 | ctrl_inl(CCN_PRR)); |
56 | printk("I-cache : n_ways=%d n_sets=%d way_incr=%d\n", | 56 | printk("I-cache : n_ways=%d n_sets=%d way_incr=%d\n", |
57 | current_cpu_data.icache.ways, | 57 | boot_cpu_data.icache.ways, |
58 | current_cpu_data.icache.sets, | 58 | boot_cpu_data.icache.sets, |
59 | current_cpu_data.icache.way_incr); | 59 | boot_cpu_data.icache.way_incr); |
60 | printk("I-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n", | 60 | printk("I-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n", |
61 | current_cpu_data.icache.entry_mask, | 61 | boot_cpu_data.icache.entry_mask, |
62 | current_cpu_data.icache.alias_mask, | 62 | boot_cpu_data.icache.alias_mask, |
63 | current_cpu_data.icache.n_aliases); | 63 | boot_cpu_data.icache.n_aliases); |
64 | printk("D-cache : n_ways=%d n_sets=%d way_incr=%d\n", | 64 | printk("D-cache : n_ways=%d n_sets=%d way_incr=%d\n", |
65 | current_cpu_data.dcache.ways, | 65 | boot_cpu_data.dcache.ways, |
66 | current_cpu_data.dcache.sets, | 66 | boot_cpu_data.dcache.sets, |
67 | current_cpu_data.dcache.way_incr); | 67 | boot_cpu_data.dcache.way_incr); |
68 | printk("D-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n", | 68 | printk("D-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n", |
69 | current_cpu_data.dcache.entry_mask, | 69 | boot_cpu_data.dcache.entry_mask, |
70 | current_cpu_data.dcache.alias_mask, | 70 | boot_cpu_data.dcache.alias_mask, |
71 | current_cpu_data.dcache.n_aliases); | 71 | boot_cpu_data.dcache.n_aliases); |
72 | |||
73 | /* | ||
74 | * Emit Secondary Cache parameters if the CPU has a probed L2. | ||
75 | */ | ||
76 | if (boot_cpu_data.flags & CPU_HAS_L2_CACHE) { | ||
77 | printk("S-cache : n_ways=%d n_sets=%d way_incr=%d\n", | ||
78 | boot_cpu_data.scache.ways, | ||
79 | boot_cpu_data.scache.sets, | ||
80 | boot_cpu_data.scache.way_incr); | ||
81 | printk("S-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n", | ||
82 | boot_cpu_data.scache.entry_mask, | ||
83 | boot_cpu_data.scache.alias_mask, | ||
84 | boot_cpu_data.scache.n_aliases); | ||
85 | } | ||
72 | 86 | ||
73 | if (!__flush_dcache_segment_fn) | 87 | if (!__flush_dcache_segment_fn) |
74 | panic("unknown number of cache ways\n"); | 88 | panic("unknown number of cache ways\n"); |
@@ -79,10 +93,11 @@ static void __init emit_cache_params(void) | |||
79 | */ | 93 | */ |
80 | void __init p3_cache_init(void) | 94 | void __init p3_cache_init(void) |
81 | { | 95 | { |
82 | compute_alias(¤t_cpu_data.icache); | 96 | compute_alias(&boot_cpu_data.icache); |
83 | compute_alias(¤t_cpu_data.dcache); | 97 | compute_alias(&boot_cpu_data.dcache); |
98 | compute_alias(&boot_cpu_data.scache); | ||
84 | 99 | ||
85 | switch (current_cpu_data.dcache.ways) { | 100 | switch (boot_cpu_data.dcache.ways) { |
86 | case 1: | 101 | case 1: |
87 | __flush_dcache_segment_fn = __flush_dcache_segment_1way; | 102 | __flush_dcache_segment_fn = __flush_dcache_segment_1way; |
88 | break; | 103 | break; |
@@ -187,13 +202,13 @@ void flush_cache_sigtramp(unsigned long addr) | |||
187 | : "m" (__m(v))); | 202 | : "m" (__m(v))); |
188 | 203 | ||
189 | index = CACHE_IC_ADDRESS_ARRAY | | 204 | index = CACHE_IC_ADDRESS_ARRAY | |
190 | (v & current_cpu_data.icache.entry_mask); | 205 | (v & boot_cpu_data.icache.entry_mask); |
191 | 206 | ||
192 | local_irq_save(flags); | 207 | local_irq_save(flags); |
193 | jump_to_P2(); | 208 | jump_to_P2(); |
194 | 209 | ||
195 | for (i = 0; i < current_cpu_data.icache.ways; | 210 | for (i = 0; i < boot_cpu_data.icache.ways; |
196 | i++, index += current_cpu_data.icache.way_incr) | 211 | i++, index += boot_cpu_data.icache.way_incr) |
197 | ctrl_outl(0, index); /* Clear out Valid-bit */ | 212 | ctrl_outl(0, index); /* Clear out Valid-bit */ |
198 | 213 | ||
199 | back_to_P1(); | 214 | back_to_P1(); |
@@ -210,7 +225,7 @@ static inline void flush_cache_4096(unsigned long start, | |||
210 | * All types of SH-4 require PC to be in P2 to operate on the I-cache. | 225 | * All types of SH-4 require PC to be in P2 to operate on the I-cache. |
211 | * Some types of SH-4 require PC to be in P2 to operate on the D-cache. | 226 | * Some types of SH-4 require PC to be in P2 to operate on the D-cache. |
212 | */ | 227 | */ |
213 | if ((current_cpu_data.flags & CPU_HAS_P2_FLUSH_BUG) || | 228 | if ((boot_cpu_data.flags & CPU_HAS_P2_FLUSH_BUG) || |
214 | (start < CACHE_OC_ADDRESS_ARRAY)) | 229 | (start < CACHE_OC_ADDRESS_ARRAY)) |
215 | exec_offset = 0x20000000; | 230 | exec_offset = 0x20000000; |
216 | 231 | ||
@@ -232,7 +247,7 @@ void flush_dcache_page(struct page *page) | |||
232 | int i, n; | 247 | int i, n; |
233 | 248 | ||
234 | /* Loop all the D-cache */ | 249 | /* Loop all the D-cache */ |
235 | n = current_cpu_data.dcache.n_aliases; | 250 | n = boot_cpu_data.dcache.n_aliases; |
236 | for (i = 0; i < n; i++, addr += 4096) | 251 | for (i = 0; i < n; i++, addr += 4096) |
237 | flush_cache_4096(addr, phys); | 252 | flush_cache_4096(addr, phys); |
238 | } | 253 | } |
@@ -264,7 +279,7 @@ static inline void flush_icache_all(void) | |||
264 | 279 | ||
265 | void flush_dcache_all(void) | 280 | void flush_dcache_all(void) |
266 | { | 281 | { |
267 | (*__flush_dcache_segment_fn)(0UL, current_cpu_data.dcache.way_size); | 282 | (*__flush_dcache_segment_fn)(0UL, boot_cpu_data.dcache.way_size); |
268 | wmb(); | 283 | wmb(); |
269 | } | 284 | } |
270 | 285 | ||
@@ -278,8 +293,8 @@ static void __flush_cache_mm(struct mm_struct *mm, unsigned long start, | |||
278 | unsigned long end) | 293 | unsigned long end) |
279 | { | 294 | { |
280 | unsigned long d = 0, p = start & PAGE_MASK; | 295 | unsigned long d = 0, p = start & PAGE_MASK; |
281 | unsigned long alias_mask = current_cpu_data.dcache.alias_mask; | 296 | unsigned long alias_mask = boot_cpu_data.dcache.alias_mask; |
282 | unsigned long n_aliases = current_cpu_data.dcache.n_aliases; | 297 | unsigned long n_aliases = boot_cpu_data.dcache.n_aliases; |
283 | unsigned long select_bit; | 298 | unsigned long select_bit; |
284 | unsigned long all_aliases_mask; | 299 | unsigned long all_aliases_mask; |
285 | unsigned long addr_offset; | 300 | unsigned long addr_offset; |
@@ -366,7 +381,7 @@ void flush_cache_mm(struct mm_struct *mm) | |||
366 | * If cache is only 4k-per-way, there are never any 'aliases'. Since | 381 | * If cache is only 4k-per-way, there are never any 'aliases'. Since |
367 | * the cache is physically tagged, the data can just be left in there. | 382 | * the cache is physically tagged, the data can just be left in there. |
368 | */ | 383 | */ |
369 | if (current_cpu_data.dcache.n_aliases == 0) | 384 | if (boot_cpu_data.dcache.n_aliases == 0) |
370 | return; | 385 | return; |
371 | 386 | ||
372 | /* | 387 | /* |
@@ -403,7 +418,7 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long address, | |||
403 | unsigned long phys = pfn << PAGE_SHIFT; | 418 | unsigned long phys = pfn << PAGE_SHIFT; |
404 | unsigned int alias_mask; | 419 | unsigned int alias_mask; |
405 | 420 | ||
406 | alias_mask = current_cpu_data.dcache.alias_mask; | 421 | alias_mask = boot_cpu_data.dcache.alias_mask; |
407 | 422 | ||
408 | /* We only need to flush D-cache when we have alias */ | 423 | /* We only need to flush D-cache when we have alias */ |
409 | if ((address^phys) & alias_mask) { | 424 | if ((address^phys) & alias_mask) { |
@@ -417,7 +432,7 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long address, | |||
417 | phys); | 432 | phys); |
418 | } | 433 | } |
419 | 434 | ||
420 | alias_mask = current_cpu_data.icache.alias_mask; | 435 | alias_mask = boot_cpu_data.icache.alias_mask; |
421 | if (vma->vm_flags & VM_EXEC) { | 436 | if (vma->vm_flags & VM_EXEC) { |
422 | /* | 437 | /* |
423 | * Evict entries from the portion of the cache from which code | 438 | * Evict entries from the portion of the cache from which code |
@@ -449,7 +464,7 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start, | |||
449 | * If cache is only 4k-per-way, there are never any 'aliases'. Since | 464 | * If cache is only 4k-per-way, there are never any 'aliases'. Since |
450 | * the cache is physically tagged, the data can just be left in there. | 465 | * the cache is physically tagged, the data can just be left in there. |
451 | */ | 466 | */ |
452 | if (current_cpu_data.dcache.n_aliases == 0) | 467 | if (boot_cpu_data.dcache.n_aliases == 0) |
453 | return; | 468 | return; |
454 | 469 | ||
455 | /* | 470 | /* |
@@ -510,7 +525,7 @@ static void __flush_cache_4096(unsigned long addr, unsigned long phys, | |||
510 | unsigned long a, ea, p; | 525 | unsigned long a, ea, p; |
511 | unsigned long temp_pc; | 526 | unsigned long temp_pc; |
512 | 527 | ||
513 | dcache = ¤t_cpu_data.dcache; | 528 | dcache = &boot_cpu_data.dcache; |
514 | /* Write this way for better assembly. */ | 529 | /* Write this way for better assembly. */ |
515 | way_count = dcache->ways; | 530 | way_count = dcache->ways; |
516 | way_incr = dcache->way_incr; | 531 | way_incr = dcache->way_incr; |
@@ -585,7 +600,7 @@ static void __flush_dcache_segment_1way(unsigned long start, | |||
585 | base_addr = ((base_addr >> 16) << 16); | 600 | base_addr = ((base_addr >> 16) << 16); |
586 | base_addr |= start; | 601 | base_addr |= start; |
587 | 602 | ||
588 | dcache = ¤t_cpu_data.dcache; | 603 | dcache = &boot_cpu_data.dcache; |
589 | linesz = dcache->linesz; | 604 | linesz = dcache->linesz; |
590 | way_incr = dcache->way_incr; | 605 | way_incr = dcache->way_incr; |
591 | way_size = dcache->way_size; | 606 | way_size = dcache->way_size; |
@@ -627,7 +642,7 @@ static void __flush_dcache_segment_2way(unsigned long start, | |||
627 | base_addr = ((base_addr >> 16) << 16); | 642 | base_addr = ((base_addr >> 16) << 16); |
628 | base_addr |= start; | 643 | base_addr |= start; |
629 | 644 | ||
630 | dcache = ¤t_cpu_data.dcache; | 645 | dcache = &boot_cpu_data.dcache; |
631 | linesz = dcache->linesz; | 646 | linesz = dcache->linesz; |
632 | way_incr = dcache->way_incr; | 647 | way_incr = dcache->way_incr; |
633 | way_size = dcache->way_size; | 648 | way_size = dcache->way_size; |
@@ -686,7 +701,7 @@ static void __flush_dcache_segment_4way(unsigned long start, | |||
686 | base_addr = ((base_addr >> 16) << 16); | 701 | base_addr = ((base_addr >> 16) << 16); |
687 | base_addr |= start; | 702 | base_addr |= start; |
688 | 703 | ||
689 | dcache = ¤t_cpu_data.dcache; | 704 | dcache = &boot_cpu_data.dcache; |
690 | linesz = dcache->linesz; | 705 | linesz = dcache->linesz; |
691 | way_incr = dcache->way_incr; | 706 | way_incr = dcache->way_incr; |
692 | way_size = dcache->way_size; | 707 | way_size = dcache->way_size; |