]>
Commit | Line | Data |
---|---|---|
5a0015d6 CZ |
1 | /* |
2 | * arch/xtensa/kernel/head.S | |
3 | * | |
4 | * Xtensa Processor startup code. | |
5 | * | |
6 | * This file is subject to the terms and conditions of the GNU General Public | |
7 | * License. See the file "COPYING" in the main directory of this archive | |
8 | * for more details. | |
9 | * | |
2d1c645c | 10 | * Copyright (C) 2001 - 2008 Tensilica Inc. |
5a0015d6 CZ |
11 | * |
12 | * Chris Zankel <chris@zankel.net> | |
13 | * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca> | |
14 | * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com> | |
15 | * Kevin Chea | |
16 | */ | |
17 | ||
5a0015d6 CZ |
18 | #include <asm/processor.h> |
19 | #include <asm/page.h> | |
173d6681 | 20 | #include <asm/cacheasm.h> |
c622b29d | 21 | #include <asm/initialize_mmu.h> |
5a0015d6 | 22 | |
0ebdcb4d | 23 | #include <linux/init.h> |
adba09f0 CZ |
24 | #include <linux/linkage.h> |
25 | ||
5a0015d6 CZ |
26 | /* |
27 | * This module contains the entry code for kernel images. It performs the | |
28 | * minimal setup needed to call the generic C routines. | |
29 | * | |
30 | * Prerequisites: | |
31 | * | |
32 | * - The kernel image has been loaded to the actual address where it was | |
33 | * compiled to. | |
34 | * - a2 contains either 0 or a pointer to a list of boot parameters. | |
35 | * (see setup.c for more details) | |
36 | * | |
37 | */ | |
38 | ||
5a0015d6 CZ |
39 | /* |
40 | * _start | |
41 | * | |
42 | * The bootloader passes a pointer to a list of boot parameters in a2. | |
43 | */ | |
44 | ||
45 | /* The first bytes of the kernel image must be an instruction, so we | |
46 | * manually allocate and define the literal constant we need for a jx | |
47 | * instruction. | |
48 | */ | |
49 | ||
0ebdcb4d | 50 | __HEAD |
e85e335f MF |
51 | .begin no-absolute-literals |
52 | ||
d1538c46 CZ |
53 | ENTRY(_start) |
54 | ||
e85e335f MF |
55 | /* Preserve the pointer to the boot parameter list in EXCSAVE_1 */ |
56 | wsr a2, excsave1 | |
57 | _j _SetupMMU | |
58 | ||
59 | .align 4 | |
60 | .literal_position | |
61 | .Lstartup: | |
62 | .word _startup | |
63 | ||
5a0015d6 | 64 | .align 4 |
e85e335f MF |
65 | .global _SetupMMU |
66 | _SetupMMU: | |
67 | Offset = _SetupMMU - _start | |
68 | ||
69 | #ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX | |
70 | initialize_mmu | |
c5a771d0 MF |
71 | #if defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY |
72 | rsr a2, excsave1 | |
73 | movi a3, 0x08000000 | |
74 | bgeu a2, a3, 1f | |
75 | movi a3, 0xd0000000 | |
76 | add a2, a2, a3 | |
77 | wsr a2, excsave1 | |
78 | 1: | |
79 | #endif | |
e85e335f MF |
80 | #endif |
81 | .end no-absolute-literals | |
82 | ||
83 | l32r a0, .Lstartup | |
5a0015d6 CZ |
84 | jx a0 |
85 | ||
d1538c46 CZ |
86 | ENDPROC(_start) |
87 | ||
e85e335f MF |
88 | __INIT |
89 | .literal_position | |
d1538c46 CZ |
90 | |
91 | ENTRY(_startup) | |
5a0015d6 CZ |
92 | |
93 | /* Disable interrupts and exceptions. */ | |
94 | ||
173d6681 | 95 | movi a0, LOCKLEVEL |
bc5378fc | 96 | wsr a0, ps |
5a0015d6 | 97 | |
5a0015d6 CZ |
98 | /* Start with a fresh windowbase and windowstart. */ |
99 | ||
100 | movi a1, 1 | |
101 | movi a0, 0 | |
bc5378fc MF |
102 | wsr a1, windowstart |
103 | wsr a0, windowbase | |
5a0015d6 CZ |
104 | rsync |
105 | ||
106 | /* Set a0 to 0 for the remaining initialization. */ | |
107 | ||
108 | movi a0, 0 | |
109 | ||
110 | /* Clear debugging registers. */ | |
111 | ||
112 | #if XCHAL_HAVE_DEBUG | |
d83ff0bb | 113 | #if XCHAL_NUM_IBREAK > 0 |
bc5378fc | 114 | wsr a0, ibreakenable |
d83ff0bb | 115 | #endif |
bc5378fc | 116 | wsr a0, icount |
5a0015d6 | 117 | movi a1, 15 |
bc5378fc | 118 | wsr a0, icountlevel |
5a0015d6 | 119 | |
173d6681 CZ |
120 | .set _index, 0 |
121 | .rept XCHAL_NUM_DBREAK - 1 | |
bc5378fc | 122 | wsr a0, SREG_DBREAKC + _index |
173d6681 CZ |
123 | .set _index, _index + 1 |
124 | .endr | |
5a0015d6 CZ |
125 | #endif |
126 | ||
127 | /* Clear CCOUNT (not really necessary, but nice) */ | |
128 | ||
bc5378fc | 129 | wsr a0, ccount # not really necessary, but nice |
5a0015d6 CZ |
130 | |
131 | /* Disable zero-loops. */ | |
132 | ||
133 | #if XCHAL_HAVE_LOOPS | |
bc5378fc | 134 | wsr a0, lcount |
5a0015d6 CZ |
135 | #endif |
136 | ||
137 | /* Disable all timers. */ | |
138 | ||
173d6681 | 139 | .set _index, 0 |
79fcf52b | 140 | .rept XCHAL_NUM_TIMERS |
bc5378fc | 141 | wsr a0, SREG_CCOMPARE + _index |
173d6681 CZ |
142 | .set _index, _index + 1 |
143 | .endr | |
5a0015d6 CZ |
144 | |
145 | /* Interrupt initialization. */ | |
146 | ||
147 | movi a2, XCHAL_INTTYPE_MASK_SOFTWARE | XCHAL_INTTYPE_MASK_EXTERN_EDGE | |
bc5378fc MF |
148 | wsr a0, intenable |
149 | wsr a2, intclear | |
5a0015d6 CZ |
150 | |
151 | /* Disable coprocessors. */ | |
152 | ||
eab5e7a7 | 153 | #if XCHAL_HAVE_CP |
bc5378fc | 154 | wsr a0, cpenable |
5a0015d6 CZ |
155 | #endif |
156 | ||
2d1c645c | 157 | /* Set PS.INTLEVEL=LOCKLEVEL, PS.WOE=0, kernel stack, PS.EXCM=0 |
5a0015d6 CZ |
158 | * |
159 | * Note: PS.EXCM must be cleared before using any loop | |
160 | * instructions; otherwise, they are silently disabled, and | |
161 | * at most one iteration of the loop is executed. | |
162 | */ | |
163 | ||
2d1c645c | 164 | movi a1, LOCKLEVEL |
bc5378fc | 165 | wsr a1, ps |
5a0015d6 CZ |
166 | rsync |
167 | ||
168 | /* Initialize the caches. | |
173d6681 | 169 | * a2, a3 are just working registers (clobbered). |
5a0015d6 CZ |
170 | */ |
171 | ||
173d6681 CZ |
172 | #if XCHAL_DCACHE_LINE_LOCKABLE |
173 | ___unlock_dcache_all a2 a3 | |
174 | #endif | |
175 | ||
176 | #if XCHAL_ICACHE_LINE_LOCKABLE | |
177 | ___unlock_icache_all a2 a3 | |
178 | #endif | |
179 | ||
180 | ___invalidate_dcache_all a2 a3 | |
181 | ___invalidate_icache_all a2 a3 | |
182 | ||
183 | isync | |
5a0015d6 CZ |
184 | |
185 | /* Unpack data sections | |
186 | * | |
187 | * The linker script used to build the Linux kernel image | |
188 | * creates a table located at __boot_reloc_table_start | |
189 | * that contans the information what data needs to be unpacked. | |
190 | * | |
191 | * Uses a2-a7. | |
192 | */ | |
193 | ||
194 | movi a2, __boot_reloc_table_start | |
195 | movi a3, __boot_reloc_table_end | |
196 | ||
197 | 1: beq a2, a3, 3f # no more entries? | |
198 | l32i a4, a2, 0 # start destination (in RAM) | |
199 | l32i a5, a2, 4 # end desination (in RAM) | |
200 | l32i a6, a2, 8 # start source (in ROM) | |
201 | addi a2, a2, 12 # next entry | |
202 | beq a4, a5, 1b # skip, empty entry | |
203 | beq a4, a6, 1b # skip, source and dest. are the same | |
204 | ||
205 | 2: l32i a7, a6, 0 # load word | |
206 | addi a6, a6, 4 | |
207 | s32i a7, a4, 0 # store word | |
208 | addi a4, a4, 4 | |
209 | bltu a4, a5, 2b | |
210 | j 1b | |
211 | ||
212 | 3: | |
213 | /* All code and initialized data segments have been copied. | |
214 | * Now clear the BSS segment. | |
215 | */ | |
216 | ||
8b307f9c CZ |
217 | movi a2, __bss_start # start of BSS |
218 | movi a3, __bss_stop # end of BSS | |
5a0015d6 | 219 | |
173d6681 | 220 | __loopt a2, a3, a4, 2 |
5a0015d6 | 221 | s32i a0, a2, 0 |
173d6681 | 222 | __endla a2, a4, 4 |
5a0015d6 CZ |
223 | |
224 | #if XCHAL_DCACHE_IS_WRITEBACK | |
225 | ||
226 | /* After unpacking, flush the writeback cache to memory so the | |
227 | * instructions/data are available. | |
228 | */ | |
229 | ||
173d6681 | 230 | ___flush_dcache_all a2 a3 |
5a0015d6 | 231 | #endif |
e85e335f MF |
232 | memw |
233 | isync | |
234 | ___invalidate_icache_all a2 a3 | |
235 | isync | |
5a0015d6 CZ |
236 | |
237 | /* Setup stack and enable window exceptions (keep irqs disabled) */ | |
238 | ||
239 | movi a1, init_thread_union | |
240 | addi a1, a1, KERNEL_STACK_SIZE | |
241 | ||
2d1c645c MG |
242 | movi a2, (1 << PS_WOE_BIT) | LOCKLEVEL |
243 | # WOE=1, INTLEVEL=LOCKLEVEL, UM=0 | |
bc5378fc | 244 | wsr a2, ps # (enable reg-windows; progmode stack) |
5a0015d6 CZ |
245 | rsync |
246 | ||
247 | /* Set up EXCSAVE[DEBUGLEVEL] to point to the Debug Exception Handler.*/ | |
248 | ||
249 | movi a2, debug_exception | |
bc5378fc | 250 | wsr a2, SREG_EXCSAVE + XCHAL_DEBUGLEVEL |
5a0015d6 CZ |
251 | |
252 | /* Set up EXCSAVE[1] to point to the exc_table. */ | |
253 | ||
254 | movi a6, exc_table | |
bc5378fc | 255 | xsr a6, excsave1 |
5a0015d6 CZ |
256 | |
257 | /* init_arch kick-starts the linux kernel */ | |
258 | ||
259 | movi a4, init_arch | |
260 | callx4 a4 | |
261 | ||
262 | movi a4, start_kernel | |
263 | callx4 a4 | |
264 | ||
265 | should_never_return: | |
266 | j should_never_return | |
267 | ||
d1538c46 | 268 | ENDPROC(_startup) |
5a0015d6 | 269 | |
adba09f0 CZ |
270 | /* |
271 | * BSS section | |
272 | */ | |
273 | ||
02b7da37 | 274 | __PAGE_ALIGNED_BSS |
e5083a63 | 275 | #ifdef CONFIG_MMU |
adba09f0 CZ |
276 | ENTRY(swapper_pg_dir) |
277 | .fill PAGE_SIZE, 1, 0 | |
d1538c46 | 278 | END(swapper_pg_dir) |
e5083a63 | 279 | #endif |
adba09f0 CZ |
280 | ENTRY(empty_zero_page) |
281 | .fill PAGE_SIZE, 1, 0 | |
d1538c46 | 282 | END(empty_zero_page) |