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