Merge remote-tracking branch 's5p/for-next'
[linux-2.6/next.git] / arch / arm / mm / proc-v7lpae.S
blob0bee21308d20e30df3820014ed6214ab4ceb8236
1 /*
2  * arch/arm/mm/proc-v7lpae.S
3  *
4  * Copyright (C) 2001 Deep Blue Solutions Ltd.
5  * Copyright (C) 2011 ARM Ltd.
6  * Author: Catalin Marinas <catalin.marinas@arm.com>
7  *   based on arch/arm/mm/proc-v7.S
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
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 #include <linux/init.h>
23 #include <linux/linkage.h>
24 #include <asm/assembler.h>
25 #include <asm/asm-offsets.h>
26 #include <asm/hwcap.h>
27 #include <asm/pgtable-hwdef.h>
28 #include <asm/pgtable.h>
30 #include "proc-macros.S"
32 #define TTB_IRGN_NC     (0 << 8)
33 #define TTB_IRGN_WBWA   (1 << 8)
34 #define TTB_IRGN_WT     (2 << 8)
35 #define TTB_IRGN_WB     (3 << 8)
36 #define TTB_RGN_NC      (0 << 10)
37 #define TTB_RGN_OC_WBWA (1 << 10)
38 #define TTB_RGN_OC_WT   (2 << 10)
39 #define TTB_RGN_OC_WB   (3 << 10)
40 #define TTB_S           (3 << 12)
41 #define TTB_EAE         (1 << 31)
43 /* PTWs cacheable, inner WB not shareable, outer WB not shareable */
44 #define TTB_FLAGS_UP    (TTB_IRGN_WB|TTB_RGN_OC_WB)
45 #define PMD_FLAGS_UP    (PMD_SECT_WB)
47 /* PTWs cacheable, inner WBWA shareable, outer WBWA not shareable */
48 #define TTB_FLAGS_SMP   (TTB_IRGN_WBWA|TTB_S|TTB_RGN_OC_WBWA)
49 #define PMD_FLAGS_SMP   (PMD_SECT_WBWA|PMD_SECT_S)
51 ENTRY(cpu_v7_proc_init)
52         mov     pc, lr
53 ENDPROC(cpu_v7_proc_init)
55 ENTRY(cpu_v7_proc_fin)
56         mrc     p15, 0, r0, c1, c0, 0           @ ctrl register
57         bic     r0, r0, #0x1000                 @ ...i............
58         bic     r0, r0, #0x0006                 @ .............ca.
59         mcr     p15, 0, r0, c1, c0, 0           @ disable caches
60         mov     pc, lr
61 ENDPROC(cpu_v7_proc_fin)
64  *      cpu_v7_reset(loc)
65  *
66  *      Perform a soft reset of the system.  Put the CPU into the
67  *      same state as it would be if it had been reset, and branch
68  *      to what would be the reset vector.
69  *
70  *      - loc   - location to jump to for soft reset
71  */
72         .align  5
73 ENTRY(cpu_v7_reset)
74         mov     pc, r0
75 ENDPROC(cpu_v7_reset)
78  *      cpu_v7_do_idle()
79  *
80  *      Idle the processor (eg, wait for interrupt).
81  *
82  *      IRQs are already disabled.
83  */
84 ENTRY(cpu_v7_do_idle)
85         dsb                                     @ WFI may enter a low-power mode
86         wfi
87         mov     pc, lr
88 ENDPROC(cpu_v7_do_idle)
90 ENTRY(cpu_v7_dcache_clean_area)
91 #ifndef TLB_CAN_READ_FROM_L1_CACHE
92         dcache_line_size r2, r3
93 1:      mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
94         add     r0, r0, r2
95         subs    r1, r1, r2
96         bhi     1b
97         dsb
98 #endif
99         mov     pc, lr
100 ENDPROC(cpu_v7_dcache_clean_area)
103  *      cpu_v7_switch_mm(pgd_phys, tsk)
105  *      Set the translation table base pointer to be pgd_phys
107  *      - pgd_phys - physical address of new TTB
109  *      It is assumed that:
110  *      - we are not using split page tables
111  */
112 ENTRY(cpu_v7_switch_mm)
113 #ifdef CONFIG_MMU
114         ldr     r1, [r1, #MM_CONTEXT_ID]        @ get mm->context.id
115         mov     r2, #0
116         and     r3, r1, #0xff
117         mov     r3, r3, lsl #(48 - 32)          @ ASID
118         mcrr    p15, 0, r0, r3, c2              @ set TTB 0
119         isb
120 #endif
121         mov     pc, lr
122 ENDPROC(cpu_v7_switch_mm)
125  *      cpu_v7_set_pte_ext(ptep, pte)
127  *      Set a level 2 translation table entry.
129  *      - ptep  - pointer to level 2 translation table entry
130  *                (hardware version is stored at +2048 bytes)
131  *      - pte   - PTE value to store
132  *      - ext   - value for extended PTE bits
133  */
134 ENTRY(cpu_v7_set_pte_ext)
135 #ifdef CONFIG_MMU
136         tst     r2, #L_PTE_PRESENT
137         beq     1f
138         tst     r3, #1 << (55 - 32)             @ L_PTE_DIRTY
139         orreq   r2, #L_PTE_RDONLY
140 1:      strd    r2, r3, [r0]
141         mcr     p15, 0, r0, c7, c10, 1          @ flush_pte
142 #endif
143         mov     pc, lr
144 ENDPROC(cpu_v7_set_pte_ext)
146 cpu_v7_name:
147         .ascii  "ARMv7 Processor"
148         .align
150         /*
151          * Memory region attributes for LPAE (defined in pgtable-3level.h):
152          *
153          *   n = AttrIndx[2:0]
154          *
155          *                      n       MAIR
156          *   UNCACHED           000     00000000
157          *   BUFFERABLE         001     01000100
158          *   DEV_WC             001     01000100
159          *   WRITETHROUGH       010     10101010
160          *   WRITEBACK          011     11101110
161          *   DEV_CACHED         011     11101110
162          *   DEV_SHARED         100     00000100
163          *   DEV_NONSHARED      100     00000100
164          *   unused             101
165          *   unused             110
166          *   WRITEALLOC         111     11111111
167          */
168 .equ    MAIR0,  0xeeaa4400                      @ MAIR0
169 .equ    MAIR1,  0xff000004                      @ MAIR1
171 /* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */
172 .globl  cpu_v7_suspend_size
173 .equ    cpu_v7_suspend_size, 4 * 10
174 #ifdef CONFIG_PM_SLEEP
175 ENTRY(cpu_v7_do_suspend)
176         stmfd   sp!, {r4 - r11, lr}
177         mrc     p15, 0, r4, c13, c0, 0  @ FCSE/PID
178         mrc     p15, 0, r5, c13, c0, 1  @ Context ID
179         mrc     p15, 0, r6, c3, c0, 0   @ Domain ID
180         mrrc    p15, 0, r7, r8, c2      @ TTB 0
181         mrrc    p15, 1, r2, r3, c2      @ TTB 1
182         mrc     p15, 0, r9, c1, c0, 0   @ Control register
183         mrc     p15, 0, r10, c1, c0, 1  @ Auxiliary control register
184         mrc     p15, 0, r11, c1, c0, 2  @ Co-processor access control
185         stmia   r0, {r2 - r11}
186         ldmfd   sp!, {r4 - r11, pc}
187 ENDPROC(cpu_v7_do_suspend)
189 ENTRY(cpu_v7_do_resume)
190         mov     ip, #0
191         mcr     p15, 0, ip, c8, c7, 0   @ invalidate TLBs
192         mcr     p15, 0, ip, c7, c5, 0   @ invalidate I cache
193         ldmia   r0, {r2 - r11}
194         mcr     p15, 0, r4, c13, c0, 0  @ FCSE/PID
195         mcr     p15, 0, r5, c13, c0, 1  @ Context ID
196         mcr     p15, 0, r6, c3, c0, 0   @ Domain ID
197         mcrr    p15, 0, r7, r8, c2      @ TTB 0
198         mcrr    p15, 1, r2, r3, c2      @ TTB 1
199         mcr     p15, 0, ip, c2, c0, 2   @ TTB control register
200         mcr     p15, 0, r10, c1, c0, 1  @ Auxiliary control register
201         mcr     p15, 0, r11, c1, c0, 2  @ Co-processor access control
202         ldr     r4, =MAIR0
203         ldr     r5, =MAIR1
204         mcr     p15, 0, r4, c10, c2, 0  @ write MAIR0
205         mcr     p15, 0, r5, c10, c2, 1  @ write MAIR1
206         isb
207         mov     r0, r9                  @ control register
208         mov     r2, r7, lsr #14         @ get TTB0 base
209         mov     r2, r2, lsl #14
210         ldr     r3, cpu_resume_l1_flags
211         b       cpu_resume_mmu
212 ENDPROC(cpu_v7_do_resume)
213 cpu_resume_l1_flags:
214         ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP)
215         ALT_UP(.long  PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP)
216 #else
217 #define cpu_v7_do_suspend       0
218 #define cpu_v7_do_resume        0
219 #endif
221         __CPUINIT
224  *      __v7_setup
226  *      Initialise TLB, Caches, and MMU state ready to switch the MMU
227  *      on. Return in r0 the new CP15 C1 control register setting.
229  *      This should be able to cover all ARMv7 cores with LPAE.
231  *      It is assumed that:
232  *      - cache type register is implemented
233  */
234 __v7_ca15mp_setup:
235         mov     r10, #0
237 #ifdef CONFIG_SMP
238         ALT_SMP(mrc     p15, 0, r0, c1, c0, 1)
239         ALT_UP(mov      r0, #(1 << 6))          @ fake it for UP
240         tst     r0, #(1 << 6)                   @ SMP/nAMP mode enabled?
241         orreq   r0, r0, #(1 << 6)               @ Enable SMP/nAMP mode
242         orreq   r0, r0, r10                     @ Enable CPU-specific SMP bits
243         mcreq   p15, 0, r0, c1, c0, 1
244 #endif
245 __v7_setup:
246         adr     r12, __v7_setup_stack           @ the local stack
247         stmia   r12, {r0-r5, r7, r9, r11, lr}
248         bl      v7_flush_dcache_all
249         ldmia   r12, {r0-r5, r7, r9, r11, lr}
251         mov     r10, #0
252         mcr     p15, 0, r10, c7, c5, 0          @ I+BTB cache invalidate
253         dsb
254 #ifdef CONFIG_MMU
255         mcr     p15, 0, r10, c8, c7, 0          @ invalidate I + D TLBs
256         mov     r5, #TTB_EAE
257         ALT_SMP(orr     r5, r5, #TTB_FLAGS_SMP)
258         ALT_SMP(orr     r5, r5, #TTB_FLAGS_SMP << 16)
259         ALT_UP(orr      r5, r5, #TTB_FLAGS_UP)
260         ALT_UP(orr      r5, r5, #TTB_FLAGS_UP << 16)
261         mrc     p15, 0, r10, c2, c0, 2
262         orr     r10, r10, r5
263 #if PHYS_OFFSET <= PAGE_OFFSET
264         /*
265          * TTBR0/TTBR1 split (PAGE_OFFSET):
266          *   0x40000000: T0SZ = 2, T1SZ = 0 (not used)
267          *   0x80000000: T0SZ = 0, T1SZ = 1
268          *   0xc0000000: T0SZ = 0, T1SZ = 2
269          *
270          * Only use this feature if PAGE_OFFSET <=  PAGE_OFFSET, otherwise
271          * booting secondary CPUs would end up using TTBR1 for the identity
272          * mapping set up in TTBR0.
273          */
274         orr     r10, r10, #(((PAGE_OFFSET >> 30) - 1) << 16)    @ TTBCR.T1SZ
275 #endif
276         mcr     p15, 0, r10, c2, c0, 2          @ TTB control register
277         mov     r5, #0
278 #if defined CONFIG_VMSPLIT_2G
279         /* PAGE_OFFSET == 0x80000000, T1SZ == 1 */
280         add     r6, r8, #1 << 4                 @ skip two L1 entries
281 #elif defined CONFIG_VMSPLIT_3G
282         /* PAGE_OFFSET == 0xc0000000, T1SZ == 2 */
283         add     r6, r8, #4096 * (1 + 3)         @ only L2 used, skip pgd+3*pmd
284 #else
285         mov     r6, r8
286 #endif
287         mcrr    p15, 1, r6, r5, c2              @ load TTBR1
288         ldr     r5, =MAIR0
289         ldr     r6, =MAIR1
290         mcr     p15, 0, r5, c10, c2, 0          @ write MAIR0
291         mcr     p15, 0, r6, c10, c2, 1          @ write MAIR1
292 #endif
293         adr     r5, v7_crval
294         ldmia   r5, {r5, r6}
295 #ifdef CONFIG_CPU_ENDIAN_BE8
296         orr     r6, r6, #1 << 25                @ big-endian page tables
297 #endif
298 #ifdef CONFIG_SWP_EMULATE
299         orr     r5, r5, #(1 << 10)              @ set SW bit in "clear"
300         bic     r6, r6, #(1 << 10)              @ clear it in "mmuset"
301 #endif
302         mrc     p15, 0, r0, c1, c0, 0           @ read control register
303         bic     r0, r0, r5                      @ clear bits them
304         orr     r0, r0, r6                      @ set them
305  THUMB( orr     r0, r0, #1 << 30        )       @ Thumb exceptions
306         mov     pc, lr                          @ return to head.S:__ret
307 ENDPROC(__v7_setup)
309         /*   AT
310          *  TFR   EV X F   IHD LR    S
311          * .EEE ..EE PUI. .TAT 4RVI ZWRS BLDP WCAM
312          * rxxx rrxx xxx0 0101 xxxx xxxx x111 xxxx < forced
313          *   11    0 110    1  0011 1100 .111 1101 < we want
314          */
315         .type   v7_crval, #object
316 v7_crval:
317         crval   clear=0x0120c302, mmuset=0x30c23c7d, ucset=0x00c01c7c
319 __v7_setup_stack:
320         .space  4 * 11                          @ 11 registers
322         __INITDATA
324         .type   v7_processor_functions, #object
325 ENTRY(v7_processor_functions)
326         .word   v7_early_abort
327         .word   v7_pabort
328         .word   cpu_v7_proc_init
329         .word   cpu_v7_proc_fin
330         .word   cpu_v7_reset
331         .word   cpu_v7_do_idle
332         .word   cpu_v7_dcache_clean_area
333         .word   cpu_v7_switch_mm
334         .word   cpu_v7_set_pte_ext
335         .word   0
336         .word   0
337         .word   0
338         .size   v7_processor_functions, . - v7_processor_functions
340         .section ".rodata"
342         .type   cpu_arch_name, #object
343 cpu_arch_name:
344         .asciz  "armv7"
345         .size   cpu_arch_name, . - cpu_arch_name
347         .type   cpu_elf_name, #object
348 cpu_elf_name:
349         .asciz  "v7"
350         .size   cpu_elf_name, . - cpu_elf_name
351         .align
353         .section ".proc.info.init", #alloc, #execinstr
355         .type   __v7_ca15mp_proc_info, #object
356 __v7_ca15mp_proc_info:
357         .long   0x410fc0f0              @ Required ID value
358         .long   0xff0ffff0              @ Mask for ID
359         ALT_SMP(.long \
360                 PMD_TYPE_SECT | \
361                 PMD_SECT_AP_WRITE | \
362                 PMD_SECT_AP_READ | \
363                 PMD_SECT_AF | \
364                 PMD_FLAGS_SMP)
365         ALT_UP(.long \
366                 PMD_TYPE_SECT | \
367                 PMD_SECT_AP_WRITE | \
368                 PMD_SECT_AP_READ | \
369                 PMD_SECT_AF | \
370                 PMD_FLAGS_UP)
371                 /* PMD_SECT_XN is set explicitly in head.S for LPAE */
372         .long   PMD_TYPE_SECT | \
373                 PMD_SECT_XN | \
374                 PMD_SECT_AP_WRITE | \
375                 PMD_SECT_AP_READ | \
376                 PMD_SECT_AF
377         b       __v7_ca15mp_setup
378         .long   cpu_arch_name
379         .long   cpu_elf_name
380         .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_TLS
381         .long   cpu_v7_name
382         .long   v7_processor_functions
383         .long   v7wbi_tlb_fns
384         .long   v6_user_fns
385         .long   v7_cache_fns
386         .size   __v7_ca15mp_proc_info, . - __v7_ca15mp_proc_info
388         /*
389          * Match any ARMv7 processor core.
390          */
391         .type   __v7_proc_info, #object
392 __v7_proc_info:
393         .long   0x000f0000              @ Required ID value
394         .long   0x000f0000              @ Mask for ID
395         ALT_SMP(.long \
396                 PMD_TYPE_SECT | \
397                 PMD_SECT_AP_WRITE | \
398                 PMD_SECT_AP_READ | \
399                 PMD_SECT_AF | \
400                 PMD_FLAGS_SMP)
401         ALT_UP(.long \
402                 PMD_TYPE_SECT | \
403                 PMD_SECT_AP_WRITE | \
404                 PMD_SECT_AP_READ | \
405                 PMD_SECT_AF | \
406                 PMD_FLAGS_UP)
407                 /* PMD_SECT_XN is set explicitly in head.S for LPAE */
408         .long   PMD_TYPE_SECT | \
409                 PMD_SECT_XN | \
410                 PMD_SECT_AP_WRITE | \
411                 PMD_SECT_AP_READ | \
412                 PMD_SECT_AF
413         W(b)    __v7_setup
414         .long   cpu_arch_name
415         .long   cpu_elf_name
416         .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_TLS
417         .long   cpu_v7_name
418         .long   v7_processor_functions
419         .long   v7wbi_tlb_fns
420         .long   v6_user_fns
421         .long   v7_cache_fns
422         .size   __v7_proc_info, . - __v7_proc_info