/* $NetBSD: entry.S,v 1.6 2012/01/14 20:03:12 phx Exp $ */
#include <powerpc/psl.h>
#include <powerpc/spr.h>
#include <powerpc/oea/spr.h>
#include <powerpc/oea/bat.h>
#include <powerpc/oea/hid.h>
.text
.globl _start
_start:
/*
* Save possible argc and argv values from the firmware, usually
* passed in r3 and r4.
* When started with "bootm", as a Linux kernel module, r6 and r7
* point to the start and end address of the bootargs.
*/
mr 30,3
mr 31,4
mr 28,6
mr 29,7
/* Disable interrupts and everything except the MMU. */
mfmsr 3
andi. 3,3,PSL_DR|PSL_IR
mtmsr 3
isync
/*
* U-Boot/PPCBoot forgets to flush the cache when using the "bootm"
* command, so we have to do that now.
*/
lis 11,_start@ha
addi 11,11,_start@l
li 10,-32
and 11,11,10
lis 12,(_edata+31)@ha
addi 12,12,(_edata+31)@l
bl syncicache
mfspr 11,SPR_HID0
andi. 0,11,HID0_DCE
ori 11,11,HID0_ICE
ori 8,11,HID0_ICFI
bne 1f /* don't invalidate the D-cache */
ori 8,8,HID0_DCFI /* unless it wasn't enabled */
1:
mfmsr 0
andi. 0,0,PSL_DR
beq 2f
lis 5,0xfec00000@ha /* CONFIG_ADDR of PCI */
lis 6,0xfee00000@ha /* CONFIG_DATA of PCI */
mfspr 3,SPR_DBAT0U
mfspr 4,SPR_DBAT0L
bl dbat_sanity_check
beq 3f
mfspr 3,SPR_DBAT1U
mfspr 4,SPR_DBAT1L
bl dbat_sanity_check
beq 3f
mfspr 3,SPR_DBAT2U
mfspr 4,SPR_DBAT2L
bl dbat_sanity_check
beq 3f
mfspr 3,SPR_DBAT3U
mfspr 4,SPR_DBAT3L
bl dbat_sanity_check
beq 3f
2: /* Disable D-cache */
li 0,HID0_DCE
andc 11,11,0
b 4f
3: /* Enable D-cache */
ori 11,11,HID0_DCE
4:
lis 1,BAT123@ha
addi 1,1,BAT123@l
lwz 3,0(1)
lwz 4,4(1)
mtdbatl 1,3
mtdbatu 1,4
lwz 3,8(1)
lwz 4,12(1)
mtdbatl 2,3
mtdbatu 2,4
lwz 3,16(1)
lwz 4,20(1)
mtdbatl 3,3
mtdbatu 3,4
sync
mtspr SPR_HID0,8 /* enable and invalidate caches */
sync
mtspr SPR_HID0,11 /* enable caches */
sync
isync
/* make sure .bss gets zeroed. */
li 0,0
lis 8,edata@ha
addi 8,8,edata@l
lis 9,end@ha
addi 9,9,end@l
5: cmpw 0,8,9 /* edata & end are >= word aligned */
bge 6f
stw 0,0(8)
addi 8,8,4
b 5b
6:
/* prepare stack at +1MB from _start, 16-byte aligned */
lis 1,_start@ha
addi 1,1,_start@l
addis 1,1,0x100000@ha
li 10,-16
and 1,1,10
stw 0,0(1)
bl brdsetup
#ifdef DEBUG
bl init_vectors
#endif
mr 3,30
mr 4,31
mr 5,28
mr 6,29
bl main
hang: b hang
/* NOTREACHED */
dbat_sanity_check:
andi. 0,3,BAT_Vs
beq 2f
andi. 0,4,BAT_I|BAT_PP_RW
cmpwi 0,0,BAT_I|BAT_PP_RW
bnelr
rlwinm 0,3,15,4,14
andis. 3,3,0xfffe0000@ha /* BAT_EPI */
andis. 4,4,BAT_RPN@ha
cmplw 0,3,4
bnelr
add 4,4,0
oris 4,4,0x0001ffff@ha
ori 4,4,0x0001ffff@l
cmplw 0,3,5
bgt 1f
cmplw 0,5,4
bgt 1f
li 5,0
1: cmplw 0,3,6
bgt 2f
cmplw 0,6,4
bgt 2f
li 6,0
2: cmplw 0,5,6
blr
/*
* run(startsym, endsym, howto, bootinfo, entry)
*/
.globl run
run:
mtctr 7 /* hat trick jump to entry point */
bctr
/*
* newaltboot(argc, argv, altboot_base, altboot_len)
* To be executed in a safe memory region. Copies the new altboot from
* altboot_base to 0x1000000 and starts it there.
*/
.globl newaltboot
newaltboot:
lis 7,0x1000000@h
mr 11,7
subi 7,7,4
subi 5,5,4
add 12,11,6
addi 6,6,3
srawi 6,6,2
mtctr 6
1: lwzu 8,4(5)
stwu 8,4(7)
bdnz+ 1b
mtctr 11
addi 12,12,31
bl syncicache
bctr
syncicache:
/* r11=start, r12=end, r10=scratch */
mr 10,11
2: dcbst 0,10
addi 10,10,32
cmplw 10,12
ble 2b
sync
3: icbi 0,11
addi 11,11,32
cmplw 11,12
ble 3b
sync
isync
blr
.globl newaltboot_end
newaltboot_end:
/* 8-bit i/o access */
.globl out8
out8:
stb 4,0(3)
eieio
blr
.globl in8
in8:
lbz 3,0(3)
eieio
blr
/*
* reverse endian access to mimic outw/outl/inw/inl
*/
.globl out16rb
.globl iohtole16
out16rb:
iohtole16:
sthbrx 4,0,3
eieio
blr
.globl out32rb
.globl iohtole32
out32rb:
iohtole32:
stwbrx 4,0,3
eieio
blr
.globl in16rb
.globl iole16toh
in16rb:
iole16toh:
lhbrx 3,0,3
eieio
blr
.globl in32rb
.globl iole32toh
in32rb:
iole32toh:
lwbrx 3,0,3
eieio
blr
#ifdef DEBUG
/*
* Call an exception handler, which prints out all information
* about the type of exception, cpu registers, stack frame
* backtrace, etc.
* Use a new stack at 0x2000 and make room for 32 GPRs, and 15
* special registers. The layout will be:
* 0x00: link area
* 0x10: R0
* ...
* 0x8c: R31
* 0x90: CR, XER, LR, CTR
* 0xa0: SRR0, SRR1, DAR, DSISR
* 0xb0: DMISS, DCMP, HASH1, HASH2
* 0xc0: IMISS, ICMP, RPA
*
*/
.globl trap
trap:
mtsprg1 1
mfmsr 1
andis. 1,1,PSL_TGPR@h
beq 1f
andi. 1,1,0xffff /* make sure TGPR is disabled */
mtmsr 1
isync
mtsprg1 1 /* and save the real r1 again */
1: li 1,0x2000-16-(32*4+15*4)
stmw 2,24(1) /* save r2..r31 */
stw 0,16(1) /* save r0 */
mfsprg1 3
stw 3,20(1) /* and finally r1 */
mfcr 3
stw 3,0x90(1)
mfxer 3
stw 3,0x94(1)
mflr 3
stw 3,0x98(1)
mfctr 3
stw 3,0x9c(1)
mfsrr0 3
stw 3,0xa0(1)
mfsrr1 3
stw 3,0xa4(1)
mfdar 3
stw 3,0xa8(1)
mfdsisr 3
stw 3,0xac(1)
mfspr 3,976
stw 3,0xb0(1)
mfspr 3,977
stw 3,0xb4(1)
mfspr 3,978
stw 3,0xb8(1)
mfspr 3,979
stw 3,0xbc(1)
mfspr 3,980
stw 3,0xc0(1)
mfspr 3,981
stw 3,0xc4(1)
mfspr 3,982
stw 3,0xc8(1)
bl call_handler
call_handler:
lis 11,exception_handler@ha
addi 11,11,exception_handler@l
mtsrr0 11
li 0,PSL_DR|PSL_IR
mtsrr1 0
mflr 3
subi 3,3,call_handler-trap
addi 4,1,16
rfi
.globl trap_end
trap_end:
#endif
.data
#define xBATL(pa, wimg, pp) \
((pa) | (wimg) | (pp))
#define xBATU(va, len, v) \
((va) | ((len) & BAT_BL) | ((v) & BAT_V))
BAT123:
.long xBATL(0x80000000, BAT_I|BAT_G, BAT_PP_RW)
.long xBATU(0x80000000, BAT_BL_256M, BAT_Vs)
.long xBATL(0xfc000000, BAT_I|BAT_G, BAT_PP_RW)
.long xBATU(0xfc000000, BAT_BL_64M, BAT_Vs)
.long xBATL(0x70000000, BAT_I|BAT_G, BAT_PP_RW)
.long xBATU(0x70000000, BAT_BL_128K, BAT_Vs)