]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/arm/cpufunc_asm_xscale.S
Add the start of INTRNG support for ACPI.
[FreeBSD/FreeBSD.git] / sys / arm / arm / cpufunc_asm_xscale.S
1 /*      $NetBSD: cpufunc_asm_xscale.S,v 1.16 2002/08/17 16:36:32 thorpej Exp $  */
2
3 /*-
4  * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
5  * All rights reserved.
6  *
7  * Written by Allen Briggs and Jason R. Thorpe for Wasabi Systems, Inc.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed for the NetBSD Project by
20  *      Wasabi Systems, Inc.
21  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22  *    or promote products derived from this software without specific prior
23  *    written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  *
37  */
38
39 /*-
40  * Copyright (c) 2001 Matt Thomas.
41  * Copyright (c) 1997,1998 Mark Brinicombe.
42  * Copyright (c) 1997 Causality Limited
43  * All rights reserved.
44  *
45  * Redistribution and use in source and binary forms, with or without
46  * modification, are permitted provided that the following conditions
47  * are met:
48  * 1. Redistributions of source code must retain the above copyright
49  *    notice, this list of conditions and the following disclaimer.
50  * 2. Redistributions in binary form must reproduce the above copyright
51  *    notice, this list of conditions and the following disclaimer in the
52  *    documentation and/or other materials provided with the distribution.
53  * 3. All advertising materials mentioning features or use of this software
54  *    must display the following acknowledgement:
55  *      This product includes software developed by Causality Limited.
56  * 4. The name of Causality Limited may not be used to endorse or promote
57  *    products derived from this software without specific prior written
58  *    permission.
59  *
60  * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
61  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
62  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
63  * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
64  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
65  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
66  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
67  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
68  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
69  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
70  * SUCH DAMAGE.
71  *
72  * XScale assembly functions for CPU / MMU / TLB specific operations
73  */
74 #include <machine/asm.h>
75 __FBSDID("$FreeBSD$");
76
77 #include <machine/armreg.h>
78
79 /*
80  * Size of the XScale core D-cache.
81  */
82 #define DCACHE_SIZE             0x00008000
83
84 /*
85  * CPWAIT -- Canonical method to wait for CP15 update.
86  * From: Intel 80200 manual, section 2.3.3.
87  *
88  * NOTE: Clobbers the specified temp reg.
89  */
90 #define CPWAIT_BRANCH                                                    \
91         sub     pc, pc, #4
92
93 #define CPWAIT(tmp)                                                      \
94         mrc     p15, 0, tmp, c2, c0, 0  /* arbitrary read of CP15 */    ;\
95         mov     tmp, tmp                /* wait for it to complete */   ;\
96         CPWAIT_BRANCH                   /* branch to next insn */
97
98 #define CPWAIT_AND_RETURN_SHIFTER       lsr #32
99
100 #define CPWAIT_AND_RETURN(tmp)                                           \
101         mrc     p15, 0, tmp, c2, c0, 0  /* arbitrary read of CP15 */    ;\
102         /* Wait for it to complete and branch to the return address */   \
103         sub     pc, lr, tmp, CPWAIT_AND_RETURN_SHIFTER
104
105 ENTRY(xscale_cpwait)
106         CPWAIT_AND_RETURN(r0)
107 END(xscale_cpwait)
108
109 /*
110  * We need a separate cpu_control() entry point, since we have to
111  * invalidate the Branch Target Buffer in the event the BPRD bit
112  * changes in the control register.
113  */
114 ENTRY(xscale_control)
115         mrc     CP15_SCTLR(r3)          /* Read the control register */
116         bic     r2, r3, r0              /* Clear bits */
117         eor     r2, r2, r1              /* XOR bits */
118
119         teq     r2, r3                  /* Only write if there was a change */
120         mcrne   p15, 0, r0, c7, c5, 6   /* Invalidate the BTB */
121         mcrne   CP15_SCTLR(r2)          /* Write new control register */
122         mov     r0, r3                  /* Return old value */
123
124         CPWAIT_AND_RETURN(r1)
125 END(xscale_control)
126
127 /*
128  * Functions to set the MMU Translation Table Base register
129  *
130  * We need to clean and flush the cache as it uses virtual
131  * addresses that are about to change.
132  */
133 ENTRY(xscale_setttb)
134 #ifdef CACHE_CLEAN_BLOCK_INTR
135         mrs     r3, cpsr
136         orr     r1, r3, #(PSR_I | PSR_F)
137         msr     cpsr_fsxc, r1
138 #endif
139         stmfd   sp!, {r0-r3, lr}
140         bl      _C_LABEL(xscale_cache_cleanID)
141         mcr     p15, 0, r0, c7, c5, 0   /* invalidate I$ and BTB */
142         mcr     p15, 0, r0, c7, c10, 4  /* drain write and fill buffer */
143
144         CPWAIT(r0)
145
146         ldmfd   sp!, {r0-r3, lr}
147
148         /* Write the TTB */
149         mcr     p15, 0, r0, c2, c0, 0
150
151         /* If we have updated the TTB we must flush the TLB */
152         mcr     p15, 0, r0, c8, c7, 0   /* invalidate I+D TLB */
153
154         /* The cleanID above means we only need to flush the I cache here */
155         mcr     p15, 0, r0, c7, c5, 0   /* invalidate I$ and BTB */
156
157         CPWAIT(r0)
158
159 #ifdef CACHE_CLEAN_BLOCK_INTR
160         msr     cpsr_fsxc, r3
161 #endif
162         RET
163 END(xscale_setttb)
164
165 /*
166  * TLB functions
167  *
168  */
169 ENTRY(xscale_tlb_flushID_SE)
170         mcr     p15, 0, r0, c8, c6, 1   /* flush D tlb single entry */
171         mcr     p15, 0, r0, c8, c5, 1   /* flush I tlb single entry */
172         CPWAIT_AND_RETURN(r0)
173 END(xscale_tlb_flushID_SE)
174
175 /*
176  * Cache functions
177  */
178 ENTRY(xscale_cache_flushID)
179         mcr     p15, 0, r0, c7, c7, 0   /* flush I+D cache */
180         CPWAIT_AND_RETURN(r0)
181 END(xscale_cache_flushID)
182
183 ENTRY(xscale_cache_flushI)
184         mcr     p15, 0, r0, c7, c5, 0   /* flush I cache */
185         CPWAIT_AND_RETURN(r0)
186 END(xscale_cache_flushI)
187
188 ENTRY(xscale_cache_flushD)
189         mcr     p15, 0, r0, c7, c6, 0   /* flush D cache */
190         CPWAIT_AND_RETURN(r0)
191 END(xscale_cache_flushD)
192
193 ENTRY(xscale_cache_flushI_SE)
194         mcr     p15, 0, r0, c7, c5, 1   /* flush I cache single entry */
195         CPWAIT_AND_RETURN(r0)
196 END(xscale_cache_flushI_SE)
197
198 ENTRY(xscale_cache_flushD_SE)
199         /*
200          * Errata (rev < 2): Must clean-dcache-line to an address
201          * before invalidate-dcache-line to an address, or dirty
202          * bits will not be cleared in the dcache array.
203          */
204         mcr     p15, 0, r0, c7, c10, 1
205         mcr     p15, 0, r0, c7, c6, 1   /* flush D cache single entry */
206         CPWAIT_AND_RETURN(r0)
207 END(xscale_cache_flushD_SE)
208
209 ENTRY(xscale_cache_cleanD_E)
210         mcr     p15, 0, r0, c7, c10, 1  /* clean D cache entry */
211         CPWAIT_AND_RETURN(r0)
212 END(xscale_cache_cleanD_E)
213
214 /*
215  * Information for the XScale cache clean/purge functions:
216  *
217  *      * Virtual address of the memory region to use
218  *      * Size of memory region
219  *
220  * Note the virtual address for the Data cache clean operation
221  * does not need to be backed by physical memory, since no loads
222  * will actually be performed by the allocate-line operation.
223  *
224  * Note that the Mini-Data cache MUST be cleaned by executing
225  * loads from memory mapped into a region reserved exclusively
226  * for cleaning of the Mini-Data cache.
227  */
228         .data
229
230         .global _C_LABEL(xscale_cache_clean_addr)
231 _C_LABEL(xscale_cache_clean_addr):
232         .word   0x00000000
233
234         .global _C_LABEL(xscale_cache_clean_size)
235 _C_LABEL(xscale_cache_clean_size):
236         .word   DCACHE_SIZE
237
238         .global _C_LABEL(xscale_minidata_clean_addr)
239 _C_LABEL(xscale_minidata_clean_addr):
240         .word   0x00000000
241
242         .global _C_LABEL(xscale_minidata_clean_size)
243 _C_LABEL(xscale_minidata_clean_size):
244         .word   0x00000800
245
246         .text
247
248 .Lxscale_cache_clean_addr:
249         .word   _C_LABEL(xscale_cache_clean_addr)
250 .Lxscale_cache_clean_size:
251         .word   _C_LABEL(xscale_cache_clean_size)
252
253 .Lxscale_minidata_clean_addr:
254         .word   _C_LABEL(xscale_minidata_clean_addr)
255 .Lxscale_minidata_clean_size:
256         .word   _C_LABEL(xscale_minidata_clean_size)
257
258 #ifdef CACHE_CLEAN_BLOCK_INTR
259 #define XSCALE_CACHE_CLEAN_BLOCK                                        \
260         mrs     r3, cpsr                                        ;       \
261         orr     r0, r3, #(PSR_I | PSR_F)                        ;       \
262         msr     cpsr_fsxc, r0
263
264 #define XSCALE_CACHE_CLEAN_UNBLOCK                                      \
265         msr     cpsr_fsxc, r3
266 #else
267 #define XSCALE_CACHE_CLEAN_BLOCK
268
269 #define XSCALE_CACHE_CLEAN_UNBLOCK
270 #endif /* CACHE_CLEAN_BLOCK_INTR */
271
272 #define XSCALE_CACHE_CLEAN_PROLOGUE                                     \
273         XSCALE_CACHE_CLEAN_BLOCK                                ;       \
274         ldr     r2, .Lxscale_cache_clean_addr                   ;       \
275         ldmia   r2, {r0, r1}                                    ;       \
276         /*                                                              \
277          * BUG ALERT!                                                   \
278          *                                                              \
279          * The XScale core has a strange cache eviction bug, which      \
280          * requires us to use 2x the cache size for the cache clean     \
281          * and for that area to be aligned to 2 * cache size.           \
282          *                                                              \
283          * The work-around is to use 2 areas for cache clean, and to    \
284          * alternate between them whenever this is done.  No one knows  \
285          * why the work-around works (mmm!).                            \
286          */                                                             \
287         eor     r0, r0, #(DCACHE_SIZE)                          ;       \
288         str     r0, [r2]                                        ;       \
289         add     r0, r0, r1
290
291 #define XSCALE_CACHE_CLEAN_EPILOGUE                                     \
292         XSCALE_CACHE_CLEAN_UNBLOCK
293
294 ENTRY_NP(xscale_cache_syncI)
295
296 EENTRY_NP(xscale_cache_purgeID)
297         mcr     p15, 0, r0, c7, c5, 0   /* flush I cache (D cleaned below) */
298 EENTRY_NP(xscale_cache_cleanID)
299 EENTRY_NP(xscale_cache_purgeD)
300 EENTRY(xscale_cache_cleanD)
301         XSCALE_CACHE_CLEAN_PROLOGUE
302
303 1:      subs    r0, r0, #32
304         mcr     p15, 0, r0, c7, c2, 5   /* allocate cache line */
305         subs    r1, r1, #32
306         bne     1b
307
308         CPWAIT(r0)
309
310         mcr     p15, 0, r0, c7, c10, 4  /* drain write buffer */
311
312         CPWAIT(r0)
313
314         XSCALE_CACHE_CLEAN_EPILOGUE
315         RET
316 EEND(xscale_cache_cleanD)
317 EEND(xscale_cache_purgeD)
318 EEND(xscale_cache_cleanID)
319 EEND(xscale_cache_purgeID)
320 END(xscale_cache_syncI)
321
322 /*
323  * Clean the mini-data cache.
324  *
325  * It's expected that we only use the mini-data cache for
326  * kernel addresses, so there is no need to purge it on
327  * context switch, and no need to prevent userspace access
328  * while we clean it.
329  */
330 ENTRY(xscale_cache_clean_minidata)
331         ldr     r2, .Lxscale_minidata_clean_addr
332         ldmia   r2, {r0, r1}
333 1:      ldr     r3, [r0], #32
334         subs    r1, r1, #32
335         bne     1b
336
337         mcr     p15, 0, r0, c7, c10, 4  /* drain write buffer */
338
339         CPWAIT_AND_RETURN(r1)
340 END(xscale_cache_clean_minidata)
341
342 ENTRY(xscale_cache_purgeID_E)
343         mcr     p15, 0, r0, c7, c10, 1  /* clean D cache entry */
344         CPWAIT(r1)
345         mcr     p15, 0, r0, c7, c10, 4  /* drain write buffer */
346         mcr     p15, 0, r0, c7, c5, 1   /* flush I cache single entry */
347         mcr     p15, 0, r0, c7, c6, 1   /* flush D cache single entry */
348         CPWAIT_AND_RETURN(r1)
349 END(xscale_cache_purgeID_E)
350
351 ENTRY(xscale_cache_purgeD_E)
352         mcr     p15, 0, r0, c7, c10, 1  /* clean D cache entry */
353         CPWAIT(r1)
354         mcr     p15, 0, r0, c7, c10, 4  /* drain write buffer */
355         mcr     p15, 0, r0, c7, c6, 1   /* flush D cache single entry */
356         CPWAIT_AND_RETURN(r1)
357 END(xscale_cache_purgeD_E)
358
359 /*
360  * Soft functions
361  */
362 /* xscale_cache_syncI is identical to xscale_cache_purgeID */
363
364 EENTRY(xscale_cache_cleanID_rng)
365 ENTRY(xscale_cache_cleanD_rng)
366         cmp     r1, #0x4000
367         bcs     _C_LABEL(xscale_cache_cleanID)
368
369         and     r2, r0, #0x1f
370         add     r1, r1, r2
371         bic     r0, r0, #0x1f
372
373 1:      mcr     p15, 0, r0, c7, c10, 1  /* clean D cache entry */
374         add     r0, r0, #32
375         subs    r1, r1, #32
376         bhi     1b
377
378         CPWAIT(r0)
379
380         mcr     p15, 0, r0, c7, c10, 4  /* drain write buffer */
381
382         CPWAIT_AND_RETURN(r0)
383 /*END(xscale_cache_cleanID_rng)*/
384 END(xscale_cache_cleanD_rng)
385
386 ENTRY(xscale_cache_purgeID_rng)
387         cmp     r1, #0x4000
388         bcs     _C_LABEL(xscale_cache_purgeID)
389
390         and     r2, r0, #0x1f
391         add     r1, r1, r2
392         bic     r0, r0, #0x1f
393
394 1:      mcr     p15, 0, r0, c7, c10, 1  /* clean D cache entry */
395         mcr     p15, 0, r0, c7, c6, 1   /* flush D cache single entry */
396         mcr     p15, 0, r0, c7, c5, 1   /* flush I cache single entry */
397         add     r0, r0, #32
398         subs    r1, r1, #32
399         bhi     1b
400
401         CPWAIT(r0)
402
403         mcr     p15, 0, r0, c7, c10, 4  /* drain write buffer */
404
405         CPWAIT_AND_RETURN(r0)
406 END(xscale_cache_purgeID_rng)
407
408 ENTRY(xscale_cache_purgeD_rng)
409         cmp     r1, #0x4000
410         bcs     _C_LABEL(xscale_cache_purgeD)
411
412         and     r2, r0, #0x1f
413         add     r1, r1, r2
414         bic     r0, r0, #0x1f
415
416 1:      mcr     p15, 0, r0, c7, c10, 1  /* clean D cache entry */
417         mcr     p15, 0, r0, c7, c6, 1   /* flush D cache single entry */
418         add     r0, r0, #32
419         subs    r1, r1, #32
420         bhi     1b
421
422         CPWAIT(r0)
423
424         mcr     p15, 0, r0, c7, c10, 4  /* drain write buffer */
425
426         CPWAIT_AND_RETURN(r0)
427 END(xscale_cache_purgeD_rng)
428
429 ENTRY(xscale_cache_syncI_rng)
430         cmp     r1, #0x4000
431         bcs     _C_LABEL(xscale_cache_syncI)
432
433         and     r2, r0, #0x1f
434         add     r1, r1, r2
435         bic     r0, r0, #0x1f
436
437 1:      mcr     p15, 0, r0, c7, c10, 1  /* clean D cache entry */
438         mcr     p15, 0, r0, c7, c5, 1   /* flush I cache single entry */
439         add     r0, r0, #32
440         subs    r1, r1, #32
441         bhi     1b
442
443         CPWAIT(r0)
444
445         mcr     p15, 0, r0, c7, c10, 4  /* drain write buffer */
446
447         CPWAIT_AND_RETURN(r0)
448 END(xscale_cache_syncI_rng)
449
450 ENTRY(xscale_cache_flushD_rng)
451         and     r2, r0, #0x1f
452         add     r1, r1, r2
453         bic     r0, r0, #0x1f
454
455 1:      mcr     p15, 0, r0, c7, c6, 1   /* flush D cache single entry */
456         add     r0, r0, #32
457         subs    r1, r1, #32
458         bhi     1b
459
460         mcr     p15, 0, r0, c7, c10, 4  /* drain write buffer */
461
462         CPWAIT_AND_RETURN(r0)
463 END(xscale_cache_flushD_rng)
464
465 /*
466  * Context switch.
467  *
468  * These is the CPU-specific parts of the context switcher cpu_switch()
469  * These functions actually perform the TTB reload.
470  *
471  * NOTE: Special calling convention
472  *      r1, r4-r13 must be preserved
473  */
474 ENTRY(xscale_context_switch)
475         /*
476          * CF_CACHE_PURGE_ID will *ALWAYS* be called prior to this.
477          * Thus the data cache will contain only kernel data and the
478          * instruction cache will contain only kernel code, and all
479          * kernel mappings are shared by all processes.
480          */
481
482         /* Write the TTB */
483         mcr     p15, 0, r0, c2, c0, 0
484
485         /* If we have updated the TTB we must flush the TLB */
486         mcr     p15, 0, r0, c8, c7, 0   /* flush the I+D tlb */
487
488         CPWAIT_AND_RETURN(r0)
489 END(xscale_context_switch)
490
491 /*
492  * xscale_cpu_sleep
493  *
494  * This is called when there is nothing on any of the run queues.
495  * We go into IDLE mode so that any IRQ or FIQ will awaken us.
496  *
497  * If this is called with anything other than ARM_SLEEP_MODE_IDLE,
498  * ignore it.
499  */
500 ENTRY(xscale_cpu_sleep)
501         tst     r0, #0x00000000
502         bne     1f
503         mov     r0, #0x1
504         mcr     p14, 0, r0, c7, c0, 0
505
506 1:
507         RET
508 END(xscale_cpu_sleep)
509