/* ** 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. */ #define LANGUAGE_ASSEMBLY #include #include "regs.S" #include "mg5.h" #ifdef __mips16 /* This file contains 32 bit assembly code. */ .set nomips16 #endif #ifdef HACKED_PMON #define PMON_UTIL_ROUTINES 0xbfc00200 #define UTIL_WARMSTART_VECTOR 21*4 #define UTIL_CPUINIT_VECTOR 22*4 #define UTIL_CONFIGUART_VECTOR 23*4 #define UTIL_PUTCHROM_VECTOR 24*4 #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 move k1,ra /* save ra so we can optionally return to caller */ $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 /* ** 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 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 jal t0 nop /* ** 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 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< 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 /******************************************************************************* ** Function Name: IcacheFlush ** Description: This functions flushes the on chip icache. */ .globl IcacheFlush .ent IcacheFlush 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) .set noreorder # 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 addres 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. */ .globl DcacheFlush .ent DcacheFlush DcacheFlush: # isolate icache .set noreorder 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 */