prom_iface.c revision 1.1 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
63 void *nope(void) {return NULL;}
64 int getchar(void){return GetChar();}
65
66 void 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 void halt(int *unused, int howto)
103 {
104 /* We must switch to a safe stack! TLB will go down
105 */
106 switch_stack_and_call((void *)howto,real_halt);
107 /* no return, stack lost */
108 }
109
110 struct callback cb = {
111 nope,
112 nope,
113 nope,
114 nope,
115 nope,
116 nope,
117 nope,
118 nope,
119 nope,
120 getchar,
121 nope,
122 nope,
123 printf,
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 nope,
138 nope,
139 nope,
140 nope,
141 nope,
142 nope,
143 getsysid,
144 nope,
145 nope,
146 nope,
147 nope,
148 nope,
149 nope,
150 halt
151 };
152
153 typedef char *string_t;
154
155 void epmc_halt(void)
156 {
157 struct _Pmc *pm = (struct _Pmc *)0xfff00000;
158
159 pm->SystemPowerDisable = PMCSC_CPU;
160 }
161
162
163 int init_usart(void)
164 {
165 struct _Usart *us = (struct _Usart *)0xfff90000;
166
167 us->Baud = 0x29;
168 us->Control = (USC_RXEN|USC_TXEN|USC_BPC_8|USC_NONE|USC_1STOP|USC_CLKDIV_4);
169 return 1;
170 }
171
172 /* Need to scan the PMT for all memory controllers
173 * Actually.. just enough to make the kernel fit but we dont know how big it is
174 */
175
176 /* Common format for SRAM, DDRAM, and FLASH controllers.
177 * Use SRAM decl. and careful about DDRAM that is twice as big.
178 */
179 typedef struct _Sram *ram_controller_t;
180 # define RAMBT_TAG SRAMBT_TAG
181 # define RAMBT_BASE SRAMBT_BASE
182 # define RAMST_SIZE SRAMST_SIZE
183
184 int init_memory(void)
185 {
186 struct _Pmt *Pmt;
187 ram_controller_t Ram, Ours, First;
188 uint32_t base, addr, moi = (uint32_t)(&init_memory) & 0x3ffff000;
189 size_t size;
190 uint16_t tag;
191 int nsr, ndr, nfl;
192
193 /* Make three passes.
194 * First find which controller we are running under, cuz we cant touch it.
195 * Then remap every RAM segment around it.
196 * Then make sure FLASH segments do not overlap RAM.
197 */
198
199 nsr = ndr = nfl = 0;
200 First = Ours = NULL;
201 base = ~0;
202 for (Pmt = ThePmt;;Pmt--) {
203 tag = Pmt->Tag;
204 //printf("PMT @%x tag=%x\n",Pmt,tag);
205 switch (tag) {
206 case PMTTAG_END_OF_TABLE:
207 goto DoneFirst;
208 case PMTTAG_SRAM:
209 case PMTTAG_DDRAM:
210 case PMTTAG_FLASH:
211 Ram = (ram_controller_t)(Pmt->TopOfPhysicalAddress << 16);
212 /* Scan the whole segment */
213 for (;;) {
214 //printf("RAM @%x tag=%x ctl=%x\n", Ram, Ram->BaseAddressAndTag,Ram->Control);
215 if (tag != (Ram->BaseAddressAndTag & RAMBT_TAG))
216 break;
217 addr = Ram->BaseAddressAndTag & RAMBT_BASE;
218 if ((tag != PMTTAG_FLASH) && (addr < base)) {
219 base = addr;
220 First = Ram;
221 }
222 size = Ram->Control & RAMST_SIZE;
223 if ((moi >= addr) && (moi < (addr + size))) {
224 Ours = Ram;
225 }
226 /* Next one.. and count them */
227 Ram++;
228 switch (tag) {
229 case PMTTAG_SRAM:
230 nsr++;
231 break;
232 case PMTTAG_FLASH:
233 nfl++;
234 break;
235 case PMTTAG_DDRAM:
236 Ram++; /* yeach */
237 ndr++;
238 break;
239 }
240 }
241 break;
242 default:
243 break;
244 }
245 }
246
247 /* Make sure we know */
248 DoneFirst:
249 if ((First == NULL) || (Ours == NULL)) {
250 printf("Bad memory layout (%x,%x), wont work.\n", First, Ours);
251 return 0;
252 }
253
254 /* Second pass now */
255 base += First->BaseAddressAndTag & RAMBT_BASE;
256 for (Pmt = ThePmt;;Pmt--) {
257 tag = Pmt->Tag;
258 //printf("PMT @%x tag=%x\n",Pmt,tag);
259 switch (tag) {
260 case PMTTAG_END_OF_TABLE:
261 goto DoneSecond;
262 case PMTTAG_SRAM:
263 case PMTTAG_DDRAM:
264 case PMTTAG_FLASH:
265 Ram = (ram_controller_t)(Pmt->TopOfPhysicalAddress << 16);
266 /* Scan the whole segment */
267 for (;;) {
268 //printf("RAM @%x tag=%x ctl=%x\n", Ram, Ram->BaseAddressAndTag,Ram->Control);
269 if (tag != (Ram->BaseAddressAndTag & RAMBT_TAG))
270 break;
271 /* Leave us alone */
272 if (Ram == Ours)
273 goto Next;
274 /* Leave the first alone too */
275 if (Ram == First)
276 goto Next;
277 /* We do FLASH next round */
278 if (tag == PMTTAG_FLASH)
279 goto Next;
280
281 addr = Ram->BaseAddressAndTag & RAMBT_BASE;
282 size = Ram->Control & RAMST_SIZE;
283
284 /* Dont make it overlap with us */
285 if ((moi >= base) && (moi < (base + size)))
286 base += Ours->Control & RAMST_SIZE;
287
288 if (addr != base) {
289 printf("remapping %x+%x to %x\n", addr, size, base);
290 Ram->BaseAddressAndTag = base;
291 }
292 base += size;
293
294 Next:
295 Ram++;
296 if (tag == PMTTAG_DDRAM) Ram++; /* yeach */
297 }
298 break;
299 default:
300 break;
301 }
302 }
303 DoneSecond:
304
305 /* Third pass now: FLASH */
306 for (Pmt = ThePmt;;Pmt--) {
307 tag = Pmt->Tag;
308 //printf("PMT @%x tag=%x\n",Pmt,tag);
309 switch (tag) {
310 case PMTTAG_END_OF_TABLE:
311 goto DoneThird;
312 case PMTTAG_FLASH:
313 Ram = (ram_controller_t)(Pmt->TopOfPhysicalAddress << 16);
314 /* Scan the whole segment */
315 for (;;Ram++) {
316 //printf("RAM @%x tag=%x ctl=%x\n", Ram, Ram->BaseAddressAndTag,Ram->Control);
317 if (tag != (Ram->BaseAddressAndTag & RAMBT_TAG))
318 break;
319 /* Leave us alone */
320 if (Ram == Ours)
321 continue;
322
323 addr = Ram->BaseAddressAndTag & RAMBT_BASE;
324 size = Ram->Control & RAMST_SIZE;
325
326 /* No need to move if it does not overlap RAM */
327 if (addr >= base)
328 continue;
329
330 /* Ahi */
331 printf("remapping FLASH %x+%x to %x\n", addr, size, base);
332 Ram->BaseAddressAndTag = base;
333 base += size;
334 }
335 break;
336 default:
337 break;
338 }
339 }
340 DoneThird:
341 return (nfl<<16) | (nsr << 8) | (ndr << 0);
342 }
343
344 u_int startjump[2];
345 u_int exceptioncode[(0x200-0x080)/4]; /* Change if ExceptionHandlerEnd changes */
346
347 void save_locore(void)
348 {
349 memcpy(startjump,start,sizeof startjump);
350 memcpy(exceptioncode,ExceptionHandler,sizeof exceptioncode);
351 }
352
353 void restore_locore(void)
354 {
355 memcpy(start,startjump,sizeof startjump);
356 memcpy(ExceptionHandler,exceptioncode,sizeof exceptioncode);
357 /* BUGBUG flush icache */
358 }
359
360 void call_kernel(uint32_t addr, char *kname, char *kargs, u_int bim, char *bip)
361 {
362 int argc = 0;
363 string_t argv[3];
364 int code = PROM_MAGIC;
365 struct callback * cv = &cb;
366
367 /* Safeguard ourselves */
368 save_locore();
369
370 if (kargs == NULL) kargs = "";
371 argv[0] = kname;
372 argv[1] = kargs;
373 argv[2] = NULL;
374 argc = 2;
375
376 TRACE(("Geronimo(%x,%s %s)!\n",addr,kname,kargs));
377 ((void(*)(int,char**,int,struct callback *,u_int,char*))addr)
378 (argc,argv,code,cv,bim,bip);
379 }
380
381