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

📄 bcm1480_altcpu.s

📁 一个很好的嵌入式linux平台下的bootloader
💻 S
📖 第 1 页 / 共 2 页
字号:
		mflo	t1		daddu	t2,t2,t1		sd	t0,(t2)			# do CPU[a0]	/*	 * Let the secondary CPU(s) out of reset	 * 	 * XXX This is very BCM1480-specific at the moment.	 */		la	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		not	t1			# clear this bit		and	t0,t1			# New value to write		sd	t0,0(t2)		# CPU[v0] is now running	/*	 * Wait for the other CPU to ring our doorbell	 */2:		la	t2,PHYS_TO_K1(A_BCM1480_IMR_REGISTER(0,R_BCM1480_IMR_MAILBOX_0_CPU));		ld	t0,(t2)			# Read mailbox		beq	t0,zero,2b		# Loop till the bit is set	/*	 * Clear the mailbox to dismiss the pending interrupts	 */		la	t2,PHYS_TO_K1(A_BCM1480_IMR_REGISTER(0,R_BCM1480_IMR_MAILBOX_0_CLR_CPU))		dli	t0,-1			# clear all 64 bits		sd	t0,(t2)	#	# It's safe to be cached again.	#		bal	_altcpu_kseg0_switch	#	# At this point, CPU1 is waiting for us to indicate that it's	# okay to use memory again.  Ring its doorbell.	#		la	t2,PHYS_TO_K1(A_BCM1480_IMR_REGISTER(0,R_BCM1480_IMR_MAILBOX_0_SET_CPU))		dli	t1,BCM1480_IMR_REGISTER_SPACING		multu	a0,t1		mflo	t1		daddu	t2,t2,t1		LR	t0,mem_datareloc		or	t0,1		sd	t0,(t2)	#	# CPU[a0] is back in our control.	#		move	ra,t7		move	v0,zero		j	raEND(bcm1480_altcpu_kill)/*  *********************************************************************    *  ALTCPU_RESET    *      *  Start address for secondary CPU(s) - do the initialization of    *  the local CPU and then notify CPU0 that we're done.    *    *  This routine is called in KSEG1.    *      *  Input parameters:     *  	   t0 - CPU identifier    *  	       *  Return value:    *  	   nothing    ********************************************************************* */LEAF(bcm1480_altcpu_reset)		GET_CUR_CPU(t0)			# read current cpu # to t0		beq	t0,zero,iscpu0		# go if on CPU0#if CFG_RELOC       /*        * SVR4 PIC mode: get a copy of GP for use in the boot ROM.	*/		lui	gp,%hi(_gp)		addiu	gp,%lo(_gp)		or	gp,gp,K1BASE#endif	/*	 * Note: we should never get to the CPU1 code if we're	 * with only one CPU.  Theoretically, nobody got past the	 * check in altcpu_start.  But, just in case, if we	 * get here and we're on CPU1, and we supposedly only	 * have one CPU, reset CPU1.	 */		GET_NUM_CPUS(t0, t1)		beq	t0,1,iscpu0		# If only one CPU, kill off CPU1	/*	 * Initialize CPU registers.	 */		JAL_KSEG1(sb1_cpu_init)		GET_CUR_CPU(t1)		SETLEDS1_ADD('C','P','U','0', t1)	/*	 * Initialize the L1 cache	 */#if CFG_INIT_L1		JAL_KSEG1(bcm1480_l1cache_init)#endif	/*	 * Notify the SCD that we're done initializing.  Do this by 	 * ringing CPU0's doorbell.	 */		la	a0,PHYS_TO_K1(A_BCM1480_IMR_REGISTER(0,R_BCM1480_IMR_MAILBOX_0_SET_CPU));		GET_CUR_CPU(t0)			# get our processor # to t0		li	t1,1			# make a bit mask depending on CPU		sll	t1,t1,t0		# calculate t1 = 1 shl cpu number		sd	t1,0(a0)		# set corresponding bit in mailbox	 /*	  * Go to the idle loop	  */		b	altcpu_idle		# go to idle loop		   	 /*	  * We get here if we were running on CPU0.  Make things	  * pretty for the reset of CPU initialization.	  */iscpu0:			/*	 * If we are on CPU0, then force secondary CPUs1 into reset.	 *  This is needed for the case where the firmware has crashed	 * and we need to get control of the system again.	 */		li	a0,PHYS_TO_K1(A_SCD_SYSTEM_CFG)		ld	t0,0(a0)		dli	t1,(M_BCM1480_SYS_CPU_RESET_1|M_BCM1480_SYS_CPU_RESET_2|M_BCM1480_SYS_CPU_RESET_3)		or	t0,t1			# New value to write		sd	t0,0(a0)		# secondary CPUs are now in reset		j	ra			# return (we were on CPU 0)END(bcm1480_altcpu_reset)/*  *********************************************************************    *  ALTCPU_CMD_START(cpu,addr)    *      *  Start an alternate CPU.    *      *  Input parameters:     *  	   a0 - cpu number (must be 1-3 for the BCM1480)    *  	   a1 - pointer to start parameters (four 64-bit values)    *             array[0] = start address (PC)    *             array[1] = start stack pointer (SP)    *             array[2] = start global pointer (GP)    *             array[3] = start user argument (A1)    *  	       *  Return value:    *  	   v0 - 0 if ok    *  	   else -1 if request could not be handled    ********************************************************************* */#define R_CPUSTART_PCVAL  0#define R_CPUSTART_SPVAL  8#define R_CPUSTART_GPVAL  16#define R_CPUSTART_A1VAL  24LEAF(altcpu_cmd_start)		li	v0,-1		/* assume failure */		beq	a0,0,2f		/* can't start CPU0 with this routine */	/*	 * Return an error if running in uniprocessor mode.	 */		GET_NUM_CPUS(t0, t1)		beq	t0,1,2f			# If only one CPU, error.	/*	 * Multiprocessor mode, start the other CPU	 */		move	t0,a0		/* get CPU number */		sll	t0,5		/* multiply by 5 for cache offset */		la	t1,cpu_idledata		add	t1,t0		/* t1 = desired CPU's idle data */		ld	t2,R_CPUSTART_GPVAL(a1)		SR	t2,R_CPU_GPVAL(t1)		ld	t2,R_CPUSTART_SPVAL(a1)		SR	t2,R_CPU_SPVAL(t1)		ld	t2,R_CPUSTART_A1VAL(a1)		SR	t2,R_CPU_ARG(t1)		ld	t2,R_CPUSTART_PCVAL(a1)	/* this one actually starts the CPU */		SR	t2,R_CPU_STARTVECT(t1)		move	v0,zero		/* success */		j	ra	/*	 * Error return - invalid cpu number	 */2:		li	v0,-1		j	raEND(altcpu_cmd_start)/*  *********************************************************************    *  ALTCPU_CMD_STOP(cpu)    *      *  Stop the specified CPU.    *      *  We don't really support this at the moment.    *      *  Input parameters:     *  	   a0 - cpu number    *  	       *  Return value:    *  	   v0 - 0 if ok, else error code    ********************************************************************* */LEAF(altcpu_cmd_stop)		beq	a0,zero,1f		# can't stop CPU0	/*	 * Return an error if running in uniprocessor mode.	 */		GET_NUM_CPUS(t0, t1)		# t0 = number of CPUs		beq	t0,1,1f			# If only one CPU, error.		bge	a0,t0,1f		# Range check CPU number	/*	 * Multiprocessor mode, stop the other CPU (a0 = cpu number)	 */		b	_bcm1480_altcpu_kill	/* kill the CPU */1:		li	v0,-1		j	raEND(altcpu_cmd_stop)/*  *********************************************************************    *  ALTCPU_IDLE    *      *  Loop forever waiting for someone to tell us where to go.    *      *  Input parameters:     *  	   nothing.    *  	       *  Return value:    *  	   nothing    ********************************************************************* */altcpu_idle:	#if CFG_RELOC		lui	gp,%hi(_gp)		addiu	gp,%lo(_gp)#endif		GET_CUR_CPU(t1)		SETLEDS1_ADD('c','p','u','0', t1)	/*	 * Now wait for CPU0 to ring *our* doorbell.  This is our signal that	 * it's safe to go to the idle loop.  Until CPU0 rings our	 * doorbell, we can't use memory or the cache (since other CPUs	 * caches may not be initted yet).	 * XXX Very BCM1480 specific here.	 */1:		la	a0,PHYS_TO_K1(A_BCM1480_IMR_REGISTER(0,R_BCM1480_IMR_MAILBOX_0_CPU))		GET_CUR_CPU(t0)		li	t1,BCM1480_IMR_REGISTER_SPACING		multu	t0,t1		mflo	t1		daddu	a0,a0,t1		ld	t0,(a0)			# Read mailbox		beq	t0,zero,1b		# Loop till the bit is set	/*	 * Switch to KSEG0 (cached)	 */		bal	_altcpu_kseg0_switch	/*	 * Clear all the bits in the mailbox register to dismiss the 	 * pending interrupt 	 */		daddiu	a0,a0,(R_BCM1480_IMR_MAILBOX_0_CLR_CPU-R_BCM1480_IMR_MAILBOX_0_CPU)		li	t1,-1		sd	t1,0(a0)	/*	 * We may need GP, especially in relocated version	 *	 * Yucky hack: The relocation factor was passed to us in	 * the mailbox register, which is conveniently in t0 right now.	 * (except the lower bit is set just in case the reloc was	 * zero, so clear that first).	 */		li	t1,1			# 1		not	t1			# FFFFFFFFE		and	t0,t1			# clear lower bit.#if (CFG_RELOC)	/* 	 * Now that we can talk to memory again, get the "text relocation"	 * and move the loop into DRAM.	 */__AltCpuGoRel:		la	t1,1f			# Get address of where to go		ADDU	gp,t0			# Relocate GP		ADDU	t1,t0			# Relocate address		jr	t1			# Go there.1:						# we will go "here" in the reloc world#else	 /*	  * non-PIC: Standard GP	  */		la	gp,_gp		ADD	gp,t0			# relocate GP.#endif	/*	 * Get our processor number, and calculate address of cpu's idle data	 */		GET_CUR_CPU(t0)			# processor number to t0		sll	t0,t0,5			# Multiply by 32 for cache offset		la	t1,cpu_idledata		# address of base of table		addu	t0,t1			# t0 = our cpu data	/*	 * Set up registers like we were launching a program.	 */		la	a2,cpu_apientry # A2 = firmware entry vector		move	a0,gp		# A0 = handle		li	a3,CFE_EPTSEAL  # A3 = entrypoint signature	/*	 * Read the start address from the CPU restart table	 * and jump to it.  For an idle CPU, the address in the	 * table below will be the zero, causing	 * the CPU to loop forever.  To start a secondary CPU,	 * just write an address in cpu_idledata[cpu_id].start_vector	 *	 * Warning: This kind of assumes that this code will 	 * live in cacheable space.  If it doesn't, it will	 * probably cause lots of unwanted bus traffic.	 */		li	s4,0loop_forever:	LR	t1,R_CPU_STARTVECT(t0)  # Load address of routine		beq	t1,zero,loop_forever		LR	a1,R_CPU_ARG(t0)	# Load user argument (A1)		LR	sp,R_CPU_SPVAL(t0)	# Load stack pointer		LR	t2,R_CPU_GPVAL(t0)	# Load global pointer		move	gp,t2			# and put in real register		j	t1			# jump to start address/*  *********************************************************************    *  End    ********************************************************************* */

⌨️ 快捷键说明

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