⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bcm1480_altcpu.s

📁 一个很好的嵌入式linux平台下的bootloader
💻 S
📖 第 1 页 / 共 2 页
字号:
/*  *********************************************************************    *  Broadcom Common Firmware Environment (CFE)    *      *  CPU init module				File: bcm1480_altcpu.S    *    *  Secondary core startup routines for CFE    *      *  Author:  Mitch Lichtenberg    *      *********************************************************************      *    *  Copyright 2000,2001,2002,2003    *  Broadcom Corporation. All rights reserved.    *      *  This software is furnished under license and may be used and     *  copied only in accordance with the following terms and     *  conditions.  Subject to these conditions, you may download,     *  copy, install, use, modify and distribute modified or unmodified     *  copies of this software in source and/or binary form.  No title     *  or ownership is transferred hereby.    *      *  1) Any source code used, modified or distributed must reproduce     *     and retain this copyright notice and list of conditions     *     as they appear in the source file.    *      *  2) No right is granted to use any trade name, trademark, or     *     logo of Broadcom Corporation.  The "Broadcom Corporation"     *     name may not be used to endorse or promote products derived     *     from this software without the prior written permission of     *     Broadcom Corporation.    *      *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR     *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT     *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN     *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES     *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY     *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF     *     THE POSSIBILITY OF SUCH DAMAGE.    ********************************************************************* */#include "sbmips.h"#include "exception.h"#include "bsp_config.h"#ifdef _CFE_#include "cfe_devfuncs.h"#else#define CFE_EPTSEAL 0x43464531#endif#include "bcm1480_regs.h"#include "bcm1480_scd.h"#include "cpu_config.h"/*  *********************************************************************    *  Macros    ********************************************************************* */#include "mipsmacros.h"#define SETLEDS1(a,b,c,d)                     \       li     a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ;    \       JAL_KSEG1(board_setleds)#define SETLEDS(a,b,c,d)                     \       li     a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ;    \       JAL(board_setleds)#define SETLEDS1_ADD(a,b,c,d,add)			\       li     a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ;	\       addu   a0, a0, add ;				\       JAL_KSEG1(board_setleds)#define SETLEDS_ADD(a,b,c,d,add)			\       li     a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ;	\       addu   a0, a0, add ;				\       JAL(board_setleds)/* * Read system revision register to get # of CPUs on this part *   Do this by reading CPU disables from system_cfg, *   and using that to index a bit array to get the number of *   cpus enabled (minus 1). */ #define GET_NUM_CPUS(reg, tmp) 					\		la	reg,PHYS_TO_K1(A_SCD_SYSTEM_CFG)	; \		ld	reg,(reg)				; \		dsrl	reg,(S_BCM1480_SYS_DISABLECPU0)		; \		and	reg,0x0f				; \		li	tmp, 0x0116166b				; \		srl	tmp, tmp, reg				; \		srl	tmp, tmp, reg   /* really, twice */	; \		andi	tmp, tmp, 0x3				; \		addiu	reg, tmp, 1#define GET_CUR_CPU(reg) \		mfc0	reg,C0_PRID ; \		srl	reg,reg,25 ; \		and	reg,reg,7   /*  *********************************************************************    *  Initialized Data    ********************************************************************* */                .sdata#define R_CPU_STARTVECT	_TBLIDX(0)#define R_CPU_SPVAL	_TBLIDX(1)#define R_CPU_GPVAL	_TBLIDX(2)#define R_CPU_ARG	_TBLIDX(3)#define R_CPU_RECSIZE	32		/* One cache line per record *//* * Initial start addresses for secondary CPUs.  Each record below * is on its own cache line.  That cache line will be held exclusive * by the owning CPU and only the snoop traffic should show up * on the bus. */		.align 5		.globl	cpu_idledatacpu_idledata:		.dword 0,0,0,0			# cpu #0 (not used)		.dword 0,0,0,0			# cpu #1		.dword 0,0,0,0			# cpu #2		.dword 0,0,0,0			# cpu #3		.extern mem_datareloc		.text		.set mips64/*  *********************************************************************    *  ALTCPU_KSEG1_SWITCH    *      *  Hack the return address so we will come back in KSEG1 (uncached)    *      *  Input parameters:     *  	   nothing    *  	       *  Return value:    *  	   nothing    ********************************************************************* */LEAF(altcpu_kseg1_switch)_altcpu_kseg1_switch:		and	ra,(K0SIZE-1)		or	ra,K1BASE		jr	raEND(altcpu_kseg1_switch)/*  *********************************************************************    *  ALTCPU_KSEG0_SWITCH    *      *  Hack the return address so we will come back in KSEG0    *      *  Input parameters:     *  	   nothing    *  	       *  Return value:    *  	   nothing    ********************************************************************* */LEAF(altcpu_kseg0_switch)_altcpu_kseg0_switch:		and	ra,(K0SIZE-1)		or	ra,K0BASE		jr	raEND(altcpu_kseg0_switch)/*  *********************************************************************    *  BCM1480_ALTCPU_START1    *      *  Start secondary processor(s).  These processors will start    *  running the code at ALTCPU_RESET (see below).  We wait here    *  for the secondary processor(s) to finish their cache    *  initialization and then  return.    *    *  For simplicity, we serialize starting the secondary processors    *  and waiting until done for now.    *    *  This routine is normally run from KSEG1    *      *  Input parameters:     *  	   nothing    *  	       *  Return value:    *  	   nothing    ********************************************************************* */LEAF(bcm1480_altcpu_start1)	/*	 * Do this only for CPUs with non-zero processor IDs, possibly	 * none if we have only one CPU.  This way we can	 * support running the multiprocessor version of CFE	 * with only one core.	 */		GET_NUM_CPUS(v0, t0)		b	3f			# loop test	/*	 * Main loop, CPU number is in v0.	 */1:	/*	 * Clear out our mailbox registers (both CPUs)	 * XXX - need to do all CPUs and both mailboxes	 */		la	a0,PHYS_TO_K1(A_BCM1480_IMR_REGISTER(0,R_BCM1480_IMR_MAILBOX_0_CLR_CPU))		dli	t0,-1			# clear all 64 bits		dli	t1,BCM1480_IMR_REGISTER_SPACING		sd	t0,(a0)		multu	v0,t1		mflo	t1		daddu	a0,a0,t1		sd	t0,(a0)	/*	 * Let the secondary CPU(s) out of reset	 * 	 * XXX This is very BCM1480-specific at the moment.	 */		la	a0,PHYS_TO_K1(A_SCD_SYSTEM_CFG)		ld	t0,0(a0)		dli	t1,M_BCM1480_SYS_CPU_RESET_0	# Base reset mask		dsll	t1,t1,v0		not	t1			# clear this bit		and	t0,t1			# New value to write		sd	t0,0(a0)		# CPU[v0] is now running	/*	 * Wait for the other CPU to ring our doorbell	 */2:		la	a0,PHYS_TO_K1(A_BCM1480_IMR_REGISTER(0,R_BCM1480_IMR_MAILBOX_0_CPU));		ld	t0,(a0)			# Read mailbox		beq	t0,zero,2b		# Loop till the bit is set	/*	 * Clear the mailbox to dismiss the pending interrupts	 */		la	a0,PHYS_TO_K1(A_BCM1480_IMR_REGISTER(0,R_BCM1480_IMR_MAILBOX_0_CLR_CPU))		dli	t0,-1			# clear all 64 bits		sd	t0,(a0)3:		daddiu	v0,v0,-1		bne	v0,zero,1b		# Keep going if more secondary CPUs		/*	 * Okay, it's safe to return	 */		j	raEND(bcm1480_altcpu_start1)/*  *********************************************************************    *  BCM1480_ALTCPU_START2    *      *  Finish startup of secondary processor(s) - we pass the relocation    *  offset to the other CPUs here, and the CPUs relocate their    *  data segments and go to the idle loop.    *    *  This routine is normally run from KSEG0    *      *  Input parameters:     *  	   a0 - data relocation offset (0=none)    *  	       *  Return value:    *  	   nothing    ********************************************************************* */LEAF(bcm1480_altcpu_start2)	/*	 * Do this for all secondary CPUs (if any)	 */		GET_NUM_CPUS(v0, t0)		b	2f	/*	 * Main loop, CPU number is in v0.	 */1:	/*	 * Let secondary CPU(s) run their idle loops.  Set the 	 * mailbox register to our relocation factor so we can read	 * it out of the mailbox register and relocate GP properly.	 */		la	t1,PHYS_TO_K1(A_BCM1480_IMR_REGISTER(0,R_BCM1480_IMR_MAILBOX_0_SET_CPU))		dli	t2,BCM1480_IMR_REGISTER_SPACING		or	t0,a0,1		# hack - make sure reloc is nonzero		multu	v0,t2		mflo	t2		daddu	t1,t1,t2		sd	t0,0(t1)	# Write to mailbox register2:		daddiu	v0,v0,-1		bne	v0,zero,1b		# Keep going if more secondary CPUs		j	ra	END(bcm1480_altcpu_start2)/*  *********************************************************************    *  BCM1480_ALTCPU_KILL    *      *  Kill a secondary CPU, causing it to return to the idle    *  loop.  We do this by switching to uncached mode,     *  asserting RESET on the other CPU, and then re-run    *  ALTCPU_START again.    *      *  Input parameters:     *  	   a0 - cpu number to stop    *  	       *  Return value:    *  	   nothing    ********************************************************************* */LEAF(bcm1480_altcpu_kill)_bcm1480_altcpu_kill:	/*	 * Don't do this if we have only one CPU. 	 */		GET_NUM_CPUS(t0, t1)		bgt	t0,1,1f			# Keep going if more than one CPU		j	ra			# Go back home, nothing to do1:	/*	 * More than one CPU, go ahead...	 */		move	t7,ra			# save RA, we'll make calls	#	# Stop CPU[a0], where a0 is the cpu number.	#		move	t0,a0			# t0 = cpu #		sll	t0,t0,5			# index by cache lines		la	t1,cpu_idledata		# 		add	t1,t0			# point at cpu[a0]'s data		SR	zero,R_CPU_STARTVECT(t1)  # Reset address of CPU1	#	# Flush the D cache to ensure that the write above made it 	# out of our L1.	#		JAL(bcm1480_l1cache_flush_d)	# uses t0, t2, t3	#	# Switch to KSEG1 to quiesce our cache activity.	#		bal	_altcpu_kseg1_switch	# switch to uncached mode	#	# Force CPU into reset (cpu number should still be in a0)	#		li	t2,PHYS_TO_K1(A_SCD_SYSTEM_CFG)		ld	t0,0(t2)		dli	t1,M_BCM1480_SYS_CPU_RESET_0	# Base Reset mask		dsll	t1,t1,a0		# Shift by processor number		or	t0,t1			# New value to write		sd	t0,0(t2)		# CPUn is now in reset	#	# Not sure how long we're supposed to wait.	#		ssnop		ssnop		ssnop		ssnop	#	# Now restart CPUn.  We can't use "altcpu_start1" here because	# we're probably restarting only one of 'n' cpus.	#	/*	 * Clear out our mailbox registers (both CPUs we're interested in)	 */		la	t2,PHYS_TO_K1(A_BCM1480_IMR_REGISTER(0,R_BCM1480_IMR_MAILBOX_0_CLR_CPU))		dli	t0,-1			# clear all 64 bits		dli	t1,BCM1480_IMR_REGISTER_SPACING		sd	t0,(t2)			# do CPU0 		multu	a0,t1

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -