head-nommu.S 7.5 KB
Newer Older
Hyok S. Choi's avatar
Hyok S. Choi committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
 *  linux/arch/arm/kernel/head-nommu.S
 *
 *  Copyright (C) 1994-2002 Russell King
 *  Copyright (C) 2003-2006 Hyok S. Choi
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 *  Common kernel startup code (non-paged MM)
 *
 */
#include <linux/linkage.h>
#include <linux/init.h>

#include <asm/assembler.h>
#include <asm/ptrace.h>
19
#include <asm/asm-offsets.h>
20
#include <asm/memory.h>
21
#include <asm/cp15.h>
22
#include <asm/thread_info.h>
23
#include <asm/v7m.h>
24
#include <asm/mpu.h>
25
#include <asm/page.h>
Hyok S. Choi's avatar
Hyok S. Choi committed
26
27
28
29
30
31
32
33
34
35
36
37
38

/*
 * Kernel startup entry point.
 * ---------------------------
 *
 * This is normally called from the decompressor code.  The requirements
 * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
 * r1 = machine nr.
 *
 * See linux/arch/arm/tools/mach-types for the complete list of machine
 * numbers for r1.
 *
 */
39

40
	__HEAD
41
42
43
44
45
46

#ifdef CONFIG_CPU_THUMBONLY
	.thumb
ENTRY(stext)
#else
	.arm
Hyok S. Choi's avatar
Hyok S. Choi committed
47
ENTRY(stext)
48

49
 THUMB(	badr	r9, 1f		)	@ Kernel is always entered in ARM.
50
51
52
 THUMB(	bx	r9		)	@ If this is a Thumb-2 kernel,
 THUMB(	.thumb			)	@ switch to Thumb now.
 THUMB(1:			)
53
#endif
54

55
	setmode	PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode
Hyok S. Choi's avatar
Hyok S. Choi committed
56
						@ and irqs disabled
57
#if defined(CONFIG_CPU_CP15)
Hyok S. Choi's avatar
Hyok S. Choi committed
58
	mrc	p15, 0, r9, c0, c0		@ get processor id
59
60
61
62
63
#elif defined(CONFIG_CPU_V7M)
	ldr	r9, =BASEADDR_V7M_SCB
	ldr	r9, [r9, V7M_SCB_CPUID]
#else
	ldr	r9, =CONFIG_PROCESSOR_ID
64
#endif
Hyok S. Choi's avatar
Hyok S. Choi committed
65
66
67
68
	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid
	movs	r10, r5				@ invalid processor (r5=0)?
	beq	__error_p				@ yes, error 'p'

69
70
#ifdef CONFIG_ARM_MPU
	/* Calculate the size of a region covering just the kernel */
71
	ldr	r5, =PLAT_PHYS_OFFSET		@ Region start: PHYS_OFFSET
72
73
74
75
76
77
78
79
	ldr     r6, =(_end)			@ Cover whole kernel
	sub	r6, r6, r5			@ Minimum size of region to map
	clz	r6, r6				@ Region size must be 2^N...
	rsb	r6, r6, #31			@ ...so round up region size
	lsl	r6, r6, #MPU_RSR_SZ		@ Put size in right field
	orr	r6, r6, #(1 << MPU_RSR_EN)	@ Set region enabled bit
	bl	__setup_mpu
#endif
80

81
	badr	lr, 1f				@ return (PIC) address
