xref: /linux/arch/nios2/kernel/head.S (revision e5451c8f8330e03ad3cfa16048b4daf961af434f)
1*27d22413SLey Foon Tan/*
2*27d22413SLey Foon Tan * Copyright (C) 2009 Wind River Systems Inc
3*27d22413SLey Foon Tan *   Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
4*27d22413SLey Foon Tan * Copyright (C) 2004 Microtronix Datacom Ltd
5*27d22413SLey Foon Tan * Copyright (C) 2001 Vic Phillips, Microtronix Datacom Ltd.
6*27d22413SLey Foon Tan *
7*27d22413SLey Foon Tan * Based on head.S for Altera's Excalibur development board with nios processor
8*27d22413SLey Foon Tan *
9*27d22413SLey Foon Tan * Based on the following from the Excalibur sdk distribution:
10*27d22413SLey Foon Tan *	NA_MemoryMap.s, NR_JumpToStart.s, NR_Setup.s, NR_CWPManager.s
11*27d22413SLey Foon Tan *
12*27d22413SLey Foon Tan * This file is subject to the terms and conditions of the GNU General Public
13*27d22413SLey Foon Tan * License. See the file "COPYING" in the main directory of this archive
14*27d22413SLey Foon Tan * for more details.
15*27d22413SLey Foon Tan */
16*27d22413SLey Foon Tan
17*27d22413SLey Foon Tan#include <linux/init.h>
18*27d22413SLey Foon Tan#include <linux/linkage.h>
19*27d22413SLey Foon Tan#include <asm/thread_info.h>
20*27d22413SLey Foon Tan#include <asm/processor.h>
21*27d22413SLey Foon Tan#include <asm/cache.h>
22*27d22413SLey Foon Tan#include <asm/page.h>
23*27d22413SLey Foon Tan#include <asm/asm-offsets.h>
24*27d22413SLey Foon Tan#include <asm/asm-macros.h>
25*27d22413SLey Foon Tan
26*27d22413SLey Foon Tan/*
27*27d22413SLey Foon Tan * ZERO_PAGE is a special page that is used for zero-initialized
28*27d22413SLey Foon Tan * data and COW.
29*27d22413SLey Foon Tan */
30*27d22413SLey Foon Tan.data
31*27d22413SLey Foon Tan.global empty_zero_page
32*27d22413SLey Foon Tan.align 12
33*27d22413SLey Foon Tanempty_zero_page:
34*27d22413SLey Foon Tan	.space	PAGE_SIZE
35*27d22413SLey Foon Tan
36*27d22413SLey Foon Tan/*
37*27d22413SLey Foon Tan * This global variable is used as an extension to the nios'
38*27d22413SLey Foon Tan * STATUS register to emulate a user/supervisor mode.
39*27d22413SLey Foon Tan */
40*27d22413SLey Foon Tan	.data
41*27d22413SLey Foon Tan	.align	2
42*27d22413SLey Foon Tan	.set noat
43*27d22413SLey Foon Tan
44*27d22413SLey Foon Tan	.global _current_thread
45*27d22413SLey Foon Tan_current_thread:
46*27d22413SLey Foon Tan	.long	0
47*27d22413SLey Foon Tan/*
48*27d22413SLey Foon Tan * Input(s): passed from u-boot
49*27d22413SLey Foon Tan *   r4 - Optional pointer to a board information structure.
50*27d22413SLey Foon Tan *   r5 - Optional pointer to the physical starting address of the init RAM
51*27d22413SLey Foon Tan *        disk.
52*27d22413SLey Foon Tan *   r6 - Optional pointer to the physical ending address of the init RAM
53*27d22413SLey Foon Tan *        disk.
54*27d22413SLey Foon Tan *   r7 - Optional pointer to the physical starting address of any kernel
55*27d22413SLey Foon Tan *        command-line parameters.
56*27d22413SLey Foon Tan */
57*27d22413SLey Foon Tan
58*27d22413SLey Foon Tan/*
59*27d22413SLey Foon Tan * First executable code - detected and jumped to by the ROM bootstrap
60*27d22413SLey Foon Tan * if the code resides in flash (looks for "Nios" at offset 0x0c from
61*27d22413SLey Foon Tan * the potential executable image).
62*27d22413SLey Foon Tan */
63*27d22413SLey Foon Tan	__HEAD
64*27d22413SLey Foon TanENTRY(_start)
65*27d22413SLey Foon Tan	wrctl	status, r0		/* Disable interrupts */
66*27d22413SLey Foon Tan
67*27d22413SLey Foon Tan	/* Initialize all cache lines within the instruction cache */
68*27d22413SLey Foon Tan	movia	r1, NIOS2_ICACHE_SIZE
69*27d22413SLey Foon Tan	movui	r2, NIOS2_ICACHE_LINE_SIZE
70*27d22413SLey Foon Tan
71*27d22413SLey Foon Tanicache_init:
72*27d22413SLey Foon Tan	initi	r1
73*27d22413SLey Foon Tan	sub	r1, r1, r2
74*27d22413SLey Foon Tan	bgt	r1, r0, icache_init
75*27d22413SLey Foon Tan	br	1f
76*27d22413SLey Foon Tan
77*27d22413SLey Foon Tan	/*
78*27d22413SLey Foon Tan	 * This is the default location for the exception handler. Code in jump
79*27d22413SLey Foon Tan	 * to our handler
80*27d22413SLey Foon Tan	 */
81*27d22413SLey Foon TanENTRY(exception_handler_hook)
82*27d22413SLey Foon Tan	movia	r24, inthandler
83*27d22413SLey Foon Tan	jmp	r24
84*27d22413SLey Foon Tan
85*27d22413SLey Foon TanENTRY(fast_handler)
86*27d22413SLey Foon Tan	nextpc et
87*27d22413SLey Foon Tanhelper:
88*27d22413SLey Foon Tan	stw	r3, r3save - helper(et)
89*27d22413SLey Foon Tan
90*27d22413SLey Foon Tan	rdctl	r3 , pteaddr
91*27d22413SLey Foon Tan	srli	r3, r3, 12
92*27d22413SLey Foon Tan	slli	r3, r3, 2
93*27d22413SLey Foon Tan	movia	et, pgd_current
94*27d22413SLey Foon Tan
95*27d22413SLey Foon Tan	ldw	et, 0(et)
96*27d22413SLey Foon Tan	add	r3, et, r3
97*27d22413SLey Foon Tan	ldw	et, 0(r3)
98*27d22413SLey Foon Tan
99*27d22413SLey Foon Tan	rdctl	r3, pteaddr
100*27d22413SLey Foon Tan	andi	r3, r3, 0xfff
101*27d22413SLey Foon Tan	add	et, r3, et
102*27d22413SLey Foon Tan	ldw	et, 0(et)
103*27d22413SLey Foon Tan	wrctl	tlbacc, et
104*27d22413SLey Foon Tan	nextpc	et
105*27d22413SLey Foon Tanhelper2:
106*27d22413SLey Foon Tan	ldw	r3, r3save - helper2(et)
107*27d22413SLey Foon Tan	subi	ea, ea, 4
108*27d22413SLey Foon Tan	eret
109*27d22413SLey Foon Tanr3save:
110*27d22413SLey Foon Tan	.word 0x0
111*27d22413SLey Foon TanENTRY(fast_handler_end)
112*27d22413SLey Foon Tan
113*27d22413SLey Foon Tan1:
114*27d22413SLey Foon Tan	/*
115*27d22413SLey Foon Tan	 * After the instruction cache is initialized, the data cache must
116*27d22413SLey Foon Tan	 * also be initialized.
117*27d22413SLey Foon Tan	 */
118*27d22413SLey Foon Tan	movia	r1, NIOS2_DCACHE_SIZE
119*27d22413SLey Foon Tan	movui	r2, NIOS2_DCACHE_LINE_SIZE
120*27d22413SLey Foon Tan
121*27d22413SLey Foon Tandcache_init:
122*27d22413SLey Foon Tan	initd	0(r1)
123*27d22413SLey Foon Tan	sub	r1, r1, r2
124*27d22413SLey Foon Tan	bgt	r1, r0, dcache_init
125*27d22413SLey Foon Tan
126*27d22413SLey Foon Tan	nextpc	r1			/* Find out where we are */
127*27d22413SLey Foon Tanchkadr:
128*27d22413SLey Foon Tan	movia	r2, chkadr
129*27d22413SLey Foon Tan	beq	r1, r2,finish_move	/* We are running in RAM done */
130*27d22413SLey Foon Tan	addi	r1, r1,(_start - chkadr)	/* Source */
131*27d22413SLey Foon Tan	movia	r2, _start		/* Destination */
132*27d22413SLey Foon Tan	movia	r3, __bss_start		/* End of copy */
133*27d22413SLey Foon Tan
134*27d22413SLey Foon Tanloop_move:				/* r1: src, r2: dest, r3: last dest */
135*27d22413SLey Foon Tan	ldw	r8, 0(r1)		/* load a word from [r1] */
136*27d22413SLey Foon Tan	stw	r8, 0(r2)		/* store a word to dest [r2] */
137*27d22413SLey Foon Tan	flushd	0(r2)			/* Flush cache for safety */
138*27d22413SLey Foon Tan	addi 	r1, r1, 4		/* inc the src addr */
139*27d22413SLey Foon Tan	addi	r2, r2, 4		/* inc the dest addr */
140*27d22413SLey Foon Tan	blt	r2, r3, loop_move
141*27d22413SLey Foon Tan
142*27d22413SLey Foon Tan	movia	r1, finish_move		/* VMA(_start)->l1 */
143*27d22413SLey Foon Tan	jmp	r1			/* jmp to _start */
144*27d22413SLey Foon Tan
145*27d22413SLey Foon Tanfinish_move:
146*27d22413SLey Foon Tan
147*27d22413SLey Foon Tan	/* Mask off all possible interrupts */
148*27d22413SLey Foon Tan	wrctl	ienable, r0
149*27d22413SLey Foon Tan
150*27d22413SLey Foon Tan	/* Clear .bss */
151*27d22413SLey Foon Tan	movia	r2, __bss_start
152*27d22413SLey Foon Tan	movia	r1, __bss_stop
153*27d22413SLey Foon Tan1:
154*27d22413SLey Foon Tan	stb	r0, 0(r2)
155*27d22413SLey Foon Tan	addi	r2, r2, 1
156*27d22413SLey Foon Tan	bne	r1, r2, 1b
157*27d22413SLey Foon Tan
158*27d22413SLey Foon Tan	movia	r1, init_thread_union	/* set stack at top of the task union */
159*27d22413SLey Foon Tan	addi	sp, r1, THREAD_SIZE
160*27d22413SLey Foon Tan	movia	r2, _current_thread	/* Remember current thread */
161*27d22413SLey Foon Tan	stw	r1, 0(r2)
162*27d22413SLey Foon Tan
163*27d22413SLey Foon Tan	movia	r1, nios2_boot_init	/* save args r4-r7 passed from u-boot */
164*27d22413SLey Foon Tan	callr	r1
165*27d22413SLey Foon Tan
166*27d22413SLey Foon Tan	movia	r1, start_kernel	/* call start_kernel as a subroutine */
167*27d22413SLey Foon Tan	callr	r1
168*27d22413SLey Foon Tan
169*27d22413SLey Foon Tan	/* If we return from start_kernel, break to the oci debugger and
170*27d22413SLey Foon Tan	 * buggered we are.
171*27d22413SLey Foon Tan	 */
172*27d22413SLey Foon Tan	break
173*27d22413SLey Foon Tan
174*27d22413SLey Foon Tan	/* End of startup code */
175*27d22413SLey Foon Tan.set at
176