📄 start.s
字号:
/* $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 + -