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