/*1* arch/xtensa/kernel/head.S2*3* Xtensa Processor startup code.4*5* This file is subject to the terms and conditions of the GNU General Public6* License. See the file "COPYING" in the main directory of this archive7* for more details.8*9* Copyright (C) 2001 - 2008 Tensilica Inc.10*11* Chris Zankel <[email protected]>12* Marc Gauthier <[email protected], [email protected]>13* Joe Taylor <[email protected], [email protected]>14* Kevin Chea15*/1617#include <asm/asmmacro.h>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>2324#include <linux/init.h>25#include <linux/linkage.h>2627/*28* This module contains the entry code for kernel images. It performs the29* 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 was34* 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*/3940/*41* _start42*43* The bootloader passes a pointer to a list of boot parameters in a2.44*/4546/* The first bytes of the kernel image must be an instruction, so we47* manually allocate and define the literal constant we need for a jx48* instruction.49*/5051__HEAD52.begin no-absolute-literals5354ENTRY(_start)5556/* Preserve the pointer to the boot parameter list in EXCSAVE_1 */57wsr a2, excsave158_j _SetupOCD5960.align 461.literal_position62_SetupOCD:63/*64* Initialize WB, WS, and clear PS.EXCM (to allow loop instructions).65* Set Interrupt Level just below XCHAL_DEBUGLEVEL to allow66* xt-gdb to single step via DEBUG exceptions received directly67* by ocd.68*/69#if XCHAL_HAVE_WINDOWED70movi a1, 171movi a0, 072wsr a1, windowstart73wsr a0, windowbase74rsync75#endif7677movi a1, LOCKLEVEL78wsr a1, ps79rsync8081.global _SetupMMU82_SetupMMU:83Offset = _SetupMMU - _start8485#ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX86initialize_mmu87#if defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY88rsr a2, excsave189movi a3, XCHAL_KSEG_PADDR90bltu a2, a3, 1f91sub a2, a2, a392movi a3, XCHAL_KSEG_SIZE93bgeu a2, a3, 1f94movi a3, XCHAL_KSEG_CACHED_VADDR95add a2, a2, a396wsr a2, excsave1971:98#endif99#endif100101movi a0, _startup102jx a0103104ENDPROC(_start)105.end no-absolute-literals106107__REF108.literal_position109110ENTRY(_startup)111112/* Set a0 to 0 for the remaining initialization. */113114movi a0, 0115116#if XCHAL_HAVE_VECBASE117movi a2, VECBASE_VADDR118wsr a2, vecbase119#endif120121/* Clear debugging registers. */122123#if XCHAL_HAVE_DEBUG124#if XCHAL_NUM_IBREAK > 0125wsr a0, ibreakenable126#endif127wsr a0, icount128movi a1, 15129wsr a0, icountlevel130131.set _index, 0132.rept XCHAL_NUM_DBREAK133wsr a0, SREG_DBREAKC + _index134.set _index, _index + 1135.endr136#endif137138/* Clear CCOUNT (not really necessary, but nice) */139140wsr a0, ccount # not really necessary, but nice141142/* Disable zero-loops. */143144#if XCHAL_HAVE_LOOPS145wsr a0, lcount146#endif147148/* Disable all timers. */149150.set _index, 0151.rept XCHAL_NUM_TIMERS152wsr a0, SREG_CCOMPARE + _index153.set _index, _index + 1154.endr155156/* Interrupt initialization. */157158movi a2, XCHAL_INTTYPE_MASK_SOFTWARE | XCHAL_INTTYPE_MASK_EXTERN_EDGE159wsr a0, intenable160wsr a2, intclear161162/* Disable coprocessors. */163164#if XCHAL_HAVE_CP165wsr a0, cpenable166#endif167168/* Initialize the caches.169* a2, a3 are just working registers (clobbered).170*/171172#if XCHAL_DCACHE_LINE_LOCKABLE173___unlock_dcache_all a2 a3174#endif175176#if XCHAL_ICACHE_LINE_LOCKABLE177___unlock_icache_all a2 a3178#endif179180___invalidate_dcache_all a2 a3181___invalidate_icache_all a2 a3182183isync184185initialize_cacheattr186187#ifdef CONFIG_HAVE_SMP188movi a2, CCON # MX External Register to Configure Cache189movi a3, 1190wer a3, a2191#endif192193/* Setup stack and enable window exceptions (keep irqs disabled) */194195movi a1, start_info196l32i a1, a1, 0197198/* Disable interrupts. */199/* Enable window exceptions if kernel is built with windowed ABI. */200movi a2, KERNEL_PS_WOE_MASK | LOCKLEVEL201wsr a2, ps202rsync203204#ifdef CONFIG_SMP205/*206* Notice that we assume with SMP that cores have PRID207* supported by the cores.208*/209rsr a2, prid210bnez a2, .Lboot_secondary211212#endif /* CONFIG_SMP */213214/* Unpack data sections215*216* The linker script used to build the Linux kernel image217* creates a table located at __boot_reloc_table_start218* that contains the information what data needs to be unpacked.219*220* Uses a2-a7.221*/222223movi a2, __boot_reloc_table_start224movi a3, __boot_reloc_table_end2252261: beq a2, a3, 3f # no more entries?227l32i a4, a2, 0 # start destination (in RAM)228l32i a5, a2, 4 # end destination (in RAM)229l32i a6, a2, 8 # start source (in ROM)230addi a2, a2, 12 # next entry231beq a4, a5, 1b # skip, empty entry232beq a4, a6, 1b # skip, source and dest. are the same2332342: l32i a7, a6, 0 # load word235addi a6, a6, 4236s32i a7, a4, 0 # store word237addi a4, a4, 4238bltu a4, a5, 2b239j 1b2402413:242/* All code and initialized data segments have been copied.243* Now clear the BSS segment.244*/245246movi a2, __bss_start # start of BSS247movi a3, __bss_stop # end of BSS248249__loopt a2, a3, a4, 2250s32i a0, a2, 0251__endla a2, a3, 4252253#if XCHAL_DCACHE_IS_WRITEBACK254255/* After unpacking, flush the writeback cache to memory so the256* instructions/data are available.257*/258259___flush_dcache_all a2 a3260#endif261memw262isync263___invalidate_icache_all a2 a3264isync265266#ifdef CONFIG_XIP_KERNEL267/* Setup bootstrap CPU stack in XIP kernel */268269movi a1, start_info270l32i a1, a1, 0271#endif272273movi abi_arg0, 0274xsr abi_arg0, excsave1275276/* init_arch kick-starts the linux kernel */277278abi_call init_arch279abi_call start_kernel280281should_never_return:282j should_never_return283284#ifdef CONFIG_SMP285.Lboot_secondary:286287movi a2, cpu_start_ccount2881:289memw290l32i a3, a2, 0291beqi a3, 0, 1b292movi a3, 0293s32i a3, a2, 02941:295memw296l32i a3, a2, 0297beqi a3, 0, 1b298wsr a3, ccount299movi a3, 0300s32i a3, a2, 0301memw302303movi abi_arg0, 0304wsr abi_arg0, excsave1305306abi_call secondary_start_kernel307j should_never_return308309#endif /* CONFIG_SMP */310311ENDPROC(_startup)312313#ifdef CONFIG_HOTPLUG_CPU314315ENTRY(cpu_restart)316317#if XCHAL_DCACHE_IS_WRITEBACK318___flush_invalidate_dcache_all a2 a3319#else320___invalidate_dcache_all a2 a3321#endif322memw323movi a2, CCON # MX External Register to Configure Cache324movi a3, 0325wer a3, a2326extw327328rsr a0, prid329neg a2, a0330movi a3, cpu_start_id331memw332s32i a2, a3, 0333#if XCHAL_DCACHE_IS_WRITEBACK334dhwbi a3, 0335#endif3361:337memw338l32i a2, a3, 0339dhi a3, 0340bne a2, a0, 1b341342/*343* Initialize WB, WS, and clear PS.EXCM (to allow loop instructions).344* Set Interrupt Level just below XCHAL_DEBUGLEVEL to allow345* xt-gdb to single step via DEBUG exceptions received directly346* by ocd.347*/348movi a1, 1349movi a0, 0350wsr a1, windowstart351wsr a0, windowbase352rsync353354movi a1, LOCKLEVEL355wsr a1, ps356rsync357358j _startup359360ENDPROC(cpu_restart)361362#endif /* CONFIG_HOTPLUG_CPU */363364/*365* DATA section366*/367368__REFDATA369.align 4370ENTRY(start_info)371.long init_thread_union + KERNEL_STACK_SIZE372373/*374* BSS section375*/376377__PAGE_ALIGNED_BSS378#ifdef CONFIG_MMU379ENTRY(swapper_pg_dir)380.fill PAGE_SIZE, 1, 0381END(swapper_pg_dir)382#endif383ENTRY(empty_zero_page)384.fill PAGE_SIZE, 1, 0385END(empty_zero_page)386387388