OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [c/] [src/] [lib/] [libbsp/] [mips/] [genmongoosev/] [start/] [start.S] - Rev 1765

Compare with Previous | Blame | View Log

/*
** start.S -- startup file for Mongoose V BSP based upon crt0.S from
** newlib-1.8.2/libgloss/mips and adapted for RTEMS.
**
** crt0.S -- startup file for MIPS.
**
** Copyright (c) 1995, 1996, 1997 Cygnus Support
**
** The authors hereby grant permission to use, copy, modify, distribute,
** and license this software and its documentation for any purpose, provided
** that existing copyright notices are retained in all copies and that this
** notice is included verbatim in any distributions. No written agreement,
** license, or royalty fee is required for any of the authorized uses.
** Modifications to this software may be copyrighted by their authors
** and need not follow the licensing terms described here, provided that
** the new terms are clearly indicated on the first page of each file where
** they apply.
**
**
** Modification History:
**        01/XX/01  Joel Sherrill, OAR Corp,
**           Modified for Mongoose V BSP for NASA/GSFC Code 582.
**
**        06/XX/01  Greg Menke, Raytheon, Code 582
**           Debug modifications. Removed R4000 dependencies.
**           Added HACKED_PMON defines to facilitate startup.
**           Added DEFAULT_EXIT_RETURN_TO_MONITOR option.
**
**        11/14/01  A.Ferrer, NASA/GSFC, Code 582
**           Cleanup for ST5 mission.
**
**        11/27/01  A.Ferrer, NASA/GSFC, Code 582
**           Added cache flush routines.
*/

#ifndef LANGUAGE_ASSEMBLY
#define LANGUAGE_ASSEMBLY
#endif


#include <asm.h>
#include "regs.S"
#include "mg5.h"


        
#ifdef __mips16
   /* This file contains 32 bit assembly code.  */
   .set nomips16
#endif


/*
** defined by linkcmds, pointing to the start of the relocation target
** memory, referenced in this way so we can avoid defining it
** multiply
*/
   .bss
   .word 0
   .text
   .align 2


/**********************************************************************
**
** Function: _start
*/

   /* Without the following nop, GDB thinks _start is a data variable.
   ** This is probably a bug in GDB in handling a symbol that is at the
   ** start of the .text section.
   */
    nop
   .globl  _start
   .ent    _start

   .globl putch_rom
_start:
   .set    noreorder
   $LF1 = . + 8

   /*
   ** Get the address of start into $5 in a position independent fashion.
   ** This lets us know whether we have been relocated or not.
   */

   bal     $LF1
   nop
_branch:
   move    a1, ra      /* save return address from the jump above */

   /* ensure we're sane before doing anything */

   li      t0, SR_CU0|SR_PE
   mtc0    t0, C0_SR
   nop
   li      t0, 0
   mtc0    t0, C0_DCIC
   nop
   mtc0    t0, C0_CAUSE
   nop


   /*
   ** Call cpuinit. Masking used to call EEPROM address of _cpuinit.  Label is RAM label.
   */
   move   t2,a1
   and    t2,0xffff0000
   la     t0,_cpuinit
   and    t0,0x0000ffff
   or     t0,t2
   jal    t0
   nop

   /*
   ** Configure UART
   */
   move   t2,a1
   and    t2,0xffff0000
   la     t0,config_uart
   and    t0,0x0000ffff
   or     t0,t2
   jal    t0
   nop



   /*
   ** Print 'b'.  Show that we started.
   */
   move   t2,a1
   and    t2,0xffff0000
   li     a0,'b'
   la     t0,putch_rom
   and    t0,0x0000ffff
   or     t0,t2
   jal    t0
   nop
        

                        
                

   li   k0,0
   li   k1,0
        
   move t1,a1
   nop
   li   t2,0xa0000000   /* lower limit of kseg1 */
   li   t3,0xbfffffff   /* upper limit of kseg1 */

   subu t0,t1,t2
   srl  t0,31           /* shift high bit down to bit 0 */
   bnez t0,1f           /* booting from below kseg1 */
        
   subu t0,t3,t1
   srl  t0,31           /* shift high bit down to bit 0 */
   bnez t0,1f           /* booting from above kseg1 */

                
        
   /*
   ** Call IcacheFlush. Masking used to call EEPROM address of IcacheFlush.  Label is RAM label.
   */
   move   t2,a1
   and    t2,0xffff0000
   la     t0,IcacheFlush
   and    t0,0x0000ffff
   or     t0,t2
   move   k0,t0         /* save cache flush in-prom address */
   jal    t0
   nop


   /*
   ** Print 'I'.  Show that we flushed I cache.
   */
   move   t2,a1
   and    t2,0xffff0000
   li     a0,'I'
   la     t0,putch_rom
   and    t0,0x0000ffff
   or     t0,t2
   jal    t0
   nop


   /*
   ** Call DcacheFlush. Masking used to call EEPROM address of DcacheFlush.  Label is RAM label.
   */
   move   t2,a1
   and    t2,0xffff0000
   la     t0,DcacheFlush
   and    t0,0x0000ffff
   or     t0,t2
   jal    t0
   nop


   /*
   ** Print 'D'.  Show that we flushed D cache.
   */
   move   t2,a1
   and    t2,0xffff0000
   li     a0,'D'
   la     t0,putch_rom
   and    t0,0x0000ffff
   or     t0,t2
   move   k1,t0         /* save cache flush in-prom address */
   jal    t0
   nop


