diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-16 15:45:08 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-16 15:45:08 -0400 |
commit | 1b821bfb034c5db5af62b463e3001243905179ba (patch) | |
tree | a5c1090f41716a6912742c9bc960dc2d3ae82899 /arch/blackfin/mach-common | |
parent | a45fbc33137b11e479ea8b7d478a1d7e6488971b (diff) | |
parent | 1390da4ee75168b6e4d8354e93e3b5f0a0291f2f (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/blackfin-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/blackfin-2.6:
Blackfin arch: make sure cycles is marked as volatile so gcc doesnt reorder on us
Blackfin arch: disable CONFIG_HW_RANDOM and CONFIG_DAB in defconfig files
Blackfin arch: update cache flush prototypes with argument names to make them less mysterious
Blackfin arch: move bfin_addr_dcachable() and friends into the cacheflush header where it belongs
Blackfin arch: use the new bfin_addr_dcachable() function
Blackfin arch: fix bug - build kernel failed at head.S when reprogram clock on all platforms
Blackfin arch: unify/cleanup cache code
Blackfin arch: update AD7879 platform resources in board file
Blackfin arch: Zero out bss region in L1/L2 memory.
Blackfin arch: add read/write IO accessor functions to Blackfin
Blackfin arch: fix bug - some serial header files set RTS to an input when they should all be outputs
Diffstat (limited to 'arch/blackfin/mach-common')
-rw-r--r-- | arch/blackfin/mach-common/cache.S | 173 | ||||
-rw-r--r-- | arch/blackfin/mach-common/head.S | 54 |
2 files changed, 112 insertions, 115 deletions
diff --git a/arch/blackfin/mach-common/cache.S b/arch/blackfin/mach-common/cache.S index 85f8c79b3c37..db532181fbde 100644 --- a/arch/blackfin/mach-common/cache.S +++ b/arch/blackfin/mach-common/cache.S | |||
@@ -1,148 +1,91 @@ | |||
1 | /* | 1 | /* |
2 | * File: arch/blackfin/mach-common/cache.S | 2 | * Blackfin cache control code |
3 | * Based on: | ||
4 | * Author: LG Soft India | ||
5 | * | 3 | * |
6 | * Created: | 4 | * Copyright 2004-2008 Analog Devices Inc. |
7 | * Description: cache control support | ||
8 | * | 5 | * |
9 | * Modified: | 6 | * Enter bugs at http://blackfin.uclinux.org/ |
10 | * Copyright 2004-2006 Analog Devices Inc. | ||
11 | * | 7 | * |
12 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | 8 | * Licensed under the GPL-2 or later. |
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, see the file COPYING, or write | ||
26 | * to the Free Software Foundation, Inc., | ||
27 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
28 | */ | 9 | */ |
29 | 10 | ||
30 | #include <linux/linkage.h> | 11 | #include <linux/linkage.h> |
31 | #include <asm/cplb.h> | ||
32 | #include <asm/entry.h> | ||
33 | #include <asm/blackfin.h> | 12 | #include <asm/blackfin.h> |
34 | #include <asm/cache.h> | 13 | #include <asm/cache.h> |
14 | #include <asm/page.h> | ||
35 | 15 | ||
36 | .text | 16 | .text |
37 | 17 | ||
38 | /* | 18 | /* Since all L1 caches work the same way, we use the same method for flushing |
39 | * blackfin_cache_flush_range(start, end) | 19 | * them. Only the actual flush instruction differs. We write this in asm as |
40 | * Invalidate all cache lines assocoiated with this | 20 | * GCC can be hard to coax into writing nice hardware loops. |
41 | * area of memory. | ||
42 | * | 21 | * |
43 | * start: Start address | 22 | * Also, we assume the following register setup: |
44 | * end: End address | 23 | * R0 = start address |
24 | * R1 = end address | ||
45 | */ | 25 | */ |
46 | ENTRY(_blackfin_icache_flush_range) | 26 | .macro do_flush flushins:req optflushins optnopins label |
27 | |||
28 | /* end = ((end - 1) & -L1_CACHE_BYTES) + L1_CACHE_BYTES; */ | ||
29 | R1 += -1; | ||
47 | R2 = -L1_CACHE_BYTES; | 30 | R2 = -L1_CACHE_BYTES; |
48 | R2 = R0 & R2; | 31 | R1 = R1 & R2; |
49 | P0 = R2; | 32 | R1 += L1_CACHE_BYTES; |
50 | P1 = R1; | 33 | |
51 | CSYNC(R3); | 34 | /* count = (end - start) >> L1_CACHE_SHIFT */ |
52 | IFLUSH [P0]; | 35 | R2 = R1 - R0; |
36 | R2 >>= L1_CACHE_SHIFT; | ||
37 | P1 = R2; | ||
38 | |||
39 | .ifnb \label | ||
40 | \label : | ||
41 | .endif | ||
42 | P0 = R0; | ||
43 | LSETUP (1f, 2f) LC1 = P1; | ||
53 | 1: | 44 | 1: |
54 | IFLUSH [P0++]; | 45 | .ifnb \optflushins |
55 | CC = P0 < P1 (iu); | 46 | \optflushins [P0]; |
56 | IF CC JUMP 1b (bp); | 47 | .endif |
57 | IFLUSH [P0]; | 48 | .ifb \optnopins |
58 | SSYNC(R3); | 49 | 2: |
50 | .endif | ||
51 | \flushins [P0++]; | ||
52 | .ifnb \optnopins | ||
53 | 2: \optnopins; | ||
54 | .endif | ||
55 | |||
59 | RTS; | 56 | RTS; |
60 | ENDPROC(_blackfin_icache_flush_range) | 57 | .endm |
61 | 58 | ||
62 | /* | 59 | /* Invalidate all instruction cache lines assocoiated with this memory area */ |
63 | * blackfin_icache_dcache_flush_range(start, end) | 60 | ENTRY(_blackfin_icache_flush_range) |
64 | * FLUSH all cache lines assocoiated with this | 61 | do_flush IFLUSH, , nop |
65 | * area of memory. | 62 | ENDPROC(_blackfin_icache_flush_range) |
66 | * | ||
67 | * start: Start address | ||
68 | * end: End address | ||
69 | */ | ||
70 | 63 | ||
64 | /* Flush all cache lines assocoiated with this area of memory. */ | ||
71 | ENTRY(_blackfin_icache_dcache_flush_range) | 65 | ENTRY(_blackfin_icache_dcache_flush_range) |
72 | R2 = -L1_CACHE_BYTES; | 66 | do_flush IFLUSH, FLUSH |
73 | R2 = R0 & R2; | ||
74 | P0 = R2; | ||
75 | P1 = R1; | ||
76 | CSYNC(R3); | ||
77 | IFLUSH [P0]; | ||
78 | 1: | ||
79 | FLUSH [P0]; | ||
80 | IFLUSH [P0++]; | ||
81 | CC = P0 < P1 (iu); | ||
82 | IF CC JUMP 1b (bp); | ||
83 | IFLUSH [P0]; | ||
84 | FLUSH [P0]; | ||
85 | SSYNC(R3); | ||
86 | RTS; | ||
87 | ENDPROC(_blackfin_icache_dcache_flush_range) | 67 | ENDPROC(_blackfin_icache_dcache_flush_range) |
88 | 68 | ||
89 | /* Throw away all D-cached data in specified region without any obligation to | 69 | /* Throw away all D-cached data in specified region without any obligation to |
90 | * write them back. However, we must clean the D-cached entries around the | 70 | * write them back. Since the Blackfin ISA does not have an "invalidate" |
91 | * boundaries of the start and/or end address is not cache aligned. | 71 | * instruction, we use flush/invalidate. Perhaps as a speed optimization we |
92 | * | 72 | * could bang on the DTEST MMRs ... |
93 | * Start: start address, | ||
94 | * end : end address. | ||
95 | */ | 73 | */ |
96 | |||
97 | ENTRY(_blackfin_dcache_invalidate_range) | 74 | ENTRY(_blackfin_dcache_invalidate_range) |
98 | R2 = -L1_CACHE_BYTES; | 75 | do_flush FLUSHINV |
99 | R2 = R0 & R2; | ||
100 | P0 = R2; | ||
101 | P1 = R1; | ||
102 | CSYNC(R3); | ||
103 | FLUSHINV[P0]; | ||
104 | 1: | ||
105 | FLUSHINV[P0++]; | ||
106 | CC = P0 < P1 (iu); | ||
107 | IF CC JUMP 1b (bp); | ||
108 | |||
109 | /* If the data crosses a cache line, then we'll be pointing to | ||
110 | * the last cache line, but won't have flushed/invalidated it yet, | ||
111 | * so do one more. | ||
112 | */ | ||
113 | FLUSHINV[P0]; | ||
114 | SSYNC(R3); | ||
115 | RTS; | ||
116 | ENDPROC(_blackfin_dcache_invalidate_range) | 76 | ENDPROC(_blackfin_dcache_invalidate_range) |
117 | 77 | ||
78 | /* Flush all data cache lines assocoiated with this memory area */ | ||
118 | ENTRY(_blackfin_dcache_flush_range) | 79 | ENTRY(_blackfin_dcache_flush_range) |
119 | R2 = -L1_CACHE_BYTES; | 80 | do_flush FLUSH, , , .Ldfr |
120 | R2 = R0 & R2; | ||
121 | P0 = R2; | ||
122 | P1 = R1; | ||
123 | CSYNC(R3); | ||
124 | FLUSH[P0]; | ||
125 | 1: | ||
126 | FLUSH[P0++]; | ||
127 | CC = P0 < P1 (iu); | ||
128 | IF CC JUMP 1b (bp); | ||
129 | |||
130 | /* If the data crosses a cache line, then we'll be pointing to | ||
131 | * the last cache line, but won't have flushed it yet, so do | ||
132 | * one more. | ||
133 | */ | ||
134 | FLUSH[P0]; | ||
135 | SSYNC(R3); | ||
136 | RTS; | ||
137 | ENDPROC(_blackfin_dcache_flush_range) | 81 | ENDPROC(_blackfin_dcache_flush_range) |
138 | 82 | ||
83 | /* Our headers convert the page structure to an address, so just need to flush | ||
84 | * its contents like normal. We know the start address is page aligned (which | ||
85 | * greater than our cache alignment), as is the end address. So just jump into | ||
86 | * the middle of the dcache flush function. | ||
87 | */ | ||
139 | ENTRY(_blackfin_dflush_page) | 88 | ENTRY(_blackfin_dflush_page) |
140 | P1 = 1 << (PAGE_SHIFT - L1_CACHE_SHIFT); | 89 | P1 = 1 << (PAGE_SHIFT - L1_CACHE_SHIFT); |
141 | P0 = R0; | 90 | jump .Ldfr; |
142 | CSYNC(R3); | ||
143 | FLUSH[P0]; | ||
144 | LSETUP (.Lfl1, .Lfl1) LC0 = P1; | ||
145 | .Lfl1: FLUSH [P0++]; | ||
146 | SSYNC(R3); | ||
147 | RTS; | ||
148 | ENDPROC(_blackfin_dflush_page) | 91 | ENDPROC(_blackfin_dflush_page) |
diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S index 3069df580729..f123a62e2451 100644 --- a/arch/blackfin/mach-common/head.S +++ b/arch/blackfin/mach-common/head.S | |||
@@ -206,6 +206,60 @@ ENTRY(_real_start) | |||
206 | w[p0] = r0; | 206 | w[p0] = r0; |
207 | ssync; | 207 | ssync; |
208 | 208 | ||
209 | #if L1_DATA_A_LENGTH > 0 | ||
210 | r1.l = __sbss_l1; | ||
211 | r1.h = __sbss_l1; | ||
212 | r2.l = __ebss_l1; | ||
213 | r2.h = __ebss_l1; | ||
214 | r0 = 0 (z); | ||
215 | r2 = r2 - r1; | ||
216 | cc = r2 == 0; | ||
217 | if cc jump .L_a_l1_done; | ||
218 | r2 >>= 2; | ||
219 | p1 = r1; | ||
220 | p2 = r2; | ||
221 | lsetup (.L_clear_a_l1, .L_clear_a_l1 ) lc0 = p2; | ||
222 | .L_clear_a_l1: | ||
223 | [p1++] = r0; | ||
224 | .L_a_l1_done: | ||
225 | #endif | ||
226 | |||
227 | #if L1_DATA_B_LENGTH > 0 | ||
228 | r1.l = __sbss_b_l1; | ||
229 | r1.h = __sbss_b_l1; | ||
230 | r2.l = __ebss_b_l1; | ||
231 | r2.h = __ebss_b_l1; | ||
232 | r0 = 0 (z); | ||
233 | r2 = r2 - r1; | ||
234 | cc = r2 == 0; | ||
235 | if cc jump .L_b_l1_done; | ||
236 | r2 >>= 2; | ||
237 | p1 = r1; | ||
238 | p2 = r2; | ||
239 | lsetup (.L_clear_b_l1, .L_clear_b_l1 ) lc0 = p2; | ||
240 | .L_clear_b_l1: | ||
241 | [p1++] = r0; | ||
242 | .L_b_l1_done: | ||
243 | #endif | ||
244 | |||
245 | #if L2_LENGTH > 0 | ||
246 | r1.l = __sbss_l2; | ||
247 | r1.h = __sbss_l2; | ||
248 | r2.l = __ebss_l2; | ||
249 | r2.h = __ebss_l2; | ||
250 | r0 = 0 (z); | ||
251 | r2 = r2 - r1; | ||
252 | cc = r2 == 0; | ||
253 | if cc jump .L_l2_done; | ||
254 | r2 >>= 2; | ||
255 | p1 = r1; | ||
256 | p2 = r2; | ||
257 | lsetup (.L_clear_l2, .L_clear_l2 ) lc0 = p2; | ||
258 | .L_clear_l2: | ||
259 | [p1++] = r0; | ||
260 | .L_l2_done: | ||
261 | #endif | ||
262 | |||
209 | /* Zero out the bss region | 263 | /* Zero out the bss region |
210 | * Note: this will fail if bss is 0 bytes ... | 264 | * Note: this will fail if bss is 0 bytes ... |
211 | */ | 265 | */ |