]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/arm/cpufunc_asm_xscale_c3.S
MFH
[FreeBSD/FreeBSD.git] / sys / arm / arm / cpufunc_asm_xscale_c3.S
1 /*      $NetBSD: cpufunc_asm_xscale.S,v 1.16 2002/08/17 16:36:32 thorpej Exp $  */
2
3 /*-
4  * Copyright (c) 2007 Olivier Houchard
5  * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
6  * All rights reserved.
7  *
8  * Written by Allen Briggs and Jason R. Thorpe for Wasabi Systems, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed for the NetBSD Project by
21  *      Wasabi Systems, Inc.
22  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
23  *    or promote products derived from this software without specific prior
24  *    written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  *
38  */
39
40 /*-
41  * Copyright (c) 2001 Matt Thomas.
42  * Copyright (c) 1997,1998 Mark Brinicombe.
43  * Copyright (c) 1997 Causality Limited
44  * All rights reserved.
45  *
46  * Redistribution and use in source and binary forms, with or without
47  * modification, are permitted provided that the following conditions
48  * are met:
49  * 1. Redistributions of source code must retain the above copyright
50  *    notice, this list of conditions and the following disclaimer.
51  * 2. Redistributions in binary form must reproduce the above copyright
52  *    notice, this list of conditions and the following disclaimer in the
53  *    documentation and/or other materials provided with the distribution.
54  * 3. All advertising materials mentioning features or use of this software
55  *    must display the following acknowledgement:
56  *      This product includes software developed by Causality Limited.
57  * 4. The name of Causality Limited may not be used to endorse or promote
58  *    products derived from this software without specific prior written
59  *    permission.
60  *
61  * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
62  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
63  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
64  * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
65  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
66  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
67  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
69  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
70  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
71  * SUCH DAMAGE.
72  *
73  * XScale core 3 assembly functions for CPU / MMU / TLB specific operations
74  */
75
76 #include <machine/armreg.h>
77 #include <machine/asm.h>
78 __FBSDID("$FreeBSD$");
79
80 /*
81  * Size of the XScale core D-cache.
82  */
83 #define DCACHE_SIZE             0x00008000
84
85 /*
86  * CPWAIT -- Canonical method to wait for CP15 update.
87  * From: Intel 80200 manual, section 2.3.3.
88  *
89  * NOTE: Clobbers the specified temp reg.
90  */
91 #define CPWAIT_BRANCH                                                    \
92         sub     pc, pc, #4
93
94 #define CPWAIT(tmp)                                                      \
95         mrc     p15, 0, tmp, c2, c0, 0  /* arbitrary read of CP15 */    ;\
96         mov     tmp, tmp                /* wait for it to complete */   ;\
97         CPWAIT_BRANCH                   /* branch to next insn */
98
99 #define CPWAIT_AND_RETURN_SHIFTER       lsr #32
100
101 #define CPWAIT_AND_RETURN(tmp)                                           \
102         mrc     p15, 0, tmp, c2, c0, 0  /* arbitrary read of CP15 */    ;\
103         /* Wait for it to complete and branch to the return address */   \
104         sub     pc, lr, tmp, CPWAIT_AND_RETURN_SHIFTER
105
106 #define ARM_USE_L2_CACHE
107
108 #define L2_CACHE_SIZE           0x80000
109 #define L2_CACHE_WAYS           8
110 #define L2_CACHE_LINE_SIZE      32
111 #define L2_CACHE_SETS           (L2_CACHE_SIZE / \
112     (L2_CACHE_WAYS * L2_CACHE_LINE_SIZE))
113
114 #define L1_DCACHE_SIZE          32 * 1024
115 #define L1_DCACHE_WAYS          4
116 #define L1_DCACHE_LINE_SIZE     32
117 #define L1_DCACHE_SETS          (L1_DCACHE_SIZE / \
118     (L1_DCACHE_WAYS * L1_DCACHE_LINE_SIZE))
119 #ifdef CACHE_CLEAN_BLOCK_INTR
120 #define XSCALE_CACHE_CLEAN_BLOCK                                        \
121         stmfd   sp!, {r4}                                       ;       \
122         mrs     r4, cpsr                                        ;       \
123         orr     r0, r4, #(PSR_I | PSR_F)                        ;       \
124         msr     cpsr_fsxc, r0
125
126 #define XSCALE_CACHE_CLEAN_UNBLOCK                                      \
127         msr     cpsr_fsxc, r4                                   ;       \
128         ldmfd   sp!, {r4}
129 #else
130 #define XSCALE_CACHE_CLEAN_BLOCK
131 #define XSCALE_CACHE_CLEAN_UNBLOCK
132 #endif /* CACHE_CLEAN_BLOCK_INTR */
133
134
135 ENTRY_NP(xscalec3_cache_syncI)
136 EENTRY_NP(xscalec3_cache_purgeID)
137         mcr     p15, 0, r0, c7, c5, 0   /* flush I cache (D cleaned below) */
138 EENTRY_NP(xscalec3_cache_cleanID)
139 EENTRY_NP(xscalec3_cache_purgeD)
140 EENTRY(xscalec3_cache_cleanD)
141
142         XSCALE_CACHE_CLEAN_BLOCK
143         mov     r0, #0
144 1:
145         mov     r1, r0, asl #30
146         mov     r2, #0
147 2:
148         orr     r3, r1, r2, asl #5
149         mcr     p15, 0, r3, c7, c14, 2  /* clean and invalidate */
150         add     r2, r2, #1
151         cmp     r2, #L1_DCACHE_SETS
152         bne     2b
153         add     r0, r0, #1
154         cmp     r0, #4
155         bne     1b
156         CPWAIT(r0)
157         XSCALE_CACHE_CLEAN_UNBLOCK
158         mcr     p15, 0, r0, c7, c10, 4  /* drain write buffer */
159
160         RET
161 EEND(xscalec3_cache_purgeID)
162 EEND(xscalec3_cache_cleanID)
163 EEND(xscalec3_cache_purgeD)
164 EEND(xscalec3_cache_cleanD)
165 END(xscalec3_cache_syncI)
166
167 ENTRY(xscalec3_cache_purgeID_rng)
168
169         cmp     r1, #0x4000
170         bcs     _C_LABEL(xscalec3_cache_cleanID)
171         and     r2, r0, #0x1f
172         add     r1, r1, r2
173         bic     r0, r0, #0x1f
174
175 1:      mcr     p15, 0, r0, c7, c14, 1  /* clean/invalidate L1 D cache entry */
176         nop
177         mcr     p15, 0, r0, c7, c5, 1   /* flush I cache single entry */
178         add     r0, r0, #32
179         subs    r1, r1, #32
180         bhi     1b
181
182         CPWAIT(r0)
183
184         mcr     p15, 0, r0, c7, c10, 4  /* drain write buffer */
185
186         CPWAIT_AND_RETURN(r0)
187 END(xscalec3_cache_purgeID_rng)
188
189 ENTRY(xscalec3_cache_syncI_rng)
190         cmp     r1, #0x4000
191         bcs     _C_LABEL(xscalec3_cache_syncI)
192
193         and     r2, r0, #0x1f
194         add     r1, r1, r2
195         bic     r0, r0, #0x1f
196
197 1:      mcr     p15, 0, r0, c7, c10, 1  /* clean D cache entry */
198         mcr     p15, 0, r0, c7, c5, 1   /* flush I cache single entry */
199         add     r0, r0, #32
200         subs    r1, r1, #32
201         bhi     1b
202
203         CPWAIT(r0)
204
205         mcr     p15, 0, r0, c7, c10, 4  /* drain write buffer */
206
207         CPWAIT_AND_RETURN(r0)
208 END(xscalec3_cache_syncI_rng)
209
210 ENTRY(xscalec3_cache_purgeD_rng)
211
212         cmp     r1, #0x4000
213         bcs     _C_LABEL(xscalec3_cache_cleanID)
214         and     r2, r0, #0x1f
215         add     r1, r1, r2
216         bic     r0, r0, #0x1f
217
218 1:      mcr     p15, 0, r0, c7, c14, 1  /* Clean and invalidate D cache entry */
219         add     r0, r0, #32
220         subs    r1, r1, #32
221         bhi     1b
222
223         CPWAIT(r0)
224
225         mcr     p15, 0, r0, c7, c10, 4  /* drain write buffer */
226
227         CPWAIT_AND_RETURN(r0)
228 END(xscalec3_cache_purgeD_rng)
229
230 ENTRY(xscalec3_cache_cleanID_rng)
231 EENTRY(xscalec3_cache_cleanD_rng)
232
233         cmp     r1, #0x4000
234         bcs     _C_LABEL(xscalec3_cache_cleanID)
235         and     r2, r0, #0x1f
236         add     r1, r1, r2
237         bic     r0, r0, #0x1f
238
239 1:      mcr     p15, 0, r0, c7, c10, 1  /* clean L1 D cache entry */
240         nop
241         add     r0, r0, #32
242         subs    r1, r1, #32
243         bhi     1b
244
245         CPWAIT(r0)
246
247         mcr     p15, 0, r0, c7, c10, 4  /* drain write buffer */
248
249         CPWAIT_AND_RETURN(r0)
250 EEND(xscalec3_cache_cleanD_rng)
251 END(xscalec3_cache_cleanID_rng)
252
253 ENTRY(xscalec3_l2cache_purge)
254         /* Clean-up the L2 cache */
255         mcr     p15, 0, r0, c7, c10, 5  /* Data memory barrier */
256         mov     r0, #0
257 1:
258         mov     r1, r0, asl #29
259         mov     r2, #0
260 2:
261         orr     r3, r1, r2, asl #5
262         mcr     p15, 1, r3, c7, c15, 2
263         add     r2, r2, #1
264         cmp     r2, #L2_CACHE_SETS
265         bne     2b
266         add     r0, r0, #1
267         cmp     r0, #8
268         bne     1b
269         mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
270
271         CPWAIT(r0)
272         mcr     p15, 0, r0, c7, c10, 5  /* Data memory barrier */
273         RET
274 END(xscalec3_l2cache_purge)
275
276 ENTRY(xscalec3_l2cache_clean_rng)
277         mcr     p15, 0, r0, c7, c10, 5  /* Data memory barrier */
278
279         and     r2, r0, #0x1f
280         add     r1, r1, r2
281         bic     r0, r0, #0x1f
282
283 1:      mcr     p15, 1, r0, c7, c11, 1  /* Clean L2 D cache entry */
284         add     r0, r0, #32
285         subs    r1, r1, #32
286         bhi     1b
287
288
289         CPWAIT(r0)
290
291         mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
292         mcr     p15, 0, r0, c7, c10, 5
293
294         CPWAIT_AND_RETURN(r0)
295 END(xscalec3_l2cache_clean_rng)
296
297 ENTRY(xscalec3_l2cache_purge_rng)
298
299         mcr     p15, 0, r0, c7, c10, 5  /* Data memory barrier */
300
301         and     r2, r0, #0x1f
302         add     r1, r1, r2
303         bic     r0, r0, #0x1f
304
305 1:      mcr     p15, 1, r0, c7, c11, 1  /* Clean L2 D cache entry */
306         mcr     p15, 1, r0, c7, c7, 1   /* Invalidate L2 D cache entry */
307         add     r0, r0, #32
308         subs    r1, r1, #32
309         bhi     1b
310
311         mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
312         mcr     p15, 0, r0, c7, c10, 5
313
314         CPWAIT_AND_RETURN(r0)
315 END(xscalec3_l2cache_purge_rng)
316
317 ENTRY(xscalec3_l2cache_flush_rng)
318         mcr     p15, 0, r0, c7, c10, 5  /* Data memory barrier */
319
320         and     r2, r0, #0x1f
321         add     r1, r1, r2
322         bic     r0, r0, #0x1f
323
324 1:      mcr     p15, 1, r0, c7, c7, 1   /* Invalidate L2 cache line */
325         add     r0, r0, #32
326         subs    r1, r1, #32
327         bhi     1b
328         mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
329         mcr     p15, 0, r0, c7, c10, 5
330         CPWAIT_AND_RETURN(r0)
331 END(xscalec3_l2cache_flush_rng)
332
333 /*
334  * Functions to set the MMU Translation Table Base register
335  *
336  * We need to clean and flush the cache as it uses virtual
337  * addresses that are about to change.
338  */
339 ENTRY(xscalec3_setttb)
340 #ifdef CACHE_CLEAN_BLOCK_INTR
341         mrs     r3, cpsr
342         orr     r1, r3, #(PSR_I | PSR_F)
343         msr     cpsr_fsxc, r1
344 #endif
345         stmfd   sp!, {r0-r3, lr}
346         bl      _C_LABEL(xscalec3_cache_cleanID)
347         mcr     p15, 0, r0, c7, c5, 0   /* invalidate I$ and BTB */
348         mcr     p15, 0, r0, c7, c10, 4  /* drain write and fill buffer */
349
350         CPWAIT(r0)
351
352         ldmfd   sp!, {r0-r3, lr}
353
354 #ifdef ARM_USE_L2_CACHE
355         orr     r0, r0, #0x18   /* cache the page table in L2 */
356 #endif
357         /* Write the TTB */
358         mcr     p15, 0, r0, c2, c0, 0
359
360         /* If we have updated the TTB we must flush the TLB */
361         mcr     p15, 0, r0, c8, c7, 0   /* invalidate I+D TLB */
362
363         CPWAIT(r0)
364
365 #ifdef CACHE_CLEAN_BLOCK_INTR
366         msr     cpsr_fsxc, r3
367 #else
368         str     r2, [r3]
369 #endif
370         RET
371 END(xscalec3_setttb)
372
373 /*
374  * Context switch.
375  *
376  * These is the CPU-specific parts of the context switcher cpu_switch()
377  * These functions actually perform the TTB reload.
378  *
379  * NOTE: Special calling convention
380  *      r1, r4-r13 must be preserved
381  */
382 ENTRY(xscalec3_context_switch)
383         /*
384          * CF_CACHE_PURGE_ID will *ALWAYS* be called prior to this.
385          * Thus the data cache will contain only kernel data and the
386          * instruction cache will contain only kernel code, and all
387          * kernel mappings are shared by all processes.
388          */
389 #ifdef ARM_USE_L2_CACHE
390         orr     r0, r0, #0x18   /* Cache the page table in L2 */
391 #endif
392         /* Write the TTB */
393         mcr     p15, 0, r0, c2, c0, 0
394
395         /* If we have updated the TTB we must flush the TLB */
396         mcr     p15, 0, r0, c8, c7, 0   /* flush the I+D tlb */
397
398         CPWAIT_AND_RETURN(r0)
399 END(xscalec3_context_switch)
400