1:      
   /*
   ** Print ' RTEMS  b'.  Show that we are booting.
   */
   move   t2,a1
   and    t2,0xffff0000
   li     a0,' '
   la     t0,putch_rom
   and    t0,0x0000ffff
   or     t0,t2
   jal    t0
   nop

   move   t2,a1
   and    t2,0xffff0000
   li     a0,'R'
   la     t0,putch_rom
   and    t0,0x0000ffff
   or     t0,t2
   jal    t0
   nop

   move   t2,a1
   and    t2,0xffff0000
   li     a0,'T'
   la     t0,putch_rom
   and    t0,0x0000ffff
   or     t0,t2
   jal    t0
   nop

   move   t2,a1
   and    t2,0xffff0000
   li     a0,'E'
   la     t0,putch_rom
   and    t0,0x0000ffff
   or     t0,t2
   jal    t0
   nop

   move   t2,a1
   and    t2,0xffff0000
   li     a0,'M'
   la     t0,putch_rom
   and    t0,0x0000ffff
   or     t0,t2
   jal    t0
   nop

   move   t2,a1
   and    t2,0xffff0000
   li     a0,'S'
   la     t0,putch_rom
   and    t0,0x0000ffff
   or     t0,t2
   jal    t0
   nop

   move   t2,a1
   and    t2,0xffff0000
   li     a0,' '
   la     t0,putch_rom
   and    t0,0x0000ffff
   or     t0,t2
   jal    t0
   nop

   move   t2,a1
   and    t2,0xffff0000
   li     a0,'b'
   la     t0,putch_rom
   and    t0,0x0000ffff
   or     t0,t2
   jal    t0
   nop


   /*
   ** get the address of the _branch label above as it would appear in
   ** the relocated code
   */

   la  a2, _branch                 /* relocation destination */
   beq a1, a2, _start_in_ram       /* skip relocating if we're already there */
   nop

   /* relocate the code from EEPROM to RAM */

   /*
   ** Print 'r'
   */
   move   t2,a1
   and    t2,0xffff0000
   li     a0,'r'
   la     t0,putch_rom
   and    t0,0x0000ffff
   or     t0,t2
   jal    t0
   nop

   la           a3, _edata
relocate:
   lw           t0, (a1)            /* load from EEPROM */
   addu         a1, 4
   sw           t0, (a2)            /* store to RAM */
   addu         a2, 4
   bne          a2, a3, relocate    /* copied all the way to edata? */
   nop

   /*
   ** Print 'R'
   */
   li     a0,'R'
   la     t0,putch_rom
   and    t0,0x0000ffff
   or     t0,t2
   jal    t0
   nop

   la  a2, _start_in_ram
   jr  a2
   nop
   .end _start


