Merge git://git.infradead.org/mtd-2.6
[linux-2.6] / arch / arm / mm / proc-xsc3.S
1 /*
2  * linux/arch/arm/mm/proc-xsc3.S
3  *
4  * Original Author: Matthew Gilbert
5  * Current Maintainer: Lennert Buytenhek <buytenh@wantstofly.org>
6  *
7  * Copyright 2004 (C) Intel Corp.
8  * Copyright 2005 (C) MontaVista Software, Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  *
14  * MMU functions for the Intel XScale3 Core (XSC3).  The XSC3 core is
15  * an extension to Intel's original XScale core that adds the following
16  * features:
17  *
18  * - ARMv6 Supersections
19  * - Low Locality Reference pages (replaces mini-cache)
20  * - 36-bit addressing
21  * - L2 cache
22  * - Cache coherency if chipset supports it
23  *
24  * Based on original XScale code by Nicolas Pitre.
25  */
26
27 #include <linux/linkage.h>
28 #include <linux/init.h>
29 #include <asm/assembler.h>
30 #include <asm/elf.h>
31 #include <asm/hardware.h>
32 #include <asm/pgtable.h>
33 #include <asm/pgtable-hwdef.h>
34 #include <asm/page.h>
35 #include <asm/ptrace.h>
36 #include "proc-macros.S"
37
38 /*
39  * This is the maximum size of an area which will be flushed.  If the
40  * area is larger than this, then we flush the whole cache.
41  */
42 #define MAX_AREA_SIZE   32768
43
44 /*
45  * The cache line size of the L1 I, L1 D and unified L2 cache.
46  */
47 #define CACHELINESIZE   32
48
49 /*
50  * The size of the L1 D cache.
51  */
52 #define CACHESIZE       32768
53
54 /*
55  * Run with L2 enabled.
56  */
57 #define L2_CACHE_ENABLE 1
58
59 /*
60  * This macro is used to wait for a CP15 write and is needed when we
61  * have to ensure that the last operation to the coprocessor was
62  * completed before continuing with operation.
63  */
64         .macro  cpwait_ret, lr, rd
65         mrc     p15, 0, \rd, c2, c0, 0          @ arbitrary read of cp15
66         sub     pc, \lr, \rd, LSR #32           @ wait for completion and
67                                                 @ flush instruction pipeline
68         .endm
69
70 /*
71  * This macro cleans and invalidates the entire L1 D cache.
72  */
73
74         .macro  clean_d_cache rd, rs
75         mov     \rd, #0x1f00
76         orr     \rd, \rd, #0x00e0
77 1:      mcr     p15, 0, \rd, c7, c14, 2         @ clean/invalidate L1 D line
78         adds    \rd, \rd, #0x40000000
79         bcc     1b
80         subs    \rd, \rd, #0x20
81         bpl     1b
82         .endm
83
84         .text
85
86 /*
87  * cpu_xsc3_proc_init()
88  *
89  * Nothing too exciting at the moment
90  */
91 ENTRY(cpu_xsc3_proc_init)
92         mov     pc, lr
93
94 /*
95  * cpu_xsc3_proc_fin()
96  */
97 ENTRY(cpu_xsc3_proc_fin)
98         str     lr, [sp, #-4]!
99         mov     r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
100         msr     cpsr_c, r0
101         bl      xsc3_flush_kern_cache_all       @ clean caches
102         mrc     p15, 0, r0, c1, c0, 0           @ ctrl register
103         bic     r0, r0, #0x1800                 @ ...IZ...........
104         bic     r0, r0, #0x0006                 @ .............CA.
105         mcr     p15, 0, r0, c1, c0, 0           @ disable caches
106         ldr     pc, [sp], #4
107
108 /*
109  * cpu_xsc3_reset(loc)
110  *
111  * Perform a soft reset of the system.  Put the CPU into the
112  * same state as it would be if it had been reset, and branch
113  * to what would be the reset vector.
114  *
115  * loc: location to jump to for soft reset
116  */
117         .align  5
118 ENTRY(cpu_xsc3_reset)
119         mov     r1, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
120         msr     cpsr_c, r1                      @ reset CPSR
121         mrc     p15, 0, r1, c1, c0, 0           @ ctrl register
122         bic     r1, r1, #0x3900                 @ ..VIZ..S........
123         bic     r1, r1, #0x0086                 @ ........B....CA.
124         mcr     p15, 0, r1, c1, c0, 0           @ ctrl register
125         mcr     p15, 0, ip, c7, c7, 0           @ invalidate L1 caches and BTB
126         bic     r1, r1, #0x0001                 @ ...............M
127         mcr     p15, 0, r1, c1, c0, 0           @ ctrl register
128         @ CAUTION: MMU turned off from this point.  We count on the pipeline
129         @ already containing those two last instructions to survive.
130         mcr     p15, 0, ip, c8, c7, 0           @ invalidate I and D TLBs
131         mov     pc, r0
132
133 /*
134  * cpu_xsc3_do_idle()
135  *
136  * Cause the processor to idle
137  *
138  * For now we do nothing but go to idle mode for every case
139  *
140  * XScale supports clock switching, but using idle mode support
141  * allows external hardware to react to system state changes.
142  */
143         .align  5
144
145 ENTRY(cpu_xsc3_do_idle)
146         mov     r0, #1
147         mcr     p14, 0, r0, c7, c0, 0           @ go to idle
148         mov     pc, lr
149
150 /* ================================= CACHE ================================ */
151
152 /*
153  *      flush_user_cache_all()
154  *
155  *      Invalidate all cache entries in a particular address
156  *      space.
157  */
158 ENTRY(xsc3_flush_user_cache_all)
159         /* FALLTHROUGH */
160
161 /*
162  *      flush_kern_cache_all()
163  *
164  *      Clean and invalidate the entire cache.
165  */
166 ENTRY(xsc3_flush_kern_cache_all)
167         mov     r2, #VM_EXEC
168         mov     ip, #0
169 __flush_whole_cache:
170         clean_d_cache r0, r1
171         tst     r2, #VM_EXEC
172         mcrne   p15, 0, ip, c7, c5, 0           @ invalidate L1 I cache and BTB
173         mcrne   p15, 0, ip, c7, c10, 4          @ data write barrier
174         mcrne   p15, 0, ip, c7, c5, 4           @ prefetch flush
175         mov     pc, lr
176
177 /*
178  *      flush_user_cache_range(start, end, vm_flags)
179  *
180  *      Invalidate a range of cache entries in the specified
181  *      address space.
182  *
183  *      - start - start address (may not be aligned)
184  *      - end   - end address (exclusive, may not be aligned)
185  *      - vma   - vma_area_struct describing address space
186  */
187         .align  5
188 ENTRY(xsc3_flush_user_cache_range)
189         mov     ip, #0
190         sub     r3, r1, r0                      @ calculate total size
191         cmp     r3, #MAX_AREA_SIZE
192         bhs     __flush_whole_cache
193
194 1:      tst     r2, #VM_EXEC
195         mcrne   p15, 0, r0, c7, c5, 1           @ invalidate L1 I line
196         mcr     p15, 0, r0, c7, c14, 1          @ clean/invalidate L1 D line
197         add     r0, r0, #CACHELINESIZE
198         cmp     r0, r1
199         blo     1b
200         tst     r2, #VM_EXEC
201         mcrne   p15, 0, ip, c7, c5, 6           @ invalidate BTB
202         mcrne   p15, 0, ip, c7, c10, 4          @ data write barrier
203         mcrne   p15, 0, ip, c7, c5, 4           @ prefetch flush
204         mov     pc, lr
205
206 /*
207  *      coherent_kern_range(start, end)
208  *
209  *      Ensure coherency between the I cache and the D cache in the
210  *      region described by start.  If you have non-snooping
211  *      Harvard caches, you need to implement this function.
212  *
213  *      - start  - virtual start address
214  *      - end    - virtual end address
215  *
216  *      Note: single I-cache line invalidation isn't used here since
217  *      it also trashes the mini I-cache used by JTAG debuggers.
218  */
219 ENTRY(xsc3_coherent_kern_range)
220 /* FALLTHROUGH */
221 ENTRY(xsc3_coherent_user_range)
222         bic     r0, r0, #CACHELINESIZE - 1
223 1:      mcr     p15, 0, r0, c7, c10, 1          @ clean L1 D line
224         add     r0, r0, #CACHELINESIZE
225         cmp     r0, r1
226         blo     1b
227         mov     r0, #0
228         mcr     p15, 0, r0, c7, c5, 0           @ invalidate L1 I cache and BTB
229         mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
230         mcr     p15, 0, r0, c7, c5, 4           @ prefetch flush
231         mov     pc, lr
232
233 /*
234  *      flush_kern_dcache_page(void *page)
235  *
236  *      Ensure no D cache aliasing occurs, either with itself or
237  *      the I cache.
238  *
239  *      - addr  - page aligned address
240  */
241 ENTRY(xsc3_flush_kern_dcache_page)
242         add     r1, r0, #PAGE_SZ
243 1:      mcr     p15, 0, r0, c7, c14, 1          @ clean/invalidate L1 D line
244         add     r0, r0, #CACHELINESIZE
245         cmp     r0, r1
246         blo     1b
247         mov     r0, #0
248         mcr     p15, 0, r0, c7, c5, 0           @ invalidate L1 I cache and BTB
249         mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
250         mcr     p15, 0, r0, c7, c5, 4           @ prefetch flush
251         mov     pc, lr
252
253 /*
254  *      dma_inv_range(start, end)
255  *
256  *      Invalidate (discard) the specified virtual address range.
257  *      May not write back any entries.  If 'start' or 'end'
258  *      are not cache line aligned, those lines must be written
259  *      back.
260  *
261  *      - start  - virtual start address
262  *      - end    - virtual end address
263  */
264 ENTRY(xsc3_dma_inv_range)
265         tst     r0, #CACHELINESIZE - 1
266         bic     r0, r0, #CACHELINESIZE - 1
267         mcrne   p15, 0, r0, c7, c10, 1          @ clean L1 D line
268         mcrne   p15, 1, r0, c7, c11, 1          @ clean L2 line
269         tst     r1, #CACHELINESIZE - 1
270         mcrne   p15, 0, r1, c7, c10, 1          @ clean L1 D line
271         mcrne   p15, 1, r1, c7, c11, 1          @ clean L2 line
272 1:      mcr     p15, 0, r0, c7, c6, 1           @ invalidate L1 D line
273         mcr     p15, 1, r0, c7, c7, 1           @ invalidate L2 line
274         add     r0, r0, #CACHELINESIZE
275         cmp     r0, r1
276         blo     1b
277         mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
278         mov     pc, lr
279
280 /*
281  *      dma_clean_range(start, end)
282  *
283  *      Clean the specified virtual address range.
284  *
285  *      - start  - virtual start address
286  *      - end    - virtual end address
287  */
288 ENTRY(xsc3_dma_clean_range)
289         bic     r0, r0, #CACHELINESIZE - 1
290 1:      mcr     p15, 0, r0, c7, c10, 1          @ clean L1 D line
291         mcr     p15, 1, r0, c7, c11, 1          @ clean L2 line
292         add     r0, r0, #CACHELINESIZE
293         cmp     r0, r1
294         blo     1b
295         mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
296         mov     pc, lr
297
298 /*
299  *      dma_flush_range(start, end)
300  *
301  *      Clean and invalidate the specified virtual address range.
302  *
303  *      - start  - virtual start address
304  *      - end    - virtual end address
305  */
306 ENTRY(xsc3_dma_flush_range)
307         bic     r0, r0, #CACHELINESIZE - 1
308 1:      mcr     p15, 0, r0, c7, c14, 1          @ clean/invalidate L1 D line
309         mcr     p15, 1, r0, c7, c11, 1          @ clean L2 line
310         mcr     p15, 1, r0, c7, c7, 1           @ invalidate L2 line
311         add     r0, r0, #CACHELINESIZE
312         cmp     r0, r1
313         blo     1b
314         mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
315         mov     pc, lr
316
317 ENTRY(xsc3_cache_fns)
318         .long   xsc3_flush_kern_cache_all
319         .long   xsc3_flush_user_cache_all
320         .long   xsc3_flush_user_cache_range
321         .long   xsc3_coherent_kern_range
322         .long   xsc3_coherent_user_range
323         .long   xsc3_flush_kern_dcache_page
324         .long   xsc3_dma_inv_range
325         .long   xsc3_dma_clean_range
326         .long   xsc3_dma_flush_range
327
328 ENTRY(cpu_xsc3_dcache_clean_area)
329 1:      mcr     p15, 0, r0, c7, c10, 1          @ clean L1 D line
330         add     r0, r0, #CACHELINESIZE
331         subs    r1, r1, #CACHELINESIZE
332         bhi     1b
333         mov     pc, lr
334
335 /* =============================== PageTable ============================== */
336
337 /*
338  * cpu_xsc3_switch_mm(pgd)
339  *
340  * Set the translation base pointer to be as described by pgd.
341  *
342  * pgd: new page tables
343  */
344         .align  5
345 ENTRY(cpu_xsc3_switch_mm)
346         clean_d_cache r1, r2
347         mcr     p15, 0, ip, c7, c5, 0           @ invalidate L1 I cache and BTB
348         mcr     p15, 0, ip, c7, c10, 4          @ data write barrier
349         mcr     p15, 0, ip, c7, c5, 4           @ prefetch flush
350 #ifdef L2_CACHE_ENABLE
351         orr     r0, r0, #0x18                   @ cache the page table in L2
352 #endif
353         mcr     p15, 0, r0, c2, c0, 0           @ load page table pointer
354         mcr     p15, 0, ip, c8, c7, 0           @ invalidate I and D TLBs
355         cpwait_ret lr, ip
356
357 /*
358  * cpu_xsc3_set_pte_ext(ptep, pte, ext)
359  *
360  * Set a PTE and flush it out
361  *
362  */
363         .align  5
364 ENTRY(cpu_xsc3_set_pte_ext)
365         str     r1, [r0], #-2048                @ linux version
366
367         bic     r2, r1, #0xff0                  @ keep C, B bits
368         orr     r2, r2, #PTE_TYPE_EXT           @ extended page
369         tst     r1, #L_PTE_SHARED               @ shared?
370         orrne   r2, r2, #0x200
371
372         eor     r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
373
374         tst     r3, #L_PTE_USER                 @ user?
375         orrne   r2, r2, #PTE_EXT_AP_URO_SRW     @ yes -> user r/o, system r/w
376
377         tst     r3, #L_PTE_WRITE | L_PTE_DIRTY  @ write and dirty?
378         orreq   r2, r2, #PTE_EXT_AP_UNO_SRW     @ yes -> user n/a, system r/w
379                                                 @ combined with user -> user r/w
380
381 #if L2_CACHE_ENABLE
382         @ If it's cacheable, it needs to be in L2 also.
383         eor     ip, r1, #L_PTE_CACHEABLE
384         tst     ip, #L_PTE_CACHEABLE
385         orreq   r2, r2, #PTE_EXT_TEX(0x5)
386 #endif
387
388         tst     r3, #L_PTE_PRESENT | L_PTE_YOUNG        @ present and young?
389         movne   r2, #0                          @ no -> fault
390
391         str     r2, [r0]                        @ hardware version
392         mov     ip, #0
393         mcr     p15, 0, r0, c7, c10, 1          @ clean L1 D line
394         mcr     p15, 0, ip, c7, c10, 4          @ data write barrier
395         mov     pc, lr
396
397         .ltorg
398
399         .align
400
401         __INIT
402
403         .type   __xsc3_setup, #function
404 __xsc3_setup:
405         mov     r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
406         msr     cpsr_c, r0
407         mcr     p15, 0, ip, c7, c7, 0           @ invalidate L1 caches and BTB
408         mcr     p15, 0, ip, c7, c10, 4          @ data write barrier
409         mcr     p15, 0, ip, c7, c5, 4           @ prefetch flush
410         mcr     p15, 0, ip, c8, c7, 0           @ invalidate I and D TLBs
411 #if L2_CACHE_ENABLE
412         orr     r4, r4, #0x18                   @ cache the page table in L2
413 #endif
414         mcr     p15, 0, r4, c2, c0, 0           @ load page table pointer
415
416         mov     r0, #0                          @ don't allow CP access
417         mcr     p15, 0, r0, c15, c1, 0          @ write CP access register
418
419         mrc     p15, 0, r0, c1, c0, 1           @ get auxiliary control reg
420         and     r0, r0, #2                      @ preserve bit P bit setting
421 #if L2_CACHE_ENABLE
422         orr     r0, r0, #(1 << 10)              @ enable L2 for LLR cache
423 #endif
424         mcr     p15, 0, r0, c1, c0, 1           @ set auxiliary control reg
425
426         adr     r5, xsc3_crval
427         ldmia   r5, {r5, r6}
428         mrc     p15, 0, r0, c1, c0, 0           @ get control register
429         bic     r0, r0, r5                      @ ..V. ..R. .... ..A.
430         orr     r0, r0, r6                      @ ..VI Z..S .... .C.M (mmu)
431                                                 @ ...I Z..S .... .... (uc)
432 #if L2_CACHE_ENABLE
433         orr     r0, r0, #0x04000000             @ L2 enable
434 #endif
435         mov     pc, lr
436
437         .size   __xsc3_setup, . - __xsc3_setup
438
439         .type   xsc3_crval, #object
440 xsc3_crval:
441         crval   clear=0x04002202, mmuset=0x00003905, ucset=0x00001900
442
443         __INITDATA
444
445 /*
446  * Purpose : Function pointers used to access above functions - all calls
447  *           come through these
448  */
449
450         .type   xsc3_processor_functions, #object
451 ENTRY(xsc3_processor_functions)
452         .word   v5t_early_abort
453         .word   cpu_xsc3_proc_init
454         .word   cpu_xsc3_proc_fin
455         .word   cpu_xsc3_reset
456         .word   cpu_xsc3_do_idle
457         .word   cpu_xsc3_dcache_clean_area
458         .word   cpu_xsc3_switch_mm
459         .word   cpu_xsc3_set_pte_ext
460         .size   xsc3_processor_functions, . - xsc3_processor_functions
461
462         .section ".rodata"
463
464         .type   cpu_arch_name, #object
465 cpu_arch_name:
466         .asciz  "armv5te"
467         .size   cpu_arch_name, . - cpu_arch_name
468
469         .type   cpu_elf_name, #object
470 cpu_elf_name:
471         .asciz  "v5"
472         .size   cpu_elf_name, . - cpu_elf_name
473
474         .type   cpu_xsc3_name, #object
475 cpu_xsc3_name:
476         .asciz  "XScale-V3 based processor"
477         .size   cpu_xsc3_name, . - cpu_xsc3_name
478
479         .align
480
481         .section ".proc.info.init", #alloc, #execinstr
482
483         .type   __xsc3_proc_info,#object
484 __xsc3_proc_info:
485         .long   0x69056000
486         .long   0xffffe000
487         .long   PMD_TYPE_SECT | \
488                 PMD_SECT_BUFFERABLE | \
489                 PMD_SECT_CACHEABLE | \
490                 PMD_SECT_AP_WRITE | \
491                 PMD_SECT_AP_READ
492         .long   PMD_TYPE_SECT | \
493                 PMD_SECT_AP_WRITE | \
494                 PMD_SECT_AP_READ
495         b       __xsc3_setup
496         .long   cpu_arch_name
497         .long   cpu_elf_name
498         .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
499         .long   cpu_xsc3_name
500         .long   xsc3_processor_functions
501         .long   v4wbi_tlb_fns
502         .long   xsc3_mc_user_fns
503         .long   xsc3_cache_fns
504         .size   __xsc3_proc_info, . - __xsc3_proc_info