Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney...
[deliverable/linux.git] / arch / blackfin / mach-common / cache.S
1 /*
2 * File: arch/blackfin/mach-common/cache.S
3 * Based on:
4 * Author: LG Soft India
5 *
6 * Created:
7 * Description: cache control support
8 *
9 * Modified:
10 * Copyright 2004-2006 Analog Devices Inc.
11 *
12 * Bugs: Enter bugs at http://blackfin.uclinux.org/
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 */
29
30 #include <linux/linkage.h>
31 #include <asm/cplb.h>
32 #include <asm/entry.h>
33 #include <asm/blackfin.h>
34 #include <asm/cache.h>
35
36 .text
37 .align 2
38 ENTRY(_cache_invalidate)
39
40 /*
41 * Icache or DcacheA or DcacheB Invalidation
42 * or any combination thereof
43 * R0 has bits
44 * CPLB_ENABLE_ICACHE_P,CPLB_ENABLE_DCACHE_P,CPLB_ENABLE_DCACHE2_P
45 * set as required
46 */
47 [--SP] = R7;
48
49 R7 = R0;
50 CC = BITTST(R7,CPLB_ENABLE_ICACHE_P);
51 IF !CC JUMP .Lno_icache;
52 [--SP] = RETS;
53 CALL _icache_invalidate;
54 RETS = [SP++];
55 .Lno_icache:
56 CC = BITTST(R7,CPLB_ENABLE_DCACHE_P);
57 IF !CC JUMP .Lno_dcache_a;
58 R0 = 0; /* specifies bank A */
59 [--SP] = RETS;
60 CALL _dcache_invalidate;
61 RETS = [SP++];
62 .Lno_dcache_a:
63 CC = BITTST(R7,CPLB_ENABLE_DCACHE2_P);
64 IF !CC JUMP .Lno_dcache_b;
65 R0 = 0;
66 BITSET(R0, 23); /* specifies bank B */
67 [--SP] = RETS;
68 CALL _dcache_invalidate;
69 RETS = [SP++];
70 .Lno_dcache_b:
71 R7 = [SP++];
72 RTS;
73 ENDPROC(_cache_invalidate)
74
75 /* Invalidate the Entire Instruction cache by
76 * disabling IMC bit
77 */
78 ENTRY(_icache_invalidate)
79 ENTRY(_invalidate_entire_icache)
80 [--SP] = ( R7:5);
81
82 P0.L = LO(IMEM_CONTROL);
83 P0.H = HI(IMEM_CONTROL);
84 R7 = [P0];
85
86 /* Clear the IMC bit , All valid bits in the instruction
87 * cache are set to the invalid state
88 */
89 BITCLR(R7,IMC_P);
90 CLI R6;
91 SSYNC; /* SSYNC required before invalidating cache. */
92 .align 8;
93 [P0] = R7;
94 SSYNC;
95 STI R6;
96
97 /* Configures the instruction cache agian */
98 R6 = (IMC | ENICPLB);
99 R7 = R7 | R6;
100
101 CLI R6;
102 SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */
103 .align 8;
104 [P0] = R7;
105 SSYNC;
106 STI R6;
107
108 ( R7:5) = [SP++];
109 RTS;
110 ENDPROC(_invalidate_entire_icache)
111 ENDPROC(_icache_invalidate)
112
113 /*
114 * blackfin_cache_flush_range(start, end)
115 * Invalidate all cache lines assocoiated with this
116 * area of memory.
117 *
118 * start: Start address
119 * end: End address
120 */
121 ENTRY(_blackfin_icache_flush_range)
122 R2 = -L1_CACHE_BYTES;
123 R2 = R0 & R2;
124 P0 = R2;
125 P1 = R1;
126 CSYNC(R3);
127 IFLUSH [P0];
128 1:
129 IFLUSH [P0++];
130 CC = P0 < P1 (iu);
131 IF CC JUMP 1b (bp);
132 IFLUSH [P0];
133 SSYNC(R3);
134 RTS;
135 ENDPROC(_blackfin_icache_flush_range)
136
137 /*
138 * blackfin_icache_dcache_flush_range(start, end)
139 * FLUSH all cache lines assocoiated with this
140 * area of memory.
141 *
142 * start: Start address
143 * end: End address
144 */
145
146 ENTRY(_blackfin_icache_dcache_flush_range)
147 R2 = -L1_CACHE_BYTES;
148 R2 = R0 & R2;
149 P0 = R2;
150 P1 = R1;
151 CSYNC(R3);
152 IFLUSH [P0];
153 1:
154 FLUSH [P0];
155 IFLUSH [P0++];
156 CC = P0 < P1 (iu);
157 IF CC JUMP 1b (bp);
158 IFLUSH [P0];
159 FLUSH [P0];
160 SSYNC(R3);
161 RTS;
162 ENDPROC(_blackfin_icache_dcache_flush_range)
163
164 /* Throw away all D-cached data in specified region without any obligation to
165 * write them back. However, we must clean the D-cached entries around the
166 * boundaries of the start and/or end address is not cache aligned.
167 *
168 * Start: start address,
169 * end : end address.
170 */
171
172 ENTRY(_blackfin_dcache_invalidate_range)
173 R2 = -L1_CACHE_BYTES;
174 R2 = R0 & R2;
175 P0 = R2;
176 P1 = R1;
177 CSYNC(R3);
178 FLUSHINV[P0];
179 1:
180 FLUSHINV[P0++];
181 CC = P0 < P1 (iu);
182 IF CC JUMP 1b (bp);
183
184 /* If the data crosses a cache line, then we'll be pointing to
185 * the last cache line, but won't have flushed/invalidated it yet,
186 * so do one more.
187 */
188 FLUSHINV[P0];
189 SSYNC(R3);
190 RTS;
191 ENDPROC(_blackfin_dcache_invalidate_range)
192
193 /* Invalidate the Entire Data cache by
194 * clearing DMC[1:0] bits
195 */
196 ENTRY(_invalidate_entire_dcache)
197 ENTRY(_dcache_invalidate)
198 [--SP] = ( R7:6);
199
200 P0.L = LO(DMEM_CONTROL);
201 P0.H = HI(DMEM_CONTROL);
202 R7 = [P0];
203
204 /* Clear the DMC[1:0] bits, All valid bits in the data
205 * cache are set to the invalid state
206 */
207 BITCLR(R7,DMC0_P);
208 BITCLR(R7,DMC1_P);
209 CLI R6;
210 SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */
211 .align 8;
212 [P0] = R7;
213 SSYNC;
214 STI R6;
215
216 /* Configures the data cache again */
217
218 R6 = DMEM_CNTR;
219 R7 = R7 | R6;
220
221 CLI R6;
222 SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */
223 .align 8;
224 [P0] = R7;
225 SSYNC;
226 STI R6;
227
228 ( R7:6) = [SP++];
229 RTS;
230 ENDPROC(_dcache_invalidate)
231 ENDPROC(_invalidate_entire_dcache)
232
233 ENTRY(_blackfin_dcache_flush_range)
234 R2 = -L1_CACHE_BYTES;
235 R2 = R0 & R2;
236 P0 = R2;
237 P1 = R1;
238 CSYNC(R3);
239 FLUSH[P0];
240 1:
241 FLUSH[P0++];
242 CC = P0 < P1 (iu);
243 IF CC JUMP 1b (bp);
244
245 /* If the data crosses a cache line, then we'll be pointing to
246 * the last cache line, but won't have flushed it yet, so do
247 * one more.
248 */
249 FLUSH[P0];
250 SSYNC(R3);
251 RTS;
252 ENDPROC(_blackfin_dcache_flush_range)
253
254 ENTRY(_blackfin_dflush_page)
255 P1 = 1 << (PAGE_SHIFT - L1_CACHE_SHIFT);
256 P0 = R0;
257 CSYNC(R3);
258 FLUSH[P0];
259 LSETUP (.Lfl1, .Lfl1) LC0 = P1;
260 .Lfl1: FLUSH [P0++];
261 SSYNC(R3);
262 RTS;
263 ENDPROC(_blackfin_dflush_page)
This page took 0.03623 seconds and 5 git commands to generate.