viper_start.S revision 1.1 1 /* $NetBSD: viper_start.S,v 1.1 2005/06/06 20:24:11 pooka Exp $ */
2
3 /*
4 * Copyright (c) 2005 Antti Kantee. All Rights Reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by The NetBSD
17 * Foundation, Inc. and its contributors.
18 * 4. The name of the company nor the name of the author may be used to
19 * endorse or promote products derived from this software without specific
20 * prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
23 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #include <machine/asm.h>
36 #include <arm/armreg.h>
37 #include <arm/arm32/pmap.h>
38 #include <arm/arm32/pte.h>
39
40 /*
41 * We start out with RAM mapped to the bottom 64MB. We are jogging
42 * happily there with the MMU on. Our mission: map some important
43 * bootstrap devices (such as console port) in addition to mapping
44 * the physical RAM to 0xc0...
45 *
46 * If I try to create a mapping from scratch, something important gets
47 * wiped out (never could figure out exactly what), so we do this with
48 * the MMU on adding to the existing translation table.
49 */
50
51 #define CPWAIT_BRANCH \
52 sub pc, pc, #4
53
54 #define CPWAIT(tmp) \
55 mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\
56 mov tmp, tmp /* wait for it to complete */ ;\
57 CPWAIT_BRANCH /* branch to next insn */
58
59 #ifndef SDRAM_START
60 #define SDRAM_START 0xa0000000
61 #endif
62
63 .text
64
65 .global _C_LABEL(viper_start)
66 _C_LABEL(viper_start):
67
68 /* Figure out where we want to jump to when the time comes */
69 adr r8, .Linva
70 ldr r8, [r8]
71
72 /*
73 * Start playing with the virtual address space mapping
74 * for initial bootstrap.
75 *
76 * Load registers, which will remain constant throughout
77 * building the VA mapping.
78 */
79 mov r2, #(L1_S_SIZE) /* 1MB chunks */
80
81 /*
82 * First map SDRAM VA == PA. This enables us to cut&waste
83 * some existing initarm() code without modification
84 * (and, if, god forbid, someone would like to unify them
85 * some day, this'll make that job easier)
86 */
87 mrc p15, 0, r0, c2, c0, 0 /* Get L1 */
88 bic r0, r0, #0xff000000
89 add r0, r0, #(0xa00 * 4) /* offset to 0xa0.. */
90
91 mov r3, #SDRAM_START /* map to 0xa00.. */
92 orr r3, r3, #(L1_S_AP(AP_KRW)) /* the usual perms & stuff */
93 orr r3, r3, #(L1_TYPE_S)
94 orr r3, r3, #(L1_S_DOM(PMAP_DOMAIN_KERNEL))
95 mov r1, #0x40 /* 64 1MB entries */
96
97 1:
98 /* and looplooploop */
99 str r3, [r0], #4
100 add r3, r3, r2
101 subs r1, r1, #1
102 bgt 1b
103
104 /*
105 * Map SDRAM also to VA 0xc00...
106 */
107 mrc p15, 0, r0, c2, c0, 0 /* Get L1 */
108 bic r0, r0, #0xff000000
109 add r0, r0, #(0xc00 * 4) /* start from 0xc00.. */
110
111 mov r3, #SDRAM_START /* map to 0xa00.. */
112 orr r3, r3, #(L1_S_AP(AP_KRW)) /* the usual perms & stuff */
113 orr r3, r3, #(L1_TYPE_S)
114 orr r3, r3, #(L1_S_DOM(PMAP_DOMAIN_KERNEL))
115 mov r1, #0x40 /* 64 1MB entries */
116
117 1:
118 /* and looplooploop */
119 str r3, [r0], #4
120 add r3, r3, r2
121 subs r1, r1, #1
122 bgt 1b
123
124 /*
125 * Here come the devices. Map an L1 section for each device
126 * to make this easy.
127 */
128
129 /* INTCTL */
130 mrc p15, 0, r0, c2, c0, 0 /* Get L1 */
131 bic r0, r0, #0xff000000
132 add r0, r0, #(0xfd0 * 4) /* offset to 0xfd000000 */
133
134 mov r3, #0x40000000
135 orr r3, r3, #0x00d00000
136 orr r3, r3, #(L1_S_AP(AP_KRW))
137 orr r3, r3, #(L1_TYPE_S)
138 orr r3, r3, #(L1_S_DOM(PMAP_DOMAIN_KERNEL))
139 str r3, [r0], #4
140
141 /* GPIO */
142 mov r3, #0x40000000
143 orr r3, r3, #0x00e00000
144 orr r3, r3, #(L1_S_AP(AP_KRW))
145 orr r3, r3, #(L1_TYPE_S)
146 orr r3, r3, #(L1_S_DOM(PMAP_DOMAIN_KERNEL))
147 str r3, [r0], #4
148
149 /* CLKMAN */
150 mov r3, #0x41000000
151 orr r3, r3, #0x00300000
152 orr r3, r3, #(L1_S_AP(AP_KRW))
153 orr r3, r3, #(L1_TYPE_S)
154 orr r3, r3, #(L1_S_DOM(PMAP_DOMAIN_KERNEL))
155 str r3, [r0], #4
156
157 /* FFUART */
158 mov r3, #0x40000000
159 orr r3, r3, #0x00100000
160 orr r3, r3, #(L1_S_AP(AP_KRW))
161 orr r3, r3, #(L1_TYPE_S)
162 orr r3, r3, #(L1_S_DOM(PMAP_DOMAIN_KERNEL))
163 str r3, [r0], #4
164
165 /* BTUART */
166 mov r3, #0x40000000
167 orr r3, r3, #0x00200000
168 orr r3, r3, #(L1_S_AP(AP_KRW))
169 orr r3, r3, #(L1_TYPE_S)
170 orr r3, r3, #(L1_S_DOM(PMAP_DOMAIN_KERNEL))
171 str r3, [r0], #4
172
173 #if 0
174 /*
175 * Cache cleanup. Not needed here? Slight speedup in booting.
176 */
177 mov r3, #(DCACHE_SIZE)
178 subs r3, r3, #32
179 1:
180 mcr p15, 0, r3, c7, c10, 2
181 subs r3, r3, #32
182 bne 1b
183 CPWAIT(r3)
184
185 /* Drain write buffer */
186 mcr p15, 0, r6, c7, c10, 4
187 #endif
188
189 /*
190 * Make domain control go ful fart.
191 * We probably could be slightly more sensible about this,
192 * but it'll be replaced soon anyway, so why bother.
193 */
194 mov r0, #0xffffffff
195 mcr p15, 0, r0, c3, c0, 0
196
197 /*
198 * Relocate the kernel to where we want it, not where Redboot
199 * let's us load it. Don't bother jumping after this stage,
200 * we'll do that soon enough anyway, and to the correct virtual
201 * address space region I might add.
202 */
203 adr r0, _C_LABEL(viper_start) /* start copy from here */
204 add r0, r0, #SDRAM_START /* offset to SDRAM mapping */
205
206 ldr r1, .Lcopy_size /* copy this much (bytes) */
207 add r1, r1, #3 /* prepare for roundup */
208 mov r1, r1, LSR #2 /* make it words */
209
210 mov r2, #SDRAM_START /* target address, */
211 add r2, r2, #0x00200000 /* kernel offsets by 2megs */
212
213 /* after this it's just a load-store-loop */
214 1:
215 ldr r3, [r0], #4
216 str r3, [r2], #4
217 subs r1, r1, #1
218 bgt 1b
219
220 /*
221 * Now let's clean the cache again to make sure everything
222 * is in place.
223 *
224 * XXX: should this take into account the XScale cache clean bug?
225 */
226 mov r3, #(DCACHE_SIZE)
227 subs r3, r3, #32
228 1:
229 mcr p15, 0, r3, c7, c10, 2
230 subs r3, r3, #32
231 bne 1b
232 CPWAIT(r3)
233
234 /* Drain write buffer */
235 mcr p15, 0, r6, c7, c10, 4
236
237 /* Invalidate TLBs just to be sure */
238 mcr p15, 0, r0, c8, c7, 0
239
240 /*
241 * You are standing at the gate to NetBSD. --More--
242 * Unspeakable cruelty and harm lurk down there. --More--
243 * Are you sure you want to enter?
244 */
245 mov pc, r8 /* So be it */
246
247 /* symbol to use for address calculation in the right VA */
248 .Linva:
249 .word start
250
251 /*
252 * Calculate size of kernel to copy. Don't bother to copy bss,
253 * although I guess the CPU could use the warmup exercise ...
254 */
255 .Lcopy_size:
256 .word _edata - _C_LABEL(viper_start)
257