/**********************************************************************
**
** Function: _start_in_ram
*/

   .globl  _start_in_ram
   .ent _start_in_ram
_start_in_ram:

   /*
   ** Print 'S'.  Already in RAM no need to reference EEPROM address.
   */
   li   a0,'S'
   jal  putch_rom
   nop

   la   gp, _gp                 /* set the global data pointer */
   .end _start_in_ram


/**********************************************************************
**
** Function: zerobss
*/
   .globl  __memsize
   .globl  zerobss
   .ent    zerobss
zerobss:

   /*
   ** Print 'z'.  Starting to zero out bss.
   */
   li a0,'z'
   jal putch_rom
   nop

   la           v0, _fbss
   la           v1, _end
3:
   sw           zero,0(v0)
   bltu         v0,v1,3b
   addiu        v0,v0,4               /* executed in delay slot */

   la  t0, _stack_init         /* initialize stack so we */

   /*
   ** We must subtract 24 bytes for the 3 8 byte arguments to main, in
   ** case main wants to write them back to the stack.  The caller is
   ** supposed to allocate stack space for parameters in registers in
   ** the old MIPS ABIs.  We must do this even though we aren't passing
   ** arguments, because main might be declared to have them.
   **
   ** Some ports need a larger alignment for the stack, so we subtract
   ** 32, which satisifes the stack for the arguments and keeps the
   ** stack pointer better aligned.
   */
   subu    t0,t0,32
   move    sp,t0               /* set stack pointer */
   nop

   /*
   ** Print 'Z'.  Finished zeroing bss.
   */
   li   a0,'Z'
   jal  putch_rom
   nop

   .end    zerobss


/**********************************************************************
**
** Function: _init
*/
   .globl  exit .text
   .globl  _init
   .ent    _init
_init:

   /*
   ** Print 'i'.  Starting to initialize RTEMS.
   */
   li           a0, 'i'
   jal          putch_rom
   nop


   /*
   ** Save the boot-time addresses of the I & D cache flush routines.
   ** Note, if we're running from RAM, we cannot manipulate the cache
   ** so we just disable the cache flush functions.
   */
   la           a0,_promIcache
   sw           k0,0(a0)
   nop
        
   la           a0,_promDcache
   sw           k1,0(a0)
   nop

   move         a0,zero         /* set argc to 0 */
   jal          boot_card           /* call the program start function */
   nop

   /*
   ** fall through to the "exit" routine
   */
   jal _sys_exit
   nop
   .end _init


/**********************************************************************
**
** Function: _sys_exit
**
** Exit from the application by jumping to PMON address in EEPROM.
*/
   .globl  _sys_exit
   .ent _sys_exit
_sys_exit:
   la  t0, PMON_ADDRESS
   jal t0
   .end _sys_exit



/**********************************************************************
**
** function: putch
** input   : ASCII character in A0
** registers used: ra, a0, t0, t1
**
*/
   .globl putch_rom
   .ent   putch_rom
putch_rom:

   /*
   ** Delay for UART
   */
   li   t0, 1000
   move t1, zero
2:
   beq  t0, t1, 3f
   addu t1, 1
   b    2b
   nop

3:
   /*
   ** Print a character out from a0
   */

   li   t0, MG5_INT_STATUS_REG      /* load uart register base address */
   lw   t1, 0(t0)                   /* Read status */
   nop
   and  t1, t1, UART_0_TX_READY_BIT /* see if the transmitter is ready */
   beq  t1 , zero , 1f              /* skip uart output if not ready */
   nop
   la   t0, MG5_UART_0_TX_REG
   sw   a0, 0(t0)
   nop

1: /*
   ** if jumped to here, UART was not ready...forget it
   */
   j    ra
  .end putch_rom


/**********************************************************************
**
** function: config_uart
** registers used: ra, t0, t1
**
*/

   .globl config_uart
   .ent   config_uart
