1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * CPU init module File: init_mips.S
6 * This module contains the vectors and lowest-level CPU startup
9 * Author: Mitch Lichtenberg (mpl@broadcom.com)
11 *********************************************************************
13 * Copyright 2000,2001,2002,2003
14 * Broadcom Corporation. All rights reserved.
16 * This software is furnished under license and may be used and
17 * copied only in accordance with the following terms and
18 * conditions. Subject to these conditions, you may download,
19 * copy, install, use, modify and distribute modified or unmodified
20 * copies of this software in source and/or binary form. No title
21 * or ownership is transferred hereby.
23 * 1) Any source code used, modified or distributed must reproduce
24 * and retain this copyright notice and list of conditions
25 * as they appear in the source file.
27 * 2) No right is granted to use any trade name, trademark, or
28 * logo of Broadcom Corporation. The "Broadcom Corporation"
29 * name may not be used to endorse or promote products derived
30 * from this software without the prior written permission of
31 * Broadcom Corporation.
33 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
34 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
35 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
36 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
37 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
38 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
39 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
41 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
42 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
43 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
45 * THE POSSIBILITY OF SUCH DAMAGE.
46 ********************************************************************* */
50 #include "exception.h"
52 #include "bsp_config.h"
53 #include "cpu_config.h"
56 #include "cfe_devfuncs.h"
59 #if CFG_BIENDIAN && defined(__MIPSEB)
60 #define CFE_EPTSEAL_REV 0x31454643
62 #define CFE_EPTSEAL 0x43464531
64 #define cfe_command_restart 0
67 #if CFG_VAPI /* haul in SB1250-specfic stuff only for VAPI */
68 #include "sb1250_defs.h"
69 #include "sb1250_regs.h"
70 #include "sb1250_scd.h"
73 /* *********************************************************************
75 ********************************************************************* */
77 #include "mipsmacros.h"
80 /* *********************************************************************
84 * Sets the on-board LED display (if present). Two variants
85 * of this routine are provided. If you're running KSEG1,
86 * call the SETLEDS1 variant, else call SETLEDS.
89 * a,b,c,d - four ASCII characters (literal constants)
93 ********************************************************************* */
95 #define SETLEDS(a,b,c,d) \
96 li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \
97 CALLINIT_KSEG0(init_table,R_INIT_SETLEDS)
99 #define SETLEDS1(a,b,c,d) \
100 li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \
101 CALLINIT_KSEG1(init_table,R_INIT_SETLEDS)
103 /* *********************************************************************
105 ********************************************************************* */
108 * This is the size of the stack, rounded to KByte boundaries.
111 #ifndef CFG_STACK_SIZE
112 #error "CFG_STACK_SIZE not defined"
114 #define STACK_SIZE ((CFG_STACK_SIZE+1023) & ~1023)
118 #define TEXTSECTION 0x2e746578 # ".tex", big-endian
120 #define TEXTSECTION 0x7865742e # ".tex", little-endian
124 * Duplicates from cfe_iocb.h -- warning!
127 #define CFE_CACHE_FLUSH_D 1
128 #define CFE_CACHE_INVAL_I 2
129 #define CFE_CACHE_INVAL_D 4
130 #define CFE_CACHE_INVAL_L2 8
131 #define CFE_CACHE_FLUSH_L2 16
132 #define CFE_CACHE_INVAL_RANGE 32
133 #define CFE_CACHE_FLUSH_RANGE 64
137 * To make life easier reading this code, define "KSEGBASE"
138 * to either K0BASE or K1BASE depending on whether we're running
143 #define KSEGBASE K0BASE
145 #define KSEGBASE K1BASE
149 /* *********************************************************************
150 * Names of registers used in this module
151 ********************************************************************* */
153 #define RELOCOFFSET s8 /* $30 (fp) */
154 #define TEXTOFFSET t9 /* $25 (t9) */
155 #define MEMTOP t8 /* $24 (t8) */
156 #define TEXTBASE s7 /* $23 (s7) */
160 #include "initdata.h" /* declare variables we use here */
164 cfe_spinlock: .word 0
174 /* *********************************************************************
176 ********************************************************************* */
182 /* *********************************************************************
184 ********************************************************************* */
191 * If we're building a bi-endian version, this is the base
192 * address that we can expect to find the little-endian version
195 * Warning: If you change this, you must also change
196 * the linker script (arch/mips/common/src/cfe_rom_reloc_cached_biendian.lds)
197 * and the mkflashimage program (hosttools/mkflashimage.c)
200 #define BIENDIAN_LE_BASE 0xBFD00000
203 * Declare the actual vectors. This expands to code that
204 * must be at the very beginning of the text segment.
207 DECLARE_VECTOR(0x0000,vec_reset,cpu_reset)
208 DECLARE_VECTOR(0x0200,vec_tlbfill,cpu_tlbfill)
209 DECLARE_XVECTOR(0x0280,vec_xtlbfill,cpu_xtlbfill,XTYPE_XTLBFILL)
210 DECLARE_VECTOR(0x0300,vec_cacheerr,cpu_cacheerr)
211 DECLARE_XVECTOR(0x0380,vec_exception,cpu_exception,XTYPE_EXCEPTION)
212 DECLARE_XVECTOR(0x0400,vec_interrupt,cpu_interrupt,XTYPE_INTERRUPT)
213 DECLARE_XVECTOR(0x0480,vec_ejtag,cpu_ejtag,XTYPE_EJTAG)
217 * New location of CFE seal. Will eventually phase out the seal at
221 cfe_seal: .word CFE_EPTSEAL
224 #if CFG_BIENDIAN && defined(__MIPSEB)
226 cfe_seal_rev: .word CFE_EPTSEAL_REV
227 .word CFE_EPTSEAL_REV
232 /* *********************************************************************
233 * CFE Entry Point (used by OS boot loaders and such)
234 ********************************************************************* */
238 DECLARE_VECTOR(0x0500,vec_apientry,cpu_apientry)
245 /* *********************************************************************
246 * Verification APIs (if present) [SB1250-specific]
247 ********************************************************************* */
251 #error "CFG_VAPI is not compatible with relocatable code"
255 * Vector should be 16 bytes long
257 #define VAPI_VECTOR(l,x) \
259 .org (l & 0xFFFF) ; \
262 .word VAPI_EPTSEAL ; \
265 VAPI_VECTOR(VAPI_FUNC_EXIT,vapi_exit)
266 VAPI_VECTOR(VAPI_FUNC_DUMPGPRS,vapi_dumpgprs)
267 VAPI_VECTOR(VAPI_FUNC_SETLOG,vapi_setlog)
268 VAPI_VECTOR(VAPI_FUNC_LOGVALUE,vapi_logsingle)
269 VAPI_VECTOR(VAPI_FUNC_LOGDATA,vapi_logdata)
270 VAPI_VECTOR(VAPI_FUNC_LOGTRACE,vapi_logtrace)
271 VAPI_VECTOR(VAPI_FUNC_LOGSOC,vapi_savesoc)
272 VAPI_VECTOR(VAPI_FUNC_LOGGPRS,vapi_loggprs)
273 VAPI_VECTOR(VAPI_FUNC_DUMPSTRING,vapi_puts)
274 VAPI_VECTOR(VAPI_FUNC_SETLEDS,vapi_setleds)
275 VAPI_VECTOR(VAPI_FUNC_LOGFPRS,vapi_logfprs)
281 /* *********************************************************************
282 * Some offsets depend on our current configuration
283 ********************************************************************* */
286 #define RUNTIME_RELOC_START __runtime_reloc_start
287 #define RUNTIME_RELOC_STOP __runtime_reloc_stop
289 #define RUNTIME_RELOC_START 0
290 #define RUNTIME_RELOC_STOP 0
294 /* *********************************************************************
297 * Addresses of data segments and of certain routines we're going
298 * to call from KSEG1. These are here mostly for the embedded
299 * PIC case, since we can't count on the 'la' instruction to
300 * do the expected thing (the assembler expands it into a macro
301 * for doing GP-relative stuff, and the code is NOT GP-relative.
302 * So, we (relocatably) get the offset of this table and then
305 * Pointer values in this segment will be relative to KSEG0 for
306 * cached versions of CFE, so we need to OR in K1BASE in the
307 * case of calling to a uncached address.
309 * The LOADREL macro handles most of the nastiness here.
310 ********************************************************************* */
313 #include "segtable.h"
316 .org 0x600 # move past exception vectors
318 .org 0x580 # move past exception vectors
321 #if CFG_EMBEDDED_NVRAM
323 .globl embedded_nvram
324 embedded_nvram: .fill 0x400,4,~(0x48534c46)
325 .long 0x4c5a4d41 # LZMA NVRAM Supported
331 _LONG_ _etext # [ 0] End of text (R_SEG_ETEXT)
332 _LONG_ _fdata # [ 1] Beginning of data (R_SEG_FDATA)
333 _LONG_ _edata # [ 2] End of data (R_SEG_EDATA)
334 _LONG_ _end # [ 3] End of BSS (R_SEG_END)
335 _LONG_ _ftext # [ 4] Beginning of text (R_SEG_FTEXT)
336 _LONG_ _fbss # [ 5] Beginning of BSS (R_SEG_FBSS)
337 _LONG_ _gp # [ 6] Global Pointer (R_SEG_GP)
338 _LONG_ RUNTIME_RELOC_START # [ 7] Beginning of reloc entries
339 _LONG_ RUNTIME_RELOC_STOP # [ 8] End of reloc entries
340 _LONG_ cpu_apientry # [ 9] R_SEG_APIENTRY
342 /* *********************************************************************
345 * This is like segment_table except it contains pointers to
346 * routines used during initialization. It serves both as a
347 * table for doing PIC stuff and also to separate out
348 * machine-specific init routines.
350 * The CALLINIT_xxx macros are used to call routines in this table.
351 ********************************************************************* */
356 _LONG_ board_earlyinit # [ 0] R_INIT_EARLYINIT
357 _LONG_ board_setleds # [ 1] R_INIT_SETLEDS
358 _LONG_ board_draminfo # [ 2] R_INIT_DRAMINFO
359 _LONG_ CPUCFG_CPUINIT # [ 3] R_INIT_CPUINIT
360 _LONG_ CPUCFG_ALTCPU_START1 # [ 4] R_INIT_ALTCPU_START1
361 _LONG_ CPUCFG_ALTCPU_START2 # [ 5] R_INIT_ALTCPU_START2
362 _LONG_ CPUCFG_ALTCPU_RESET # [ 6] R_INIT_ALTCPU_RESET
363 _LONG_ CPUCFG_CPURESTART # [ 7] R_INIT_CPURESTART
364 _LONG_ CPUCFG_DRAMINIT # [ 8] R_INIT_DRAMINIT
365 _LONG_ CPUCFG_CACHEOPS # [ 9] R_INIT_CACHEOPS
366 _LONG_ CPUCFG_TLBHANDLER # [ 10] R_INIT_TLBHANDLER
367 _LONG_ cfe_main # [ 11] R_INIT_CMDSTART
368 _LONG_ cfe_command_restart # [ 12] R_INIT_CMDRESTART
369 _LONG_ cfe_doxreq # [ 13] R_INIT_DOXREQ
372 #if !CFG_MINIMAL_SIZE
374 diag_table: _LONG_ CPUCFG_DIAG_TEST1 # [ 0 ] R_DIAG_TEST1
375 _LONG_ CPUCFG_DIAG_TEST2 # [ 1 ] R_DIAG_TEST2
378 /* *********************************************************************
380 ********************************************************************* */
385 * Start with GP as zero. Nobody should touch
386 * this or set it to any other value until we're ready
387 * to use it. This is used to tell when we should start
388 * using relocated references in the init table,
389 * so beware! (see CALLINIT_RELOC in mipsmacros.h)
392 move gp,zero # start with no GP.
396 * VAPI works by using the SCD to reset just the core.
397 * Look for a special signature in the mailbox register
398 * on CPU0 - if present, jump to the start of the diag.
399 * Of course, you need a real 12500 to do this.
402 li k0,PHYS_TO_K1(A_IMR_REGISTER(0,R_IMR_MAILBOX_CPU))
404 dli k1,VAPI_MAGIC_NUMBER_MC
406 dli k1,VAPI_MAGIC_NUMBER_UNC
407 beq k0,k1,vapi_rununc
408 dli k1,VAPI_MAGIC_NUMBER
412 * The only CP0 init we do is to set K0 to cacheable
415 mfc0 k0,C0_CONFIG # get current CONFIG register
416 srl k0,k0,3 # strip out K0 bits
417 sll k0,k0,3 # k0 bits now zero
418 or k0,k0,K_CFG_K0COH_COHERENT # K0 is cacheable.
422 * Set any required defeature bits (for VAPI diagnostics only)
423 * they get cleared by the soft reset.
426 jal sb1250_reset_defeature /* in sb1250_l1cache.S */
429 * Jump to the diagnostic. Two variants, one for cached
430 * and one for uncached.
433 li k0,VAPI_DIAG_ENTRY
436 vapi_rununc: li k0,VAPI_DIAG_ENTRY_UNC
439 vapi_runmc: li k0,VAPI_DIAG_ENTRY_MC
446 * Test the CAUSE and STATUS registers for why we
447 * are here. Cold reset, Warm reset, and NMI all
454 * Test to see if we're on the secondary CPU. If so,
455 * go do the initialization for that CPU.
459 CALLINIT_KSEG1(init_table,R_INIT_ALTCPU_RESET)
460 /* does not return if on CPU1 */
463 #------------------------------------------------------------------------------
466 * Do low-level board initialization. This is our first
467 * chance to customize the startup sequence.
470 CALLINIT_KSEG1(init_table,R_INIT_EARLYINIT)
472 SETLEDS1('H','E','L','O')
474 CALLINIT_KSEG1(init_table,R_INIT_CPUINIT)
477 * Run some diagnostics
480 #if !CFG_MINIMAL_SIZE
481 SETLEDS1('T','S','T','1')
483 CALLINIT_KSEG1(diag_table,R_DIAG_TEST1)
487 #------------------------------------------------------------------------------
490 * Spin up secondary CPU core(s)
493 CALLINIT_KSEG1(init_table,R_INIT_ALTCPU_START1)
497 * Now, switch from KSEG1 to KSEG0
505 #------------------------------------------------------------------------------
507 * Now running on cpu0 in K0SEG.
511 SETLEDS('D','R','A','M')
513 CALLINIT_KSEG0(init_table,R_INIT_DRAMINFO)
515 move a0,v0 # pass these params
516 CALLINIT_KSEG0(init_table,R_INIT_DRAMINIT)
517 srl k0,v0,10 # board_draminit returns memsize in bytes
526 /* Check if we are already in RAM */
535 SETLEDS('C','O','P','Y')
537 #if !CFG_EMBEDDED_PIC
539 /* Copy self to RAM */
543 /* Copy data only to RAM */
559 SETLEDS('Z','B','S','S')
571 SETLEDS(' ','D','$','F')
573 /* Flush the D cache */
574 CALLINIT_KSEG0(cacheops_table,_TBLIDX(0))
576 SETLEDS(' ','I','$','I')
578 /* and invalidate the I cache */
579 CALLINIT_KSEG0(cacheops_table,_TBLIDX(1))
581 SETLEDS(' ','J','S','R')
583 /* Jump to self in RAM */
588 .globl cacheops_table
589 cacheops_table: _LONG_ bcmcore_l1cache_flush_d # [ 0 ] DCACHE_FULSH
590 _LONG_ bcmcore_l1cache_inval_i # [ 1 ] ICACHE_INVAL
593 #------------------------------------------------------------------------------
596 b have_ram # No RAM is ok if using emulator RAM
601 SETLEDS('R','A','M','X') # die here if no ram
608 * If this is the 64-bit version, turn on the KX bit
609 * to allow 64-bit accesses.
618 #------------------------------------------------------------------------------
620 * K0 contains the RAM size (and therefore the top of RAM
621 * offset). Start there, and subtract the amount of memory
622 * we expect to use. If we have more than 256MB of
623 * physical memory, work backwards from the 256MB
627 __CalcMemTop: li MEMTOP,0x40000 # 256MB boundary
628 bgt k0,MEMTOP,1f # use 256MB if k0 is greater
629 move MEMTOP,k0 # otherwise keep top
630 1: sll MEMTOP,10 # make into byte amount
635 * Calculate the data relocation amount. Store in FP
636 * for now. We'll call this register RELOCOFFSET.
638 * Also calculate a similar offset for relocating code
639 * if we're doing that. Call this TEXTOFFSET (t9).
642 LOADREL(a0,segment_table) # we'll need this.
644 LR t1,R_SEG_ETEXT(a0)
645 LR t0,R_SEG_FTEXT(a0)
646 sub t1,t1,t0 # T1 = text size
647 sub t3,MEMTOP,t1 # reserve room for code
648 li t2,~31 # round down to cache-line boundary
650 move TEXTBASE,t3 # TEXTBASE is current mem top
651 sub TEXTBASE,64 # Reserve top 64 bytes
654 * If you're debugging the relocation stuff, you can uncomment this
655 * line to force CFE to be relocated to a specific address. Sure
656 * makes life easier when setting breakpoints!
658 * li TEXTBASE,0x3C00000
662 add TEXTBASE,t2 # offset is in K0SEG.
663 sub TEXTOFFSET,TEXTBASE,t0 # TEXTOFFSET is distance to move
667 li t0,((CFG_HEAP_SIZE*1024)+STACK_SIZE) # t0 = size of heap + stack
669 LR t2,R_SEG_FDATA(a0)
670 sub t1,t2 # t1 = data + bss
671 add t0,t1 # t0 = total
672 li t1,31 # round to 32-byte boundary
675 and t0,t1 # t0 = total size rounded up
677 sub t1,TEXTBASE,t0 # t1 = TEXTBASE - total size
680 * t1 now contains the place where we would like to put our
681 * data segment, BSS, and heap. Calculate the difference between that
682 * and where our data segment currently resides.
685 LR t0,R_SEG_FDATA(a0) # beginning of data
686 subu RELOCOFFSET,t1,t0 # offset = distance to move segment
688 li t0,31 # round *down* to a cache line
692 li RELOCOFFSET,0 # not relocating, no offset
697 * DRAM is now running, and we're alive in cacheable memory
698 * on cpu0 in K0SEG. Set up GP.
701 LOADREL(a0,segment_table)
706 #------------------------------------------------------------------------------
711 SETLEDS('Z','B','S','S')
713 LOADREL(a0,segment_table)
718 ADD v0,RELOCOFFSET # Relocate to actual data segment
721 1: SR zero,0(v0) # Zero one cacheline at a time
722 SR zero,(REGSIZE*1)(v0)
723 SR zero,(REGSIZE*2)(v0)
724 SR zero,(REGSIZE*3)(v0)
728 #------------------------------------------------------------------------------
733 SETLEDS('C','O','D','E')
735 LOADREL(a0,segment_table)
738 move t1,TEXTBASE # destination address
740 LR t2,R_SEG_FTEXT(a0) # Source address
741 LR t3,R_SEG_ETEXT(a0)
743 1: LR t4,0(t2) # read one cache line
744 LR t5,(REGSIZE*1)(t2)
745 LR t6,(REGSIZE*2)(t2)
746 LR t7,(REGSIZE*3)(t2)
747 SR t4,0(t1) # write one cache line
748 SR t5,(REGSIZE*1)(t1)
749 SR t6,(REGSIZE*2)(t1)
750 SR t7,(REGSIZE*3)(t1)
756 #------------------------------------------------------------------------------
758 * Copy initialized data
761 #if (CFG_BOOTRAM == 0)
763 SETLEDS('D','A','T','A')
765 LOADREL(a0,segment_table)
768 LR t1,R_SEG_ETEXT(a0)
772 and t1,t0 # t1 = _etext rounded up to 16-byte boundary
774 LR t2,R_SEG_FDATA(a0)
775 LR t3,R_SEG_EDATA(a0)
776 ADD t2,RELOCOFFSET # Relocate to actual data segment
779 1: LR t4,0(t1) # read one cache line
780 LR t5,(REGSIZE*1)(t1)
781 LR t6,(REGSIZE*2)(t1)
782 LR t7,(REGSIZE*3)(t1)
783 SR t4,0(t2) # write one cache line
784 SR t5,(REGSIZE*1)(t2)
785 SR t6,(REGSIZE*2)(t2)
786 SR t7,(REGSIZE*3)(t2)
793 #------------------------------------------------------------------------------
798 * Walk through relocation table and do the data segment
799 * fixups. Each entry in this table is in the following
802 * <offset> <segment-name>
805 * The 'offset' represents the distance into the segment where
806 * a fixup needs to be applied, and the 'segment-name'
807 * is the name of the section where the offset is located.
808 * The basic idea is that you would expect that code and
809 * data are moved by different amounts, so places where
810 * the data segment references the text segment you need
811 * apply the offset that the text segment was moved, not data.
815 SETLEDS('R','E','L','O')
817 LOADREL(a0,segment_table)
819 LR a1,R_SEG_FDATA(a0) # beginning of data segment
820 add a1,RELOCOFFSET # relocate it.
822 LR v0,R_SEG_RELOCSTART(a0) # relocs start here
823 LR v1,R_SEG_RELOCEND(a0) # and end here
824 li t2,TEXTSECTION # marker for text sections
827 # The bottom bit in the offset will be set if we want to
828 # handle a MIPS_64 relocation. Of course, this bit is not really
829 # part of the relocation offset.
831 li t4,1 # Make the mask that we
832 not t4 # need to mask off bottom bit
834 reloclp: lw t0,4(v0) # Get section name
835 beq t0,t2,textreloc # skip if for text section
837 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
839 lw t0,0(v0) # T0 = relocation offset
840 and t1,t0,1 # test MIPS_64 reloc bit (t1=0 for 32-bit)
841 and t0,t4 # clear MIPS_64 reloc bit
842 add t0,a1 # Add offset to start of data segment
844 beq t1,zero,reloc32 # go if doing a 32-bit reloc
846 reloc64: ld t1,(t0) # Get word from data segment
847 add t1,RELOCOFFSET # Add relocation offset
848 sd t1,(t0) # Put it back
849 b skipreloc # next...
851 reloc32: lw t1,(t0) # Get word from data segment
852 add t1,RELOCOFFSET # Add relocation offset
853 sw t1,(t0) # Put it back
856 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
859 lw t0,0(v0) # T0 = relocation offset
860 and t1,t0,1 # test MIPS_64 reloc bit (t1=0 for 32-bit)
861 and t0,t4 # clear MIPS_64 reloc bit
862 add t0,a1 # Add offset to start of data segment
864 beq t1,zero,treloc32 # go if doing a 32-bit reloc
866 treloc64: ld t1,(t0) # Get word from data segment
867 add t1,TEXTOFFSET # Add relocation offset
868 sd t1,(t0) # Put it back
869 b skipreloc # next...
871 treloc32: lw t1,(t0) # Get word from data segment
872 add t1,TEXTOFFSET # Add relocation offset
873 sw t1,(t0) # Put it back
876 skipreloc: add v0,12 # Go to next relocation entry
881 #------------------------------------------------------------------------------
885 * Flush the cache, then switch to relocated code
886 * We need to flush the cache since we just moved the code and
887 * it may still live in our L1 DCache. We also need to
888 * flush L2, since there are some rare times we run
889 * uncached from DRAM, like when we start/stop a CPU.
891 * In the case of running completely uncached, don't flush the
892 * cache. It should not have any dirty lines in it, but you
899 SETLEDS('L','1','2','F')
901 li a0,CFE_CACHE_FLUSH_D | CFE_CACHE_FLUSH_L2
902 CALLINIT_KSEG0(init_table,R_INIT_CACHEOPS)
903 li a0,CFE_CACHE_INVAL_I
904 CALLINIT_KSEG0(init_table,R_INIT_CACHEOPS)
905 #endif /* CFG_RUNFROMKSEG0 */
907 LOADREL(t0,gorelo) # get offset of next instr
908 add t0,TEXTOFFSET # add in our relocation
914 * Remember total amount of memory. This is *still* in k0
915 * after all this time. Hopefully.
920 SR RELOCOFFSET,mem_datareloc
924 LOADREL(a0,segment_table) # trashed by l2 cache flush
926 LR v0,R_SEG_FDATA(a0)
929 LR v0,R_SEG_FTEXT(a0)
935 SR v0,mem_bottomofmem
939 move t0,MEMTOP # relocated code means top of memory
940 add t0,KSEGBASE # is *after* code.
943 // SR gp,-8(t0) # Store handle at top of memory
944 // SR zero,-16(t0) # Zero out the other handles
945 // SR zero,-24(t0) # in our special place.
950 add v1,(CFG_HEAP_SIZE*1024) # Otherwise
955 SR TEXTOFFSET,mem_textreloc
957 /* At this point it's safe to use the CALLINIT_RELOC macro */
960 LR t1,R_SEG_FTEXT(a0)
961 LR t0,R_SEG_ETEXT(a0)
968 #------------------------------------------------------------------------------
972 * Let secondary CPU(s) run their idle loops. Set the
973 * mailbox register to our relocation factor so we can read
974 * it out of the mailbox register and relocate GP properly.
978 CALLINIT_RELOC(init_table,R_INIT_ALTCPU_START2)
981 #ifdef _SB1250_PASS1_WORKAROUNDS_
983 * Okay, it's safe now to be coherent.
984 * Flush the D cache to invalidate all the lines we have,
985 * then change the config register back.
987 li a0,CFE_CACHE_FLUSH_D
988 CALLINIT_RELOC(init_table,R_INIT_CACHEOPS)
989 SETCCAMODE(v0,K_CFG_K0COH_COHERENT) /* cacheable coherent */
993 * Stash away some config register stuff
1000 #------------------------------------------------------------------------------
1003 * Set up the "C" stack and jump to the main routine.
1006 SETLEDS('M','A','I','N')
1009 ADD sp,((CFG_HEAP_SIZE*1024)+STACK_SIZE - 8)
1010 li a0,0 # call as "cfe_main(0,0)"
1013 CALLINIT_RELOC(init_table,R_INIT_CMDSTART) # should not return
1017 * Terminate the simulator.
1028 /* *********************************************************************
1031 * Restart the command interpreter
1034 * A0 - command status
1035 * nothing (GP has already been set up for us)
1039 ********************************************************************* */
1043 SR a0,0(sp) # store on old stack
1044 LOADREL(v0,init_table)
1045 LR v0,R_INIT_CPURESTART(v0)
1046 #if CFG_EMBEDDED_PIC
1047 LR t0,mem_textreloc # relocate table entry
1051 jal v0 # had better not trash GP or K1
1054 * If this is the 64-bit version, turn on the KX bit
1055 * to allow 64-bit accesses. Do after calling the cpu
1056 * init routine, but before touching the stack, which
1057 * *could* be a 64-bit address.
1070 ADD sp,((CFG_HEAP_SIZE*1024)+STACK_SIZE - 8)
1073 * If someone called the API to do a warm start, clear the
1074 * spin lock, since the call will never return.
1078 SPIN_UNLOCK(cfe_spinlock,t0)
1081 CALLINIT_RELOC(init_table,R_INIT_CMDRESTART) # should not return
1086 /* *********************************************************************
1089 * Perform certain cache operations
1092 * a0 - flags (CFE_CACHE_xxx flags, or zero for a default)
1093 * a1,a2 - start/end of range for "range invalidate" operations
1094 * (not used otherwise)
1098 ********************************************************************* */
1100 LEAF(_cfe_flushcache)
1113 CALLINIT_RELOC(init_table,R_INIT_CACHEOPS)
1126 END(_cfe_flushcache)
1129 /* *********************************************************************
1132 * Start the user program. The program is passed a handle
1133 * that must be passed back when calling the firmware.
1135 * Parameters passed to the called program are as follows:
1139 * a2 - reserved, will be 0
1140 * a3 - entrypoint signature.
1147 ********************************************************************* */
1156 * Mask all interrupts.
1158 mfc0 v0,C0_SR # Get current interrupt flag
1159 li v1,M_SR_IE # master interrupt control
1160 not v1 # disable interrupts
1161 and v0,v1 # SR now has IE=0
1162 mtc0 v0,C0_SR # put back into CP0
1166 * Flush the D-Cache, since the program we loaded is "data".
1167 * Invalidate the I-Cache, so that addresses in the program
1168 * region will miss and need to be filled from the data we
1169 * just flushed above.
1172 li a0,CFE_CACHE_FLUSH_D|CFE_CACHE_INVAL_I
1173 CALLINIT_RELOC(init_table,R_INIT_CACHEOPS)
1177 * Set things up for launching the program. Pass the
1178 * handle in A0 - apps need to remember that and pass it
1187 * This is a nice place to set a breakpoint.
1191 LOADREL(a2,segment_table)
1192 LR a2,R_SEG_APIENTRY(a2) # A2 = code entry
1194 #if CFG_EMBEDDED_PIC
1195 LR t1,mem_textreloc # relocate table entry
1199 move a1,zero # A1 = 0
1200 move a0,gp # A0 = handle
1201 li a3,CFE_EPTSEAL # A3 = entrypoint signature
1202 LR t0,0(sp) # entry point
1210 /* *********************************************************************
1213 * Set the on-board LEDs.
1220 ********************************************************************* */
1224 #if CFG_EMBEDDED_PIC
1225 move t1,ra # LOADREL trashes ra!
1226 LOADREL(t0,init_table)
1228 LR t0,R_INIT_SETLEDS(t0)
1231 j board_setleds # jump to BSP routine
1236 /* *********************************************************************
1237 * TLB Fill Exeption Handler
1238 ********************************************************************* */
1241 move k0,ra # Save, we're about to trash
1242 LOADREL(k1,init_table) # Load offset of init table
1243 LR k1,R_INIT_TLBHANDLER(k1) # Get entry from table
1244 move ra,k0 # restore trashed ra
1245 j k1 # Dispatch to handler
1247 /* *********************************************************************
1248 * XTLB Fill Exception Handler
1249 ********************************************************************* */
1254 /* *********************************************************************
1255 * Cache Error Exception Handler
1256 ********************************************************************* */
1260 #if defined(_CSWARM_) || defined(_SWARM_) || defined(_BCM91120C_) || defined(_PTSWARM_)
1261 #define LED_CHAR0 (32+8*3)
1262 #define LED_CHAR1 (32+8*2)
1263 #define LED_CHAR2 (32+8*1)
1264 #define LED_CHAR3 (32+8*0)
1265 #if defined(_PTSWARM_)
1266 li k0,0xBB0A0000 /* address of LEDs */
1268 li k0,0xB00A0000 /* address of LEDs */
1279 SETLEDS1('C','e','r','2')
1282 cpu_cache_death: b cpu_cache_death
1286 /* *********************************************************************
1287 * General Exception Handler
1288 ********************************************************************* */
1294 /* *********************************************************************
1295 * General Interrupt Handler
1296 ********************************************************************* */
1302 /* *********************************************************************
1303 * EJTAG Debug Exception Handler
1304 ********************************************************************* */
1313 /* *********************************************************************
1314 * cpu_apientry(handle,iocb)
1316 * API entry point for external apps.
1319 * a0 - firmware handle (used to determine the location of
1320 * our relocated data)
1321 * a1 - pointer to IOCB to execute
1324 * v0 - return code, 0 if ok
1325 ********************************************************************* */
1327 #define _regidx(x) ((x)*8)
1329 #define CAE_SRSAVE _regidx(0)
1330 #define CAE_GPSAVE _regidx(1)
1331 #define CAE_RASAVE _regidx(2)
1332 #define CAE_S0SAVE _regidx(3)
1333 #define CAE_S1SAVE _regidx(4)
1334 #define CAE_S2SAVE _regidx(5)
1335 #define CAE_S3SAVE _regidx(6)
1336 #define CAE_S4SAVE _regidx(7)
1337 #define CAE_S5SAVE _regidx(8)
1338 #define CAE_S6SAVE _regidx(9)
1339 #define CAE_S7SAVE _regidx(10)
1340 #define CAE_K0SAVE _regidx(11)
1341 #define CAE_K1SAVE _regidx(12)
1343 #define CAE_STKSIZE _regidx(13)
1347 sub sp,CAE_STKSIZE # Make room for our stuff
1349 mfc0 v0,C0_SR # Get current interrupt flag
1350 SR v0,CAE_SRSAVE(sp) # save on stack
1351 li t0,M_SR_IE # master interrupt control
1352 not t0 # disable interrupts
1353 and v0,t0 # SR now has IE=0
1357 mtc0 v0,C0_SR # put back into CP0
1360 SR gp,CAE_GPSAVE(sp) # save GP
1361 SR ra,CAE_RASAVE(sp) # and old RA
1363 SR s0,CAE_S0SAVE(sp)
1364 SR s1,CAE_S1SAVE(sp)
1365 SR s2,CAE_S2SAVE(sp)
1366 SR s3,CAE_S3SAVE(sp)
1367 SR s4,CAE_S4SAVE(sp)
1368 SR s5,CAE_S5SAVE(sp)
1369 SR s6,CAE_S6SAVE(sp)
1370 SR s7,CAE_S7SAVE(sp)
1371 SR k0,CAE_K0SAVE(sp)
1372 SR k1,CAE_K1SAVE(sp)
1374 move gp,a0 # set up new GP
1375 move a0,a1 # A0 points at IOCB
1377 #if CFG_RUNFROMKSEG0
1378 bal cpu_kseg0_switch # switch to kseg0 if not already there
1382 SPIN_LOCK(cfe_spinlock,t0,t1)
1385 CALLINIT_RELOC(init_table,R_INIT_DOXREQ)
1388 SPIN_UNLOCK(cfe_spinlock,t0)
1392 # Restore the saved registers.
1395 LR k1,CAE_K1SAVE(sp)
1396 LR k0,CAE_K0SAVE(sp)
1397 LR s7,CAE_S7SAVE(sp)
1398 LR s6,CAE_S6SAVE(sp)
1399 LR s5,CAE_S5SAVE(sp)
1400 LR s4,CAE_S4SAVE(sp)
1401 LR s3,CAE_S3SAVE(sp)
1402 LR s2,CAE_S2SAVE(sp)
1403 LR s1,CAE_S1SAVE(sp)
1404 LR s0,CAE_S0SAVE(sp)
1406 LR ra,CAE_RASAVE(sp) # unwind the stack
1407 LR gp,CAE_GPSAVE(sp)
1409 LR t0,CAE_SRSAVE(sp) # old interrupt mask
1411 add sp,CAE_STKSIZE # restore old stack pointer
1413 mtc0 t0,C0_SR # restore interrupts
1421 /* *********************************************************************
1424 * Hack the return address so we will come back in KSEG0
1431 ********************************************************************* */
1433 LEAF(cpu_kseg0_switch)
1439 END(cpu_kseg0_switch)
1444 /* *********************************************************************
1447 * Read the STATUS register into v0
1453 * v0 - Status register
1454 ********************************************************************* */
1462 /* *********************************************************************
1465 * Set the STATUS register to the value in a0
1471 * v0 - Status register
1472 ********************************************************************* */
1481 /* *********************************************************************
1484 * Read the CAUSE register into v0
1490 * v0 - Cause register
1491 ********************************************************************* */
1500 /* *********************************************************************
1503 * Read the COUNT register into v0
1509 * v0 - count register
1510 ********************************************************************* */
1519 /* *********************************************************************
1522 * Set the C0_Compare register from a0
1525 * a0 - compare register
1529 ********************************************************************* */
1538 /* *********************************************************************
1541 * Set the CONTEXT register.
1548 ********************************************************************* */
1556 /* *********************************************************************
1559 * Return the address of the segment table. We use this
1560 * to display the startup messages.
1562 * You can't just address the table from C because it lives
1563 * in the text segment.
1570 ********************************************************************* */
1575 LOADREL(v0,segment_table)
1581 /* *********************************************************************
1584 * Flush the write buffer. This is probably not necessary
1585 * on SiByte CPUs, but we have it for completeness.
1592 ********************************************************************* */
1596 sync /* drain the buffers */
1597 la t0,__junk /* do an uncached read to force it out */
1605 /* *********************************************************************
1607 ********************************************************************* */