2
* linux/arch/arm/mm/proc-v7.S
4
* Copyright (C) 2001 Deep Blue Solutions Ltd.
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.
10
* This is the "shell" of the ARMv7 processor support.
12
#include <linux/init.h>
13
#include <linux/linkage.h>
14
#include <asm/assembler.h>
15
#include <asm/asm-offsets.h>
16
#include <asm/hwcap.h>
17
#include <asm/pgtable-hwdef.h>
18
#include <asm/pgtable.h>
20
#include "proc-macros.S"
22
#define TTB_S (1 << 1)
23
#define TTB_RGN_NC (0 << 3)
24
#define TTB_RGN_OC_WBWA (1 << 3)
25
#define TTB_RGN_OC_WT (2 << 3)
26
#define TTB_RGN_OC_WB (3 << 3)
27
#define TTB_NOS (1 << 5)
28
#define TTB_IRGN_NC ((0 << 0) | (0 << 6))
29
#define TTB_IRGN_WBWA ((0 << 0) | (1 << 6))
30
#define TTB_IRGN_WT ((1 << 0) | (0 << 6))
31
#define TTB_IRGN_WB ((1 << 0) | (1 << 6))
33
/* PTWs cacheable, inner WB not shareable, outer WB not shareable */
34
#define TTB_FLAGS_UP TTB_IRGN_WB|TTB_RGN_OC_WB
35
#define PMD_FLAGS_UP PMD_SECT_WB
37
/* PTWs cacheable, inner WBWA shareable, outer WBWA not shareable */
38
#define TTB_FLAGS_SMP TTB_IRGN_WBWA|TTB_S|TTB_NOS|TTB_RGN_OC_WBWA
39
#define PMD_FLAGS_SMP PMD_SECT_WBWA|PMD_SECT_S
41
ENTRY(cpu_v7_proc_init)
43
ENDPROC(cpu_v7_proc_init)
45
ENTRY(cpu_v7_proc_fin)
46
mrc p15, 0, r0, c1, c0, 0 @ ctrl register
47
bic r0, r0, #0x1000 @ ...i............
48
bic r0, r0, #0x0006 @ .............ca.
49
mcr p15, 0, r0, c1, c0, 0 @ disable caches
51
ENDPROC(cpu_v7_proc_fin)
56
* Perform a soft reset of the system. Put the CPU into the
57
* same state as it would be if it had been reset, and branch
58
* to what would be the reset vector.
60
* - loc - location to jump to for soft reset
62
* This code must be executed using a flat identity mapping with
67
mrc p15, 0, r1, c1, c0, 0 @ ctrl register
68
bic r1, r1, #0x1 @ ...............m
69
THUMB( bic r1, r1, #1 << 30 ) @ SCTLR.TE (Thumb exceptions)
70
mcr p15, 0, r1, c1, c0, 0 @ disable MMU
78
* Idle the processor (eg, wait for interrupt).
80
* IRQs are already disabled.
83
dsb @ WFI may enter a low-power mode
86
ENDPROC(cpu_v7_do_idle)
88
ENTRY(cpu_v7_dcache_clean_area)
89
#ifndef TLB_CAN_READ_FROM_L1_CACHE
90
dcache_line_size r2, r3
91
1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
98
ENDPROC(cpu_v7_dcache_clean_area)
101
* cpu_v7_switch_mm(pgd_phys, tsk)
103
* Set the translation table base pointer to be pgd_phys
105
* - pgd_phys - physical address of new TTB
107
* It is assumed that:
108
* - we are not using split page tables
110
ENTRY(cpu_v7_switch_mm)
113
ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id
114
ALT_SMP(orr r0, r0, #TTB_FLAGS_SMP)
115
ALT_UP(orr r0, r0, #TTB_FLAGS_UP)
116
#ifdef CONFIG_ARM_ERRATA_430973
117
mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
119
#ifdef CONFIG_ARM_ERRATA_754322
122
mcr p15, 0, r2, c13, c0, 1 @ set reserved context ID
124
1: mcr p15, 0, r0, c2, c0, 0 @ set TTB 0
126
#ifdef CONFIG_ARM_ERRATA_754322
129
mcr p15, 0, r1, c13, c0, 1 @ set context ID
133
ENDPROC(cpu_v7_switch_mm)
136
* cpu_v7_set_pte_ext(ptep, pte)
138
* Set a level 2 translation table entry.
140
* - ptep - pointer to level 2 translation table entry
141
* (hardware version is stored at +2048 bytes)
142
* - pte - PTE value to store
143
* - ext - value for extended PTE bits
145
ENTRY(cpu_v7_set_pte_ext)
147
str r1, [r0] @ linux version
149
bic r3, r1, #0x000003f0
150
bic r3, r3, #PTE_TYPE_MASK
152
orr r3, r3, #PTE_EXT_AP0 | 2
155
orrne r3, r3, #PTE_EXT_TEX(1)
157
eor r1, r1, #L_PTE_DIRTY
158
tst r1, #L_PTE_RDONLY | L_PTE_DIRTY
159
orrne r3, r3, #PTE_EXT_APX
162
orrne r3, r3, #PTE_EXT_AP1
163
#ifdef CONFIG_CPU_USE_DOMAINS
164
@ allow kernel read/write access to read-only user pages
165
tstne r3, #PTE_EXT_APX
166
bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
170
orrne r3, r3, #PTE_EXT_XN
173
tstne r1, #L_PTE_PRESENT
176
ARM( str r3, [r0, #2048]! )
177
THUMB( add r0, r0, #2048 )
178
THUMB( str r3, [r0] )
179
mcr p15, 0, r0, c7, c10, 1 @ flush_pte
182
ENDPROC(cpu_v7_set_pte_ext)
184
string cpu_v7_name, "ARMv7 Processor"
188
* Memory region attributes with SCTLR.TRE=1
191
* TR = PRRR[2n+1:2n] - memory type
192
* IR = NMRR[2n+1:2n] - inner cacheable property
193
* OR = NMRR[2n+17:2n+16] - outer cacheable property
197
* BUFFERABLE 001 10 00 00
198
* WRITETHROUGH 010 10 10 10
199
* WRITEBACK 011 10 11 11
201
* WRITEALLOC 111 10 01 01
203
* DEV_NONSHARED 100 01
209
* DS0 = PRRR[16] = 0 - device shareable property
210
* DS1 = PRRR[17] = 1 - device shareable property
211
* NS0 = PRRR[18] = 0 - normal shareable property
212
* NS1 = PRRR[19] = 1 - normal shareable property
213
* NOS = PRRR[24+n] = 1 - not outer shareable
215
.equ PRRR, 0xff0a81a8
216
.equ NMRR, 0x40e040e0
218
/* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */
219
.globl cpu_v7_suspend_size
220
.equ cpu_v7_suspend_size, 4 * 7
221
#ifdef CONFIG_ARM_CPU_SUSPEND
222
ENTRY(cpu_v7_do_suspend)
223
stmfd sp!, {r4 - r10, lr}
224
mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
225
mrc p15, 0, r5, c13, c0, 3 @ User r/o thread ID
227
mrc p15, 0, r6, c3, c0, 0 @ Domain ID
228
mrc p15, 0, r7, c2, c0, 1 @ TTB 1
229
mrc p15, 0, r8, c1, c0, 0 @ Control register
230
mrc p15, 0, r9, c1, c0, 1 @ Auxiliary control register
231
mrc p15, 0, r10, c1, c0, 2 @ Co-processor access control
233
ldmfd sp!, {r4 - r10, pc}
234
ENDPROC(cpu_v7_do_suspend)
236
ENTRY(cpu_v7_do_resume)
238
mcr p15, 0, ip, c8, c7, 0 @ invalidate TLBs
239
mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
240
mcr p15, 0, ip, c13, c0, 1 @ set reserved context ID
242
mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID
243
mcr p15, 0, r5, c13, c0, 3 @ User r/o thread ID
245
mcr p15, 0, r6, c3, c0, 0 @ Domain ID
246
ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP)
247
ALT_UP(orr r1, r1, #TTB_FLAGS_UP)
248
mcr p15, 0, r1, c2, c0, 0 @ TTB 0
249
mcr p15, 0, r7, c2, c0, 1 @ TTB 1
250
mcr p15, 0, ip, c2, c0, 2 @ TTB control register
251
mrc p15, 0, r4, c1, c0, 1 @ Read Auxiliary control register
252
teq r4, r9 @ Is it already set?
253
mcrne p15, 0, r9, c1, c0, 1 @ No, so write it
254
mcr p15, 0, r10, c1, c0, 2 @ Co-processor access control
257
mcr p15, 0, r4, c10, c2, 0 @ write PRRR
258
mcr p15, 0, r5, c10, c2, 1 @ write NMRR
261
mov r0, r8 @ control register
263
ENDPROC(cpu_v7_do_resume)
271
* Initialise TLB, Caches, and MMU state ready to switch the MMU
272
* on. Return in r0 the new CP15 C1 control register setting.
274
* We automatically detect if we have a Harvard cache, and use the
275
* Harvard cache control instructions insead of the unified cache
276
* control instructions.
278
* This should be able to cover all ARMv7 cores.
280
* It is assumed that:
281
* - cache type register is implemented
285
mov r10, #(1 << 0) @ TLB ops broadcasting
291
ALT_SMP(mrc p15, 0, r0, c1, c0, 1)
292
ALT_UP(mov r0, #(1 << 6)) @ fake it for UP
293
tst r0, #(1 << 6) @ SMP/nAMP mode enabled?
294
orreq r0, r0, #(1 << 6) @ Enable SMP/nAMP mode
295
orreq r0, r0, r10 @ Enable CPU-specific SMP bits
296
mcreq p15, 0, r0, c1, c0, 1
299
adr r12, __v7_setup_stack @ the local stack
300
stmia r12, {r0-r5, r7, r9, r11, lr}
301
bl v7_flush_dcache_all
302
ldmia r12, {r0-r5, r7, r9, r11, lr}
304
mrc p15, 0, r0, c0, c0, 0 @ read main ID register
305
and r10, r0, #0xff000000 @ ARM?
308
and r5, r0, #0x00f00000 @ variant
309
and r6, r0, #0x0000000f @ revision
310
orr r6, r6, r5, lsr #20-4 @ combine variant and revision
311
ubfx r0, r0, #4, #12 @ primary part number
313
/* Cortex-A8 Errata */
314
ldr r10, =0x00000c08 @ Cortex-A8 primary part number
317
#ifdef CONFIG_ARM_ERRATA_430973
318
teq r5, #0x00100000 @ only present in r1p*
319
mrceq p15, 0, r10, c1, c0, 1 @ read aux control register
320
orreq r10, r10, #(1 << 6) @ set IBE to 1
321
mcreq p15, 0, r10, c1, c0, 1 @ write aux control register
323
#ifdef CONFIG_ARM_ERRATA_458693
324
teq r6, #0x20 @ only present in r2p0
325
mrceq p15, 0, r10, c1, c0, 1 @ read aux control register
326
orreq r10, r10, #(1 << 5) @ set L1NEON to 1
327
orreq r10, r10, #(1 << 9) @ set PLDNOP to 1
328
mcreq p15, 0, r10, c1, c0, 1 @ write aux control register
330
#ifdef CONFIG_ARM_ERRATA_460075
331
teq r6, #0x20 @ only present in r2p0
332
mrceq p15, 1, r10, c9, c0, 2 @ read L2 cache aux ctrl register
334
orreq r10, r10, #(1 << 22) @ set the Write Allocate disable bit
335
mcreq p15, 1, r10, c9, c0, 2 @ write the L2 cache aux ctrl register
339
/* Cortex-A9 Errata */
340
2: ldr r10, =0x00000c09 @ Cortex-A9 primary part number
343
#ifdef CONFIG_ARM_ERRATA_742230
344
cmp r6, #0x22 @ only present up to r2p2
345
mrcle p15, 0, r10, c15, c0, 1 @ read diagnostic register
346
orrle r10, r10, #1 << 4 @ set bit #4
347
mcrle p15, 0, r10, c15, c0, 1 @ write diagnostic register
349
#ifdef CONFIG_ARM_ERRATA_742231
350
teq r6, #0x20 @ present in r2p0
351
teqne r6, #0x21 @ present in r2p1
352
teqne r6, #0x22 @ present in r2p2
353
mrceq p15, 0, r10, c15, c0, 1 @ read diagnostic register
354
orreq r10, r10, #1 << 12 @ set bit #12
355
orreq r10, r10, #1 << 22 @ set bit #22
356
mcreq p15, 0, r10, c15, c0, 1 @ write diagnostic register
358
#ifdef CONFIG_ARM_ERRATA_743622
359
teq r6, #0x20 @ present in r2p0
360
teqne r6, #0x21 @ present in r2p1
361
teqne r6, #0x22 @ present in r2p2
362
mrceq p15, 0, r10, c15, c0, 1 @ read diagnostic register
363
orreq r10, r10, #1 << 6 @ set bit #6
364
mcreq p15, 0, r10, c15, c0, 1 @ write diagnostic register
366
#if defined(CONFIG_ARM_ERRATA_751472) && defined(CONFIG_SMP)
367
ALT_SMP(cmp r6, #0x30) @ present prior to r3p0
369
mrclt p15, 0, r10, c15, c0, 1 @ read diagnostic register
370
orrlt r10, r10, #1 << 11 @ set bit #11
371
mcrlt p15, 0, r10, c15, c0, 1 @ write diagnostic register
377
mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate
381
mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs
382
mcr p15, 0, r10, c2, c0, 2 @ TTB control register
383
ALT_SMP(orr r4, r4, #TTB_FLAGS_SMP)
384
ALT_UP(orr r4, r4, #TTB_FLAGS_UP)
385
ALT_SMP(orr r8, r8, #TTB_FLAGS_SMP)
386
ALT_UP(orr r8, r8, #TTB_FLAGS_UP)
387
mcr p15, 0, r8, c2, c0, 1 @ load TTB1
390
mcr p15, 0, r5, c10, c2, 0 @ write PRRR
391
mcr p15, 0, r6, c10, c2, 1 @ write NMRR
395
#ifdef CONFIG_CPU_ENDIAN_BE8
396
orr r6, r6, #1 << 25 @ big-endian page tables
398
#ifdef CONFIG_SWP_EMULATE
399
orr r5, r5, #(1 << 10) @ set SW bit in "clear"
400
bic r6, r6, #(1 << 10) @ clear it in "mmuset"
402
mrc p15, 0, r0, c1, c0, 0 @ read control register
403
bic r0, r0, r5 @ clear bits them
404
orr r0, r0, r6 @ set them
405
THUMB( orr r0, r0, #1 << 30 ) @ Thumb exceptions
406
mov pc, lr @ return to head.S:__ret
410
* TFR EV X F I D LR S
411
* .EEE ..EE PUI. .T.T 4RVI ZWRS BLDP WCAM
412
* rxxx rrxx xxx0 0101 xxxx xxxx x111 xxxx < forced
413
* 1 0 110 0011 1100 .111 1101 < we want
415
.type v7_crval, #object
417
crval clear=0x0120c302, mmuset=0x10c03c7d, ucset=0x00c01c7c
420
.space 4 * 11 @ 11 registers
424
@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
425
define_processor_functions v7, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
429
string cpu_arch_name, "armv7"
430
string cpu_elf_name, "v7"
433
.section ".proc.info.init", #alloc, #execinstr
436
* Standard v7 proc info content
438
.macro __v7_proc initfunc, mm_mmuflags = 0, io_mmuflags = 0, hwcaps = 0
439
ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \
440
PMD_FLAGS_SMP | \mm_mmuflags)
441
ALT_UP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \
442
PMD_FLAGS_UP | \mm_mmuflags)
443
.long PMD_TYPE_SECT | PMD_SECT_XN | PMD_SECT_AP_WRITE | \
444
PMD_SECT_AP_READ | \io_mmuflags
448
.long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT | \
449
HWCAP_EDSP | HWCAP_TLS | \hwcaps
451
.long v7_processor_functions
458
* ARM Ltd. Cortex A5 processor.
460
.type __v7_ca5mp_proc_info, #object
461
__v7_ca5mp_proc_info:
464
__v7_proc __v7_ca5mp_setup
465
.size __v7_ca5mp_proc_info, . - __v7_ca5mp_proc_info
468
* ARM Ltd. Cortex A9 processor.
470
.type __v7_ca9mp_proc_info, #object
471
__v7_ca9mp_proc_info:
474
__v7_proc __v7_ca9mp_setup
475
.size __v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info
478
* ARM Ltd. Cortex A15 processor.
480
.type __v7_ca15mp_proc_info, #object
481
__v7_ca15mp_proc_info:
484
__v7_proc __v7_ca15mp_setup, hwcaps = HWCAP_IDIV
485
.size __v7_ca15mp_proc_info, . - __v7_ca15mp_proc_info
488
* Match any ARMv7 processor core.
490
.type __v7_proc_info, #object
492
.long 0x000f0000 @ Required ID value
493
.long 0x000f0000 @ Mask for ID
495
.size __v7_proc_info, . - __v7_proc_info