diff options
Diffstat (limited to 'arch/sh/mm')
| -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 397c1030c7a..b36a9c986a5 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) |
