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 | |
71 | #endif | |
72 | .end no-absolute-literals | |
73 | ||
74 | l32r a0, .Lstartup | |
5a0015d6 CZ |
75 | jx a0 |
76 | ||
d1538c46 CZ |
77 | ENDPROC(_start) |
78 | ||
e85e335f MF |
79 | __INIT |
80 | .literal_position | |
d1538c46 CZ |
81 | |
82 | ENTRY(_startup) | |
5a0015d6 CZ |
83 | |
84 | /* Disable interrupts and exceptions. */ | |
85 | ||
173d6681 | 86 | movi a0, LOCKLEVEL |
bc5378fc | 87 | wsr a0, ps |
5a0015d6 | 88 | |
5a0015d6 CZ |
89 | /* Start with a fresh windowbase and windowstart. */ |
90 | ||
91 | movi a1, 1 | |
92 | movi a0, 0 | |
bc5378fc MF |
93 | wsr a1, windowstart |
94 | wsr a0, windowbase | |
5a0015d6 CZ |
95 | rsync |
96 | ||
97 | /* Set a0 to 0 for the remaining initialization. */ | |
98 | ||
99 | movi a0, 0 | |
100 | ||
101 | /* Clear debugging registers. */ | |
102 | ||
103 | #if XCHAL_HAVE_DEBUG | |
d83ff0bb | 104 | #if XCHAL_NUM_IBREAK > 0 |
bc5378fc | 105 | wsr a0, ibreakenable |
d83ff0bb | 106 | #endif |
bc5378fc | 107 | wsr a0, icount |
5a0015d6 | 108 | movi a1, 15 |
bc5378fc | 109 | wsr a0, icountlevel |
5a0015d6 | 110 | |
173d6681 CZ |
111 | .set _index, 0 |
112 | .rept XCHAL_NUM_DBREAK - 1 | |
bc5378fc | 113 | wsr a0, SREG_DBREAKC + _index |
173d6681 CZ |
114 | .set _index, _index + 1 |
115 | .endr | |
5a0015d6 CZ |
116 | #endif |
117 | ||
118 | /* Clear CCOUNT (not really necessary, but nice) */ | |
119 | ||
bc5378fc | 120 | wsr a0, ccount # not really necessary, but nice |
5a0015d6 CZ |
121 | |
122 | /* Disable zero-loops. */ | |
123 | ||
124 | #if XCHAL_HAVE_LOOPS | |
bc5378fc | 125 | wsr a0, lcount |
5a0015d6 CZ |
126 | #endif |
127 | ||
128 | /* Disable all timers. */ | |
129 | ||
173d6681 | 130 | .set _index, 0 |
79fcf52b | 131 | .rept XCHAL_NUM_TIMERS |
bc5378fc | 132 | wsr a0, SREG_CCOMPARE + _index |
173d6681 CZ |
133 | .set _index, _index + 1 |
134 | .endr | |
5a0015d6 CZ |
135 | |
136 | /* Interrupt initialization. */ | |
137 | ||
138 | movi a2, XCHAL_INTTYPE_MASK_SOFTWARE | XCHAL_INTTYPE_MASK_EXTERN_EDGE | |
bc5378fc MF |
139 | wsr a0, intenable |
140 | wsr a2, intclear | |
5a0015d6 CZ |
141 | |
142 | /* Disable coprocessors. */ | |
143 | ||
eab5e7a7 | 144 | #if XCHAL_HAVE_CP |
bc5378fc | 145 | wsr a0, cpenable |
5a0015d6 CZ |
146 | #endif |
147 | ||
2d1c645c | 148 | /* Set PS.INTLEVEL=LOCKLEVEL, PS.WOE=0, kernel stack, PS.EXCM=0 |
5a0015d6 CZ |
149 | * |
150 | * Note: PS.EXCM must be cleared before using any loop | |
151 | * instructions; otherwise, they are silently disabled, and | |
152 | * at most one iteration of the loop is executed. | |
153 | */ | |
154 | ||
2d1c645c | 155 | movi a1, LOCKLEVEL |
bc5378fc | 156 | wsr a1, ps |
5a0015d6 CZ |
157 | rsync |
158 | ||
159 | /* Initialize the caches. | |
173d6681 | 160 | * a2, a3 are just working registers (clobbered). |
5a0015d6 CZ |
161 | */ |
162 | ||
173d6681 CZ |
163 | #if XCHAL_DCACHE_LINE_LOCKABLE |
164 | ___unlock_dcache_all a2 a3 | |
165 | #endif | |
166 | ||
167 | #if XCHAL_ICACHE_LINE_LOCKABLE | |
168 | ___unlock_icache_all a2 a3 | |
169 | #endif | |
170 | ||
171 | ___invalidate_dcache_all a2 a3 | |
172 | ___invalidate_icache_all a2 a3 | |
173 | ||
174 | isync | |
5a0015d6 CZ |
175 | |
176 | /* Unpack data sections | |
177 | * | |
178 | * The linker script used to build the Linux kernel image | |
179 | * creates a table located at __boot_reloc_table_start | |
180 | * that contans the information what data needs to be unpacked. | |
181 | * | |
182 | * Uses a2-a7. | |
183 | */ | |
184 | ||
185 | movi a2, __boot_reloc_table_start | |
186 | movi a3, __boot_reloc_table_end | |
187 | ||
188 | 1: beq a2, a3, 3f # no more entries? | |
189 | l32i a4, a2, 0 # start destination (in RAM) | |
190 | l32i a5, a2, 4 # end desination (in RAM) | |
191 | l32i a6, a2, 8 # start source (in ROM) | |
192 | addi a2, a2, 12 # next entry | |
193 | beq a4, a5, 1b # skip, empty entry | |
194 | beq a4, a6, 1b # skip, source and dest. are the same | |
195 | ||
196 | 2: l32i a7, a6, 0 # load word | |
197 | addi a6, a6, 4 | |
198 | s32i a7, a4, 0 # store word | |
199 | addi a4, a4, 4 | |
200 | bltu a4, a5, 2b | |
201 | j 1b | |
202 | ||
203 | 3: | |
204 | /* All code and initialized data segments have been copied. | |
205 | * Now clear the BSS segment. | |
206 | */ | |
207 | ||
8b307f9c CZ |
208 | movi a2, __bss_start # start of BSS |
209 | movi a3, __bss_stop # end of BSS | |
5a0015d6 | 210 | |
173d6681 | 211 | __loopt a2, a3, a4, 2 |
5a0015d6 | 212 | s32i a0, a2, 0 |
173d6681 | 213 | __endla a2, a4, 4 |
5a0015d6 CZ |
214 | |
215 | #if XCHAL_DCACHE_IS_WRITEBACK | |
216 | ||
217 | /* After unpacking, flush the writeback cache to memory so the | |
218 | * instructions/data are available. | |
219 | */ | |
220 | ||
173d6681 | 221 | ___flush_dcache_all a2 a3 |
5a0015d6 | 222 | #endif |
e85e335f MF |
223 | memw |
224 | isync | |
225 | ___invalidate_icache_all a2 a3 | |
226 | isync | |
5a0015d6 CZ |
227 | |
228 | /* Setup stack and enable window exceptions (keep irqs disabled) */ | |
229 | ||
230 | movi a1, init_thread_union | |
231 | addi a1, a1, KERNEL_STACK_SIZE | |
232 | ||
2d1c645c MG |
233 | movi a2, (1 << PS_WOE_BIT) | LOCKLEVEL |
234 | # WOE=1, INTLEVEL=LOCKLEVEL, UM=0 | |
bc5378fc | 235 | wsr a2, ps # (enable reg-windows; progmode stack) |
5a0015d6 CZ |
236 | rsync |
237 | ||
238 | /* Set up EXCSAVE[DEBUGLEVEL] to point to the Debug Exception Handler.*/ | |
239 | ||
240 | movi a2, debug_exception | |
bc5378fc | 241 | wsr a2, SREG_EXCSAVE + XCHAL_DEBUGLEVEL |
5a0015d6 CZ |
242 | |
243 | /* Set up EXCSAVE[1] to point to the exc_table. */ | |
244 | ||
245 | movi a6, exc_table | |
bc5378fc | 246 | xsr a6, excsave1 |
5a0015d6 CZ |
247 | |
248 | /* init_arch kick-starts the linux kernel */ | |
249 | ||
250 | movi a4, init_arch | |
251 | callx4 a4 | |
252 | ||
253 | movi a4, start_kernel | |
254 | callx4 a4 | |
255 | ||
256 | should_never_return: | |
257 | j should_never_return | |
258 | ||
d1538c46 | 259 | ENDPROC(_startup) |
5a0015d6 | 260 | |
adba09f0 CZ |
261 | /* |
262 | * BSS section | |
263 | */ | |
264 | ||
02b7da37 | 265 | __PAGE_ALIGNED_BSS |
e5083a63 | 266 | #ifdef CONFIG_MMU |
adba09f0 CZ |
267 | ENTRY(swapper_pg_dir) |
268 | .fill PAGE_SIZE, 1, 0 | |
d1538c46 | 269 | END(swapper_pg_dir) |
e5083a63 | 270 | #endif |
adba09f0 CZ |
271 | ENTRY(empty_zero_page) |
272 | .fill PAGE_SIZE, 1, 0 | |
d1538c46 | 273 | END(empty_zero_page) |