diff options
Diffstat (limited to 'bsps/powerpc/motorola_powerpc/bootloader/qemu_fakerom.S')
-rw-r--r-- | bsps/powerpc/motorola_powerpc/bootloader/qemu_fakerom.S | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/bsps/powerpc/motorola_powerpc/bootloader/qemu_fakerom.S b/bsps/powerpc/motorola_powerpc/bootloader/qemu_fakerom.S new file mode 100644 index 0000000000..b77c3bd138 --- /dev/null +++ b/bsps/powerpc/motorola_powerpc/bootloader/qemu_fakerom.S @@ -0,0 +1,217 @@ +/* A fake 'bios' which does nothing but move a kernel image + * to RAM address zero and then starts that... + */ + +#include <bsp/residual.h> + +#define LD_CACHE_LINE_SIZE 5 +#define INIT_STACK (0x100 - 16) /* 16-byte/svr4 aligned */ + +/* These offsets must correspond to declaration in qemu_fakeres.c */ +#define DAT_LEN 0 +#define RES_OFF 4 +#define CMD_OFF 8 +#define CMD_LEN 12 +#define IMG_ADR 16 + +/* Non-volatile registers */ +#define OBASE 30 +#define PCID 25 +#define PCIA 26 + +#define PCI_MAX_DEV 32 + +#define BA_OPCODE(tgt) ((18<<(31-5)) | 2 | ((tgt) & 0x03fffffc)) + + .global fake_data + .global res_set_memsz + + .global _start +_start: + lis 1, INIT_STACK@h + ori 1,1,INIT_STACK@l + + /* qemu 0.14.1 has the wrong exception prefix for 74xx CPUs + * (bug 811683). Work around this by putting a stub at 0x00000X00 + * which simply jumps to high memory. We only need the SC exception + * for now. + */ + lis 3, BA_OPCODE(0xfff00000)@h + ori 3, 3, BA_OPCODE(0xfff00000)@l + li 4, 0x0c00 + add 3, 3, 4 + stw 3, 0(4) + dcbf 0, 4 + icbi 0, 4 + + bl pci_irq_set + /* copy residual to RAM and fix up; + * this routine returns a pointer to + * a 'fake_data' struct. If reading + * NVRAM failed then the return value + * points to a fall-back version in + * ROM... + */ + bl res_copy + /* fake_data pointer to R29 */ + mr 29, 3 + + /* Load up R3..R5 with PreP mandated + * values (R3: residual, R4: kernel image, + * R5: OpenFirmware PTR (or NULL). + */ + + /* load R3 with residual pointer */ + lwz 3, RES_OFF(29) + add 3, 3, 29 + + /* load R4 with image address */ + lwz 4, IMG_ADR(29) + + /* load R5 with zero (OFW = NULL) */ + li 5, 0 + /* EXTENSION: R6 = cmdline start */ + lwz 6, CMD_OFF(29) + add 6, 6, 29 + /* EXTENSION: R7 = cmdline end */ + lwz 7, CMD_LEN(29) + add 7, 7, 6 + + /* jump to image address */ + mtctr 4 + bctr + + .org 0x100 + b _start + + .org 0x110 +template: + mfsrr0 30 + mfsrr1 31 +1: b 1b +template_end: + + .org 0xc00 + b monitor + + + .org 0x4000 +codemove: /* src/dst are cache-aligned */ + addi 5,5,(1<<LD_CACHE_LINE_SIZE)-1 + srwi 5,5,LD_CACHE_LINE_SIZE + addi 3,3,-4 + addi 4,4,-4 +1: + li 0, (1<<LD_CACHE_LINE_SIZE) + mtctr 0 +2: + lwzu 0, 4(3) + stwu 0, 4(4) + bdnz 2b + dcbf 0,4 + icbi 0,4 + addic. 5,5,-1 + bne 1b + blr + +cpexc: + lis 3,template@h + ori 3,3,template@l + li 5,template_end-template + b codemove + +monitor: + stwu 1,-16(1) + stw OBASE, 8(1) + lis OBASE, 0x80000000@h + cmplwi 10,0x63 /* enter_monitor -> RESET */ + bne 10f +hwreset: + li 3,1 + stb 3,0x92(OBASE) +1: b 1b +10: cmplwi 10,0x1d /* .NETCTRL -> ignore */ + bne 10f + b ret_from_mon +10: b hwreset /* unknown -> RESET */ + +ret_from_mon: + lwz OBASE,8(1) + lwz 1,0(1) + rfi + +rcb: + stwbrx 3, 0, PCIA + lbzx 3, 0, PCID + blr + +wcb: + stwbrx 3, 0, PCIA + stbx 4, 0, PCID + blr + +rcd: + stwbrx 3, 0, PCIA + lwbrx 3, 0, PCID + blr + +/* fixup pci interrupt line register according to what + * qemu does: line = ((pin-1) + slot_no) & 1 ? 11 : 9; + */ +pci_irq_set: + /* set up stack frame */ + stwu 1, -32(1) + mflr 0 + stw 0, 32+4(1) + /* load counter with # of PCI devs */ + li 0, PCI_MAX_DEV + mtctr 0 + /* save non-volatile registers we use + * in stack frame + */ + stw 20, 8(1) + stw PCIA, 12(1) + stw PCID, 16(1) + /* load non-volatile registers with + * intended values. + */ + lis 20, 0x80000000@h /* key for slot # 0 */ + lis PCIA, 0x80000cf8@h /* PCI config space address reg */ + ori PCIA, PCIA, 0x80000cf8@l + addi PCID, PCIA, 4 /* PCI config space data reg */ + + /* loop over all slots and fix up PCI IRQ LINE */ +1: + mr 3, 20 + bl rcd + addi 3, 3, 1 + cmplwi 3, 0 /* slot empty (= -1 + 1 = 0) ? */ + beq 2f + addi 3, 20, 0x3d + bl rcb + cmplwi 3, 0 + beq 2f + slwi 4, 3, 11 + addi 3, 20, 0x3c + xor 4, 4, 3 /* bit 11 = slot # + irq_num [zero-based] + 1 */ + andi. 4, 4, 0x0800 + li 4, 11 + beq 3f + li 4, 9 +3: + bl wcb +2: + addi 20, 20, 0x0800 /* next slot */ + bdnz 1b + + /* restore and return */ + lwz 20, 32+4(1) + mtlr 20 + lwz PCID, 16(1) + lwz PCIA, 12(1) + lwz 20, 8(1) + lwz 1, 0(1) + blr + + .section .romentry, "ax" + b _start |