ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / arm / mm / proc-arm1026.S
1 /*
2  *  linux/arch/arm/mm/proc-arm1026.S: MMU functions for ARM1026EJ-S
3  *
4  *  Copyright (C) 2000 ARM Limited
5  *  Copyright (C) 2000 Deep Blue Solutions Ltd.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  *
13  * These are the low level assembler for performing cache and TLB
14  * functions on the ARM1026EJ-S.
15  */
16 #include <linux/linkage.h>
17 #include <linux/config.h>
18 #include <linux/init.h>
19 #include <asm/assembler.h>
20 #include <asm/constants.h>
21 #include <asm/pgtable.h>
22 #include <asm/procinfo.h>
23 #include <asm/ptrace.h>
24
25 /*
26  * This is the maximum size of an area which will be invalidated
27  * using the single invalidate entry instructions.  Anything larger
28  * than this, and we go for the whole cache.
29  *
30  * This value should be chosen such that we choose the cheapest
31  * alternative.
32  */
33 #define MAX_AREA_SIZE   32768
34
35 /*
36  * The size of one data cache line.
37  */
38 #define CACHE_DLINESIZE 32
39
40 /*
41  * The number of data cache segments.
42  */
43 #define CACHE_DSEGMENTS 16
44
45 /*
46  * The number of lines in a cache segment.
47  */
48 #define CACHE_DENTRIES  64
49
50 /*
51  * This is the size at which it becomes more efficient to
52  * clean the whole cache, rather than using the individual
53  * cache line maintainence instructions.
54  */
55 #define CACHE_DLIMIT    32768
56
57         .text
58 /*
59  * cpu_arm1026_proc_init()
60  */
61 ENTRY(cpu_arm1026_proc_init)
62         mov     pc, lr
63
64 /*
65  * cpu_arm1026_proc_fin()
66  */
67 ENTRY(cpu_arm1026_proc_fin)
68         stmfd   sp!, {lr}
69         mov     ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
70         msr     cpsr_c, ip
71         bl      arm1026_flush_kern_cache_all
72         mrc     p15, 0, r0, c1, c0, 0           @ ctrl register
73         bic     r0, r0, #0x1000                 @ ...i............
74         bic     r0, r0, #0x000e                 @ ............wca.
75         mcr     p15, 0, r0, c1, c0, 0           @ disable caches
76         ldmfd   sp!, {pc}
77
78 /*
79  * cpu_arm1026_reset(loc)
80  *
81  * Perform a soft reset of the system.  Put the CPU into the
82  * same state as it would be if it had been reset, and branch
83  * to what would be the reset vector.
84  *
85  * loc: location to jump to for soft reset
86  */
87         .align  5
88 ENTRY(cpu_arm1026_reset)
89         mov     ip, #0
90         mcr     p15, 0, ip, c7, c7, 0           @ invalidate I,D caches
91         mcr     p15, 0, ip, c7, c10, 4          @ drain WB
92         mcr     p15, 0, ip, c8, c7, 0           @ invalidate I & D TLBs
93         mrc     p15, 0, ip, c1, c0, 0           @ ctrl register
94         bic     ip, ip, #0x000f                 @ ............wcam
95         bic     ip, ip, #0x1100                 @ ...i...s........
96         mcr     p15, 0, ip, c1, c0, 0           @ ctrl register
97         mov     pc, r0
98
99 /*
100  * cpu_arm1026_do_idle()
101  */
102         .align  5
103 ENTRY(cpu_arm1026_do_idle)
104         mcr     p15, 0, r0, c7, c0, 4           @ Wait for interrupt
105         mov     pc, lr
106
107 /* ================================= CACHE ================================ */
108
109         .align  5
110 /*
111  *      flush_user_cache_all()
112  *
113  *      Invalidate all cache entries in a particular address
114  *      space.
115  */
116 ENTRY(arm1026_flush_user_cache_all)
117         /* FALLTHROUGH */
118 /*
119  *      flush_kern_cache_all()
120  *
121  *      Clean and invalidate the entire cache.
122  */
123 ENTRY(arm1026_flush_kern_cache_all)
124         mov     r2, #VM_EXEC
125         mov     ip, #0
126 __flush_whole_cache:
127 #ifndef CONFIG_CPU_DCACHE_DISABLE
128 1:      mrc     p15, 0, r15, c7, c14, 3         @ test, clean, invalidate
129         bne     1b
130 #endif
131         tst     r2, #VM_EXEC
132 #ifndef CONFIG_CPU_ICACHE_DISABLE
133         mcrne   p15, 0, ip, c7, c5, 0           @ invalidate I cache
134 #endif
135         mcrne   p15, 0, ip, c7, c10, 4          @ drain WB
136         mov     pc, lr
137
138 /*
139  *      flush_user_cache_range(start, end, flags)
140  *
141  *      Invalidate a range of cache entries in the specified
142  *      address space.
143  *
144  *      - start - start address (inclusive)
145  *      - end   - end address (exclusive)
146  *      - flags - vm_flags for this space
147  */
148 ENTRY(arm1026_flush_user_cache_range)
149         mov     ip, #0
150         sub     r3, r1, r0                      @ calculate total size
151         cmp     r3, #CACHE_DLIMIT
152         bhs     __flush_whole_cache
153
154 #ifndef CONFIG_CPU_DCACHE_DISABLE
155 1:      mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
156         add     r0, r0, #CACHE_DLINESIZE
157         cmp     r0, r1
158         blo     1b
159 #endif
160         tst     r2, #VM_EXEC
161 #ifndef CONFIG_CPU_ICACHE_DISABLE
162         mcrne   p15, 0, ip, c7, c5, 0           @ invalidate I cache
163 #endif
164         mcrne   p15, 0, ip, c7, c10, 4          @ drain WB
165         mov     pc, lr
166
167 /*
168  *      coherent_kern_range(start, end)
169  *
170  *      Ensure coherency between the Icache and the Dcache in the
171  *      region described by start.  If you have non-snooping
172  *      Harvard caches, you need to implement this function.
173  *
174  *      - start - virtual start address
175  *      - end   - virtual end address
176  */
177 ENTRY(arm1026_coherent_kern_range)
178         mov     ip, #0
179         bic     r0, r0, #CACHE_DLINESIZE - 1
180 1:
181 #ifndef CONFIG_CPU_DCACHE_DISABLE
182         mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
183 #endif
184 #ifndef CONFIG_CPU_ICACHE_DISABLE
185         mcr     p15, 0, r0, c7, c5, 1           @ invalidate I entry
186 #endif
187         add     r0, r0, #CACHE_DLINESIZE
188         cmp     r0, r1
189         blo     1b
190         mcr     p15, 0, ip, c7, c10, 4          @ drain WB
191         mov     pc, lr
192
193 /*
194  *      flush_kern_dcache_page(void *page)
195  *
196  *      Ensure no D cache aliasing occurs, either with itself or
197  *      the I cache
198  *
199  *      - page  - page aligned address
200  */
201 ENTRY(arm1026_flush_kern_dcache_page)
202         mov     ip, #0
203 #ifndef CONFIG_CPU_DCACHE_DISABLE
204         add     r1, r0, #PAGE_SZ
205 1:      mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
206         add     r0, r0, #CACHE_DLINESIZE
207         cmp     r0, r1
208         blo     1b
209 #endif
210         mcr     p15, 0, ip, c7, c10, 4          @ drain WB
211         mov     pc, lr
212
213 /*
214  *      dma_inv_range(start, end)
215  *
216  *      Invalidate (discard) the specified virtual address range.
217  *      May not write back any entries.  If 'start' or 'end'
218  *      are not cache line aligned, those lines must be written
219  *      back.
220  *
221  *      - start - virtual start address
222  *      - end   - virtual end address
223  *
224  * (same as v4wb)
225  */
226 ENTRY(arm1026_dma_inv_range)
227         mov     ip, #0
228 #ifndef CONFIG_CPU_DCACHE_DISABLE
229         tst     r0, #CACHE_DLINESIZE - 1
230         bic     r0, r0, #CACHE_DLINESIZE - 1
231         mcrne   p15, 0, r0, c7, c10, 1          @ clean D entry
232         tst     r1, #CACHE_DLINESIZE - 1
233         mcrne   p15, 0, r1, c7, c10, 1          @ clean D entry
234 1:      mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
235         add     r0, r0, #CACHE_DLINESIZE
236         cmp     r0, r1
237         blo     1b
238 #endif
239         mcr     p15, 0, ip, c7, c10, 4          @ drain WB
240         mov     pc, lr
241
242 /*
243  *      dma_clean_range(start, end)
244  *
245  *      Clean the specified virtual address range.
246  *
247  *      - start - virtual start address
248  *      - end   - virtual end address
249  *
250  * (same as v4wb)
251  */
252 ENTRY(arm1026_dma_clean_range)
253         mov     ip, #0
254 #ifndef CONFIG_CPU_DCACHE_DISABLE
255         bic     r0, r0, #CACHE_DLINESIZE - 1
256 1:      mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
257         add     r0, r0, #CACHE_DLINESIZE
258         cmp     r0, r1
259         blo     1b
260 #endif
261         mcr     p15, 0, ip, c7, c10, 4          @ drain WB
262         mov     pc, lr
263
264 /*
265  *      dma_flush_range(start, end)
266  *
267  *      Clean and invalidate the specified virtual address range.
268  *
269  *      - start - virtual start address
270  *      - end   - virtual end address
271  */
272 ENTRY(arm1026_dma_flush_range)
273         mov     ip, #0
274 #ifndef CONFIG_CPU_DCACHE_DISABLE
275         bic     r0, r0, #CACHE_DLINESIZE - 1
276 1:      mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
277         add     r0, r0, #CACHE_DLINESIZE
278         cmp     r0, r1
279         blo     1b
280 #endif
281         mcr     p15, 0, ip, c7, c10, 4          @ drain WB
282         mov     pc, lr
283
284 ENTRY(arm1026_cache_fns)
285         .long   arm1026_flush_kern_cache_all
286         .long   arm1026_flush_user_cache_all
287         .long   arm1026_flush_user_cache_range
288         .long   arm1026_coherent_kern_range
289         .long   arm1026_flush_kern_dcache_page
290         .long   arm1026_dma_inv_range
291         .long   arm1026_dma_clean_range
292         .long   arm1026_dma_flush_range
293
294         .align  5
295 ENTRY(cpu_arm1026_dcache_clean_area)
296 #ifndef CONFIG_CPU_DCACHE_DISABLE
297         mov     ip, #0
298 1:      mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
299         add     r0, r0, #CACHE_DLINESIZE
300         subs    r1, r1, #CACHE_DLINESIZE
301         bhi     1b
302 #endif
303         mov     pc, lr
304
305 /* =============================== PageTable ============================== */
306
307 /*
308  * cpu_arm1026_switch_mm(pgd)
309  *
310  * Set the translation base pointer to be as described by pgd.
311  *
312  * pgd: new page tables
313  */
314         .align  5
315 ENTRY(cpu_arm1026_switch_mm)
316         mov     r1, #0
317 #ifndef CONFIG_CPU_DCACHE_DISABLE
318 1:      mrc     p15, 0, r15, c7, c14, 3         @ test, clean, invalidate
319         bne     1b
320 #endif
321 #ifndef CONFIG_CPU_ICACHE_DISABLE
322         mcr     p15, 0, r1, c7, c5, 0           @ invalidate I cache
323 #endif
324         mcr     p15, 0, r1, c7, c10, 4          @ drain WB
325         mcr     p15, 0, r0, c2, c0, 0           @ load page table pointer
326         mcr     p15, 0, r1, c8, c7, 0           @ invalidate I & D TLBs
327         mov     pc, lr
328         
329 /*
330  * cpu_arm1026_set_pte(ptep, pte)
331  *
332  * Set a PTE and flush it out
333  */
334         .align  5
335 ENTRY(cpu_arm1026_set_pte)
336         str     r1, [r0], #-2048                @ linux version
337
338         eor     r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
339
340         bic     r2, r1, #PTE_SMALL_AP_MASK
341         bic     r2, r2, #PTE_TYPE_MASK
342         orr     r2, r2, #PTE_TYPE_SMALL
343
344         tst     r1, #L_PTE_USER                 @ User?
345         orrne   r2, r2, #PTE_SMALL_AP_URO_SRW
346
347         tst     r1, #L_PTE_WRITE | L_PTE_DIRTY  @ Write and Dirty?
348         orreq   r2, r2, #PTE_SMALL_AP_UNO_SRW
349
350         tst     r1, #L_PTE_PRESENT | L_PTE_YOUNG        @ Present and Young?
351         movne   r2, #0
352
353 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
354         eor     r3, r1, #0x0a                   @ C & small page?
355         tst     r3, #0x0b
356         biceq   r2, r2, #4
357 #endif
358         str     r2, [r0]                        @ hardware version
359         mov     r0, r0
360 #ifndef CONFIG_CPU_DCACHE_DISABLE
361         mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
362 #endif
363         mov     pc, lr
364
365
366         __INIT
367
368         .type   __arm1026_setup, #function
369 __arm1026_setup:
370         mov     r0, #0
371         mcr     p15, 0, r0, c7, c7              @ invalidate I,D caches on v4
372         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer on v4
373         mcr     p15, 0, r0, c8, c7              @ invalidate I,D TLBs on v4
374         mcr     p15, 0, r4, c2, c0              @ load page table pointer
375 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
376         mov     r0, #4                          @ explicitly disable writeback
377         mcr     p15, 7, r0, c15, c0, 0
378 #endif
379         mov     r0, #0x1f                       @ Domains 0, 1 = client
380         mcr     p15, 0, r0, c3, c0              @ load domain access register
381         mrc     p15, 0, r0, c1, c0              @ get control register v4
382 /*
383  * Clear out 'unwanted' bits (then put them in if we need them)
384  */
385         bic     r0, r0, #0x1e00                 @ ...i??r.........
386         bic     r0, r0, #0x000e                 @ ............wca.
387 /*
388  * Turn on what we want
389  */
390         orr     r0, r0, #0x0031                 @ ..........DP...M
391         orr     r0, r0, #0x2100                 @ ..V....S........
392
393 #ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
394         orr     r0, r0, #0x4000                 @ .R..............
395 #endif
396 #ifndef CONFIG_CPU_BPREDICT_DISABLE
397         orr     r0, r0, #0x0800                 @ ....Z...........
398 #endif
399 #ifndef CONFIG_CPU_DCACHE_DISABLE
400         orr     r0, r0, #0x0004                 @ .............C..
401 #endif
402 #ifndef CONFIG_CPU_ICACHE_DISABLE
403         orr     r0, r0, #0x1000                 @ ...I............
404 #endif
405         mov     pc, lr
406         .size   __arm1026_setup, . - __arm1026_setup
407
408         __INITDATA
409
410 /*
411  * Purpose : Function pointers used to access above functions - all calls
412  *           come through these
413  */
414         .type   arm1026_processor_functions, #object
415 arm1026_processor_functions:
416         .word   v5t_early_abort
417         .word   cpu_arm1026_proc_init
418         .word   cpu_arm1026_proc_fin
419         .word   cpu_arm1026_reset
420         .word   cpu_arm1026_do_idle
421         .word   cpu_arm1026_dcache_clean_area
422         .word   cpu_arm1026_switch_mm
423         .word   cpu_arm1026_set_pte
424         .size   arm1026_processor_functions, . - arm1026_processor_functions
425
426         .section .rodata
427
428         .type   cpu_arch_name, #object
429 cpu_arch_name:
430         .asciz  "armv5tej"
431         .size   cpu_arch_name, . - cpu_arch_name
432
433         .type   cpu_elf_name, #object
434 cpu_elf_name:
435         .asciz  "v5"
436         .size   cpu_elf_name, . - cpu_elf_name
437         .align
438
439         .type   cpu_arm1026_name, #object
440 cpu_arm1026_name:
441         .ascii  "ARM1026EJ-S"
442 #ifndef CONFIG_CPU_ICACHE_DISABLE
443         .ascii  "i"
444 #endif
445 #ifndef CONFIG_CPU_DCACHE_DISABLE
446         .ascii  "d"
447 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
448         .ascii  "(wt)"
449 #else
450         .ascii  "(wb)"
451 #endif
452 #endif
453 #ifndef CONFIG_CPU_BPREDICT_DISABLE
454         .ascii  "B"
455 #endif
456 #ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
457         .ascii  "RR"
458 #endif
459         .ascii  "\0"
460         .size   cpu_arm1026_name, . - cpu_arm1026_name
461
462         .align
463
464         .section ".proc.info", #alloc, #execinstr
465
466         .type   __arm1026_proc_info,#object
467 __arm1026_proc_info:
468         .long   0x4106a260                      @ ARM 1026EJ-S (v5TEJ)
469         .long   0xff0ffff0
470         .long   0x00000c12                      @ mmuflags
471         b       __arm1026_setup
472         .long   cpu_arch_name
473         .long   cpu_elf_name
474         .long   HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT
475         .long   cpu_arm1026_name
476         .long   arm1026_processor_functions
477         .long   v4wbi_tlb_fns
478         .long   v4wb_user_fns
479         .long   arm1026_cache_fns
480         .size   __arm1026_proc_info, . - __arm1026_proc_info