[PATCH] 997/1: Cotulla --> PXA250
[opensuse:kernel.git] / arch / arm / mm / proc-xscale.S
1 /*
2  *  linux/arch/arm/mm/proc-xscale.S
3  *
4  *  Author:     Nicolas Pitre
5  *  Created:    November 2000
6  *  Copyright:  (C) 2000, 2001 MontaVista Software Inc.
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 version 2 as
10  * published by the Free Software Foundation.
11  *
12  * MMU functions for the Intel XScale CPUs
13  *
14  * 2001 Aug 21:
15  *      some contributions by Brett Gaines <brett.w.gaines@intel.com>
16  *      Copyright 2001 by Intel Corp.
17  *
18  * 2001 Sep 08:
19  *      Completely revisited, many important fixes
20  *      Nicolas Pitre <nico@cam.org>
21  */
22
23 #include <linux/linkage.h>
24 #include <asm/assembler.h>
25 #include <asm/constants.h>
26 #include <asm/procinfo.h>
27 #include <asm/hardware.h>
28 #include <asm/proc/pgtable.h>
29
30 /*
31  * This is the maximum size of an area which will be flushed.  If the area
32  * is larger than this, then we flush the whole cache
33  */
34 #define MAX_AREA_SIZE   32768
35
36 /*
37  * the cache line size of the I and D cache
38  */
39 #define CACHELINESIZE   32
40
41 /*
42  * the size of the data cache
43  */
44 #define CACHESIZE       32768
45
46 /*
47  * and the page size
48  */
49 #define PAGESIZE        4096
50
51 /*
52  * Virtual address used to allocate the cache when flushed
53  *
54  * This must be an address range which is _never_ used.  It should
55  * apparently have a mapping in the corresponding page table for
56  * compatibility with future CPUs that _could_ require it.  For instance we
57  * don't care.
58  *
59  * This must be aligned on a 2*CACHESIZE boundary.  The code selects one of
60  * the 2 areas in alternance each time the clean_d_cache macro is used.
61  * Without this the XScale core exhibits cache eviction problems and no one
62  * knows why.
63  *
64  * Reminder: the vector table is located at 0xffff0000-0xffff0fff.
65  */
66 #define CLEAN_ADDR      0xfffe0000
67
68 /*
69  * This macro is used to wait for a CP15 write and is needed
70  * when we have to ensure that the last operation to the co-pro
71  * was completed before continuing with operation.
72  */
73         .macro  cpwait, rd
74         mrc     p15, 0, \rd, c2, c0, 0          @ arbitrary read of cp15
75         mov     \rd, \rd                        @ wait for completion
76         sub     pc, pc, #4                      @ flush instruction pipeline
77         .endm
78
79         .macro  cpwait_ret, lr, rd
80         mrc     p15, 0, \rd, c2, c0, 0          @ arbitrary read of cp15
81         sub     pc, \lr, \rd, LSR #32           @ wait for completion and
82                                                 @ flush instruction pipeline
83         .endm
84
85 /*
86  * This macro cleans the entire dcache using line allocate.
87  * The main loop has been unrolled to reduce loop overhead.
88  * rd and rs are two scratch registers.
89  */
90         .macro  clean_d_cache, rd, rs
91         ldr     \rs, =clean_addr
92         ldr     \rd, [\rs]
93         eor     \rd, \rd, #CACHESIZE
94         str     \rd, [\rs]
95         add     \rs, \rd, #CACHESIZE
96 1:      mcr     p15, 0, \rd, c7, c2, 5          @ allocate D cache line
97         add     \rd, \rd, #CACHELINESIZE
98         mcr     p15, 0, \rd, c7, c2, 5          @ allocate D cache line
99         add     \rd, \rd, #CACHELINESIZE
100         mcr     p15, 0, \rd, c7, c2, 5          @ allocate D cache line
101         add     \rd, \rd, #CACHELINESIZE
102         mcr     p15, 0, \rd, c7, c2, 5          @ allocate D cache line
103         add     \rd, \rd, #CACHELINESIZE
104         teq     \rd, \rs
105         bne     1b
106         .endm
107
108         .data
109 clean_addr:     .word   CLEAN_ADDR
110
111         .text
112
113 /*
114  * cpu_xscale_check_bugs()
115  */
116 ENTRY(cpu_xscale_check_bugs)
117         mrs     ip, cpsr
118         bic     ip, ip, #PSR_F_BIT
119         msr     cpsr, ip
120         mov     pc, lr
121
122 /*
123  * cpu_xscale_proc_init()
124  *
125  * Nothing too exciting at the moment
126  */
127 ENTRY(cpu_xscale_proc_init)
128         mov     pc, lr
129
130 /*
131  * cpu_xscale_proc_fin()
132  */
133 ENTRY(cpu_xscale_proc_fin)
134         str     lr, [sp, #-4]!
135         mov     r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
136         msr     cpsr_c, r0
137         mrc     p15, 0, r0, c1, c0, 0           @ ctrl register
138         bic     r0, r0, #0x1800                 @ ...IZ...........
139         bic     r0, r0, #0x0006                 @ .............CA.
140         mcr     p15, 0, r0, c1, c0, 0           @ disable caches
141         bl      cpu_xscale_cache_clean_invalidate_all   @ clean caches
142         ldr     pc, [sp], #4
143
144 /*
145  * cpu_xscale_reset(loc)
146  *
147  * Perform a soft reset of the system.  Put the CPU into the
148  * same state as it would be if it had been reset, and branch
149  * to what would be the reset vector.
150  *
151  * loc: location to jump to for soft reset
152  */
153         .align  5
154 ENTRY(cpu_xscale_reset)
155         mov     r1, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
156         msr     cpsr_c, r1                      @ reset CPSR
157         mrc     p15, 0, r1, c1, c0, 0           @ ctrl register
158         bic     r1, r1, #0x0086                 @ ........B....CA.
159         bic     r1, r1, #0x1900                 @ ...IZ..S........
160         mcr     p15, 0, r1, c1, c0, 0           @ ctrl register
161         mcr     p15, 0, ip, c7, c7, 0           @ invalidate I,D caches & BTB
162         bic     r1, r1, #0x0001                 @ ...............M
163         mcr     p15, 0, r1, c1, c0, 0           @ ctrl register
164         @ CAUTION: MMU turned off from this point. We count on the pipeline
165         @ already containing those two last instructions to survive.
166         mcr     p15, 0, ip, c8, c7, 0           @ invalidate I & D TLBs
167         mov     pc, r0
168
169 /*
170  * cpu_xscale_do_idle(type)
171  *
172  * Cause the processor to idle
173  *
174  * type:
175  *   0 = slow idle
176  *   1 = fast idle
177  *   2 = switch to slow processor clock
178  *   3 = switch to fast processor clock
179  *
180  * For now we do nothing but go to idle mode for every case
181  *
182  * XScale supports clock switching, but using idle mode support
183  * allows external hardware to react to system state changes.
184  */
185         .align  5
186
187 ENTRY(cpu_xscale_do_idle)
188         mov     r0, #1
189         mcr     p14, 0, r0, c7, c0, 0           @ Go to IDLE
190         mov     pc, lr
191
192 /* ================================= CACHE ================================ */
193
194 /*
195  * cpu_xscale_cache_clean_invalidate_all (void)
196  *
197  * clean and invalidate all cache lines
198  *
199  * Note:
200  *  1. We should preserve r0 at all times.
201  *  2. Even if this function implies cache "invalidation" by its name,
202  *     we don't need to actually use explicit invalidation operations
203  *     since the goal is to discard all valid references from the cache
204  *     and the cleaning of it already has that effect.
205  *  3. Because of 2 above and the fact that kernel space memory is always
206  *     coherent across task switches there is no need to worry about
207  *     inconsistencies due to interrupts, ence no irq disabling.
208  */
209         .align  5
210 ENTRY(cpu_xscale_cache_clean_invalidate_all)
211         mov     r2, #1
212 cpu_xscale_cache_clean_invalidate_all_r2:
213         clean_d_cache r0, r1
214         teq     r2, #0
215         mcrne   p15, 0, ip, c7, c5, 0           @ Invalidate I cache & BTB
216         mcr     p15, 0, ip, c7, c10, 4          @ Drain Write (& Fill) Buffer
217         mov     pc, lr
218
219 /*
220  * cpu_xscale_cache_clean_invalidate_range(start, end, flags)
221  *
222  * clean and invalidate all cache lines associated with this area of memory
223  *
224  * start: Area start address
225  * end:   Area end address
226  * flags: nonzero for I cache as well
227  */
228         .align  5
229 ENTRY(cpu_xscale_cache_clean_invalidate_range)
230         bic     r0, r0, #CACHELINESIZE - 1      @ round down to cache line
231         sub     r3, r1, r0
232         cmp     r3, #MAX_AREA_SIZE
233         bhi     cpu_xscale_cache_clean_invalidate_all_r2
234 1:      mcr     p15, 0, r0, c7, c10, 1          @ Clean D cache line
235         mcr     p15, 0, r0, c7, c6, 1           @ Invalidate D cache line
236         add     r0, r0, #CACHELINESIZE
237         cmp     r0, r1
238         blo     1b
239         teq     r2, #0
240         mcr     p15, 0, ip, c7, c10, 4          @ Drain Write (& Fill) Buffer
241         moveq   pc, lr
242         sub     r0, r0, r3
243 1:      mcr     p15, 0, r0, c7, c5, 1           @ Invalidate I cache line
244         add     r0, r0, #CACHELINESIZE
245         cmp     r0, r1
246         blo     1b
247         mcr     p15, 0, ip, c7, c5, 6           @ Invalidate BTB
248         mov     pc, lr
249
250 /*
251  * cpu_xscale_flush_ram_page(page)
252  *
253  * clean all cache lines associated with this memory page
254  *
255  * page: page to clean
256  */
257         .align  5
258 ENTRY(cpu_xscale_flush_ram_page)
259         mov     r1, #PAGESIZE
260 1:      mcr     p15, 0, r0, c7, c10, 1          @ Clean D cache line
261         add     r0, r0, #CACHELINESIZE
262         mcr     p15, 0, r0, c7, c10, 1          @ Clean D cache line
263         add     r0, r0, #CACHELINESIZE
264         subs    r1, r1, #2 * CACHELINESIZE
265         bne     1b
266         mcr     p15, 0, ip, c7, c10, 4          @ Drain Write (& Fill) Buffer
267         mov     pc, lr
268
269 /* ================================ D-CACHE =============================== */
270
271 /*
272  * cpu_xscale_dcache_invalidate_range(start, end)
273  *
274  * throw away all D-cached data in specified region without an obligation
275  * to write them back.  Note however that on XScale we must clean all
276  * entries also due to hardware errata (80200 A0 & A1 only).
277  *
278  * start: virtual start address
279  * end:   virtual end address
280  */
281         .align  5
282 ENTRY(cpu_xscale_dcache_invalidate_range)
283         mrc     p15, 0, r2, c0, c0, 0           @ Read part no.
284         eor     r2, r2, #0x69000000
285         eor     r2, r2, #0x00052000             @ 80200 XX part no.
286         bics    r2, r2, #0x1                    @ Clear LSB in revision field
287         moveq   r2, #0
288         beq     cpu_xscale_cache_clean_invalidate_range @ An 80200 A0 or A1
289
290         tst     r0, #CACHELINESIZE - 1
291         mcrne   p15, 0, r0, c7, c10, 1          @ Clean D cache line
292         tst     r1, #CACHELINESIZE - 1
293         mcrne   p15, 0, r1, c7, c10, 1          @ Clean D cache line
294         bic     r0, r0, #CACHELINESIZE - 1      @ round down to cache line
295 1:      mcr     p15, 0, r0, c7, c6, 1           @ Invalidate D cache line
296         add     r0, r0, #CACHELINESIZE
297         cmp     r0, r1
298         blo     1b
299         mov     pc, lr
300
301 /*
302  * cpu_xscale_dcache_clean_range(start, end)
303  *
304  * For the specified virtual address range, ensure that all caches contain
305  * clean data, such that peripheral accesses to the physical RAM fetch
306  * correct data.
307  *
308  * start: virtual start address
309  * end:   virtual end address
310  */
311         .align  5
312 ENTRY(cpu_xscale_dcache_clean_range)
313         bic     r0, r0, #CACHELINESIZE - 1
314         sub     r2, r1, r0
315         cmp     r2, #MAX_AREA_SIZE
316         movhi   r2, #0
317         bhi     cpu_xscale_cache_clean_invalidate_all_r2
318
319 1:      mcr     p15, 0, r0, c7, c10, 1          @ Clean D cache line
320         add     r0, r0, #CACHELINESIZE
321         mcr     p15, 0, r0, c7, c10, 1          @ Clean D cache line
322         add     r0, r0, #CACHELINESIZE
323         cmp     r0, r1
324         blo     1b
325         mcr     p15, 0, ip, c7, c10, 4          @ Drain Write (& Fill) Buffer
326         mov     pc, lr
327
328 /*
329  * cpu_xscale_clean_dcache_page(page)
330  *
331  * Cleans a single page of dcache so that if we have any future aliased
332  * mappings, they will be consistent at the time that they are created.
333  *
334  * Note:
335  *  1. we don't need to flush the write buffer in this case. [really? -Nico]
336  *  2. we don't invalidate the entries since when we write the page
337  *     out to disk, the entries may get reloaded into the cache.
338  */
339         .align  5
340 ENTRY(cpu_xscale_dcache_clean_page)
341         mov     r1, #PAGESIZE
342 1:      mcr     p15, 0, r0, c7, c10, 1          @ Clean D cache line
343         add     r0, r0, #CACHELINESIZE
344         mcr     p15, 0, r0, c7, c10, 1          @ Clean D cache line
345         add     r0, r0, #CACHELINESIZE
346         mcr     p15, 0, r0, c7, c10, 1          @ Clean D cache line
347         add     r0, r0, #CACHELINESIZE
348         mcr     p15, 0, r0, c7, c10, 1          @ Clean D cache line
349         add     r0, r0, #CACHELINESIZE
350         subs    r1, r1, #4 * CACHELINESIZE
351         bne     1b
352         mcr     p15, 0, ip, c7, c10, 4          @ Drain Write (& Fill) Buffer
353         mov     pc, lr
354
355 /*
356  * cpu_xscale_dcache_clean_entry(addr)
357  *
358  * Clean the specified entry of any caches such that the MMU
359  * translation fetches will obtain correct data.
360  *
361  * addr: cache-unaligned virtual address
362  */
363         .align  5
364 ENTRY(cpu_xscale_dcache_clean_entry)
365         mcr     p15, 0, r0, c7, c10, 1          @ Clean D cache line
366         mcr     p15, 0, ip, c7, c10, 4          @ Drain Write (& Fill) Buffer
367         mov     pc, lr
368
369 /* ================================ I-CACHE =============================== */
370
371 /*
372  * cpu_xscale_icache_invalidate_range(start, end)
373  *
374  * invalidate a range of virtual addresses from the Icache
375  *
376  * start: virtual start address
377  * end:   virtual end address
378  *
379  * Note: This is vaguely defined as supposed to bring the dcache and the
380  *       icache in sync by the way this function is used.
381  */
382         .align  5
383 ENTRY(cpu_xscale_icache_invalidate_range)
384         bic     r0, r0, #CACHELINESIZE - 1
385 1:      mcr     p15, 0, r0, c7, c10, 1          @ Clean D cache line
386         mcr     p15, 0, r0, c7, c5, 1           @ Invalidate I cache line
387         add     r0, r0, #CACHELINESIZE
388         cmp     r0, r1
389         blo     1b
390         mcr     p15, 0, ip, c7, c5, 6           @ Invalidate BTB
391         mcr     p15, 0, ip, c7, c10, 4          @ Drain Write (& Fill) Buffer
392         mov     pc, lr
393
394 /*
395  * cpu_xscale_icache_invalidate_page(page)
396  *
397  * invalidate all Icache lines associated with this area of memory
398  *
399  * page: page to invalidate
400  */
401         .align  5
402 ENTRY(cpu_xscale_icache_invalidate_page)
403         mov     r1, #PAGESIZE
404 1:      mcr     p15, 0, r0, c7, c5, 1           @ Invalidate I cache line
405         add     r0, r0, #CACHELINESIZE
406         mcr     p15, 0, r0, c7, c5, 1           @ Invalidate I cache line
407         add     r0, r0, #CACHELINESIZE
408         mcr     p15, 0, r0, c7, c5, 1           @ Invalidate I cache line
409         add     r0, r0, #CACHELINESIZE
410         mcr     p15, 0, r0, c7, c5, 1           @ Invalidate I cache line
411         add     r0, r0, #CACHELINESIZE
412         subs    r1, r1, #4 * CACHELINESIZE
413         bne     1b
414         mcr     p15, 0, r0, c7, c5, 6           @ Invalidate BTB
415         mov     pc, lr
416
417 /* ================================ CACHE LOCKING============================
418  *
419  * The XScale MicroArchitecture implements support for locking entries into
420  * the data and instruction cache.  The following functions implement the core
421  * low level instructions needed to accomplish the locking.  The developer's
422  * manual states that the code that performs the locking must be in non-cached
423  * memory.  To accomplish this, the code in xscale-cache-lock.c copies the
424  * following functions from the cache into a non-cached memory region that
425  * is allocated through consistent_alloc().
426  *
427  */
428         .align  5
429 /*
430  * xscale_icache_lock
431  *
432  * r0: starting address to lock
433  * r1: end address to lock
434  */
435 ENTRY(xscale_icache_lock)
436
437 iLockLoop:
438         bic     r0, r0, #CACHELINESIZE - 1
439         mcr     p15, 0, r0, c9, c1, 0   @ lock into cache
440         cmp     r0, r1                  @ are we done?
441         add     r0, r0, #CACHELINESIZE  @ advance to next cache line
442         bls     iLockLoop
443         mov     pc, lr
444
445 /*
446  * xscale_icache_unlock
447  */
448 ENTRY(xscale_icache_unlock)
449         mcr     p15, 0, r0, c9, c1, 1   @ Unlock icache
450         mov     pc, lr
451
452 /*
453  * xscale_dcache_lock
454  *
455  * r0: starting address to lock
456  * r1: end address to lock
457  */
458 ENTRY(xscale_dcache_lock)
459         mcr     p15, 0, ip, c7, c10, 4          @ Drain Write (& Fill) Buffer
460         mov     r2, #1
461         mcr     p15, 0, r2, c9, c2, 0   @ Put dcache in lock mode
462         cpwait  ip                      @ Wait for completion
463
464         mrs     r2, cpsr
465         orr     r3, r2, #PSR_F_BIT | PSR_I_BIT
466 dLockLoop:
467         msr     cpsr_c, r3
468         mcr     p15, 0, r0, c7, c10, 1  @ Write back line if it is dirty
469         mcr     p15, 0, r0, c7, c6, 1   @ Flush/invalidate line
470         msr     cpsr_c, r2
471         ldr     ip, [r0], #CACHELINESIZE @ Preload 32 bytes into cache from
472                                         @ location [r0]. Post-increment
473                                         @ r3 to next cache line
474         cmp     r0, r1                  @ Are we done?
475         bls     dLockLoop
476
477         mcr     p15, 0, ip, c7, c10, 4          @ Drain Write (& Fill) Buffer
478         mov     r2, #0
479         mcr     p15, 0, r2, c9, c2, 0   @ Get out of lock mode
480         cpwait_ret lr, ip
481
482 /*
483  * xscale_dcache_unlock
484  */
485 ENTRY(xscale_dcache_unlock)
486         mcr     p15, 0, ip, c7, c10, 4          @ Drain Write (& Fill) Buffer
487         mcr     p15, 0, ip, c9, c2, 1   @ Unlock cache
488         mov     pc, lr
489
490 /*
491  * Needed to determine the length of the code that needs to be copied.
492  */
493         .align  5
494 ENTRY(xscale_cache_dummy)
495         mov     pc, lr
496
497 /* ================================ TLB LOCKING==============================
498  *
499  * The XScale MicroArchitecture implements support for locking entries into
500  * the Instruction and Data TLBs.  The following functions provide the
501  * low level support for supporting these under Linux.  xscale-lock.c
502  * implements some higher level management code.  Most of the following
503  * is taken straight out of the Developer's Manual.
504  */
505
506 /*
507  * Lock I-TLB entry
508  *
509  * r0: Virtual address to translate and lock
510  */
511         .align  5
512 ENTRY(xscale_itlb_lock)
513         mrs     r2, cpsr
514         orr     r3, r2, #PSR_F_BIT | PSR_I_BIT
515         msr     cpsr_c, r3                      @ Disable interrupts
516         mcr     p15, 0, r0, c8, c5, 1           @ Invalidate I-TLB entry
517         mcr     p15, 0, r0, c10, c4, 0          @ Translate and lock
518         msr     cpsr_c, r2                      @ Restore interrupts
519         cpwait_ret lr, ip
520
521 /*
522  * Lock D-TLB entry
523  *
524  * r0: Virtual address to translate and lock
525  */
526         .align  5
527 ENTRY(xscale_dtlb_lock)
528         mrs     r2, cpsr
529         orr     r3, r2, #PSR_F_BIT | PSR_I_BIT
530         msr     cpsr_c, r3                      @ Disable interrupts
531         mcr     p15, 0, r0, c8, c6, 1           @ Invalidate D-TLB entry
532         mcr     p15, 0, r0, c10, c8, 0          @ Translate and lock
533         msr     cpsr_c, r2                      @ Restore interrupts
534         cpwait_ret lr, ip
535
536 /*
537  * Unlock all I-TLB entries
538  */
539         .align  5
540 ENTRY(xscale_itlb_unlock)
541         mcr     p15, 0, ip, c10, c4, 1          @ Unlock I-TLB
542         mcr     p15, 0, ip, c8, c5, 0           @ Invalidate I-TLB
543         cpwait_ret lr, ip
544
545 /*
546  * Unlock all D-TLB entries
547  */
548 ENTRY(xscale_dtlb_unlock)
549         mcr     p15, 0, ip, c10, c8, 1          @ Unlock D-TBL
550         mcr     p15, 0, ip, c8, c6, 0           @ Invalidate D-TLB
551         cpwait_ret lr, ip
552
553 /* =============================== PageTable ============================== */
554
555 #define PMD_CACHE_WRITE_ALLOCATE 0
556 #define PTE_CACHE_WRITE_ALLOCATE 0
557
558 /*
559  * cpu_xscale_set_pgd(pgd)
560  *
561  * Set the translation base pointer to be as described by pgd.
562  *
563  * pgd: new page tables
564  */
565         .align  5
566 ENTRY(cpu_xscale_set_pgd)
567         clean_d_cache r1, r2
568         mcr     p15, 0, ip, c7, c5, 0           @ Invalidate I cache & BTB
569         mcr     p15, 0, ip, c7, c10, 4          @ Drain Write (& Fill) Buffer
570         mcr     p15, 0, r0, c2, c0, 0           @ load page table pointer
571         mcr     p15, 0, ip, c8, c7, 0           @ invalidate I & D TLBs
572         cpwait_ret lr, ip
573
574 /*
575  * cpu_xscale_set_pmd(pmdp, pmd)
576  *
577  * Set a level 1 translation table entry, and clean it out of
578  * any caches such that the MMUs can load it correctly.
579  *
580  * pmdp: pointer to PMD entry
581  * pmd:  PMD value to store
582  */
583         .align  5
584 ENTRY(cpu_xscale_set_pmd)
585 #if PMD_CACHE_WRITE_ALLOCATE
586         and     r2, r1, #PMD_TYPE_MASK|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE
587         cmp     r2, #PMD_TYPE_SECT|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE
588         orreq   r1, r1, #PMD_SECT_TEX(1)
589 #endif
590         str     r1, [r0]
591         mov     ip, #0
592         mcr     p15, 0, r0, c7, c10, 1          @ Clean D cache line
593         mcr     p15, 0, ip, c7, c10, 4          @ Drain Write (& Fill) Buffer
594         mov     pc, lr
595
596 /*
597  * cpu_xscale_set_pte(ptep, pte)
598  *
599  * Set a PTE and flush it out
600  *
601  * Errata 40: must set memory to write-through for user read-only pages.
602  */
603         .align  5
604 ENTRY(cpu_xscale_set_pte)
605         str     r1, [r0], #-1024                @ linux version
606
607         bic     r2, r1, #0xff0
608         orr     r2, r2, #PTE_TYPE_EXT           @ extended page
609
610         eor     r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
611
612         tst     r3, #L_PTE_USER | L_PTE_EXEC    @ User or Exec?
613         orrne   r2, r2, #PTE_EXT_AP_URO_SRW     @ yes -> user r/o, system r/w
614
615         tst     r3, #L_PTE_WRITE | L_PTE_DIRTY  @ Write and Dirty?
616         orreq   r2, r2, #PTE_EXT_AP_UNO_SRW     @ yes -> user n/a, system r/w
617                                                 @ combined with user -> user r/w
618
619         @
620         @ Handle the X bit.  We want to set this bit for the minicache
621         @ (U = E = B = W = 0, C = 1) or when write allocate is enabled,
622         @ and we have a writeable, cacheable region.  If we ignore the
623         @ U and E bits, we can allow user space to use the minicache as
624         @ well.
625         @
626         @  X = (C & ~W & ~B) | (C & W & B & write_allocate)
627         @
628         eor     ip, r1, #L_PTE_CACHEABLE
629         tst     ip, #L_PTE_CACHEABLE | L_PTE_WRITE | L_PTE_BUFFERABLE
630 #if PTE_CACHE_WRITE_ALLOCATE
631         eorne   ip, r1, #L_PTE_CACHEABLE | L_PTE_WRITE | L_PTE_BUFFERABLE
632         tstne   ip, #L_PTE_CACHEABLE | L_PTE_WRITE | L_PTE_BUFFERABLE
633 #endif
634         orreq   r2, r2, #PTE_EXT_TEX(1)
635
636         @
637         @ Erratum 40: The B bit must be cleared for a user read-only
638         @ cacheable page.
639         @
640         @  B = B & ~((U|E) & C & ~W)
641         @
642         and     ip, r1, #L_PTE_USER | L_PTE_EXEC | L_PTE_WRITE | L_PTE_CACHEABLE
643         teq     ip, #L_PTE_USER | L_PTE_CACHEABLE
644         teqne   ip, #L_PTE_EXEC | L_PTE_CACHEABLE
645         teqne   ip, #L_PTE_USER | L_PTE_EXEC | L_PTE_CACHEABLE
646         biceq   r2, r2, #PTE_BUFFERABLE
647
648         tst     r3, #L_PTE_PRESENT | L_PTE_YOUNG        @ Present and Young?
649         movne   r2, #0                          @ no -> fault
650
651         str     r2, [r0]                        @ hardware version
652         mov     ip, #0
653         mcr     p15, 0, r0, c7, c10, 1          @ Clean D cache line
654         mcr     p15, 0, ip, c7, c10, 4          @ Drain Write (& Fill) Buffer
655         mov     pc, lr
656
657
658         .ltorg
659
660 cpu_manu_name:
661         .asciz  "Intel"
662
663 cpu_80200_name:
664         .asciz  "XScale-80200"
665
666 cpu_pxa250_name:
667         .asciz  "XScale-PXA250"
668
669         .align
670
671         .section ".text.init", #alloc, #execinstr
672
673 __xscale_setup:
674         mov     r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
675         msr     cpsr_c, r0
676         mcr     p15, 0, ip, c7, c7, 0           @ invalidate I, D caches & BTB
677         mcr     p15, 0, ip, c7, c10, 4          @ Drain Write (& Fill) Buffer
678         mcr     p15, 0, ip, c8, c7, 0           @ invalidate I, D TLBs
679         mcr     p15, 0, r4, c2, c0, 0           @ load page table pointer
680         mov     r0, #0x1f                       @ Domains 0, 1 = client
681         mcr     p15, 0, r0, c3, c0, 0           @ load domain access register
682         mrc     p15, 0, r0, c1, c0, 0           @ get control register
683         bic     r0, r0, #0x0200                 @ .... ..R. .... ....
684         bic     r0, r0, #0x0082                 @ .... .... B... ..A.
685         orr     r0, r0, #0x0005                 @ .... .... .... .C.M
686         orr     r0, r0, #0x3900                 @ ..VI Z..S .... ....
687         mov     pc, lr
688
689         .text
690
691 /*
692  * Purpose : Function pointers used to access above functions - all calls
693  *           come through these
694  */
695
696         .type   xscale_processor_functions, #object
697 ENTRY(xscale_processor_functions)
698         .word   armv4t_early_abort
699         .word   cpu_xscale_check_bugs
700         .word   cpu_xscale_proc_init
701         .word   cpu_xscale_proc_fin
702         .word   cpu_xscale_reset
703         .word   cpu_xscale_do_idle
704
705         /* cache */
706         .word   cpu_xscale_cache_clean_invalidate_all
707         .word   cpu_xscale_cache_clean_invalidate_range
708         .word   cpu_xscale_flush_ram_page
709
710         /* dcache */
711         .word   cpu_xscale_dcache_invalidate_range
712         .word   cpu_xscale_dcache_clean_range
713         .word   cpu_xscale_dcache_clean_page
714         .word   cpu_xscale_dcache_clean_entry
715
716         /* icache */
717         .word   cpu_xscale_icache_invalidate_range
718         .word   cpu_xscale_icache_invalidate_page
719
720         /* pgtable */
721         .word   cpu_xscale_set_pgd
722         .word   cpu_xscale_set_pmd
723         .word   cpu_xscale_set_pte
724
725         /* misc */
726         .word   armv5te_clear_user_page
727         .word   armv5te_copy_user_page
728
729         .size   xscale_processor_functions, . - xscale_processor_functions
730
731         .type   cpu_80200_info, #object
732 cpu_80200_info:
733         .long   cpu_manu_name
734         .long   cpu_80200_name
735         .size   cpu_80200_info, . - cpu_80200_info
736
737         .type   cpu_pxa250_info, #object
738 cpu_pxa250_info:
739         .long   cpu_manu_name
740         .long   cpu_pxa250_name
741         .size   cpu_pxa250_info, . - cpu_pxa250_info
742
743         .type   cpu_arch_name, #object
744 cpu_arch_name:
745         .asciz  "armv5"
746         .size   cpu_arch_name, . - cpu_arch_name
747
748         .type   cpu_elf_name, #object
749 cpu_elf_name:
750         .asciz  "v5"
751         .size   cpu_elf_name, . - cpu_elf_name
752         .align
753
754         .section ".proc.info", #alloc, #execinstr
755
756         .type   __80200_proc_info,#object
757 __80200_proc_info:
758         .long   0x69052000
759         .long   0xfffffff0
760         .long   0x00000c0e
761         b       __xscale_setup
762         .long   cpu_arch_name
763         .long   cpu_elf_name
764         .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
765         .long   cpu_80200_info
766         .long   xscale_processor_functions
767         .long   v4wbi_tlb_fns
768         .size   __80200_proc_info, . - __80200_proc_info
769
770         .type   __pxa250_proc_info,#object
771 __pxa250_proc_info:
772         .long   0x69052100
773         .long   0xfffffff0
774         .long   0x00000c0e
775         b       __xscale_setup
776         .long   cpu_arch_name
777         .long   cpu_elf_name
778         .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
779         .long   cpu_pxa250_info
780         .long   xscale_processor_functions
781         .long   v4wbi_tlb_fns
782         .size   __cotulla_proc_info, . - __cotulla_proc_info
783         .size   __pxa250_proc_info, . - __pxa250_proc_info
784