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