v2.4.8 -> v2.4.8.1
[opensuse:kernel.git] / arch / arm / mm / proc-arm720.S
1 /*
2  *  linux/arch/arm/mm/proc-arm720.S: MMU functions for ARM720
3  *
4  *  Copyright (C) 2000 Steve Hill (sjhill@cotw.com)
5  *                     Rob Scott (rscott@mtrob.fdns.net)
6  *  Copyright (C) 2000 ARM Limited, Deep Blue Solutions Ltd.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  *
23  * These are the low level assembler for performing cache and TLB
24  * functions on the ARM720T.  The ARM720T has a writethrough IDC
25  * cache, so we don't need to clean it.
26  *
27  *  Changelog:
28  *   05-09-2000 SJH     Created by moving 720 specific functions
29  *                      out of 'proc-arm6,7.S' per RMK discussion
30  *   07-25-2000 SJH     Added idle function.
31  *   08-25-2000 DBS     Updated for integration of ARM Ltd version.
32  */
33 #include <linux/linkage.h>
34 #include <asm/assembler.h>
35 #include <asm/constants.h>
36 #include <asm/procinfo.h>
37 #include <asm/hardware.h>
38
39 /*
40  * Function: arm720_cache_clean_invalidate_all (void)
41  *         : arm720_cache_clean_invalidate_page (unsigned long address, int size,
42  *                                    int flags)
43  *
44  * Params  : address    Area start address
45  *         : size       size of area
46  *         : flags      b0 = I cache as well
47  *
48  * Purpose : Flush all cache lines
49  */
50 ENTRY(cpu_arm720_cache_clean_invalidate_all)
51 ENTRY(cpu_arm720_cache_clean_invalidate_range)
52 ENTRY(cpu_arm720_icache_invalidate_range)
53 ENTRY(cpu_arm720_icache_invalidate_page)
54 ENTRY(cpu_arm720_dcache_invalidate_range)
55                 mov     r0, #0
56                 mcr     p15, 0, r0, c7, c7, 0           @ flush cache
57                 mov     pc, lr
58
59 /*
60  * These just expect cache lines to be cleaned.  Since we have a writethrough
61  * cache, we never have any dirty cachelines to worry about.
62  */
63 ENTRY(cpu_arm720_dcache_clean_range)
64 ENTRY(cpu_arm720_dcache_clean_page)
65 ENTRY(cpu_arm720_dcache_clean_entry)
66 ENTRY(cpu_arm720_flush_ram_page)
67                 mov     pc, lr
68
69 /*
70  * Function: arm720_tlb_invalidate_all (void)
71  *
72  * Purpose : flush all TLB entries in all caches
73  */
74 ENTRY(cpu_arm720_tlb_invalidate_all)
75                 mov     r0, #0
76                 mcr     p15, 0, r0, c8, c7, 0           @ flush TLB (v4)
77                 mov     pc, lr
78
79 /*
80  * Function: arm720_tlb_invalidate_page (unsigned long address, int end, int flags)
81  *
82  * Params  : address    Area start address
83  *         : end        Area end address
84  *         : flags      b0 = I cache as well
85  *
86  * Purpose : flush a TLB entry
87  */
88 ENTRY(cpu_arm720_tlb_invalidate_range)
89 1:              mcr     p15, 0, r0, c8, c7, 1           @ flush TLB (v4)
90                 add     r0, r0, #4096
91                 cmp     r0, r1
92                 blt     1b
93                 mov     pc, lr
94
95 /*
96  * Function: arm720_tlb_invalidate_page (unsigned long address, int flags)
97  *
98  * Params  : address    Address
99  *         : flags      b0 = I-TLB as well
100  *
101  * Purpose : flush a TLB entry
102  */
103 ENTRY(cpu_arm720_tlb_invalidate_page)
104                 mcr     p15, 0, r0, c8, c7, 1           @ flush TLB (v4)
105                 mov     pc, lr
106
107 /*
108  * Function: arm720_data_abort ()
109  *
110  * Params  : r0 = address of aborted instruction
111  *
112  * Purpose : obtain information about current aborted instruction
113  *
114  * Returns : r0 = address of abort
115  *         : r1 != 0 if writing
116  *         : r3 = FSR
117  *         : sp = pointer to registers
118  */
119
120 Ldata_ldmstm:   tst     r4, #1 << 21                    @ check writeback bit
121                 beq     Ldata_simple
122                 mov     r7, #0x11
123                 orr     r7, r7, r7, lsl #8
124                 and     r0, r4, r7
125                 and     r2, r4, r7, lsl #1
126                 add     r0, r0, r2, lsr #1
127                 and     r2, r4, r7, lsl #2
128                 add     r0, r0, r2, lsr #2
129                 and     r2, r4, r7, lsl #3
130                 add     r0, r0, r2, lsr #3
131                 add     r0, r0, r0, lsr #8
132                 add     r0, r0, r0, lsr #4
133                 and     r7, r0, #15                     @ r7 = no. of registers to transfer.
134                 and     r5, r4, #15 << 16               @ Get Rn
135                 ldr     r0, [sp, r5, lsr #14]           @ Get register
136                 tst     r4, #1 << 23                    @ U bit
137                 subne   r7, r0, r7, lsl #2
138                 addeq   r7, r0, r7, lsl #2              @ Do correction (signed)
139 Ldata_saver7:   str     r7, [sp, r5, lsr #14]           @ Put register
140 Ldata_simple:   mrc     p15, 0, r0, c6, c0, 0           @ get FAR
141                 mrc     p15, 0, r3, c5, c0, 0           @ get FSR
142                 and     r3, r3, #255
143                 mov     pc, lr
144
145 ENTRY(cpu_arm720_data_abort)
146                 ldr     r4, [r0]                        @ read instruction causing problem
147                 tst     r4, r4, lsr #21                 @ C = bit 20
148                 sbc     r1, r1, r1                      @ r1 = C - 1
149                 and     r2, r4, #15 << 24
150                 add     pc, pc, r2, lsr #22             @ Now branch to the relevent processing routine
151                 movs    pc, lr
152
153                 b       Ldata_lateldrhpost              @ ldrh  rd, [rn], #m/rm
154                 b       Ldata_lateldrhpre               @ ldrh  rd, [rn, #m/rm]
155                 b       Ldata_unknown
156                 b       Ldata_unknown
157                 b       Ldata_lateldrpostconst          @ ldr   rd, [rn], #m
158                 b       Ldata_lateldrpreconst           @ ldr   rd, [rn, #m] 
159                 b       Ldata_lateldrpostreg            @ ldr   rd, [rn], rm
160                 b       Ldata_lateldrprereg             @ ldr   rd, [rn, rm]
161                 b       Ldata_ldmstm                    @ ldm*a rn, <rlist>
162                 b       Ldata_ldmstm                    @ ldm*b rn, <rlist>
163                 b       Ldata_unknown
164                 b       Ldata_unknown
165                 b       Ldata_simple                    @ ldc   rd, [rn], #m    @ Same as ldr   rd, [rn], #m
166                 b       Ldata_simple                    @ ldc   rd, [rn, #m]
167                 b       Ldata_unknown
168
169 Ldata_unknown:  @ Part of jumptable
170                 mov     r0, r2
171                 mov     r1, r4
172                 mov     r2, r3
173                 bl      baddataabort
174                 b       ret_from_exception
175
176 Ldata_lateldrhpre:
177                 tst     r4, #1 << 21                    @ check writeback bit
178                 beq     Ldata_simple
179 Ldata_lateldrhpost:
180                 and     r5, r4, #0x00f                  @ get Rm / low nibble of immediate value
181                 tst     r4, #1 << 22                    @ if (immediate offset)
182                 andne   r2, r4, #0xf00                  @ { immediate high nibble
183                 orrne   r2, r5, r2, lsr #4              @   combine nibbles } else
184                 ldreq   r2, [sp, r5, lsl #2]            @ { load Rm value }
185                 and     r5, r4, #15 << 16               @ get Rn
186                 ldr     r0, [sp, r5, lsr #14]           @ load Rn value
187                 tst     r4, #1 << 23                    @ U bit
188                 subne   r7, r0, r2
189                 addeq   r7, r0, r2
190                 b       Ldata_saver7
191
192 Ldata_lateldrpreconst:
193                 tst     r4, #1 << 21                    @ check writeback bit
194                 beq     Ldata_simple
195 Ldata_lateldrpostconst:
196                 movs    r2, r4, lsl #20                 @ Get offset
197                 beq     Ldata_simple
198                 and     r5, r4, #15 << 16               @ Get Rn
199                 ldr     r0, [sp, r5, lsr #14]
200                 tst     r4, #1 << 23                    @ U bit
201                 subne   r7, r0, r2, lsr #20
202                 addeq   r7, r0, r2, lsr #20
203                 b       Ldata_saver7
204
205 Ldata_lateldrprereg:
206                 tst     r4, #1 << 21                    @ check writeback bit
207                 beq     Ldata_simple
208 Ldata_lateldrpostreg:
209                 and     r5, r4, #15
210                 ldr     r2, [sp, r5, lsl #2]            @ Get Rm
211                 mov     r3, r4, lsr #7
212                 ands    r3, r3, #31
213                 and     r6, r4, #0x70
214                 orreq   r6, r6, #8
215                 add     pc, pc, r6
216                 mov     r0, r0
217
218                 mov     r2, r2, lsl r3                  @ 0: LSL #!0
219                 b       1f
220                 b       1f                              @ 1: LSL #0
221                 mov     r0, r0
222                 b       1f                              @ 2: MUL?
223                 mov     r0, r0
224                 b       1f                              @ 3: MUL?
225                 mov     r0, r0
226                 mov     r2, r2, lsr r3                  @ 4: LSR #!0
227                 b       1f
228                 mov     r2, r2, lsr #32                 @ 5: LSR #32
229                 b       1f
230                 b       1f                              @ 6: MUL?
231                 mov     r0, r0
232                 b       1f                              @ 7: MUL?
233                 mov     r0, r0
234                 mov     r2, r2, asr r3                  @ 8: ASR #!0
235                 b       1f
236                 mov     r2, r2, asr #32                 @ 9: ASR #32
237                 b       1f
238                 b       1f                              @ A: MUL?
239                 mov     r0, r0
240                 b       1f                              @ B: MUL?
241                 mov     r0, r0
242                 mov     r2, r2, ror r3                  @ C: ROR #!0
243                 b       1f
244                 mov     r2, r2, rrx                     @ D: RRX
245                 b       1f
246                 mov     r0, r0                          @ E: MUL?
247                 mov     r0, r0
248                 mov     r0, r0                          @ F: MUL?
249
250
251 1:              and     r5, r4, #15 << 16               @ Get Rn
252                 ldr     r0, [sp, r5, lsr #14]
253                 tst     r4, #1 << 23                    @ U bit
254                 subne   r7, r0, r2
255                 addeq   r7, r0, r2
256                 b       Ldata_saver7
257
258 /*
259  * Function: arm720_check_bugs (void)
260  *         : arm720_proc_init (void)
261  *         : arm720_proc_fin (void)
262  *
263  * Notes   : This processor does not require these
264  */
265 ENTRY(cpu_arm720_check_bugs)
266                 mrs     ip, cpsr
267                 bic     ip, ip, #F_BIT
268                 msr     cpsr, ip
269                 mov     pc, lr
270
271 ENTRY(cpu_arm720_proc_init)
272                 mov     pc, lr
273
274 ENTRY(cpu_arm720_proc_fin)
275                 stmfd   sp!, {lr}
276                 mov     ip, #F_BIT | I_BIT | SVC_MODE
277                 msr     cpsr_c, ip
278                 mrc     p15, 0, r0, c1, c0, 0
279                 bic     r0, r0, #0x1000                 @ ...i............
280                 bic     r0, r0, #0x000e                 @ ............wca.
281                 mcr     p15, 0, r0, c1, c0, 0           @ disable caches
282                 mcr     p15, 0, r1, c7, c7, 0           @ invalidate cache
283                 ldmfd   sp!, {pc}
284
285 /*
286  * Function: arm720_proc_do_idle(void)
287  * Params  : r0 = unused
288  * Purpose : put the processer in proper idle mode
289  */
290 ENTRY(cpu_arm720_do_idle)
291                 mov     pc, lr
292
293 /*
294  * Function: arm720_set_pgd(unsigned long pgd_phys)
295  * Params  : pgd_phys   Physical address of page table
296  * Purpose : Perform a task switch, saving the old process' state and restoring
297  *           the new.
298  */
299 ENTRY(cpu_arm720_set_pgd)
300                 mov     r1, #0
301                 mcr     p15, 0, r1, c7, c7, 0           @ invalidate cache
302                 mcr     p15, 0, r0, c2, c0, 0           @ update page table ptr
303                 mcr     p15, 0, r1, c8, c7, 0           @ flush TLB (v4)
304                 mov     pc, lr
305
306 /*
307  * Function: arm720_set_pmd ()
308  *
309  * Params  : r0 = Address to set
310  *         : r1 = value to set
311  *
312  * Purpose : Set a PMD and flush it out of any WB cache
313  */
314 ENTRY(cpu_arm720_set_pmd)
315                 tst     r1, #3
316                 orrne   r1, r1, #16                     @ Updatable bit is
317                 str     r1, [r0]                        @ always set on ARM720
318                 mov     pc, lr
319
320 /*
321  * Function: arm720_set_pte(pte_t *ptep, pte_t pte)
322  * Params  : r0 = Address to set
323  *         : r1 = value to set
324  * Purpose : Set a PTE and flush it out of any WB cache
325  */
326                 .align  5
327 ENTRY(cpu_arm720_set_pte)
328                 str     r1, [r0], #-1024                @ linux version
329
330                 eor     r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
331
332                 bic     r2, r1, #0xff0
333                 bic     r2, r2, #3
334                 orr     r2, r2, #HPTE_TYPE_SMALL
335
336                 tst     r1, #LPTE_USER | LPTE_EXEC      @ User or Exec?
337                 orrne   r2, r2, #HPTE_AP_READ
338
339                 tst     r1, #LPTE_WRITE | LPTE_DIRTY    @ Write and Dirty?
340                 orreq   r2, r2, #HPTE_AP_WRITE
341
342                 tst     r1, #LPTE_PRESENT | LPTE_YOUNG  @ Present and Young
343                 movne   r2, #0
344
345                 str     r2, [r0]                        @ hardware version
346                 mov     pc, lr
347
348 /*
349  * Function: arm720_reset
350  * Params  : r0 = address to jump to
351  * Notes   : This sets up everything for a reset
352  */
353 ENTRY(cpu_arm720_reset)
354                 mov     ip, #0
355                 mcr     p15, 0, ip, c7, c7, 0           @ invalidate cache
356                 mcr     p15, 0, ip, c8, c7, 0           @ flush TLB (v4)
357                 mrc     p15, 0, ip, c1, c0, 0           @ get ctrl register
358                 bic     ip, ip, #0x000f                 @ ............wcam
359                 bic     ip, ip, #0x2100                 @ ..v....s........
360                 mcr     p15, 0, ip, c1, c0, 0           @ ctrl register
361                 mov     pc, r0
362
363         
364 cpu_armvlsi_name:
365                 .asciz  "ARM"
366 cpu_arm720_name:
367                 .asciz  "ARM720T"
368                 .align
369
370                 .section ".text.init", #alloc, #execinstr
371
372 __arm720_setup: mov     r0, #0
373                 mcr     p15, 0, r0, c7, c7, 0           @ invalidate caches
374                 mcr     p15, 0, r0, c8, c7, 0           @ flush TLB (v4)
375                 mcr     p15, 0, r4, c2, c0              @ load page table pointer
376                 mov     r0, #0x1f                       @ Domains 0, 1 = client
377                 mcr     p15, 0, r0, c3, c0              @ load domain access register
378
379                 mrc     p15, 0, r0, c1, c0              @ get control register
380                 bic     r0, r0, #0x0e00                 @ ..V. ..RS BLDP WCAM
381                 orr     r0, r0, #0x2100                 @ .... .... .111 .... (old)
382                 orr     r0, r0, #0x003d                 @ ..1. ..01 ..11 1101 (new)
383                 mov     pc, lr                          @ __ret (head-armv.S)
384
385 /*
386  * Purpose : Function pointers used to access above functions - all calls
387  *           come through these
388  */
389                 .type   arm720_processor_functions, #object
390 ENTRY(arm720_processor_functions)
391                 .word   cpu_arm720_data_abort
392                 .word   cpu_arm720_check_bugs
393                 .word   cpu_arm720_proc_init
394                 .word   cpu_arm720_proc_fin
395                 .word   cpu_arm720_reset
396                 .word   cpu_arm720_do_idle
397
398                 /* cache */
399                 .word   cpu_arm720_cache_clean_invalidate_all
400                 .word   cpu_arm720_cache_clean_invalidate_range
401                 .word   cpu_arm720_flush_ram_page
402
403                 /* dcache */
404                 .word   cpu_arm720_dcache_invalidate_range
405                 .word   cpu_arm720_dcache_clean_range
406                 .word   cpu_arm720_dcache_clean_page
407                 .word   cpu_arm720_dcache_clean_entry
408
409                 /* icache */
410                 .word   cpu_arm720_icache_invalidate_range
411                 .word   cpu_arm720_icache_invalidate_page
412
413                 /* tlb */
414                 .word   cpu_arm720_tlb_invalidate_all
415                 .word   cpu_arm720_tlb_invalidate_range
416                 .word   cpu_arm720_tlb_invalidate_page
417
418                 /* pgtable */
419                 .word   cpu_arm720_set_pgd
420                 .word   cpu_arm720_set_pmd
421                 .word   cpu_arm720_set_pte
422                 .size   arm720_processor_functions, . - arm720_processor_functions
423
424                 .type   cpu_arm720_info, #object
425 cpu_arm720_info:
426                 .long   cpu_armvlsi_name
427                 .long   cpu_arm720_name
428                 .size   cpu_arm720_info, . - cpu_arm720_info
429         
430                 .type   cpu_arch_name, #object
431 cpu_arch_name:  .asciz  "armv4"
432                 .size   cpu_arch_name, . - cpu_arch_name
433
434                 .type   cpu_elf_name, #object
435 cpu_elf_name:   .asciz  "v4"
436                 .size   cpu_elf_name, . - cpu_elf_name
437                 .align
438
439 /*
440  * See /include/asm-arm for a definition of this structure.
441  */
442         
443                 .section ".proc.info", #alloc, #execinstr
444
445                 .type   __arm720_proc_info, #object
446 __arm720_proc_info:
447                 .long   0x41807200                              @ cpu_val
448                 .long   0xffffff00                              @ cpu_mask
449                 .long   0x00000c1e                              @ section_mmu_flags
450                 b       __arm720_setup                          @ cpu_flush
451                 .long   cpu_arch_name                           @ arch_name
452                 .long   cpu_elf_name                            @ elf_name
453                 .long   HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT    @ elf_hwcap
454                 .long   cpu_arm720_info                         @ info
455                 .long   arm720_processor_functions
456                 .size   __arm720_proc_info, . - __arm720_proc_info