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