root/sys/arch/sandpoint/stand/altboot/entry.S
/* $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)