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