#ifndef _KERNEL
#define _KERNEL
#endif
#include <asm.h>
#include <regnum.h>
#include <cpu.h>
#include <pte.h>
#include "pmon/dev/ns16550.h"
#include "target/prid.h"
#include "target/sbd.h"
#include "target/hisense.h"
#include "huaya_uart.h"
#ifndef BOOT_FROM_EJTAG
#define BOOT_FROM_EJTAG
#endif
#undefine BOOT_FROM_EJTAG
#define DEBUG_LOCORE
#define __DEBUG_PRINT__ 1
#define __REMOVE_DEBUG_SERIAL__ 0
#define __DDR_DEBUG_PRINT__ 0
#ifdef DEBUG_LOCORE
#define TTYDBG(x) \
.rdata;98: .asciiz x; .text; la a0, 98b; bal stringserial; nop
#else
#define TTYDBG(x)
#endif
#define PRINTSTR(x)
// .rdata;98: .asciiz x; .text; la a0, 98b; bal stringserial; nop
#define NOP10 nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop
#ifdef DEVBD_LS232_SM502
#define GPIOLED_DIR 0xff
#define GPIO_OE_7_0 0x0
#define GPIO_OE_15_8 0x1
#define GPIO_OE_23_16 0x2
#define GPIO_OE_28_24 0x3
#define GPIO_OE GPIO_OE_7_0
#define GPIO_O_7_0 0x20
#define GPIO_O_15_8 0x21
#define GPIO_O_23_16 0x22
#define GPIO_O_28_24 0x2c
#define GPIO_O GPIO_O_7_0
#endif
#define tmpsize s1
#define msize s2
#define bonito s4
#define dbg s5
#define sdCfg s6
#define CP0_CONFIG $16
#define CP0_TAGLO $28
#define CP0_TAGHI $29
#define CPUConfig1 0xbf204000
#define CPUConfig2 0xbf204004
#define CPUConfig3 0xbf204008
#define CPUConfig4 0xbf200090 //thunder 20120228
/*
* Register usage:
*
* s0 link versus load offset, used to relocate absolute adresses.
* s1 free
* s2 memory size.
* s3 free.
* s4 Bonito base address.
* s5 dbg.
* s6 sdCfg.
* s7 rasave.
* s8 L3 Cache size.
*/
.set noreorder
.globl _start
.globl start
.globl __main
_start:
start:
.globl stack
stack = start - 0x8000 /*+ 0x20000000 thunder 20120830*/ /* Place PMON stack below PMON start in RAM */
/* 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 sp, stack
la gp, _gp
bal locate /* Get current execute address */
nop
uncached:
or ra, UNCACHED_MEMORY_ADDR
j ra
nop
/*
* Reboot vector usable from outside pmon.
*/
.align 9
ext_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
/* */
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 9 /* bfc00400 */
la a0, v400_msg
bal stringserial
nop
b exc_common
.align 7 /* bfc00480 */
la a0, v480_msg
bal stringserial
nop
b exc_common
.align 8 /* bfc00500 */
exc_common:
PRINTSTR("\r\nCAUSE=")
mfc0 a0, COP_0_CAUSE_REG
bal hexserial
nop
PRINTSTR("\r\nSTATUS=")
mfc0 a0, COP_0_STATUS_REG
bal hexserial
nop
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
.align 9
nop
.align 8
.word read
.word write
.word open
.word close
#if 0
.word nullfunction
.word nullfunction
.word nullfunction
.word nullfunction
#endif
.word nullfunction
.word printf
.word vsprintf
#if 0
.word nullfunction
.word nullfunction
#endif
.word nullfunction
.word nullfunction
.word getenv
// .word nullfunction
.word nullfunction
.word nullfunction
.word nullfunction
.word nullfunction
/*
* 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,uncached //把编译之后uncached这个符号的地址load给s0(应为一个0x8开的头的地址)
subu s0,ra,s0
// and s0,0xffffff00
beqz s0,skipddr
nop
/*
s0 是个比较重要的寄存器,定位代码的位置。
若代码在spiflash中,ra = 一个以0xbfc开头的地址,这样ra-s0得出的是代码在spiflash跟ddr之间的偏移量。
若s0 = 0,说明代码在内存里面执行,所以直接跳过PLL的初始化代码,因为PLL是不能重复初始化的。
若s0 !=0,说明代码是在spiflash里面执行,接着进行PLL的初始化操作。
*/
#include "1050/debug_Hynix_HS3K_H1PLL_1050_0515_v4-1_no-bprd_upd0522-test.S" //PLL初始化代码
/*
为了在下面DDR初始化的时候,打印字符进行调试,所以在这里提前把串口初始化好。这样
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x42//B
sw t1,UART_TX(t0)
#endif
这样的代码就能打印出一个B字符出来。
*/
skipddr:
bal initserial
nop
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x42//B
sw t1,UART_TX(t0)
#endif
/*
如果s0=0的话,说明代码是在DDR中运行,跳过下面DDR初始化的代码,因为DDR也是不能重复初始化的。
/*
beqz s0,skipddr1
nop
#include "1050/debug_Hynix_HS3K_H1MVDDR_1050_0515_v4-1_no-bprd_upd0522-test.S"
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x42//B
sw t1,UART_TX(t0)
#endif
/*
进行清TLB操作,把TLB 32项的寄存器都赋值为0.
/*
skipddr1:
bal CPU_TLBClear
nop
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x6F//o
sw t1,UART_TX(t0)
#endif
li t0,SR_BOOT_EXC_VEC
mtc0 t0,COP_0_STATUS_REG //初始化CP0 status寄存器。
mtc0 zero,COP_0_CAUSE_REG //初始化CPO CAUSE寄存器,写0.
.set noreorder //禁止乱序执行。
mfc0 a0, COP_0_ERROR_PC
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDRli
t1,0x6F//o
sw t1,UART_TX(t0)
#endif
PRINTSTR(" CONFIG=")
mfc0 a0, COP_0_CONFIG
PRINTSTR("\r\n")
PRINTSTR(" PRID=")
mfc0 a0, COP_0_PRIDbal
hexserialnopPRINTSTR(" s0=")
move a0, s0
bal hexserial
nop
PRINTSTR("\r\n")
/* * Now determine DRAM configuration and size by * reading the I2C EEROM on the DIMMS */
dmc_init:
PRINTSTR("Start initializing SDRAM(dmc init)...\n")
//#include "dmc_init.S"
PRINTSTR("Finish configurating the SDRAM's register...\n")
li msize,0x10000000 #for 256MB memory size
PRINTSTR("Init SDRAM Done!\n\n")
#define CF_7_SE (1 << 3) /* Secondary cache enable */
#define CF_7_SC (1 << 31) /* Secondary cache not present */
#define CF_7_TE (1 << 12) /* Tertiary cache enable */
#define CF_7_TC (1 << 17) /* Tertiary cache not present */
#define CF_7_TS (3 << 20) /* Tertiary cache size */
#define CF_7_TS_AL 20 /* Shift to align */
#define NOP8 nop;nop;nop;nop;nop;nop;nop;nop
do_caches:
PRINTSTR("Init caches...\r\n")
li s7, 0 /* no L2 cache */
li s8, 0 /* no L3 cache */
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x74//t
sw t1,UART_TX(t0)
#endifPRINTSTR("LS232 caches found...\r\n")
bal cache_init //进行cache init操作。
nop
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x69//i
sw t1,UART_TX(t0)
#endif
PRINTSTR("Init caches done, cfg = ")
mfc0 a0, COP_0_CONFIG
bal hexserial
nop
PRINTSTR("\r\n\r\nbootnow...")
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x6E//n
sw t1,UART_TX(t0)
#endif
/* Clear BSS */
la a0, _edata
la a2, _end
2: sw zero, 0(a0)
bne a2, a0, 2b
addu a0, 4
PRINTSTR("CLEAR_DOWN\r\n")
bootnow:
bnez s0,1f //s0 = 0, code in ddr; s0 != 0 ,code in spiflash.也就是说,如果代码在spiflash中的话,就会跳到1f,去运行拷贝代码;如果代码在ddr里面,那么会直接跳到copydone(拷贝完成),1f之后的copy代码就不再执行了。
nop
/*把cache打开*/
mfc0 a0,COP_0_CONFIG
and a0,a0,0xfffffff8
or a0,a0,0x3
mtc0 a0,COP_0_CONFIG
nop
b copydone
nop
1:
#define FCALL_PRINTSTR(x) \
.rdata;98: .asciz x; .text; la a0, 98b; la v0, stringserial; addu v0,s0;jalr v0; nop
#undef BAL
#define BAL(x) \
la v0,x; \
addu v0,s0; \
jalr v0; \
nop;
/*执行拷贝代码之前,要把cache关掉,以为不关的话,代码可能只拷贝在cache里面,没有真正写入ddr,这样再跳到0x80000000去执行的时候会出问题(reboot)*/
mfc0 a0,COP_0_CONFIG
and a0,a0,0xfffffff8
or a0,a0,0x2
mtc0 a0,COP_0_CONFIG
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x67//g
sw t1,UART_TX(t0)
#endif
/*copy copy program to sdram to make copy fast*/
/* Don't Copy! */
/*下面这段代码的作用是将121f-122f之间的代码,拷贝到ddr 0x80000000的位置,然后去ddr里执行,这样执行速度更快
121f 122f这写符号的地址是编译后代码里的地址,是以0x8开头的运行地址,所以要将其加上s0(spi相对ddr的偏移量)*/
la t0,121f // copy program start addr
addu t0,s0
la t1,122f // copy program end addr
addu t1,s0
li t2,0x80000000 // write copy program to 0x80000000
1:
lw v0,(t0)
sw v0,(t2)
addu t0,4
addu t2,4
ble t0,t1,1b
nop
#if __DEBUG_PRINT__
li t5,UART0_BASE_ADDR
li t6,0x20// space
sw t6,UART_TX(t5)
#endif
sync
nop
li t0,0x80000000
jr t0 // jump to 0x80000000 to execute the copy program
nop
.align 3
121:
#if __DEBUG_PRINT__
li t5,UART0_BASE_ADDR
li t6,0x50//P
sw t6,UART_TX(t5)
#endif
la a0, start // 0x81000 0000
addu a1,a0,s0
la a2, _edata // 0x81047010
subu t1, a2, a0
srl t1, t1, 2
#if __DEBUG_PRINT__
li t5,UART0_BASE_ADDR
li t6,0x4D//M
sw t6,UART_TX(t5)
#endif
move t0, a0 //t0保存start的地址
move t1, a1 //t1保存在start在spiflash里的地址。
move t2, a2 //t2保存_edata的地址,从ld.script里可以看出,_edata与start之间主要为代码段和数据段。
#if __DEBUG_PRINT__
li t5,UART0_BASE_ADDR
li t6,0x4F//O
sw t6,UART_TX(t5)
#endif
/* copy text section */
/*下面这段代码将程序的_edata与start之间的代码段和数据段拷贝到内存对应的位置*/
1: and t3,t0,0x0000ffff
bnez t3,2f
nop
move a0,t0
BAL(hexserial)
nop
li a0,'\r'
BAL(tgt_putchar)
nop
2: lw t3, 0(t1)
nop
sw t3, 0(t0)
addu t0, 4
addu t1, 4
bne t2, t0, 1b
nop
sync
#if __DEBUG_PRINT__
li t5,UART0_BASE_ADDR
li t6,0x4E//N
sw t6,UART_TX(t5)
#endif
/* Clear BSS */
la a0, _edata
la a2, _end
2: sw zero, 0(a0)
bne a2, a0, 2b
addu a0, 4
move a0, sp
BAL(hexserial)
nop
copydone:
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x2E//.
sw t1,UART_TX(t0)
#endif
/*下面这段代码用来刷4路cache*/
.set mips3
#ifndef WAYBIT
#define WAYBIT 12
#endif
#define WAY__(x) x
#define WAY_(x,y) WAY__((x<<y))
#define WAY(x) WAY_(x,WAYBIT)
li $5,0x80000000;
addu $6,$5,16384;
1:
cache 1, WAY(0)($5);
cache 1, WAY(1)($5);
cache 1, WAY(2)($5);
cache 1, WAY(3)($5);
cache 0, WAY(0)($5);
cache 0, WAY(1)($5);
cache 0, WAY(2)($5);
cache 0, WAY(3)($5);
add $5,$5,32;
bne $5,$6,1b;
nop
.set mips0
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x2E//.
sw t1,UART_TX(t0)
#endif
li a0, 0
sw a0, CpuTertiaryCacheSize /* Set L3 cache size */
move a0,msize //initmips的参数
srl a0,20
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x2E//.
sw t1,UART_TX(t0)
#endif
la v0, initmips //跳转到initmips.c的initmips函数开始执行c代码。initmips.c是用perl脚本,根据编译好的pmon elf文件生成的一个.c文件,
jalr v0
nop
.align 3
122:
/*
* get the status of cache
*/
LEAF(GET_CACHE_STATUS)
mfc0 v0,COP_0_CONFIG
andi v0,v0,0x3
nop
jr ra
END(GET_CACHE_STATUS)
LEAF(CACHE_ENABLE)
nop
mfc0 a0,COP_0_CONFIG
and a0,a0,0xfffffff8
or a0,a0,0x3
mtc0 a0,COP_0_CONFIG
nop
jr ra
nop
END(CACHE_ENABLE)
stuck:
b stuck
nop
/*
* Clear the TLB. Normally called from start.S.
*/
#if __mips64
#define MTC0 dmtc0
#else
#define MTC0 mtc0
#endif
LEAF(CPU_TLBClear)
li a3, 0 # First TLB index.
li a2, PG_SIZE_4K
MTC0 a2, COP_0_TLB_PG_MASK # Whatever...
1:
MTC0 zero, COP_0_TLB_HI # Clear entry high.
MTC0 zero, COP_0_TLB_LO0 # Clear entry low0.
MTC0 zero, COP_0_TLB_LO1 # Clear entry low1.
mtc0 a3, COP_0_TLB_INDEX # Set the index.
addiu a3, 1
li a2, 64
nop
nop
tlbwi # Write the TLB
bne a3, a2, 1b
nop
jr ra
nop
END(CPU_TLBClear)
/*
* Set up the TLB. Normally called from start.S.
*/
LEAF(CPU_TLBInit)
li a3, 0 # First TLB index.
li a2, PG_SIZE_16M
MTC0 a2, COP_0_TLB_PG_MASK # All pages are 16Mb.
1:
and a2, a0, PG_SVPN
MTC0 a2, COP_0_TLB_HI # Set up entry high.
move a2, a0
srl a2, a0, PG_SHIFT
and a2, a2, PG_FRAME
ori a2, PG_IOPAGE
MTC0 a2, COP_0_TLB_LO0 # Set up entry low0.
addu a2, (0x01000000 >> PG_SHIFT)
MTC0 a2, COP_0_TLB_LO1 # Set up entry low1.
mtc0 a3, COP_0_TLB_INDEX # Set the index.
addiu a3, 1
li a2, 0x02000000
subu a1, a2
nop
tlbwi # Write the TLB
bgtz a1, 1b
addu a0, a2 # Step address 32Mb.
jr ra
nop
END(CPU_TLBInit)
LEAF(stringserial)
#if __REMOVE_DEBUG_SERIAL__
move a2, ra
addu a1, a0, s0
// addiu a1,a0,0x0 // wyj 7-26
lbu a0, 0(a1)
1:
beqz a0, 2f
nop
bal tgt_putchar
addiu a1, 1
b 1b
lbu a0, 0(a1)
2:
j a2
nop
#endif
jr ra
nop
END(stringserial)
LEAF(outstring)
#if __REMOVE_DEBUG_SERIAL__
move a2, ra
move a1, a0
lbu a0, 0(a1)
1:
beqz a0, 2f
nop
bal tgt_putchar
addiu a1, 1
b 1b
lbu a0, 0(a1)
2:
j a2
nop
#endif
jr ra
nop
END(outstring)
LEAF(hexserial)
#if __REMOVE_DEBUG_SERIAL__
move a2, ra
move a1, a0
li a3, 7
1:
rol a0, a1, 4
move a1, a0
and a0, 0xf
la v0, hexchar
addu v0, s0
addu v0, a0
bal tgt_putchar
lbu a0, 0(v0)
bnez a3, 1b
addu a3, -1
j a2
nop
#endif
jr ra
nop
END(hexserial)
#if 1
LEAF(tgt_putchar)
#if __REMOVE_DEBUG_SERIAL__
li v0,UART0_BASE_ADDR
1:
lw v1,UART_LSR(v0)
and v1,UART_LSR_TX_EMPTY
beqz v1,1b
nop
andi a0,0xff
sw a0,UART_TX(v0)
j ra
nop
#endif
jr ra
nop
END(tgt_putchar)
#endif
LEAF(tgt_testchar) /* need to fix wyj*/
la v0,UART0_BASE_ADDR
1:
lw v1, UART_LSR(v0)
and v0,v1, UART_LSR_DR
jr ra
nop
END(tgt_testchar)
/*===========================*/
/*Huaya Uart : tgt_getchar*/
LEAF(tgt_getchar)
la v0, UART0_BASE_ADDR
1:
lw v1, UART_LSR(v0)
and v1, UART_LSR_DR // wait for received data ready
beqz v1, 1b
nop
lw v0, UART_RX(v0)
andi v0,0xff
jr ra
nop
END(tgt_getchar)
LEAF(delay1000)
li t0,0x01
li t1,0xFF
li t2,0xFF
1:
nop
2:
nop
3:
nop
subu t2,0x01
bnez t2,3b
nop
li t2,0x20
subu t1,0x01
bnez t1,2b
nop
li t1,0x10
subu t0,0x01
bnez t0,1b
nop
j ra
nop
END(delay1000)
LEAF(delay10)//delay 50us
li t0,0x01
li t1,0x01
li t2,0x01
1:
nop
2:
nop
3:
nop
subu t2,0x01
bnez t2,3b
nop
li t2,0x20
subu t1,0x01
bnez t1,2b
nop
li t1,0x10
subu t0,0x01
bnez t0,1b
nop
j ra
nop
END(delay10)
LEAF(delay100)//delay 4.5ms*32
li t0,0x20
li t1,0x0F
li t2,0x0F
1:
nop
2:
nop
3:
nop
subu t2,0x01
bnez t2,3b
nop
li t2,0x20
subu t1,0x01
bnez t1,2b
nop
li t1,0x10
subu t0,0x01
bnez t0,1b
nop
j ra
nop
END(delay100)
LEAF(delay10000)
//li t0,0xFF //lxf 20130410
li t0,0x80
li t1,0xFF
li t2,0xFF
1:
nop
2:
nop
3:
nop
subu t2,0x01
bnez t2,3b
nop
li t2,0x20
subu t1,0x01
bnez t1,2b
nop
li t1,0x10
subu t0,0x01
bnez t0,1b
nop
j ra
nop
END(delay10000)
/*
*
* a0= w/r arr
* a1=1:w 2:r
* a2=loop times
* a3= r/w data
*
* thunder 2012/03/22
*/
LEAF(ddr_polling)
nop
1:
nop
nop
nop
lw t0,0(a0)
beq t0, a3,2f
nop
nop //subu a2,0x01
nop
b 1b//bnez a2,1b
nop
2:
nop
j ra
nop
END(ddr_polling)
/*
*
* a0= w/r arr
* a1= logic volume=0xffff0001
* a2=loop times
* a3= r/w data
*
* thunder 2012/03/22
*/
LEAF(ddr_polling_bits)
nop
1:
nop
nop
nop
lw t0,0(a0)
and t0,t0,a1
beq t0, a3,2f
nop
nop
nop
b 1b
//subu a2,0x01
//bnez a2,1b
nop
2:
nop
j ra
nop
END(ddr_polling_bits)
/*lxf 20130409 add begin*/
LEAF(ddr_polling2)
nop
1:
nop
nop
nop
lw t0,0(a0)
and t0,t0,a3
beq t0,1,2f
nop
subu a2,0x01
bnez a2,1b
nop
2:
lw t0,0(a0)
and t0,t0,0x7fff0000
bnez t0,3f
li t0,UART0_BASE_ADDR
li t1,0x4F//O
sw t1,UART_TX(t0)
li t0,UART0_BASE_ADDR
li t1,0x4B//K
sw t1,UART_TX(t0)
nop
j ra
nop
3:
nop
li t0,UART0_BASE_ADDR
li t1,0x45//E
sw t1,UART_TX(t0)
li t0,UART0_BASE_ADDR
li t1,0x52//R
sw t1,UART_TX(t0)
li t0,UART0_BASE_ADDR
li t1,0x52//R
sw t1,UART_TX(t0)
nop
j ra
nop
END(ddr_polling2)
/*lxf 20130409 add end*/
/* Huaya UARt
*
* UART_BAUD = APB_CLK/(16*bps)
*
* UART_BAUD = (UART_CLK*16)/(bps) DLM DLL DLF
* wyj 2011-7-25
*/
LEAF(initserial)
#if __DEBUG_PRINT__
#if 1
li t4,CPUConfig1
lw t0,0(t4)
li t4,CPUConfig2
lw t1,0(t4)
li t4,CPUConfig3
lw t2,0(t4)
// bal delay1000
NOP10
li t4,CPUConfig4
lw t3,0(t4)
//t0-t3 store reg data
// data = 27000000 * (1 << ((reg[0] >> 5) & 1)) / (((reg[0] >> 24) & 0xFF) + 1);
srl t4,t0,0x05
andi t4,0x01
li t5,0x01
sllv t6,t5,t4 //(1 << ((reg[0] >> 5) & 1)) ->t6
li t7,27000000
mul t8,t6,t7 //27000000*t6 ->t8
srl t5,t0,0x18
andi t5,0xff
addiu t5,0x01 //(((reg[0] >> 24) & 0xFF) + 1) ->t5
divu t4,t8,t5 //data=t8/t5 ->t4
// data *= (((reg[0] & 0xF) << 8) + ((reg[1] >> 24) & 0xFF) + 1);
andi t5,t0,0x0f
sll t6,t5,0x08 //((reg[0] & 0xF) << 8) ->t6
srl t5,t1,0x18
andi t5,0xff
addiu t5,0x01 //((reg[1] >> 24) & 0xFF)+1 ->t5
addu t7,t6,t5 //t5+t6 ->t7
mul t5,t4,t7 //data=t4*t7 ->t5
// data /= (((reg[2] >> 16) & 0xF) + 1); /* MAXI */
srl t0,t2,0x10
andi t0,0x0f
addiu t0,0x01 //((reg[2] >> 16) & 0x0F)+1 ->t0
divu t4,t5,t0
// hal_clock_sb = data / (1 << (((reg[3] >> 19) & 7) + 1)); /* APB */
srl t0,t3,0x13
andi t0,0x07
addiu t0,0x01 //(((reg[3] >> 19) & 7) + 1) ->t0
li t2,0x01
sllv t6,t2,t0 // ->t6
divu t3,t4,t6 //->t3==uart_clock
#endif
li t0,UART0_BASE_ADDR // 0xbf280000
li t1,0x0 // disable interrupt
sw t1,UART_IER(t0)
li t1,LCR_INIT // 0x1f
sw t1,UART_LCR(t0)
li t1,LCR_DLAB //Enable set baud LCR_INIT | 0x80
sw t1,UART_LCR(t0)
li t1,16
mul t2,t1,t3
divu t1,t2,UART_BAUD
//li t1,(t3*16)/(UART_BAUD) // div = (UART_CLOCK*16)/(CONS_BAUD)
//li t1,(UART_CLOCK*16)/(UART_BAUD) // div = (UART_CLOCK*16)/(CONS_BAUD)
addiu t1,t1,0x1
and t2,t1,0xff // div & 0xff
sw t2,UART_DLF(t0)
srl t2,t1,0x08 // div>>8 & 0xff
andi t2,0xff
sw t2,UART_DLL(t0)
srl t2,t1,0x10 // div>>16 * 0xff
andi t2,0xff
sw t2,UART_DLM(t0)
li t1,LCR_INIT
sw t1,UART_LCR(t0) //Disable set baud
/*enable fifo reset fifo*/
li t1,FCR_INIT // 0x86 (or 0x87?)
sw t1,UART_FCR(t0)
/* Reset line status */
li t1,0x0
sw t1,UART_LSR(t0)
j ra
nop
#else
j ra
nop
#endif
END(initserial)
__main:
j ra
nop
.rdata
transmit_pat_msg:
.asciz "\r\nInvalid transmit pattern. Must be DDDD or DDxDDx\r\n"
v200_msg:
.asciz "\r\nPANIC! Unexpected TLB refill exception!\r\n"
v280_msg:
.asciz "\r\nPANIC! Unexpected XTLB refill exception!\r\n"
v380_msg:
.asciz "\r\nPANIC! Unexpected General exception!\r\n"
v400_msg:
.asciz "\r\nPANIC! Unexpected Interrupt exception!\r\n"
v480_msg:
.asciz "\r\nPANIC! You have been in the Ejtag Debug MOde Trap is 0!\r\n"
hexchar:
.ascii "0123456789abcdef"
.globl
.rdata
msg_pmon :
.asciiz "Init pmon doing......\n"
msg_cache :
.asciiz "Init cache donig ...\n"
.text
.align 2
/*
* I2C Functions used in early startup code to get SPD info from
* SDRAM modules. This code must be entirely PIC and RAM independent.
*/
/* Delay macro */
#define DELAY(count) \
li v0, count; \
99: \
bnz vo, 99b;\
addiu v0, -1
#define Index_Store_Tag_D 0x09
#define Index_Invalidate_I 0x00
#define Index_Writeback_Inv_D 0x01
LEAF(nullfunction)
jr ra
nop
END(nullfunction)
.ent cache_init
.global cache_init
.set noreorder
cache_init:
move t1,ra
####part 2####
cache_detect_4way:
.set mips32
mfc0 t4, CP0_CONFIG,1
# mfc0 $12, $16,1
lui t5, 0x7
and t5, t4, t5
srl t5, t5, 16 #ic
andi t6, t4, 0x0380
srl t6, t6, 7 #dc
addiu t8, $0, 1
#set dcache way
beq t6, $0, cache_d1way
addiu t7, $0, 1 #1 way
beq t6, t8, cache_d2way
addiu t7, $0, 2 #2 way
beq $0, $0, cache_d4way
addiu t7, $0, 4 #4 way
cache_d1way:
beq $0, $0, 1f
addiu t6, t6, 12 #1 way
cache_d2way:
beq $0, $0, 1f
addiu t6, t6, 11 #2 way
cache_d4way:
addiu t6, t6, 10 #4 way (10), 2 way(11), 1 way(12)
1: #set icache way
beq t5, $0, cache_i1way
addiu t3, $0, 1 #1 way
beq t5, t8, cache_i2way
addiu t3, $0, 2 #2 way
beq $0, $0, cache_i4way
addiu t3, $0, 4 #4 way
cache_i1way:
beq $0, $0, 1f
addiu t5, t5, 12
cache_i2way:
beq $0, $0, 1f
addiu t5, t5, 11
cache_i4way:
addiu t5, t5, 10 #4 way (10), 2 way(11), 1 way(12)
1: addiu t4, $0, 1
sllv t6, t4, t6
sllv t5, t4, t5
#if 0
la t0, memvar
sw t7, 0x0(t0) #ways
sw t5, 0x4(t0) #icache size
sw t6, 0x8(t0) #dcache size
#endif
####part 3####
# .set mips3
lui a0, 0x8000
addu a1, $0, t5
addu a2, $0, t6
cache_init_d2way:
#a0=0x80000000, a1=icache_size, a2=dcache_size
#a3, v0 and v1 used as local registers
mtc0 $0, CP0_TAGHI
addu v0, $0, a0
addu v1, a0, a2
1: slt a3, v0, v1
beq a3, $0, 1f
nop
mtc0 $0, CP0_TAGLO
beq t7, 1, 4f
cache Index_Store_Tag_D, 0x0(v0) # 1 way
beq t7, 2 ,4f
cache Index_Store_Tag_D, 0x1000(v0) # 2 way
cache Index_Store_Tag_D, 0x2000(v0) # 4 way
cache Index_Store_Tag_D, 0x3000(v0)
4: beq $0, $0, 1b
addiu v0, v0, 0x20
1:
cache_flush_i2way:
addu v0, $0, a0
addu v1, a0, a1
1: slt a3, v0, v1
beq a3, $0, 1f
nop
beq t3, 1, 4f
cache Index_Invalidate_I, 0x0(v0) # 1 way
beq t3, 2, 4f
cache Index_Invalidate_I, 0x1000(v0) # 2 way
cache Index_Invalidate_I, 0x2000(v0)
cache Index_Invalidate_I, 0x3000(v0) # 4 way
4: beq $0, $0, 1b
addiu v0, v0, 0x20
1:
cache_flush_d2way:
addu v0, $0, a0
addu v1, a0, a2
1: slt a3, v0, v1
beq a3, $0, 1f
nop
beq t7, 1, 4f
cache Index_Writeback_Inv_D, 0x0(v0) #1 way
beq t7, 2, 4f
cache Index_Writeback_Inv_D, 0x1000(v0) # 2 way
cache Index_Writeback_Inv_D, 0x2000(v0)
cache Index_Writeback_Inv_D, 0x3000(v0) # 4 way
4: beq $0, $0, 1b
addiu v0, v0, 0x20
.set mips0
1:
cache_init_finish:
jr t1
nop
.set reorder
.end cache_init
LEAF(cache_sync)
sync
nop
j ra
nop
END(cache_sync)
LEAF(ddr_polling_bits_mddr)
nop
1:
nop
nop
nop
lw t0,0(a0)
and t0,t0,a1
beq t0,a3,2f
nop
nop
nop
subu a2,0x01
bnez a2,1b
nop
addu t6,t6,1 //set flag for polling failure
2:
nop
j ra
nop
END(ddr_polling_bits_mddr)
LEAF(ddr_polling_bits_vddr)
nop
1:
nop
nop
nop
lw t0,0(a0)
and t0,t0,a1
beq t0,a3,2f
nop
nop
nop
subu a2,0x01
bnez a2,1b
nop
addu t7,t7,1 //set flag for polling failure
2:
nop
j ra
nop
END(ddr_polling_bits_vddr)
LEAF(ddr_polling_init_mddr)
nop
1:
nop
nop
nop
lw t0,0(a0)
and t1,t0,a1
beq t1,a3,2f
nop
nop
nop
subu a2,0x01
bnez a2,1b
nop
addu t6,t6,1 //set flag for polling failure
2:
and t0,t0,0x7fff0000
beqz t0,3f
nop
addu t6,t6,1 //set flag for polling failure
3:
j ra
nop
END(ddr_polling_init_mddr)
LEAF(ddr_polling_init_vddr)
nop
1:
nop
nop
nop
lw t0,0(a0)
and t1,t0,a1
beq t1,a3,2f
nop
nop
nop
subu a2,0x01
bnez a2,1b
nop
addu t7,t7,1 //set flag for polling failure
2:
and t0,t0,0x7fff0000
beqz t0,3f
nop
addu t7,t7,1 //set flag for polling failure
3:
j ra
nop
END(ddr_polling_init_vddr)
LEAF(reset_mddr)
beqz t6,1f
nop
#if __DDR_DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x6d //m
sw t1,UART_TX(t0)
#endif
li t0,0xbf200080
lw t1,0(t0)
and t1,t1,0xFFFFFFFB
1:
j ra
nop
END(reset_mddr)
LEAF(release_mddr)
li t0,0xbf200080
lw t1,0(t0)
or t1,t1,0x00000004
j ra
nop
END(release_mddr)
LEAF(reset_vddr)
beqz t7,1f
nop
#if __DDR_DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x76 //v
sw t1,UART_TX(t0)
#endif
li t0,0xbf200080
lw t1,0(t0)
and t1,t1,0xFFFFFFF7
1:
j ra
nop
END(reset_vddr)
LEAF(release_vddr)
li t0,0xbf200080
lw t1,0(t0)
or t1,t1,0x00000008
j ra
nop
END(release_vddr)
#define _KERNEL
#endif
#include <asm.h>
#include <regnum.h>
#include <cpu.h>
#include <pte.h>
#include "pmon/dev/ns16550.h"
#include "target/prid.h"
#include "target/sbd.h"
#include "target/hisense.h"
#include "huaya_uart.h"
#ifndef BOOT_FROM_EJTAG
#define BOOT_FROM_EJTAG
#endif
#undefine BOOT_FROM_EJTAG
#define DEBUG_LOCORE
#define __DEBUG_PRINT__ 1
#define __REMOVE_DEBUG_SERIAL__ 0
#define __DDR_DEBUG_PRINT__ 0
#ifdef DEBUG_LOCORE
#define TTYDBG(x) \
.rdata;98: .asciiz x; .text; la a0, 98b; bal stringserial; nop
#else
#define TTYDBG(x)
#endif
#define PRINTSTR(x)
// .rdata;98: .asciiz x; .text; la a0, 98b; bal stringserial; nop
#define NOP10 nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop
#ifdef DEVBD_LS232_SM502
#define GPIOLED_DIR 0xff
#define GPIO_OE_7_0 0x0
#define GPIO_OE_15_8 0x1
#define GPIO_OE_23_16 0x2
#define GPIO_OE_28_24 0x3
#define GPIO_OE GPIO_OE_7_0
#define GPIO_O_7_0 0x20
#define GPIO_O_15_8 0x21
#define GPIO_O_23_16 0x22
#define GPIO_O_28_24 0x2c
#define GPIO_O GPIO_O_7_0
#endif
#define tmpsize s1
#define msize s2
#define bonito s4
#define dbg s5
#define sdCfg s6
#define CP0_CONFIG $16
#define CP0_TAGLO $28
#define CP0_TAGHI $29
#define CPUConfig1 0xbf204000
#define CPUConfig2 0xbf204004
#define CPUConfig3 0xbf204008
#define CPUConfig4 0xbf200090 //thunder 20120228
/*
* Register usage:
*
* s0 link versus load offset, used to relocate absolute adresses.
* s1 free
* s2 memory size.
* s3 free.
* s4 Bonito base address.
* s5 dbg.
* s6 sdCfg.
* s7 rasave.
* s8 L3 Cache size.
*/
.set noreorder
.globl _start
.globl start
.globl __main
_start:
start:
.globl stack
stack = start - 0x8000 /*+ 0x20000000 thunder 20120830*/ /* Place PMON stack below PMON start in RAM */
/* 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 sp, stack
la gp, _gp
bal locate /* Get current execute address */
nop
uncached:
or ra, UNCACHED_MEMORY_ADDR
j ra
nop
/*
* Reboot vector usable from outside pmon.
*/
.align 9
ext_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
/* */
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 9 /* bfc00400 */
la a0, v400_msg
bal stringserial
nop
b exc_common
.align 7 /* bfc00480 */
la a0, v480_msg
bal stringserial
nop
b exc_common
.align 8 /* bfc00500 */
exc_common:
PRINTSTR("\r\nCAUSE=")
mfc0 a0, COP_0_CAUSE_REG
bal hexserial
nop
PRINTSTR("\r\nSTATUS=")
mfc0 a0, COP_0_STATUS_REG
bal hexserial
nop
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
.align 9
nop
.align 8
.word read
.word write
.word open
.word close
#if 0
.word nullfunction
.word nullfunction
.word nullfunction
.word nullfunction
#endif
.word nullfunction
.word printf
.word vsprintf
#if 0
.word nullfunction
.word nullfunction
#endif
.word nullfunction
.word nullfunction
.word getenv
// .word nullfunction
.word nullfunction
.word nullfunction
.word nullfunction
.word nullfunction
/*
* 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,uncached //把编译之后uncached这个符号的地址load给s0(应为一个0x8开的头的地址)
subu s0,ra,s0
// and s0,0xffffff00
beqz s0,skipddr
nop
/*
s0 是个比较重要的寄存器,定位代码的位置。
若代码在spiflash中,ra = 一个以0xbfc开头的地址,这样ra-s0得出的是代码在spiflash跟ddr之间的偏移量。
若s0 = 0,说明代码在内存里面执行,所以直接跳过PLL的初始化代码,因为PLL是不能重复初始化的。
若s0 !=0,说明代码是在spiflash里面执行,接着进行PLL的初始化操作。
*/
#include "1050/debug_Hynix_HS3K_H1PLL_1050_0515_v4-1_no-bprd_upd0522-test.S" //PLL初始化代码
/*
为了在下面DDR初始化的时候,打印字符进行调试,所以在这里提前把串口初始化好。这样
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x42//B
sw t1,UART_TX(t0)
#endif
这样的代码就能打印出一个B字符出来。
*/
skipddr:
bal initserial
nop
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x42//B
sw t1,UART_TX(t0)
#endif
/*
如果s0=0的话,说明代码是在DDR中运行,跳过下面DDR初始化的代码,因为DDR也是不能重复初始化的。
/*
beqz s0,skipddr1
nop
#include "1050/debug_Hynix_HS3K_H1MVDDR_1050_0515_v4-1_no-bprd_upd0522-test.S"
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x42//B
sw t1,UART_TX(t0)
#endif
/*
进行清TLB操作,把TLB 32项的寄存器都赋值为0.
/*
skipddr1:
bal CPU_TLBClear
nop
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x6F//o
sw t1,UART_TX(t0)
#endif
li t0,SR_BOOT_EXC_VEC
mtc0 t0,COP_0_STATUS_REG //初始化CP0 status寄存器。
mtc0 zero,COP_0_CAUSE_REG //初始化CPO CAUSE寄存器,写0.
.set noreorder //禁止乱序执行。
mfc0 a0, COP_0_ERROR_PC
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDRli
t1,0x6F//o
sw t1,UART_TX(t0)
#endif
PRINTSTR(" CONFIG=")
mfc0 a0, COP_0_CONFIG
PRINTSTR("\r\n")
PRINTSTR(" PRID=")
mfc0 a0, COP_0_PRIDbal
hexserialnopPRINTSTR(" s0=")
move a0, s0
bal hexserial
nop
PRINTSTR("\r\n")
/* * Now determine DRAM configuration and size by * reading the I2C EEROM on the DIMMS */
dmc_init:
PRINTSTR("Start initializing SDRAM(dmc init)...\n")
//#include "dmc_init.S"
PRINTSTR("Finish configurating the SDRAM's register...\n")
li msize,0x10000000 #for 256MB memory size
PRINTSTR("Init SDRAM Done!\n\n")
#define CF_7_SE (1 << 3) /* Secondary cache enable */
#define CF_7_SC (1 << 31) /* Secondary cache not present */
#define CF_7_TE (1 << 12) /* Tertiary cache enable */
#define CF_7_TC (1 << 17) /* Tertiary cache not present */
#define CF_7_TS (3 << 20) /* Tertiary cache size */
#define CF_7_TS_AL 20 /* Shift to align */
#define NOP8 nop;nop;nop;nop;nop;nop;nop;nop
do_caches:
PRINTSTR("Init caches...\r\n")
li s7, 0 /* no L2 cache */
li s8, 0 /* no L3 cache */
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x74//t
sw t1,UART_TX(t0)
#endifPRINTSTR("LS232 caches found...\r\n")
bal cache_init //进行cache init操作。
nop
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x69//i
sw t1,UART_TX(t0)
#endif
PRINTSTR("Init caches done, cfg = ")
mfc0 a0, COP_0_CONFIG
bal hexserial
nop
PRINTSTR("\r\n\r\nbootnow...")
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x6E//n
sw t1,UART_TX(t0)
#endif
/* Clear BSS */
la a0, _edata
la a2, _end
2: sw zero, 0(a0)
bne a2, a0, 2b
addu a0, 4
PRINTSTR("CLEAR_DOWN\r\n")
bootnow:
bnez s0,1f //s0 = 0, code in ddr; s0 != 0 ,code in spiflash.也就是说,如果代码在spiflash中的话,就会跳到1f,去运行拷贝代码;如果代码在ddr里面,那么会直接跳到copydone(拷贝完成),1f之后的copy代码就不再执行了。
nop
/*把cache打开*/
mfc0 a0,COP_0_CONFIG
and a0,a0,0xfffffff8
or a0,a0,0x3
mtc0 a0,COP_0_CONFIG
nop
b copydone
nop
1:
#define FCALL_PRINTSTR(x) \
.rdata;98: .asciz x; .text; la a0, 98b; la v0, stringserial; addu v0,s0;jalr v0; nop
#undef BAL
#define BAL(x) \
la v0,x; \
addu v0,s0; \
jalr v0; \
nop;
/*执行拷贝代码之前,要把cache关掉,以为不关的话,代码可能只拷贝在cache里面,没有真正写入ddr,这样再跳到0x80000000去执行的时候会出问题(reboot)*/
mfc0 a0,COP_0_CONFIG
and a0,a0,0xfffffff8
or a0,a0,0x2
mtc0 a0,COP_0_CONFIG
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x67//g
sw t1,UART_TX(t0)
#endif
/*copy copy program to sdram to make copy fast*/
/* Don't Copy! */
/*下面这段代码的作用是将121f-122f之间的代码,拷贝到ddr 0x80000000的位置,然后去ddr里执行,这样执行速度更快
121f 122f这写符号的地址是编译后代码里的地址,是以0x8开头的运行地址,所以要将其加上s0(spi相对ddr的偏移量)*/
la t0,121f // copy program start addr
addu t0,s0
la t1,122f // copy program end addr
addu t1,s0
li t2,0x80000000 // write copy program to 0x80000000
1:
lw v0,(t0)
sw v0,(t2)
addu t0,4
addu t2,4
ble t0,t1,1b
nop
#if __DEBUG_PRINT__
li t5,UART0_BASE_ADDR
li t6,0x20// space
sw t6,UART_TX(t5)
#endif
sync
nop
li t0,0x80000000
jr t0 // jump to 0x80000000 to execute the copy program
nop
.align 3
121:
#if __DEBUG_PRINT__
li t5,UART0_BASE_ADDR
li t6,0x50//P
sw t6,UART_TX(t5)
#endif
la a0, start // 0x81000 0000
addu a1,a0,s0
la a2, _edata // 0x81047010
subu t1, a2, a0
srl t1, t1, 2
#if __DEBUG_PRINT__
li t5,UART0_BASE_ADDR
li t6,0x4D//M
sw t6,UART_TX(t5)
#endif
move t0, a0 //t0保存start的地址
move t1, a1 //t1保存在start在spiflash里的地址。
move t2, a2 //t2保存_edata的地址,从ld.script里可以看出,_edata与start之间主要为代码段和数据段。
#if __DEBUG_PRINT__
li t5,UART0_BASE_ADDR
li t6,0x4F//O
sw t6,UART_TX(t5)
#endif
/* copy text section */
/*下面这段代码将程序的_edata与start之间的代码段和数据段拷贝到内存对应的位置*/
1: and t3,t0,0x0000ffff
bnez t3,2f
nop
move a0,t0
BAL(hexserial)
nop
li a0,'\r'
BAL(tgt_putchar)
nop
2: lw t3, 0(t1)
nop
sw t3, 0(t0)
addu t0, 4
addu t1, 4
bne t2, t0, 1b
nop
sync
#if __DEBUG_PRINT__
li t5,UART0_BASE_ADDR
li t6,0x4E//N
sw t6,UART_TX(t5)
#endif
/* Clear BSS */
la a0, _edata
la a2, _end
2: sw zero, 0(a0)
bne a2, a0, 2b
addu a0, 4
move a0, sp
BAL(hexserial)
nop
copydone:
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x2E//.
sw t1,UART_TX(t0)
#endif
/*下面这段代码用来刷4路cache*/
.set mips3
#ifndef WAYBIT
#define WAYBIT 12
#endif
#define WAY__(x) x
#define WAY_(x,y) WAY__((x<<y))
#define WAY(x) WAY_(x,WAYBIT)
li $5,0x80000000;
addu $6,$5,16384;
1:
cache 1, WAY(0)($5);
cache 1, WAY(1)($5);
cache 1, WAY(2)($5);
cache 1, WAY(3)($5);
cache 0, WAY(0)($5);
cache 0, WAY(1)($5);
cache 0, WAY(2)($5);
cache 0, WAY(3)($5);
add $5,$5,32;
bne $5,$6,1b;
nop
.set mips0
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x2E//.
sw t1,UART_TX(t0)
#endif
li a0, 0
sw a0, CpuTertiaryCacheSize /* Set L3 cache size */
move a0,msize //initmips的参数
srl a0,20
#if __DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x2E//.
sw t1,UART_TX(t0)
#endif
la v0, initmips //跳转到initmips.c的initmips函数开始执行c代码。initmips.c是用perl脚本,根据编译好的pmon elf文件生成的一个.c文件,
jalr v0
nop
.align 3
122:
/*
* get the status of cache
*/
LEAF(GET_CACHE_STATUS)
mfc0 v0,COP_0_CONFIG
andi v0,v0,0x3
nop
jr ra
END(GET_CACHE_STATUS)
LEAF(CACHE_ENABLE)
nop
mfc0 a0,COP_0_CONFIG
and a0,a0,0xfffffff8
or a0,a0,0x3
mtc0 a0,COP_0_CONFIG
nop
jr ra
nop
END(CACHE_ENABLE)
stuck:
b stuck
nop
/*
* Clear the TLB. Normally called from start.S.
*/
#if __mips64
#define MTC0 dmtc0
#else
#define MTC0 mtc0
#endif
LEAF(CPU_TLBClear)
li a3, 0 # First TLB index.
li a2, PG_SIZE_4K
MTC0 a2, COP_0_TLB_PG_MASK # Whatever...
1:
MTC0 zero, COP_0_TLB_HI # Clear entry high.
MTC0 zero, COP_0_TLB_LO0 # Clear entry low0.
MTC0 zero, COP_0_TLB_LO1 # Clear entry low1.
mtc0 a3, COP_0_TLB_INDEX # Set the index.
addiu a3, 1
li a2, 64
nop
nop
tlbwi # Write the TLB
bne a3, a2, 1b
nop
jr ra
nop
END(CPU_TLBClear)
/*
* Set up the TLB. Normally called from start.S.
*/
LEAF(CPU_TLBInit)
li a3, 0 # First TLB index.
li a2, PG_SIZE_16M
MTC0 a2, COP_0_TLB_PG_MASK # All pages are 16Mb.
1:
and a2, a0, PG_SVPN
MTC0 a2, COP_0_TLB_HI # Set up entry high.
move a2, a0
srl a2, a0, PG_SHIFT
and a2, a2, PG_FRAME
ori a2, PG_IOPAGE
MTC0 a2, COP_0_TLB_LO0 # Set up entry low0.
addu a2, (0x01000000 >> PG_SHIFT)
MTC0 a2, COP_0_TLB_LO1 # Set up entry low1.
mtc0 a3, COP_0_TLB_INDEX # Set the index.
addiu a3, 1
li a2, 0x02000000
subu a1, a2
nop
tlbwi # Write the TLB
bgtz a1, 1b
addu a0, a2 # Step address 32Mb.
jr ra
nop
END(CPU_TLBInit)
LEAF(stringserial)
#if __REMOVE_DEBUG_SERIAL__
move a2, ra
addu a1, a0, s0
// addiu a1,a0,0x0 // wyj 7-26
lbu a0, 0(a1)
1:
beqz a0, 2f
nop
bal tgt_putchar
addiu a1, 1
b 1b
lbu a0, 0(a1)
2:
j a2
nop
#endif
jr ra
nop
END(stringserial)
LEAF(outstring)
#if __REMOVE_DEBUG_SERIAL__
move a2, ra
move a1, a0
lbu a0, 0(a1)
1:
beqz a0, 2f
nop
bal tgt_putchar
addiu a1, 1
b 1b
lbu a0, 0(a1)
2:
j a2
nop
#endif
jr ra
nop
END(outstring)
LEAF(hexserial)
#if __REMOVE_DEBUG_SERIAL__
move a2, ra
move a1, a0
li a3, 7
1:
rol a0, a1, 4
move a1, a0
and a0, 0xf
la v0, hexchar
addu v0, s0
addu v0, a0
bal tgt_putchar
lbu a0, 0(v0)
bnez a3, 1b
addu a3, -1
j a2
nop
#endif
jr ra
nop
END(hexserial)
#if 1
LEAF(tgt_putchar)
#if __REMOVE_DEBUG_SERIAL__
li v0,UART0_BASE_ADDR
1:
lw v1,UART_LSR(v0)
and v1,UART_LSR_TX_EMPTY
beqz v1,1b
nop
andi a0,0xff
sw a0,UART_TX(v0)
j ra
nop
#endif
jr ra
nop
END(tgt_putchar)
#endif
LEAF(tgt_testchar) /* need to fix wyj*/
la v0,UART0_BASE_ADDR
1:
lw v1, UART_LSR(v0)
and v0,v1, UART_LSR_DR
jr ra
nop
END(tgt_testchar)
/*===========================*/
/*Huaya Uart : tgt_getchar*/
LEAF(tgt_getchar)
la v0, UART0_BASE_ADDR
1:
lw v1, UART_LSR(v0)
and v1, UART_LSR_DR // wait for received data ready
beqz v1, 1b
nop
lw v0, UART_RX(v0)
andi v0,0xff
jr ra
nop
END(tgt_getchar)
LEAF(delay1000)
li t0,0x01
li t1,0xFF
li t2,0xFF
1:
nop
2:
nop
3:
nop
subu t2,0x01
bnez t2,3b
nop
li t2,0x20
subu t1,0x01
bnez t1,2b
nop
li t1,0x10
subu t0,0x01
bnez t0,1b
nop
j ra
nop
END(delay1000)
LEAF(delay10)//delay 50us
li t0,0x01
li t1,0x01
li t2,0x01
1:
nop
2:
nop
3:
nop
subu t2,0x01
bnez t2,3b
nop
li t2,0x20
subu t1,0x01
bnez t1,2b
nop
li t1,0x10
subu t0,0x01
bnez t0,1b
nop
j ra
nop
END(delay10)
LEAF(delay100)//delay 4.5ms*32
li t0,0x20
li t1,0x0F
li t2,0x0F
1:
nop
2:
nop
3:
nop
subu t2,0x01
bnez t2,3b
nop
li t2,0x20
subu t1,0x01
bnez t1,2b
nop
li t1,0x10
subu t0,0x01
bnez t0,1b
nop
j ra
nop
END(delay100)
LEAF(delay10000)
//li t0,0xFF //lxf 20130410
li t0,0x80
li t1,0xFF
li t2,0xFF
1:
nop
2:
nop
3:
nop
subu t2,0x01
bnez t2,3b
nop
li t2,0x20
subu t1,0x01
bnez t1,2b
nop
li t1,0x10
subu t0,0x01
bnez t0,1b
nop
j ra
nop
END(delay10000)
/*
*
* a0= w/r arr
* a1=1:w 2:r
* a2=loop times
* a3= r/w data
*
* thunder 2012/03/22
*/
LEAF(ddr_polling)
nop
1:
nop
nop
nop
lw t0,0(a0)
beq t0, a3,2f
nop
nop //subu a2,0x01
nop
b 1b//bnez a2,1b
nop
2:
nop
j ra
nop
END(ddr_polling)
/*
*
* a0= w/r arr
* a1= logic volume=0xffff0001
* a2=loop times
* a3= r/w data
*
* thunder 2012/03/22
*/
LEAF(ddr_polling_bits)
nop
1:
nop
nop
nop
lw t0,0(a0)
and t0,t0,a1
beq t0, a3,2f
nop
nop
nop
b 1b
//subu a2,0x01
//bnez a2,1b
nop
2:
nop
j ra
nop
END(ddr_polling_bits)
/*lxf 20130409 add begin*/
LEAF(ddr_polling2)
nop
1:
nop
nop
nop
lw t0,0(a0)
and t0,t0,a3
beq t0,1,2f
nop
subu a2,0x01
bnez a2,1b
nop
2:
lw t0,0(a0)
and t0,t0,0x7fff0000
bnez t0,3f
li t0,UART0_BASE_ADDR
li t1,0x4F//O
sw t1,UART_TX(t0)
li t0,UART0_BASE_ADDR
li t1,0x4B//K
sw t1,UART_TX(t0)
nop
j ra
nop
3:
nop
li t0,UART0_BASE_ADDR
li t1,0x45//E
sw t1,UART_TX(t0)
li t0,UART0_BASE_ADDR
li t1,0x52//R
sw t1,UART_TX(t0)
li t0,UART0_BASE_ADDR
li t1,0x52//R
sw t1,UART_TX(t0)
nop
j ra
nop
END(ddr_polling2)
/*lxf 20130409 add end*/
/* Huaya UARt
*
* UART_BAUD = APB_CLK/(16*bps)
*
* UART_BAUD = (UART_CLK*16)/(bps) DLM DLL DLF
* wyj 2011-7-25
*/
LEAF(initserial)
#if __DEBUG_PRINT__
#if 1
li t4,CPUConfig1
lw t0,0(t4)
li t4,CPUConfig2
lw t1,0(t4)
li t4,CPUConfig3
lw t2,0(t4)
// bal delay1000
NOP10
li t4,CPUConfig4
lw t3,0(t4)
//t0-t3 store reg data
// data = 27000000 * (1 << ((reg[0] >> 5) & 1)) / (((reg[0] >> 24) & 0xFF) + 1);
srl t4,t0,0x05
andi t4,0x01
li t5,0x01
sllv t6,t5,t4 //(1 << ((reg[0] >> 5) & 1)) ->t6
li t7,27000000
mul t8,t6,t7 //27000000*t6 ->t8
srl t5,t0,0x18
andi t5,0xff
addiu t5,0x01 //(((reg[0] >> 24) & 0xFF) + 1) ->t5
divu t4,t8,t5 //data=t8/t5 ->t4
// data *= (((reg[0] & 0xF) << 8) + ((reg[1] >> 24) & 0xFF) + 1);
andi t5,t0,0x0f
sll t6,t5,0x08 //((reg[0] & 0xF) << 8) ->t6
srl t5,t1,0x18
andi t5,0xff
addiu t5,0x01 //((reg[1] >> 24) & 0xFF)+1 ->t5
addu t7,t6,t5 //t5+t6 ->t7
mul t5,t4,t7 //data=t4*t7 ->t5
// data /= (((reg[2] >> 16) & 0xF) + 1); /* MAXI */
srl t0,t2,0x10
andi t0,0x0f
addiu t0,0x01 //((reg[2] >> 16) & 0x0F)+1 ->t0
divu t4,t5,t0
// hal_clock_sb = data / (1 << (((reg[3] >> 19) & 7) + 1)); /* APB */
srl t0,t3,0x13
andi t0,0x07
addiu t0,0x01 //(((reg[3] >> 19) & 7) + 1) ->t0
li t2,0x01
sllv t6,t2,t0 // ->t6
divu t3,t4,t6 //->t3==uart_clock
#endif
li t0,UART0_BASE_ADDR // 0xbf280000
li t1,0x0 // disable interrupt
sw t1,UART_IER(t0)
li t1,LCR_INIT // 0x1f
sw t1,UART_LCR(t0)
li t1,LCR_DLAB //Enable set baud LCR_INIT | 0x80
sw t1,UART_LCR(t0)
li t1,16
mul t2,t1,t3
divu t1,t2,UART_BAUD
//li t1,(t3*16)/(UART_BAUD) // div = (UART_CLOCK*16)/(CONS_BAUD)
//li t1,(UART_CLOCK*16)/(UART_BAUD) // div = (UART_CLOCK*16)/(CONS_BAUD)
addiu t1,t1,0x1
and t2,t1,0xff // div & 0xff
sw t2,UART_DLF(t0)
srl t2,t1,0x08 // div>>8 & 0xff
andi t2,0xff
sw t2,UART_DLL(t0)
srl t2,t1,0x10 // div>>16 * 0xff
andi t2,0xff
sw t2,UART_DLM(t0)
li t1,LCR_INIT
sw t1,UART_LCR(t0) //Disable set baud
/*enable fifo reset fifo*/
li t1,FCR_INIT // 0x86 (or 0x87?)
sw t1,UART_FCR(t0)
/* Reset line status */
li t1,0x0
sw t1,UART_LSR(t0)
j ra
nop
#else
j ra
nop
#endif
END(initserial)
__main:
j ra
nop
.rdata
transmit_pat_msg:
.asciz "\r\nInvalid transmit pattern. Must be DDDD or DDxDDx\r\n"
v200_msg:
.asciz "\r\nPANIC! Unexpected TLB refill exception!\r\n"
v280_msg:
.asciz "\r\nPANIC! Unexpected XTLB refill exception!\r\n"
v380_msg:
.asciz "\r\nPANIC! Unexpected General exception!\r\n"
v400_msg:
.asciz "\r\nPANIC! Unexpected Interrupt exception!\r\n"
v480_msg:
.asciz "\r\nPANIC! You have been in the Ejtag Debug MOde Trap is 0!\r\n"
hexchar:
.ascii "0123456789abcdef"
.globl
.rdata
msg_pmon :
.asciiz "Init pmon doing......\n"
msg_cache :
.asciiz "Init cache donig ...\n"
.text
.align 2
/*
* I2C Functions used in early startup code to get SPD info from
* SDRAM modules. This code must be entirely PIC and RAM independent.
*/
/* Delay macro */
#define DELAY(count) \
li v0, count; \
99: \
bnz vo, 99b;\
addiu v0, -1
#define Index_Store_Tag_D 0x09
#define Index_Invalidate_I 0x00
#define Index_Writeback_Inv_D 0x01
LEAF(nullfunction)
jr ra
nop
END(nullfunction)
.ent cache_init
.global cache_init
.set noreorder
cache_init:
move t1,ra
####part 2####
cache_detect_4way:
.set mips32
mfc0 t4, CP0_CONFIG,1
# mfc0 $12, $16,1
lui t5, 0x7
and t5, t4, t5
srl t5, t5, 16 #ic
andi t6, t4, 0x0380
srl t6, t6, 7 #dc
addiu t8, $0, 1
#set dcache way
beq t6, $0, cache_d1way
addiu t7, $0, 1 #1 way
beq t6, t8, cache_d2way
addiu t7, $0, 2 #2 way
beq $0, $0, cache_d4way
addiu t7, $0, 4 #4 way
cache_d1way:
beq $0, $0, 1f
addiu t6, t6, 12 #1 way
cache_d2way:
beq $0, $0, 1f
addiu t6, t6, 11 #2 way
cache_d4way:
addiu t6, t6, 10 #4 way (10), 2 way(11), 1 way(12)
1: #set icache way
beq t5, $0, cache_i1way
addiu t3, $0, 1 #1 way
beq t5, t8, cache_i2way
addiu t3, $0, 2 #2 way
beq $0, $0, cache_i4way
addiu t3, $0, 4 #4 way
cache_i1way:
beq $0, $0, 1f
addiu t5, t5, 12
cache_i2way:
beq $0, $0, 1f
addiu t5, t5, 11
cache_i4way:
addiu t5, t5, 10 #4 way (10), 2 way(11), 1 way(12)
1: addiu t4, $0, 1
sllv t6, t4, t6
sllv t5, t4, t5
#if 0
la t0, memvar
sw t7, 0x0(t0) #ways
sw t5, 0x4(t0) #icache size
sw t6, 0x8(t0) #dcache size
#endif
####part 3####
# .set mips3
lui a0, 0x8000
addu a1, $0, t5
addu a2, $0, t6
cache_init_d2way:
#a0=0x80000000, a1=icache_size, a2=dcache_size
#a3, v0 and v1 used as local registers
mtc0 $0, CP0_TAGHI
addu v0, $0, a0
addu v1, a0, a2
1: slt a3, v0, v1
beq a3, $0, 1f
nop
mtc0 $0, CP0_TAGLO
beq t7, 1, 4f
cache Index_Store_Tag_D, 0x0(v0) # 1 way
beq t7, 2 ,4f
cache Index_Store_Tag_D, 0x1000(v0) # 2 way
cache Index_Store_Tag_D, 0x2000(v0) # 4 way
cache Index_Store_Tag_D, 0x3000(v0)
4: beq $0, $0, 1b
addiu v0, v0, 0x20
1:
cache_flush_i2way:
addu v0, $0, a0
addu v1, a0, a1
1: slt a3, v0, v1
beq a3, $0, 1f
nop
beq t3, 1, 4f
cache Index_Invalidate_I, 0x0(v0) # 1 way
beq t3, 2, 4f
cache Index_Invalidate_I, 0x1000(v0) # 2 way
cache Index_Invalidate_I, 0x2000(v0)
cache Index_Invalidate_I, 0x3000(v0) # 4 way
4: beq $0, $0, 1b
addiu v0, v0, 0x20
1:
cache_flush_d2way:
addu v0, $0, a0
addu v1, a0, a2
1: slt a3, v0, v1
beq a3, $0, 1f
nop
beq t7, 1, 4f
cache Index_Writeback_Inv_D, 0x0(v0) #1 way
beq t7, 2, 4f
cache Index_Writeback_Inv_D, 0x1000(v0) # 2 way
cache Index_Writeback_Inv_D, 0x2000(v0)
cache Index_Writeback_Inv_D, 0x3000(v0) # 4 way
4: beq $0, $0, 1b
addiu v0, v0, 0x20
.set mips0
1:
cache_init_finish:
jr t1
nop
.set reorder
.end cache_init
LEAF(cache_sync)
sync
nop
j ra
nop
END(cache_sync)
LEAF(ddr_polling_bits_mddr)
nop
1:
nop
nop
nop
lw t0,0(a0)
and t0,t0,a1
beq t0,a3,2f
nop
nop
nop
subu a2,0x01
bnez a2,1b
nop
addu t6,t6,1 //set flag for polling failure
2:
nop
j ra
nop
END(ddr_polling_bits_mddr)
LEAF(ddr_polling_bits_vddr)
nop
1:
nop
nop
nop
lw t0,0(a0)
and t0,t0,a1
beq t0,a3,2f
nop
nop
nop
subu a2,0x01
bnez a2,1b
nop
addu t7,t7,1 //set flag for polling failure
2:
nop
j ra
nop
END(ddr_polling_bits_vddr)
LEAF(ddr_polling_init_mddr)
nop
1:
nop
nop
nop
lw t0,0(a0)
and t1,t0,a1
beq t1,a3,2f
nop
nop
nop
subu a2,0x01
bnez a2,1b
nop
addu t6,t6,1 //set flag for polling failure
2:
and t0,t0,0x7fff0000
beqz t0,3f
nop
addu t6,t6,1 //set flag for polling failure
3:
j ra
nop
END(ddr_polling_init_mddr)
LEAF(ddr_polling_init_vddr)
nop
1:
nop
nop
nop
lw t0,0(a0)
and t1,t0,a1
beq t1,a3,2f
nop
nop
nop
subu a2,0x01
bnez a2,1b
nop
addu t7,t7,1 //set flag for polling failure
2:
and t0,t0,0x7fff0000
beqz t0,3f
nop
addu t7,t7,1 //set flag for polling failure
3:
j ra
nop
END(ddr_polling_init_vddr)
LEAF(reset_mddr)
beqz t6,1f
nop
#if __DDR_DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x6d //m
sw t1,UART_TX(t0)
#endif
li t0,0xbf200080
lw t1,0(t0)
and t1,t1,0xFFFFFFFB
1:
j ra
nop
END(reset_mddr)
LEAF(release_mddr)
li t0,0xbf200080
lw t1,0(t0)
or t1,t1,0x00000004
j ra
nop
END(release_mddr)
LEAF(reset_vddr)
beqz t7,1f
nop
#if __DDR_DEBUG_PRINT__
li t0,UART0_BASE_ADDR
li t1,0x76 //v
sw t1,UART_TX(t0)
#endif
li t0,0xbf200080
lw t1,0(t0)
and t1,t1,0xFFFFFFF7
1:
j ra
nop
END(reset_vddr)
LEAF(release_vddr)
li t0,0xbf200080
lw t1,0(t0)
or t1,t1,0x00000008
j ra
nop
END(release_vddr)