Russell King's avatar
Russell King committed
82
83
84
	ldr	r12, [r10, #PROCINFO_INITFUNC]
	add	r12, r12, r10
	ret	r12
85
86
1:	bl	__after_proc_init
	b	__mmap_switched
87
ENDPROC(stext)
Hyok S. Choi's avatar
Hyok S. Choi committed
88

89
#ifdef CONFIG_SMP
90
	.text
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
ENTRY(secondary_startup)
	/*
	 * Common entry point for secondary CPUs.
	 *
	 * Ensure that we're in SVC mode, and IRQs are disabled.  Lookup
	 * the processor type - there is no need to check the machine type
	 * as it has already been validated by the primary processor.
	 */
	setmode	PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9
#ifndef CONFIG_CPU_CP15
	ldr	r9, =CONFIG_PROCESSOR_ID
#else
	mrc	p15, 0, r9, c0, c0		@ get processor id
#endif
	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid
	movs	r10, r5				@ invalid processor?
	beq	__error_p			@ yes, error 'p'

109
	ldr	r7, __secondary_data
110
111
112
113
114
115
116

#ifdef CONFIG_ARM_MPU
	/* Use MPU region info supplied by __cpu_up */
	ldr	r6, [r7]			@ get secondary_data.mpu_szr
	bl      __setup_mpu			@ Initialize the MPU
#endif

117
	badr	lr, 1f				@ return (PIC) address
Russell King's avatar
Russell King committed
118
119
120
	ldr	r12, [r10, #PROCINFO_INITFUNC]
	add	r12, r12, r10
	ret	r12
121
1:	bl	__after_proc_init
122
	ldr	sp, [r7, #12]			@ set up the stack pointer
123
124
	mov	fp, #0
	b	secondary_start_kernel
125
ENDPROC(secondary_startup)
126
127
128
129
130
131

	.type	__secondary_data, %object
__secondary_data:
	.long	secondary_data
#endif /* CONFIG_SMP */

Hyok S. Choi's avatar
Hyok S. Choi committed
132
133
134
135
/*
 * Set the Control Register and Read the process ID.
 */
__after_proc_init:
136
#ifdef CONFIG_CPU_CP15
137
138
139
140
	/*
	 * CP15 system control register value returned in r0 from
	 * the CPU init function.
	 */
141
#if defined(CONFIG_ALIGNMENT_TRAP) && __LINUX_ARM_ARCH__ < 6
Hyok S. Choi's avatar
Hyok S. Choi committed
142
143
144
145
146
147
148
149
150
151
152
153
154
155
	orr	r0, r0, #CR_A
#else
	bic	r0, r0, #CR_A
#endif
#ifdef CONFIG_CPU_DCACHE_DISABLE
	bic	r0, r0, #CR_C
#endif
#ifdef CONFIG_CPU_BPREDICT_DISABLE
	bic	r0, r0, #CR_Z
#endif
#ifdef CONFIG_CPU_ICACHE_DISABLE
	bic	r0, r0, #CR_I
#endif
	mcr	p15, 0, r0, c1, c0, 0		@ write control reg
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#elif defined (CONFIG_CPU_V7M)
	/* For V7M systems we want to modify the CCR similarly to the SCTLR */
#ifdef CONFIG_CPU_DCACHE_DISABLE
	bic	r0, r0, #V7M_SCB_CCR_DC
#endif
#ifdef CONFIG_CPU_BPREDICT_DISABLE
	bic	r0, r0, #V7M_SCB_CCR_BP
#endif
#ifdef CONFIG_CPU_ICACHE_DISABLE
	bic	r0, r0, #V7M_SCB_CCR_IC
#endif
	movw	r3, #:lower16:(BASEADDR_V7M_SCB + V7M_SCB_CCR)
	movt	r3, #:upper16:(BASEADDR_V7M_SCB + V7M_SCB_CCR)
	str	r0, [r3]
#endif /* CONFIG_CPU_CP15 elif CONFIG_CPU_V7M */
171
	ret	lr
172
ENDPROC(__after_proc_init)
173
	.ltorg
Hyok S. Choi's avatar
Hyok S. Choi committed
174

175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#ifdef CONFIG_ARM_MPU


/* Set which MPU region should be programmed */
.macro set_region_nr tmp, rgnr
	mov	\tmp, \rgnr			@ Use static region numbers
	mcr	p15, 0, \tmp, c6, c2, 0		@ Write RGNR
.endm

/* Setup a single MPU region, either D or I side (D-side for unified) */
.macro setup_region bar, acr, sr, side = MPU_DATA_SIDE
	mcr	p15, 0, \bar, c6, c1, (0 + \side)	@ I/DRBAR
	mcr	p15, 0, \acr, c6, c1, (4 + \side)	@ I/DRACR
	mcr	p15, 0, \sr, c6, c1, (2 + \side)		@ I/DRSR
.endm

/*
 * Setup the MPU and initial MPU Regions. We create the following regions:
 * Region 0: Use this for probing the MPU details, so leave disabled.
 * Region 1: Background region - covers the whole of RAM as strongly ordered
 * Region 2: Normal, Shared, cacheable for RAM. From PHYS_OFFSET, size from r6
196
 * Region 3: Normal, shared, inaccessible from PL0 to protect the vectors page
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
 *
 * r6: Value to be written to DRSR (and IRSR if required) for MPU_RAM_REGION
*/

ENTRY(__setup_mpu)

	/* Probe for v7 PMSA compliance */
	mrc	p15, 0, r0, c0, c1, 4		@ Read ID_MMFR0
	and	r0, r0, #(MMFR0_PMSA)		@ PMSA field
	teq	r0, #(MMFR0_PMSAv7)		@ PMSA v7
	bne	__error_p			@ Fail: ARM_MPU on NOT v7 PMSA

	/* Determine whether the D/I-side memory map is unified. We set the
	 * flags here and continue to use them for the rest of this function */
	mrc	p15, 0, r0, c0, c0, 4		@ MPUIR
	ands	r5, r0, #MPUIR_DREGION_SZMASK	@ 0 size d region => No MPU
	beq	__error_p			@ Fail: ARM_MPU and no MPU
	tst	r0, #MPUIR_nU			@ MPUIR_nU = 0 for unified

	/* Setup second region first to free up r6 */
	set_region_nr r0, #MPU_RAM_REGION
	isb
	/* Full access from PL0, PL1, shared for CONFIG_SMP, cacheable */
220
	ldr	r0, =PLAT_PHYS_OFFSET		@ RAM starts at PHYS_OFFSET
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
	ldr	r5,=(MPU_AP_PL1RW_PL0RW | MPU_RGN_NORMAL)

	setup_region r0, r5, r6, MPU_DATA_SIDE	@ PHYS_OFFSET, shared, enabled
	beq	1f				@ Memory-map not unified
	setup_region r0, r5, r6, MPU_INSTR_SIDE @ PHYS_OFFSET, shared, enabled
1:	isb

	/* First/background region */
	set_region_nr r0, #MPU_BG_REGION
	isb
	/* Execute Never,  strongly ordered, inaccessible to PL0, rw PL1  */
	mov	r0, #0				@ BG region starts at 0x0
	ldr	r5,=(MPU_ACR_XN | MPU_RGN_STRONGLY_ORDERED | MPU_AP_PL1RW_PL0NA)
	mov	r6, #MPU_RSR_ALL_MEM		@ 4GB region, enabled

	setup_region r0, r5, r6, MPU_DATA_SIDE	@ 0x0, BG region, enabled
	beq	2f				@ Memory-map not unified
	setup_region r0, r5, r6, MPU_INSTR_SIDE @ 0x0, BG region, enabled
2:	isb

241
242
243
244
245
246
247
	/* Vectors region */
	set_region_nr r0, #MPU_VECTORS_REGION
	isb
	/* Shared, inaccessible to PL0, rw PL1 */
	mov	r0, #CONFIG_VECTORS_BASE	@ Cover from VECTORS_BASE
	ldr	r5,=(MPU_AP_PL1RW_PL0NA | MPU_RGN_NORMAL)
	/* Writing N to bits 5:1 (RSR_SZ) --> region size 2^N+1 */
248
	mov	r6, #(((2 * PAGE_SHIFT - 1) << MPU_RSR_SZ) | 1 << MPU_RSR_EN)
249
250
251
252
253
254

	setup_region r0, r5, r6, MPU_DATA_SIDE	@ VECTORS_BASE, PL0 NA, enabled
	beq	3f				@ Memory-map not unified
	setup_region r0, r5, r6, MPU_INSTR_SIDE	@ VECTORS_BASE, PL0 NA, enabled
3:	isb

255
256
257
258
259
260
	/* Enable the MPU */
	mrc	p15, 0, r0, c1, c0, 0		@ Read SCTLR
	bic     r0, r0, #CR_BR			@ Disable the 'default mem-map'
	orr	r0, r0, #CR_M			@ Set SCTRL.M (MPU on)
	mcr	p15, 0, r0, c1, c0, 0		@ Enable MPU
	isb
261
	ret	lr
262
263
ENDPROC(__setup_mpu)
#endif
Hyok S. Choi's avatar
Hyok S. Choi committed
264
#include "head-common.S"