/* $NetBSD: start.S,v 1.3 2005/12/11 12:17:34 christos Exp $ */
/*
* Copyright (c) 2003 Naoto Shimazaki.
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY NAOTO SHIMAZAKI AND CONTRIBUTORS ``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 NAOTO OR CONTRIBUTORS 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.
*/
/*
* NOTE:
* This code assumes some trick described below:
*
* - Located at 0x80000000 by linker
* - Placed at 0xbfc00000 (by ROM writer)
* - Executed at 0xbfc00000 by CPU
*
* So,
*
* - You cannot use 'j' and 'jal'. Instead, you must use 'b'.
* - If you want to jump to absolute address, you must load
* the target address to a register and jump to it with
* 'jr' or 'jalr'.
* - You never be able to write any memory before
* the bus configuration completed.
*
*/
#include <sys/cdefs.h>
#include <sys/errno.h>
#include <sys/syscall.h>
#include <machine/param.h>
#include <mips/asm.h>
#include <mips/cpuregs.h>
#include <mips/trap.h>
#include "extern.h"
.text
.set noreorder
.align 2
/*
* macro ROMICE - support for Kyoto-micro's PARTNER-ETII ROM-ICE
*
* PARTNER-ETII by Kyoto-microcomputer is a ROM based emulater.
* This ICE initializes by itself the very early configurations of
* the target CPU. This macro skips that configurations.
*/
#ifndef ROMICE
/*
* exception vector table
*/
.org 0x0000
reset_vector:
b start /* MUST relative jump */
nop
.org 0x0200
tlb_vector:
b start
nop
.org 0x0280
xtlb_vector:
b start
nop
.org 0x0380
exception_vector:
b start
nop
#endif
.org 0x1000
.globl start
start:
#ifndef ROMICE
/*
* setup CP0 CONFIG
* EP = 0, AD = 0, K0 = 2
*/
li t1, 0x00125482
mtc0 t1, $16
/*
* setup CP0 STATUS
* CU0 = 0, RE = 0, DS:BEV = 0, IM = 0, KX = SX = UX = 0,
* KSU = 0, IE = 0, others = untouch
*/
mfc0 t1, $12
li t2, 0x00770006
and t1, t1, t2
li t2, 0x00400000
or t1, t1, t2
mtc0 t1, $12
mtc0 zero, $18 /* CP0 Watch Lo */
mtc0 zero, $11 /* CP0 compare */
/*
* setup LED
*/
li t0, 0xab000248 /* LEDCNTREG */
li t1, 0x0001
sh t1, (t0)
/*
* reset HALTimer
*/
li t0, 0xab0000a2
li t1, 0x0004
sh t1, (t0)
/*
* initialize VR4181 bus controller
*/
/*
* setup BCUCNTREG1
* ROMs = 10 (64Mbit), ROMWEN0 = 1, Rtype = 01 (flash)
* RSTOUT = 1 (inactive)
*/
li t0, 0xaa000000 /* BCUCNTREG1 */
li t1, 0x8013
sh t1, (t0)
/*
* setup BCURFCNTREG
* BRF = refresh cycle x 1/TClock
* = 30.52usec x 32.768MHz
* = 0x3e8 (1000 TClock)
*/
li t0, 0xaa000010 /* BCURFCNTREG */
li t1, 0x03e8
sh t1, (t0)
/*
* setup BCUSPEEDREG
* WPROM = 111 = 8.5TClock = 259ns
* WROMA = 1000 = 9.5TClock = 290ns
*/
li t0, 0xaa00000c /* BCUSPEEDREG */
li t1, 0x7008
sh t1, (t0)
/*
* setup SDTIMINGREG
* BIT8 = 1 (always 1)
* TRAS = 01 = 5SDCLK (forced under 66, 50, 33MHz bus clock)
* TRC = 01 = 7SDCLK (forced under 66, 50, 33MHz bus clock)
* TRP = 10 = 3SDCLK (forced under 66, 50, 33MHz bus clock)
* TRCP = 01 = 2SDCLK (forced under 66, 50, 33MHz bus clock)
*/
li t0, 0xaa00030c /* SDTIMINGREG */
li t1, 0x0159
sh t1, (t0)
/*
* To initialize 64Mbit SDRAM properly, we have to take
* following steps:
*
* 1. set MEMCFG_REG for 16Mbit SDRAM
* 2. setup MODE_REG
* 3. init SDRAM (setting MEMCFG_REG:Init to 1)
* 4. set MEMCFG_REG for 64Mbit SDRAM
*
* confirm to VR4181 users manual 6.5.2 MEMCFG_REG (page 142).
* (the page number is for Japanese edition. it might be
* at another page number for the English edition.)
*/
/*
* first, say MEMCFG_REG that SDRAM is 16Mbit
* Init = 0
* B1Config = 01 (16Mbit)
* Bstreftype = 1 (all raw refresh)
* BstRefr = 0 (not allow burst refresh)
* EDOAsym = 0 (asymetric)
* B0Config = 01 (16Mbit)
* EDO/SDRAM = 1 (SDRAM)
*/
li t0, 0xaa000304 /* MEMCFG_REG <- 503 (16Mbit) */
li t1, 0x0503
sh t1, (t0)
/*
* second, setup MODE_REG
* Bit11 = 0 (always 0)
* Bit10 = 0 (always 0)
* BR-SW = 0 (always 0)
* TE-Ven = 00 (always 00)
* LTMode = 011 (3clock CAS latency)
* WT = 0 (always 0)
* BL = 111 (always 111)
*/
li t0, 0xaa000308 /* MODE_REG */
li t1, 0x0037
sh t1, (t0)
/*
* third, kick SDRAM initialization
* Init = 1
* other = untouched
*/
li t0, 0xaa000304 /* MEMCFG_REG:Init <- 1 */
li t1, 0x8503
sh t1, (t0)
/*
* final, say MEMCFG_REG that SDRAM is 16Mbit
* Init = 0
* B1Config = 10 (64Mbit)
* Bstreftype = 1 (all raw refresh)
* BstRefr = 0 (not allow burst refresh)
* EDOAsym = 0 (asymetric)
* B0Config = 10 (64Mbit)
* EDO/SDRAM = 1 (SDRAM)
*/
li t0, 0xaa000304 /* MEMCFG_REG */
li t1, 0x0905
sh t1, (t0)
/*
* setup XISACTL
* EXTRESULT = 1 (1 is recommended)
* INTRESULT = 0 (0 is recommended)
* EXBUFEN = 0 (use SYSDIR and SYSEN)
* MEMWS = 00 (1.5 SYSCLK)
* IOWS = 10 (2.5 SYSCLK)
* SCLKDIV = 10 (PCLK/6)
*/
li t0, 0xab0002c4 /* XISACTL */
li t1, 0x0422
sh t1, (t0)
nop
/*
* enable cache
*/
mfc0 t0, $16
li t1, 0xfffffff8
and t0, t0, t1
or t0, t0, 0x00000003 /* K0 = 3 */
mtc0 t0, $16 /* config */
nop
nop
nop
/*
* initialize cache
*/
mtc0 zero, $28 /* TagLo */
lui t0, 0x8000 /* vaddr */
ori t1, zero, 0x1000 /* cache size = 4KB */
cache_clear:
.set push
.set mips3
cache 0x00, (t0) /* Index_Invalidate */
cache 0x09, (t0) /* Index_Store_Tag */
.set pop
addiu t1, t1, -0x10
bgtz t1, cache_clear
addiu t0, t0, 0x10 /* increment of line size */
/* LED3 ON */
li t0, 0xab000306
li t1, 0x0800
sh t1, (t0)
li t0, 0xab000308
sh zero, (t0)
nop
/* LED3 ON */
/*
* now early bus configuration is done.
*/
/*
* copy bootloader ROM to RAM
*/
li t1, LCBOOT_ROMSTARTADDR
la t2, start
la t3, edata
1:
lw t0, (t1)
nop
sw t0, (t2)
addu t2, t2, 4
sltu t0, t2, t3
.set push
.set noreorder
.set nomacro
bne t0, zero, 1b
addu t1, t1, 4
.set pop
/* verify */
li t1, LCBOOT_ROMSTARTADDR
la t2, start
la t3, edata
1:
lw t0, (t1)
lw t4, (t2)
addu t2, t2, 4
bne t0, t4, 2f
sltu t0, t2, t3
.set push
.set noreorder
.set nomacro
bne t0, zero, 1b
addu t1, t1, 4
.set pop
b 4f
nop
2:
/* panic. stop LED */
li t0, 0xab000248 /* LEDCNTREG */
sh zero, (t0)
3:
b 3b
nop
4:
/* verify done */
/* LED4 ON */
li t0, 0xab000306
li t1, 0x8800
sh t1, (t0)
li t0, 0xab000308
sh zero, (t0)
/* LED4 ON */
/*
* now we've got a working RAM with cache.
*/
#else /* !ROMICE */
/*
* enable cache
*/
mfc0 t0, $16
li t1, 0xfffffff8
and t0, t0, t1
or t0, t0, 0x00000003 /* K0 = 3 */
mtc0 t0, $16 /* config */
nop
nop
nop
#endif /* !ROMICE */
/*
* zero the bss
*/
la t1, edata
la t2, end
sw zero, (t1)
1:
addu t1, t1, 4
.set push
.set mips3
.set noreorder
.set nomacro
sltu t0, t1, t2
bnel t0, zero, 1b
sw zero, (t1) /* delay slot */
.set pop
#ifdef DEBUG_LED
/* LED5 ON */
li t0, 0xab000302
li t1, 0x0002
sh t1, (t0)
li t0, 0xab00030a
sh zero, (t0)
/* LED5 ON */
#endif
#ifdef DEBUG_LED
/* LED6 ON */
li t0, 0xab000300
li t1, 0x0020
sh t1, (t0)
li t0, 0xab00030a
sh zero, (t0)
/* LED6 ON */
#endif
/*
* call lcboot main()
*/
move a0, zero /* a0: argc = 0 */
move a1, zero /* a1 */
move a2, zero /* a2 */
move a3, zero /* a3 */
move k0, zero /* k0 */
move k1, zero /* k1 */
la gp, _C_LABEL(_gp) /* global pointer */
la sp, start /* stack pointer */
la v0, main
jalr v0
nop
.globl start_netbsd
start_netbsd:
/*
* all LED OFF
*/
li t0, 0xab000248 /* LEDCNTREG */
sh zero, (t0)
li t1, 0xffff
li t0, 0xab000308
sh t1, (t0)
li t0, 0xab00030a
sh t1, (t0)
/*
* initialize registers
*/
li a0, 1 /* a0: argc = 1 */
la a1, argv0 /* a1: argv */
la a2, bootinfo /* a2: bootinfo */
move a3, zero /* a3 */
move k0, zero /* k0 */
move k1, zero /* k1 */
/* no need to set grobal pointer. it set in locore.S */
la sp, NETBSD_STARTADDR /* stack pointer */
/*
* call netbsd
*/
jr sp
nop
/*
* arguments for mach_init()
*/
.data
argv0:
.word argv0c
argv1:
.word 0
argv0c:
.asciiz "netbsd"
bootinfo:
.half 34 /* length */
.half 0 /* reserved */
.word 0x13536135 /* magic */
.word 0 /* fb_addr */
.half 0 /* fb_line_bytes */
.half 0 /* fb_width */
.half 0 /* fb_height */
.half 0 /* fb_type */
.half 2 /* BI_CNUSE_SERIAL */
.half 0 /* padding */
.word 0x04104400 /* PLATID_CPU_MIPS_VR_4181 */
.word 0x03810100 /* PLATID_MACH_LASER5_L_CARD */
.word 0 /* GMT */
/*
* End of start.S
*/