From 3c21f9dfcf8c8120e2fd5e8c5cbea61f21e7be69 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Thu, 23 Oct 2025 02:06:19 +0200 Subject: [PATCH] hw/ppc/pegasos2: Add VOF support for pegasos1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Philippe Mathieu-Daudé Link: https://lore.kernel.org/qemu-devel/d2d7f173dbd436b47382f384d5a93eb7e713424e.1761176219.git.balaton@eik.bme.hu Signed-off-by: Harsh Prateek Bora --- 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 36eef27b41..684d7a5b37 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1652,6 +1652,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 diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c index a11f3c99ed..93696ed381 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", @@ -934,6 +1011,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 f14648f3a4..81bdd7580e 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 zc-nnZ%}N6?5T3S*iimpFL!}oHS6W4=H>FB@(xP|}50cGJ>(bpMCR?R~Sl`2g;8own z7ZH2_Ehf9$HeJDiZ*Zet>LFB7|}QBSpEt#R5cHu)XO zX03SEQxS%7KU^Ral806wOI9D7<*kZa+1@c{dE-y7xk3gb9%9I4Z@+BC&zQR<`b2-1 z)@+hoqN_49y835khIdjP$G3Q$#OXGMu?HCIKPjxAX;|kqGfRWH67f8VN;wpR zK!Jz1KET)8z5%W+{>5Iq&NNht%`S+OS wF2!$015P_mOX5uz8SO!Jdw0+AS%gw{MdT3LVf-#YuZ; + 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.47.3