/*
 * Based on: arch/ppc/boot/sandpoint/head.S
 *           arch/ppc/kernel/head.S
 *           http://www-106.ibm.com/developerworks/library/pa-ppccache.html
 */

#define HID0        0x3F0       /* Hardware Implementation Register 0 */
#define HID0_ICE    (1<<15)     /* Instruction Cache Enable */
#define HID0_DCE    (1<<14)     /* Data Cache Enable */

.section ".text"
.globl load_kernel

load_kernel:
        /* save parameters */
        mr      r31,r3  /* pa_load_kernel */
        mr      r30,r4  /* pa_kernel_buf */
        mr      r29,r5  /* pa_initrd_buf */
        mr      r28,r6  /* pa_cmdline_start */
        mr      r27,r7  /* pa_cmdline_end */

        /* disable interrupt */
        mfmsr   r0
        rlwinm  r0,r0,0,17,15   /* clear MSR_EE in r0 */
        sync
        mtmsr   r0
        sync

        /* disable cache */
        bl      disable_cache

        /* jump to after_mmu_off */
        addi    r4,r31,after_mmu_off-load_kernel
        li      r3,0
        mtspr   SRR0,r4
        mtspr   SRR1,r3
        isync
        sync
        rfi

after_mmu_off:

        /* copy kernel image */
        li      r4,0
        addi    r30,r30,4       /* skip size */

2:      li      r0,1024
        lwz     r9,0(r30)

        mtctr   r0
1:      lwz     r0,0(r9)
        addi    r9,r9,4
        stw     r0,0(r4)
        addi    r4,r4,4
        bdnz    1b

        addi    r30,r30,4
        lwz     r0,0(r30)
        cmpwi   r0,0
        bne     2b

        li      r24,0           /* initrd start */
        li      r25,0           /* initrd end */
        cmpwi   r29,0
        beq     go

        /* copy initrd */

        lis     r3,0x10         /* assume 1M bss is enough */
        add     r4,r4,r3        /* reserve bss */
        mr      r24,r4          /* initrd start */
        lwz     r25,0(r29)      /* initrd size */
        add     r25,r25,r24     /* initrd end */
        addi    r29,r29,4       /* skip size */

2:      li      r0,1024
        lwz     r9,0(r29)

        mtctr   r0
1:      lwz     r0,0(r9)
        addi    r9,r9,4
        stw     r0,0(r4)
        addi    r4,r4,4
        bdnz    1b

        addi    r29,r29,4
        lwz     r0,0(r29)
        cmpwi   r0,0
        bne     2b

        /*
         *   From arch/ppc/kernel/head.S:
         *
         *   r3: ptr to residual data
         *   r4: initrd_start or if no initrd then 0
         *   r5: initrd_end - unused if r4 is 0
         *   r6: Start of command line string
         *   r7: End of command line string
         */
go:
        /* jump to new kernel */
        lis     r1,0x100        /* put stack at 16M */
        li      r3,0
        mr      r4,r24
        mr      r5,r25
        mr      r6,r28
        mr      r7,r27
        li      r9,0
        mtlr    r9
        blr

disable_cache:
        li      r2,1024 /* flush 16K cache */
        mtctr   r2
        mr      r3,r2
        lis     r4,0xC000
loop1:
        lwz     r6,0(r4)
        addi    r4,r4,16
        bdnz    loop1

        lis     r4,0xC000
        mtctr   r3
loop2:
        dcbf    r0,r4
        addi    r4,r4,16
        bdnz    loop2

        mfspr   r4,HID0
        li      r3,0
        ori     r3,r3,HID0_ICE|HID0_DCE
        andc    r4,r4,r3
        mtspr   HID0,r4
        isync
        blr
