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