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 - 2008 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 18#include <asm/processor.h> 19#include <asm/page.h> 20#include <asm/cacheasm.h> 21#include <asm/initialize_mmu.h> 22#include <asm/mxregs.h> 23 24#include <linux/init.h> 25#include <linux/linkage.h> 26 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 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 51 __HEAD 52 .begin no-absolute-literals 53 54ENTRY(_start) 55 56 /* Preserve the pointer to the boot parameter list in EXCSAVE_1 */ 57 wsr a2, excsave1 58 _j _SetupOCD 59 60 .align 4 61 .literal_position 62.Lstartup: 63 .word _startup 64 65 .align 4 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 83 .global _SetupMMU 84_SetupMMU: 85 Offset = _SetupMMU - _start 86 87#ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX 88 initialize_mmu 89#if defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY 90 rsr a2, excsave1 91 movi a3, XCHAL_KSEG_PADDR 92 bltu a2, a3, 1f 93 sub a2, a2, a3 94 movi a3, XCHAL_KSEG_SIZE 95 bgeu a2, a3, 1f 96 movi a3, XCHAL_KSEG_CACHED_VADDR 97 add a2, a2, a3 98 wsr a2, excsave1 991: 100#endif 101#endif 102 .end no-absolute-literals 103 104 l32r a0, .Lstartup 105 jx a0 106 107ENDPROC(_start) 108 109 __REF 110 .literal_position 111 112ENTRY(_startup) 113 114 /* Set a0 to 0 for the remaining initialization. */ 115 116 movi a0, 0 117 118#if XCHAL_HAVE_VECBASE 119 movi a2, VECBASE_VADDR 120 wsr a2, vecbase 121#endif 122 123 /* Clear debugging registers. */ 124 125#if XCHAL_HAVE_DEBUG 126#if XCHAL_NUM_IBREAK > 0 127 wsr a0, ibreakenable 128#endif 129 wsr a0, icount 130 movi a1, 15 131 wsr a0, icountlevel 132 133 .set _index, 0 134 .rept XCHAL_NUM_DBREAK 135 wsr a0, SREG_DBREAKC + _index 136 .set _index, _index + 1 137 .endr 138#endif 139 140 /* Clear CCOUNT (not really necessary, but nice) */ 141 142 wsr a0, ccount # not really necessary, but nice 143 144 /* Disable zero-loops. */ 145 146#if XCHAL_HAVE_LOOPS 147 wsr a0, lcount 148#endif 149 150 /* Disable all timers. */ 151 152 .set _index, 0 153 .rept XCHAL_NUM_TIMERS 154 wsr a0, SREG_CCOMPARE + _index 155 .set _index, _index + 1 156 .endr 157 158 /* Interrupt initialization. */ 159 160 movi a2, XCHAL_INTTYPE_MASK_SOFTWARE | XCHAL_INTTYPE_MASK_EXTERN_EDGE 161 wsr a0, intenable 162 wsr a2, intclear 163 164 /* Disable coprocessors. */ 165 166#if XCHAL_HAVE_CP 167 wsr a0, cpenable 168#endif 169 170 /* Initialize the caches. 171 * a2, a3 are just working registers (clobbered). 172 */ 173 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 186 187#ifdef CONFIG_HAVE_SMP 188 movi a2, CCON # MX External Register to Configure Cache 189 movi a3, 1 190 wer a3, a2 191#endif 192 193 /* Setup stack and enable window exceptions (keep irqs disabled) */ 194 195 movi a1, start_info 196 l32i a1, a1, 0 197 198 movi a2, (1 << PS_WOE_BIT) | LOCKLEVEL 199 # WOE=1, INTLEVEL=LOCKLEVEL, UM=0 200 wsr a2, ps # (enable reg-windows; progmode stack) 201 rsync 202 203#ifdef CONFIG_SMP 204 /* 205 * Notice that we assume with SMP that cores have PRID 206 * supported by the cores. 207 */ 208 rsr a2, prid 209 bnez a2, .Lboot_secondary 210 211#endif /* CONFIG_SMP */ 212 213 /* Unpack data sections 214 * 215 * The linker script used to build the Linux kernel image 216 * creates a table located at __boot_reloc_table_start 217 * that contans the information what data needs to be unpacked. 218 * 219 * Uses a2-a7. 220 */ 221 222 movi a2, __boot_reloc_table_start 223 movi a3, __boot_reloc_table_end 224 2251: beq a2, a3, 3f # no more entries? 226 l32i a4, a2, 0 # start destination (in RAM) 227 l32i a5, a2, 4 # end desination (in RAM) 228 l32i a6, a2, 8 # start source (in ROM) 229 addi a2, a2, 12 # next entry 230 beq a4, a5, 1b # skip, empty entry 231 beq a4, a6, 1b # skip, source and dest. are the same 232 2332: l32i a7, a6, 0 # load word 234 addi a6, a6, 4 235 s32i a7, a4, 0 # store word 236 addi a4, a4, 4 237 bltu a4, a5, 2b 238 j 1b 239 2403: 241 /* All code and initialized data segments have been copied. 242 * Now clear the BSS segment. 243 */ 244 245 movi a2, __bss_start # start of BSS 246 movi a3, __bss_stop # end of BSS 247 248 __loopt a2, a3, a4, 2 249 s32i a0, a2, 0 250 __endla a2, a3, 4 251 252#if XCHAL_DCACHE_IS_WRITEBACK 253 254 /* After unpacking, flush the writeback cache to memory so the 255 * instructions/data are available. 256 */ 257 258 ___flush_dcache_all a2 a3 259#endif 260 memw 261 isync 262 ___invalidate_icache_all a2 a3 263 isync 264 265 movi a6, 0 266 xsr a6, excsave1 267 268 /* init_arch kick-starts the linux kernel */ 269 270 movi a4, init_arch 271 callx4 a4 272 273 movi a4, start_kernel 274 callx4 a4 275 276should_never_return: 277 j should_never_return 278 279#ifdef CONFIG_SMP 280.Lboot_secondary: 281 282 movi a2, cpu_start_ccount 2831: 284 memw 285 l32i a3, a2, 0 286 beqi a3, 0, 1b 287 movi a3, 0 288 s32i a3, a2, 0 2891: 290 memw 291 l32i a3, a2, 0 292 beqi a3, 0, 1b 293 wsr a3, ccount 294 movi a3, 0 295 s32i a3, a2, 0 296 memw 297 298 movi a6, 0 299 wsr a6, excsave1 300 301 movi a4, secondary_start_kernel 302 callx4 a4 303 j should_never_return 304 305#endif /* CONFIG_SMP */ 306 307ENDPROC(_startup) 308 309#ifdef CONFIG_HOTPLUG_CPU 310 311ENTRY(cpu_restart) 312 313#if XCHAL_DCACHE_IS_WRITEBACK 314 ___flush_invalidate_dcache_all a2 a3 315#else 316 ___invalidate_dcache_all a2 a3 317#endif 318 memw 319 movi a2, CCON # MX External Register to Configure Cache 320 movi a3, 0 321 wer a3, a2 322 extw 323 324 rsr a0, prid 325 neg a2, a0 326 movi a3, cpu_start_id 327 memw 328 s32i a2, a3, 0 329#if XCHAL_DCACHE_IS_WRITEBACK 330 dhwbi a3, 0 331#endif 3321: 333 memw 334 l32i a2, a3, 0 335 dhi a3, 0 336 bne a2, a0, 1b 337 338 /* 339 * Initialize WB, WS, and clear PS.EXCM (to allow loop instructions). 340 * Set Interrupt Level just below XCHAL_DEBUGLEVEL to allow 341 * xt-gdb to single step via DEBUG exceptions received directly 342 * by ocd. 343 */ 344 movi a1, 1 345 movi a0, 0 346 wsr a1, windowstart 347 wsr a0, windowbase 348 rsync 349 350 movi a1, LOCKLEVEL 351 wsr a1, ps 352 rsync 353 354 j _startup 355 356ENDPROC(cpu_restart) 357 358#endif /* CONFIG_HOTPLUG_CPU */ 359 360/* 361 * DATA section 362 */ 363 364 .section ".data.init.refok" 365 .align 4 366ENTRY(start_info) 367 .long init_thread_union + KERNEL_STACK_SIZE 368 369/* 370 * BSS section 371 */ 372 373__PAGE_ALIGNED_BSS 374#ifdef CONFIG_MMU 375ENTRY(swapper_pg_dir) 376 .fill PAGE_SIZE, 1, 0 377END(swapper_pg_dir) 378#endif 379ENTRY(empty_zero_page) 380 .fill PAGE_SIZE, 1, 0 381END(empty_zero_page) 382