diff options
author | Matt Fleming <matt@console-pimps.org> | 2009-09-01 00:32:48 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-09-01 00:32:48 -0400 |
commit | ce3f7cb96e67d6518c7fc7b361a76409c3817d64 (patch) | |
tree | 183e635fb7b855f348a6e4ba42a1da0a2692a4b2 /arch/sh/mm/cache-sh4.c | |
parent | 1279b7f1168ad6a2606191090f8a96eba64766a4 (diff) |
sh: Fix dcache flushing for N-way write-through caches.
This adopts the special-cased 2-way write-through dcache flusher for
N-ways and moves it in to the generic path. Assignment is done at runtime
via the check for the CCR_CACHE_WT bit in the same path as the per-way
writeback flushers.
Signed-off-by: Matt Fleming <matt@console-pimps.org>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/mm/cache-sh4.c')
-rw-r--r-- | arch/sh/mm/cache-sh4.c | 48 |
1 files changed, 27 insertions, 21 deletions
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c index 397c1030c7a6..b36a9c986a58 100644 --- a/arch/sh/mm/cache-sh4.c +++ b/arch/sh/mm/cache-sh4.c | |||
@@ -25,13 +25,14 @@ | |||
25 | #define MAX_DCACHE_PAGES 64 /* XXX: Tune for ways */ | 25 | #define MAX_DCACHE_PAGES 64 /* XXX: Tune for ways */ |
26 | #define MAX_ICACHE_PAGES 32 | 26 | #define MAX_ICACHE_PAGES 32 |
27 | 27 | ||
28 | static void __flush_dcache_segment_writethrough(unsigned long start, | ||
29 | unsigned long extent); | ||
28 | static void __flush_dcache_segment_1way(unsigned long start, | 30 | static void __flush_dcache_segment_1way(unsigned long start, |
29 | unsigned long extent); | 31 | unsigned long extent); |
30 | static void __flush_dcache_segment_2way(unsigned long start, | 32 | static void __flush_dcache_segment_2way(unsigned long start, |
31 | unsigned long extent); | 33 | unsigned long extent); |
32 | static void __flush_dcache_segment_4way(unsigned long start, | 34 | static void __flush_dcache_segment_4way(unsigned long start, |
33 | unsigned long extent); | 35 | unsigned long extent); |
34 | |||
35 | static void __flush_cache_4096(unsigned long addr, unsigned long phys, | 36 | static void __flush_cache_4096(unsigned long addr, unsigned long phys, |
36 | unsigned long exec_offset); | 37 | unsigned long exec_offset); |
37 | 38 | ||
@@ -95,10 +96,17 @@ static void __init emit_cache_params(void) | |||
95 | */ | 96 | */ |
96 | void __init p3_cache_init(void) | 97 | void __init p3_cache_init(void) |
97 | { | 98 | { |
99 | unsigned int wt_enabled = !!(__raw_readl(CCR) & CCR_CACHE_WT); | ||
100 | |||
98 | compute_alias(&boot_cpu_data.icache); | 101 | compute_alias(&boot_cpu_data.icache); |
99 | compute_alias(&boot_cpu_data.dcache); | 102 | compute_alias(&boot_cpu_data.dcache); |
100 | compute_alias(&boot_cpu_data.scache); | 103 | compute_alias(&boot_cpu_data.scache); |
101 | 104 | ||
105 | if (wt_enabled) { | ||
106 | __flush_dcache_segment_fn = __flush_dcache_segment_writethrough; | ||
107 | goto out; | ||
108 | } | ||
109 | |||
102 | switch (boot_cpu_data.dcache.ways) { | 110 | switch (boot_cpu_data.dcache.ways) { |
103 | case 1: | 111 | case 1: |
104 | __flush_dcache_segment_fn = __flush_dcache_segment_1way; | 112 | __flush_dcache_segment_fn = __flush_dcache_segment_1way; |
@@ -114,6 +122,7 @@ void __init p3_cache_init(void) | |||
114 | break; | 122 | break; |
115 | } | 123 | } |
116 | 124 | ||
125 | out: | ||
117 | emit_cache_params(); | 126 | emit_cache_params(); |
118 | } | 127 | } |
119 | 128 | ||
@@ -607,6 +616,23 @@ static void __flush_cache_4096(unsigned long addr, unsigned long phys, | |||
607 | * - If caches are disabled or configured in write-through mode, then | 616 | * - If caches are disabled or configured in write-through mode, then |
608 | * the movca.l writes garbage directly into memory. | 617 | * the movca.l writes garbage directly into memory. |
609 | */ | 618 | */ |
619 | static void __flush_dcache_segment_writethrough(unsigned long start, | ||
620 | unsigned long extent_per_way) | ||
621 | { | ||
622 | unsigned long addr; | ||
623 | int i; | ||
624 | |||
625 | addr = CACHE_OC_ADDRESS_ARRAY | (start & cpu_data->dcache.entry_mask); | ||
626 | |||
627 | while (extent_per_way) { | ||
628 | for (i = 0; i < cpu_data->dcache.ways; i++) | ||
629 | __raw_writel(0, addr + cpu_data->dcache.way_incr * i); | ||
630 | |||
631 | addr += cpu_data->dcache.linesz; | ||
632 | extent_per_way -= cpu_data->dcache.linesz; | ||
633 | } | ||
634 | } | ||
635 | |||
610 | static void __flush_dcache_segment_1way(unsigned long start, | 636 | static void __flush_dcache_segment_1way(unsigned long start, |
611 | unsigned long extent_per_way) | 637 | unsigned long extent_per_way) |
612 | { | 638 | { |
@@ -655,25 +681,6 @@ static void __flush_dcache_segment_1way(unsigned long start, | |||
655 | } while (a0 < a0e); | 681 | } while (a0 < a0e); |
656 | } | 682 | } |
657 | 683 | ||
658 | #ifdef CONFIG_CACHE_WRITETHROUGH | ||
659 | /* This method of cache flushing avoids the problems discussed | ||
660 | * in the comment above if writethrough caches are enabled. */ | ||
661 | static void __flush_dcache_segment_2way(unsigned long start, | ||
662 | unsigned long extent_per_way) | ||
663 | { | ||
664 | unsigned long array_addr; | ||
665 | |||
666 | array_addr = CACHE_OC_ADDRESS_ARRAY | | ||
667 | (start & cpu_data->dcache.entry_mask); | ||
668 | |||
669 | while (extent_per_way) { | ||
670 | ctrl_outl(0, array_addr); | ||
671 | ctrl_outl(0, array_addr + cpu_data->dcache.way_incr); | ||
672 | array_addr += cpu_data->dcache.linesz; | ||
673 | extent_per_way -= cpu_data->dcache.linesz; | ||
674 | } | ||
675 | } | ||
676 | #else | ||
677 | static void __flush_dcache_segment_2way(unsigned long start, | 684 | static void __flush_dcache_segment_2way(unsigned long start, |
678 | unsigned long extent_per_way) | 685 | unsigned long extent_per_way) |
679 | { | 686 | { |
@@ -732,7 +739,6 @@ static void __flush_dcache_segment_2way(unsigned long start, | |||
732 | a1 += linesz; | 739 | a1 += linesz; |
733 | } while (a0 < a0e); | 740 | } while (a0 < a0e); |
734 | } | 741 | } |
735 | #endif | ||
736 | 742 | ||
737 | static void __flush_dcache_segment_4way(unsigned long start, | 743 | static void __flush_dcache_segment_4way(unsigned long start, |
738 | unsigned long extent_per_way) | 744 | unsigned long extent_per_way) |