783 lines
24 KiB
ArmAsm
783 lines
24 KiB
ArmAsm
/* romInit.s - MIPS ROM initialization module */
|
|
|
|
/*
|
|
* Copyright (c) 2001-2002, 2005-2006 Wind River Systems, Inc.
|
|
*
|
|
* The right to copy, distribute or otherwise make use of this software
|
|
* may be licensed only pursuant to the terms of an applicable Wind River
|
|
* license agreement.
|
|
*/
|
|
|
|
/*********************************************************************
|
|
*
|
|
* Copyright 2000,2001
|
|
* Broadcom Corporation. All rights reserved.
|
|
*
|
|
* This software is furnished under license to Wind River Systems, Inc.
|
|
* and may be used only in accordance with the terms and conditions
|
|
* of this license. No title or ownership is transferred hereby.
|
|
********************************************************************* */
|
|
|
|
/*
|
|
* This file has been developed or significantly modified by the
|
|
* MIPS Center of Excellence Dedicated Engineering Staff.
|
|
* This notice is as per the MIPS Center of Excellence Master Partner
|
|
* Agreement, do not remove this notice without checking first with
|
|
* WR/Platforms MIPS Center of Excellence engineering management.
|
|
*/
|
|
|
|
/*
|
|
modification history
|
|
--------------------
|
|
01g,25oct06,pes Conditionalize for CFE support. Use CFEARGS to save args
|
|
passed by CFE. Correct initial stack setup.
|
|
01f,14mar06,pes Use sibyte.h to determine board type.
|
|
01e,03aug05,dr added #include "bcm1250DramInit.s".
|
|
01d,03oct02,agf changes for shared sentosa support
|
|
01c,23jan02,agf Add .set noreorder to ROM vector section
|
|
01b,14jan02,pes Eliminate '#'-style comments
|
|
01a,15nov01,agf Created for the bcm1250 BSP
|
|
|
|
*/
|
|
|
|
/*
|
|
DESCRIPTION
|
|
This module contains the entry code for the VxWorks bootrom.
|
|
The entry point romInit, is the first code executed on power-up.
|
|
|
|
The routine sysToMonitor() jumps to romInit() to perform a
|
|
"warm boot".
|
|
|
|
*/
|
|
|
|
|
|
/* includes */
|
|
#define _ASMLANGUAGE
|
|
#include <vxWorks.h>
|
|
#include <sysLib.h>
|
|
#include <cacheLib.h>
|
|
#include "config.h"
|
|
#include <asm.h>
|
|
#include <esf.h>
|
|
#include <drv/multi/sb1Lib.h>
|
|
|
|
#define CFG_MULTI_CPUS 1
|
|
|
|
|
|
/* defines */
|
|
#define ROM_ISP_BASE 0xa0010000
|
|
|
|
#define LED_CHAR0 (32+8*3)
|
|
#define LED_CHAR1 (32+8*2)
|
|
#define LED_CHAR2 (32+8*1)
|
|
#define LED_CHAR3 (32+8*0)
|
|
|
|
/* macros */
|
|
|
|
/* in archMips.h these macros are not assembler friendly, so fix for here */
|
|
#undef PHYS_TO_K0
|
|
#define PHYS_TO_K0(x) (K0BASE | (x))
|
|
#undef PHYS_TO_K1
|
|
#define PHYS_TO_K1(x) (K1BASE | (x))
|
|
|
|
/*
|
|
* Relocate an address.
|
|
*
|
|
* This macro is used to call routines in a position independent
|
|
* manner. That way code can be relocated from ROM to RAM and
|
|
* still work properly. Note this will overwrite the ra register.
|
|
*/
|
|
#define RELOC(toreg,address) \
|
|
bal 9f; \
|
|
9:; \
|
|
la toreg,address; \
|
|
addu toreg,ra; \
|
|
la ra,9b; \
|
|
subu toreg,ra
|
|
|
|
/*
|
|
* Set a vector in a jump table
|
|
*/
|
|
#define RVECENT(f,n) \
|
|
b f; nop
|
|
#define XVECENT(f,bev) \
|
|
b f; li k0,bev
|
|
|
|
/*
|
|
* Set the on-board LED display.
|
|
*
|
|
* Input parameters:
|
|
* a,b,c,d - four ASCII characters (literal constants)
|
|
*/
|
|
#if (BOARD_TYPE == BCM91250A) || (BOARD_TYPE == BCM91480B)
|
|
#define SETLEDS(a,b,c,d) \
|
|
li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \
|
|
li t0,PHYS_TO_K1(LEDS_PHYS) ; \
|
|
rol a0,a0,8 ; \
|
|
and t1,a0,0xFF ; \
|
|
sb t1,LED_CHAR0(t0) ; \
|
|
rol a0,a0,8 ; \
|
|
and t1,a0,0xFF ; \
|
|
sb t1,LED_CHAR1(t0) ; \
|
|
rol a0,a0,8 ; \
|
|
and t1,a0,0xFF ; \
|
|
sb t1,LED_CHAR2(t0) ; \
|
|
rol a0,a0,8 ; \
|
|
and t1,a0,0xFF ; \
|
|
sb t1,LED_CHAR3(t0)
|
|
#else /* BOARD_TYPE */
|
|
#ifdef DEBUG_LEDS_TO_UART
|
|
#define SETLEDS(a,b,c,d) \
|
|
li t0,PHYS_TO_K1(A_DUART_CHANREG(0,R_DUART_STATUS)) ; \
|
|
2: ld a0,0(t0) ; \
|
|
andi a0,0x04 ; \
|
|
beqz a0,2b ; \
|
|
li a0,a ; \
|
|
li t0,PHYS_TO_K1(A_DUART_CHANREG(0,R_DUART_TX_HOLD)) ; \
|
|
sd a0,0(t0) ; \
|
|
li a0,b ; \
|
|
sd a0,0(t0) ; \
|
|
li a0,c ; \
|
|
sd a0,0(t0) ; \
|
|
li a0,d ; \
|
|
sd a0,0(t0) ; \
|
|
li a0,13 ; \
|
|
sd a0,0(t0) ; \
|
|
li a0,10 ; \
|
|
sd a0,0(t0)
|
|
#else /* DEBUG_LEDS_TO_UART */
|
|
#define SETLEDS(a,b,c,d)
|
|
#endif /* DEBUG_LEDS_TO_UART */
|
|
#endif /* BOARD_TYPE */
|
|
|
|
/* internals */
|
|
|
|
.globl romInit /* start of system code */
|
|
|
|
/* externals */
|
|
|
|
.extern romStart /* system initialization routine */
|
|
.extern cacheSb1Reset /* L1 cache reset */
|
|
|
|
.data
|
|
|
|
/* ensure data segment is 16-byte aligned */
|
|
|
|
.align 4
|
|
_sdata:
|
|
.asciiz "start of data"
|
|
|
|
.text
|
|
.set noreorder
|
|
promEntry:
|
|
romInit:
|
|
_romInit:
|
|
#ifndef INCLUDE_CFE_SUPPORT
|
|
RVECENT(__romInit,0) /* PROM entry point */
|
|
RVECENT(romReboot,1) /* software reboot */
|
|
RVECENT(romReserved,2)
|
|
RVECENT(romReserved,3)
|
|
RVECENT(romReserved,4)
|
|
RVECENT(romReserved,5)
|
|
RVECENT(romReserved,6)
|
|
RVECENT(romReserved,7)
|
|
RVECENT(romReserved,8)
|
|
RVECENT(romReserved,9)
|
|
RVECENT(romReserved,10)
|
|
RVECENT(romReserved,11)
|
|
RVECENT(romReserved,12)
|
|
RVECENT(romReserved,13)
|
|
RVECENT(romReserved,14)
|
|
RVECENT(romReserved,15)
|
|
RVECENT(romReserved,16)
|
|
RVECENT(romReserved,17)
|
|
RVECENT(romReserved,18)
|
|
RVECENT(romReserved,19)
|
|
RVECENT(romReserved,20)
|
|
RVECENT(romReserved,21)
|
|
RVECENT(romReserved,22)
|
|
RVECENT(romReserved,23)
|
|
RVECENT(romReserved,24)
|
|
RVECENT(romReserved,25)
|
|
RVECENT(romReserved,26)
|
|
RVECENT(romReserved,27)
|
|
RVECENT(romReserved,28)
|
|
RVECENT(romReserved,29)
|
|
RVECENT(romReserved,30)
|
|
RVECENT(romReserved,31)
|
|
RVECENT(romReserved,32)
|
|
RVECENT(romReserved,33)
|
|
RVECENT(romReserved,34)
|
|
RVECENT(romReserved,35)
|
|
RVECENT(romReserved,36)
|
|
RVECENT(romReserved,37)
|
|
RVECENT(romReserved,38)
|
|
RVECENT(romReserved,39)
|
|
RVECENT(romReserved,40)
|
|
RVECENT(romReserved,41)
|
|
RVECENT(romReserved,42)
|
|
RVECENT(romReserved,43)
|
|
RVECENT(romReserved,44)
|
|
RVECENT(romReserved,45)
|
|
RVECENT(romReserved,46)
|
|
RVECENT(romReserved,47)
|
|
RVECENT(romReserved,48)
|
|
RVECENT(romReserved,49)
|
|
RVECENT(romReserved,50)
|
|
RVECENT(romReserved,51)
|
|
RVECENT(romReserved,52)
|
|
RVECENT(romReserved,53)
|
|
RVECENT(romReserved,54)
|
|
RVECENT(romReserved,55)
|
|
RVECENT(romReserved,56)
|
|
RVECENT(romReserved,57)
|
|
RVECENT(romReserved,58)
|
|
RVECENT(romReserved,59)
|
|
RVECENT(romReserved,60)
|
|
RVECENT(romReserved,61)
|
|
RVECENT(romReserved,62)
|
|
RVECENT(romReserved,63)
|
|
XVECENT(romExcHandle,0x200) /* bfc00200: R4000 tlbmiss vector */
|
|
RVECENT(romReserved,65)
|
|
RVECENT(romReserved,66)
|
|
RVECENT(romReserved,67)
|
|
RVECENT(romReserved,68)
|
|
RVECENT(romReserved,69)
|
|
RVECENT(romReserved,70)
|
|
RVECENT(romReserved,71)
|
|
RVECENT(romReserved,72)
|
|
RVECENT(romReserved,73)
|
|
RVECENT(romReserved,74)
|
|
RVECENT(romReserved,75)
|
|
RVECENT(romReserved,76)
|
|
RVECENT(romReserved,77)
|
|
RVECENT(romReserved,78)
|
|
RVECENT(romReserved,79)
|
|
XVECENT(romExcHandle,0x280) /* bfc00280: R4000 xtlbmiss vector */
|
|
RVECENT(romReserved,81)
|
|
RVECENT(romReserved,82)
|
|
RVECENT(romReserved,83)
|
|
RVECENT(romReserved,84)
|
|
RVECENT(romReserved,85)
|
|
RVECENT(romReserved,86)
|
|
RVECENT(romReserved,87)
|
|
RVECENT(romReserved,88)
|
|
RVECENT(romReserved,89)
|
|
RVECENT(romReserved,90)
|
|
RVECENT(romReserved,91)
|
|
RVECENT(romReserved,92)
|
|
RVECENT(romReserved,93)
|
|
RVECENT(romReserved,94)
|
|
RVECENT(romReserved,95)
|
|
XVECENT(romExcHandle,0x300) /* bfc00300: R4000 cache vector */
|
|
RVECENT(romReserved,97)
|
|
RVECENT(romReserved,98)
|
|
RVECENT(romReserved,99)
|
|
RVECENT(romReserved,100)
|
|
RVECENT(romReserved,101)
|
|
RVECENT(romReserved,102)
|
|
RVECENT(romReserved,103)
|
|
RVECENT(romReserved,104)
|
|
RVECENT(romReserved,105)
|
|
RVECENT(romReserved,106)
|
|
RVECENT(romReserved,107)
|
|
RVECENT(romReserved,108)
|
|
RVECENT(romReserved,109)
|
|
RVECENT(romReserved,110)
|
|
RVECENT(romReserved,111)
|
|
XVECENT(romExcHandle,0x380) /* bfc00380: R4000 general vector */
|
|
RVECENT(romReserved,113)
|
|
RVECENT(romReserved,114)
|
|
RVECENT(romReserved,115)
|
|
RVECENT(romReserved,116)
|
|
RVECENT(romReserved,116)
|
|
RVECENT(romReserved,118)
|
|
RVECENT(romReserved,119)
|
|
RVECENT(romReserved,120)
|
|
RVECENT(romReserved,121)
|
|
RVECENT(romReserved,122)
|
|
RVECENT(romReserved,123)
|
|
RVECENT(romReserved,124)
|
|
RVECENT(romReserved,125)
|
|
RVECENT(romReserved,126)
|
|
RVECENT(romReserved,127)
|
|
|
|
/* We hope there are no more reserved vectors!
|
|
* 128 * 8 == 1024 == 0x400
|
|
* so this is address R_VEC+0x400 == 0xbfc00400
|
|
*/
|
|
|
|
/* XXX - sb1 has two additional vectors:
|
|
* XVECENT(romExcHandle,0x400) /@ bfc00400: SB1 interrupt vector @/
|
|
* XVECENT(romExcHandle,0x400) /@ bfc00480: SB1 EJTAG vector @/
|
|
*/
|
|
#endif
|
|
.align 4
|
|
.set reorder
|
|
|
|
/******************************************************************************
|
|
*
|
|
* romInit - entry point for VxWorks in ROM
|
|
*
|
|
* romInit
|
|
* (
|
|
#ifdef INCLUDE_CFE_SUPPORT
|
|
* _RType cfeHandle
|
|
* _RType cfeCPU
|
|
* _RType cfeEntry
|
|
* _RType cfeSeal
|
|
#else /@ INCLUDE_CFE_SUPPORT @/
|
|
* int startType
|
|
#endif /@ INCLUDE_CFE_SUPPORT @/
|
|
* )
|
|
*/
|
|
|
|
__romInit:
|
|
#ifdef INCLUDE_CFE_SUPPORT
|
|
/*
|
|
* when booting from CFE, a0-a3 hold magic values that need
|
|
* to be stashed in known locations before proceeding.
|
|
*
|
|
* These values are stored immediately below the
|
|
* bootrom (which really is in ram in this case).
|
|
*
|
|
*/
|
|
li t0, CFEARGS
|
|
#if defined(INCLUDE_MAPPED_KERNEL)
|
|
and t0, ADDRESS_SPACE_MASK
|
|
or t0, K0BASE
|
|
#endif /* INCLUDE_MAPPED_KERNEL */
|
|
sd a0, (t0)
|
|
sd a1, 8(t0)
|
|
sd a2, 16(t0)
|
|
sd a3, 24(t0)
|
|
#endif /* INCLUDE_CFE_SUPPORT */
|
|
|
|
|
|
/* force power-on startType */
|
|
li a0, BOOT_CLEAR
|
|
|
|
/*
|
|
* If there was some way to distinguish between a cold and warm
|
|
* restart AND the memory system is guaranteed to be intact then
|
|
* we could load BOOT_NORMAL instead
|
|
*/
|
|
|
|
romReboot: /* sw reboot inherits a0 startType */
|
|
/* move startType to s6 to keep it 'safe' */
|
|
move s6, a0
|
|
|
|
#ifndef INCLUDE_CFE_SUPPORT
|
|
#if CFG_MULTI_CPUS
|
|
/*
|
|
* Test to see if which cpu is executing since they
|
|
* both share the 0xbfc0.0000 reset vector. Make the
|
|
* secondary cpu(s) use a different bring-up sequence.
|
|
*/
|
|
mfc0 t0, C0_PRID /* get cpu PRID */
|
|
HAZARD_CP_READ
|
|
and t0, t0, 0xe000000 /* determine cpu number */
|
|
beq t0, zero, 1f /* skip if primary cpu */
|
|
|
|
RELOC(k1, alt_romInit) /* cpu1 will not return */
|
|
jal k1
|
|
nop
|
|
1:
|
|
/*
|
|
* In case cpu0 got here from a sw reboot [as opposed to hw reset]
|
|
* reset cpu1 to make sure cpu0 and cpu1 stay sync-ed.
|
|
*
|
|
* This is may not always be necessary, application developers may
|
|
* wish to implement a more graceful reboot sequence.
|
|
*/
|
|
li a0,PHYS_TO_K1(A_SCD_SYSTEM_CFG)
|
|
ld t0,0(a0)
|
|
dli t1,M_SYS_CPU_RESET_1 /* Reset mask */
|
|
or t0,t1 /* New value to write */
|
|
sd t0,0(a0) /* cpu1 is now in reset */
|
|
#endif
|
|
|
|
/*
|
|
* Do low-level board initialization. Only needed
|
|
* once, so have cpu0 do it.
|
|
*/
|
|
|
|
RELOC(k1, board_earlyinit)
|
|
jal k1
|
|
|
|
SETLEDS('H','E','L','O')
|
|
|
|
/*
|
|
* Initialize cpu0's core
|
|
*/
|
|
|
|
RELOC(k1, core_init)
|
|
jal k1
|
|
|
|
/*
|
|
* Do low-level processor initialization. Again, only
|
|
* needed once, so have cpu0 do it.
|
|
*/
|
|
|
|
RELOC(k1, processor_init)
|
|
jal k1
|
|
|
|
#if CFG_MULTI_CPUS
|
|
/*
|
|
* Release secondary core(s)
|
|
*
|
|
* cpu0 will take the secondary out of reset; then wait
|
|
* until the secondary signals for it to continue.
|
|
*
|
|
* The secondary will start at _romInit, hit the
|
|
* 'alt_romInit' routine and go with that bring-up
|
|
* sequence. Eventually, it will get to a stopping point
|
|
* and then will signal for cpu0 to continue.
|
|
*/
|
|
|
|
SETLEDS('a','l','t','C')
|
|
RELOC(k1, start_altCpu)
|
|
jal k1
|
|
#endif
|
|
|
|
/*
|
|
* Switch from KSEG1 to KSEG0
|
|
*/
|
|
|
|
bal cpu_kseg0_switch
|
|
|
|
/*
|
|
* Now initialize the DRAM
|
|
*/
|
|
SETLEDS('D','R','A','M')
|
|
RELOC(k1, board_draminfo)
|
|
jal k1
|
|
|
|
SETLEDS('D','R','A','2')
|
|
move a0,v0 /* pass params from draminfo */
|
|
RELOC(k1, bcm1250_dram_init)
|
|
jal k1
|
|
move k0,v0 /* Save in k0 for now */
|
|
|
|
#endif /* INCLUDE_CFE_SUPPORT */
|
|
/*
|
|
* Finally, do the typical romInit stuff and go to romStart
|
|
*/
|
|
SETLEDS('r','o','m','S')
|
|
li t0, 1
|
|
mtc0 t0, C0_COUNT
|
|
mtc0 zero, C0_COMPARE
|
|
|
|
|
|
la gp, _gp
|
|
la sp, STACK_ADRS-(4*_RTypeSize) /* set stack */
|
|
|
|
move a0, s6 /* restore startType */
|
|
|
|
sync
|
|
|
|
RELOC(t0,romStart)
|
|
jal t0 /* should not return */
|
|
nop
|
|
|
|
SETLEDS('e','r','r',' ') /* error in starting kernel */
|
|
1:
|
|
b 1b /* should never get here */
|
|
|
|
|
|
#ifndef INCLUDE_CFE_SUPPORT
|
|
/***************************************************************************
|
|
*
|
|
* alt_romInit - initialization sequence for the secondary CPU's
|
|
*
|
|
* Do the initialization of the local core and then notify cpu0 that
|
|
* we're done.
|
|
*
|
|
* This routine is executes in KSEG1.
|
|
*
|
|
* Input parameters:
|
|
* t0 - CPU identifier
|
|
*
|
|
* Return value:
|
|
* nothing
|
|
*/
|
|
|
|
.ent alt_romInit
|
|
alt_romInit:
|
|
|
|
/*
|
|
* cpu0 just entered start_altCpu and released us from RESET. It will
|
|
* wait there until we ring its doorbell.
|
|
*
|
|
* Initialize core
|
|
*/
|
|
|
|
RELOC(k1, core_init)
|
|
jal k1
|
|
|
|
/*
|
|
* Notify the SCD that we're done initializing. Do this by
|
|
* ringing cpu0's doorbell.
|
|
*/
|
|
|
|
la a0,PHYS_TO_K1(A_IMR_REGISTER(0,R_IMR_MAILBOX_SET_CPU))
|
|
|
|
mfc0 t0,C0_PRID /* get processor number */
|
|
srl t0,t0,25 /* shift CPU bits into low */
|
|
and t0,t0,7 /* keep only low 3 bits */
|
|
li t1,1 /* make a mask unique for a cpu */
|
|
sll t1,t1,t0 /* calc t1 = 1 shl cpu num */
|
|
sd t1,0(a0) /* set corrsp bit in mailbox */
|
|
|
|
/*
|
|
* Now wait for cpu0 to ring *our* doorbell
|
|
* The doorbell is our signal that it's safe to go to application code.
|
|
*
|
|
* Until cpu0 rings our doorbell, we can't use memory (but we can use
|
|
* the cache).
|
|
*
|
|
* Very BCM1250 specific here.
|
|
*/
|
|
|
|
/*
|
|
* Switch from KSEG1 to KSEG0
|
|
*/
|
|
|
|
bal cpu_kseg0_switch
|
|
|
|
/*
|
|
* Set the cache mode to COHERENT
|
|
*/
|
|
|
|
mfc0 t1,C0_CONFIG
|
|
HAZARD_CP_READ
|
|
srl t1,3
|
|
sll t1,3
|
|
or t1,CFG_K0_COHERENT
|
|
mtc0 t1,C0_CONFIG
|
|
|
|
|
|
/*
|
|
* Wait on doorbell
|
|
*/
|
|
|
|
1: la a0,PHYS_TO_K1(A_IMR_REGISTER(1,R_IMR_MAILBOX_CPU))
|
|
ld t2,(a0) /* Read mailbox */
|
|
beq t2,zero,1b /* Loop till the bit is set */
|
|
|
|
/*
|
|
* Clear all the bits in the mailbox register to dismiss the
|
|
* pending interrupt
|
|
*/
|
|
la a0,PHYS_TO_K1(A_IMR_REGISTER(1,R_IMR_MAILBOX_CLR_CPU))
|
|
li t1,-1
|
|
sd t1,0(a0)
|
|
|
|
/* t2 has the kernel vector, do some final init then jump to it */
|
|
|
|
SETLEDS('a','l','t','G')
|
|
|
|
jal t2
|
|
nop
|
|
|
|
SETLEDS('a','l','t','F')
|
|
1:
|
|
b 1b
|
|
|
|
|
|
.end alt_romInit
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* start_altCpu - initialization sequence for the secondary CPU's
|
|
*
|
|
* This routine is executed by the primary core. It releases the secondary(s)
|
|
* from RESET then waits for them to finish their init sequence to the
|
|
* point of L1 cache initalization. Once the secondary(s) are finished, they
|
|
* will ring the primary's door bell so it can return.
|
|
*
|
|
* Input parameters:
|
|
* nothing
|
|
*
|
|
* Return value:
|
|
* nothing
|
|
*/
|
|
|
|
.ent start_altCpu
|
|
start_altCpu:
|
|
/*
|
|
* Clear out our mailbox registers (both CPUs)
|
|
*/
|
|
|
|
la a0,PHYS_TO_K1(A_IMR_REGISTER(0,R_IMR_MAILBOX_CLR_CPU))
|
|
dli t0,-1 /* clear all 64 bits */
|
|
sd t0,(a0)
|
|
la a0,PHYS_TO_K1(A_IMR_REGISTER(1,R_IMR_MAILBOX_CLR_CPU))
|
|
sd t0,(a0)
|
|
|
|
/*
|
|
* Let the secondary CPU(s) out of reset
|
|
*
|
|
* This is very BCM1250-specific at the moment.
|
|
*/
|
|
|
|
la a0,PHYS_TO_K1(A_SCD_SYSTEM_CFG)
|
|
ld t0,0(a0)
|
|
dli t1,M_SYS_CPU_RESET_1 /* Reset mask */
|
|
not t1 /* clear this bit */
|
|
and t0,t1 /* New value to write */
|
|
sd t0,0(a0) /* CPU1 is now running */
|
|
|
|
/*
|
|
* Wait for the other CPU to ring our doorbell
|
|
*/
|
|
|
|
1: la a0,PHYS_TO_K1(A_IMR_REGISTER(0,R_IMR_MAILBOX_CPU))
|
|
ld t0,(a0) /* Read mailbox */
|
|
beq t0,zero,1b /* Loop till the bit is set */
|
|
|
|
/*
|
|
* Clear the mailbox to dismiss the pending interrupts
|
|
*/
|
|
la a0,PHYS_TO_K1(A_IMR_REGISTER(0,R_IMR_MAILBOX_CLR_CPU))
|
|
dli t0,-1 /* clear all 64 bits */
|
|
sd t0,(a0)
|
|
|
|
/*
|
|
* Okay, it's safe to return
|
|
*/
|
|
|
|
j ra
|
|
|
|
.end start_altCpu
|
|
|
|
/***************************************************************************
|
|
*
|
|
* cpu_kseg0_switch - manipulate the return address so the program counter
|
|
* returns to the KSEG0 region
|
|
*
|
|
* Input parameters:
|
|
* nothing
|
|
*
|
|
* Return value:
|
|
* nothing
|
|
*/
|
|
|
|
.ent cpu_kseg0_switch
|
|
cpu_kseg0_switch:
|
|
|
|
and ra,(K0SIZE-1)
|
|
or ra,K0BASE
|
|
j ra
|
|
|
|
.end cpu_kseg0_switch
|
|
|
|
/***************************************************************************
|
|
*
|
|
* romReserved - Handle a jump to an unknown vector
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
|
|
.ent romReserved
|
|
romReserved:
|
|
b romInit /* just start over */
|
|
.end romReserved
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* romExcHandle - rom based exception/interrupt handler
|
|
*
|
|
* This routine is invoked on an exception or interrupt while
|
|
* the status register is using the bootstrap exception vectors.
|
|
* It saves a state frame to a known uncached location so someone
|
|
* can examine the data over the VME.
|
|
*
|
|
* THIS ROUTIINE IS NOT CALLABLE FROM "C"
|
|
*
|
|
*/
|
|
|
|
.ent romExcHandle
|
|
romExcHandle:
|
|
|
|
.set noat
|
|
move k1, sp /* save fault sp */
|
|
li sp, ROM_ISP_BASE /* sp to known uncached location */
|
|
SW sp, E_STK_SP-ESTKSIZE(sp) /* save sp in new intstk frame */
|
|
subu sp, ESTKSIZE /* make new exc stk frame */
|
|
SW k0, E_STK_K0(sp) /* save k0, (exception type) */
|
|
SW k1, E_STK_SP(sp) /* save SP at fault */
|
|
SW AT, E_STK_AT(sp) /* save asmbler resvd reg */
|
|
.set at
|
|
SW v0, E_STK_V0(sp) /* save func return 0, used
|
|
to hold masked cause */
|
|
mfc0 k1, C0_BADVADDR /* read bad VA reg */
|
|
sw k1, E_STK_BADVADDR(sp) /* save bad VA on stack */
|
|
mfc0 k1, C0_EPC /* read exception pc */
|
|
sw k1, E_STK_EPC(sp) /* save EPC on stack */
|
|
mfc0 v0, C0_CAUSE /* read cause register */
|
|
sw v0, E_STK_CAUSE(sp) /* save cause on stack */
|
|
mfc0 k1, C0_SR /* read status register */
|
|
sw k1, E_STK_SR(sp) /* save status on stack */
|
|
|
|
.set noat
|
|
mflo AT /* read entry lo reg */
|
|
SW AT,E_STK_LO(sp) /* save entry lo reg */
|
|
mfhi AT /* read entry hi reg */
|
|
SW AT,E_STK_HI(sp) /* save entry hi reg */
|
|
.set at
|
|
SW zero, E_STK_ZERO(sp) /* save zero ?! */
|
|
SW v1,E_STK_V1(sp) /* save func return 1 */
|
|
SW a0,E_STK_A0(sp) /* save passed param 0 */
|
|
SW a1,E_STK_A1(sp) /* save passed param 1 */
|
|
SW a2,E_STK_A2(sp) /* save passed param 2 */
|
|
SW a3,E_STK_A3(sp) /* save passed param 3 */
|
|
SW t0,E_STK_T0(sp) /* save temp reg 0 */
|
|
SW t1,E_STK_T1(sp) /* save temp reg 1 */
|
|
SW t2,E_STK_T2(sp) /* save temp reg 2 */
|
|
SW t3,E_STK_T3(sp) /* save temp reg 3 */
|
|
SW t4,E_STK_T4(sp) /* save temp reg 4 */
|
|
SW t5,E_STK_T5(sp) /* save temp reg 5 */
|
|
SW t6,E_STK_T6(sp) /* save temp reg 6 */
|
|
SW t7,E_STK_T7(sp) /* save temp reg 7 */
|
|
SW t8,E_STK_T8(sp) /* save temp reg 8 */
|
|
SW t9,E_STK_T9(sp) /* save temp reg 9 */
|
|
SW s0,E_STK_S0(sp) /* save saved reg 0 */
|
|
SW s1,E_STK_S1(sp) /* save saved reg 1 */
|
|
SW s2,E_STK_S2(sp) /* save saved reg 2 */
|
|
SW s3,E_STK_S3(sp) /* save saved reg 3 */
|
|
SW s4,E_STK_S4(sp) /* save saved reg 4 */
|
|
SW s5,E_STK_S5(sp) /* save saved reg 5 */
|
|
SW s6,E_STK_S6(sp) /* save saved reg 6 */
|
|
SW s7,E_STK_S7(sp) /* save saved reg 7 */
|
|
SW s8,E_STK_FP(sp) /* save saved reg 8 */
|
|
SW gp,E_STK_GP(sp) /* save global pointer? */
|
|
SW ra,E_STK_RA(sp) /* save return address */
|
|
blink:
|
|
|
|
b blink
|
|
|
|
.end romExcHandle /* that's all folks */
|
|
|
|
/***************************************************************************
|
|
*
|
|
* initialization 'helper' code
|
|
*
|
|
*/
|
|
|
|
#include "bcm1250CpuInit.s"
|
|
#include "bcm1250DramInit.s"
|
|
|
|
#if (BOARD_TYPE == BCM91250A)
|
|
#include "swarm.s"
|
|
#elif (BOARD_TYPE == BCM91250E)
|
|
#include "sentosa.s"
|
|
#elif (BOARD_TYPE == BCM91480B)
|
|
#include "bcm91480b.s"
|
|
#endif /* BOARD_TYPE */
|
|
|
|
#endif /* INCLUDE_CFE_SUPPORT */
|