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 | * | |
10 | * Copyright (C) 2001 - 2005 Tensilica Inc. | |
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> |
5a0015d6 | 21 | |
adba09f0 CZ |
22 | #include <linux/linkage.h> |
23 | ||
5a0015d6 CZ |
24 | /* |
25 | * This module contains the entry code for kernel images. It performs the | |
26 | * minimal setup needed to call the generic C routines. | |
27 | * | |
28 | * Prerequisites: | |
29 | * | |
30 | * - The kernel image has been loaded to the actual address where it was | |
31 | * compiled to. | |
32 | * - a2 contains either 0 or a pointer to a list of boot parameters. | |
33 | * (see setup.c for more details) | |
34 | * | |
35 | */ | |
36 | ||
5a0015d6 CZ |
37 | /* |
38 | * _start | |
39 | * | |
40 | * The bootloader passes a pointer to a list of boot parameters in a2. | |
41 | */ | |
42 | ||
43 | /* The first bytes of the kernel image must be an instruction, so we | |
44 | * manually allocate and define the literal constant we need for a jx | |
45 | * instruction. | |
46 | */ | |
47 | ||
48 | .section .head.text, "ax" | |
49 | .globl _start | |
50 | _start: _j 2f | |
51 | .align 4 | |
52 | 1: .word _startup | |
53 | 2: l32r a0, 1b | |
54 | jx a0 | |
55 | ||
56 | .text | |
57 | .align 4 | |
58 | _startup: | |
59 | ||
60 | /* Disable interrupts and exceptions. */ | |
61 | ||
173d6681 | 62 | movi a0, LOCKLEVEL |
5a0015d6 CZ |
63 | wsr a0, PS |
64 | ||
65 | /* Preserve the pointer to the boot parameter list in EXCSAVE_1 */ | |
66 | ||
67 | wsr a2, EXCSAVE_1 | |
68 | ||
69 | /* Start with a fresh windowbase and windowstart. */ | |
70 | ||
71 | movi a1, 1 | |
72 | movi a0, 0 | |
73 | wsr a1, WINDOWSTART | |
74 | wsr a0, WINDOWBASE | |
75 | rsync | |
76 | ||
77 | /* Set a0 to 0 for the remaining initialization. */ | |
78 | ||
79 | movi a0, 0 | |
80 | ||
81 | /* Clear debugging registers. */ | |
82 | ||
83 | #if XCHAL_HAVE_DEBUG | |
84 | wsr a0, IBREAKENABLE | |
85 | wsr a0, ICOUNT | |
86 | movi a1, 15 | |
87 | wsr a0, ICOUNTLEVEL | |
88 | ||
173d6681 CZ |
89 | .set _index, 0 |
90 | .rept XCHAL_NUM_DBREAK - 1 | |
91 | wsr a0, DBREAKC + _index | |
92 | .set _index, _index + 1 | |
93 | .endr | |
5a0015d6 CZ |
94 | #endif |
95 | ||
96 | /* Clear CCOUNT (not really necessary, but nice) */ | |
97 | ||
98 | wsr a0, CCOUNT # not really necessary, but nice | |
99 | ||
100 | /* Disable zero-loops. */ | |
101 | ||
102 | #if XCHAL_HAVE_LOOPS | |
103 | wsr a0, LCOUNT | |
104 | #endif | |
105 | ||
106 | /* Disable all timers. */ | |
107 | ||
173d6681 CZ |
108 | .set _index, 0 |
109 | .rept XCHAL_NUM_TIMERS - 1 | |
110 | wsr a0, CCOMPARE + _index | |
111 | .set _index, _index + 1 | |
112 | .endr | |
5a0015d6 CZ |
113 | |
114 | /* Interrupt initialization. */ | |
115 | ||
116 | movi a2, XCHAL_INTTYPE_MASK_SOFTWARE | XCHAL_INTTYPE_MASK_EXTERN_EDGE | |
117 | wsr a0, INTENABLE | |
118 | wsr a2, INTCLEAR | |
119 | ||
120 | /* Disable coprocessors. */ | |
121 | ||
122 | #if XCHAL_CP_NUM > 0 | |
123 | wsr a0, CPENABLE | |
124 | #endif | |
125 | ||
126 | /* Set PS.INTLEVEL=1, PS.WOE=0, kernel stack, PS.EXCM=0 | |
127 | * | |
128 | * Note: PS.EXCM must be cleared before using any loop | |
129 | * instructions; otherwise, they are silently disabled, and | |
130 | * at most one iteration of the loop is executed. | |
131 | */ | |
132 | ||
133 | movi a1, 1 | |
134 | wsr a1, PS | |
135 | rsync | |
136 | ||
137 | /* Initialize the caches. | |
173d6681 | 138 | * a2, a3 are just working registers (clobbered). |
5a0015d6 CZ |
139 | */ |
140 | ||
173d6681 CZ |
141 | #if XCHAL_DCACHE_LINE_LOCKABLE |
142 | ___unlock_dcache_all a2 a3 | |
143 | #endif | |
144 | ||
145 | #if XCHAL_ICACHE_LINE_LOCKABLE | |
146 | ___unlock_icache_all a2 a3 | |
147 | #endif | |
148 | ||
149 | ___invalidate_dcache_all a2 a3 | |
150 | ___invalidate_icache_all a2 a3 | |
151 | ||
152 | isync | |
5a0015d6 CZ |
153 | |
154 | /* Unpack data sections | |
155 | * | |
156 | * The linker script used to build the Linux kernel image | |
157 | * creates a table located at __boot_reloc_table_start | |
158 | * that contans the information what data needs to be unpacked. | |
159 | * | |
160 | * Uses a2-a7. | |
161 | */ | |
162 | ||
163 | movi a2, __boot_reloc_table_start | |
164 | movi a3, __boot_reloc_table_end | |
165 | ||
166 | 1: beq a2, a3, 3f # no more entries? | |
167 | l32i a4, a2, 0 # start destination (in RAM) | |
168 | l32i a5, a2, 4 # end desination (in RAM) | |
169 | l32i a6, a2, 8 # start source (in ROM) | |
170 | addi a2, a2, 12 # next entry | |
171 | beq a4, a5, 1b # skip, empty entry | |
172 | beq a4, a6, 1b # skip, source and dest. are the same | |
173 | ||
174 | 2: l32i a7, a6, 0 # load word | |
175 | addi a6, a6, 4 | |
176 | s32i a7, a4, 0 # store word | |
177 | addi a4, a4, 4 | |
178 | bltu a4, a5, 2b | |
179 | j 1b | |
180 | ||
181 | 3: | |
182 | /* All code and initialized data segments have been copied. | |
183 | * Now clear the BSS segment. | |
184 | */ | |
185 | ||
186 | movi a2, _bss_start # start of BSS | |
187 | movi a3, _bss_end # end of BSS | |
188 | ||
173d6681 | 189 | __loopt a2, a3, a4, 2 |
5a0015d6 | 190 | s32i a0, a2, 0 |
173d6681 | 191 | __endla a2, a4, 4 |
5a0015d6 CZ |
192 | |
193 | #if XCHAL_DCACHE_IS_WRITEBACK | |
194 | ||
195 | /* After unpacking, flush the writeback cache to memory so the | |
196 | * instructions/data are available. | |
197 | */ | |
198 | ||
173d6681 | 199 | ___flush_dcache_all a2 a3 |
5a0015d6 CZ |
200 | #endif |
201 | ||
202 | /* Setup stack and enable window exceptions (keep irqs disabled) */ | |
203 | ||
204 | movi a1, init_thread_union | |
205 | addi a1, a1, KERNEL_STACK_SIZE | |
206 | ||
207 | movi a2, 0x00040001 # WOE=1, INTLEVEL=1, UM=0 | |
208 | wsr a2, PS # (enable reg-windows; progmode stack) | |
209 | rsync | |
210 | ||
211 | /* Set up EXCSAVE[DEBUGLEVEL] to point to the Debug Exception Handler.*/ | |
212 | ||
213 | movi a2, debug_exception | |
214 | wsr a2, EXCSAVE + XCHAL_DEBUGLEVEL | |
215 | ||
216 | /* Set up EXCSAVE[1] to point to the exc_table. */ | |
217 | ||
218 | movi a6, exc_table | |
219 | xsr a6, EXCSAVE_1 | |
220 | ||
221 | /* init_arch kick-starts the linux kernel */ | |
222 | ||
223 | movi a4, init_arch | |
224 | callx4 a4 | |
225 | ||
226 | movi a4, start_kernel | |
227 | callx4 a4 | |
228 | ||
229 | should_never_return: | |
230 | j should_never_return | |
231 | ||
5a0015d6 | 232 | |
adba09f0 CZ |
233 | /* |
234 | * BSS section | |
235 | */ | |
236 | ||
237 | .section ".bss.page_aligned", "w" | |
238 | ENTRY(swapper_pg_dir) | |
239 | .fill PAGE_SIZE, 1, 0 | |
240 | ENTRY(empty_zero_page) | |
241 | .fill PAGE_SIZE, 1, 0 | |
5a0015d6 | 242 |