MOXA linux-2.6.x / linux-2.6.19-uc1 from UC-7110-LX-BOOTLOADER-1.9_VERSION-4.2.tgz
[linux-2.6.19-moxart.git] / arch / arm / mm / proc-arm925.S
blob3b4bd1fcc759346fa8d1fe5cb680c8cbb2d7bc8c
1 /*
2  *  linux/arch/arm/mm/arm925.S: MMU functions for ARM925
3  *
4  *  Copyright (C) 1999,2000 ARM Limited
5  *  Copyright (C) 2000 Deep Blue Solutions Ltd.
6  *  Copyright (C) 2002 RidgeRun, Inc.
7  *  Copyright (C) 2002-2003 MontaVista Software, Inc.
8  *  Copyright (C) 2003 Hyok S. Choi <hyok.choi@samsung.com>
9  *  modified for NON-PAGED MMU version.
10  *
11  *  Update for Linux-2.6 and cache flush improvements
12  *  Copyright (C) 2004 Nokia Corporation by Tony Lindgren <tony@atomide.com>
13  *
14  *  hacked for non-paged-MM by Hyok S. Choi, 2004.
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 2 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29  *
30  *
31  * These are the low level assembler for performing cache and TLB
32  * functions on the arm925.
33  *
34  *  CONFIG_CPU_ARM925_CPU_IDLE -> nohlt
35  *
36  * Some additional notes based on deciphering the TI TRM on OMAP-5910:
37  *
38  * NOTE1: The TI925T Configuration Register bit "D-cache clean and flush
39  *        entry mode" must be 0 to flush the entries in both segments
40  *        at once. This is the default value. See TRM 2-20 and 2-24 for
41  *        more information.
42  *
43  * NOTE2: Default is the "D-cache clean and flush entry mode". It looks
44  *        like the "Transparent mode" must be on for partial cache flushes
45  *        to work in this mode. This mode only works with 16-bit external
46  *        memory. See TRM 2-24 for more information.
47  *
48  * NOTE3: Write-back cache flushing seems to be flakey with devices using
49  *        direct memory access, such as USB OHCI. The workaround is to use
50  *        write-through cache with CONFIG_CPU_DCACHE_WRITETHROUGH (this is
51  *        the default for OMAP-1510).
52  */
54 #include <linux/linkage.h>
55 #include <linux/init.h>
56 #include <asm/assembler.h>
57 #include <asm/pgtable-hwdef.h>
58 #include <asm/pgtable.h>
59 #include <asm/procinfo.h>
60 #include <asm/page.h>
61 #include <asm/ptrace.h>
62 #include "proc-macros.S"
65  * The size of one data cache line.
66  */
67 #define CACHE_DLINESIZE 16
70  * The number of data cache segments.
71  */
72 #define CACHE_DSEGMENTS 2
75  * The number of lines in a cache segment.
76  */
77 #define CACHE_DENTRIES  256
80  * This is the size at which it becomes more efficient to
81  * clean the whole cache, rather than using the individual
82  * cache line maintainence instructions.
83  */
84 #define CACHE_DLIMIT    8192
86         .text
88  * cpu_arm925_proc_init()
89  */
90 ENTRY(cpu_arm925_proc_init)
91         mov     pc, lr
94  * cpu_arm925_proc_fin()
95  */
96 ENTRY(cpu_arm925_proc_fin)
97         stmfd   sp!, {lr}
98         mov     ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
99         msr     cpsr_c, ip
100         bl      arm925_flush_kern_cache_all
101         mrc     p15, 0, r0, c1, c0, 0           @ ctrl register
102         bic     r0, r0, #0x1000                 @ ...i............
103         bic     r0, r0, #0x000e                 @ ............wca.
104         mcr     p15, 0, r0, c1, c0, 0           @ disable caches
105         ldmfd   sp!, {pc}
108  * cpu_arm925_reset(loc)
110  * Perform a soft reset of the system.  Put the CPU into the
111  * same state as it would be if it had been reset, and branch
112  * to what would be the reset vector.
114  * loc: location to jump to for soft reset
115  */
116         .align  5
117 ENTRY(cpu_arm925_reset)
118         /* Send software reset to MPU and DSP */
119         mov     ip, #0xff000000
120         orr     ip, ip, #0x00fe0000
121         orr     ip, ip, #0x0000ce00
122         mov     r4, #1
123         strh    r4, [ip, #0x10]
125         mov     ip, #0
126         mcr     p15, 0, ip, c7, c7, 0           @ invalidate I,D caches
127         mcr     p15, 0, ip, c7, c10, 4          @ drain WB
128 #ifdef CONFIG_MMU
129         mcr     p15, 0, ip, c8, c7, 0           @ invalidate I & D TLBs
130 #endif
131         mrc     p15, 0, ip, c1, c0, 0           @ ctrl register
132         bic     ip, ip, #0x000f                 @ ............wcam
133         bic     ip, ip, #0x1100                 @ ...i...s........
134         mcr     p15, 0, ip, c1, c0, 0           @ ctrl register
135         mov     pc, r0
138  * cpu_arm925_do_idle()
140  * Called with IRQs disabled
141  */
142         .align  10
143 ENTRY(cpu_arm925_do_idle)
144         mov     r0, #0
145         mrc     p15, 0, r1, c1, c0, 0           @ Read control register
146         mcr     p15, 0, r0, c7, c10, 4          @ Drain write buffer
147         bic     r2, r1, #1 << 12
148         mcr     p15, 0, r2, c1, c0, 0           @ Disable I cache
149         mcr     p15, 0, r0, c7, c0, 4           @ Wait for interrupt
150         mcr     p15, 0, r1, c1, c0, 0           @ Restore ICache enable
151         mov     pc, lr
154  *      flush_user_cache_all()
156  *      Clean and invalidate all cache entries in a particular
157  *      address space.
158  */
159 ENTRY(arm925_flush_user_cache_all)
160         /* FALLTHROUGH */
163  *      flush_kern_cache_all()
165  *      Clean and invalidate the entire cache.
166  */
167 ENTRY(arm925_flush_kern_cache_all)
168         mov     r2, #VM_EXEC
169         mov     ip, #0
170 __flush_whole_cache:
171 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
172         mcr     p15, 0, ip, c7, c6, 0           @ invalidate D cache
173 #else
174         /* Flush entries in both segments at once, see NOTE1 above */
175         mov     r3, #(CACHE_DENTRIES - 1) << 4  @ 256 entries in segment
176 2:      mcr     p15, 0, r3, c7, c14, 2          @ clean+invalidate D index
177         subs    r3, r3, #1 << 4
178         bcs     2b                              @ entries 255 to 0
179 #endif
180         tst     r2, #VM_EXEC
181         mcrne   p15, 0, ip, c7, c5, 0           @ invalidate I cache
182         mcrne   p15, 0, ip, c7, c10, 4          @ drain WB
183         mov     pc, lr
186  *      flush_user_cache_range(start, end, flags)
188  *      Clean and invalidate a range of cache entries in the
189  *      specified address range.
191  *      - start - start address (inclusive)
192  *      - end   - end address (exclusive)
193  *      - flags - vm_flags describing address space
194  */
195 ENTRY(arm925_flush_user_cache_range)
196         mov     ip, #0
197         sub     r3, r1, r0                      @ calculate total size
198         cmp     r3, #CACHE_DLIMIT
199         bgt     __flush_whole_cache
200 1:      tst     r2, #VM_EXEC
201 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
202         mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
203         mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I entry
204         add     r0, r0, #CACHE_DLINESIZE
205         mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
206         mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I entry
207         add     r0, r0, #CACHE_DLINESIZE
208 #else
209         mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
210         mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I entry
211         add     r0, r0, #CACHE_DLINESIZE
212         mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
213         mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I entry
214         add     r0, r0, #CACHE_DLINESIZE
215 #endif
216         cmp     r0, r1
217         blo     1b
218         tst     r2, #VM_EXEC
219         mcrne   p15, 0, ip, c7, c10, 4          @ drain WB
220         mov     pc, lr
223  *      coherent_kern_range(start, end)
225  *      Ensure coherency between the Icache and the Dcache in the
226  *      region described by start, end.  If you have non-snooping
227  *      Harvard caches, you need to implement this function.
229  *      - start - virtual start address
230  *      - end   - virtual end address
231  */
232 ENTRY(arm925_coherent_kern_range)
233         /* FALLTHROUGH */
236  *      coherent_user_range(start, end)
238  *      Ensure coherency between the Icache and the Dcache in the
239  *      region described by start, end.  If you have non-snooping
240  *      Harvard caches, you need to implement this function.
242  *      - start - virtual start address
243  *      - end   - virtual end address
244  */
245 ENTRY(arm925_coherent_user_range)
246         bic     r0, r0, #CACHE_DLINESIZE - 1
247 1:      mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
248         mcr     p15, 0, r0, c7, c5, 1           @ invalidate I entry
249         add     r0, r0, #CACHE_DLINESIZE
250         cmp     r0, r1
251         blo     1b
252         mcr     p15, 0, r0, c7, c10, 4          @ drain WB
253         mov     pc, lr
256  *      flush_kern_dcache_page(void *page)
258  *      Ensure no D cache aliasing occurs, either with itself or
259  *      the I cache
261  *      - addr  - page aligned address
262  */
263 ENTRY(arm925_flush_kern_dcache_page)
264         add     r1, r0, #PAGE_SZ
265 1:      mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
266         add     r0, r0, #CACHE_DLINESIZE
267         cmp     r0, r1
268         blo     1b
269         mov     r0, #0
270         mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
271         mcr     p15, 0, r0, c7, c10, 4          @ drain WB
272         mov     pc, lr
275  *      dma_inv_range(start, end)
277  *      Invalidate (discard) the specified virtual address range.
278  *      May not write back any entries.  If 'start' or 'end'
279  *      are not cache line aligned, those lines must be written
280  *      back.
282  *      - start - virtual start address
283  *      - end   - virtual end address
285  * (same as v4wb)
286  */
287 ENTRY(arm925_dma_inv_range)
288 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
289         tst     r0, #CACHE_DLINESIZE - 1
290         mcrne   p15, 0, r0, c7, c10, 1          @ clean D entry
291         tst     r1, #CACHE_DLINESIZE - 1
292         mcrne   p15, 0, r1, c7, c10, 1          @ clean D entry
293 #endif
294         bic     r0, r0, #CACHE_DLINESIZE - 1
295 1:      mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
296         add     r0, r0, #CACHE_DLINESIZE
297         cmp     r0, r1
298         blo     1b
299         mcr     p15, 0, r0, c7, c10, 4          @ drain WB
300         mov     pc, lr
303  *      dma_clean_range(start, end)
305  *      Clean the specified virtual address range.
307  *      - start - virtual start address
308  *      - end   - virtual end address
310  * (same as v4wb)
311  */
312 ENTRY(arm925_dma_clean_range)
313 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
314         bic     r0, r0, #CACHE_DLINESIZE - 1
315 1:      mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
316         add     r0, r0, #CACHE_DLINESIZE
317         cmp     r0, r1
318         blo     1b
319 #endif
320         mcr     p15, 0, r0, c7, c10, 4          @ drain WB
321         mov     pc, lr
324  *      dma_flush_range(start, end)
326  *      Clean and invalidate the specified virtual address range.
328  *      - start - virtual start address
329  *      - end   - virtual end address
330  */
331 ENTRY(arm925_dma_flush_range)
332         bic     r0, r0, #CACHE_DLINESIZE - 1
334 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
335         mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
336 #else
337         mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
338 #endif
339         add     r0, r0, #CACHE_DLINESIZE
340         cmp     r0, r1
341         blo     1b
342         mcr     p15, 0, r0, c7, c10, 4          @ drain WB
343         mov     pc, lr
345 ENTRY(arm925_cache_fns)
346         .long   arm925_flush_kern_cache_all
347         .long   arm925_flush_user_cache_all
348         .long   arm925_flush_user_cache_range
349         .long   arm925_coherent_kern_range
350         .long   arm925_coherent_user_range
351         .long   arm925_flush_kern_dcache_page
352         .long   arm925_dma_inv_range
353         .long   arm925_dma_clean_range
354         .long   arm925_dma_flush_range
356 ENTRY(cpu_arm925_dcache_clean_area)
357 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
358 1:      mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
359         add     r0, r0, #CACHE_DLINESIZE
360         subs    r1, r1, #CACHE_DLINESIZE
361         bhi     1b
362 #endif
363         mcr     p15, 0, r0, c7, c10, 4          @ drain WB
364         mov     pc, lr
366 /* =============================== PageTable ============================== */
369  * cpu_arm925_switch_mm(pgd)
371  * Set the translation base pointer to be as described by pgd.
373  * pgd: new page tables
374  */
375         .align  5
376 ENTRY(cpu_arm925_switch_mm)
377 #ifdef CONFIG_MMU
378         mov     ip, #0
379 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
380         mcr     p15, 0, ip, c7, c6, 0           @ invalidate D cache
381 #else
382         /* Flush entries in bothe segments at once, see NOTE1 above */
383         mov     r3, #(CACHE_DENTRIES - 1) << 4  @ 256 entries in segment
384 2:      mcr     p15, 0, r3, c7, c14, 2          @ clean & invalidate D index
385         subs    r3, r3, #1 << 4
386         bcs     2b                              @ entries 255 to 0
387 #endif
388         mcr     p15, 0, ip, c7, c5, 0           @ invalidate I cache
389         mcr     p15, 0, ip, c7, c10, 4          @ drain WB
390         mcr     p15, 0, r0, c2, c0, 0           @ load page table pointer
391         mcr     p15, 0, ip, c8, c7, 0           @ invalidate I & D TLBs
392 #endif
393         mov     pc, lr
395 #ifdef CONFIG_MMU
397  * cpu_arm925_set_pte(ptep, pte)
399  * Set a PTE and flush it out
400  */
401         .align  5
402 ENTRY(cpu_arm925_set_pte)
403 #ifdef CONFIG_MMU
404         str     r1, [r0], #-2048                @ linux version
406         eor     r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
408         bic     r2, r1, #PTE_SMALL_AP_MASK
409         bic     r2, r2, #PTE_TYPE_MASK
410         orr     r2, r2, #PTE_TYPE_SMALL
412         tst     r1, #L_PTE_USER                 @ User?
413         orrne   r2, r2, #PTE_SMALL_AP_URO_SRW
415         tst     r1, #L_PTE_WRITE | L_PTE_DIRTY  @ Write and Dirty?
416         orreq   r2, r2, #PTE_SMALL_AP_UNO_SRW
418         tst     r1, #L_PTE_PRESENT | L_PTE_YOUNG        @ Present and Young?
419         movne   r2, #0
421 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
422         eor     r3, r2, #0x0a                   @ C & small page?
423         tst     r3, #0x0b
424         biceq   r2, r2, #4
425 #endif
426         str     r2, [r0]                        @ hardware version
427         mov     r0, r0
428 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
429         mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
430 #endif
431         mcr     p15, 0, r0, c7, c10, 4          @ drain WB
432 #endif /* CONFIG_MMU */
433         mov     pc, lr
434 #endif /* CONFIG_MMU */
435         __INIT
437         .type   __arm925_setup, #function
438 __arm925_setup:
439         mov     r0, #0
440 #if defined(CONFIG_CPU_ICACHE_STREAMING_DISABLE)
441         orr     r0,r0,#1 << 7
442 #endif
444         /* Transparent on, D-cache clean & flush mode. See  NOTE2 above */
445         orr     r0,r0,#1 << 1                   @ transparent mode on
446         mcr     p15, 0, r0, c15, c1, 0          @ write TI config register
448         mov     r0, #0
449         mcr     p15, 0, r0, c7, c7              @ invalidate I,D caches on v4
450         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer on v4
451 #ifdef CONFIG_MMU
452         mcr     p15, 0, r0, c8, c7              @ invalidate I,D TLBs on v4
453 #endif
455 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
456         mov     r0, #4                          @ disable write-back on caches explicitly
457         mcr     p15, 7, r0, c15, c0, 0
458 #endif
460         adr     r5, arm925_crval
461         ldmia   r5, {r5, r6}
462         mrc     p15, 0, r0, c1, c0              @ get control register v4
463         bic     r0, r0, r5
464         orr     r0, r0, r6
465 #ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
466         orr     r0, r0, #0x4000                 @ .1.. .... .... ....
467 #endif
468         mov     pc, lr
469         .size   __arm925_setup, . - __arm925_setup
471         /*
472          *  R
473          * .RVI ZFRS BLDP WCAM
474          * .011 0001 ..11 1101
475          * 
476          */
477         .type   arm925_crval, #object
478 arm925_crval:
479         crval   clear=0x00007f3f, mmuset=0x0000313d, ucset=0x00001130
481         __INITDATA
484  * Purpose : Function pointers used to access above functions - all calls
485  *           come through these
486  */
487         .type   arm925_processor_functions, #object
488 arm925_processor_functions:
489         .word   v4t_early_abort
490         .word   cpu_arm925_proc_init
491         .word   cpu_arm925_proc_fin
492         .word   cpu_arm925_reset
493         .word   cpu_arm925_do_idle
494         .word   cpu_arm925_dcache_clean_area
495         .word   cpu_arm925_switch_mm
496 #ifdef CONFIG_MMU
497         .word   cpu_arm925_set_pte
498 #endif
499         .size   arm925_processor_functions, . - arm925_processor_functions
501         .section ".rodata"
503         .type   cpu_arch_name, #object
504 cpu_arch_name:
505         .asciz  "armv4t"
506         .size   cpu_arch_name, . - cpu_arch_name
508         .type   cpu_elf_name, #object
509 cpu_elf_name:
510         .asciz  "v4"
511         .size   cpu_elf_name, . - cpu_elf_name
513         .type   cpu_arm925_name, #object
514 cpu_arm925_name:
515         .asciz  "ARM925T"
516         .size   cpu_arm925_name, . - cpu_arm925_name
518         .align
520         .section ".proc.info.init", #alloc, #execinstr
522         .type   __arm925_proc_info,#object
523 __arm925_proc_info:
524         .long   0x54029250
525         .long   0xfffffff0
526         .long   PMD_TYPE_SECT | \
527                 PMD_BIT4 | \
528                 PMD_SECT_AP_WRITE | \
529                 PMD_SECT_AP_READ
530         .long   PMD_TYPE_SECT | \
531                 PMD_BIT4 | \
532                 PMD_SECT_AP_WRITE | \
533                 PMD_SECT_AP_READ
534         b       __arm925_setup
535         .long   cpu_arch_name
536         .long   cpu_elf_name
537         .long   HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
538         .long   cpu_arm925_name
539         .long   arm925_processor_functions
540         .long   v4wbi_tlb_fns
541         .long   v4wb_user_fns
542         .long   arm925_cache_fns
543         .size   __arm925_proc_info, . - __arm925_proc_info
545         .type   __arm915_proc_info,#object
546 __arm915_proc_info:
547         .long   0x54029150
548         .long   0xfffffff0
549         .long   PMD_TYPE_SECT | \
550                 PMD_BIT4 | \
551                 PMD_SECT_AP_WRITE | \
552                 PMD_SECT_AP_READ
553         .long   PMD_TYPE_SECT | \
554                 PMD_BIT4 | \
555                 PMD_SECT_AP_WRITE | \
556                 PMD_SECT_AP_READ
557         b       __arm925_setup
558         .long   cpu_arch_name
559         .long   cpu_elf_name
560         .long   HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
561         .long   cpu_arm925_name
562         .long   arm925_processor_functions
563         .long   v4wbi_tlb_fns
564         .long   v4wb_user_fns
565         .long   arm925_cache_fns
566         .size   __arm925_proc_info, . - __arm925_proc_info