config_uart:

   /*
   **  Configure UART 0
   */

   /* First, reset the uart */
   la   t0, MG5_COMMAND_REG
   li   t1, UART_RESET_BIT
   sw   t1, 0(t0)

   /* Next, set the baud rate register for 19200 with a clock speed of 12 Mhz*/
   la   t0, MG5_UART_0_BAUD_REG
   li   t1, 0x02700270
   sw   t1, 0(t0)

   /* Now, clear the reset bit & set the tx enable bit */
   la   t0, MG5_COMMAND_REG
   li   t1, UART_0_TX_ENABLE_BIT
   sw   t1, 0(t0)

   /*
   ** return
   */
   j    ra
.end config_uart


/*************************************************************
* CpuInit:
*   Perform CPU-specific initialization
*   This routine is only callable from assembly because it
*   clobbers s7. It should be called from your ROM-based startup
*   code. It returns:
*       s0 = address of cache flush routine
*/

   .globl  _cpuinit
   .ent _cpuinit
_cpuinit:

   #
   # BIU/Cache config register setup
   #
   # RES    = 0: 31 -> 18 : Reserved
   # RES    = 1: 17       : Reserved must be set to 1 (Synova Manual)
   # RES    = 0: 16       : Reserved must be set to 0 (Synova Manual)
   # BGNT   = 0: 15       : Disable Bus Grant (set to 0)
   # NOPAD  = 1: 14       : No padding of waitstates between transactions
   # RDPRI  = 1: 13       : Loads have priority over stores
   # INTP   = 1: 12       : Interrupts are active high
   # IS1    = 1: 11       : Enable I-Cache
   # IS0    = 0: 10       : Hardwired to zero
   # IBLKSZ =10:  9 ->  8 : I-Cache refill size = 8 words
   # DS     = 1:  7       : Enable D-Cache
   # RES    = 0:  6       : Hardwared to zero
   # DBLKSZ =10:  5 ->  4 : D-Cache refill block size 8 words
   # RAM    = 0:  3       : No Scratchpad RAM
   # TAG    = 0:  2       : Disable tag test
   # INV    = 0:  1       : Disable invalidate mode
   # LOCK   = 0:  0       : Disable cache lock
   #
   li  t0,0x00027AA0
   sw  t0,M_BIU

   #
   # Refresh register setup
   #
   # set 94 clock cycles at 12Mhz
   #
   li  t1,M_RTIC
   li  t0,0x5E
   sw  t0,(t1)

   #
   # DRAM register setup
   #
   #
   # RESERVED=0: 31 -> 29 : Reserved
   # SYNC  = 0 : 27       : No Syncronous DRAM
   # SCFG  = 0 : 26       : No Syncronous DRAM
   # DMARDY =1 : 25       : Internal DRDY for DMA
   # DMABLK =0 : 24 -> 22 : 2 word blk size for DMA transfers
   # DPTH = 0  : 21 -> 20 : No interleaved or syncronous memory
   # RDYW = 0  : 19       : No interleaved or syncronous memory
   # PGSZ = 110: 18 -> 16 : Page size = 1K
   # PGMW = 0  : 15       : Disable page mode write
   # RFWE = 0  : 14 -> 13 : Allow BIU to do non-DRAM work during refresh
   # RFEN = 1  : 12       : Enable Refresh generator
   # RDYEN = 1 : 11       : Internal DRDY
   # BFD =   1 : 10       : Block fetch disable
   # PE =    0 : 9        : No parity checking
   # RPC =   0 : 8 -> 7   : RAS Precharge = 2 SYSCLK cycles
   # RCD =   1 : 6 -> 5   : RAS-to-CAS delay = 3 cycles
   # CS  =   0 : 4        : CAS shortened by 1/2 cycle
   # CL  =   1 : 3 -> 1   : 2.5 cycle CAS pulse width
   # DCE =   1 : 0        : Enable DRAM controller
   li  s0,0x02061C23
   sw  s0,M_DRAM

   #
   # SRAM setup
   # Dont Care about this, we are not using SRAM
   # Power on default of 0x0 is ok
   #
   li  t0,0
   sw  t0,M_SRAM

   #
   # SPEC0 setup
   #
   # SPEC0 contains the BCRT registers, BCRT Shared RAM and EEPROM
   # This area is configured to use an external waitstate generator
   # and Data Ready signal.
   # Also, I see no need to cache this data. It could confuse the
   # BCRT.
   #
   # - 9/29/99 - APC - set NOSNOOP to 1 and EXTGNT to 1
   #  Bit 23 = 1 : EXTGNT External data ready = 1
   #  Bit 19 = 1 : NOSNOOP No Snoop = 1
   li  t0,0x00880000         # use external waitstates
   sw  t0,M_SPEC0

   #
   # SPEC1 setup
   #
   # This is where most of the SDB I/O is.
   #
   #  Important fields:
   #
   #  Bit 19 =1 : NOSNOOP = 1
   #  Bit 6 = 1 : Enable DAWG
   #  Bit 5 -> 0  = 1 : 1 Wait state
   #
   li  t0,0x00880000      /* Bit23 EXTGNT set to 1, Bit19 NOSNOOP set to 1 */
   sw  t0,M_SPEC1

   #
   # SPEC2 setup
   #
   # SPEC2 is not currently used on the SDB.
   # Bit 19 = 1 : NOSNOOP = 1
   #
   #li t0, 0x00080000
   #sw t0,M_SPEC2
   #
   li  t0, 0x0
   sw  t0,M_SPEC2


   #
   # SPEC3 Setup
   # SPEC3 will be used for the SONIC ethernet controller.
   # Use the same # of waitstates that the turborocket board uses.
   # Bit 19 = 1 : NOSNOOP = 1
   #
   #li t0, (SPC_CACHED | SPC_WAITENA | (16<<SPC_WAITSHFT))
   #sw t0,M_SPEC3
   #
   li  t0, 0x0
   sw  t0,M_SPEC3

   #
   # Finally, delay to allow RAM to stabilize
   #
   li  t0,2000
