]>
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 <[email protected]> | |
13 | * Marc Gauthier <[email protected], [email protected]> | |
14 | * Joe Taylor <[email protected], [email protected]> | |
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 | |
40dc948f MF |
91 | movi a3, XCHAL_KSEG_PADDR |
92 | bltu a2, a3, 1f | |
93 | sub a2, a2, a3 | |
94 | movi a3, XCHAL_KSEG_SIZE | |
c5a771d0 | 95 | bgeu a2, a3, 1f |
40dc948f | 96 | movi a3, XCHAL_KSEG_CACHED_VADDR |
c5a771d0 MF |
97 | add a2, a2, a3 |
98 | wsr a2, excsave1 | |
99 | 1: | |
100 | #endif | |
e85e335f MF |
101 | #endif |
102 | .end no-absolute-literals | |
103 | ||
104 | l32r a0, .Lstartup | |
5a0015d6 CZ |
105 | jx a0 |
106 | ||
d1538c46 CZ |
107 | ENDPROC(_start) |
108 | ||
49b424fe | 109 | __REF |
e85e335f | 110 | .literal_position |
d1538c46 CZ |
111 | |
112 | ENTRY(_startup) | |
5a0015d6 | 113 | |
5a0015d6 CZ |
114 | /* Set a0 to 0 for the remaining initialization. */ |
115 | ||
116 | movi a0, 0 | |
117 | ||
53490121 | 118 | #if XCHAL_HAVE_VECBASE |
a9f2fc62 | 119 | movi a2, VECBASE_VADDR |
53490121 MF |
120 | wsr a2, vecbase |
121 | #endif | |
122 | ||
5a0015d6 CZ |
123 | /* Clear debugging registers. */ |
124 | ||
125 | #if XCHAL_HAVE_DEBUG | |
d83ff0bb | 126 | #if XCHAL_NUM_IBREAK > 0 |
bc5378fc | 127 | wsr a0, ibreakenable |
d83ff0bb | 128 | #endif |
bc5378fc | 129 | wsr a0, icount |
5a0015d6 | 130 | movi a1, 15 |
bc5378fc | 131 | wsr a0, icountlevel |
5a0015d6 | 132 | |
173d6681 | 133 | .set _index, 0 |
7de7ac78 | 134 | .rept XCHAL_NUM_DBREAK |
bc5378fc | 135 | wsr a0, SREG_DBREAKC + _index |
173d6681 CZ |
136 | .set _index, _index + 1 |
137 | .endr | |
5a0015d6 CZ |
138 | #endif |
139 | ||
140 | /* Clear CCOUNT (not really necessary, but nice) */ | |
141 | ||
bc5378fc | 142 | wsr a0, ccount # not really necessary, but nice |
5a0015d6 CZ |
143 | |
144 | /* Disable zero-loops. */ | |
145 | ||
146 | #if XCHAL_HAVE_LOOPS | |
bc5378fc | 147 | wsr a0, lcount |
5a0015d6 CZ |
148 | #endif |
149 | ||
150 | /* Disable all timers. */ | |
151 | ||
173d6681 | 152 | .set _index, 0 |
79fcf52b | 153 | .rept XCHAL_NUM_TIMERS |
bc5378fc | 154 | wsr a0, SREG_CCOMPARE + _index |
173d6681 CZ |
155 | .set _index, _index + 1 |
156 | .endr | |
5a0015d6 CZ |
157 | |
158 | /* Interrupt initialization. */ | |
159 | ||
160 | movi a2, XCHAL_INTTYPE_MASK_SOFTWARE | XCHAL_INTTYPE_MASK_EXTERN_EDGE | |
bc5378fc MF |
161 | wsr a0, intenable |
162 | wsr a2, intclear | |
5a0015d6 CZ |
163 | |
164 | /* Disable coprocessors. */ | |
165 | ||
eab5e7a7 | 166 | #if XCHAL_HAVE_CP |
bc5378fc | 167 | wsr a0, cpenable |
5a0015d6 CZ |
168 | #endif |
169 | ||
5a0015d6 | 170 | /* Initialize the caches. |
173d6681 | 171 | * a2, a3 are just working registers (clobbered). |
5a0015d6 CZ |
172 | */ |
173 | ||
173d6681 CZ |
174 | #if XCHAL_DCACHE_LINE_LOCKABLE |
175 | ___unlock_dcache_all a2 a3 | |
176 | #endif | |
177 | ||
178 | #if XCHAL_ICACHE_LINE_LOCKABLE | |
179 | ___unlock_icache_all a2 a3 | |
180 | #endif | |
181 | ||
182 | ___invalidate_dcache_all a2 a3 | |
183 | ___invalidate_icache_all a2 a3 | |
184 | ||
185 | isync | |
5a0015d6 | 186 | |
7bb516ca MF |
187 | initialize_cacheattr |
188 | ||
f615136c MF |
189 | #ifdef CONFIG_HAVE_SMP |
190 | movi a2, CCON # MX External Register to Configure Cache | |
191 | movi a3, 1 | |
192 | wer a3, a2 | |
193 | #endif | |
194 | ||
195 | /* Setup stack and enable window exceptions (keep irqs disabled) */ | |
196 | ||
197 | movi a1, start_info | |
198 | l32i a1, a1, 0 | |
199 | ||
200 | movi a2, (1 << PS_WOE_BIT) | LOCKLEVEL | |
201 | # WOE=1, INTLEVEL=LOCKLEVEL, UM=0 | |
202 | wsr a2, ps # (enable reg-windows; progmode stack) | |
203 | rsync | |
204 | ||
f615136c MF |
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 |
5029615e | 252 | __endla a2, a3, 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 | ||
2da03d41 MF |
272 | call4 init_arch |
273 | call4 start_kernel | |
5a0015d6 CZ |
274 | |
275 | should_never_return: | |
276 | j should_never_return | |
277 | ||
f615136c MF |
278 | #ifdef CONFIG_SMP |
279 | .Lboot_secondary: | |
280 | ||
281 | movi a2, cpu_start_ccount | |
282 | 1: | |
283 | l32i a3, a2, 0 | |
284 | beqi a3, 0, 1b | |
285 | movi a3, 0 | |
286 | s32i a3, a2, 0 | |
287 | memw | |
288 | 1: | |
289 | l32i a3, a2, 0 | |
290 | beqi a3, 0, 1b | |
291 | wsr a3, ccount | |
292 | movi a3, 0 | |
293 | s32i a3, a2, 0 | |
294 | memw | |
295 | ||
296 | movi a6, 0 | |
297 | wsr a6, excsave1 | |
298 | ||
2da03d41 | 299 | call4 secondary_start_kernel |
f615136c MF |
300 | j should_never_return |
301 | ||
302 | #endif /* CONFIG_SMP */ | |
303 | ||
d1538c46 | 304 | ENDPROC(_startup) |
5a0015d6 | 305 | |
49b424fe MF |
306 | #ifdef CONFIG_HOTPLUG_CPU |
307 | ||
308 | ENTRY(cpu_restart) | |
309 | ||
310 | #if XCHAL_DCACHE_IS_WRITEBACK | |
311 | ___flush_invalidate_dcache_all a2 a3 | |
312 | #else | |
313 | ___invalidate_dcache_all a2 a3 | |
314 | #endif | |
315 | memw | |
316 | movi a2, CCON # MX External Register to Configure Cache | |
317 | movi a3, 0 | |
318 | wer a3, a2 | |
319 | extw | |
320 | ||
321 | rsr a0, prid | |
322 | neg a2, a0 | |
323 | movi a3, cpu_start_id | |
324 | s32i a2, a3, 0 | |
325 | #if XCHAL_DCACHE_IS_WRITEBACK | |
326 | dhwbi a3, 0 | |
327 | #endif | |
328 | 1: | |
329 | l32i a2, a3, 0 | |
330 | dhi a3, 0 | |
331 | bne a2, a0, 1b | |
332 | ||
333 | /* | |
334 | * Initialize WB, WS, and clear PS.EXCM (to allow loop instructions). | |
335 | * Set Interrupt Level just below XCHAL_DEBUGLEVEL to allow | |
336 | * xt-gdb to single step via DEBUG exceptions received directly | |
337 | * by ocd. | |
338 | */ | |
339 | movi a1, 1 | |
340 | movi a0, 0 | |
341 | wsr a1, windowstart | |
342 | wsr a0, windowbase | |
343 | rsync | |
344 | ||
345 | movi a1, LOCKLEVEL | |
346 | wsr a1, ps | |
347 | rsync | |
348 | ||
349 | j _startup | |
350 | ||
351 | ENDPROC(cpu_restart) | |
352 | ||
353 | #endif /* CONFIG_HOTPLUG_CPU */ | |
354 | ||
f615136c MF |
355 | /* |
356 | * DATA section | |
357 | */ | |
358 | ||
359 | .section ".data.init.refok" | |
360 | .align 4 | |
361 | ENTRY(start_info) | |
362 | .long init_thread_union + KERNEL_STACK_SIZE | |
363 | ||
adba09f0 CZ |
364 | /* |
365 | * BSS section | |
366 | */ | |
367 | ||
02b7da37 | 368 | __PAGE_ALIGNED_BSS |
e5083a63 | 369 | #ifdef CONFIG_MMU |
adba09f0 CZ |
370 | ENTRY(swapper_pg_dir) |
371 | .fill PAGE_SIZE, 1, 0 | |
d1538c46 | 372 | END(swapper_pg_dir) |
e5083a63 | 373 | #endif |
adba09f0 CZ |
374 | ENTRY(empty_zero_page) |
375 | .fill PAGE_SIZE, 1, 0 | |
d1538c46 | 376 | END(empty_zero_page) |