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

📄 start.s

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 S
📖 第 1 页 / 共 3 页
字号:
/*	$Id: start.S,v 1.9 2003/08/10 11:11:31 pefo Exp $ *//* * Copyright (c) 2002 Momentum Computer  (www.momenco.com) * Copyright (c) 2001 Opsycon AB  (www.opsycon.se) *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by Opsycon AB, Sweden. * 4. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * 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) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */#ifndef _KERNEL#define _KERNEL#endif#include <asm.h>#include <regnum.h>#include <cpu.h>#include <pte.h>#include <machine/rm9k.h>#include "target/jaguar_atx.h"#include "target/fpga.h" #include "pmon/dev/ns16550.h"#include "pmon/dev/mv64340reg.h"#ifdef DEBUG_LOCORE#define	TTYDBG(x) \	.rdata;98: .asciz x; .text; la a0, 98b; bal stringserial; nop#define TTYDBGHEX(x) \	bal hexserial; move a0, x#else#define TTYDBG(x)#define TTYDBGHEX(x)#endif#define	PRINTSTR(x) \	.rdata;98: .asciz x; .text; la a0, 98b; bal stringserial; nop#define GTINIT(offset, value) \	.word	GT_BASE_ADDR+(offset), HTOLE32(value)#define RM9K_INIT(offset, value) \	.word	RM9K_BASE_ADDR+(offset), value/* *   Register usage: * *	s0	link versus load offset, used to relocate absolute adresses. *	s2	base address to Galileo chip. *	s4	RM9000 memory size passed to init *	s5	GT64260 memory size passed to init */	.set	mips64	.set	noreorder	.globl	_start	.globl	start	.globl	__mainstack = .		/* Place PMON stack below PMON start in RAM */_start:start:/* NOTE!! Not more that 16 instructions here!!! Right now it's FULL! */	mtc0	zero, COP_0_STATUS_REG	mtc0	zero, COP_0_CAUSE_REG	li	t0, SR_BOOT_EXC_VEC	/* Exception to Boostrap Location */	mtc0	t0, COP_0_STATUS_REG	la	gp, _gp	bal	uncached		/* Switch to uncached address space */	nop	bal	locate			/* Get current execute address */	nopuncached:	or	ra, UNCACHED_MEMORY_ADDR	j	ra	nop/* *  Reboot vector usable from outside pmon. */	.align	8ext_map_and_reboot:	bal	CPU_TLBClear	nop	li	a0, 0xc0000000	li	a1, 0x40000000	bal	CPU_TLBInit	nop	la	v0, tgt_reboot	la	v1, start	subu	v0, v1	lui	v1, 0xffc0	addu	v0, v1	jr	v0	nop/* *  Exception vectors here for rom, before we are up and running. Catch *  whatever comes up before we have a fully fledged exception handler. */	.align	9			/* bfc00200 */	la	a0, v200_msg	bal	stringserial	nop	b	exc_common	.align	7			/* bfc00280 */	la	a0, v280_msg	bal	stringserial	nop	b	exc_common/* Cache error */	.align	8			/* bfc00300 */	PRINTSTR("\r\nPANIC! Unexpected Cache Error exception! ")	mfc0	a0, COP_0_CACHE_ERR	bal	hexserial	nop	b	exc_common/* General exception */	.align	7			/* bfc00380 */	la	a0, v380_msg	bal	stringserial	nop	b	exc_common	.align	8			/* bfc00400 */	la	a0, v400_msg	bal	stringserial	nopexc_common:	PRINTSTR("\r\nERRORPC=")	mfc0	a0, COP_0_ERROR_PC	bal	hexserial	nop	PRINTSTR("\r\nEPC=")	mfc0	a0, COP_0_EXC_PC	bal	hexserial	nop	PRINTSTR("\r\nDERR0=")	cfc0	a0, COP_0_DERR_0	bal	hexserial	nop	PRINTSTR("\r\nDERR1=")	cfc0	a0, COP_0_DERR_1	bal	hexserial	nop	b	ext_map_and_reboot	nop/* *  We get here from executing a bal to get the PC value of the current execute *  location into ra. Check to see if we run from ROM or if this is ramloaded. */locate:	la	s0, start		/* RA set from BAL above! */	subu	s0, ra, s0		/* s0 is now load vs. link offset */	and	s0, 0xffff0000		/* Mask off lower bits *//* Who are we? If not CPU 0 skip init */	mfc0	v0, COP_0_PRID	srl	v0, 24	andi	v0, 0x07	bnez	v0, start_other_cpu	nop/* NOTE: This works because LKM6 defaults to 0x1fc0_0000, and the 'size' is * really just a mask.  So when we increase the mask, we really (technically) * don't need to touch the base address. */	la	s2, RM9K_BASE_ADDR	li	v0, 0xffffffff	sw	v0, RM9K_SEMCLR(s2)	/* Clear semaphore register */	/* set LKM6 for 8MByte */	li	t0, 0x0007ff00	sw	t0, 0x134(s2)	lw	t0, 0x134(s2)	sync	/* set LKB6 for 0x1f80_0000 base */	li	t0, 0x01f80001	sw	t0, 0x130(s2)	lw	t0, 0x130(s2)	sync/* * We set LKM/B 5 to show the GT-64340 internal registers before we move them. */	/* set LKM5 for 64KByte */	li	t0, 0x00000f00	sw	t0, 0x12c(s2)	lw	t0, 0x12c(s2)	sync	/* set LKB5 for 0x1400_0000 base */	li	t0, 0x01400001	sw	t0, 0x128(s2)	lw	t0, 0x128(s2)	sync/* *  Turn off all high decoders to avoid address conflicts. */	la	s2, GT_BASE_ADDR_DEFAULT	li	t0, HTOLE32(0x0007fe0e)	sw	t0, CPU_BASE_ADDRESS_ENABLE(s2)/* *  Relocate the Galileo to HIGH memory. */	li	t0, HTOLE32((GT_BASE_ADDR >> 16) | 0x01000000)	sw	t0, INTERNAL_SPACE_BASE(s2)	li	t0, 0x100		/* Need a small delay here */1:	bnez	t0, 1b	addiu	t0, -1/* *  Reset the TLB to map upper Gigabyte of memory space. */	bal	CPU_TLBClear	nop	li	a0, 0xc0000000	li	a1, 0x40000000	bal	CPU_TLBInit	nop/* * Set LKM/B 5 to map entire GT-64340 I/O space at 0xc0000000 - 0xffffffff * This will also map in the GT-64340 at its new location. */	la	s2, RM9K_BASE_ADDR	/* set LKB5 for 0xc000_0000 base */	li	t0, 0x0c000001	sw	t0, 0x128(s2)	lw	t0, 0x128(s2)	sync	/* set LKM5 for 1GByte */	li	t0, 0x03ffff00	sw	t0, 0x12c(s2)	lw	t0, 0x12c(s2)	sync	la	s2, GT_BASE_ADDR	/* From now this is the GT base */	/* Assume 150 MHz timing */	bal	tgt_setpar150mhz	nop	lw	t0, CPU_CONFIG(s2)	/* Turn off  automatic retries */	li	t1, HTOLE32(0x00020000)		or	t0, t0, t1	sw	t0, CPU_CONFIG(s2)/* *  Set up I/O decoders to point correctly. */	bal	2f	/* Load address to init table */	nop	GTINIT(CS_0_BASE_ADDRESS, FPGA_BASE >> 16)	GTINIT(CS_0_SIZE, (FPGA_SIZE - 1) >> 16)	GTINIT(CS_1_BASE_ADDRESS, RTC_BASE >> 16)	GTINIT(CS_1_SIZE, (RTC_SIZE - 1) >> 16)	GTINIT(CS_2_BASE_ADDRESS, UART_BASE >> 16)	GTINIT(CS_2_SIZE, (UART_SIZE - 1) >> 16)	GTINIT(CS_3_BASE_ADDRESS, FLASH_BASE >> 16)	GTINIT(CS_3_SIZE, (FLASH_SIZE - 1) >> 16)	GTINIT(INTERNAL_SRAM_BASE, OC_SRAM_BASE >> 16)	/* Serial ports in MV64340 */	GTINIT(MAIN_ROUTING_REGISTER, 0x00000038)	/* Route both UARTS */	GTINIT(RECEIVE_CLOCK_ROUTING_REGISTER, 0)	GTINIT(TRANSMIT_CLOCK_ROUTING_REGISTER, 0)	GTINIT(MPP_CONTROL1, 0x00002222)#define GTBAUD ((GTSYSCLK / (32 * CONS_BAUD) / 2) - 1)	GTINIT(BRG0_CFG_REG, 0x00210000 + GTBAUD)#undef GTBAUD	GTINIT(BRG0_BAUD_TUNING_REG, 0x0)	GTINIT(MPSC0_MAIN_CONFIGURATION_LOW, 0x04c4)	GTINIT(MPSC0_MAIN_CONFIGURATION_HIGH, 0x06400600)	GTINIT(MPSC0_PROTOCOL_CONFIGURATION, 0x00003000)	GTINIT(CHANNEL0_COMMAND_REGISTER, 0x00008000)	GTINIT(CHANNEL0_REGISTER4, 0x20000000)	GTINIT(CHANNEL0_REGISTER5, 0x00009000)	/* GPP for seven seg LED */	GTINIT(GPP_IO_CONTROL, 0xff000000)	GTINIT(GPP_LEVEL_CONTROL, 0xff000000)	GTINIT(GPP_VALUE, 0x80000000)	/* end mark */	.word	0, 01:	sw	v1, 0(v0)2:	lw	v0, 0(ra)		/* Address */	lw	v1, 4(ra)		/* Data */	bnez	v0, 1b	addiu	ra, 8/* *  Init serial I/O for diagnostic output. */	bal	initserial	nop	PRINTSTR("\r\nPMON2000 MIPS Initializing. Standby...\r\n")	PRINTSTR("EXCEPTIONPC=")	mfc0	a0, COP_0_EXC_PC	bal	hexserial	nop	PRINTSTR(" CONFIG=")	mfc0	a0, COP_0_CONFIG	bal	hexserial	nop	PRINTSTR(" STATUS=")	mfc0	a0, COP_0_STATUS_REG	bal	hexserial	nop	PRINTSTR("\r\n")	la	s0, start		/* RA set from BAL above! */	subu	s0, ra, s0		/* s0 is now load vs. link offset */	and	s0, 0xffff0000		/* Mask off lower bits *//* *  Map RM9K on chip packet buffer and init it. */	la	v1, RM9K_BASE_ADDR	li	v0, ((PKT_SRAM_SIZE-1) >> 4) & ~0xff	sw	v0, 0x16c(v1)	li	v0, (PKT_SRAM_BASE >> 4) | 1	sw	v0, 0x168(v1)	la	v0, PHYS_TO_UNCACHED(PKT_SRAM_BASE)	addu	v1, v0, PKT_SRAM_SIZE1:	addiu	v0, 8	bne	v0, v1, 1b	sd	zero, -8(v0)#if defined(SMP)/* *  Now we need to release the second core so it can enter *  a safe state waiting in the holding area until we have *  initialized the rest of the system. First check that *  core 2 is enabled to run. */	la	v0, RM9K_BASE_ADDR	lw	v1, RM9K_CONF128(v0)	and	v1, (1 << (155-128))	bnez	v1, 3f	nop1:	bal	release_core2	nop	beqz	v0, 2f	nop	PRINTSTR("Core 2 in holding location\r\n")	b	3f	nop2:	PRINTSTR("Core 2 no show!\r\n")3:#endif/* * Now to the hairy part. We have only TWO SysAD regions and * we need one to map I/O and one to map RAM memory. Thus we * need to free up LK6 by remapping the boot rom. However * that can't be done while executing from it. So we copy * the code to do that to the RM9K on-chip ram and execute * it there. We must remember to adjust the return address and * the load vs link offset in s0. */	TTYDBG("Remapping BOOT\r\n")	bal	1f	ori	v1, zero, ocramcodeend-ocramcode	/* This code is copied to RM9K on chip ram and executed there */ocramcode:	li	v0, HTOLE32(BOOT_BASE >> 16)	sw	v0, BOOTCS_BASE_ADDRESS(s2)	li	v0, HTOLE32((BOOT_SIZE - 1) >> 16)	sw	v0, BOOTCS_SIZE(s2)	lw	v0, BOOTCS_SIZE(s2)	/* IOSYNC */	li	v0, BOOT_BASE - 0xbfc00000	addu	s0, v0	li	v0, BOOT_BASE	or	ra, v0	jr	ra	nopocramcodeend:1:	la	v0, PHYS_TO_UNCACHED(PKT_SRAM_BASE)+0x4002:	lw	t0, (ra)	sw	t0, (v0)	addiu	ra, 4	addiu	v1, -4	bnez	v1, 2b	addiu	v0, 4	la	v0, PHYS_TO_UNCACHED(PKT_SRAM_BASE)+0x400	jalr	v0			/* Execute remapping in packet ram */	nop/* *  Initialize SDRAM controllers. * *  We have two SDRAM controllers, one on the RM9000 itself and *  one on the GT64340. Depending on the "user jumper" setting we *  either place the RM9000 modules or the GT64340 modules first. */	TTYDBG("Setting up SDRAM controllers\r\n")	li	s4, 0			/* Clear memory sizes */	li	s5, 0	bal	boot_i2c_init		/* Init SPD read interface */	nop/* *  Dig the memory modules for information. *  RM9K has module address 0 and 1, MV64340 has 3 and 4. */		/*	 * Check for user jumper -- if not present, normal setup.	 * Otherwise, swap the order of memory, Marvel @ 0x0.	 */	la	v0, FPGA_BASE_ADDR	lb	t0, BOARD_STAT(v0)	and	t0, BOARD_USER	beqz	t0, sdram_normal	nop	TTYDBG("SDRAM: Inverse module order\r\n")	bal	init_mv64340_sdram	nop	bal	init_gemini_sdram	nop	b	mem_done	nopsdram_normal:	bal	init_gemini_sdram	nop	bal	init_mv64340_sdram	nop/* *  Clear out 1Mb of memory (maximum cache size * 4) */mem_done:	TTYDBG("SDRAM Memory setup done.\r\n")	li	v0, 0xb0000000		/* ra is set from previous bal */	bgtu	v0, ra, in_ram		/* if pc is lower than rom space.. */	nop	TTYDBG("Clearing cache size memory...\r\n")	la	t0, 0xa0000000	addu	t1, t0, 1*1024*10241:	addu	t0, 8	bne	t1, t0, 1b	sd	zero, -8(t0)	TTYDBG("Init SDRAM Done!\r\n")in_ram:	TTYDBG("Initializing caches...\r\n")	bal	init_caches	nop#ifdef DEBUG_LOCORE	TTYDBG("Init caches done, cfg = ")	mfc0	a0, COP_0_CONFIG	bal	hexserial	nop	TTYDBG("\r\n")#endif/* *  At this point all memory controller setup should have been done *  and we should be able to function 'normally' and C code can be *  used freely from this point. */	TTYDBG("Copy PMON to execute location...\r\n")	la	sp, stack-2048	la	a1, start	/* RAM start address */	la	v0, copytoram	addu	v0, s0		/* Compute ROM address of 'copytoram' */	jal	v0	add	a0, a1, s0	/* ROM start address */	beqz	v0, 1f	nop	move	s3, v0	PRINTSTR("\r\nPANIC! Copy to memory failed at 0x")	move	a0, s3	bal	hexserial	nop	PRINTSTR(".\r\n")	b	stuck	nop1:	TTYDBG("Copy PMON to execute location done.\r\n")	sw	zero, CpuTertiaryCacheSize /* Set L3 cache size to zero */	la	v0, initmips	move	a1, s5		/* Arg 2 is Galileo mem size */	jalr	v0	move	a0, s4		/* Arg 1 is RM9000 memory size *//*-------------------------------------------------------------------- *        SMP stuff */LEAF(release_core2)	la	v0, RM9K_BASE_ADDR	lw	v1, 0x0f0(v0)	ori	v1, 0x01	sw	v1, 0x0f0(v0)	li	v1, 0x02	sw	v1, 0x0a28(v0)	li	a0, 100001:	lw	v1, RM9K_SEM(v0)	bltz	v1, 2f	addiu	a0, -1	bnez	a0, 1b	nop2:	jr	ra	move	v0, a0		/* a0 = zero if timed out */END(release_core2)/* *  Init code used by core 2. */start_other_cpu:	la	sp, stack-16384-2048	bal	CPU_TLBClear	nop	li	a0, 0xc0000000	li	a1, 0x40000000	bal	CPU_TLBInit	nop	la	v0, GT_BASE_ADDR+GPP_VALUE	li	v1, 0x5c	sw	v1, 0(v0)/* Move out 'holding location' code to packet sram */	bal	1f	ori	v1, zero, holdingcodesz-holdingcode	/* This code is copied to RM9K on chip ram and executed there */holdingcode:	la	s2, RM9K_BASE_ADDR	li	v0, 0x80000000	sw	v0, RM9K_SEMSET(s2)	/* Set 'in holding' semaphore */holdwait:	lw	v1, RM9K_SEM(s2)	/* Wait for 'release' from core 1 */	and	v1, v0	bnez	v1, holdwait	nop	la	v0, GT_BASE_ADDR+GPP_VALUE	li	v1, 0x50	sw	v1, 0(v0)	jr	ra	nopholdingcodesz:1:	la	v0, PHYS_TO_UNCACHED(PKT_SRAM_BASE)2:	lw	t0, (ra)	sw	t0, (v0)	addiu	v1, -4	addiu	v0, 4	bgtz	v1, 2b	addiu	ra, 4

⌨️ 快捷键说明

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