1: subu    t0,1
   bne t0,zero,1b
   nop

   #
   # Init Mongoose V registers.
   #

   /*
   ** Mongoose V Control Register Setup
   ** For now just setup UART defaults, turn edac off.
   ** May not even need to put anything in here...
   */
   li  t0,0
   sw  t0,MG5_COMMAND_REG

   /*
   ** Setup Mongoose V extended interrupt mask
   */
   li  t0,0
   sw  t0,MG5_INT_MASK_REG

   /*
   ** Clear Mongoose V extended interrupts
   ** Clear all of the pulse interrupts that may be pending.
   */
   li  t0,( EDAC_SERR_BIT | EDAC_MERR_BIT | UART_0_RX_OVERRUN_BIT | UART_0_FRAME_ERR_BIT | UART_1_RX_OVERRUN_BIT | UART_1_FRAME_ERR_BIT | MAVN_WRITE_ACC_BIT | MAVN_READ_ACC_BIT )
   sw  t0,MG5_INT_STATUS_REG

   /*
   ** Setup MAVN Access Priv Register
   */
   li  t0,0x7FFFFFFF  /* Default reset value */
   sw  t0,MG5_MAVN_PRIVLEGE_REG

   /*
   ** Mavn Range Register 0 -- 0 and 1 cover EEPROM
   ** 0xbfc00000 -> 0xbfe00000
   */
   li  t0,( 0xBFC00000 | 0x15 )
   sw  t0,MG5_MAVN_RANGE_0_REG

   /*
   ** Mavn Range Register 1
   ** 0xbfe00000 -> 0xc0000000
   */
   li  t0,( 0xBFE00000 | 0x15 )
   sw  t0,MG5_MAVN_RANGE_1_REG

   /*
   ** Mavn Range Register 2 -- 2 and 3 cover the first RAM
   ** 0x80000000 -> 0x80200000
   */
   li  t0,( 0x80000000 | 0x15 )
   sw  t0,MG5_MAVN_RANGE_2_REG

   /*
   ** Mavn Range Register 3
   ** 0x80200000 -> 0x80400000
   */
   li  t0, ( 0x80200000 | 0x15 )
   sw  t0, MG5_MAVN_RANGE_3_REG

   /*
   ** Mavn Range Register 4 -- IO Space 1
   ** 0xBE00000 -> 0xBe0000200
   */
   li  t0, ( 0xBe000000 | 0x09 )
   sw  t0, MG5_MAVN_RANGE_4_REG

   /*
   ** Mavn Range Register 5 -- IO Space 2
   ** 0xBe200000 -> 0xbe400000
   */
   li  t0, ( 0xBE200000 | 0x15 )
   sw  t0, MG5_MAVN_RANGE_5_REG

   /*
   ** MAVN Error Address Register ( Unstick )
   */
   la      t0, MG5_MAVN_VIOLATION_REG
   lw      t1, 0(t0)

   /*
   ** Read EDAC Error Register to unstick it
   */
   la      t0, MG5_EDAC_ADDR_REG
   lw      t1, 0(t0)

   /*
   ** Enable Mongoose V EDAC
   */
   la      t0, MG5_COMMAND_REG
   li      t1, EDAC_ENABLE_BIT
   sw      t1, 0(t0)
   nop

   /*
   ** Program Watchdog to 10 seconds - If PMON will
   ** run, it will be set to MAX later.
   */
   la      t0, 0xBE000000
   li      t1, 0xA0
   sw      t1, 0(t0)

