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_SetupOCD: 63 /* 64 * Initialize WB, WS, and clear PS.EXCM (to allow loop instructions). 65 * Set Interrupt Level just below XCHAL_DEBUGLEVEL to allow 66 * xt-gdb to single step via DEBUG exceptions received directly 67 * by ocd. 68 */ 69 movi a1, 1 70 movi a0, 0 71 wsr a1, windowstart 72 wsr a0, windowbase 73 rsync 74 75 movi a1, LOCKLEVEL 76 wsr a1, ps 77 rsync 78 79 .global _SetupMMU 80_SetupMMU: 81 Offset = _SetupMMU - _start 82 83#ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX 84 initialize_mmu 85#if defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY 86 rsr a2, excsave1 87 movi a3, XCHAL_KSEG_PADDR 88 bltu a2, a3, 1f 89 sub a2, a2, a3 90 movi a3, XCHAL_KSEG_SIZE 91 bgeu a2, a3, 1f 92 movi a3, XCHAL_KSEG_CACHED_VADDR 93 add a2, a2, a3 94 wsr a2, excsave1 951: 96#endif 97#endif 98 99 movi a0, _startup 100 jx a0 101 102ENDPROC(_start) 103 .end no-absolute-literals 104 105 __REF 106 .literal_position 107 108ENTRY(_startup) 109 110 /* Set a0 to 0 for the remaining initialization. */ 111 112 movi a0, 0 113 114#if XCHAL_HAVE_VECBASE 115 movi a2, VECBASE_VADDR 116 wsr a2, vecbase 117#endif 118 119 /* Clear debugging registers. */ 120 121#if XCHAL_HAVE_DEBUG 122#if XCHAL_NUM_IBREAK > 0 123 wsr a0, ibreakenable 124#endif 125 wsr a0, icount 126 movi a1, 15 127 wsr a0, icountlevel 128 129 .set _index, 0 130 .rept XCHAL_NUM_DBREAK 131 wsr a0, SREG_DBREAKC + _index 132 .set _index, _index + 1 133 .endr 134#endif 135 136 /* Clear CCOUNT (not really necessary, but nice) */ 137 138 wsr a0, ccount # not really necessary, but nice 139 140 /* Disable zero-loops. */ 141 142#if XCHAL_HAVE_LOOPS 143 wsr a0, lcount 144#endif 145 146 /* Disable all timers. */ 147 148 .set _index, 0 149 .rept XCHAL_NUM_TIMERS 150 wsr a0, SREG_CCOMPARE + _index 151 .set _index, _index + 1 152 .endr 153 154 /* Interrupt initialization. */ 155 156 movi a2, XCHAL_INTTYPE_MASK_SOFTWARE | XCHAL_INTTYPE_MASK_EXTERN_EDGE 157 wsr a0, intenable 158 wsr a2, intclear 159 160 /* Disable coprocessors. */ 161 162#if XCHAL_HAVE_CP 163 wsr a0, cpenable 164#endif 165 166 /* Initialize the caches. 167 * a2, a3 are just working registers (clobbered). 168 */ 169 170#if XCHAL_DCACHE_LINE_LOCKABLE 171 ___unlock_dcache_all a2 a3 172#endif 173 174#if XCHAL_ICACHE_LINE_LOCKABLE 175 ___unlock_icache_all a2 a3 176#endif 177 178 ___invalidate_dcache_all a2 a3 179 ___invalidate_icache_all a2 a3 180 181 isync 182 183 initialize_cacheattr 184 185#ifdef CONFIG_HAVE_SMP 186 movi a2, CCON # MX External Register to Configure Cache 187 movi a3, 1 188 wer a3, a2 189#endif 190 191 /* Setup stack and enable window exceptions (keep irqs disabled) */ 192 193 movi a1, start_info 194 l32i a1, a1, 0 195 196 movi a2, (1 << PS_WOE_BIT) | LOCKLEVEL 197 # WOE=1, INTLEVEL=LOCKLEVEL, UM=0 198 wsr a2, ps # (enable reg-windows; progmode stack) 199 rsync 200 201#ifdef CONFIG_SMP 202 /* 203 * Notice that we assume with SMP that cores have PRID 204 * supported by the cores. 205 */ 206 rsr a2, prid 207 bnez a2, .Lboot_secondary 208 209#endif /* CONFIG_SMP */ 210 211 /* Unpack data sections 212 * 213 * The linker script used to build the Linux kernel image 214 * creates a table located at __boot_reloc_table_start 215 * that contans the information what data needs to be unpacked. 216 * 217 * Uses a2-a7. 218 */ 219 220 movi a2, __boot_reloc_table_start 221 movi a3, __boot_reloc_table_end 222 2231: beq a2, a3, 3f # no more entries? 224 l32i a4, a2, 0 # start destination (in RAM) 225 l32i a5, a2, 4 # end desination (in RAM) 226 l32i a6, a2, 8 # start source (in ROM) 227 addi a2, a2, 12 # next entry 228 beq a4, a5, 1b # skip, empty entry 229 beq a4, a6, 1b # skip, source and dest. are the same 230 2312: l32i a7, a6, 0 # load word 232 addi a6, a6, 4 233 s32i a7, a4, 0 # store word 234 addi a4, a4, 4 235 bltu a4, a5, 2b 236 j 1b 237 2383: 239 /* All code and initialized data segments have been copied. 240 * Now clear the BSS segment. 241 */ 242 243 movi a2, __bss_start # start of BSS 244 movi a3, __bss_stop # end of BSS 245 246 __loopt a2, a3, a4, 2 247 s32i a0, a2, 0 248 __endla a2, a3, 4 249 250#if XCHAL_DCACHE_IS_WRITEBACK 251 252 /* After unpacking, flush the writeback cache to memory so the 253 * instructions/data are available. 254 */ 255 256 ___flush_dcache_all a2 a3 257#endif 258 memw 259 isync 260 ___invalidate_icache_all a2 a3 261 isync 262 263 movi a6, 0 264 xsr a6, excsave1 265 266 /* init_arch kick-starts the linux kernel */ 267 268 call4 init_arch 269 call4 start_kernel 270 271should_never_return: 272 j should_never_return 273 274#ifdef CONFIG_SMP 275.Lboot_secondary: 276 277 movi a2, cpu_start_ccount 2781: 279 memw 280 l32i a3, a2, 0 281 beqi a3, 0, 1b 282 movi a3, 0 283 s32i a3, a2, 0 2841: 285 memw 286 l32i a3, a2, 0 287 beqi a3, 0, 1b 288 wsr a3, ccount 289 movi a3, 0 290 s32i a3, a2, 0 291 memw 292 293 movi a6, 0 294 wsr a6, excsave1 295 296 call4 secondary_start_kernel 297 j should_never_return 298 299#endif /* CONFIG_SMP */ 300 301ENDPROC(_startup) 302 303#ifdef CONFIG_HOTPLUG_CPU 304 305ENTRY(cpu_restart) 306 307#if XCHAL_DCACHE_IS_WRITEBACK 308 ___flush_invalidate_dcache_all a2 a3 309#else 310 ___invalidate_dcache_all a2 a3 311#endif 312 memw 313 movi a2, CCON # MX External Register to Configure Cache 314 movi a3, 0 315 wer a3, a2 316 extw 317 318 rsr a0, prid 319 neg a2, a0 320 movi a3, cpu_start_id 321 memw 322 s32i a2, a3, 0 323#if XCHAL_DCACHE_IS_WRITEBACK 324 dhwbi a3, 0 325#endif 3261: 327 memw 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