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