summaryrefslogtreecommitdiffstats
path: root/bsps/powerpc/motorola_powerpc/bootloader/qemu_fakerom.S
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/powerpc/motorola_powerpc/bootloader/qemu_fakerom.S')
-rw-r--r--bsps/powerpc/motorola_powerpc/bootloader/qemu_fakerom.S217
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