xref: /netbsd/sys/arch/emips/stand/common/prom_iface.c (revision 6550d01e)
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