armadillo9_start.S revision 1.4.4.1 1 /* $NetBSD: armadillo9_start.S,v 1.4.4.1 2011/03/05 20:50:02 rmind Exp $ */
2
3 /*
4 * Copyright (c) 2003
5 * Ichiro FUKUHARA <ichiro (at) ichiro.org>.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29 #include "epcom.h"
30
31 #include <machine/asm.h>
32 #include <arm/armreg.h>
33 #include "assym.h"
34
35 RCSID("$NetBSD: armadillo9_start.S,v 1.4.4.1 2011/03/05 20:50:02 rmind Exp $")
36
37 .section .start,"ax",%progbits
38
39 .global _C_LABEL(armadillo9_start)
40 _C_LABEL(armadillo9_start):
41
42 /* make sure svc mode and all fiqs&irqs disabled */
43 mov r0, #(PSR_SVC32_MODE | I32_bit | F32_bit)
44 msr cpsr_c, r0
45
46 /*
47 * We will go ahead and disable the MMU here so that we don't
48 * have to worry about flushing caches, etc.
49 *
50 * Note that we may not currently be running VA==PA, which means
51 * we'll need to leap to the next insn after disabing the MMU.
52 */
53 adr r8, Lunmapped
54 bic r8, r8, #0xff000000 /* clear upper 8 bits */
55 orr r8, r8, #0xc0000000 /* OR in physical base address */
56
57 /*
58 * Setup coprocessor 15.
59 */
60 mrc p15, 0, r2, c1, c0, 0
61 bic r2, r2, #CPU_CONTROL_MMU_ENABLE
62 bic r2, r2, #CPU_CONTROL_DC_ENABLE
63 bic r2, r2, #CPU_CONTROL_IC_ENABLE
64 mcr p15, 0, r2, c1, c0, 0
65
66 nop
67 nop
68 nop
69 mov pc, r8 /* Heave-ho! */
70
71 Lunmapped:
72 /* set temporary stack pointer */
73 ldr sp, Ltable
74
75 #ifdef VERBOSE_INIT_ARM
76 /* initialize UART */
77 bl init_UART
78 #endif
79 /* copy bootparam */
80 bl copy_bootparam
81
82 /* copy myself to virtual address */
83 bl copy_myself
84
85 /*
86 * We want to construct a memory map that maps us
87 * VA==PA (SDRAM at 0xc0000000). We create these
88 * mappings uncached and unbuffered to be safe.
89 */
90 /*
91 * Step 1: Map the entire address space VA==PA.
92 */
93 adr r4, Ltable
94 ldr r0, [r4] /* r0 = &l1table */
95 mov r1, #(L1_TABLE_SIZE / 4) /* 4096 entry */
96 mov r2, #(L1_S_SIZE) /* 1MB / section */
97 mov r3, #(L1_S_AP_KRW) /* kernel read/write */
98 orr r3, r3, #(L1_TYPE_S) /* L1 entry is section */
99 1:
100 str r3, [r0], #0x04
101 add r3, r3, r2
102 subs r1, r1, #1
103 bgt 1b
104
105 /*
106 * Step 2: Map VA 0xf0000000->0xf00fffff to PA 0x80000000->0x800fffff.
107 */
108 ldr r0, [r4]
109 add r0, r0, #(0xf00 * 4) /* offset to 0xf0000000 */
110 mov r3, #(L1_S_AP_KRW) /* kernel read/write */
111 orr r3, r3, #(L1_TYPE_S) /* L1 entry is section */
112 orr r3, r3, #0x80000000
113 str r3, [r0], #4
114
115 /*
116 * Step 3: Map VA 0xf0100000->0xf02fffff to PA 0x80800000->0x809fffff.
117 */
118 mov r3, #(L1_S_AP_KRW) /* kernel read/write */
119 orr r3, r3, #(L1_TYPE_S) /* L1 entry is section */
120 orr r3, r3, #0x80000000
121 orr r3, r3, #0x00800000
122 str r3, [r0], #0x4
123 add r3, r3, r2
124 str r3, [r0], #0x4
125
126 /* OK! Page table is set up. Give it to the CPU. */
127 adr r0, Ltable
128 ldr r0, [r0]
129 mcr p15, 0, r0, c2, c0, 0
130
131 /* Flush the old TLBs, just in case. */
132 mcr p15, 0, r0, c8, c7, 0
133
134 /* Set the Domain Access register. Very important! */
135 mov r0, #1
136 mcr p15, 0, r0, c3, c0, 0
137
138 /* Get ready to jump to the "real" kernel entry point... */
139 ldr r1, Lstart
140 mov r1, r1 /* Make sure the load completes! */
141
142 /* OK, let's enable the MMU. */
143 mrc p15, 0, r2, c1, c0, 0
144 orr r2, r2, #CPU_CONTROL_MMU_ENABLE
145 mcr p15, 0, r2, c1, c0, 0
146
147 nop
148 nop
149 nop
150
151 /* CPWAIT sequence to make sure the MMU is on... */
152 mrc p15, 0, r2, c2, c0, 0 /* arbitrary read of CP15 */
153 mov r2, r2 /* force it to complete */
154 mov pc, r1 /* leap to kernel entry point! */
155
156 #define BOOTPARAM_ADDRESS 0xc0000100
157 #define BOOTPARAM_SIZE 0x0f00
158
159 Ltable:
160 .word armadillo9_start - L1_TABLE_SIZE
161 Lstart:
162 .word start
163
164 Lsection:
165 .word .start
166 .word 0xc0200000
167 .word __bss_start
168
169 Lbootparam_address:
170 .word BOOTPARAM_ADDRESS
171
172 copy_myself:
173 stmfd sp!, {r0-r5, lr}
174 adr r0, Lsection
175 ldmia r0, {r1, r2, r4} /* r1: kernel(load) start address */
176 /* r2: kernel(virtual) start address */
177 /* r3: kernel size */
178 sub r3, r4, r2 /* r4: kernel(virtual) end address */
179 add r5, r1, r3 /* r5: kernel(load) end address */
180 #ifdef VERBOSE_INIT_ARM
181 adr r0, Lmsg1 /* "copy kernel from " */
182 bl print_str
183 bl print_r1
184 adr r0, Lmsg2 /* " to " */
185 bl print_str
186 bl print_r2
187 adr r0, Lmsg3 /* " size " */
188 bl print_str
189 bl print_r3
190 bl print_cr
191 #endif
192 1:
193 ldr r0, [r5], #-4
194 str r0, [r4], #-4
195 cmp r5, r1
196 bge 1b
197 ldmfd sp!, {r0-r5, pc}
198
199 copy_bootparam:
200 stmfd sp!, {r0-r3, lr}
201 mov r1, #BOOTPARAM_SIZE
202 ldr r2, Lbootparam_address
203 adr r3, _C_LABEL(bootparam)
204 #ifdef VERBOSE_INIT_ARM
205 adr r0, Lmsg0 /* "copy bootparam from " */
206 bl print_str
207 bl print_r2
208 adr r0, Lmsg2 /* " to " */
209 bl print_str
210 bl print_r3
211 adr r0, Lmsg3 /* " size " */
212 bl print_str
213 bl print_r1
214 bl print_cr
215 #endif
216 1:
217 ldr r0, [r2], #4
218 str r0, [r3], #4
219 subs r1, r1, #4
220 bne 1b
221 ldmfd sp!, {r0-r3, pc}
222
223 #ifdef VERBOSE_INIT_ARM
224 Lmsg0:
225 .asciz "copy bootparam from "
226 .align 0
227 Lmsg1:
228 .asciz "copy kernel from "
229 .align 0
230 Lmsg2:
231 .asciz " to "
232 .align 0
233 Lmsg3:
234 .asciz " size "
235 .align 0
236
237 #if NEPCOM > 0
238 #define EP93XX_APB_UART1 0x808c0000
239 #define EP93XX_APB_UART2 0x808d0000
240
241 #ifndef CONUNIT
242 #define CONUNIT 0
243 #endif
244
245 Lcomaddr:
246 .word EP93XX_APB_UART1
247 .word EP93XX_APB_UART2
248 #endif
249
250 init_UART:
251 stmfd sp!, {r4-r5, lr}
252 #if NEPCOM > 0
253 ldr r4, Lcomaddr+(CONUNIT*4)
254 ldr r5, [r4, #0x08]
255 orr r5, r5, #0x10
256 str r5, [r4, #0x08] /* enable FIFO */
257 mov r5, #0x01
258 str r5, [r4, #0x14] /* disable interrupt */
259 #endif
260 ldmfd sp!, {r4-r5, pc}
261
262 print_char: /* char = r0 */
263 stmfd sp!, {r4-r5, lr}
264 #if NEPCOM > 0
265 ldr r4, Lcomaddr+(CONUNIT*4)
266 1:
267 ldr r5, [r4, #0x18]
268 tst r5, #0x20 /* check TXFF */
269 bne 1b
270 str r0, [r4, #0x00]
271 #endif
272 ldmfd sp!, {r4-r5, pc}
273
274 print_cr:
275 stmfd sp!, {r0, lr}
276 #if NEPCOM > 0
277 mov r0, #0x0d /* cr */
278 bl print_char
279 mov r0, #0x0a /* lf */
280 bl print_char
281 #endif
282 ldmfd sp!, {r0, pc}
283
284 print_str:
285 stmfd sp!, {r0, r4, lr}
286 #if NEPCOM > 0
287 mov r4, r0
288 1:
289 ldrb r0, [r4], #1
290 cmp r0, #0
291 beq 2f
292 bl print_char
293 b 1b
294 2:
295 #endif
296 ldmfd sp!, {r0, r4, pc}
297
298 print_r3:
299 stmfd sp!, {r0, r3-r6, lr}
300 #if NEPCOM > 0
301 mov r4, #28
302 mov r5, #0xf
303 1:
304 and r6, r5, r3, ROR r4
305 cmp r6, #10
306 addlt r0, r6, #'0'
307 addge r0, r6, #('a' - 0x0a)
308 bl print_char
309 subs r4, r4, #4
310 bge 1b
311 #endif
312 ldmfd sp!, {r0, r3-r6, pc}
313
314 #define print_register(reg) \
315 stmfd sp!, {r3, lr} ;\
316 mov r3, reg ;\
317 bl print_r3 ;\
318 ldmfd sp!, {r3, pc}
319
320 print_r0:
321 print_register(r0)
322
323 print_r1:
324 print_register(r1)
325
326 print_r2:
327 print_register(r2)
328 #endif
329
330 .global _C_LABEL(bootparam)
331 _C_LABEL(bootparam):
332 .space BOOTPARAM_SIZE
333