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