blob: ee6f152987350033fdf69586b8fe01314f5c28eb [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/arch/arm/mm/proc-v6.S
3 *
4 * Copyright (C) 2001 Deep Blue Solutions Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This is the "shell" of the ARMv6 processor support.
11 */
12#include <linux/linkage.h>
13#include <asm/assembler.h>
Sam Ravnborge6ae7442005-09-09 21:08:59 +020014#include <asm/asm-offsets.h>
Russell King862184f2005-11-07 21:05:42 +000015#include <asm/hardware/arm_scu.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070016#include <asm/procinfo.h>
Russell King74945c82006-03-16 14:44:36 +000017#include <asm/pgtable-hwdef.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include <asm/pgtable.h>
19
20#include "proc-macros.S"
21
22#define D_CACHE_LINE_SIZE 32
23
Russell King3747b362006-03-27 16:59:07 +010024#define TTB_C (1 << 0)
25#define TTB_S (1 << 1)
26#define TTB_IMP (1 << 2)
27#define TTB_RGN_NC (0 << 3)
28#define TTB_RGN_WBWA (1 << 3)
29#define TTB_RGN_WT (2 << 3)
30#define TTB_RGN_WB (3 << 3)
31
Linus Torvalds1da177e2005-04-16 15:20:36 -070032 .macro cpsie, flags
33 .ifc \flags, f
34 .long 0xf1080040
35 .exitm
36 .endif
37 .ifc \flags, i
38 .long 0xf1080080
39 .exitm
40 .endif
41 .ifc \flags, if
42 .long 0xf10800c0
43 .exitm
44 .endif
45 .err
46 .endm
47
48 .macro cpsid, flags
49 .ifc \flags, f
50 .long 0xf10c0040
51 .exitm
52 .endif
53 .ifc \flags, i
54 .long 0xf10c0080
55 .exitm
56 .endif
57 .ifc \flags, if
58 .long 0xf10c00c0
59 .exitm
60 .endif
61 .err
62 .endm
63
64ENTRY(cpu_v6_proc_init)
65 mov pc, lr
66
67ENTRY(cpu_v6_proc_fin)
Tony Lindgren67c5587a2005-10-19 23:00:56 +010068 stmfd sp!, {lr}
69 cpsid if @ disable interrupts
70 bl v6_flush_kern_cache_all
71 mrc p15, 0, r0, c1, c0, 0 @ ctrl register
72 bic r0, r0, #0x1000 @ ...i............
73 bic r0, r0, #0x0006 @ .............ca.
74 mcr p15, 0, r0, c1, c0, 0 @ disable caches
75 ldmfd sp!, {pc}
Linus Torvalds1da177e2005-04-16 15:20:36 -070076
77/*
78 * cpu_v6_reset(loc)
79 *
80 * Perform a soft reset of the system. Put the CPU into the
81 * same state as it would be if it had been reset, and branch
82 * to what would be the reset vector.
83 *
84 * - loc - location to jump to for soft reset
85 *
86 * It is assumed that:
87 */
88 .align 5
89ENTRY(cpu_v6_reset)
90 mov pc, r0
91
92/*
93 * cpu_v6_do_idle()
94 *
95 * Idle the processor (eg, wait for interrupt).
96 *
97 * IRQs are already disabled.
98 */
99ENTRY(cpu_v6_do_idle)
100 mcr p15, 0, r1, c7, c0, 4 @ wait for interrupt
101 mov pc, lr
102
103ENTRY(cpu_v6_dcache_clean_area)
104#ifndef TLB_CAN_READ_FROM_L1_CACHE
1051: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
106 add r0, r0, #D_CACHE_LINE_SIZE
107 subs r1, r1, #D_CACHE_LINE_SIZE
108 bhi 1b
109#endif
110 mov pc, lr
111
112/*
113 * cpu_arm926_switch_mm(pgd_phys, tsk)
114 *
115 * Set the translation table base pointer to be pgd_phys
116 *
117 * - pgd_phys - physical address of new TTB
118 *
119 * It is assumed that:
120 * - we are not using split page tables
121 */
122ENTRY(cpu_v6_switch_mm)
123 mov r2, #0
124 ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id
Russell Kingcd03adb2005-11-07 10:10:28 +0000125#ifdef CONFIG_SMP
Russell King3747b362006-03-27 16:59:07 +0100126 orr r0, r0, #TTB_RGN_WBWA|TTB_S @ mark PTWs shared, outer cacheable
Russell Kingcd03adb2005-11-07 10:10:28 +0000127#endif
Russell Kingd93742f52005-08-15 16:53:38 +0100128 mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129 mcr p15, 0, r2, c7, c10, 4 @ drain write buffer
130 mcr p15, 0, r0, c2, c0, 0 @ set TTB 0
131 mcr p15, 0, r1, c13, c0, 1 @ set context ID
132 mov pc, lr
133
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134/*
135 * cpu_v6_set_pte(ptep, pte)
136 *
137 * Set a level 2 translation table entry.
138 *
139 * - ptep - pointer to level 2 translation table entry
140 * (hardware version is stored at -1024 bytes)
141 * - pte - PTE value to store
142 *
143 * Permissions:
144 * YUWD APX AP1 AP0 SVC User
145 * 0xxx 0 0 0 no acc no acc
146 * 100x 1 0 1 r/o no acc
147 * 10x0 1 0 1 r/o no acc
148 * 1011 0 0 1 r/w no acc
Catalin Marinas79042f02005-06-24 21:27:39 +0100149 * 110x 0 1 0 r/w r/o
150 * 11x0 0 1 0 r/w r/o
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 * 1111 0 1 1 r/w r/w
152 */
153ENTRY(cpu_v6_set_pte)
154 str r1, [r0], #-2048 @ linux version
155
Russell Kingcd03adb2005-11-07 10:10:28 +0000156 bic r2, r1, #0x000003f0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 bic r2, r2, #0x00000003
Russell King1b9749e2005-08-10 16:15:32 +0100158 orr r2, r2, #PTE_EXT_AP0 | 2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159
160 tst r1, #L_PTE_WRITE
161 tstne r1, #L_PTE_DIRTY
Russell King1b9749e2005-08-10 16:15:32 +0100162 orreq r2, r2, #PTE_EXT_APX
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163
164 tst r1, #L_PTE_USER
Russell King6626a702005-08-10 16:18:35 +0100165 orrne r2, r2, #PTE_EXT_AP1
Russell King1b9749e2005-08-10 16:15:32 +0100166 tstne r2, #PTE_EXT_APX
167 bicne r2, r2, #PTE_EXT_APX | PTE_EXT_AP0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168
169 tst r1, #L_PTE_YOUNG
Russell King1b9749e2005-08-10 16:15:32 +0100170 biceq r2, r2, #PTE_EXT_APX | PTE_EXT_AP_MASK
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171
Russell King3747b362006-03-27 16:59:07 +0100172 tst r1, #L_PTE_EXEC
173 orreq r2, r2, #PTE_EXT_XN
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174
175 tst r1, #L_PTE_PRESENT
176 moveq r2, #0
177
178 str r2, [r0]
179 mcr p15, 0, r0, c7, c10, 1 @ flush_pte
180 mov pc, lr
181
182
183
184
185cpu_v6_name:
186 .asciz "Some Random V6 Processor"
187 .align
188
189 .section ".text.init", #alloc, #execinstr
190
191/*
192 * __v6_setup
193 *
194 * Initialise TLB, Caches, and MMU state ready to switch the MMU
195 * on. Return in r0 the new CP15 C1 control register setting.
196 *
197 * We automatically detect if we have a Harvard cache, and use the
198 * Harvard cache control instructions insead of the unified cache
199 * control instructions.
200 *
201 * This should be able to cover all ARMv6 cores.
202 *
203 * It is assumed that:
204 * - cache type register is implemented
205 */
206__v6_setup:
Russell King862184f2005-11-07 21:05:42 +0000207#ifdef CONFIG_SMP
208 /* Set up the SCU on core 0 only */
209 mrc p15, 0, r0, c0, c0, 5 @ CPU core number
210 ands r0, r0, #15
211 moveq r0, #0x10000000 @ SCU_BASE
212 orreq r0, r0, #0x00100000
213 ldreq r5, [r0, #SCU_CTRL]
214 orreq r5, r5, #1
215 streq r5, [r0, #SCU_CTRL]
216
217#ifndef CONFIG_CPU_DCACHE_DISABLE
218 mrc p15, 0, r0, c1, c0, 1 @ Enable SMP/nAMP mode
219 orr r0, r0, #0x20
220 mcr p15, 0, r0, c1, c0, 1
221#endif
222#endif
223
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 mov r0, #0
225 mcr p15, 0, r0, c7, c14, 0 @ clean+invalidate D cache
226 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
227 mcr p15, 0, r0, c7, c15, 0 @ clean+invalidate cache
228 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
229 mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs
230 mcr p15, 0, r0, c2, c0, 2 @ TTB control register
Russell Kingcd03adb2005-11-07 10:10:28 +0000231#ifdef CONFIG_SMP
Russell King3747b362006-03-27 16:59:07 +0100232 orr r4, r4, #TTB_RGN_WBWA|TTB_S @ mark PTWs shared, outer cacheable
Russell Kingcd03adb2005-11-07 10:10:28 +0000233#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 mcr p15, 0, r4, c2, c0, 1 @ load TTB1
235#ifdef CONFIG_VFP
236 mrc p15, 0, r0, c1, c0, 2
Catalin Marinasd1d890e2005-07-06 23:06:03 +0100237 orr r0, r0, #(0xf << 20)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 mcr p15, 0, r0, c1, c0, 2 @ Enable full access to VFP
239#endif
240 mrc p15, 0, r0, c1, c0, 0 @ read control register
241 ldr r5, v6_cr1_clear @ get mask for bits to clear
242 bic r0, r0, r5 @ clear bits them
243 ldr r5, v6_cr1_set @ get mask for bits to set
244 orr r0, r0, r5 @ set them
245 mov pc, lr @ return to head.S:__ret
246
247 /*
248 * V X F I D LR
249 * .... ...E PUI. .T.T 4RVI ZFRS BLDP WCAM
250 * rrrr rrrx xxx0 0101 xxxx xxxx x111 xxxx < forced
251 * 0 110 0011 1.00 .111 1101 < we want
252 */
253 .type v6_cr1_clear, #object
254 .type v6_cr1_set, #object
255v6_cr1_clear:
256 .word 0x01e0fb7f
257v6_cr1_set:
258 .word 0x00c0387d
259
260 .type v6_processor_functions, #object
261ENTRY(v6_processor_functions)
262 .word v6_early_abort
263 .word cpu_v6_proc_init
264 .word cpu_v6_proc_fin
265 .word cpu_v6_reset
266 .word cpu_v6_do_idle
267 .word cpu_v6_dcache_clean_area
268 .word cpu_v6_switch_mm
269 .word cpu_v6_set_pte
270 .size v6_processor_functions, . - v6_processor_functions
271
272 .type cpu_arch_name, #object
273cpu_arch_name:
274 .asciz "armv6"
275 .size cpu_arch_name, . - cpu_arch_name
276
277 .type cpu_elf_name, #object
278cpu_elf_name:
279 .asciz "v6"
280 .size cpu_elf_name, . - cpu_elf_name
281 .align
282
Ben Dooks02b7dd12005-09-20 16:35:03 +0100283 .section ".proc.info.init", #alloc, #execinstr
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284
285 /*
286 * Match any ARMv6 processor core.
287 */
288 .type __v6_proc_info, #object
289__v6_proc_info:
290 .long 0x0007b000
291 .long 0x0007f000
292 .long PMD_TYPE_SECT | \
293 PMD_SECT_BUFFERABLE | \
294 PMD_SECT_CACHEABLE | \
295 PMD_SECT_AP_WRITE | \
296 PMD_SECT_AP_READ
297 b __v6_setup
298 .long cpu_arch_name
299 .long cpu_elf_name
300 .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_VFP|HWCAP_EDSP|HWCAP_JAVA
301 .long cpu_v6_name
302 .long v6_processor_functions
303 .long v6wbi_tlb_fns
304 .long v6_user_fns
305 .long v6_cache_fns
306 .size __v6_proc_info, . - __v6_proc_info