xref: /openbmc/linux/arch/xtensa/kernel/head.S (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
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