Home | History | Annotate | Line # | Download | only in common
      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 
     55 static void *nope(void) {return NULL;}
     56 int getchar(void){return GetChar();}
     57 
     58 static void
     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
     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 
    149 void epmc_halt(void)
    150 {
    151     struct _Pmc *pm = (struct _Pmc *)0xfff00000;
    152 
    153     pm->SystemPowerDisable = PMCSC_CPU;
    154 }
    155 
    156 
    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 
    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 
    341 void save_locore(void)
    342 {
    343     memcpy(startjump,start,sizeof startjump);
    344     memcpy(exceptioncode,ExceptionHandler,sizeof exceptioncode);
    345 }
    346 
    347 void restore_locore(void)
    348 {
    349     memcpy(start,startjump,sizeof startjump);
    350     memcpy(ExceptionHandler,exceptioncode,sizeof exceptioncode);
    351     /* BUGBUG flush icache */
    352 }
    353 
    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