[PATCH 13/13] hw/ppc/pegasos2: Add VOF support for pegasos1

BALATON Zoltan posted 13 patches 4 months ago
Maintainers: BALATON Zoltan <balaton@eik.bme.hu>, Alexey Kardashevskiy <aik@ozlabs.ru>, Eduardo Habkost <eduardo@habkost.net>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, "Philippe Mathieu-Daudé" <philmd@linaro.org>, Yanan Wang <wangyanan55@huawei.com>, Zhao Liu <zhao1.liu@intel.com>
There is a newer version of this series
[PATCH 13/13] hw/ppc/pegasos2: Add VOF support for pegasos1
Posted by BALATON Zoltan 4 months ago
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 <balaton@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 <balaton@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