diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2009-03-26 19:10:11 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-03-26 19:10:11 -0400 |
commit | 542f869f1826f092606efd0c4c771f070d1314f5 (patch) | |
tree | 9c9d265ab0c87ea7862ccb70933f33d3d7011334 /arch/arm/mm | |
parent | e8b374bb6c888a70530d800c9e2fcd153e2c325d (diff) | |
parent | 839e642f3dda44a35c6a91780bff41d84c288022 (diff) |
Merge branch 'for-rmk' of git://gitorious.org/linux-gemini/mainline into devel
Conflicts:
arch/arm/mm/Kconfig
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mm')
-rw-r--r-- | arch/arm/mm/Kconfig | 35 | ||||
-rw-r--r-- | arch/arm/mm/Makefile | 4 | ||||
-rw-r--r-- | arch/arm/mm/cache-fa.S | 220 | ||||
-rw-r--r-- | arch/arm/mm/copypage-fa.c | 86 | ||||
-rw-r--r-- | arch/arm/mm/proc-fa526.S | 248 | ||||
-rw-r--r-- | arch/arm/mm/tlb-fa.S | 75 |
6 files changed, 666 insertions, 2 deletions
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index a6230f7a24c8..20979564e7ee 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
@@ -186,6 +186,24 @@ config CPU_ARM926T | |||
186 | Say Y if you want support for the ARM926T processor. | 186 | Say Y if you want support for the ARM926T processor. |
187 | Otherwise, say N. | 187 | Otherwise, say N. |
188 | 188 | ||
189 | # FA526 | ||
190 | config CPU_FA526 | ||
191 | bool | ||
192 | select CPU_32v4 | ||
193 | select CPU_ABRT_EV4 | ||
194 | select CPU_PABRT_NOIFAR | ||
195 | select CPU_CACHE_VIVT | ||
196 | select CPU_CP15_MMU | ||
197 | select CPU_CACHE_FA | ||
198 | select CPU_COPY_FA if MMU | ||
199 | select CPU_TLB_FA if MMU | ||
200 | help | ||
201 | The FA526 is a version of the ARMv4 compatible processor with | ||
202 | Branch Target Buffer, Unified TLB and cache line size 16. | ||
203 | |||
204 | Say Y if you want support for the FA526 processor. | ||
205 | Otherwise, say N. | ||
206 | |||
189 | # ARM940T | 207 | # ARM940T |
190 | config CPU_ARM940T | 208 | config CPU_ARM940T |
191 | bool "Support ARM940T processor" if ARCH_INTEGRATOR | 209 | bool "Support ARM940T processor" if ARCH_INTEGRATOR |
@@ -495,6 +513,9 @@ config CPU_CACHE_VIVT | |||
495 | config CPU_CACHE_VIPT | 513 | config CPU_CACHE_VIPT |
496 | bool | 514 | bool |
497 | 515 | ||
516 | config CPU_CACHE_FA | ||
517 | bool | ||
518 | |||
498 | if MMU | 519 | if MMU |
499 | # The copy-page model | 520 | # The copy-page model |
500 | config CPU_COPY_V3 | 521 | config CPU_COPY_V3 |
@@ -509,6 +530,9 @@ config CPU_COPY_V4WB | |||
509 | config CPU_COPY_FEROCEON | 530 | config CPU_COPY_FEROCEON |
510 | bool | 531 | bool |
511 | 532 | ||
533 | config CPU_COPY_FA | ||
534 | bool | ||
535 | |||
512 | config CPU_COPY_V6 | 536 | config CPU_COPY_V6 |
513 | bool | 537 | bool |
514 | 538 | ||
@@ -539,6 +563,13 @@ config CPU_TLB_FEROCEON | |||
539 | help | 563 | help |
540 | Feroceon TLB (v4wbi with non-outer-cachable page table walks). | 564 | Feroceon TLB (v4wbi with non-outer-cachable page table walks). |
541 | 565 | ||
566 | config CPU_TLB_FA | ||
567 | bool | ||
568 | help | ||
569 | Faraday ARM FA526 architecture, unified TLB with writeback cache | ||
570 | and invalidate instruction cache entry. Branch target buffer is | ||
571 | also supported. | ||
572 | |||
542 | config CPU_TLB_V6 | 573 | config CPU_TLB_V6 |
543 | bool | 574 | bool |
544 | 575 | ||
@@ -649,7 +680,7 @@ config CPU_DCACHE_SIZE | |||
649 | 680 | ||
650 | config CPU_DCACHE_WRITETHROUGH | 681 | config CPU_DCACHE_WRITETHROUGH |
651 | bool "Force write through D-cache" | 682 | bool "Force write through D-cache" |
652 | depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020) && !CPU_DCACHE_DISABLE | 683 | depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_FA526) && !CPU_DCACHE_DISABLE |
653 | default y if CPU_ARM925T | 684 | default y if CPU_ARM925T |
654 | help | 685 | help |
655 | Say Y here to use the data cache in writethrough mode. Unless you | 686 | Say Y here to use the data cache in writethrough mode. Unless you |
@@ -664,7 +695,7 @@ config CPU_CACHE_ROUND_ROBIN | |||
664 | 695 | ||
665 | config CPU_BPREDICT_DISABLE | 696 | config CPU_BPREDICT_DISABLE |
666 | bool "Disable branch prediction" | 697 | bool "Disable branch prediction" |
667 | depends on CPU_ARM1020 || CPU_V6 || CPU_MOHAWK || CPU_XSC3 || CPU_V7 | 698 | depends on CPU_ARM1020 || CPU_V6 || CPU_MOHAWK || CPU_XSC3 || CPU_V7 || CPU_FA526 |
668 | help | 699 | help |
669 | Say Y here to disable branch prediction. If unsure, say N. | 700 | Say Y here to disable branch prediction. If unsure, say N. |
670 | 701 | ||
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index c264683538bc..63e3f6dd0e21 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile | |||
@@ -33,6 +33,7 @@ obj-$(CONFIG_CPU_CACHE_V4WT) += cache-v4wt.o | |||
33 | obj-$(CONFIG_CPU_CACHE_V4WB) += cache-v4wb.o | 33 | obj-$(CONFIG_CPU_CACHE_V4WB) += cache-v4wb.o |
34 | obj-$(CONFIG_CPU_CACHE_V6) += cache-v6.o | 34 | obj-$(CONFIG_CPU_CACHE_V6) += cache-v6.o |
35 | obj-$(CONFIG_CPU_CACHE_V7) += cache-v7.o | 35 | obj-$(CONFIG_CPU_CACHE_V7) += cache-v7.o |
36 | obj-$(CONFIG_CPU_CACHE_FA) += cache-fa.o | ||
36 | 37 | ||
37 | obj-$(CONFIG_CPU_COPY_V3) += copypage-v3.o | 38 | obj-$(CONFIG_CPU_COPY_V3) += copypage-v3.o |
38 | obj-$(CONFIG_CPU_COPY_V4WT) += copypage-v4wt.o | 39 | obj-$(CONFIG_CPU_COPY_V4WT) += copypage-v4wt.o |
@@ -42,6 +43,7 @@ obj-$(CONFIG_CPU_COPY_V6) += copypage-v6.o context.o | |||
42 | obj-$(CONFIG_CPU_SA1100) += copypage-v4mc.o | 43 | obj-$(CONFIG_CPU_SA1100) += copypage-v4mc.o |
43 | obj-$(CONFIG_CPU_XSCALE) += copypage-xscale.o | 44 | obj-$(CONFIG_CPU_XSCALE) += copypage-xscale.o |
44 | obj-$(CONFIG_CPU_XSC3) += copypage-xsc3.o | 45 | obj-$(CONFIG_CPU_XSC3) += copypage-xsc3.o |
46 | obj-$(CONFIG_CPU_COPY_FA) += copypage-fa.o | ||
45 | 47 | ||
46 | obj-$(CONFIG_CPU_TLB_V3) += tlb-v3.o | 48 | obj-$(CONFIG_CPU_TLB_V3) += tlb-v3.o |
47 | obj-$(CONFIG_CPU_TLB_V4WT) += tlb-v4.o | 49 | obj-$(CONFIG_CPU_TLB_V4WT) += tlb-v4.o |
@@ -50,6 +52,7 @@ obj-$(CONFIG_CPU_TLB_V4WBI) += tlb-v4wbi.o | |||
50 | obj-$(CONFIG_CPU_TLB_FEROCEON) += tlb-v4wbi.o # reuse v4wbi TLB functions | 52 | obj-$(CONFIG_CPU_TLB_FEROCEON) += tlb-v4wbi.o # reuse v4wbi TLB functions |
51 | obj-$(CONFIG_CPU_TLB_V6) += tlb-v6.o | 53 | obj-$(CONFIG_CPU_TLB_V6) += tlb-v6.o |
52 | obj-$(CONFIG_CPU_TLB_V7) += tlb-v7.o | 54 | obj-$(CONFIG_CPU_TLB_V7) += tlb-v7.o |
55 | obj-$(CONFIG_CPU_TLB_FA) += tlb-fa.o | ||
53 | 56 | ||
54 | obj-$(CONFIG_CPU_ARM610) += proc-arm6_7.o | 57 | obj-$(CONFIG_CPU_ARM610) += proc-arm6_7.o |
55 | obj-$(CONFIG_CPU_ARM710) += proc-arm6_7.o | 58 | obj-$(CONFIG_CPU_ARM710) += proc-arm6_7.o |
@@ -63,6 +66,7 @@ obj-$(CONFIG_CPU_ARM925T) += proc-arm925.o | |||
63 | obj-$(CONFIG_CPU_ARM926T) += proc-arm926.o | 66 | obj-$(CONFIG_CPU_ARM926T) += proc-arm926.o |
64 | obj-$(CONFIG_CPU_ARM940T) += proc-arm940.o | 67 | obj-$(CONFIG_CPU_ARM940T) += proc-arm940.o |
65 | obj-$(CONFIG_CPU_ARM946E) += proc-arm946.o | 68 | obj-$(CONFIG_CPU_ARM946E) += proc-arm946.o |
69 | obj-$(CONFIG_CPU_FA526) += proc-fa526.o | ||
66 | obj-$(CONFIG_CPU_ARM1020) += proc-arm1020.o | 70 | obj-$(CONFIG_CPU_ARM1020) += proc-arm1020.o |
67 | obj-$(CONFIG_CPU_ARM1020E) += proc-arm1020e.o | 71 | obj-$(CONFIG_CPU_ARM1020E) += proc-arm1020e.o |
68 | obj-$(CONFIG_CPU_ARM1022) += proc-arm1022.o | 72 | obj-$(CONFIG_CPU_ARM1022) += proc-arm1022.o |
diff --git a/arch/arm/mm/cache-fa.S b/arch/arm/mm/cache-fa.S new file mode 100644 index 000000000000..b63a8f7b95cf --- /dev/null +++ b/arch/arm/mm/cache-fa.S | |||
@@ -0,0 +1,220 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mm/cache-fa.S | ||
3 | * | ||
4 | * Copyright (C) 2005 Faraday Corp. | ||
5 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
6 | * | ||
7 | * Based on cache-v4wb.S: | ||
8 | * Copyright (C) 1997-2002 Russell king | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * Processors: FA520 FA526 FA626 | ||
15 | */ | ||
16 | #include <linux/linkage.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <asm/memory.h> | ||
19 | #include <asm/page.h> | ||
20 | |||
21 | #include "proc-macros.S" | ||
22 | |||
23 | /* | ||
24 | * The size of one data cache line. | ||
25 | */ | ||
26 | #define CACHE_DLINESIZE 16 | ||
27 | |||
28 | /* | ||
29 | * The total size of the data cache. | ||
30 | */ | ||
31 | #ifdef CONFIG_ARCH_GEMINI | ||
32 | #define CACHE_DSIZE 8192 | ||
33 | #else | ||
34 | #define CACHE_DSIZE 16384 | ||
35 | #endif | ||
36 | |||
37 | /* FIXME: put optimal value here. Current one is just estimation */ | ||
38 | #define CACHE_DLIMIT (CACHE_DSIZE * 2) | ||
39 | |||
40 | /* | ||
41 | * flush_user_cache_all() | ||
42 | * | ||
43 | * Clean and invalidate all cache entries in a particular address | ||
44 | * space. | ||
45 | */ | ||
46 | ENTRY(fa_flush_user_cache_all) | ||
47 | /* FALLTHROUGH */ | ||
48 | /* | ||
49 | * flush_kern_cache_all() | ||
50 | * | ||
51 | * Clean and invalidate the entire cache. | ||
52 | */ | ||
53 | ENTRY(fa_flush_kern_cache_all) | ||
54 | mov ip, #0 | ||
55 | mov r2, #VM_EXEC | ||
56 | __flush_whole_cache: | ||
57 | mcr p15, 0, ip, c7, c14, 0 @ clean/invalidate D cache | ||
58 | tst r2, #VM_EXEC | ||
59 | mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache | ||
60 | mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB | ||
61 | mcrne p15, 0, ip, c7, c10, 4 @ drain write buffer | ||
62 | mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush | ||
63 | mov pc, lr | ||
64 | |||
65 | /* | ||
66 | * flush_user_cache_range(start, end, flags) | ||
67 | * | ||
68 | * Invalidate a range of cache entries in the specified | ||
69 | * address space. | ||
70 | * | ||
71 | * - start - start address (inclusive, page aligned) | ||
72 | * - end - end address (exclusive, page aligned) | ||
73 | * - flags - vma_area_struct flags describing address space | ||
74 | */ | ||
75 | ENTRY(fa_flush_user_cache_range) | ||
76 | mov ip, #0 | ||
77 | sub r3, r1, r0 @ calculate total size | ||
78 | cmp r3, #CACHE_DLIMIT @ total size >= limit? | ||
79 | bhs __flush_whole_cache @ flush whole D cache | ||
80 | |||
81 | 1: tst r2, #VM_EXEC | ||
82 | mcrne p15, 0, r0, c7, c5, 1 @ invalidate I line | ||
83 | mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry | ||
84 | add r0, r0, #CACHE_DLINESIZE | ||
85 | cmp r0, r1 | ||
86 | blo 1b | ||
87 | tst r2, #VM_EXEC | ||
88 | mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB | ||
89 | mcrne p15, 0, ip, c7, c10, 4 @ data write barrier | ||
90 | mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush | ||
91 | mov pc, lr | ||
92 | |||
93 | /* | ||
94 | * coherent_kern_range(start, end) | ||
95 | * | ||
96 | * Ensure coherency between the Icache and the Dcache in the | ||
97 | * region described by start. If you have non-snooping | ||
98 | * Harvard caches, you need to implement this function. | ||
99 | * | ||
100 | * - start - virtual start address | ||
101 | * - end - virtual end address | ||
102 | */ | ||
103 | ENTRY(fa_coherent_kern_range) | ||
104 | /* fall through */ | ||
105 | |||
106 | /* | ||
107 | * coherent_user_range(start, end) | ||
108 | * | ||
109 | * Ensure coherency between the Icache and the Dcache in the | ||
110 | * region described by start. If you have non-snooping | ||
111 | * Harvard caches, you need to implement this function. | ||
112 | * | ||
113 | * - start - virtual start address | ||
114 | * - end - virtual end address | ||
115 | */ | ||
116 | ENTRY(fa_coherent_user_range) | ||
117 | bic r0, r0, #CACHE_DLINESIZE - 1 | ||
118 | 1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry | ||
119 | mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry | ||
120 | add r0, r0, #CACHE_DLINESIZE | ||
121 | cmp r0, r1 | ||
122 | blo 1b | ||
123 | mov r0, #0 | ||
124 | mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB | ||
125 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | ||
126 | mcr p15, 0, r0, c7, c5, 4 @ prefetch flush | ||
127 | mov pc, lr | ||
128 | |||
129 | /* | ||
130 | * flush_kern_dcache_page(kaddr) | ||
131 | * | ||
132 | * Ensure that the data held in the page kaddr is written back | ||
133 | * to the page in question. | ||
134 | * | ||
135 | * - kaddr - kernel address (guaranteed to be page aligned) | ||
136 | */ | ||
137 | ENTRY(fa_flush_kern_dcache_page) | ||
138 | add r1, r0, #PAGE_SZ | ||
139 | 1: mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line | ||
140 | add r0, r0, #CACHE_DLINESIZE | ||
141 | cmp r0, r1 | ||
142 | blo 1b | ||
143 | mov r0, #0 | ||
144 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache | ||
145 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | ||
146 | mov pc, lr | ||
147 | |||
148 | /* | ||
149 | * dma_inv_range(start, end) | ||
150 | * | ||
151 | * Invalidate (discard) the specified virtual address range. | ||
152 | * May not write back any entries. If 'start' or 'end' | ||
153 | * are not cache line aligned, those lines must be written | ||
154 | * back. | ||
155 | * | ||
156 | * - start - virtual start address | ||
157 | * - end - virtual end address | ||
158 | */ | ||
159 | ENTRY(fa_dma_inv_range) | ||
160 | tst r0, #CACHE_DLINESIZE - 1 | ||
161 | bic r0, r0, #CACHE_DLINESIZE - 1 | ||
162 | mcrne p15, 0, r0, c7, c14, 1 @ clean & invalidate D entry | ||
163 | tst r1, #CACHE_DLINESIZE - 1 | ||
164 | bic r1, r1, #CACHE_DLINESIZE - 1 | ||
165 | mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D entry | ||
166 | 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry | ||
167 | add r0, r0, #CACHE_DLINESIZE | ||
168 | cmp r0, r1 | ||
169 | blo 1b | ||
170 | mov r0, #0 | ||
171 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | ||
172 | mov pc, lr | ||
173 | |||
174 | /* | ||
175 | * dma_clean_range(start, end) | ||
176 | * | ||
177 | * Clean (write back) the specified virtual address range. | ||
178 | * | ||
179 | * - start - virtual start address | ||
180 | * - end - virtual end address | ||
181 | */ | ||
182 | ENTRY(fa_dma_clean_range) | ||
183 | bic r0, r0, #CACHE_DLINESIZE - 1 | ||
184 | 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry | ||
185 | add r0, r0, #CACHE_DLINESIZE | ||
186 | cmp r0, r1 | ||
187 | blo 1b | ||
188 | mov r0, #0 | ||
189 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | ||
190 | mov pc, lr | ||
191 | |||
192 | /* | ||
193 | * dma_flush_range(start,end) | ||
194 | * - start - virtual start address of region | ||
195 | * - end - virtual end address of region | ||
196 | */ | ||
197 | ENTRY(fa_dma_flush_range) | ||
198 | bic r0, r0, #CACHE_DLINESIZE - 1 | ||
199 | 1: mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D entry | ||
200 | add r0, r0, #CACHE_DLINESIZE | ||
201 | cmp r0, r1 | ||
202 | blo 1b | ||
203 | mov r0, #0 | ||
204 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | ||
205 | mov pc, lr | ||
206 | |||
207 | __INITDATA | ||
208 | |||
209 | .type fa_cache_fns, #object | ||
210 | ENTRY(fa_cache_fns) | ||
211 | .long fa_flush_kern_cache_all | ||
212 | .long fa_flush_user_cache_all | ||
213 | .long fa_flush_user_cache_range | ||
214 | .long fa_coherent_kern_range | ||
215 | .long fa_coherent_user_range | ||
216 | .long fa_flush_kern_dcache_page | ||
217 | .long fa_dma_inv_range | ||
218 | .long fa_dma_clean_range | ||
219 | .long fa_dma_flush_range | ||
220 | .size fa_cache_fns, . - fa_cache_fns | ||
diff --git a/arch/arm/mm/copypage-fa.c b/arch/arm/mm/copypage-fa.c new file mode 100644 index 000000000000..b2a6008b0111 --- /dev/null +++ b/arch/arm/mm/copypage-fa.c | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/lib/copypage-fa.S | ||
3 | * | ||
4 | * Copyright (C) 2005 Faraday Corp. | ||
5 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
6 | * | ||
7 | * Based on copypage-v4wb.S: | ||
8 | * Copyright (C) 1995-1999 Russell King | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/highmem.h> | ||
16 | |||
17 | /* | ||
18 | * Faraday optimised copy_user_page | ||
19 | */ | ||
20 | static void __naked | ||
21 | fa_copy_user_page(void *kto, const void *kfrom) | ||
22 | { | ||
23 | asm("\ | ||
24 | stmfd sp!, {r4, lr} @ 2\n\ | ||
25 | mov r2, %0 @ 1\n\ | ||
26 | 1: ldmia r1!, {r3, r4, ip, lr} @ 4\n\ | ||
27 | stmia r0, {r3, r4, ip, lr} @ 4\n\ | ||
28 | mcr p15, 0, r0, c7, c14, 1 @ 1 clean and invalidate D line\n\ | ||
29 | add r0, r0, #16 @ 1\n\ | ||
30 | ldmia r1!, {r3, r4, ip, lr} @ 4\n\ | ||
31 | stmia r0, {r3, r4, ip, lr} @ 4\n\ | ||
32 | mcr p15, 0, r0, c7, c14, 1 @ 1 clean and invalidate D line\n\ | ||
33 | add r0, r0, #16 @ 1\n\ | ||
34 | subs r2, r2, #1 @ 1\n\ | ||
35 | bne 1b @ 1\n\ | ||
36 | mcr p15, 0, r2, c7, c10, 4 @ 1 drain WB\n\ | ||
37 | ldmfd sp!, {r4, pc} @ 3" | ||
38 | : | ||
39 | : "I" (PAGE_SIZE / 32)); | ||
40 | } | ||
41 | |||
42 | void fa_copy_user_highpage(struct page *to, struct page *from, | ||
43 | unsigned long vaddr) | ||
44 | { | ||
45 | void *kto, *kfrom; | ||
46 | |||
47 | kto = kmap_atomic(to, KM_USER0); | ||
48 | kfrom = kmap_atomic(from, KM_USER1); | ||
49 | fa_copy_user_page(kto, kfrom); | ||
50 | kunmap_atomic(kfrom, KM_USER1); | ||
51 | kunmap_atomic(kto, KM_USER0); | ||
52 | } | ||
53 | |||
54 | /* | ||
55 | * Faraday optimised clear_user_page | ||
56 | * | ||
57 | * Same story as above. | ||
58 | */ | ||
59 | void fa_clear_user_highpage(struct page *page, unsigned long vaddr) | ||
60 | { | ||
61 | void *ptr, *kaddr = kmap_atomic(page, KM_USER0); | ||
62 | asm volatile("\ | ||
63 | mov r1, %2 @ 1\n\ | ||
64 | mov r2, #0 @ 1\n\ | ||
65 | mov r3, #0 @ 1\n\ | ||
66 | mov ip, #0 @ 1\n\ | ||
67 | mov lr, #0 @ 1\n\ | ||
68 | 1: stmia %0, {r2, r3, ip, lr} @ 4\n\ | ||
69 | mcr p15, 0, %0, c7, c14, 1 @ 1 clean and invalidate D line\n\ | ||
70 | add %0, %0, #16 @ 1\n\ | ||
71 | stmia %0, {r2, r3, ip, lr} @ 4\n\ | ||
72 | mcr p15, 0, %0, c7, c14, 1 @ 1 clean and invalidate D line\n\ | ||
73 | add %0, %0, #16 @ 1\n\ | ||
74 | subs r1, r1, #1 @ 1\n\ | ||
75 | bne 1b @ 1\n\ | ||
76 | mcr p15, 0, r1, c7, c10, 4 @ 1 drain WB" | ||
77 | : "=r" (ptr) | ||
78 | : "0" (kaddr), "I" (PAGE_SIZE / 32) | ||
79 | : "r1", "r2", "r3", "ip", "lr"); | ||
80 | kunmap_atomic(kaddr, KM_USER0); | ||
81 | } | ||
82 | |||
83 | struct cpu_user_fns fa_user_fns __initdata = { | ||
84 | .cpu_clear_user_highpage = fa_clear_user_highpage, | ||
85 | .cpu_copy_user_highpage = fa_copy_user_highpage, | ||
86 | }; | ||
diff --git a/arch/arm/mm/proc-fa526.S b/arch/arm/mm/proc-fa526.S new file mode 100644 index 000000000000..08b8a955d5d7 --- /dev/null +++ b/arch/arm/mm/proc-fa526.S | |||
@@ -0,0 +1,248 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mm/proc-fa526.S: MMU functions for FA526 | ||
3 | * | ||
4 | * Written by : Luke Lee | ||
5 | * Copyright (C) 2005 Faraday Corp. | ||
6 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * | ||
14 | * These are the low level assembler for performing cache and TLB | ||
15 | * functions on the fa526. | ||
16 | */ | ||
17 | #include <linux/linkage.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <asm/assembler.h> | ||
20 | #include <asm/hwcap.h> | ||
21 | #include <asm/pgtable-hwdef.h> | ||
22 | #include <asm/pgtable.h> | ||
23 | #include <asm/page.h> | ||
24 | #include <asm/ptrace.h> | ||
25 | #include <asm/system.h> | ||
26 | |||
27 | #include "proc-macros.S" | ||
28 | |||
29 | #define CACHE_DLINESIZE 16 | ||
30 | |||
31 | .text | ||
32 | /* | ||
33 | * cpu_fa526_proc_init() | ||
34 | */ | ||
35 | ENTRY(cpu_fa526_proc_init) | ||
36 | mov pc, lr | ||
37 | |||
38 | /* | ||
39 | * cpu_fa526_proc_fin() | ||
40 | */ | ||
41 | ENTRY(cpu_fa526_proc_fin) | ||
42 | stmfd sp!, {lr} | ||
43 | mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE | ||
44 | msr cpsr_c, ip | ||
45 | bl fa_flush_kern_cache_all | ||
46 | mrc p15, 0, r0, c1, c0, 0 @ ctrl register | ||
47 | bic r0, r0, #0x1000 @ ...i............ | ||
48 | bic r0, r0, #0x000e @ ............wca. | ||
49 | mcr p15, 0, r0, c1, c0, 0 @ disable caches | ||
50 | nop | ||
51 | nop | ||
52 | ldmfd sp!, {pc} | ||
53 | |||
54 | /* | ||
55 | * cpu_fa526_reset(loc) | ||
56 | * | ||
57 | * Perform a soft reset of the system. Put the CPU into the | ||
58 | * same state as it would be if it had been reset, and branch | ||
59 | * to what would be the reset vector. | ||
60 | * | ||
61 | * loc: location to jump to for soft reset | ||
62 | */ | ||
63 | .align 4 | ||
64 | ENTRY(cpu_fa526_reset) | ||
65 | /* TODO: Use CP8 if possible... */ | ||
66 | mov ip, #0 | ||
67 | mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches | ||
68 | mcr p15, 0, ip, c7, c10, 4 @ drain WB | ||
69 | #ifdef CONFIG_MMU | ||
70 | mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs | ||
71 | #endif | ||
72 | mrc p15, 0, ip, c1, c0, 0 @ ctrl register | ||
73 | bic ip, ip, #0x000f @ ............wcam | ||
74 | bic ip, ip, #0x1100 @ ...i...s........ | ||
75 | bic ip, ip, #0x0800 @ BTB off | ||
76 | mcr p15, 0, ip, c1, c0, 0 @ ctrl register | ||
77 | nop | ||
78 | nop | ||
79 | mov pc, r0 | ||
80 | |||
81 | /* | ||
82 | * cpu_fa526_do_idle() | ||
83 | */ | ||
84 | .align 4 | ||
85 | ENTRY(cpu_fa526_do_idle) | ||
86 | mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt | ||
87 | mov pc, lr | ||
88 | |||
89 | |||
90 | ENTRY(cpu_fa526_dcache_clean_area) | ||
91 | 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry | ||
92 | add r0, r0, #CACHE_DLINESIZE | ||
93 | subs r1, r1, #CACHE_DLINESIZE | ||
94 | bhi 1b | ||
95 | mcr p15, 0, r0, c7, c10, 4 @ drain WB | ||
96 | mov pc, lr | ||
97 | |||
98 | /* =============================== PageTable ============================== */ | ||
99 | |||
100 | /* | ||
101 | * cpu_fa526_switch_mm(pgd) | ||
102 | * | ||
103 | * Set the translation base pointer to be as described by pgd. | ||
104 | * | ||
105 | * pgd: new page tables | ||
106 | */ | ||
107 | .align 4 | ||
108 | ENTRY(cpu_fa526_switch_mm) | ||
109 | #ifdef CONFIG_MMU | ||
110 | mov ip, #0 | ||
111 | #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH | ||
112 | mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache | ||
113 | #else | ||
114 | mcr p15, 0, ip, c7, c14, 0 @ clean and invalidate whole D cache | ||
115 | #endif | ||
116 | mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache | ||
117 | mcr p15, 0, ip, c7, c5, 6 @ invalidate BTB since mm changed | ||
118 | mcr p15, 0, ip, c7, c10, 4 @ data write barrier | ||
119 | mcr p15, 0, ip, c7, c5, 4 @ prefetch flush | ||
120 | mcr p15, 0, r0, c2, c0, 0 @ load page table pointer | ||
121 | mcr p15, 0, ip, c8, c7, 0 @ invalidate UTLB | ||
122 | #endif | ||
123 | mov pc, lr | ||
124 | |||
125 | /* | ||
126 | * cpu_fa526_set_pte_ext(ptep, pte, ext) | ||
127 | * | ||
128 | * Set a PTE and flush it out | ||
129 | */ | ||
130 | .align 4 | ||
131 | ENTRY(cpu_fa526_set_pte_ext) | ||
132 | #ifdef CONFIG_MMU | ||
133 | armv3_set_pte_ext | ||
134 | mov r0, r0 | ||
135 | mcr p15, 0, r0, c7, c10, 1 @ clean D entry | ||
136 | mov r0, #0 | ||
137 | mcr p15, 0, r0, c7, c10, 4 @ drain WB | ||
138 | #endif | ||
139 | mov pc, lr | ||
140 | |||
141 | __INIT | ||
142 | |||
143 | .type __fa526_setup, #function | ||
144 | __fa526_setup: | ||
145 | /* On return of this routine, r0 must carry correct flags for CFG register */ | ||
146 | mov r0, #0 | ||
147 | mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4 | ||
148 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 | ||
149 | #ifdef CONFIG_MMU | ||
150 | mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4 | ||
151 | #endif | ||
152 | mcr p15, 0, r0, c7, c5, 5 @ invalidate IScratchpad RAM | ||
153 | |||
154 | mov r0, #1 | ||
155 | mcr p15, 0, r0, c1, c1, 0 @ turn-on ECR | ||
156 | |||
157 | mov r0, #0 | ||
158 | mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB All | ||
159 | mcr p15, 0, r0, c7, c10, 4 @ data write barrier | ||
160 | mcr p15, 0, r0, c7, c5, 4 @ prefetch flush | ||
161 | |||
162 | mov r0, #0x1f @ Domains 0, 1 = manager, 2 = client | ||
163 | mcr p15, 0, r0, c3, c0 @ load domain access register | ||
164 | |||
165 | mrc p15, 0, r0, c1, c0 @ get control register v4 | ||
166 | ldr r5, fa526_cr1_clear | ||
167 | bic r0, r0, r5 | ||
168 | ldr r5, fa526_cr1_set | ||
169 | orr r0, r0, r5 | ||
170 | mov pc, lr | ||
171 | .size __fa526_setup, . - __fa526_setup | ||
172 | |||
173 | /* | ||
174 | * .RVI ZFRS BLDP WCAM | ||
175 | * ..11 1001 .111 1101 | ||
176 | * | ||
177 | */ | ||
178 | .type fa526_cr1_clear, #object | ||
179 | .type fa526_cr1_set, #object | ||
180 | fa526_cr1_clear: | ||
181 | .word 0x3f3f | ||
182 | fa526_cr1_set: | ||
183 | .word 0x397D | ||
184 | |||
185 | __INITDATA | ||
186 | |||
187 | /* | ||
188 | * Purpose : Function pointers used to access above functions - all calls | ||
189 | * come through these | ||
190 | */ | ||
191 | .type fa526_processor_functions, #object | ||
192 | fa526_processor_functions: | ||
193 | .word v4_early_abort | ||
194 | .word pabort_noifar | ||
195 | .word cpu_fa526_proc_init | ||
196 | .word cpu_fa526_proc_fin | ||
197 | .word cpu_fa526_reset | ||
198 | .word cpu_fa526_do_idle | ||
199 | .word cpu_fa526_dcache_clean_area | ||
200 | .word cpu_fa526_switch_mm | ||
201 | .word cpu_fa526_set_pte_ext | ||
202 | .size fa526_processor_functions, . - fa526_processor_functions | ||
203 | |||
204 | .section ".rodata" | ||
205 | |||
206 | .type cpu_arch_name, #object | ||
207 | cpu_arch_name: | ||
208 | .asciz "armv4" | ||
209 | .size cpu_arch_name, . - cpu_arch_name | ||
210 | |||
211 | .type cpu_elf_name, #object | ||
212 | cpu_elf_name: | ||
213 | .asciz "v4" | ||
214 | .size cpu_elf_name, . - cpu_elf_name | ||
215 | |||
216 | .type cpu_fa526_name, #object | ||
217 | cpu_fa526_name: | ||
218 | .asciz "FA526" | ||
219 | .size cpu_fa526_name, . - cpu_fa526_name | ||
220 | |||
221 | .align | ||
222 | |||
223 | .section ".proc.info.init", #alloc, #execinstr | ||
224 | |||
225 | .type __fa526_proc_info,#object | ||
226 | __fa526_proc_info: | ||
227 | .long 0x66015261 | ||
228 | .long 0xff01fff1 | ||
229 | .long PMD_TYPE_SECT | \ | ||
230 | PMD_SECT_BUFFERABLE | \ | ||
231 | PMD_SECT_CACHEABLE | \ | ||
232 | PMD_BIT4 | \ | ||
233 | PMD_SECT_AP_WRITE | \ | ||
234 | PMD_SECT_AP_READ | ||
235 | .long PMD_TYPE_SECT | \ | ||
236 | PMD_BIT4 | \ | ||
237 | PMD_SECT_AP_WRITE | \ | ||
238 | PMD_SECT_AP_READ | ||
239 | b __fa526_setup | ||
240 | .long cpu_arch_name | ||
241 | .long cpu_elf_name | ||
242 | .long HWCAP_SWP | HWCAP_HALF | ||
243 | .long cpu_fa526_name | ||
244 | .long fa526_processor_functions | ||
245 | .long fa_tlb_fns | ||
246 | .long fa_user_fns | ||
247 | .long fa_cache_fns | ||
248 | .size __fa526_proc_info, . - __fa526_proc_info | ||
diff --git a/arch/arm/mm/tlb-fa.S b/arch/arm/mm/tlb-fa.S new file mode 100644 index 000000000000..9694f1f6f485 --- /dev/null +++ b/arch/arm/mm/tlb-fa.S | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mm/tlb-fa.S | ||
3 | * | ||
4 | * Copyright (C) 2005 Faraday Corp. | ||
5 | * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
6 | * | ||
7 | * Based on tlb-v4wbi.S: | ||
8 | * Copyright (C) 1997-2002 Russell King | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * ARM architecture version 4, Faraday variation. | ||
15 | * This assume an unified TLBs, with a write buffer, and branch target buffer (BTB) | ||
16 | * | ||
17 | * Processors: FA520 FA526 FA626 | ||
18 | */ | ||
19 | #include <linux/linkage.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <asm/asm-offsets.h> | ||
22 | #include <asm/tlbflush.h> | ||
23 | #include "proc-macros.S" | ||
24 | |||
25 | |||
26 | /* | ||
27 | * flush_user_tlb_range(start, end, mm) | ||
28 | * | ||
29 | * Invalidate a range of TLB entries in the specified address space. | ||
30 | * | ||
31 | * - start - range start address | ||
32 | * - end - range end address | ||
33 | * - mm - mm_struct describing address space | ||
34 | */ | ||
35 | .align 4 | ||
36 | ENTRY(fa_flush_user_tlb_range) | ||
37 | vma_vm_mm ip, r2 | ||
38 | act_mm r3 @ get current->active_mm | ||
39 | eors r3, ip, r3 @ == mm ? | ||
40 | movne pc, lr @ no, we dont do anything | ||
41 | mov r3, #0 | ||
42 | mcr p15, 0, r3, c7, c10, 4 @ drain WB | ||
43 | bic r0, r0, #0x0ff | ||
44 | bic r0, r0, #0xf00 | ||
45 | 1: mcr p15, 0, r0, c8, c7, 1 @ invalidate UTLB entry | ||
46 | add r0, r0, #PAGE_SZ | ||
47 | cmp r0, r1 | ||
48 | blo 1b | ||
49 | mcr p15, 0, r3, c7, c5, 6 @ invalidate BTB | ||
50 | mcr p15, 0, r3, c7, c10, 4 @ data write barrier | ||
51 | mov pc, lr | ||
52 | |||
53 | |||
54 | ENTRY(fa_flush_kern_tlb_range) | ||
55 | mov r3, #0 | ||
56 | mcr p15, 0, r3, c7, c10, 4 @ drain WB | ||
57 | bic r0, r0, #0x0ff | ||
58 | bic r0, r0, #0xf00 | ||
59 | 1: mcr p15, 0, r0, c8, c7, 1 @ invalidate UTLB entry | ||
60 | add r0, r0, #PAGE_SZ | ||
61 | cmp r0, r1 | ||
62 | blo 1b | ||
63 | mcr p15, 0, r3, c7, c5, 6 @ invalidate BTB | ||
64 | mcr p15, 0, r3, c7, c10, 4 @ data write barrier | ||
65 | mcr p15, 0, r3, c7, c5, 4 @ prefetch flush | ||
66 | mov pc, lr | ||
67 | |||
68 | __INITDATA | ||
69 | |||
70 | .type fa_tlb_fns, #object | ||
71 | ENTRY(fa_tlb_fns) | ||
72 | .long fa_flush_user_tlb_range | ||
73 | .long fa_flush_kern_tlb_range | ||
74 | .long fa_tlb_flags | ||
75 | .size fa_tlb_fns, . - fa_tlb_fns | ||