2 * linux/arch/arm/mm/proc-sa110.S: MMU functions for SA110
4 * (C) 1997-1999 Russell King
6 * These are the low level assembler for performing cache and TLB
7 * functions on the StrongARM-110 and StrongARM-1100
9 #include <linux/linkage.h>
10 #include <asm/assembler.h>
11 #include <asm/procinfo.h>
12 #include <asm/hardware.h>
13 #include "../lib/constants.h"
15 /* This is the maximum size of an area which will be flushed. If the area
16 * is larger than this, then we flush the whole cache
18 #define MAX_AREA_SIZE 32768
19 #define FLUSH_OFFSET 32768
21 .macro flush_110_dcache rd, ra, re
22 add \re, \ra, #16384 @ only necessary for 16k
23 1001: ldr \rd, [\ra], #32
28 .macro flush_1100_dcache rd, ra, re
29 add \re, \ra, #8192 @ only necessary for 8k
30 1001: ldr \rd, [\ra], #32
33 #ifdef FLUSH_BASE_MINICACHE
34 add \ra, \ra, #FLUSH_BASE_MINICACHE - FLUSH_BASE
35 add \re, \ra, #512 @ only 512 bytes
36 1002: ldr \rd, [\ra], #32
43 Lclean_switch: .long 0
47 * Function: sa110_flush_cache_all (void)
48 * Purpose : Flush all cache lines
51 ENTRY(cpu_sa110_flush_cache_all) @ preserves r0
53 cpu_sa110_flush_cache_all_r2:
54 ldr r3, =Lclean_switch
60 addne ip, ip, #FLUSH_OFFSET
61 flush_110_dcache r3, ip, r1
64 mcrne p15, 0, ip, c7, c5, 0 @ flush I cache
65 mcr p15, 0, ip, c7, c10, 4 @ drain WB
69 ENTRY(cpu_sa1100_flush_cache_all) @ preserves r0
71 cpu_sa1100_flush_cache_all_r2:
72 ldr r3, =Lclean_switch
78 addne ip, ip, #FLUSH_OFFSET
79 flush_1100_dcache r3, ip, r1
82 mcrne p15, 0, ip, c7, c5, 0 @ flush I cache
83 mcr p15, 0, ip, c7, c10, 4 @ drain WB
87 * Function: sa110_flush_cache_area (unsigned long address, int end, int flags)
88 * Params : address Area start address
89 * : end Area end address
90 * : flags b0 = I cache as well
91 * Purpose : clean & flush all cache lines associated with this area of memory
94 ENTRY(cpu_sa110_flush_cache_area)
96 cmp r3, #MAX_AREA_SIZE
97 bgt cpu_sa110_flush_cache_all_r2
98 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
99 mcr p15, 0, r0, c7, c6, 1 @ flush D entry
101 mcr p15, 0, r0, c7, c10, 1 @ clean D entry
102 mcr p15, 0, r0, c7, c6, 1 @ flush D entry
108 mcrne p15, 0, r0, c7, c5, 0 @ flush I cache
111 ENTRY(cpu_sa1100_flush_cache_area)
113 cmp r3, #MAX_AREA_SIZE
114 bgt cpu_sa1100_flush_cache_all_r2
118 * Function: sa110_cache_wback_area(unsigned long address, unsigned long end)
119 * Params : address Area start address
120 * : end Area end address
121 * Purpose : ensure all dirty cachelines in the specified area have been
122 * written out to memory (for DMA)
125 ENTRY(cpu_sa110_cache_wback_area)
127 cmp r3, #MAX_AREA_SIZE
129 bgt cpu_sa110_flush_cache_all_r2
131 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
133 mcr p15, 0, r0, c7, c10, 1 @ clean D entry
137 mcr p15, 0, r2, c7, c10, 4 @ drain WB
140 ENTRY(cpu_sa1100_cache_wback_area)
142 cmp r3, #MAX_AREA_SIZE
144 bgt cpu_sa1100_flush_cache_all_r2
148 * Function: sa110_cache_purge_area(unsigned long address, unsigned long end)
149 * Params : address Area start address
150 * : end Area end address
151 * Purpose : throw away all D-cached data in specified region without
152 * an obligation to write it back.
153 * Note : Must clean the D-cached entries around the boundaries if the
154 * start and/or end address are not cache aligned.
157 ENTRY(cpu_sa110_cache_purge_area)
158 ENTRY(cpu_sa1100_cache_purge_area)
161 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
163 mcrne p15, 0, r1, c7, c10, 1 @ clean D entry
164 1: mcr p15, 0, r0, c7, c6, 1 @ flush D entry
171 * Function: sa110_flush_cache_entry (unsigned long address)
172 * Params : address Address of cache line to flush
173 * Purpose : clean & flush an entry
176 ENTRY(cpu_sa110_flush_cache_entry)
177 ENTRY(cpu_sa1100_flush_cache_entry)
179 mcr p15, 0, r0, c7, c10, 1 @ clean D entry
180 mcr p15, 0, r1, c7, c10, 4 @ drain WB
181 mcr p15, 0, r1, c7, c5, 0 @ flush I cache
185 * Function: sa110_clean_cache_area(unsigned long start, unsigned long size)
186 * Params : address Address of cache line to clean
187 * Purpose : Ensure that physical memory reflects cache at this location
188 * for page table purposes.
190 ENTRY(cpu_sa110_clean_cache_area)
191 ENTRY(cpu_sa1100_clean_cache_area)
192 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns)
199 * Function: sa110_flush_ram_page (unsigned long page)
200 * Params : page Area start address
201 * Purpose : clean all cache lines associated with this area of memory
204 ENTRY(cpu_sa110_flush_ram_page)
205 ENTRY(cpu_sa1100_flush_ram_page)
207 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
209 mcr p15, 0, r0, c7, c10, 1 @ clean D entry
211 mcr p15, 0, r0, c7, c10, 1 @ clean D entry
213 mcr p15, 0, r0, c7, c10, 1 @ clean D entry
218 mcr p15, 0, r0, c7, c10, 4 @ drain WB
222 * Function: sa110_flush_tlb_all (void)
223 * Purpose : flush all TLB entries in all caches
226 ENTRY(cpu_sa110_flush_tlb_all)
227 ENTRY(cpu_sa1100_flush_tlb_all)
229 mcr p15, 0, r0, c7, c10, 4 @ drain WB
230 mcr p15, 0, r0, c8, c7, 0 @ flush I & D tlbs
234 * Function: sa110_flush_tlb_area (unsigned long address, unsigned long end, int flags)
235 * Params : address Area start address
236 * : end Area end address
237 * : flags b0 = I-TLB as well
238 * Purpose : flush a TLB entry
241 ENTRY(cpu_sa110_flush_tlb_area)
242 ENTRY(cpu_sa1100_flush_tlb_area)
244 mcr p15, 0, r3, c7, c10, 4 @ drain WB
246 mcrlt p15, 0, r0, c8, c6, 1 @ flush D TLB entry
249 mcrlt p15, 0, r0, c8, c6, 1 @ flush D TLB entry
253 mcrne p15, 0, r3, c8, c5, 0 @ flush I TLB
257 * Function: sa110_flush_tlb_page (unsigned long address, int flags)
258 * Params : address Address to flush
259 * : flags b0 = I-TLB as well
260 * Purpose : flush a TLB entry
263 ENTRY(cpu_sa110_flush_tlb_page)
264 ENTRY(cpu_sa1100_flush_tlb_page)
266 mcr p15, 0, r3, c7, c10, 4 @ drain WB
267 mcr p15, 0, r0, c8, c6, 1 @ flush D TLB entry
269 mcrne p15, 0, r3, c8, c5, 0 @ flush I TLB
273 * Function: sa110_flush_icache_area (unsigned long address, unsigned long size)
274 * Params : address Address of area to flush
275 * : size Size of area to flush
276 * Purpose : flush an area from the Icache
279 ENTRY(cpu_sa110_flush_icache_area)
280 ENTRY(cpu_sa1100_flush_icache_area)
281 1: mcr p15, 0, r0, c7, c10, 1 @ Clean D entry
286 mcr p15, 0, r0, c7, c10, 4 @ drain WB
287 mcr p15, 0, r0, c7, c5, 0 @ flush I cache
291 ENTRY(cpu_sa110_flush_icache_page)
292 ENTRY(cpu_sa1100_flush_icache_page)
293 mcr p15, 0, r0, c7, c5, 0 @ flush I cache
297 * Function: sa110_data_abort ()
298 * Params : r0 = address of aborted instruction
299 * Purpose : obtain information about current aborted instruction
300 * Returns : r0 = address of abort
302 * : r2 != 0 if writing
305 ENTRY(cpu_sa110_data_abort)
306 ENTRY(cpu_sa1100_data_abort)
307 ldr r2, [r0] @ read instruction causing problem
308 mrc p15, 0, r0, c6, c0, 0 @ get FAR
309 mov r2, r2, lsr #19 @ b1 = L
310 and r3, r2, #0x69 << 2
312 mrc p15, 0, r1, c5, c0, 0 @ get FSR
318 * Function: sa110_set_pgd(unsigned long pgd_phys)
319 * Params : pgd_phys Physical address of page table
320 * Purpose : Perform a task switch, saving the old processes state, and restoring
324 ENTRY(cpu_sa110_set_pgd)
325 ldr r3, =Lclean_switch
331 addne ip, ip, #FLUSH_OFFSET
332 flush_110_dcache r3, ip, r1
334 mcr p15, 0, r1, c7, c5, 0 @ flush I cache
335 mcr p15, 0, r1, c7, c10, 4 @ drain WB
336 mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
337 mcr p15, 0, r1, c8, c7, 0 @ flush TLBs
341 ENTRY(cpu_sa1100_set_pgd)
342 ldr r3, =Lclean_switch
348 addne ip, ip, #FLUSH_OFFSET
349 flush_1100_dcache r3, ip, r1
351 mcr p15, 0, r1, c7, c5, 0 @ flush I cache
352 mcr p15, 0, r1, c7, c10, 4 @ drain WB
353 mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
354 mcr p15, 0, r1, c8, c7, 0 @ flush TLBs
358 * Function: sa110_set_pmd(pmd_t *pmdp, pmd_t pmd)
359 * Params : r0 = Address to set
360 * : r1 = value to set
361 * Purpose : Set a PMD and flush it out
364 ENTRY(cpu_sa110_set_pmd)
365 ENTRY(cpu_sa1100_set_pmd)
367 mcr p15, 0, r0, c7, c10, 1 @ clean D entry
368 mcr p15, 0, r0, c7, c10, 4 @ drain WB
372 * Function: sa110_set_pte(pte_t *ptep, pte_t pte)
373 * Params : r0 = Address to set
374 * : r1 = value to set
375 * Purpose : Set a PTE and flush it out
378 ENTRY(cpu_sa110_set_pte)
379 ENTRY(cpu_sa1100_set_pte)
380 str r1, [r0], #-1024 @ linux version
382 eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
386 orr r2, r2, #HPTE_TYPE_SMALL
388 tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
389 orrne r2, r2, #HPTE_AP_READ
391 tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
392 orreq r2, r2, #HPTE_AP_WRITE
394 tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young?
397 str r2, [r0] @ hardware version
399 mcr p15, 0, r0, c7, c10, 1 @ clean D entry
400 mcr p15, 0, r0, c7, c10, 4 @ drain WB
404 * Function: sa110_check_bugs (void)
405 * : sa110_proc_init (void)
406 * : sa110_proc_fin (void)
407 * Notes : This processor does not require these
409 ENTRY(cpu_sa110_check_bugs)
410 ENTRY(cpu_sa1100_check_bugs)
416 ENTRY(cpu_sa110_proc_init)
417 ENTRY(cpu_sa1100_proc_init)
419 mcr p15, 0, r0, c15, c1, 2 @ Enable clock switching
422 ENTRY(cpu_sa110_proc_fin)
423 ENTRY(cpu_sa1100_proc_fin)
425 orr r0, r0, #F_BIT | I_BIT
428 mcr p15, 0, r0, c15, c2, 2 @ Disable clock switching
429 mrc p15, 0, r0, c1, c0, 0
430 bic r0, r0, #0x1100 @ ...i...s........
431 bic r0, r0, #0x000e @ ............wca.
432 mcr p15, 0, r0, c1, c0, 0 @ disable caches
436 ENTRY(cpu_sa110_do_idle)
437 ENTRY(cpu_sa1100_do_idle)
439 mcr p15, 0, r0, c15, c2, 2 @ Disable clock switching
440 ldr r1, =FLUSH_BASE+FLUSH_OFFSET*2 @ load from uncacheable loc
445 1: mcr p15, 0, r0, c15, c8, 2 @ Wait for interrupt
446 mcr p15, 0, r0, c15, c1, 2 @ Enable clock switching
450 * Function: sa110_reset
451 * Notes : This sets up everything for a reset
453 ENTRY(cpu_sa110_reset)
454 ENTRY(cpu_sa1100_reset)
456 bl cpu_sa110_flush_cache_all
457 bl cpu_sa110_flush_tlb_all
458 mcr p15, 0, ip, c7, c7, 0 @ flush I,D caches
459 mrc p15, 0, r0, c1, c0, 0 @ ctrl register
460 bic r0, r0, #0x000f @ ............wcam
461 bic r0, r0, #0x1100 @ ...i...s........
464 * Purpose : Function pointers used to access above functions - all calls
468 cpu_manu_name: .asciz "Intel"
469 ENTRY(cpu_sa110_name)
470 .asciz "StrongARM-110"
471 ENTRY(cpu_sa1100_name)
472 .asciz "StrongARM-1100"
475 .section ".text.init", #alloc, #execinstr
477 __sa110_setup: mov r0, #0
478 mcr p15, 0, r0, c7, c7 @ flush I,D caches on v4
479 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4
480 mcr p15, 0, r0, c8, c7 @ flush I,D TLBs on v4
481 mcr p15, 0, r4, c2, c0 @ load page table pointer
482 mov r0, #0x1f @ Domains 0, 1 = client
483 mcr p15, 0, r0, c3, c0 @ load domain access register
484 mrc p15, 0, r0, c1, c0 @ get control register v4
485 bic r0, r0, #0x0e00 @ ....??r.........
486 bic r0, r0, #0x0002 @ ..............a.
487 orr r0, r0, #0x003d @ ..........DPWC.M
488 orr r0, r0, #0x1100 @ ...I...S........
491 .type sa110_processor_functions, #object
492 ENTRY(sa110_processor_functions)
493 .word cpu_sa110_data_abort
494 .word cpu_sa110_check_bugs
495 .word cpu_sa110_proc_init
496 .word cpu_sa110_proc_fin
497 .word cpu_sa110_flush_cache_all
498 .word cpu_sa110_flush_cache_area
499 .word cpu_sa110_flush_cache_entry
500 .word cpu_sa110_clean_cache_area
501 .word cpu_sa110_flush_ram_page
502 .word cpu_sa110_flush_tlb_all
503 .word cpu_sa110_flush_tlb_area
504 .word cpu_sa110_set_pgd
505 .word cpu_sa110_set_pmd
506 .word cpu_sa110_set_pte
507 .word cpu_sa110_reset
508 .word cpu_sa110_flush_icache_area
509 .word cpu_sa110_cache_wback_area
510 .word cpu_sa110_cache_purge_area
511 .word cpu_sa110_flush_tlb_page
512 .word cpu_sa110_do_idle
513 .word cpu_sa110_flush_icache_page
514 .size sa110_processor_functions, . - sa110_processor_functions
516 .type cpu_sa110_info, #object
520 .size cpu_sa110_info, . - cpu_sa110_info
523 .type sa1100_processor_functions, #object
524 ENTRY(sa1100_processor_functions)
525 .word cpu_sa1100_data_abort
526 .word cpu_sa1100_check_bugs
527 .word cpu_sa1100_proc_init
528 .word cpu_sa1100_proc_fin
529 .word cpu_sa1100_flush_cache_all
530 .word cpu_sa1100_flush_cache_area
531 .word cpu_sa1100_flush_cache_entry
532 .word cpu_sa1100_clean_cache_area
533 .word cpu_sa1100_flush_ram_page
534 .word cpu_sa1100_flush_tlb_all
535 .word cpu_sa1100_flush_tlb_area
536 .word cpu_sa1100_set_pgd
537 .word cpu_sa1100_set_pmd
538 .word cpu_sa1100_set_pte
539 .word cpu_sa1100_reset
540 .word cpu_sa1100_flush_icache_area
541 .word cpu_sa1100_cache_wback_area
542 .word cpu_sa1100_cache_purge_area
543 .word cpu_sa1100_flush_tlb_page
544 .word cpu_sa1100_do_idle
545 .word cpu_sa1100_flush_icache_page
546 .size sa1100_processor_functions, . - sa1100_processor_functions
550 .long cpu_sa1100_name
551 .size cpu_sa1100_info, . - cpu_sa1100_info
553 .type cpu_arch_name, #object
554 cpu_arch_name: .asciz "armv4"
555 .size cpu_arch_name, . - cpu_arch_name
557 .type cpu_elf_name, #object
558 cpu_elf_name: .asciz "v4"
559 .size cpu_elf_name, . - cpu_elf_name
562 .section ".proc.info", #alloc, #execinstr
564 .type __sa110_proc_info,#object
572 .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT
574 .long sa110_processor_functions
575 .size __sa110_proc_info, . - __sa110_proc_info
577 .type __sa1100_proc_info,#object
585 .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT
586 .long cpu_sa1100_info
587 .long sa1100_processor_functions
588 .size __sa1100_proc_info, . - __sa1100_proc_info