When running without firmware ROM using Virtual Open Firmware we need to do some hardware initialisation and provide the device tree as the machine firmware would normally do.
Signed-off-by: BALATON Zoltan <bala...@eik.bme.hu> --- MAINTAINERS | 1 + hw/ppc/pegasos2.c | 140 +++++++++++++++++++++++++++++++++------ pc-bios/dtb/meson.build | 1 + pc-bios/dtb/pegasos1.dtb | Bin 0 -> 857 bytes pc-bios/dtb/pegasos1.dts | 125 ++++++++++++++++++++++++++++++++++ 5 files changed, 246 insertions(+), 21 deletions(-) create mode 100644 pc-bios/dtb/pegasos1.dtb create mode 100644 pc-bios/dtb/pegasos1.dts diff --git a/MAINTAINERS b/MAINTAINERS index b3f9f2680b..473ffabf22 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1595,6 +1595,7 @@ F: hw/ppc/pegasos2.c F: hw/pci-host/mv64361.c F: hw/pci-host/mv643xx.h F: include/hw/pci-host/mv64361.h +F: pc-bios/dtb/pegasos[12].dt[sb] amigaone M: BALATON Zoltan <bala...@eik.bme.hu> diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c index a88d93ae04..c9a35198e9 100644 --- a/hw/ppc/pegasos2.c +++ b/hw/ppc/pegasos2.c @@ -84,6 +84,7 @@ struct PegasosMachineState { uint64_t initrd_size; }; +static void *pegasos1_build_fdt(PegasosMachineState *pm, int *fdt_size); static void *pegasos2_build_fdt(PegasosMachineState *pm, int *fdt_size); static void pegasos_cpu_reset(void *opaque) @@ -314,6 +315,82 @@ static void pegasos_init(MachineState *machine) } } +static void pegasos_superio_write(uint8_t addr, uint8_t val) +{ + cpu_physical_memory_write(0xfe0003f0, &addr, 1); + cpu_physical_memory_write(0xfe0003f1, &val, 1); +} + +static void pegasos1_pci_config_write(PegasosMachineState *pm, int bus, + uint32_t addr, uint32_t len, uint32_t val) +{ + addr |= BIT(31); + cpu_physical_memory_write(0xfec00cf8, &addr, 4); + cpu_physical_memory_write(0xfee00cfc, &val, len); +} + +static void pegasos1_chipset_reset(PegasosMachineState *pm) +{ + uint8_t elcr = 0x2e; + cpu_physical_memory_write(0xfe0004d1, &elcr, sizeof(elcr)); + + pegasos1_pci_config_write(pm, 0, PCI_COMMAND, 2, PCI_COMMAND_IO | + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + + pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) | + PCI_INTERRUPT_LINE, 2, 0x9); + pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) | + 0x50, 1, 0x6); + pegasos_superio_write(0xf4, 0xbe); + pegasos_superio_write(0xf6, 0xef); + pegasos_superio_write(0xf7, 0xfc); + pegasos_superio_write(0xf2, 0x14); + pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) | + 0x51, 1, 0x3d); + pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) | + 0x55, 1, 0x90); + pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) | + 0x56, 1, 0x99); + pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) | + 0x57, 1, 0x90); + + pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 1) << 8) | + PCI_INTERRUPT_LINE, 2, 0x10e); + pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 1) << 8) | + PCI_CLASS_PROG, 1, 0xf); + pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 1) << 8) | + 0x40, 1, 0xb); + pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 1) << 8) | + 0x50, 4, 0x17171717); + pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 1) << 8) | + PCI_COMMAND, 2, 0x87); + + pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 2) << 8) | + PCI_INTERRUPT_LINE, 2, 0x409); + pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 2) << 8) | + PCI_COMMAND, 2, 0x7); + + pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 3) << 8) | + PCI_INTERRUPT_LINE, 2, 0x409); + pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 3) << 8) | + PCI_COMMAND, 2, 0x7); + + pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 4) << 8) | + PCI_INTERRUPT_LINE, 2, 0x9); + pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 4) << 8) | + 0x48, 4, 0x2001); + pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 4) << 8) | + 0x41, 1, 0); + pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 4) << 8) | + 0x90, 4, 0x1000); + + pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 5) << 8) | + PCI_INTERRUPT_LINE, 2, 0x309); + + pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 6) << 8) | + PCI_INTERRUPT_LINE, 2, 0x309); +} + static uint32_t pegasos2_mv_reg_read(PegasosMachineState *pm, uint32_t addr, uint32_t len) { @@ -357,12 +434,6 @@ static void pegasos2_pci_config_write(PegasosMachineState *pm, int bus, pegasos2_mv_reg_write(pm, pcicfg + 4, len, val); } -static void pegasos2_superio_write(uint8_t addr, uint8_t val) -{ - cpu_physical_memory_write(0xfe0003f0, &addr, 1); - cpu_physical_memory_write(0xfe0003f1, &val, 1); -} - static void pegasos2_chipset_reset(PegasosMachineState *pm) { pegasos2_mv_reg_write(pm, 0, 4, 0x28020ff); @@ -379,10 +450,10 @@ static void pegasos2_chipset_reset(PegasosMachineState *pm) PCI_INTERRUPT_LINE, 2, 0x9); pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 0) << 8) | 0x50, 1, 0x6); - pegasos2_superio_write(0xf4, 0xbe); - pegasos2_superio_write(0xf6, 0xef); - pegasos2_superio_write(0xf7, 0xfc); - pegasos2_superio_write(0xf2, 0x14); + pegasos_superio_write(0xf4, 0xbe); + pegasos_superio_write(0xf6, 0xef); + pegasos_superio_write(0xf7, 0xfc); + pegasos_superio_write(0xf2, 0x14); pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 0) << 8) | 0x50, 1, 0x2); pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 0) << 8) | @@ -432,7 +503,7 @@ static void pegasos2_chipset_reset(PegasosMachineState *pm) static void pegasos_machine_reset(MachineState *machine, ResetType type) { PegasosMachineState *pm = PEGASOS_MACHINE(machine); - void *fdt; + void *fdt = NULL; uint32_t c[2]; uint64_t d[2]; int sz; @@ -440,13 +511,22 @@ static void pegasos_machine_reset(MachineState *machine, ResetType type) qemu_devices_reset(type); if (!pm->vof) { return; /* Firmware should set up machine so nothing to do */ - } else if (pm->type == PEGASOS1) { - error_report("VOF is not supported by this machine"); - exit(1); } /* Otherwise, set up devices that board firmware would normally do */ - pegasos2_chipset_reset(pm); + switch (pm->type) { + case PEGASOS1: + pegasos1_chipset_reset(pm); + fdt = pegasos1_build_fdt(pm, &sz); + break; + case PEGASOS2: + pegasos2_chipset_reset(pm); + fdt = pegasos2_build_fdt(pm, &sz); + break; + } + if (!fdt) { + exit(1); + } /* Device tree and VOF set up */ vof_init(pm->vof, machine->ram_size, &error_fatal); @@ -465,11 +545,6 @@ static void pegasos_machine_reset(MachineState *machine, ResetType type) exit(1); } - fdt = pegasos2_build_fdt(pm, &sz); - if (!fdt) { - exit(1); - } - /* Set memory size */ c[0] = 0; c[1] = cpu_to_be32(machine->ram_size); @@ -761,6 +836,8 @@ static struct { const char *name; void (*dtf)(PCIBus *bus, PCIDevice *d, FDTInfo *fi); } device_map[] = { + { "pci10cc,660", "host", NULL }, + { "pci10cc,661", "host", NULL }, { "pci11ab,6460", "host", NULL }, { "pci1106,571", "ide", dt_ide }, { "pci1106,3044", "firewire", NULL }, @@ -846,7 +923,7 @@ static void add_pci_device(PCIBus *bus, PCIDevice *d, void *opaque) qemu_fdt_setprop_cell(fi->fdt, node->str, "interrupts", pci_get_byte(&d->config[PCI_INTERRUPT_PIN])); } - /* Pegasos2 firmware has subsystem-id amd subsystem-vendor-id swapped */ + /* Pegasos firmware has subsystem-id and subsystem-vendor-id swapped */ qemu_fdt_setprop_cell(fi->fdt, node->str, "subsystem-vendor-id", pci_get_word(&d->config[PCI_SUBSYSTEM_ID])); qemu_fdt_setprop_cell(fi->fdt, node->str, "subsystem-id", @@ -935,6 +1012,27 @@ static void *load_dtb(const char *filename, int *fdt_size) return fdt; } +static void *pegasos1_build_fdt(PegasosMachineState *pm, int *fdt_size) +{ + FDTInfo fi; + PCIBus *pci_bus; + void *fdt = load_dtb("pegasos1.dtb", fdt_size); + + if (!fdt) { + return NULL; + } + qemu_fdt_setprop_string(fdt, "/", "name", "bplan,Pegasos"); + + add_cpu_info(fdt, pm->cpu, pm->bus_freq_hz); + + fi.fdt = fdt; + fi.path = "/pci@80000000"; + pci_bus = PCI_BUS(qdev_get_child_bus(pm->nb, "pci.0")); + pci_for_each_device_reverse(pci_bus, 0, add_pci_device, &fi); + + return fdt; +} + static void *pegasos2_build_fdt(PegasosMachineState *pm, int *fdt_size) { FDTInfo fi; diff --git a/pc-bios/dtb/meson.build b/pc-bios/dtb/meson.build index cea76c0aa1..4c9504ea5b 100644 --- a/pc-bios/dtb/meson.build +++ b/pc-bios/dtb/meson.build @@ -1,6 +1,7 @@ dtbs = [ 'bamboo.dtb', 'canyonlands.dtb', + 'pegasos1.dtb', 'pegasos2.dtb', 'petalogix-ml605.dtb', 'petalogix-s3adsp1800.dtb', diff --git a/pc-bios/dtb/pegasos1.dtb b/pc-bios/dtb/pegasos1.dtb new file mode 100644 index 0000000000000000000000000000000000000000..3b863b25288a59bcede9459ff42afad713dde741 GIT binary patch literal 857 zcmZ8fO>Yx15OvxjK&T3w=^-c=RCQ5Ogp}S|g(^KkM8yI1P<g$Rbd_D(wKuI&2~qwB z2PCfWU-%<P`~ZlU=k<oRBR$W&=lQVL`*U;oONjLkLWqG7Yv0*FXFOp%X25>1Ue)2P zwH4Vq`;8bw1HZ>;t21Y#4($Qs>6oU{8xI*8@T`9T8sbOnw^Lh4-5HhX(Mm_{-ksVl z)<#k543FN8J7aT6ZanN9FMLHMid)8#w$22?9P@Cm<{Ue{7yY!q`;sNG#%QTC<4J?o zyrj~&#eOd+b^U#g+qE9l=58l32d?gA=i#Evk%Mn^%78T-ar4cvKZ`unPh?(rIUyvm zp(f1s<Z@XAE#z61?+<#l1@(XbHt#{YIS+BeaUS$&_<8Hk*Y`L0=jCr^^*-L<<eHaH z3^vr@g}yXD0>mX2*md1FhM>Vd@`{15zY&OI5A?*GZ_uJ49eCK4S?0+5L{U+Ak<mr2 z=(Ji`5~azg5RMg}8!d)!UmuPR-|SqF&Wu~p)JT`DSVmsC+*T-XG!<Q+Us3GcRd_p9 s7&S{Kj?U+#)j|w*U+pEiuE@E$trDqb+FTZtO-VSZr{qOC_eluFKX>nfX#fBK literal 0 HcmV?d00001 diff --git a/pc-bios/dtb/pegasos1.dts b/pc-bios/dtb/pegasos1.dts new file mode 100644 index 0000000000..e5ef9db866 --- /dev/null +++ b/pc-bios/dtb/pegasos1.dts @@ -0,0 +1,125 @@ +/* + * QEMU Pegasos1 Device Tree Source + * + * Copyright 2025 BALATON Zoltan + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This is partial source, more info will be filled in by board code. + */ + +/dts-v1/; + +/ { + #address-cells = <1>; + device_type = "chrp"; + model = "Pegasos"; + revision = "1A"; + CODEGEN,vendor = "bplan GmbH"; + CODEGEN,board = "Pegasos"; + CODEGEN,description = "Pegasos CHRP PowerPC System"; + + openprom { + model = "Pegasos,0.1b123"; + }; + + chosen { + }; + + memory@0 { + device_type = "memory"; + reg = <0 0>; + }; + + cpus { + #size-cells = <0>; + #address-cells = <1>; + #cpus = <1>; + }; + + failsafe { + device_type = "serial"; + }; + + pci@80000000 { + device_type = "pci"; + #address-cells = <3>; + #size-cells = <2>; + clock-frequency = <33333333>; + 8259-interrupt-acknowledge = <0xfef00000>; + reg = <0x80000000 0x7f000000>; + ranges = <0x01000000 0 0x00000000 0xfe000000 0 0x00800000 + 0x02000000 0 0x80000000 0x80000000 0 0x7d000000 + 0x02000000 0 0xfd000000 0xfd000000 0 0x01000000>; + bus-range = <0 0>; + + isa@7 { + vendor-id = <0x1106>; + device-id = <0x8231>; + revision-id = <0x10>; + class-code = <0x60100>; + /* Pegasos firmware has subsystem-id and */ + /* subsystem-vendor-id swapped */ + subsystem-id = <0x1af4>; + subsystem-vendor-id = <0x1100>; + reg = <0x3800 0 0 0 0>; + device_type = "isa"; + #address-cells = <2>; + #size-cells = <1>; + eisa-slots = <0>; + clock-frequency = <8333333>; + slot-names = <0>; + + serial@i2f8 { + device_type = "serial"; + reg = <1 0x2f8 8>; + interrupts = <3 0>; + clock-frequency = <0>; + }; + + 8042@i60 { + device_type = ""; + reg = <1 0x60 5>; + clock-frequency = <0>; + interrupt-controller = ""; + #address-cells = <1>; + #size-cells = <0>; + #interrupt-cells = <2>; + + }; + + keyboard@i60 { + device_type = "keyboard"; + reg = <1 0x60 5>; + interrupts = <1 0>; + }; + + rtc@i70 { + device_type = "rtc"; + reg = <1 0x70 2>; + interrupts = <8 0>; + clock-frequency = <0>; + compatible = "ds1385-rtc"; + }; + + timer@i40 { + device_type = "timer"; + reg = <1 0x40 8>; + clock-frequency = <0>; + }; + + fdc@i3f0 { + device_type = "fdc"; + reg = <1 0x3f0 8>; + interrupts = <6 0>; + clock-frequency = <0>; + }; + + lpt@i3bc { + device_type = "lpt"; + reg = <1 0x3bc 8>; + interrupts = <7 0>; + clock-frequency = <0>; + }; + }; + }; +}; -- 2.41.3