1 /* Copyright (c) 1999 The NetBSD Foundation, Inc.
2 * All rights reserved.
3 *
4 * Copyright (c) 2008 Microsoft. 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 *
15 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <lib/libsa/stand.h>
30 #include <lib/libsa/loadfile.h>
31 #include <lib/libkern/libkern.h>
32
33 #include <sys/param.h>
34 #include <sys/exec.h>
35 #include <sys/exec_elf.h>
36 #include <sys/reboot.h>
37
38 #include <machine/emipsreg.h>
39
40 #include "common.h"
41 #include "bootinfo.h"
42 #include "start.h"
43 #include "prom_iface.h"
44
45 #if _DEBUG
46 #define TRACE(x) printf x
47 #else
48 #define TRACE(x)
49 #endif
50
51 void epmc_halt(void);
52 void save_locore(void);
53 void restore_locore(void);
54
nope(void)55 static void *nope(void) {return NULL;}
getchar(void)56 int getchar(void){return GetChar();}
57
58 static void
real_halt(void * arg)59 real_halt(void *arg)
60 {
61 int howto = (int)arg;
62 u_int ps = GetPsr();
63
64 /* Turn off interrupts and the TLB */
65 #define EMIPS_SR_RP 0x08000000 /* reduced power */
66 #define EMIPS_SR_TS 0x00200000 /* TLB shutdown */
67 #define EMIPS_SR_RST 0x00000080 /* Soft-reset */
68 #define EMIPS_SR_INT 0x0000ff00 /* Interrupt enable mask */
69 #define EMIPS_SR_IEc 0x00000001 /* Interrupt enable current */
70
71 ps &= ~(EMIPS_SR_INT | EMIPS_SR_IEc);
72 ps |= EMIPS_SR_TS;
73 SetPsr(ps);
74
75 /* Reset entry must be restored for reboot
76 */
77 restore_locore();
78
79 /* Tell the power manager to halt? */
80 for (;howto & RB_HALT;) {
81 epmc_halt();
82
83 /* We should not be here!! */
84 ps |= EMIPS_SR_RP | EMIPS_SR_INT; /* but not current */
85 SetPsr(ps);
86 }
87
88 /* For a reboot, all we can really do is a reset actually */
89 for (;;) {
90 ps |= EMIPS_SR_RST;
91 SetPsr(ps);
92 }
93 }
94
95 static void
halt(int * unused,int howto)96 halt(int *unused, int howto)
97 {
98 /* We must switch to a safe stack! TLB will go down
99 */
100 switch_stack_and_call((void *)howto,real_halt);
101 /* no return, stack lost */
102 }
103
104 struct callback cb = {
105 nope,
106 nope,
107 nope,
108 nope,
109 nope,
110 nope,
111 nope,
112 nope,
113 nope,
114 getchar,
115 nope,
116 nope,
117 printf,
118 nope,
119 nope,
120 nope,
121 nope,
122 nope,
123 nope,
124 nope,
125 nope,
126 nope,
127 nope,
128 nope,
129 nope,
130 nope,
131 nope,
132 nope,
133 nope,
134 nope,
135 nope,
136 nope,
137 getsysid,
138 nope,
139 nope,
140 nope,
141 nope,
142 nope,
143 nope,
144 halt
145 };
146
147 typedef char *string_t;
148
epmc_halt(void)149 void epmc_halt(void)
150 {
151 struct _Pmc *pm = (struct _Pmc *)0xfff00000;
152
153 pm->SystemPowerDisable = PMCSC_CPU;
154 }
155
156
init_usart(void)157 int init_usart(void)
158 {
159 struct _Usart *us = (struct _Usart *)0xfff90000;
160
161 us->Baud = 0x29;
162 us->Control = (USC_RXEN|USC_TXEN|USC_BPC_8|USC_NONE|USC_1STOP|USC_CLKDIV_4);
163 return 1;
164 }
165
166 /* Need to scan the PMT for all memory controllers
167 * Actually.. just enough to make the kernel fit but we dont know how big it is
168 */
169
170 /* Common format for SRAM, DDRAM, and FLASH controllers.
171 * Use SRAM decl. and careful about DDRAM that is twice as big.
172 */
173 typedef struct _Sram *ram_controller_t;
174 # define RAMBT_TAG SRAMBT_TAG
175 # define RAMBT_BASE SRAMBT_BASE
176 # define RAMST_SIZE SRAMST_SIZE
177
init_memory(void)178 int init_memory(void)
179 {
180 struct _Pmt *Pmt;
181 ram_controller_t Ram, Ours, First;
182 uint32_t base, addr, moi = (uint32_t)(&init_memory) & 0x3ffff000;
183 size_t size;
184 uint16_t tag;
185 int nsr, ndr, nfl;
186
187 /* Make three passes.
188 * First find which controller we are running under, cuz we cant touch it.
189 * Then remap every RAM segment around it.
190 * Then make sure FLASH segments do not overlap RAM.
191 */
192
193 nsr = ndr = nfl = 0;
194 First = Ours = NULL;
195 base = ~0;
196 for (Pmt = ThePmt;;Pmt--) {
197 tag = Pmt->Tag;
198 //printf("PMT @%x tag=%x\n",Pmt,tag);
199 switch (tag) {
200 case PMTTAG_END_OF_TABLE:
201 goto DoneFirst;
202 case PMTTAG_SRAM:
203 case PMTTAG_DDRAM:
204 case PMTTAG_FLASH:
205 Ram = (ram_controller_t)(Pmt->TopOfPhysicalAddress << 16);
206 /* Scan the whole segment */
207 for (;;) {
208 //printf("RAM @%x tag=%x ctl=%x\n", Ram, Ram->BaseAddressAndTag,Ram->Control);
209 if (tag != (Ram->BaseAddressAndTag & RAMBT_TAG))
210 break;
211 addr = Ram->BaseAddressAndTag & RAMBT_BASE;
212 if ((tag != PMTTAG_FLASH) && (addr < base)) {
213 base = addr;
214 First = Ram;
215 }
216 size = Ram->Control & RAMST_SIZE;
217 if ((moi >= addr) && (moi < (addr + size))) {
218 Ours = Ram;
219 }
220 /* Next one.. and count them */
221 Ram++;
222 switch (tag) {
223 case PMTTAG_SRAM:
224 nsr++;
225 break;
226 case PMTTAG_FLASH:
227 nfl++;
228 break;
229 case PMTTAG_DDRAM:
230 Ram++; /* yeach */
231 ndr++;
232 break;
233 }
234 }
235 break;
236 default:
237 break;
238 }
239 }
240
241 /* Make sure we know */
242 DoneFirst:
243 if ((First == NULL) || (Ours == NULL)) {
244 printf("Bad memory layout (%p, %p), wont work.\n", First, Ours);
245 return 0;
246 }
247
248 /* Second pass now */
249 base += First->BaseAddressAndTag & RAMBT_BASE;
250 for (Pmt = ThePmt;;Pmt--) {
251 tag = Pmt->Tag;
252 //printf("PMT @%x tag=%x\n",Pmt,tag);
253 switch (tag) {
254 case PMTTAG_END_OF_TABLE:
255 goto DoneSecond;
256 case PMTTAG_SRAM:
257 case PMTTAG_DDRAM:
258 case PMTTAG_FLASH:
259 Ram = (ram_controller_t)(Pmt->TopOfPhysicalAddress << 16);
260 /* Scan the whole segment */
261 for (;;) {
262 //printf("RAM @%x tag=%x ctl=%x\n", Ram, Ram->BaseAddressAndTag,Ram->Control);
263 if (tag != (Ram->BaseAddressAndTag & RAMBT_TAG))
264 break;
265 /* Leave us alone */
266 if (Ram == Ours)
267 goto Next;
268 /* Leave the first alone too */
269 if (Ram == First)
270 goto Next;
271 /* We do FLASH next round */
272 if (tag == PMTTAG_FLASH)
273 goto Next;
274
275 addr = Ram->BaseAddressAndTag & RAMBT_BASE;
276 size = Ram->Control & RAMST_SIZE;
277
278 /* Dont make it overlap with us */
279 if ((moi >= base) && (moi < (base + size)))
280 base += Ours->Control & RAMST_SIZE;
281
282 if (addr != base) {
283 printf("remapping %x+%zx to %x\n", addr, size, base);
284 Ram->BaseAddressAndTag = base;
285 }
286 base += size;
287
288 Next:
289 Ram++;
290 if (tag == PMTTAG_DDRAM) Ram++; /* yeach */
291 }
292 break;
293 default:
294 break;
295 }
296 }
297 DoneSecond:
298
299 /* Third pass now: FLASH */
300 for (Pmt = ThePmt;;Pmt--) {
301 tag = Pmt->Tag;
302 //printf("PMT @%x tag=%x\n",Pmt,tag);
303 switch (tag) {
304 case PMTTAG_END_OF_TABLE:
305 goto DoneThird;
306 case PMTTAG_FLASH:
307 Ram = (ram_controller_t)(Pmt->TopOfPhysicalAddress << 16);
308 /* Scan the whole segment */
309 for (;;Ram++) {
310 //printf("RAM @%x tag=%x ctl=%x\n", Ram, Ram->BaseAddressAndTag,Ram->Control);
311 if (tag != (Ram->BaseAddressAndTag & RAMBT_TAG))
312 break;
313 /* Leave us alone */
314 if (Ram == Ours)
315 continue;
316
317 addr = Ram->BaseAddressAndTag & RAMBT_BASE;
318 size = Ram->Control & RAMST_SIZE;
319
320 /* No need to move if it does not overlap RAM */
321 if (addr >= base)
322 continue;
323
324 /* Ahi */
325 printf("remapping FLASH %x+%x to %x\n", addr, size, base);
326 Ram->BaseAddressAndTag = base;
327 base += size;
328 }
329 break;
330 default:
331 break;
332 }
333 }
334 DoneThird:
335 return (nfl<<16) | (nsr << 8) | (ndr << 0);
336 }
337
338 u_int startjump[2];
339 u_int exceptioncode[(0x200-0x080)/4]; /* Change if ExceptionHandlerEnd changes */
340
save_locore(void)341 void save_locore(void)
342 {
343 memcpy(startjump,start,sizeof startjump);
344 memcpy(exceptioncode,ExceptionHandler,sizeof exceptioncode);
345 }
346
restore_locore(void)347 void restore_locore(void)
348 {
349 memcpy(start,startjump,sizeof startjump);
350 memcpy(ExceptionHandler,exceptioncode,sizeof exceptioncode);
351 /* BUGBUG flush icache */
352 }
353
call_kernel(uint32_t addr,char * kname,char * kargs,u_int bim,char * bip)354 void call_kernel(uint32_t addr, char *kname, char *kargs, u_int bim, char *bip)
355 {
356 int argc = 0;
357 string_t argv[3];
358 int code = PROM_MAGIC;
359 struct callback * cv = &cb;
360
361 /* Safeguard ourselves */
362 save_locore();
363
364 if (kargs == NULL) kargs = "";
365 argv[0] = kname;
366 argv[1] = kargs;
367 argv[2] = NULL;
368 argc = 2;
369
370 TRACE(("Geronimo(%x,%s %s)!\n",addr,kname,kargs));
371 ((void(*)(int,char**,int,struct callback *,u_int,char*))addr)
372 (argc,argv,code,cv,bim,bip);
373 }
374
375