]>
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> |
f615136c | 22 | #include <asm/mxregs.h> |
5a0015d6 | 23 | |
0ebdcb4d | 24 | #include <linux/init.h> |
adba09f0 CZ |
25 | #include <linux/linkage.h> |
26 | ||
5a0015d6 CZ |
27 | /* |
28 | * This module contains the entry code for kernel images. It performs the | |
29 | * minimal setup needed to call the generic C routines. | |
30 | * | |
31 | * Prerequisites: | |
32 | * | |
33 | * - The kernel image has been loaded to the actual address where it was | |
34 | * compiled to. | |
35 | * - a2 contains either 0 or a pointer to a list of boot parameters. | |
36 | * (see setup.c for more details) | |
37 | * | |
38 | */ | |
39 | ||
5a0015d6 CZ |
40 | /* |
41 | * _start | |
42 | * | |
43 | * The bootloader passes a pointer to a list of boot parameters in a2. | |
44 | */ | |
45 | ||
46 | /* The first bytes of the kernel image must be an instruction, so we | |
47 | * manually allocate and define the literal constant we need for a jx | |
48 | * instruction. | |
49 | */ | |
50 | ||
0ebdcb4d | 51 | __HEAD |
e85e335f MF |
52 | .begin no-absolute-literals |
53 | ||
d1538c46 CZ |
54 | ENTRY(_start) |
55 | ||
e85e335f MF |
56 | /* Preserve the pointer to the boot parameter list in EXCSAVE_1 */ |
57 | wsr a2, excsave1 | |
f615136c | 58 | _j _SetupOCD |
e85e335f MF |
59 | |
60 | .align 4 | |
61 | .literal_position | |
62 | .Lstartup: | |
63 | .word _startup | |
64 | ||
5a0015d6 | 65 | .align 4 |
f615136c MF |
66 | _SetupOCD: |
67 | /* | |
68 | * Initialize WB, WS, and clear PS.EXCM (to allow loop instructions). | |
69 | * Set Interrupt Level just below XCHAL_DEBUGLEVEL to allow | |
70 | * xt-gdb to single step via DEBUG exceptions received directly | |
71 | * by ocd. | |
72 | */ | |
73 | movi a1, 1 | |
74 | movi a0, 0 | |
75 | wsr a1, windowstart | |
76 | wsr a0, windowbase | |
77 | rsync | |
78 | ||
79 | movi a1, LOCKLEVEL | |
80 | wsr a1, ps | |
81 | rsync | |
82 | ||
e85e335f MF |
83 | .global _SetupMMU |
84 | _SetupMMU: | |
85 | Offset = _SetupMMU - _start | |
86 | ||
87 | #ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX | |
88 | initialize_mmu | |
c5a771d0 MF |
89 | #if defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY |
90 | rsr a2, excsave1 | |
91 | movi a3, 0x08000000 | |
92 | bgeu a2, a3, 1f | |
93 | movi a3, 0xd0000000 | |
94 | add a2, a2, a3 | |
95 | wsr a2, excsave1 | |
96 | 1: | |
97 | #endif | |
e85e335f MF |
98 | #endif |
99 | .end no-absolute-literals | |
100 | ||
101 | l32r a0, .Lstartup | |
5a0015d6 CZ |
102 | jx a0 |
103 | ||
d1538c46 CZ |
104 | ENDPROC(_start) |
105 | ||
49b424fe | 106 | __REF |
e85e335f | 107 | .literal_position |
d1538c46 CZ |
108 | |
109 | ENTRY(_startup) | |
5a0015d6 | 110 | |
5a0015d6 CZ |
111 | /* Set a0 to 0 for the remaining initialization. */ |
112 | ||
113 | movi a0, 0 | |
114 | ||
53490121 MF |
115 | #if XCHAL_HAVE_VECBASE |
116 | movi a2, VECBASE_RESET_VADDR | |
117 | wsr a2, vecbase | |
118 | #endif | |
119 | ||
5a0015d6 CZ |
120 | /* Clear debugging registers. */ |
121 | ||
122 | #if XCHAL_HAVE_DEBUG | |
d83ff0bb | 123 | #if XCHAL_NUM_IBREAK > 0 |
bc5378fc | 124 | wsr a0, ibreakenable |
d83ff0bb | 125 | #endif |
bc5378fc | 126 | wsr a0, icount |
5a0015d6 | 127 | movi a1, 15 |
bc5378fc | 128 | wsr a0, icountlevel |
5a0015d6 | 129 | |
173d6681 CZ |
130 | .set _index, 0 |
131 | .rept XCHAL_NUM_DBREAK - 1 | |
bc5378fc | 132 | wsr a0, SREG_DBREAKC + _index |
173d6681 CZ |
133 | .set _index, _index + 1 |
134 | .endr | |
5a0015d6 CZ |
135 | #endif |
136 | ||
137 | /* Clear CCOUNT (not really necessary, but nice) */ | |
138 | ||
bc5378fc | 139 | wsr a0, ccount # not really necessary, but nice |
5a0015d6 CZ |
140 | |
141 | /* Disable zero-loops. */ | |
142 | ||
143 | #if XCHAL_HAVE_LOOPS | |
bc5378fc | 144 | wsr a0, lcount |
5a0015d6 CZ |
145 | #endif |
146 | ||
147 | /* Disable all timers. */ | |
148 | ||
173d6681 | 149 | .set _index, 0 |
79fcf52b | 150 | .rept XCHAL_NUM_TIMERS |
bc5378fc | 151 | wsr a0, SREG_CCOMPARE + _index |
173d6681 CZ |
152 | .set _index, _index + 1 |
153 | .endr | |
5a0015d6 CZ |
154 | |
155 | /* Interrupt initialization. */ | |
156 | ||
157 | movi a2, XCHAL_INTTYPE_MASK_SOFTWARE | XCHAL_INTTYPE_MASK_EXTERN_EDGE | |
bc5378fc MF |
158 | wsr a0, intenable |
159 | wsr a2, intclear | |
5a0015d6 CZ |
160 | |
161 | /* Disable coprocessors. */ | |
162 | ||
eab5e7a7 | 163 | #if XCHAL_HAVE_CP |
bc5378fc | 164 | wsr a0, cpenable |
5a0015d6 CZ |
165 | #endif |
166 | ||
5a0015d6 | 167 | /* Initialize the caches. |
173d6681 | 168 | * a2, a3 are just working registers (clobbered). |
5a0015d6 CZ |
169 | */ |
170 | ||
173d6681 CZ |
171 | #if XCHAL_DCACHE_LINE_LOCKABLE |
172 | ___unlock_dcache_all a2 a3 | |
173 | #endif | |
174 | ||
175 | #if XCHAL_ICACHE_LINE_LOCKABLE | |
176 | ___unlock_icache_all a2 a3 | |
177 | #endif | |
178 | ||
179 | ___invalidate_dcache_all a2 a3 | |
180 | ___invalidate_icache_all a2 a3 | |
181 | ||
182 | isync | |
5a0015d6 | 183 | |
f615136c MF |
184 | #ifdef CONFIG_HAVE_SMP |
185 | movi a2, CCON # MX External Register to Configure Cache | |
186 | movi a3, 1 | |
187 | wer a3, a2 | |
188 | #endif | |
189 | ||
190 | /* Setup stack and enable window exceptions (keep irqs disabled) */ | |
191 | ||
192 | movi a1, start_info | |
193 | l32i a1, a1, 0 | |
194 | ||
195 | movi a2, (1 << PS_WOE_BIT) | LOCKLEVEL | |
196 | # WOE=1, INTLEVEL=LOCKLEVEL, UM=0 | |
197 | wsr a2, ps # (enable reg-windows; progmode stack) | |
198 | rsync | |
199 | ||
200 | /* Set up EXCSAVE[DEBUGLEVEL] to point to the Debug Exception Handler.*/ | |
201 | ||
202 | movi a2, debug_exception | |
203 | wsr a2, SREG_EXCSAVE + XCHAL_DEBUGLEVEL | |
204 | ||
205 | #ifdef CONFIG_SMP | |
206 | /* | |
207 | * Notice that we assume with SMP that cores have PRID | |
208 | * supported by the cores. | |
209 | */ | |
210 | rsr a2, prid | |
211 | bnez a2, .Lboot_secondary | |
212 | ||
213 | #endif /* CONFIG_SMP */ | |
214 | ||
5a0015d6 CZ |
215 | /* Unpack data sections |
216 | * | |
217 | * The linker script used to build the Linux kernel image | |
218 | * creates a table located at __boot_reloc_table_start | |
219 | * that contans the information what data needs to be unpacked. | |
220 | * | |
221 | * Uses a2-a7. | |
222 | */ | |
223 | ||
224 | movi a2, __boot_reloc_table_start | |
225 | movi a3, __boot_reloc_table_end | |
226 | ||
227 | 1: beq a2, a3, 3f # no more entries? | |
228 | l32i a4, a2, 0 # start destination (in RAM) | |
229 | l32i a5, a2, 4 # end desination (in RAM) | |
230 | l32i a6, a2, 8 # start source (in ROM) | |
231 | addi a2, a2, 12 # next entry | |
232 | beq a4, a5, 1b # skip, empty entry | |
233 | beq a4, a6, 1b # skip, source and dest. are the same | |
234 | ||
235 | 2: l32i a7, a6, 0 # load word | |
236 | addi a6, a6, 4 | |
237 | s32i a7, a4, 0 # store word | |
238 | addi a4, a4, 4 | |
239 | bltu a4, a5, 2b | |
240 | j 1b | |
241 | ||
242 | 3: | |
243 | /* All code and initialized data segments have been copied. | |
244 | * Now clear the BSS segment. | |
245 | */ | |
246 | ||
8b307f9c CZ |
247 | movi a2, __bss_start # start of BSS |
248 | movi a3, __bss_stop # end of BSS | |
5a0015d6 | 249 | |
173d6681 | 250 | __loopt a2, a3, a4, 2 |
5a0015d6 | 251 | s32i a0, a2, 0 |
173d6681 | 252 | __endla a2, a4, 4 |
5a0015d6 CZ |
253 | |
254 | #if XCHAL_DCACHE_IS_WRITEBACK | |
255 | ||
256 | /* After unpacking, flush the writeback cache to memory so the | |
257 | * instructions/data are available. | |
258 | */ | |
259 | ||
173d6681 | 260 | ___flush_dcache_all a2 a3 |
5a0015d6 | 261 | #endif |
e85e335f MF |
262 | memw |
263 | isync | |
264 | ___invalidate_icache_all a2 a3 | |
265 | isync | |
5a0015d6 | 266 | |
f615136c | 267 | movi a6, 0 |
bc5378fc | 268 | xsr a6, excsave1 |
5a0015d6 CZ |
269 | |
270 | /* init_arch kick-starts the linux kernel */ | |
271 | ||
272 | movi a4, init_arch | |
273 | callx4 a4 | |
274 | ||
275 | movi a4, start_kernel | |
276 | callx4 a4 | |
277 | ||
278 | should_never_return: | |
279 | j should_never_return | |
280 | ||
f615136c MF |
281 | #ifdef CONFIG_SMP |
282 | .Lboot_secondary: | |
283 | ||
284 | movi a2, cpu_start_ccount | |
285 | 1: | |
286 | l32i a3, a2, 0 | |
287 | beqi a3, 0, 1b | |
288 | movi a3, 0 | |
289 | s32i a3, a2, 0 | |
290 | memw | |
291 | 1: | |
292 | l32i a3, a2, 0 | |
293 | beqi a3, 0, 1b | |
294 | wsr a3, ccount | |
295 | movi a3, 0 | |
296 | s32i a3, a2, 0 | |
297 | memw | |
298 | ||
299 | movi a6, 0 | |
300 | wsr a6, excsave1 | |
301 | ||
302 | movi a4, secondary_start_kernel | |
303 | callx4 a4 | |
304 | j should_never_return | |
305 | ||
306 | #endif /* CONFIG_SMP */ | |
307 | ||
d1538c46 | 308 | ENDPROC(_startup) |
5a0015d6 | 309 | |
49b424fe MF |
310 | #ifdef CONFIG_HOTPLUG_CPU |
311 | ||
312 | ENTRY(cpu_restart) | |
313 | ||
314 | #if XCHAL_DCACHE_IS_WRITEBACK | |
315 | ___flush_invalidate_dcache_all a2 a3 | |
316 | #else | |
317 | ___invalidate_dcache_all a2 a3 | |
318 | #endif | |
319 | memw | |
320 | movi a2, CCON # MX External Register to Configure Cache | |
321 | movi a3, 0 | |
322 | wer a3, a2 | |
323 | extw | |
324 | ||
325 | rsr a0, prid | |
326 | neg a2, a0 | |
327 | movi a3, cpu_start_id | |
328 | s32i a2, a3, 0 | |
329 | #if XCHAL_DCACHE_IS_WRITEBACK | |
330 | dhwbi a3, 0 | |
331 | #endif | |
332 | 1: | |
333 | l32i a2, a3, 0 | |
334 | dhi a3, 0 | |
335 | bne a2, a0, 1b | |
336 | ||
337 | /* | |
338 | * Initialize WB, WS, and clear PS.EXCM (to allow loop instructions). | |
339 | * Set Interrupt Level just below XCHAL_DEBUGLEVEL to allow | |
340 | * xt-gdb to single step via DEBUG exceptions received directly | |
341 | * by ocd. | |
342 | */ | |
343 | movi a1, 1 | |
344 | movi a0, 0 | |
345 | wsr a1, windowstart | |
346 | wsr a0, windowbase | |
347 | rsync | |
348 | ||
349 | movi a1, LOCKLEVEL | |
350 | wsr a1, ps | |
351 | rsync | |
352 | ||
353 | j _startup | |
354 | ||
355 | ENDPROC(cpu_restart) | |
356 | ||
357 | #endif /* CONFIG_HOTPLUG_CPU */ | |
358 | ||
f615136c MF |
359 | /* |
360 | * DATA section | |
361 | */ | |
362 | ||
363 | .section ".data.init.refok" | |
364 | .align 4 | |
365 | ENTRY(start_info) | |
366 | .long init_thread_union + KERNEL_STACK_SIZE | |
367 | ||
adba09f0 CZ |
368 | /* |
369 | * BSS section | |
370 | */ | |
371 | ||
02b7da37 | 372 | __PAGE_ALIGNED_BSS |
e5083a63 | 373 | #ifdef CONFIG_MMU |
adba09f0 CZ |
374 | ENTRY(swapper_pg_dir) |
375 | .fill PAGE_SIZE, 1, 0 | |
d1538c46 | 376 | END(swapper_pg_dir) |
e5083a63 | 377 | #endif |
adba09f0 CZ |
378 | ENTRY(empty_zero_page) |
379 | .fill PAGE_SIZE, 1, 0 | |
d1538c46 | 380 | END(empty_zero_page) |