3: nop

   j ra
   .end _cpuinit





        


        
/**********************************************************************
**
** Keep the boot-time address of the I & D cache reset code for
** later on.  If we need to clear the I/D caches, we <must> run from 
** non-cached memory.  This means the relocated versions are useless, 
** thankfully they are quite small.
*/
        
_promIcache:    .word 0
_promDcache:    .word 0

                

        .globl promCopyIcacheFlush
        .ent promCopyIcacheFlush
        .set noreorder
promCopyIcacheFlush:    
        move    a0,ra
        
        la      t1,_promIcache
        lw      t0,0(t1)
        nop
        beqz    t0,1f
        
        jal     t0
        nop

1:      j       a0
        nop
        .set reorder
        .end promCopyIcacheFlush
        

        
        .globl promCopyDcacheFlush
        .ent promCopyDcacheFlush
        .set noreorder
promCopyDcacheFlush:    
        move    a0,ra
        
        la      t1,_promDcache
        lw      t0,0(t1)
        nop
        beqz    t0,1f
        
        jal     t0
        nop

1:      j       a0
        nop
        .set reorder
        .end promCopyDcacheFlush
                        
        
                

        
/*******************************************************************************
** Function Name:   IcacheFlush
** Description:     This functions flushes the on chip icache.
*/

     .ent IcacheFlush
     .set noreorder
IcacheFlush:

1:
     # Assume I cache is already enabled in BIU/Cache setup
     # Get contents of M_BIU register and save in t1
     li        t0, M_BIU
     lw        t1, 0(t0)

     # Isolate I cache
     mfc0      t3, C0_SR        /* Read Status Register */
     nop
     or        t0, t3, SR_ISC   /* Isolate Cache so we don't propagate operations */
     mtc0      t0, C0_SR        /* Write it back to Status Register */
     nop

     # Setup for cache flush
     li        t8, 0            /* Store zero */
     li        t9, LR33300_IC_SIZE

icache_write:
     sw        zero, 0(t8)          /* Store zero to memory addres in t8 */
     addu      t8, 4                /* Increment t8 address by 4 */
     bltu      t8, t9, icache_write /* check to see if we are done */
     nop


     # De-isolate I cache
     mtc0      t3, C0_SR        /* Load unchanged t3 to Status Register */
     nop

     jal       ra
     nop
     .set reorder
     .end IcacheFlush


/********************************************************
** Function Name:   DcacheFlush
** Description:     This functions flushes the on chip dcache.
*/


     .ent DcacheFlush
     .set noreorder
DcacheFlush:

     # isolate icache
     mfc0      t3,C0_SR
     nop
     or        t0, t3, SR_ISC
     mtc0      t0, C0_SR
     nop

     # Setup up for cache flush
     li        t8, 0
     li        t9, LR33300_DC_SIZE

dcache_write:
     sw        zero, 0(t8)
     addu      t8, 4
     bltu      t8, t9, dcache_write /* check to see if we are done */
     nop

     # De-isolate cache
     mtc0      t3, C0_SR
     nop

     jal       ra
     nop
     .set reorder
     .end DcacheFlush


/* EOF start.S */

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.