]>
Commit | Line | Data |
---|---|---|
b920de1b DH |
1 | /* Boot entry point for MN10300 kernel |
2 | * | |
3 | * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. | |
4 | * Written by David Howells ([email protected]) | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public Licence | |
8 | * as published by the Free Software Foundation; either version | |
9 | * 2 of the Licence, or (at your option) any later version. | |
10 | */ | |
11 | ||
9760f8fc | 12 | #include <linux/init.h> |
b920de1b DH |
13 | #include <linux/threads.h> |
14 | #include <linux/linkage.h> | |
15 | #include <linux/serial_reg.h> | |
16 | #include <asm/thread_info.h> | |
17 | #include <asm/page.h> | |
18 | #include <asm/pgtable.h> | |
19 | #include <asm/frame.inc> | |
20 | #include <asm/param.h> | |
2f2a2132 | 21 | #include <unit/serial.h> |
368dd5ac AT |
22 | #ifdef CONFIG_SMP |
23 | #include <asm/smp.h> | |
24 | #include <asm/intctl-regs.h> | |
25 | #include <asm/cpu-regs.h> | |
26 | #include <proc/smp-regs.h> | |
27 | #endif /* CONFIG_SMP */ | |
b920de1b | 28 | |
9760f8fc | 29 | __HEAD |
b920de1b DH |
30 | |
31 | ############################################################################### | |
32 | # | |
33 | # bootloader entry point | |
34 | # | |
35 | ############################################################################### | |
36 | .globl _start | |
37 | .type _start,@function | |
38 | _start: | |
368dd5ac AT |
39 | #ifdef CONFIG_SMP |
40 | # | |
41 | # If this is a secondary CPU (AP), then deal with that elsewhere | |
42 | # | |
43 | mov (CPUID),d3 | |
44 | and CPUID_MASK,d3 | |
45 | bne startup_secondary | |
46 | ||
47 | # | |
48 | # We're dealing with the primary CPU (BP) here, then. | |
49 | # Keep BP's D0,D1,D2 register for boot check. | |
50 | # | |
51 | ||
52 | # Set up the Boot IPI for each secondary CPU | |
53 | mov 0x1,a0 | |
54 | loop_set_secondary_icr: | |
55 | mov a0,a1 | |
56 | asl CROSS_ICR_CPU_SHIFT,a1 | |
57 | add CROSS_GxICR(SMP_BOOT_IRQ,0),a1 | |
58 | movhu (a1),d3 | |
59 | or GxICR_ENABLE|GxICR_LEVEL_0,d3 | |
60 | movhu d3,(a1) | |
61 | movhu (a1),d3 # flush | |
62 | inc a0 | |
63 | cmp NR_CPUS,a0 | |
64 | bne loop_set_secondary_icr | |
65 | #endif /* CONFIG_SMP */ | |
66 | ||
b920de1b DH |
67 | # save commandline pointer |
68 | mov d0,a3 | |
69 | ||
70 | # preload the PGD pointer register | |
71 | mov swapper_pg_dir,d0 | |
72 | mov d0,(PTBR) | |
368dd5ac AT |
73 | clr d0 |
74 | movbu d0,(PIDR) | |
b920de1b DH |
75 | |
76 | # turn on the TLBs | |
77 | mov MMUCTR_IIV|MMUCTR_DIV,d0 | |
78 | mov d0,(MMUCTR) | |
368dd5ac AT |
79 | #ifdef CONFIG_AM34_2 |
80 | mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE|MMUCTR_WTE,d0 | |
81 | #else | |
b920de1b | 82 | mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE,d0 |
368dd5ac | 83 | #endif |
b920de1b DH |
84 | mov d0,(MMUCTR) |
85 | ||
86 | # turn on AM33v2 exception handling mode and set the trap table base | |
87 | movhu (CPUP),d0 | |
88 | or CPUP_EXM_AM33V2,d0 | |
89 | movhu d0,(CPUP) | |
90 | mov CONFIG_INTERRUPT_VECTOR_BASE,d0 | |
91 | mov d0,(TBR) | |
92 | ||
93 | # invalidate and enable both of the caches | |
368dd5ac AT |
94 | #ifdef CONFIG_SMP |
95 | mov ECHCTR,a0 | |
96 | clr d0 | |
97 | mov d0,(a0) | |
98 | #endif | |
b920de1b DH |
99 | mov CHCTR,a0 |
100 | clr d0 | |
101 | movhu d0,(a0) # turn off first | |
102 | mov CHCTR_ICINV|CHCTR_DCINV,d0 | |
103 | movhu d0,(a0) | |
104 | setlb | |
105 | mov (a0),d0 | |
106 | btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy | |
107 | lne | |
108 | ||
344af921 | 109 | #ifdef CONFIG_MN10300_CACHE_ENABLED |
b920de1b DH |
110 | #ifdef CONFIG_MN10300_CACHE_WBACK |
111 | #ifndef CONFIG_MN10300_CACHE_WBACK_NOWRALLOC | |
112 | mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0 | |
113 | #else | |
114 | mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK|CHCTR_DCALMD,d0 | |
344af921 | 115 | #endif /* NOWRALLOC */ |
b920de1b DH |
116 | #else |
117 | mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0 | |
118 | #endif /* WBACK */ | |
119 | movhu d0,(a0) # enable | |
344af921 | 120 | #endif /* ENABLED */ |
b920de1b DH |
121 | |
122 | # turn on RTS on the debug serial port if applicable | |
123 | #ifdef CONFIG_MN10300_UNIT_ASB2305 | |
124 | bset UART_MCR_RTS,(ASB2305_DEBUG_MCR) | |
125 | #endif | |
126 | ||
127 | # clear the BSS area | |
128 | mov __bss_start,a0 | |
129 | mov __bss_stop,a1 | |
130 | clr d0 | |
131 | bssclear: | |
132 | cmp a1,a0 | |
133 | bge bssclear_end | |
134 | mov d0,(a0) | |
135 | inc4 a0 | |
136 | bra bssclear | |
137 | bssclear_end: | |
138 | ||
139 | # retrieve the parameters (including command line) before we overwrite | |
140 | # them | |
141 | cmp 0xabadcafe,d1 | |
142 | bne __no_parameters | |
143 | ||
144 | __copy_parameters: | |
145 | mov redboot_command_line,a0 | |
146 | mov a0,a1 | |
147 | add COMMAND_LINE_SIZE,a1 | |
148 | 1: | |
149 | movbu (a3),d0 | |
150 | inc a3 | |
151 | movbu d0,(a0) | |
152 | inc a0 | |
153 | cmp a1,a0 | |
154 | blt 1b | |
155 | ||
156 | mov redboot_platform_name,a0 | |
157 | mov a0,a1 | |
158 | add COMMAND_LINE_SIZE,a1 | |
159 | mov d2,a3 | |
160 | 1: | |
161 | movbu (a3),d0 | |
162 | inc a3 | |
163 | movbu d0,(a0) | |
164 | inc a0 | |
165 | cmp a1,a0 | |
166 | blt 1b | |
167 | ||
168 | __no_parameters: | |
169 | ||
170 | # set up the registers with recognisable rubbish in them | |
171 | mov init_thread_union+THREAD_SIZE-12,sp | |
172 | ||
173 | mov 0xea01eaea,d0 | |
174 | mov d0,(4,sp) # EPSW save area | |
175 | mov 0xea02eaea,d0 | |
176 | mov d0,(8,sp) # PC save area | |
177 | ||
178 | mov 0xeb0060ed,d0 | |
179 | mov d0,mdr | |
180 | mov 0xeb0061ed,d0 | |
181 | mov d0,mdrq | |
182 | mov 0xeb0062ed,d0 | |
183 | mov d0,mcrh | |
184 | mov 0xeb0063ed,d0 | |
185 | mov d0,mcrl | |
186 | mov 0xeb0064ed,d0 | |
187 | mov d0,mcvf | |
188 | mov 0xed0065ed,a3 | |
189 | mov a3,usp | |
190 | ||
191 | mov 0xed00e0ed,e0 | |
192 | mov 0xed00e1ed,e1 | |
193 | mov 0xed00e2ed,e2 | |
194 | mov 0xed00e3ed,e3 | |
195 | mov 0xed00e4ed,e4 | |
196 | mov 0xed00e5ed,e5 | |
197 | mov 0xed00e6ed,e6 | |
198 | mov 0xed00e7ed,e7 | |
199 | ||
200 | mov 0xed00d0ed,d0 | |
201 | mov 0xed00d1ed,d1 | |
202 | mov 0xed00d2ed,d2 | |
203 | mov 0xed00d3ed,d3 | |
204 | mov 0xed00a0ed,a0 | |
205 | mov 0xed00a1ed,a1 | |
206 | mov 0xed00a2ed,a2 | |
207 | mov 0,a3 | |
208 | ||
209 | # set up the initial kernel stack | |
210 | SAVE_ALL | |
211 | mov 0xffffffff,d0 | |
212 | mov d0,(REG_ORIG_D0,fp) | |
213 | ||
214 | # put different recognisable rubbish in the regs | |
215 | mov 0xfb0060ed,d0 | |
216 | mov d0,mdr | |
217 | mov 0xfb0061ed,d0 | |
218 | mov d0,mdrq | |
219 | mov 0xfb0062ed,d0 | |
220 | mov d0,mcrh | |
221 | mov 0xfb0063ed,d0 | |
222 | mov d0,mcrl | |
223 | mov 0xfb0064ed,d0 | |
224 | mov d0,mcvf | |
225 | mov 0xfd0065ed,a0 | |
226 | mov a0,usp | |
227 | ||
228 | mov 0xfd00e0ed,e0 | |
229 | mov 0xfd00e1ed,e1 | |
230 | mov 0xfd00e2ed,e2 | |
231 | mov 0xfd00e3ed,e3 | |
232 | mov 0xfd00e4ed,e4 | |
233 | mov 0xfd00e5ed,e5 | |
234 | mov 0xfd00e6ed,e6 | |
235 | mov 0xfd00e7ed,e7 | |
236 | ||
237 | mov 0xfd00d0ed,d0 | |
238 | mov 0xfd00d1ed,d1 | |
239 | mov 0xfd00d2ed,d2 | |
240 | mov 0xfd00d3ed,d3 | |
241 | mov 0xfd00a0ed,a0 | |
242 | mov 0xfd00a1ed,a1 | |
243 | mov 0xfd00a2ed,a2 | |
244 | ||
245 | # we may be holding current in E2 | |
246 | #ifdef CONFIG_MN10300_CURRENT_IN_E2 | |
247 | mov init_task,e2 | |
248 | #endif | |
249 | ||
250 | # initialise the processor and the unit | |
251 | call processor_init[],0 | |
252 | call unit_init[],0 | |
253 | ||
368dd5ac AT |
254 | #ifdef CONFIG_SMP |
255 | # mark the primary CPU in cpu_boot_map | |
256 | mov cpu_boot_map,a0 | |
257 | mov 0x1,d0 | |
258 | mov d0,(a0) | |
259 | ||
260 | # signal each secondary CPU to begin booting | |
261 | mov 0x1,d2 # CPU ID | |
262 | ||
263 | loop_request_boot_secondary: | |
264 | mov d2,a0 | |
265 | # send SMP_BOOT_IPI to secondary CPU | |
266 | asl CROSS_ICR_CPU_SHIFT,a0 | |
267 | add CROSS_GxICR(SMP_BOOT_IRQ,0),a0 | |
268 | movhu (a0),d0 | |
269 | or GxICR_REQUEST|GxICR_DETECT,d0 | |
270 | movhu d0,(a0) | |
271 | movhu (a0),d0 # flush | |
272 | ||
273 | # wait up to 100ms for AP's IPI to be received | |
274 | clr d3 | |
275 | wait_on_secondary_boot: | |
276 | mov DELAY_TIME_BOOT_IPI,d0 | |
277 | call __delay[],0 | |
278 | inc d3 | |
279 | mov cpu_boot_map,a0 | |
280 | mov (a0),d0 | |
281 | lsr d2,d0 | |
282 | btst 0x1,d0 | |
283 | bne 1f | |
284 | cmp TIME_OUT_COUNT_BOOT_IPI,d3 | |
285 | bne wait_on_secondary_boot | |
286 | 1: | |
287 | inc d2 | |
288 | cmp NR_CPUS,d2 | |
289 | bne loop_request_boot_secondary | |
290 | #endif /* CONFIG_SMP */ | |
291 | ||
b920de1b DH |
292 | #ifdef CONFIG_GDBSTUB |
293 | call gdbstub_init[],0 | |
294 | ||
295 | #ifdef CONFIG_GDBSTUB_IMMEDIATE | |
296 | .globl __gdbstub_pause | |
297 | __gdbstub_pause: | |
298 | bra __gdbstub_pause | |
299 | #endif | |
300 | #endif | |
301 | ||
302 | jmp start_kernel | |
368dd5ac AT |
303 | .size _start,.-_start |
304 | ||
305 | ############################################################################### | |
306 | # | |
307 | # Secondary CPU boot point | |
308 | # | |
309 | ############################################################################### | |
310 | #ifdef CONFIG_SMP | |
311 | startup_secondary: | |
312 | # preload the PGD pointer register | |
313 | mov swapper_pg_dir,d0 | |
314 | mov d0,(PTBR) | |
315 | clr d0 | |
316 | movbu d0,(PIDR) | |
317 | ||
318 | # turn on the TLBs | |
319 | mov MMUCTR_IIV|MMUCTR_DIV,d0 | |
320 | mov d0,(MMUCTR) | |
321 | #ifdef CONFIG_AM34_2 | |
322 | mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE|MMUCTR_WTE,d0 | |
323 | #else | |
324 | mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE,d0 | |
325 | #endif | |
326 | mov d0,(MMUCTR) | |
327 | ||
328 | # turn on AM33v2 exception handling mode and set the trap table base | |
329 | movhu (CPUP),d0 | |
330 | or CPUP_EXM_AM33V2,d0 | |
331 | movhu d0,(CPUP) | |
332 | ||
333 | # set the interrupt vector table | |
334 | mov CONFIG_INTERRUPT_VECTOR_BASE,d0 | |
335 | mov d0,(TBR) | |
336 | ||
337 | # invalidate and enable both of the caches | |
338 | mov ECHCTR,a0 | |
339 | clr d0 | |
340 | mov d0,(a0) | |
341 | mov CHCTR,a0 | |
342 | clr d0 | |
343 | movhu d0,(a0) # turn off first | |
344 | mov CHCTR_ICINV|CHCTR_DCINV,d0 | |
345 | movhu d0,(a0) | |
346 | setlb | |
347 | mov (a0),d0 | |
348 | btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy (use CPU loop buffer) | |
349 | lne | |
350 | ||
351 | #ifdef CONFIG_MN10300_CACHE_ENABLED | |
352 | #ifdef CONFIG_MN10300_CACHE_WBACK | |
353 | #ifndef CONFIG_MN10300_CACHE_WBACK_NOWRALLOC | |
354 | mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0 | |
355 | #else | |
356 | mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK|CHCTR_DCALMD,d0 | |
357 | #endif /* !NOWRALLOC */ | |
358 | #else | |
359 | mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0 | |
360 | #endif /* WBACK */ | |
361 | movhu d0,(a0) # enable | |
362 | #endif /* ENABLED */ | |
363 | ||
364 | # Clear the boot IPI interrupt for this CPU | |
365 | movhu (GxICR(SMP_BOOT_IRQ)),d0 | |
366 | and ~GxICR_REQUEST,d0 | |
367 | movhu d0,(GxICR(SMP_BOOT_IRQ)) | |
368 | movhu (GxICR(SMP_BOOT_IRQ)),d0 # flush | |
369 | ||
370 | /* get stack */ | |
371 | mov CONFIG_INTERRUPT_VECTOR_BASE + CONFIG_BOOT_STACK_OFFSET,a0 | |
372 | mov (CPUID),d0 | |
373 | and CPUID_MASK,d0 | |
374 | mulu CONFIG_BOOT_STACK_SIZE,d0 | |
375 | sub d0,a0 | |
376 | mov a0,sp | |
377 | ||
378 | # init interrupt for AP | |
379 | call smp_prepare_cpu_init[],0 | |
380 | ||
381 | # mark this secondary CPU in cpu_boot_map | |
382 | mov (CPUID),d0 | |
383 | mov 0x1,d1 | |
384 | asl d0,d1 | |
385 | mov cpu_boot_map,a0 | |
386 | bset d1,(a0) | |
387 | ||
388 | or EPSW_IE|EPSW_IM_1,epsw # permit level 0 interrupts | |
389 | nop | |
390 | nop | |
391 | #ifdef CONFIG_MN10300_CACHE_WBACK | |
392 | # flush the local cache if it's in writeback mode | |
393 | call mn10300_local_dcache_flush_inv[],0 | |
394 | setlb | |
395 | mov (CHCTR),d0 | |
396 | btst CHCTR_DCBUSY,d0 # wait till not busy (use CPU loop buffer) | |
397 | lne | |
398 | #endif | |
399 | ||
400 | # now sleep waiting for further instructions | |
401 | secondary_sleep: | |
402 | mov CPUM_SLEEP,d0 | |
403 | movhu d0,(CPUM) | |
404 | nop | |
405 | nop | |
406 | bra secondary_sleep | |
407 | .size startup_secondary,.-startup_secondary | |
408 | #endif /* CONFIG_SMP */ | |
409 | ||
410 | ############################################################################### | |
411 | # | |
412 | # | |
413 | # | |
414 | ############################################################################### | |
b920de1b DH |
415 | ENTRY(__head_end) |
416 | ||
417 | /* | |
418 | * This is initialized to disallow all access to the low 2G region | |
419 | * - the high 2G region is managed directly by the MMU | |
420 | * - range 0x70000000-0x7C000000 are initialised for use by VMALLOC | |
421 | */ | |
422 | .section .bss | |
423 | .balign PAGE_SIZE | |
424 | ENTRY(swapper_pg_dir) | |
425 | .space PTRS_PER_PGD*4 | |
426 | ||
427 | /* | |
428 | * The page tables are initialized to only 8MB here - the final page | |
429 | * tables are set up later depending on memory size. | |
430 | */ | |
431 | ||
432 | .balign PAGE_SIZE | |
433 | ENTRY(empty_zero_page) | |
434 | .space PAGE_SIZE | |
435 | ||
436 | .balign PAGE_SIZE | |
437 | ENTRY(empty_bad_page) | |
438 | .space PAGE_SIZE | |
439 | ||
440 | .balign PAGE_SIZE | |
441 | ENTRY(empty_bad_pte_table) | |
442 | .space PAGE_SIZE | |
443 | ||
444 | .balign PAGE_SIZE | |
445 | ENTRY(large_page_table) | |
446 | .space PAGE_SIZE | |
447 | ||
448 | .balign PAGE_SIZE | |
449 | ENTRY(kernel_vmalloc_ptes) | |
450 | .space ((VMALLOC_END-VMALLOC_START)/PAGE_SIZE)*4 |