2 * linux/arch/arm/mm/proc-sa110.S: MMU functions for SA110
4 * (C) 1997-2000 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, ip, c7, c10, 4 @ drain WB
230 mcr p15, 0, ip, 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)
426 orr r0, r0, #F_BIT | I_BIT
428 bl cpu_sa110_flush_cache_all @ clean caches
430 mcr p15, 0, r0, c15, c2, 2 @ Disable clock switching
431 mrc p15, 0, r0, c1, c0, 0
432 bic r0, r0, #0x1000 @ ...i............
433 bic r0, r0, #0x000e @ ............wca.
434 mcr p15, 0, r0, c1, c0, 0 @ disable caches
438 idle: mcr p15, 0, r0, c15, c8, 2 @ Wait for interrupt
442 * Function: *_do_idle
443 * Params : r0 = call type:
446 * 2 = switch to slow processor clock
447 * 3 = switch to fast processor clock
449 ENTRY(cpu_sa110_do_idle)
450 ENTRY(cpu_sa1100_do_idle)
453 addcc pc, pc, r0, lsl #2
461 fast_clock: mcr p15, 0, ip, c15, c1, 2 @ enable clock switching
464 slow_clock: mcr p15, 0, ip, c15, c2, 2 @ disable clock switching
465 ldr r1, =UNCACHEABLE_ADDR @ load from uncacheable loc
466 ldr r1, [r1, #0] @ force switch to MCLK
470 * Function: sa110_reset
471 * Params : r0 = address to jump to
472 * Notes : This sets up everything for a reset
475 ENTRY(cpu_sa110_reset)
476 ENTRY(cpu_sa1100_reset)
478 mcr p15, 0, ip, c7, c7, 0 @ flush I,D caches
479 mcr p15, 0, ip, c7, c10, 4 @ drain WB
480 mcr p15, 0, ip, c8, c7, 0 @ flush I & D tlbs
481 mrc p15, 0, ip, c1, c0, 0 @ ctrl register
482 bic ip, ip, #0x000f @ ............wcam
483 bic ip, ip, #0x1100 @ ...i...s........
484 mcr p15, 0, ip, c1, c0, 0 @ ctrl register
487 * Purpose : Function pointers used to access above functions - all calls
491 cpu_manu_name: .asciz "Intel"
492 ENTRY(cpu_sa110_name)
493 .asciz "StrongARM-110"
494 ENTRY(cpu_sa1100_name)
495 .asciz "StrongARM-1100"
498 .section ".text.init", #alloc, #execinstr
500 __sa110_setup: mov r0, #0
501 mcr p15, 0, r0, c7, c7 @ flush I,D caches on v4
502 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4
503 mcr p15, 0, r0, c8, c7 @ flush I,D TLBs on v4
504 mcr p15, 0, r4, c2, c0 @ load page table pointer
505 mov r0, #0x1f @ Domains 0, 1 = client
506 mcr p15, 0, r0, c3, c0 @ load domain access register
507 mrc p15, 0, r0, c1, c0 @ get control register v4
508 bic r0, r0, #0x0e00 @ ....??r.........
509 bic r0, r0, #0x0002 @ ..............a.
510 orr r0, r0, #0x003d @ ..........DPWC.M
511 orr r0, r0, #0x1100 @ ...I...S........
514 .type sa110_processor_functions, #object
515 ENTRY(sa110_processor_functions)
516 .word cpu_sa110_data_abort
517 .word cpu_sa110_check_bugs
518 .word cpu_sa110_proc_init
519 .word cpu_sa110_proc_fin
520 .word cpu_sa110_flush_cache_all
521 .word cpu_sa110_flush_cache_area
522 .word cpu_sa110_flush_cache_entry
523 .word cpu_sa110_clean_cache_area
524 .word cpu_sa110_flush_ram_page
525 .word cpu_sa110_flush_tlb_all
526 .word cpu_sa110_flush_tlb_area
527 .word cpu_sa110_set_pgd
528 .word cpu_sa110_set_pmd
529 .word cpu_sa110_set_pte
530 .word cpu_sa110_reset
531 .word cpu_sa110_flush_icache_area
532 .word cpu_sa110_cache_wback_area
533 .word cpu_sa110_cache_purge_area
534 .word cpu_sa110_flush_tlb_page
535 .word cpu_sa110_do_idle
536 .word cpu_sa110_flush_icache_page
537 .size sa110_processor_functions, . - sa110_processor_functions
539 .type cpu_sa110_info, #object
543 .size cpu_sa110_info, . - cpu_sa110_info
546 .type sa1100_processor_functions, #object
547 ENTRY(sa1100_processor_functions)
548 .word cpu_sa1100_data_abort
549 .word cpu_sa1100_check_bugs
550 .word cpu_sa1100_proc_init
551 .word cpu_sa1100_proc_fin
552 .word cpu_sa1100_flush_cache_all
553 .word cpu_sa1100_flush_cache_area
554 .word cpu_sa1100_flush_cache_entry
555 .word cpu_sa1100_clean_cache_area
556 .word cpu_sa1100_flush_ram_page
557 .word cpu_sa1100_flush_tlb_all
558 .word cpu_sa1100_flush_tlb_area
559 .word cpu_sa1100_set_pgd
560 .word cpu_sa1100_set_pmd
561 .word cpu_sa1100_set_pte
562 .word cpu_sa1100_reset
563 .word cpu_sa1100_flush_icache_area
564 .word cpu_sa1100_cache_wback_area
565 .word cpu_sa1100_cache_purge_area
566 .word cpu_sa1100_flush_tlb_page
567 .word cpu_sa1100_do_idle
568 .word cpu_sa1100_flush_icache_page
569 .size sa1100_processor_functions, . - sa1100_processor_functions
573 .long cpu_sa1100_name
574 .size cpu_sa1100_info, . - cpu_sa1100_info
576 .type cpu_arch_name, #object
577 cpu_arch_name: .asciz "armv4"
578 .size cpu_arch_name, . - cpu_arch_name
580 .type cpu_elf_name, #object
581 cpu_elf_name: .asciz "v4"
582 .size cpu_elf_name, . - cpu_elf_name
585 .section ".proc.info", #alloc, #execinstr
587 .type __sa110_proc_info,#object
595 .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT
597 .long sa110_processor_functions
598 .size __sa110_proc_info, . - __sa110_proc_info
600 .type __sa1100_proc_info,#object
608 .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT
609 .long cpu_sa1100_info
610 .long sa1100_processor_functions
611 .size __sa1100_proc_info, . - __sa1100_proc_info