15a0015d6SChris Zankel/* 25a0015d6SChris Zankel * arch/xtensa/kernel/head.S 35a0015d6SChris Zankel * 45a0015d6SChris Zankel * Xtensa Processor startup code. 55a0015d6SChris Zankel * 65a0015d6SChris Zankel * This file is subject to the terms and conditions of the GNU General Public 75a0015d6SChris Zankel * License. See the file "COPYING" in the main directory of this archive 85a0015d6SChris Zankel * for more details. 95a0015d6SChris Zankel * 102d1c645cSMarc Gauthier * Copyright (C) 2001 - 2008 Tensilica Inc. 115a0015d6SChris Zankel * 125a0015d6SChris Zankel * Chris Zankel <chris@zankel.net> 135a0015d6SChris Zankel * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca> 145a0015d6SChris Zankel * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com> 155a0015d6SChris Zankel * Kevin Chea 165a0015d6SChris Zankel */ 175a0015d6SChris Zankel 180b537257SMax Filippov#include <asm/asmmacro.h> 195a0015d6SChris Zankel#include <asm/processor.h> 205a0015d6SChris Zankel#include <asm/page.h> 21173d6681SChris Zankel#include <asm/cacheasm.h> 22c622b29dSMax Filippov#include <asm/initialize_mmu.h> 23f615136cSMax Filippov#include <asm/mxregs.h> 245a0015d6SChris Zankel 250ebdcb4dSTim Abbott#include <linux/init.h> 26adba09f0SChris Zankel#include <linux/linkage.h> 27adba09f0SChris Zankel 285a0015d6SChris Zankel/* 295a0015d6SChris Zankel * This module contains the entry code for kernel images. It performs the 305a0015d6SChris Zankel * minimal setup needed to call the generic C routines. 315a0015d6SChris Zankel * 325a0015d6SChris Zankel * Prerequisites: 335a0015d6SChris Zankel * 345a0015d6SChris Zankel * - The kernel image has been loaded to the actual address where it was 355a0015d6SChris Zankel * compiled to. 365a0015d6SChris Zankel * - a2 contains either 0 or a pointer to a list of boot parameters. 375a0015d6SChris Zankel * (see setup.c for more details) 385a0015d6SChris Zankel * 395a0015d6SChris Zankel */ 405a0015d6SChris Zankel 415a0015d6SChris Zankel/* 425a0015d6SChris Zankel * _start 435a0015d6SChris Zankel * 445a0015d6SChris Zankel * The bootloader passes a pointer to a list of boot parameters in a2. 455a0015d6SChris Zankel */ 465a0015d6SChris Zankel 475a0015d6SChris Zankel /* The first bytes of the kernel image must be an instruction, so we 485a0015d6SChris Zankel * manually allocate and define the literal constant we need for a jx 495a0015d6SChris Zankel * instruction. 505a0015d6SChris Zankel */ 515a0015d6SChris Zankel 520ebdcb4dSTim Abbott __HEAD 53e85e335fSMax Filippov .begin no-absolute-literals 54e85e335fSMax Filippov 55d1538c46SChris ZankelENTRY(_start) 56d1538c46SChris Zankel 57e85e335fSMax Filippov /* Preserve the pointer to the boot parameter list in EXCSAVE_1 */ 58e85e335fSMax Filippov wsr a2, excsave1 59f615136cSMax Filippov _j _SetupOCD 60e85e335fSMax Filippov 615a0015d6SChris Zankel .align 4 62e85e335fSMax Filippov .literal_position 63f615136cSMax Filippov_SetupOCD: 64f615136cSMax Filippov /* 65f615136cSMax Filippov * Initialize WB, WS, and clear PS.EXCM (to allow loop instructions). 66f615136cSMax Filippov * Set Interrupt Level just below XCHAL_DEBUGLEVEL to allow 67f615136cSMax Filippov * xt-gdb to single step via DEBUG exceptions received directly 68f615136cSMax Filippov * by ocd. 69f615136cSMax Filippov */ 70*09af39f6SMax Filippov#if XCHAL_HAVE_WINDOWED 71f615136cSMax Filippov movi a1, 1 72f615136cSMax Filippov movi a0, 0 73f615136cSMax Filippov wsr a1, windowstart 74f615136cSMax Filippov wsr a0, windowbase 75f615136cSMax Filippov rsync 76*09af39f6SMax Filippov#endif 77f615136cSMax Filippov 78f615136cSMax Filippov movi a1, LOCKLEVEL 79f615136cSMax Filippov wsr a1, ps 80f615136cSMax Filippov rsync 81f615136cSMax Filippov 82e85e335fSMax Filippov .global _SetupMMU 83e85e335fSMax Filippov_SetupMMU: 84e85e335fSMax Filippov Offset = _SetupMMU - _start 85e85e335fSMax Filippov 86e85e335fSMax Filippov#ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX 87e85e335fSMax Filippov initialize_mmu 88c5a771d0SMax Filippov#if defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY 89c5a771d0SMax Filippov rsr a2, excsave1 9040dc948fSMax Filippov movi a3, XCHAL_KSEG_PADDR 9140dc948fSMax Filippov bltu a2, a3, 1f 9240dc948fSMax Filippov sub a2, a2, a3 9340dc948fSMax Filippov movi a3, XCHAL_KSEG_SIZE 94c5a771d0SMax Filippov bgeu a2, a3, 1f 9540dc948fSMax Filippov movi a3, XCHAL_KSEG_CACHED_VADDR 96c5a771d0SMax Filippov add a2, a2, a3 97c5a771d0SMax Filippov wsr a2, excsave1 98c5a771d0SMax Filippov1: 99c5a771d0SMax Filippov#endif 100e85e335fSMax Filippov#endif 101e85e335fSMax Filippov 10203760270SMax Filippov movi a0, _startup 1035a0015d6SChris Zankel jx a0 1045a0015d6SChris Zankel 105d1538c46SChris ZankelENDPROC(_start) 10603760270SMax Filippov .end no-absolute-literals 107d1538c46SChris Zankel 10849b424feSMax Filippov __REF 109e85e335fSMax Filippov .literal_position 110d1538c46SChris Zankel 111d1538c46SChris ZankelENTRY(_startup) 1125a0015d6SChris Zankel 1135a0015d6SChris Zankel /* Set a0 to 0 for the remaining initialization. */ 1145a0015d6SChris Zankel 1155a0015d6SChris Zankel movi a0, 0 1165a0015d6SChris Zankel 11753490121SMax Filippov#if XCHAL_HAVE_VECBASE 118a9f2fc62SMax Filippov movi a2, VECBASE_VADDR 11953490121SMax Filippov wsr a2, vecbase 12053490121SMax Filippov#endif 12153490121SMax Filippov 1225a0015d6SChris Zankel /* Clear debugging registers. */ 1235a0015d6SChris Zankel 1245a0015d6SChris Zankel#if XCHAL_HAVE_DEBUG 125d83ff0bbSMax Filippov#if XCHAL_NUM_IBREAK > 0 126bc5378fcSMax Filippov wsr a0, ibreakenable 127d83ff0bbSMax Filippov#endif 128bc5378fcSMax Filippov wsr a0, icount 1295a0015d6SChris Zankel movi a1, 15 130bc5378fcSMax Filippov wsr a0, icountlevel 1315a0015d6SChris Zankel 132173d6681SChris Zankel .set _index, 0 1337de7ac78SMax Filippov .rept XCHAL_NUM_DBREAK 134bc5378fcSMax Filippov wsr a0, SREG_DBREAKC + _index 135173d6681SChris Zankel .set _index, _index + 1 136173d6681SChris Zankel .endr 1375a0015d6SChris Zankel#endif 1385a0015d6SChris Zankel 1395a0015d6SChris Zankel /* Clear CCOUNT (not really necessary, but nice) */ 1405a0015d6SChris Zankel 141bc5378fcSMax Filippov wsr a0, ccount # not really necessary, but nice 1425a0015d6SChris Zankel 1435a0015d6SChris Zankel /* Disable zero-loops. */ 1445a0015d6SChris Zankel 1455a0015d6SChris Zankel#if XCHAL_HAVE_LOOPS 146bc5378fcSMax Filippov wsr a0, lcount 1475a0015d6SChris Zankel#endif 1485a0015d6SChris Zankel 1495a0015d6SChris Zankel /* Disable all timers. */ 1505a0015d6SChris Zankel 151173d6681SChris Zankel .set _index, 0 15279fcf52bSMax Filippov .rept XCHAL_NUM_TIMERS 153bc5378fcSMax Filippov wsr a0, SREG_CCOMPARE + _index 154173d6681SChris Zankel .set _index, _index + 1 155173d6681SChris Zankel .endr 1565a0015d6SChris Zankel 1575a0015d6SChris Zankel /* Interrupt initialization. */ 1585a0015d6SChris Zankel 1595a0015d6SChris Zankel movi a2, XCHAL_INTTYPE_MASK_SOFTWARE | XCHAL_INTTYPE_MASK_EXTERN_EDGE 160bc5378fcSMax Filippov wsr a0, intenable 161bc5378fcSMax Filippov wsr a2, intclear 1625a0015d6SChris Zankel 1635a0015d6SChris Zankel /* Disable coprocessors. */ 1645a0015d6SChris Zankel 165eab5e7a7SMax Filippov#if XCHAL_HAVE_CP 166bc5378fcSMax Filippov wsr a0, cpenable 1675a0015d6SChris Zankel#endif 1685a0015d6SChris Zankel 1695a0015d6SChris Zankel /* Initialize the caches. 170173d6681SChris Zankel * a2, a3 are just working registers (clobbered). 1715a0015d6SChris Zankel */ 1725a0015d6SChris Zankel 173173d6681SChris Zankel#if XCHAL_DCACHE_LINE_LOCKABLE 174173d6681SChris Zankel ___unlock_dcache_all a2 a3 175173d6681SChris Zankel#endif 176173d6681SChris Zankel 177173d6681SChris Zankel#if XCHAL_ICACHE_LINE_LOCKABLE 178173d6681SChris Zankel ___unlock_icache_all a2 a3 179173d6681SChris Zankel#endif 180173d6681SChris Zankel 181173d6681SChris Zankel ___invalidate_dcache_all a2 a3 182173d6681SChris Zankel ___invalidate_icache_all a2 a3 183173d6681SChris Zankel 184173d6681SChris Zankel isync 1855a0015d6SChris Zankel 1867bb516caSMax Filippov initialize_cacheattr 1877bb516caSMax Filippov 188f615136cSMax Filippov#ifdef CONFIG_HAVE_SMP 189f615136cSMax Filippov movi a2, CCON # MX External Register to Configure Cache 190f615136cSMax Filippov movi a3, 1 191f615136cSMax Filippov wer a3, a2 192f615136cSMax Filippov#endif 193f615136cSMax Filippov 194f615136cSMax Filippov /* Setup stack and enable window exceptions (keep irqs disabled) */ 195f615136cSMax Filippov 196f615136cSMax Filippov movi a1, start_info 197f615136cSMax Filippov l32i a1, a1, 0 198f615136cSMax Filippov 1990b537257SMax Filippov /* Disable interrupts. */ 2000b537257SMax Filippov /* Enable window exceptions if kernel is built with windowed ABI. */ 2010b537257SMax Filippov movi a2, KERNEL_PS_WOE_MASK | LOCKLEVEL 2020b537257SMax Filippov wsr a2, ps 203f615136cSMax Filippov rsync 204f615136cSMax Filippov 205f615136cSMax Filippov#ifdef CONFIG_SMP 206f615136cSMax Filippov /* 207f615136cSMax Filippov * Notice that we assume with SMP that cores have PRID 208f615136cSMax Filippov * supported by the cores. 209f615136cSMax Filippov */ 210f615136cSMax Filippov rsr a2, prid 211f615136cSMax Filippov bnez a2, .Lboot_secondary 212f615136cSMax Filippov 213f615136cSMax Filippov#endif /* CONFIG_SMP */ 214f615136cSMax Filippov 2155a0015d6SChris Zankel /* Unpack data sections 2165a0015d6SChris Zankel * 2175a0015d6SChris Zankel * The linker script used to build the Linux kernel image 2185a0015d6SChris Zankel * creates a table located at __boot_reloc_table_start 219e1532777SBhaskar Chowdhury * that contains the information what data needs to be unpacked. 2205a0015d6SChris Zankel * 2215a0015d6SChris Zankel * Uses a2-a7. 2225a0015d6SChris Zankel */ 2235a0015d6SChris Zankel 2245a0015d6SChris Zankel movi a2, __boot_reloc_table_start 2255a0015d6SChris Zankel movi a3, __boot_reloc_table_end 2265a0015d6SChris Zankel 2275a0015d6SChris Zankel1: beq a2, a3, 3f # no more entries? 2285a0015d6SChris Zankel l32i a4, a2, 0 # start destination (in RAM) 229e1532777SBhaskar Chowdhury l32i a5, a2, 4 # end destination (in RAM) 2305a0015d6SChris Zankel l32i a6, a2, 8 # start source (in ROM) 2315a0015d6SChris Zankel addi a2, a2, 12 # next entry 2325a0015d6SChris Zankel beq a4, a5, 1b # skip, empty entry 2335a0015d6SChris Zankel beq a4, a6, 1b # skip, source and dest. are the same 2345a0015d6SChris Zankel 2355a0015d6SChris Zankel2: l32i a7, a6, 0 # load word 2365a0015d6SChris Zankel addi a6, a6, 4 2375a0015d6SChris Zankel s32i a7, a4, 0 # store word 2385a0015d6SChris Zankel addi a4, a4, 4 2395a0015d6SChris Zankel bltu a4, a5, 2b 2405a0015d6SChris Zankel j 1b 2415a0015d6SChris Zankel 2425a0015d6SChris Zankel3: 2435a0015d6SChris Zankel /* All code and initialized data segments have been copied. 2445a0015d6SChris Zankel * Now clear the BSS segment. 2455a0015d6SChris Zankel */ 2465a0015d6SChris Zankel 2478b307f9cSChris Zankel movi a2, __bss_start # start of BSS 2488b307f9cSChris Zankel movi a3, __bss_stop # end of BSS 2495a0015d6SChris Zankel 250173d6681SChris Zankel __loopt a2, a3, a4, 2 2515a0015d6SChris Zankel s32i a0, a2, 0 2525029615eSMax Filippov __endla a2, a3, 4 2535a0015d6SChris Zankel 2545a0015d6SChris Zankel#if XCHAL_DCACHE_IS_WRITEBACK 2555a0015d6SChris Zankel 2565a0015d6SChris Zankel /* After unpacking, flush the writeback cache to memory so the 2575a0015d6SChris Zankel * instructions/data are available. 2585a0015d6SChris Zankel */ 2595a0015d6SChris Zankel 260173d6681SChris Zankel ___flush_dcache_all a2 a3 2615a0015d6SChris Zankel#endif 262e85e335fSMax Filippov memw 263e85e335fSMax Filippov isync 264e85e335fSMax Filippov ___invalidate_icache_all a2 a3 265e85e335fSMax Filippov isync 2665a0015d6SChris Zankel 2677af710d9SMax Filippov#ifdef CONFIG_XIP_KERNEL 2687af710d9SMax Filippov /* Setup bootstrap CPU stack in XIP kernel */ 2697af710d9SMax Filippov 2707af710d9SMax Filippov movi a1, start_info 2717af710d9SMax Filippov l32i a1, a1, 0 2727af710d9SMax Filippov#endif 2737af710d9SMax Filippov 2740b537257SMax Filippov movi abi_arg0, 0 2750b537257SMax Filippov xsr abi_arg0, excsave1 2765a0015d6SChris Zankel 2775a0015d6SChris Zankel /* init_arch kick-starts the linux kernel */ 2785a0015d6SChris Zankel 2790b537257SMax Filippov abi_call init_arch 2800b537257SMax Filippov abi_call start_kernel 2815a0015d6SChris Zankel 2825a0015d6SChris Zankelshould_never_return: 2835a0015d6SChris Zankel j should_never_return 2845a0015d6SChris Zankel 285f615136cSMax Filippov#ifdef CONFIG_SMP 286f615136cSMax Filippov.Lboot_secondary: 287f615136cSMax Filippov 288f615136cSMax Filippov movi a2, cpu_start_ccount 289f615136cSMax Filippov1: 29032a7726cSMax Filippov memw 291f615136cSMax Filippov l32i a3, a2, 0 292f615136cSMax Filippov beqi a3, 0, 1b 293f615136cSMax Filippov movi a3, 0 294f615136cSMax Filippov s32i a3, a2, 0 295f615136cSMax Filippov1: 29632a7726cSMax Filippov memw 297f615136cSMax Filippov l32i a3, a2, 0 298f615136cSMax Filippov beqi a3, 0, 1b 299f615136cSMax Filippov wsr a3, ccount 300f615136cSMax Filippov movi a3, 0 301f615136cSMax Filippov s32i a3, a2, 0 302f615136cSMax Filippov memw 303f615136cSMax Filippov 3040b537257SMax Filippov movi abi_arg0, 0 3050b537257SMax Filippov wsr abi_arg0, excsave1 306f615136cSMax Filippov 3070b537257SMax Filippov abi_call secondary_start_kernel 308f615136cSMax Filippov j should_never_return 309f615136cSMax Filippov 310f615136cSMax Filippov#endif /* CONFIG_SMP */ 311f615136cSMax Filippov 312d1538c46SChris ZankelENDPROC(_startup) 313adba09f0SChris Zankel 31449b424feSMax Filippov#ifdef CONFIG_HOTPLUG_CPU 31549b424feSMax Filippov 31649b424feSMax FilippovENTRY(cpu_restart) 31749b424feSMax Filippov 31849b424feSMax Filippov#if XCHAL_DCACHE_IS_WRITEBACK 31949b424feSMax Filippov ___flush_invalidate_dcache_all a2 a3 32049b424feSMax Filippov#else 32149b424feSMax Filippov ___invalidate_dcache_all a2 a3 32249b424feSMax Filippov#endif 32349b424feSMax Filippov memw 32449b424feSMax Filippov movi a2, CCON # MX External Register to Configure Cache 32549b424feSMax Filippov movi a3, 0 32649b424feSMax Filippov wer a3, a2 32749b424feSMax Filippov extw 32849b424feSMax Filippov 32949b424feSMax Filippov rsr a0, prid 33049b424feSMax Filippov neg a2, a0 33149b424feSMax Filippov movi a3, cpu_start_id 33232a7726cSMax Filippov memw 33349b424feSMax Filippov s32i a2, a3, 0 33449b424feSMax Filippov#if XCHAL_DCACHE_IS_WRITEBACK 33549b424feSMax Filippov dhwbi a3, 0 33649b424feSMax Filippov#endif 33749b424feSMax Filippov1: 33832a7726cSMax Filippov memw 33949b424feSMax Filippov l32i a2, a3, 0 34049b424feSMax Filippov dhi a3, 0 34149b424feSMax Filippov bne a2, a0, 1b 34249b424feSMax Filippov 34349b424feSMax Filippov /* 34449b424feSMax Filippov * Initialize WB, WS, and clear PS.EXCM (to allow loop instructions). 34549b424feSMax Filippov * Set Interrupt Level just below XCHAL_DEBUGLEVEL to allow 34649b424feSMax Filippov * xt-gdb to single step via DEBUG exceptions received directly 34749b424feSMax Filippov * by ocd. 34849b424feSMax Filippov */ 34949b424feSMax Filippov movi a1, 1 35049b424feSMax Filippov movi a0, 0 35149b424feSMax Filippov wsr a1, windowstart 35249b424feSMax Filippov wsr a0, windowbase 35349b424feSMax Filippov rsync 35449b424feSMax Filippov 35549b424feSMax Filippov movi a1, LOCKLEVEL 35649b424feSMax Filippov wsr a1, ps 35749b424feSMax Filippov rsync 35849b424feSMax Filippov 35949b424feSMax Filippov j _startup 36049b424feSMax Filippov 36149b424feSMax FilippovENDPROC(cpu_restart) 36249b424feSMax Filippov 36349b424feSMax Filippov#endif /* CONFIG_HOTPLUG_CPU */ 36449b424feSMax Filippov 365adba09f0SChris Zankel/* 366f615136cSMax Filippov * DATA section 367f615136cSMax Filippov */ 368f615136cSMax Filippov 3699fab17caSMax Filippov __REFDATA 370f615136cSMax Filippov .align 4 371f615136cSMax FilippovENTRY(start_info) 372f615136cSMax Filippov .long init_thread_union + KERNEL_STACK_SIZE 373f615136cSMax Filippov 374f615136cSMax Filippov/* 375adba09f0SChris Zankel * BSS section 3765a0015d6SChris Zankel */ 3775a0015d6SChris Zankel 37802b7da37STim Abbott__PAGE_ALIGNED_BSS 379e5083a63SJohannes Weiner#ifdef CONFIG_MMU 380adba09f0SChris ZankelENTRY(swapper_pg_dir) 381adba09f0SChris Zankel .fill PAGE_SIZE, 1, 0 382d1538c46SChris ZankelEND(swapper_pg_dir) 383e5083a63SJohannes Weiner#endif 384adba09f0SChris ZankelENTRY(empty_zero_page) 385adba09f0SChris Zankel .fill PAGE_SIZE, 1, 0 386d1538c46SChris ZankelEND(empty_zero_page) 387