aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2007-07-31 04:07:28 -0400
committerPaul Mundt <lethal@linux-sh.org>2007-09-20 22:57:46 -0400
commite7bd34a15b85655f24d1b45edbe3bdfebf9d027e (patch)
tree051647273266582fe95dcc5cf008534c264be5ae
parentac919986d7dfc5d1d9f5585521307f222a8ebeaf (diff)
sh: Support explicit L1 cache disabling.
This reworks the cache mode configuration in Kconfig, and allows for explicit selection of write-back/write-through/off configurations. All of the cache flushing routines are optimized away for the off case. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r--arch/sh/kernel/cpu/init.c11
-rw-r--r--arch/sh/kernel/sh_ksyms.c7
-rw-r--r--arch/sh/mm/Kconfig19
-rw-r--r--arch/sh/mm/Makefile11
-rw-r--r--arch/sh/mm/pmb.c2
-rw-r--r--arch/sh/mm/tlb-sh4.c25
-rw-r--r--include/asm-sh/cacheflush.h33
-rw-r--r--include/asm-sh/page.h6
-rw-r--r--include/asm-sh/pgtable.h3
9 files changed, 86 insertions, 31 deletions
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
index 9172e97dc26a..fdc245b7b043 100644
--- a/arch/sh/kernel/cpu/init.c
+++ b/arch/sh/kernel/cpu/init.c
@@ -143,12 +143,15 @@ static void __init cache_init(void)
143 flags &= ~CCR_CACHE_EMODE; 143 flags &= ~CCR_CACHE_EMODE;
144#endif 144#endif
145 145
146#ifdef CONFIG_SH_WRITETHROUGH 146#if defined(CONFIG_CACHE_WRITETHROUGH)
147 /* Turn on Write-through caching */ 147 /* Write-through */
148 flags |= CCR_CACHE_WT; 148 flags |= CCR_CACHE_WT;
149#else 149#elif defined(CONFIG_CACHE_WRITEBACK)
150 /* .. or default to Write-back */ 150 /* Write-back */
151 flags |= CCR_CACHE_CB; 151 flags |= CCR_CACHE_CB;
152#else
153 /* Off */
154 flags &= ~CCR_CACHE_ENABLE;
152#endif 155#endif
153 156
154 ctrl_outl(flags, CCR); 157 ctrl_outl(flags, CCR);
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index 37aef0a85197..de250705c35e 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -128,7 +128,8 @@ DECLARE_EXPORT(__movstrSI12_i4);
128#endif /* __GNUC__ == 4 */ 128#endif /* __GNUC__ == 4 */
129#endif 129#endif
130 130
131#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) 131#if !defined(CONFIG_CACHE_OFF) && (defined(CONFIG_CPU_SH4) || \
132 defined(CONFIG_SH7705_CACHE_32KB))
132/* needed by some modules */ 133/* needed by some modules */
133EXPORT_SYMBOL(flush_cache_all); 134EXPORT_SYMBOL(flush_cache_all);
134EXPORT_SYMBOL(flush_cache_range); 135EXPORT_SYMBOL(flush_cache_range);
@@ -136,8 +137,8 @@ EXPORT_SYMBOL(flush_dcache_page);
136EXPORT_SYMBOL(__flush_purge_region); 137EXPORT_SYMBOL(__flush_purge_region);
137#endif 138#endif
138 139
139#if defined(CONFIG_MMU) && (defined(CONFIG_CPU_SH4) || \ 140#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \
140 defined(CONFIG_SH7705_CACHE_32KB)) 141 (defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB))
141EXPORT_SYMBOL(clear_user_page); 142EXPORT_SYMBOL(clear_user_page);
142#endif 143#endif
143 144
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index 093d491424fd..c2777555003e 100644
--- a/arch/sh/mm/Kconfig
+++ b/arch/sh/mm/Kconfig
@@ -2,7 +2,6 @@
2# Processor families 2# Processor families
3# 3#
4config CPU_SH2 4config CPU_SH2
5 select SH_WRITETHROUGH if !CPU_SH2A
6 bool 5 bool
7 6
8config CPU_SH2A 7config CPU_SH2A
@@ -414,8 +413,17 @@ config SH_DIRECT_MAPPED
414 Turn this option off for platforms that do not have a direct-mapped 413 Turn this option off for platforms that do not have a direct-mapped
415 cache, and you have no need to run the caches in such a configuration. 414 cache, and you have no need to run the caches in such a configuration.
416 415
417config SH_WRITETHROUGH 416choice
418 bool "Use write-through caching" 417 prompt "Cache mode"
418 default CACHE_WRITEBACK if CPU_SH2A || CPU_SH3 || CPU_SH4
419 default CACHE_WRITETHROUGH if (CPU_SH2 && !CPU_SH2A)
420
421config CACHE_WRITEBACK
422 bool "Write-back"
423 depends on CPU_SH2A || CPU_SH3 || CPU_SH4
424
425config CACHE_WRITETHROUGH
426 bool "Write-through"
419 help 427 help
420 Selecting this option will configure the caches in write-through 428 Selecting this option will configure the caches in write-through
421 mode, as opposed to the default write-back configuration. 429 mode, as opposed to the default write-back configuration.
@@ -426,4 +434,9 @@ config SH_WRITETHROUGH
426 434
427 If unsure, say N. 435 If unsure, say N.
428 436
437config CACHE_OFF
438 bool "Off"
439
440endchoice
441
429endmenu 442endmenu
diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile
index 4061e89d84d0..e73d7f970ce0 100644
--- a/arch/sh/mm/Makefile
+++ b/arch/sh/mm/Makefile
@@ -4,9 +4,10 @@
4 4
5obj-y := init.o extable.o consistent.o 5obj-y := init.o extable.o consistent.o
6 6
7obj-$(CONFIG_CPU_SH2) += cache-sh2.o 7cache-$(CONFIG_CPU_SH2) := cache-sh2.o
8obj-$(CONFIG_CPU_SH3) += cache-sh3.o 8cache-$(CONFIG_CPU_SH3) := cache-sh3.o
9obj-$(CONFIG_CPU_SH4) += cache-sh4.o 9cache-$(CONFIG_CPU_SH4) := cache-sh4.o pg-sh4.o
10cache-$(CONFIG_CACHE_OFF) :=
10 11
11mmu-y := tlb-nommu.o pg-nommu.o 12mmu-y := tlb-nommu.o pg-nommu.o
12mmu-$(CONFIG_CPU_SH3) += fault-nommu.o 13mmu-$(CONFIG_CPU_SH3) += fault-nommu.o
@@ -14,7 +15,7 @@ mmu-$(CONFIG_CPU_SH4) += fault-nommu.o
14mmu-$(CONFIG_MMU) := fault.o clear_page.o copy_page.o tlb-flush.o \ 15mmu-$(CONFIG_MMU) := fault.o clear_page.o copy_page.o tlb-flush.o \
15 ioremap.o 16 ioremap.o
16 17
17obj-y += $(mmu-y) 18obj-y += $(cache-y) $(mmu-y)
18 19
19ifdef CONFIG_DEBUG_FS 20ifdef CONFIG_DEBUG_FS
20obj-$(CONFIG_CPU_SH4) += cache-debugfs.o 21obj-$(CONFIG_CPU_SH4) += cache-debugfs.o
@@ -22,7 +23,7 @@ endif
22 23
23ifdef CONFIG_MMU 24ifdef CONFIG_MMU
24obj-$(CONFIG_CPU_SH3) += tlb-sh3.o 25obj-$(CONFIG_CPU_SH3) += tlb-sh3.o
25obj-$(CONFIG_CPU_SH4) += tlb-sh4.o pg-sh4.o 26obj-$(CONFIG_CPU_SH4) += tlb-sh4.o
26obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o 27obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o
27endif 28endif
28 29
diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c
index a08a4a958add..7d43758dc244 100644
--- a/arch/sh/mm/pmb.c
+++ b/arch/sh/mm/pmb.c
@@ -145,7 +145,7 @@ repeat:
145 145
146 ctrl_outl(vpn | PMB_V, mk_pmb_addr(pos)); 146 ctrl_outl(vpn | PMB_V, mk_pmb_addr(pos));
147 147
148#ifdef CONFIG_SH_WRITETHROUGH 148#ifdef CONFIG_CACHE_WRITETHROUGH
149 /* 149 /*
150 * When we are in 32-bit address extended mode, CCR.CB becomes 150 * When we are in 32-bit address extended mode, CCR.CB becomes
151 * invalid, so care must be taken to manually adjust cacheable 151 * invalid, so care must be taken to manually adjust cacheable
diff --git a/arch/sh/mm/tlb-sh4.c b/arch/sh/mm/tlb-sh4.c
index f74cf667c8fa..13fde8cc7179 100644
--- a/arch/sh/mm/tlb-sh4.c
+++ b/arch/sh/mm/tlb-sh4.c
@@ -34,22 +34,27 @@ void update_mmu_cache(struct vm_area_struct * vma,
34 unsigned long flags; 34 unsigned long flags;
35 unsigned long pteval; 35 unsigned long pteval;
36 unsigned long vpn; 36 unsigned long vpn;
37 struct page *page;
38 unsigned long pfn;
39 37
40 /* Ptrace may call this routine. */ 38 /* Ptrace may call this routine. */
41 if (vma && current->active_mm != vma->vm_mm) 39 if (vma && current->active_mm != vma->vm_mm)
42 return; 40 return;
43 41
44 pfn = pte_pfn(pte); 42#ifndef CONFIG_CACHE_OFF
45 if (pfn_valid(pfn)) { 43 {
46 page = pfn_to_page(pfn); 44 unsigned long pfn = pte_pfn(pte);
47 if (!test_bit(PG_mapped, &page->flags)) { 45
48 unsigned long phys = pte_val(pte) & PTE_PHYS_MASK; 46 if (pfn_valid(pfn)) {
49 __flush_wback_region((void *)P1SEGADDR(phys), PAGE_SIZE); 47 struct page *page = pfn_to_page(pfn);
50 __set_bit(PG_mapped, &page->flags); 48
49 if (!test_bit(PG_mapped, &page->flags)) {
50 unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
51 __flush_wback_region((void *)P1SEGADDR(phys),
52 PAGE_SIZE);
53 __set_bit(PG_mapped, &page->flags);
54 }
51 } 55 }
52 } 56 }
57#endif
53 58
54 local_irq_save(flags); 59 local_irq_save(flags);
55 60
@@ -66,7 +71,7 @@ void update_mmu_cache(struct vm_area_struct * vma,
66 71
67 /* Set PTEL register */ 72 /* Set PTEL register */
68 pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */ 73 pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
69#ifdef CONFIG_SH_WRITETHROUGH 74#ifdef CONFIG_CACHE_WRITETHROUGH
70 pteval |= _PAGE_WT; 75 pteval |= _PAGE_WT;
71#endif 76#endif
72 /* conveniently, we want all the software flags to be 0 anyway */ 77 /* conveniently, we want all the software flags to be 0 anyway */
diff --git a/include/asm-sh/cacheflush.h b/include/asm-sh/cacheflush.h
index 07f62ec9ff0c..aa558da08471 100644
--- a/include/asm-sh/cacheflush.h
+++ b/include/asm-sh/cacheflush.h
@@ -1,16 +1,47 @@
1#ifndef __ASM_SH_CACHEFLUSH_H 1#ifndef __ASM_SH_CACHEFLUSH_H
2#define __ASM_SH_CACHEFLUSH_H 2#define __ASM_SH_CACHEFLUSH_H
3
3#ifdef __KERNEL__ 4#ifdef __KERNEL__
4 5
5#include <linux/mm.h> 6#ifdef CONFIG_CACHE_OFF
7/*
8 * Nothing to do when the cache is disabled, initial flush and explicit
9 * disabling is handled at CPU init time.
10 *
11 * See arch/sh/kernel/cpu/init.c:cache_init().
12 */
13#define p3_cache_init() do { } while (0)
14#define flush_cache_all() do { } while (0)
15#define flush_cache_mm(mm) do { } while (0)
16#define flush_cache_dup_mm(mm) do { } while (0)
17#define flush_cache_range(vma, start, end) do { } while (0)
18#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
19#define flush_dcache_page(page) do { } while (0)
20#define flush_icache_range(start, end) do { } while (0)
21#define flush_icache_page(vma,pg) do { } while (0)
22#define flush_dcache_mmap_lock(mapping) do { } while (0)
23#define flush_dcache_mmap_unlock(mapping) do { } while (0)
24#define flush_cache_sigtramp(vaddr) do { } while (0)
25#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
26#define __flush_wback_region(start, size) do { (void)(start); } while (0)
27#define __flush_purge_region(start, size) do { (void)(start); } while (0)
28#define __flush_invalidate_region(start, size) do { (void)(start); } while (0)
29#else
6#include <asm/cpu/cacheflush.h> 30#include <asm/cpu/cacheflush.h>
7 31
32/*
33 * Consistent DMA requires that the __flush_xxx() primitives must be set
34 * for any of the enabled non-coherent caches (most of the UP CPUs),
35 * regardless of PIPT or VIPT cache configurations.
36 */
37
8/* Flush (write-back only) a region (smaller than a page) */ 38/* Flush (write-back only) a region (smaller than a page) */
9extern void __flush_wback_region(void *start, int size); 39extern void __flush_wback_region(void *start, int size);
10/* Flush (write-back & invalidate) a region (smaller than a page) */ 40/* Flush (write-back & invalidate) a region (smaller than a page) */
11extern void __flush_purge_region(void *start, int size); 41extern void __flush_purge_region(void *start, int size);
12/* Flush (invalidate only) a region (smaller than a page) */ 42/* Flush (invalidate only) a region (smaller than a page) */
13extern void __flush_invalidate_region(void *start, int size); 43extern void __flush_invalidate_region(void *start, int size);
44#endif
14 45
15#define flush_cache_vmap(start, end) flush_cache_all() 46#define flush_cache_vmap(start, end) flush_cache_all()
16#define flush_cache_vunmap(start, end) flush_cache_all() 47#define flush_cache_vunmap(start, end) flush_cache_all()
diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h
index 6bc9bba10105..48b718e7455c 100644
--- a/include/asm-sh/page.h
+++ b/include/asm-sh/page.h
@@ -70,14 +70,14 @@ extern void clear_page_nommu(void *to);
70extern void copy_page_nommu(void *to, void *from); 70extern void copy_page_nommu(void *to, void *from);
71#endif 71#endif
72 72
73#if defined(CONFIG_MMU) && (defined(CONFIG_CPU_SH4) || \ 73#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \
74 defined(CONFIG_SH7705_CACHE_32KB)) 74 (defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB))
75struct page; 75struct page;
76extern void clear_user_page(void *to, unsigned long address, struct page *pg); 76extern void clear_user_page(void *to, unsigned long address, struct page *pg);
77extern void copy_user_page(void *to, void *from, unsigned long address, struct page *pg); 77extern void copy_user_page(void *to, void *from, unsigned long address, struct page *pg);
78extern void __clear_user_page(void *to, void *orig_to); 78extern void __clear_user_page(void *to, void *orig_to);
79extern void __copy_user_page(void *to, void *from, void *orig_to); 79extern void __copy_user_page(void *to, void *from, void *orig_to);
80#elif defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH3) || !defined(CONFIG_MMU) 80#else
81#define clear_user_page(page, vaddr, pg) clear_page(page) 81#define clear_user_page(page, vaddr, pg) clear_page(page)
82#define copy_user_page(to, from, vaddr, pg) copy_page(to, from) 82#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
83#endif 83#endif
diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
index e3fae12c0e49..54ad5037fe40 100644
--- a/include/asm-sh/pgtable.h
+++ b/include/asm-sh/pgtable.h
@@ -563,7 +563,8 @@ struct mm_struct;
563extern unsigned int kobjsize(const void *objp); 563extern unsigned int kobjsize(const void *objp);
564#endif /* !CONFIG_MMU */ 564#endif /* !CONFIG_MMU */
565 565
566#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) 566#if !defined(CONFIG_CACHE_OFF) && (defined(CONFIG_CPU_SH4) || \
567 defined(CONFIG_SH7705_CACHE_32KB))
567#define __HAVE_ARCH_PTEP_GET_AND_CLEAR 568#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
568extern pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep); 569extern pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
569#endif 570#endif